]> git.saurik.com Git - wxWidgets.git/blame - src/os2/metafile.cpp
Misc XRC format docs corrections.
[wxWidgets.git] / src / os2 / metafile.cpp
CommitLineData
0e320a79 1/////////////////////////////////////////////////////////////////////////////
521bf4ff 2// Name: src/os2/metafile.cpp
0e320a79 3// Purpose: wxMetaFile, wxMetaFileDC etc. These classes are optional.
75f11ad7 4// Author: David Webster
0e320a79 5// Modified by:
75f11ad7 6// Created: 10/10/99
75f11ad7 7// Copyright: (c) David Webster
65571936 8// Licence: wxWindows licence
0e320a79
DW
9/////////////////////////////////////////////////////////////////////////////
10
75f11ad7
DW
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
75f11ad7
DW
14#if wxUSE_METAFILE
15
16#ifndef WX_PRECOMP
670f9935
WS
17 #include "wx/utils.h"
18 #include "wx/app.h"
75f11ad7
DW
19#endif
20
21#include "wx/metafile.h"
0e320a79 22#include "wx/clipbrd.h"
75f11ad7
DW
23#include "wx/os2/private.h"
24
25#include <stdio.h>
26#include <string.h>
0e320a79
DW
27
28extern bool wxClipboardIsOpen;
29
75f11ad7
DW
30IMPLEMENT_DYNAMIC_CLASS(wxMetafile, wxObject)
31IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC, wxDC)
0e320a79 32
75f11ad7
DW
33/*
34 * Metafiles
35 * Currently, the only purpose for making a metafile is to put
36 * it on the clipboard.
37 */
38
39wxMetafileRefData::wxMetafileRefData(void)
40{
41 m_metafile = 0;
e65a6cc1 42 m_windowsMappingMode = MM_ANISOTROPIC;
75f11ad7
DW
43}
44
45wxMetafileRefData::~wxMetafileRefData(void)
0e320a79 46{
75f11ad7
DW
47 if (m_metafile)
48 {
49// TODO: DeleteMetaFile((HMETAFILE) m_metafile);
50 m_metafile = 0;
51 }
0e320a79
DW
52}
53
75f11ad7 54wxMetafile::wxMetafile(const wxString& file)
0e320a79 55{
75f11ad7
DW
56 m_refData = new wxMetafileRefData;
57
e65a6cc1 58 M_METAFILEDATA->m_windowsMappingMode = MM_ANISOTROPIC;
75f11ad7 59 M_METAFILEDATA->m_metafile = 0;
521bf4ff 60 if (!file.empty())
75f11ad7 61 M_METAFILEDATA->m_metafile = (WXHANDLE)0; // TODO: GetMetaFile(file);
0e320a79
DW
62}
63
75f11ad7 64wxMetafile::~wxMetafile(void)
0e320a79 65{
75f11ad7
DW
66}
67
4b3f61d1
SN
68wxGDIRefData *wxMetafile::CreateGDIRefData() const
69{
70 return new wxMetafileRefData;
71}
72
73wxGDIRefData *wxMetafile::CloneGDIRefData(const wxGDIRefData *data) const
74{
5c33522f 75 return new wxMetafileRefData(*static_cast<const wxMetafileRefData *>(data));
4b3f61d1
SN
76}
77
75f11ad7
DW
78bool wxMetafile::SetClipboard(int width, int height)
79{
6670f564
WS
80#if !wxUSE_CLIPBOARD
81 wxUnusedVar(width);
82 wxUnusedVar(height);
83 return false;
84#else
75f11ad7 85 if (!m_refData)
6670f564 86 return false;
75f11ad7 87
0e320a79
DW
88 bool alreadyOpen=wxClipboardOpen();
89 if (!alreadyOpen)
90 {
91 wxOpenClipboard();
670f9935 92 if (!wxEmptyClipboard()) return false;
0e320a79 93 }
75f11ad7 94 bool success = wxSetClipboardData(wxDF_METAFILE, this, width,height);
0e320a79
DW
95 if (!alreadyOpen) wxCloseClipboard();
96 return (bool) success;
6670f564 97#endif
0e320a79
DW
98}
99
75f11ad7 100bool wxMetafile::Play(wxDC *dc)
0e320a79 101{
75f11ad7 102 if (!m_refData)
670f9935 103 return false;
75f11ad7 104
75f11ad7
DW
105 // if (dc->GetHDC() && M_METAFILEDATA->m_metafile)
106 // PlayMetaFile((HDC) dc->GetHDC(), (HMETAFILE) M_METAFILEDATA->m_metafile);
107
6670f564 108 return true;
75f11ad7
DW
109}
110
111void wxMetafile::SetHMETAFILE(WXHANDLE mf)
112{
113 if (m_refData)
114 m_refData = new wxMetafileRefData;
115
116 M_METAFILEDATA->m_metafile = mf;
117}
118
119void wxMetafile::SetWindowsMappingMode(int mm)
120{
121 if (m_refData)
122 m_refData = new wxMetafileRefData;
123
124 M_METAFILEDATA->m_windowsMappingMode = mm;
0e320a79
DW
125}
126
127/*
128 * Metafile device context
129 *
130 */
131
132// Original constructor that does not takes origin and extent. If you use this,
75f11ad7 133// *DO* give origin/extent arguments to wxMakeMetafilePlaceable.
4b3f61d1
SN
134wxMetafileDCImpl::wxMetafileDCImpl(wxDC *owner, const wxString& file)
135 : wxPMDCImpl(owner)
0e320a79 136{
75f11ad7
DW
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
6636ef8d 144 if ( wxFileExists(file) )
75f11ad7
DW
145 wxRemoveFile(file);
146
147 // TODO
148/*
521bf4ff 149 if (!file.empty())
75f11ad7
DW
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)
0e320a79
DW
161}
162
163// New constructor that takes origin and extent. If you use this, don't
75f11ad7 164// give origin/extent arguments to wxMakeMetafilePlaceable.
4b3f61d1
SN
165wxMetafileDCImpl::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)
0e320a79 171{
6670f564
WS
172 m_minX = 10000;
173 m_minY = 10000;
174 m_maxX = -10000;
175 m_maxY = -10000;
521bf4ff 176 if (!file.empty() && wxFileExists(file))
6670f564
WS
177 wxRemoveFile(file);
178
75f11ad7
DW
179// m_hDC = (WXHDC) CreateMetaFile(file);
180
6670f564 181 m_ok = true;
75f11ad7
DW
182
183// ::SetWindowOrgEx((HDC) m_hDC,xorg,yorg, NULL);
184// ::SetWindowExtEx((HDC) m_hDC,xext,yext, NULL);
185
6670f564 186 // Actual Windows mapping mode, for future reference.
e65a6cc1 187 m_windowsMappingMode = MM_ANISOTROPIC;
75f11ad7 188
6670f564 189 SetMapMode(wxMM_TEXT); // NOTE: does not set HDC mapmode (this is correct)
0e320a79
DW
190}
191
4b3f61d1 192wxMetafileDCImpl::~wxMetafileDCImpl(void)
0e320a79 193{
75f11ad7 194 m_hDC = 0;
0e320a79
DW
195}
196
4b3f61d1
SN
197void 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
0e320a79 203{
c94f845b 204 const wxFont *fontToUse = theFont;
6670f564 205 if (!fontToUse)
c94f845b 206 fontToUse = &m_font;
75f11ad7 207
6670f564 208 // TODO:
75f11ad7 209/*
6670f564
WS
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;
75f11ad7 227*/
0e320a79
DW
228}
229
4b3f61d1 230wxMetafile *wxMetafileDCImpl::Close(void)
0e320a79 231{
75f11ad7
DW
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;
0e320a79
DW
243}
244
89efaf2b 245void wxMetafileDCImpl::SetMapMode(wxMappingMode mode)
0e320a79 246{
75f11ad7 247 m_mappingMode = mode;
0e320a79 248
75f11ad7
DW
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 }
f6bcfd97
BP
291 m_nWindowExtX = 100;
292 m_nWindowExtY = 100;
75f11ad7 293}
0e320a79
DW
294
295#ifdef __WIN32__
296struct RECT32
297{
298 short left;
299 short top;
300 short right;
301 short bottom;
302};
303
304struct mfPLACEABLEHEADER {
6670f564
WS
305 DWORD key;
306 short hmf;
307 RECT32 bbox;
308 WORD inch;
309 DWORD reserved;
310 WORD checksum;
0e320a79
DW
311};
312#else
313struct mfPLACEABLEHEADER {
6670f564
WS
314 DWORD key;
315 HANDLE hmf;
316 RECT bbox;
317 WORD inch;
318 DWORD reserved;
319 WORD checksum;
0e320a79
DW
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 */
75f11ad7
DW
329
330bool wxMakeMetafilePlaceable(const wxString& filename, float scale)
0e320a79 331{
75f11ad7 332 return wxMakeMetafilePlaceable(filename, 0, 0, 0, 0, scale, FALSE);
0e320a79
DW
333}
334
6670f564
WS
335bool 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))
0e320a79 342{
75f11ad7
DW
343// TODO: the OS/2 PM/MM way to do this
344/*
6670f564
WS
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)
670f9935 367 return false;
75f11ad7 368
6670f564
WS
369 wxChar tempFileBuf[256];
370 wxGetTempFileName(wxT("mf"), tempFileBuf);
371 FILE *fHandle = fopen(wxConvFile.cWX2MB(tempFileBuf), "wb");
372 if (!fHandle)
670f9935 373 return false;
6670f564 374 fwrite((void *)&header, sizeof(unsigned char), sizeof(mfPLACEABLEHEADER), fHandle);
0e320a79 375
6670f564
WS
376 // Calculate origin and extent
377 int originX = x1;
378 int originY = y1;
379 int extentX = x2 - x1;
380 int extentY = (y2 - y1);
0e320a79 381
6670f564
WS
382 // Read metafile header and write
383 METAHEADER metaHeader;
384 fread((void *)&metaHeader, sizeof(unsigned char), sizeof(metaHeader), fd);
0e320a79 385
6670f564
WS
386 if (useOriginAndExtent)
387 metaHeader.mtSize += 15;
388 else
389 metaHeader.mtSize += 5;
0e320a79 390
6670f564 391 fwrite((void *)&metaHeader, sizeof(unsigned char), sizeof(metaHeader), fHandle);
0e320a79 392
6670f564
WS
393 // Write SetMapMode, SetWindowOrigin and SetWindowExt records
394 char modeBuffer[8];
395 char originBuffer[10];
396 char extentBuffer[10];
397 METARECORD *modeRecord = (METARECORD *)&modeBuffer;
0e320a79 398
6670f564
WS
399 METARECORD *originRecord = (METARECORD *)&originBuffer;
400 METARECORD *extentRecord = (METARECORD *)&extentBuffer;
75f11ad7 401
6670f564
WS
402 modeRecord->rdSize = 4;
403 modeRecord->rdFunction = META_SETMAPMODE;
404 modeRecord->rdParm[0] = MM_ANISOTROPIC;
0e320a79 405
6670f564
WS
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)
0e320a79 419 {
6670f564
WS
420 fwrite((void *)originBuffer, sizeof(char), 10, fHandle);
421 fwrite((void *)extentBuffer, sizeof(char), 10, fHandle);
0e320a79 422 }
6670f564
WS
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);
75f11ad7 438*/
6670f564 439 return true;
0e320a79
DW
440}
441
75f11ad7 442#endif // wxUSE_METAFILE