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