]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/metafile.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxMetafileDC etc.
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "metafile.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
34 #include "wx/metafile.h"
35 #include "wx/clipbrd.h"
36 #include "wx/msw/private.h"
41 extern bool wxClipboardIsOpen
;
43 #if !USE_SHARED_LIBRARY
44 IMPLEMENT_DYNAMIC_CLASS(wxMetafile
, wxObject
)
45 IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC
, wxDC
)
50 * Currently, the only purpose for making a metafile is to put
51 * it on the clipboard.
54 wxMetafileRefData::wxMetafileRefData(void)
57 m_windowsMappingMode
= wxMM_ANISOTROPIC
;
60 wxMetafileRefData::~wxMetafileRefData(void)
64 DeleteMetaFile((HMETAFILE
) m_metafile
);
69 wxMetafile::wxMetafile(const wxString
& file
)
71 m_refData
= new wxMetafileRefData
;
73 M_METAFILEDATA
->m_windowsMappingMode
= wxMM_ANISOTROPIC
;
74 M_METAFILEDATA
->m_metafile
= 0;
75 if (!file
.IsNull() && (file
.Cmp(T("")) == 0))
76 M_METAFILEDATA
->m_metafile
= (WXHANDLE
) GetMetaFile(file
);
79 wxMetafile::~wxMetafile(void)
83 bool wxMetafile::SetClipboard(int width
, int height
)
88 bool alreadyOpen
=wxClipboardOpen();
92 if (!wxEmptyClipboard()) return FALSE
;
94 bool success
= wxSetClipboardData(wxDF_METAFILE
, this, width
,height
);
95 if (!alreadyOpen
) wxCloseClipboard();
96 return (bool) success
;
99 bool wxMetafile::Play(wxDC
*dc
)
106 if (dc
->GetHDC() && M_METAFILEDATA
->m_metafile
)
107 PlayMetaFile((HDC
) dc
->GetHDC(), (HMETAFILE
) M_METAFILEDATA
->m_metafile
);
114 void wxMetafile::SetHMETAFILE(WXHANDLE mf
)
117 m_refData
= new wxMetafileRefData
;
119 M_METAFILEDATA
->m_metafile
= mf
;
122 void wxMetafile::SetWindowsMappingMode(int mm
)
125 m_refData
= new wxMetafileRefData
;
127 M_METAFILEDATA
->m_windowsMappingMode
= mm
;
131 * Metafile device context
135 // Original constructor that does not takes origin and extent. If you use this,
136 // *DO* give origin/extent arguments to wxMakeMetafilePlaceable.
137 wxMetafileDC::wxMetafileDC(const wxString
& file
)
146 if (!file
.IsNull() && wxFileExists(file
))
149 if (!file
.IsNull() && (file
!= T("")))
150 m_hDC
= (WXHDC
) CreateMetaFile(file
);
152 m_hDC
= (WXHDC
) CreateMetaFile(NULL
);
154 m_ok
= (m_hDC
!= (WXHDC
) 0) ;
156 // Actual Windows mapping mode, for future reference.
157 m_windowsMappingMode
= wxMM_TEXT
;
159 SetMapMode(wxMM_TEXT
); // NOTE: does not set HDC mapmode (this is correct)
162 // New constructor that takes origin and extent. If you use this, don't
163 // give origin/extent arguments to wxMakeMetafilePlaceable.
164 wxMetafileDC::wxMetafileDC(const wxString
& file
, int xext
, int yext
, int xorg
, int yorg
)
170 if (file
!= T("") && wxFileExists(file
)) wxRemoveFile(file
);
171 m_hDC
= (WXHDC
) CreateMetaFile(file
);
175 ::SetWindowOrgEx((HDC
) m_hDC
,xorg
,yorg
, NULL
);
176 ::SetWindowExtEx((HDC
) m_hDC
,xext
,yext
, NULL
);
178 // Actual Windows mapping mode, for future reference.
179 m_windowsMappingMode
= wxMM_ANISOTROPIC
;
181 SetMapMode(wxMM_TEXT
); // NOTE: does not set HDC mapmode (this is correct)
184 wxMetafileDC::~wxMetafileDC(void)
189 void wxMetafileDC::GetTextExtent(const wxString
& string
, long *x
, long *y
,
190 long *descent
, long *externalLeading
, wxFont
*theFont
, bool use16bit
) const
192 wxFont
*fontToUse
= theFont
;
194 fontToUse
= (wxFont
*) &m_font
;
196 HDC dc
= GetDC(NULL
);
200 GetTextExtentPoint(dc
, WXSTRINGCAST string
, wxStrlen(WXSTRINGCAST string
), &sizeRect
);
201 GetTextMetrics(dc
, &tm
);
210 *descent
= tm
.tmDescent
;
211 if ( externalLeading
)
212 *externalLeading
= tm
.tmExternalLeading
;
215 wxMetafile
*wxMetafileDC::Close(void)
217 SelectOldObjects(m_hDC
);
218 HANDLE mf
= CloseMetaFile((HDC
) m_hDC
);
222 wxMetafile
*wx_mf
= new wxMetafile
;
223 wx_mf
->SetHMETAFILE((WXHANDLE
) mf
);
224 wx_mf
->SetWindowsMappingMode(m_windowsMappingMode
);
230 void wxMetafileDC::SetMapMode(int mode
)
232 m_mappingMode
= mode
;
234 // int pixel_width = 0;
235 // int pixel_height = 0;
237 // int mm_height = 0;
239 float mm2pixelsX
= 10.0;
240 float mm2pixelsY
= 10.0;
246 m_logicalScaleX
= (float)(twips2mm
* mm2pixelsX
);
247 m_logicalScaleY
= (float)(twips2mm
* mm2pixelsY
);
252 m_logicalScaleX
= (float)(pt2mm
* mm2pixelsX
);
253 m_logicalScaleY
= (float)(pt2mm
* mm2pixelsY
);
258 m_logicalScaleX
= mm2pixelsX
;
259 m_logicalScaleY
= mm2pixelsY
;
264 m_logicalScaleX
= (float)(mm2pixelsX
/10.0);
265 m_logicalScaleY
= (float)(mm2pixelsY
/10.0);
271 m_logicalScaleX
= 1.0;
272 m_logicalScaleY
= 1.0;
289 struct mfPLACEABLEHEADER
{
298 struct mfPLACEABLEHEADER
{
309 * Pass filename of existing non-placeable metafile, and bounding box.
310 * Adds a placeable metafile header, sets the mapping mode to anisotropic,
311 * and sets the window origin and extent to mimic the wxMM_TEXT mapping mode.
315 bool wxMakeMetafilePlaceable(const wxString
& filename
, float scale
)
317 return wxMakeMetafilePlaceable(filename
, 0, 0, 0, 0, scale
, FALSE
);
320 bool wxMakeMetafilePlaceable(const wxString
& filename
, int x1
, int y1
, int x2
, int y2
, float scale
, bool useOriginAndExtent
)
322 // I'm not sure if this is the correct way of suggesting a scale
323 // to the client application, but it's the only way I can find.
324 int unitsPerInch
= (int)(576/scale
);
326 mfPLACEABLEHEADER header
;
327 header
.key
= 0x9AC6CDD7L
;
329 header
.bbox
.left
= (int)(x1
);
330 header
.bbox
.top
= (int)(y1
);
331 header
.bbox
.right
= (int)(x2
);
332 header
.bbox
.bottom
= (int)(y2
);
333 header
.inch
= unitsPerInch
;
336 // Calculate checksum
338 mfPLACEABLEHEADER
*pMFHead
= &header
;
339 for (p
=(WORD
*)pMFHead
,pMFHead
-> checksum
= 0;
340 p
< (WORD
*)&pMFHead
->checksum
; ++p
)
341 pMFHead
->checksum
^= *p
;
343 FILE *fd
= fopen(filename
.fn_str(), "rb");
344 if (!fd
) return FALSE
;
346 wxChar tempFileBuf
[256];
347 wxGetTempFileName(T("mf"), tempFileBuf
);
348 FILE *fHandle
= fopen(wxConvFile
.cWX2MB(tempFileBuf
), "wb");
351 fwrite((void *)&header
, sizeof(unsigned char), sizeof(mfPLACEABLEHEADER
), fHandle
);
353 // Calculate origin and extent
356 int extentX
= x2
- x1
;
357 int extentY
= (y2
- y1
);
359 // Read metafile header and write
360 METAHEADER metaHeader
;
361 fread((void *)&metaHeader
, sizeof(unsigned char), sizeof(metaHeader
), fd
);
363 if (useOriginAndExtent
)
364 metaHeader
.mtSize
+= 15;
366 metaHeader
.mtSize
+= 5;
368 fwrite((void *)&metaHeader
, sizeof(unsigned char), sizeof(metaHeader
), fHandle
);
370 // Write SetMapMode, SetWindowOrigin and SetWindowExt records
372 char originBuffer
[10];
373 char extentBuffer
[10];
374 METARECORD
*modeRecord
= (METARECORD
*)&modeBuffer
;
376 METARECORD
*originRecord
= (METARECORD
*)&originBuffer
;
377 METARECORD
*extentRecord
= (METARECORD
*)&extentBuffer
;
379 modeRecord
->rdSize
= 4;
380 modeRecord
->rdFunction
= META_SETMAPMODE
;
381 modeRecord
->rdParm
[0] = MM_ANISOTROPIC
;
383 originRecord
->rdSize
= 5;
384 originRecord
->rdFunction
= META_SETWINDOWORG
;
385 originRecord
->rdParm
[0] = originY
;
386 originRecord
->rdParm
[1] = originX
;
388 extentRecord
->rdSize
= 5;
389 extentRecord
->rdFunction
= META_SETWINDOWEXT
;
390 extentRecord
->rdParm
[0] = extentY
;
391 extentRecord
->rdParm
[1] = extentX
;
393 fwrite((void *)modeBuffer
, sizeof(char), 8, fHandle
);
395 if (useOriginAndExtent
)
397 fwrite((void *)originBuffer
, sizeof(char), 10, fHandle
);
398 fwrite((void *)extentBuffer
, sizeof(char), 10, fHandle
);
412 wxRemoveFile(filename
);
413 wxCopyFile(tempFileBuf
, filename
);
414 wxRemoveFile(tempFileBuf
);
418 #endif // wxUSE_METAFILE