]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/metafile.cpp
Don't close arcs drawn in wxPostScriptDC.
[wxWidgets.git] / src / os2 / metafile.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/os2/metafile.cpp
3// Purpose: wxMetaFile, wxMetaFileDC etc. These classes are optional.
4// Author: David Webster
5// Modified by:
6// Created: 10/10/99
7// RCS-ID: $Id$
8// Copyright: (c) David Webster
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#if wxUSE_METAFILE
16
17#ifndef WX_PRECOMP
18 #include "wx/utils.h"
19 #include "wx/app.h"
20#endif
21
22#include "wx/metafile.h"
23#include "wx/clipbrd.h"
24#include "wx/os2/private.h"
25
26#include <stdio.h>
27#include <string.h>
28
29extern bool wxClipboardIsOpen;
30
31IMPLEMENT_DYNAMIC_CLASS(wxMetafile, wxObject)
32IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC, wxDC)
33
34/*
35 * Metafiles
36 * Currently, the only purpose for making a metafile is to put
37 * it on the clipboard.
38 */
39
40wxMetafileRefData::wxMetafileRefData(void)
41{
42 m_metafile = 0;
43 m_windowsMappingMode = MM_ANISOTROPIC;
44}
45
46wxMetafileRefData::~wxMetafileRefData(void)
47{
48 if (m_metafile)
49 {
50// TODO: DeleteMetaFile((HMETAFILE) m_metafile);
51 m_metafile = 0;
52 }
53}
54
55wxMetafile::wxMetafile(const wxString& file)
56{
57 m_refData = new wxMetafileRefData;
58
59 M_METAFILEDATA->m_windowsMappingMode = MM_ANISOTROPIC;
60 M_METAFILEDATA->m_metafile = 0;
61 if (!file.empty())
62 M_METAFILEDATA->m_metafile = (WXHANDLE)0; // TODO: GetMetaFile(file);
63}
64
65wxMetafile::~wxMetafile(void)
66{
67}
68
69wxGDIRefData *wxMetafile::CreateGDIRefData() const
70{
71 return new wxMetafileRefData;
72}
73
74wxGDIRefData *wxMetafile::CloneGDIRefData(const wxGDIRefData *data) const
75{
76 return new wxMetafileRefData(*static_cast<const wxMetafileRefData *>(data));
77}
78
79bool wxMetafile::SetClipboard(int width, int height)
80{
81#if !wxUSE_CLIPBOARD
82 wxUnusedVar(width);
83 wxUnusedVar(height);
84 return false;
85#else
86 if (!m_refData)
87 return false;
88
89 bool alreadyOpen=wxClipboardOpen();
90 if (!alreadyOpen)
91 {
92 wxOpenClipboard();
93 if (!wxEmptyClipboard()) return false;
94 }
95 bool success = wxSetClipboardData(wxDF_METAFILE, this, width,height);
96 if (!alreadyOpen) wxCloseClipboard();
97 return (bool) success;
98#endif
99}
100
101bool wxMetafile::Play(wxDC *dc)
102{
103 if (!m_refData)
104 return false;
105
106 // if (dc->GetHDC() && M_METAFILEDATA->m_metafile)
107 // PlayMetaFile((HDC) dc->GetHDC(), (HMETAFILE) M_METAFILEDATA->m_metafile);
108
109 return true;
110}
111
112void wxMetafile::SetHMETAFILE(WXHANDLE mf)
113{
114 if (m_refData)
115 m_refData = new wxMetafileRefData;
116
117 M_METAFILEDATA->m_metafile = mf;
118}
119
120void wxMetafile::SetWindowsMappingMode(int mm)
121{
122 if (m_refData)
123 m_refData = new wxMetafileRefData;
124
125 M_METAFILEDATA->m_windowsMappingMode = mm;
126}
127
128/*
129 * Metafile device context
130 *
131 */
132
133// Original constructor that does not takes origin and extent. If you use this,
134// *DO* give origin/extent arguments to wxMakeMetafilePlaceable.
135wxMetafileDCImpl::wxMetafileDCImpl(wxDC *owner, const wxString& file)
136 : wxPMDCImpl(owner)
137{
138 m_metaFile = NULL;
139 m_minX = 10000;
140 m_minY = 10000;
141 m_maxX = -10000;
142 m_maxY = -10000;
143// m_title = NULL;
144
145 if ( wxFileExists(file) )
146 wxRemoveFile(file);
147
148 // TODO
149/*
150 if (!file.empty())
151 m_hDC = (WXHDC) CreateMetaFile(file);
152 else
153 m_hDC = (WXHDC) CreateMetaFile(NULL);
154*/
155
156 m_ok = (m_hDC != (WXHDC) 0) ;
157
158 // Actual Windows mapping mode, for future reference.
159 m_windowsMappingMode = wxMM_TEXT;
160
161 SetMapMode(wxMM_TEXT); // NOTE: does not set HDC mapmode (this is correct)
162}
163
164// New constructor that takes origin and extent. If you use this, don't
165// give origin/extent arguments to wxMakeMetafilePlaceable.
166wxMetafileDCImpl::wxMetafileDCImpl( wxDC *owner, const wxString& file,
167 int WXUNUSED(xext),
168 int WXUNUSED(yext),
169 int WXUNUSED(xorg),
170 int WXUNUSED(yorg) )
171 : wxPMDCImpl(owner)
172{
173 m_minX = 10000;
174 m_minY = 10000;
175 m_maxX = -10000;
176 m_maxY = -10000;
177 if (!file.empty() && wxFileExists(file))
178 wxRemoveFile(file);
179
180// m_hDC = (WXHDC) CreateMetaFile(file);
181
182 m_ok = true;
183
184// ::SetWindowOrgEx((HDC) m_hDC,xorg,yorg, NULL);
185// ::SetWindowExtEx((HDC) m_hDC,xext,yext, NULL);
186
187 // Actual Windows mapping mode, for future reference.
188 m_windowsMappingMode = MM_ANISOTROPIC;
189
190 SetMapMode(wxMM_TEXT); // NOTE: does not set HDC mapmode (this is correct)
191}
192
193wxMetafileDCImpl::~wxMetafileDCImpl(void)
194{
195 m_hDC = 0;
196}
197
198void wxMetafileDCImpl::DoGetTextExtent(const wxString& WXUNUSED(string),
199 wxCoord *WXUNUSED(x),
200 wxCoord *WXUNUSED(y),
201 wxCoord *WXUNUSED(descent),
202 wxCoord *WXUNUSED(externalLeading),
203 const wxFont *theFont) const
204{
205 const wxFont *fontToUse = theFont;
206 if (!fontToUse)
207 fontToUse = &m_font;
208
209 // TODO:
210/*
211 HDC dc = GetDC(NULL);
212
213 SIZE sizeRect;
214 TEXTMETRIC tm;
215 GetTextExtentPoint(dc, WXSTRINGCAST string, wxStrlen(WXSTRINGCAST string), &sizeRect);
216 GetTextMetrics(dc, &tm);
217
218 ReleaseDC(NULL, dc);
219
220 if ( x )
221 *x = sizeRect.cx;
222 if ( y )
223 *y = sizeRect.cy;
224 if ( descent )
225 *descent = tm.tmDescent;
226 if ( externalLeading )
227 *externalLeading = tm.tmExternalLeading;
228*/
229}
230
231wxMetafile *wxMetafileDCImpl::Close(void)
232{
233 SelectOldObjects(m_hDC);
234 HANDLE mf = 0; // TODO: CloseMetaFile((HDC) m_hDC);
235 m_hDC = 0;
236 if (mf)
237 {
238 wxMetafile *wx_mf = new wxMetafile;
239 wx_mf->SetHMETAFILE((WXHANDLE) mf);
240 wx_mf->SetWindowsMappingMode(m_windowsMappingMode);
241 return wx_mf;
242 }
243 return NULL;
244}
245
246void wxMetafileDCImpl::SetMapMode(wxMappingMode mode)
247{
248 m_mappingMode = mode;
249
250// int pixel_width = 0;
251// int pixel_height = 0;
252// int mm_width = 0;
253// int mm_height = 0;
254
255 float mm2pixelsX = 10.0;
256 float mm2pixelsY = 10.0;
257
258 switch (mode)
259 {
260 case wxMM_TWIPS:
261 {
262 m_logicalScaleX = (float)(twips2mm * mm2pixelsX);
263 m_logicalScaleY = (float)(twips2mm * mm2pixelsY);
264 break;
265 }
266 case wxMM_POINTS:
267 {
268 m_logicalScaleX = (float)(pt2mm * mm2pixelsX);
269 m_logicalScaleY = (float)(pt2mm * mm2pixelsY);
270 break;
271 }
272 case wxMM_METRIC:
273 {
274 m_logicalScaleX = mm2pixelsX;
275 m_logicalScaleY = mm2pixelsY;
276 break;
277 }
278 case wxMM_LOMETRIC:
279 {
280 m_logicalScaleX = (float)(mm2pixelsX/10.0);
281 m_logicalScaleY = (float)(mm2pixelsY/10.0);
282 break;
283 }
284 default:
285 case wxMM_TEXT:
286 {
287 m_logicalScaleX = 1.0;
288 m_logicalScaleY = 1.0;
289 break;
290 }
291 }
292 m_nWindowExtX = 100;
293 m_nWindowExtY = 100;
294}
295
296#ifdef __WIN32__
297struct RECT32
298{
299 short left;
300 short top;
301 short right;
302 short bottom;
303};
304
305struct mfPLACEABLEHEADER {
306 DWORD key;
307 short hmf;
308 RECT32 bbox;
309 WORD inch;
310 DWORD reserved;
311 WORD checksum;
312};
313#else
314struct mfPLACEABLEHEADER {
315 DWORD key;
316 HANDLE hmf;
317 RECT bbox;
318 WORD inch;
319 DWORD reserved;
320 WORD checksum;
321};
322#endif
323
324/*
325 * Pass filename of existing non-placeable metafile, and bounding box.
326 * Adds a placeable metafile header, sets the mapping mode to anisotropic,
327 * and sets the window origin and extent to mimic the wxMM_TEXT mapping mode.
328 *
329 */
330
331bool wxMakeMetafilePlaceable(const wxString& filename, float scale)
332{
333 return wxMakeMetafilePlaceable(filename, 0, 0, 0, 0, scale, FALSE);
334}
335
336bool wxMakeMetafilePlaceable(const wxString& WXUNUSED(filename),
337 int WXUNUSED(x1),
338 int WXUNUSED(y1),
339 int WXUNUSED(x2),
340 int WXUNUSED(y2),
341 float WXUNUSED(scale),
342 bool WXUNUSED(useOriginAndExtent))
343{
344// TODO: the OS/2 PM/MM way to do this
345/*
346 // I'm not sure if this is the correct way of suggesting a scale
347 // to the client application, but it's the only way I can find.
348 int unitsPerInch = (int)(576/scale);
349
350 mfPLACEABLEHEADER header;
351 header.key = 0x9AC6CDD7L;
352 header.hmf = 0;
353 header.bbox.xLeft = (int)(x1);
354 header.bbox.yTop = (int)(y1);
355 header.bbox.xRight = (int)(x2);
356 header.bbox.yBottom = (int)(y2);
357 header.inch = unitsPerInch;
358 header.reserved = 0;
359
360 // Calculate checksum
361 WORD *p;
362 mfPLACEABLEHEADER *pMFHead = &header;
363 for (p =(WORD *)pMFHead,pMFHead -> checksum = 0; p < (WORD *)&pMFHead ->checksum; ++p)
364 pMFHead ->checksum ^= *p;
365
366 FILE *fd = fopen(filename.fn_str(), "rb");
367 if (!fd)
368 return false;
369
370 wxChar tempFileBuf[256];
371 wxGetTempFileName(wxT("mf"), tempFileBuf);
372 FILE *fHandle = fopen(wxConvFile.cWX2MB(tempFileBuf), "wb");
373 if (!fHandle)
374 return false;
375 fwrite((void *)&header, sizeof(unsigned char), sizeof(mfPLACEABLEHEADER), fHandle);
376
377 // Calculate origin and extent
378 int originX = x1;
379 int originY = y1;
380 int extentX = x2 - x1;
381 int extentY = (y2 - y1);
382
383 // Read metafile header and write
384 METAHEADER metaHeader;
385 fread((void *)&metaHeader, sizeof(unsigned char), sizeof(metaHeader), fd);
386
387 if (useOriginAndExtent)
388 metaHeader.mtSize += 15;
389 else
390 metaHeader.mtSize += 5;
391
392 fwrite((void *)&metaHeader, sizeof(unsigned char), sizeof(metaHeader), fHandle);
393
394 // Write SetMapMode, SetWindowOrigin and SetWindowExt records
395 char modeBuffer[8];
396 char originBuffer[10];
397 char extentBuffer[10];
398 METARECORD *modeRecord = (METARECORD *)&modeBuffer;
399
400 METARECORD *originRecord = (METARECORD *)&originBuffer;
401 METARECORD *extentRecord = (METARECORD *)&extentBuffer;
402
403 modeRecord->rdSize = 4;
404 modeRecord->rdFunction = META_SETMAPMODE;
405 modeRecord->rdParm[0] = MM_ANISOTROPIC;
406
407 originRecord->rdSize = 5;
408 originRecord->rdFunction = META_SETWINDOWORG;
409 originRecord->rdParm[0] = originY;
410 originRecord->rdParm[1] = originX;
411
412 extentRecord->rdSize = 5;
413 extentRecord->rdFunction = META_SETWINDOWEXT;
414 extentRecord->rdParm[0] = extentY;
415 extentRecord->rdParm[1] = extentX;
416
417 fwrite((void *)modeBuffer, sizeof(char), 8, fHandle);
418
419 if (useOriginAndExtent)
420 {
421 fwrite((void *)originBuffer, sizeof(char), 10, fHandle);
422 fwrite((void *)extentBuffer, sizeof(char), 10, fHandle);
423 }
424
425 int ch = -2;
426 while (ch != EOF)
427 {
428 ch = getc(fd);
429 if (ch != EOF)
430 {
431 putc(ch, fHandle);
432 }
433 }
434 fclose(fHandle);
435 fclose(fd);
436 wxRemoveFile(filename);
437 wxCopyFile(tempFileBuf, filename);
438 wxRemoveFile(tempFileBuf);
439*/
440 return true;
441}
442
443#endif // wxUSE_METAFILE