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