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