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