]> git.saurik.com Git - wxWidgets.git/blame - src/msw/metafile.cpp
compilation fix for non-threaded compilation (threads are still broken
[wxWidgets.git] / src / msw / metafile.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
265b0c07 2// Name: msw/metafile.cpp
06e43511 3// Purpose: wxMetafileDC etc.
2bda0e17 4// Author: Julian Smart
265b0c07 5// Modified by: VZ 07.01.00: implemented wxMetaFileDataObject
2bda0e17
KB
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
265b0c07 9// Licence: wxWindows license
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
265b0c07
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
265b0c07 21 #pragma implementation "metafile.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
265b0c07 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
31#ifndef WX_PRECOMP
265b0c07 32 #include "wx/setup.h"
2bda0e17
KB
33#endif
34
47d67540 35#if wxUSE_METAFILE
2bda0e17
KB
36
37#ifndef WX_PRECOMP
265b0c07
VZ
38 #include "wx/utils.h"
39 #include "wx/app.h"
2bda0e17
KB
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
265b0c07
VZ
49// ----------------------------------------------------------------------------
50// wxWin macros
51// ----------------------------------------------------------------------------
2bda0e17 52
06e43511
JS
53IMPLEMENT_DYNAMIC_CLASS(wxMetafile, wxObject)
54IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC, wxDC)
2bda0e17 55
265b0c07
VZ
56// ============================================================================
57// implementation
58// ============================================================================
59
60// ----------------------------------------------------------------------------
61// wxMetafileRefData
62// ----------------------------------------------------------------------------
63
2bda0e17 64/*
06e43511 65 * Metafiles
2bda0e17
KB
66 * Currently, the only purpose for making a metafile is to put
67 * it on the clipboard.
68 */
69
265b0c07 70wxMetafileRefData::wxMetafileRefData()
2bda0e17 71{
06e43511 72 m_metafile = 0;
e3065973 73 m_windowsMappingMode = wxMM_ANISOTROPIC;
265b0c07 74 m_width = m_height = 0;
2bda0e17
KB
75}
76
265b0c07 77wxMetafileRefData::~wxMetafileRefData()
2bda0e17 78{
06e43511
JS
79 if (m_metafile)
80 {
81 DeleteMetaFile((HMETAFILE) m_metafile);
82 m_metafile = 0;
83 }
2bda0e17
KB
84}
85
265b0c07
VZ
86// ----------------------------------------------------------------------------
87// wxMetafile
88// ----------------------------------------------------------------------------
89
06e43511 90wxMetafile::wxMetafile(const wxString& file)
2bda0e17 91{
06e43511
JS
92 m_refData = new wxMetafileRefData;
93
e3065973 94 M_METAFILEDATA->m_windowsMappingMode = wxMM_ANISOTROPIC;
06e43511 95 M_METAFILEDATA->m_metafile = 0;
223d09f6 96 if (!file.IsNull() && (file.Cmp(wxT("")) == 0))
06e43511
JS
97 M_METAFILEDATA->m_metafile = (WXHANDLE) GetMetaFile(file);
98}
99
265b0c07 100wxMetafile::~wxMetafile()
06e43511
JS
101{
102}
103
104bool wxMetafile::SetClipboard(int width, int height)
105{
106 if (!m_refData)
107 return FALSE;
108
265b0c07 109 bool alreadyOpen = wxClipboardOpen();
06e43511
JS
110 if (!alreadyOpen)
111 {
112 wxOpenClipboard();
265b0c07
VZ
113 if (!wxEmptyClipboard())
114 return FALSE;
06e43511
JS
115 }
116 bool success = wxSetClipboardData(wxDF_METAFILE, this, width,height);
265b0c07
VZ
117 if (!alreadyOpen)
118 wxCloseClipboard();
119
120 return success;
06e43511
JS
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)
265b0c07 131 PlayMetaFile(GetHdcOf(*dc), (HMETAFILE) M_METAFILEDATA->m_metafile);
06e43511
JS
132
133 dc->EndDrawing();
134
135 return TRUE;
2bda0e17
KB
136}
137
06e43511 138void wxMetafile::SetHMETAFILE(WXHANDLE mf)
2bda0e17 139{
265b0c07 140 if (!m_refData)
06e43511 141 m_refData = new wxMetafileRefData;
2bda0e17 142
06e43511
JS
143 M_METAFILEDATA->m_metafile = mf;
144}
2bda0e17 145
06e43511
JS
146void wxMetafile::SetWindowsMappingMode(int mm)
147{
265b0c07 148 if (!m_refData)
06e43511 149 m_refData = new wxMetafileRefData;
2bda0e17 150
06e43511 151 M_METAFILEDATA->m_windowsMappingMode = mm;
2bda0e17
KB
152}
153
265b0c07
VZ
154// ----------------------------------------------------------------------------
155// Metafile device context
156// ----------------------------------------------------------------------------
2bda0e17
KB
157
158// Original constructor that does not takes origin and extent. If you use this,
06e43511
JS
159// *DO* give origin/extent arguments to wxMakeMetafilePlaceable.
160wxMetafileDC::wxMetafileDC(const wxString& file)
2bda0e17 161{
265b0c07
VZ
162 m_metaFile = NULL;
163 m_minX = 10000;
164 m_minY = 10000;
165 m_maxX = -10000;
166 m_maxY = -10000;
167 // m_title = NULL;
2bda0e17 168
265b0c07
VZ
169 if (!file.IsNull() && wxFileExists(file))
170 wxRemoveFile(file);
2bda0e17 171
265b0c07
VZ
172 if (!file.IsNull() && (file != wxT("")))
173 m_hDC = (WXHDC) CreateMetaFile(file);
174 else
175 m_hDC = (WXHDC) CreateMetaFile(NULL);
7f555861 176
265b0c07 177 m_ok = (m_hDC != (WXHDC) 0) ;
2bda0e17 178
265b0c07
VZ
179 // Actual Windows mapping mode, for future reference.
180 m_windowsMappingMode = wxMM_TEXT;
e3065973 181
265b0c07 182 SetMapMode(wxMM_TEXT); // NOTE: does not set HDC mapmode (this is correct)
2bda0e17
KB
183}
184
185// New constructor that takes origin and extent. If you use this, don't
06e43511
JS
186// give origin/extent arguments to wxMakeMetafilePlaceable.
187wxMetafileDC::wxMetafileDC(const wxString& file, int xext, int yext, int xorg, int yorg)
2bda0e17 188{
265b0c07
VZ
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);
2bda0e17 196
265b0c07 197 m_ok = TRUE;
2bda0e17 198
265b0c07
VZ
199 ::SetWindowOrgEx((HDC) m_hDC,xorg,yorg, NULL);
200 ::SetWindowExtEx((HDC) m_hDC,xext,yext, NULL);
2bda0e17 201
265b0c07
VZ
202 // Actual Windows mapping mode, for future reference.
203 m_windowsMappingMode = wxMM_ANISOTROPIC;
e3065973 204
265b0c07 205 SetMapMode(wxMM_TEXT); // NOTE: does not set HDC mapmode (this is correct)
2bda0e17
KB
206}
207
265b0c07 208wxMetafileDC::~wxMetafileDC()
2bda0e17 209{
265b0c07 210 m_hDC = 0;
2bda0e17
KB
211}
212
06e43511 213void wxMetafileDC::GetTextExtent(const wxString& string, long *x, long *y,
7f555861 214 long *descent, long *externalLeading, wxFont *theFont, bool use16bit) const
2bda0e17 215{
265b0c07
VZ
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;
2bda0e17
KB
237}
238
265b0c07 239wxMetafile *wxMetafileDC::Close()
2bda0e17 240{
265b0c07
VZ
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;
2bda0e17
KB
252}
253
06e43511 254void wxMetafileDC::SetMapMode(int mode)
2bda0e17 255{
265b0c07 256 m_mappingMode = mode;
2bda0e17 257
265b0c07
VZ
258 // int pixel_width = 0;
259 // int pixel_height = 0;
260 // int mm_width = 0;
261 // int mm_height = 0;
2bda0e17 262
265b0c07
VZ
263 float mm2pixelsX = 10.0;
264 float mm2pixelsY = 10.0;
2bda0e17 265
265b0c07 266 switch (mode)
2bda0e17 267 {
265b0c07
VZ
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 }
2bda0e17 299 }
265b0c07
VZ
300 m_windowExtX = 100;
301 m_windowExtY = 100;
2bda0e17
KB
302}
303
265b0c07
VZ
304// ----------------------------------------------------------------------------
305// wxMakeMetafilePlaceable
306// ----------------------------------------------------------------------------
307
2bda0e17
KB
308#ifdef __WIN32__
309struct RECT32
310{
311 short left;
312 short top;
313 short right;
314 short bottom;
315};
316
317struct mfPLACEABLEHEADER {
265b0c07
VZ
318 DWORD key;
319 short hmf;
320 RECT32 bbox;
321 WORD inch;
322 DWORD reserved;
323 WORD checksum;
2bda0e17
KB
324};
325#else
326struct mfPLACEABLEHEADER {
265b0c07
VZ
327 DWORD key;
328 HANDLE hmf;
329 RECT bbox;
330 WORD inch;
331 DWORD reserved;
332 WORD checksum;
2bda0e17
KB
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,
e3065973 339 * and sets the window origin and extent to mimic the wxMM_TEXT mapping mode.
2bda0e17
KB
340 *
341 */
265b0c07 342
06e43511 343bool wxMakeMetafilePlaceable(const wxString& filename, float scale)
2bda0e17 344{
06e43511 345 return wxMakeMetafilePlaceable(filename, 0, 0, 0, 0, scale, FALSE);
2bda0e17
KB
346}
347
06e43511 348bool wxMakeMetafilePlaceable(const wxString& filename, int x1, int y1, int x2, int y2, float scale, bool useOriginAndExtent)
2bda0e17 349{
265b0c07
VZ
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)
2bda0e17 424 {
265b0c07
VZ
425 fwrite((void *)originBuffer, sizeof(char), 10, fHandle);
426 fwrite((void *)extentBuffer, sizeof(char), 10, fHandle);
2bda0e17 427 }
265b0c07
VZ
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
47cb3382
GT
446
447#if wxUSE_DRAG_AND_DROP
448
265b0c07
VZ
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;
2bda0e17
KB
487}
488
47cb3382
GT
489#endif // wxUSE_DRAG_AND_DROP
490
47d67540 491#endif // wxUSE_METAFILE
2845ddc2 492