]> git.saurik.com Git - wxWidgets.git/blob - src/os2/metafile.cpp
PCH-less build fix
[wxWidgets.git] / src / os2 / metafile.cpp
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
29 extern bool wxClipboardIsOpen;
30
31 IMPLEMENT_DYNAMIC_CLASS(wxMetafile, wxObject)
32 IMPLEMENT_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
40 wxMetafileRefData::wxMetafileRefData(void)
41 {
42 m_metafile = 0;
43 m_windowsMappingMode = MM_ANISOTROPIC;
44 }
45
46 wxMetafileRefData::~wxMetafileRefData(void)
47 {
48 if (m_metafile)
49 {
50 // TODO: DeleteMetaFile((HMETAFILE) m_metafile);
51 m_metafile = 0;
52 }
53 }
54
55 wxMetafile::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
65 wxMetafile::~wxMetafile(void)
66 {
67 }
68
69 wxGDIRefData *wxMetafile::CreateGDIRefData() const
70 {
71 return new wxMetafileRefData;
72 }
73
74 wxGDIRefData *wxMetafile::CloneGDIRefData(const wxGDIRefData *data) const
75 {
76 return new wxMetafileRefData(*static_cast<const wxMetafileRefData *>(data));
77 }
78
79 bool 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
101 bool 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
112 void wxMetafile::SetHMETAFILE(WXHANDLE mf)
113 {
114 if (m_refData)
115 m_refData = new wxMetafileRefData;
116
117 M_METAFILEDATA->m_metafile = mf;
118 }
119
120 void 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.
135 wxMetafileDCImpl::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 (!file.IsNull() && 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.
166 wxMetafileDCImpl::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
193 wxMetafileDCImpl::~wxMetafileDCImpl(void)
194 {
195 m_hDC = 0;
196 }
197
198 void 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
231 wxMetafile *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
246 void 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__
297 struct RECT32
298 {
299 short left;
300 short top;
301 short right;
302 short bottom;
303 };
304
305 struct mfPLACEABLEHEADER {
306 DWORD key;
307 short hmf;
308 RECT32 bbox;
309 WORD inch;
310 DWORD reserved;
311 WORD checksum;
312 };
313 #else
314 struct 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
331 bool wxMakeMetafilePlaceable(const wxString& filename, float scale)
332 {
333 return wxMakeMetafilePlaceable(filename, 0, 0, 0, 0, scale, FALSE);
334 }
335
336 bool 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