]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/metafile.cpp
Misc XRC format docs corrections.
[wxWidgets.git] / src / os2 / metafile.cpp
... / ...
CommitLineData
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
28extern bool wxClipboardIsOpen;
29
30IMPLEMENT_DYNAMIC_CLASS(wxMetafile, wxObject)
31IMPLEMENT_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
39wxMetafileRefData::wxMetafileRefData(void)
40{
41 m_metafile = 0;
42 m_windowsMappingMode = MM_ANISOTROPIC;
43}
44
45wxMetafileRefData::~wxMetafileRefData(void)
46{
47 if (m_metafile)
48 {
49// TODO: DeleteMetaFile((HMETAFILE) m_metafile);
50 m_metafile = 0;
51 }
52}
53
54wxMetafile::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
64wxMetafile::~wxMetafile(void)
65{
66}
67
68wxGDIRefData *wxMetafile::CreateGDIRefData() const
69{
70 return new wxMetafileRefData;
71}
72
73wxGDIRefData *wxMetafile::CloneGDIRefData(const wxGDIRefData *data) const
74{
75 return new wxMetafileRefData(*static_cast<const wxMetafileRefData *>(data));
76}
77
78bool 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
100bool 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
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;
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.
134wxMetafileDCImpl::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.
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)
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
192wxMetafileDCImpl::~wxMetafileDCImpl(void)
193{
194 m_hDC = 0;
195}
196
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
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
230wxMetafile *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
245void 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__
296struct RECT32
297{
298 short left;
299 short top;
300 short right;
301 short bottom;
302};
303
304struct mfPLACEABLEHEADER {
305 DWORD key;
306 short hmf;
307 RECT32 bbox;
308 WORD inch;
309 DWORD reserved;
310 WORD checksum;
311};
312#else
313struct 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
330bool wxMakeMetafilePlaceable(const wxString& filename, float scale)
331{
332 return wxMakeMetafilePlaceable(filename, 0, 0, 0, 0, scale, FALSE);
333}
334
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))
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