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