]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/metafile.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/metafile.cpp 
   3 // Purpose:     wxMetafileDC etc. 
   4 // Author:      Julian Smart 
   5 // Modified by: VZ 07.01.00: implemented wxMetaFileDataObject 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  32 #include "wx/metafile.h" 
  34 #if wxUSE_METAFILE && !defined(wxMETAFILE_IS_ENH) 
  36 #include "wx/clipbrd.h" 
  37 #include "wx/msw/private.h" 
  42 // ---------------------------------------------------------------------------- 
  44 // ---------------------------------------------------------------------------- 
  46 IMPLEMENT_DYNAMIC_CLASS(wxMetafile
, wxObject
) 
  47 IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC
, wxDC
) 
  49 // ============================================================================ 
  51 // ============================================================================ 
  53 // ---------------------------------------------------------------------------- 
  55 // ---------------------------------------------------------------------------- 
  59  * Currently, the only purpose for making a metafile is to put 
  60  * it on the clipboard. 
  63 wxMetafileRefData::wxMetafileRefData() 
  66     m_windowsMappingMode 
= wxMM_ANISOTROPIC
; 
  67     m_width 
= m_height 
= 0; 
  70 wxMetafileRefData::~wxMetafileRefData() 
  74         DeleteMetaFile((HMETAFILE
) m_metafile
); 
  79 // ---------------------------------------------------------------------------- 
  81 // ---------------------------------------------------------------------------- 
  83 wxMetafile::wxMetafile(const wxString
& file
) 
  85     m_refData 
= new wxMetafileRefData
; 
  87     M_METAFILEDATA
->m_windowsMappingMode 
= wxMM_ANISOTROPIC
; 
  88     M_METAFILEDATA
->m_metafile 
= 0; 
  90         M_METAFILEDATA
->m_metafile 
= (WXHANDLE
) GetMetaFile(file
); 
  93 wxMetafile::~wxMetafile() 
  97 bool wxMetafile::SetClipboard(int width
, int height
) 
 105     bool alreadyOpen 
= wxClipboardOpen(); 
 109         if (!wxEmptyClipboard()) 
 112     bool success 
= wxSetClipboardData(wxDF_METAFILE
, this, width
,height
); 
 120 bool wxMetafile::Play(wxDC 
*dc
) 
 125     if (dc
->GetHDC() && M_METAFILEDATA
->m_metafile
) 
 127         if ( !::PlayMetaFile(GetHdcOf(*dc
), (HMETAFILE
) 
 128                              M_METAFILEDATA
->m_metafile
) ) 
 130             wxLogLastError(_T("PlayMetaFile")); 
 137 void wxMetafile::SetHMETAFILE(WXHANDLE mf
) 
 140         m_refData 
= new wxMetafileRefData
; 
 142     M_METAFILEDATA
->m_metafile 
= mf
; 
 145 void wxMetafile::SetWindowsMappingMode(int mm
) 
 148         m_refData 
= new wxMetafileRefData
; 
 150     M_METAFILEDATA
->m_windowsMappingMode 
= mm
; 
 153 // ---------------------------------------------------------------------------- 
 154 // Metafile device context 
 155 // ---------------------------------------------------------------------------- 
 157 // Original constructor that does not takes origin and extent. If you use this, 
 158 // *DO* give origin/extent arguments to wxMakeMetafilePlaceable. 
 159 wxMetafileDC::wxMetafileDC(const wxString
& file
) 
 168     if (!file
.IsNull() && wxFileExists(file
)) 
 171     if (!file
.IsNull() && (file 
!= wxEmptyString
)) 
 172         m_hDC 
= (WXHDC
) CreateMetaFile(file
); 
 174         m_hDC 
= (WXHDC
) CreateMetaFile(NULL
); 
 176     m_ok 
= (m_hDC 
!= (WXHDC
) 0) ; 
 178     // Actual Windows mapping mode, for future reference. 
 179     m_windowsMappingMode 
= wxMM_TEXT
; 
 181     SetMapMode(wxMM_TEXT
); // NOTE: does not set HDC mapmode (this is correct) 
 184 // New constructor that takes origin and extent. If you use this, don't 
 185 // give origin/extent arguments to wxMakeMetafilePlaceable. 
 186 wxMetafileDC::wxMetafileDC(const wxString
& file
, int xext
, int yext
, int xorg
, int yorg
) 
 192     if ( !file
.empty() && wxFileExists(file
) ) 
 194     m_hDC 
= (WXHDC
) CreateMetaFile(file
.empty() ? NULL 
: file
.c_str()); 
 198     ::SetWindowOrgEx((HDC
) m_hDC
,xorg
,yorg
, NULL
); 
 199     ::SetWindowExtEx((HDC
) m_hDC
,xext
,yext
, NULL
); 
 201     // Actual Windows mapping mode, for future reference. 
 202     m_windowsMappingMode 
= wxMM_ANISOTROPIC
; 
 204     SetMapMode(wxMM_TEXT
); // NOTE: does not set HDC mapmode (this is correct) 
 207 wxMetafileDC::~wxMetafileDC() 
 212 void wxMetafileDC::GetTextExtent(const wxString
& string
, long *x
, long *y
, 
 213                                  long *descent
, long *externalLeading
, wxFont 
*theFont
, bool WXUNUSED(use16bit
)) const 
 215     wxFont 
*fontToUse 
= theFont
; 
 217         fontToUse 
= (wxFont
*) &m_font
; 
 219     HDC dc 
= GetDC(NULL
); 
 223     ::GetTextExtentPoint32(dc
, WXSTRINGCAST string
, wxStrlen(WXSTRINGCAST string
), &sizeRect
); 
 224     GetTextMetrics(dc
, &tm
); 
 233         *descent 
= tm
.tmDescent
; 
 234     if ( externalLeading 
) 
 235         *externalLeading 
= tm
.tmExternalLeading
; 
 238 void wxMetafileDC::DoGetSize(int *width
, int *height
) const 
 240     wxCHECK_RET( m_refData
, _T("invalid wxMetafileDC") ); 
 243         *width 
= M_METAFILEDATA
->m_width
; 
 245         *height 
= M_METAFILEDATA
->m_height
; 
 248 wxMetafile 
*wxMetafileDC::Close() 
 250     SelectOldObjects(m_hDC
); 
 251     HANDLE mf 
= CloseMetaFile((HDC
) m_hDC
); 
 255         wxMetafile 
*wx_mf 
= new wxMetafile
; 
 256         wx_mf
->SetHMETAFILE((WXHANDLE
) mf
); 
 257         wx_mf
->SetWindowsMappingMode(m_windowsMappingMode
); 
 263 void wxMetafileDC::SetMapMode(int mode
) 
 265     m_mappingMode 
= mode
; 
 267     //  int pixel_width = 0; 
 268     //  int pixel_height = 0; 
 270     //  int mm_height = 0; 
 272     float mm2pixelsX 
= 10.0; 
 273     float mm2pixelsY 
= 10.0; 
 279                 m_logicalScaleX 
= (float)(twips2mm 
* mm2pixelsX
); 
 280                 m_logicalScaleY 
= (float)(twips2mm 
* mm2pixelsY
); 
 285                 m_logicalScaleX 
= (float)(pt2mm 
* mm2pixelsX
); 
 286                 m_logicalScaleY 
= (float)(pt2mm 
* mm2pixelsY
); 
 291                 m_logicalScaleX 
= mm2pixelsX
; 
 292                 m_logicalScaleY 
= mm2pixelsY
; 
 297                 m_logicalScaleX 
= (float)(mm2pixelsX
/10.0); 
 298                 m_logicalScaleY 
= (float)(mm2pixelsY
/10.0); 
 304                 m_logicalScaleX 
= 1.0; 
 305                 m_logicalScaleY 
= 1.0; 
 311 // ---------------------------------------------------------------------------- 
 312 // wxMakeMetafilePlaceable 
 313 // ---------------------------------------------------------------------------- 
 324 struct mfPLACEABLEHEADER 
{ 
 333 struct mfPLACEABLEHEADER 
{ 
 344  * Pass filename of existing non-placeable metafile, and bounding box. 
 345  * Adds a placeable metafile header, sets the mapping mode to anisotropic, 
 346  * and sets the window origin and extent to mimic the wxMM_TEXT mapping mode. 
 350 bool wxMakeMetafilePlaceable(const wxString
& filename
, float scale
) 
 352     return wxMakeMetafilePlaceable(filename
, 0, 0, 0, 0, scale
, false); 
 355 bool wxMakeMetafilePlaceable(const wxString
& filename
, int x1
, int y1
, int x2
, int y2
, float scale
, bool useOriginAndExtent
) 
 357     // I'm not sure if this is the correct way of suggesting a scale 
 358     // to the client application, but it's the only way I can find. 
 359     int unitsPerInch 
= (int)(576/scale
); 
 361     mfPLACEABLEHEADER header
; 
 362     header
.key 
= 0x9AC6CDD7L
; 
 364     header
.bbox
.left 
= (int)(x1
); 
 365     header
.bbox
.top 
= (int)(y1
); 
 366     header
.bbox
.right 
= (int)(x2
); 
 367     header
.bbox
.bottom 
= (int)(y2
); 
 368     header
.inch 
= unitsPerInch
; 
 371     // Calculate checksum 
 373     mfPLACEABLEHEADER 
*pMFHead 
= &header
; 
 374     for (p 
=(WORD 
*)pMFHead
,pMFHead 
-> checksum 
= 0; 
 375             p 
< (WORD 
*)&pMFHead 
->checksum
; ++p
) 
 376         pMFHead 
->checksum 
^= *p
; 
 378     FILE *fd 
= wxFopen(filename
.fn_str(), _T("rb")); 
 379     if (!fd
) return false; 
 381     wxChar tempFileBuf
[256]; 
 382     wxGetTempFileName(wxT("mf"), tempFileBuf
); 
 383     FILE *fHandle 
= wxFopen(wxFNCONV(tempFileBuf
), _T("wb")); 
 386     fwrite((void *)&header
, sizeof(unsigned char), sizeof(mfPLACEABLEHEADER
), fHandle
); 
 388     // Calculate origin and extent 
 391     int extentX 
= x2 
- x1
; 
 392     int extentY 
= (y2 
- y1
); 
 394     // Read metafile header and write 
 395     METAHEADER metaHeader
; 
 396     fread((void *)&metaHeader
, sizeof(unsigned char), sizeof(metaHeader
), fd
); 
 398     if (useOriginAndExtent
) 
 399         metaHeader
.mtSize 
+= 15; 
 401         metaHeader
.mtSize 
+= 5; 
 403     fwrite((void *)&metaHeader
, sizeof(unsigned char), sizeof(metaHeader
), fHandle
); 
 405     // Write SetMapMode, SetWindowOrigin and SetWindowExt records 
 407     char originBuffer
[10]; 
 408     char extentBuffer
[10]; 
 409     METARECORD 
*modeRecord 
= (METARECORD 
*)&modeBuffer
; 
 411     METARECORD 
*originRecord 
= (METARECORD 
*)&originBuffer
; 
 412     METARECORD 
*extentRecord 
= (METARECORD 
*)&extentBuffer
; 
 414     modeRecord
->rdSize 
= 4; 
 415     modeRecord
->rdFunction 
= META_SETMAPMODE
; 
 416     modeRecord
->rdParm
[0] = MM_ANISOTROPIC
; 
 418     originRecord
->rdSize 
= 5; 
 419     originRecord
->rdFunction 
= META_SETWINDOWORG
; 
 420     originRecord
->rdParm
[0] = originY
; 
 421     originRecord
->rdParm
[1] = originX
; 
 423     extentRecord
->rdSize 
= 5; 
 424     extentRecord
->rdFunction 
= META_SETWINDOWEXT
; 
 425     extentRecord
->rdParm
[0] = extentY
; 
 426     extentRecord
->rdParm
[1] = extentX
; 
 428     fwrite((void *)modeBuffer
, sizeof(char), 8, fHandle
); 
 430     if (useOriginAndExtent
) 
 432         fwrite((void *)originBuffer
, sizeof(char), 10, fHandle
); 
 433         fwrite((void *)extentBuffer
, sizeof(char), 10, fHandle
); 
 447     wxRemoveFile(filename
); 
 448     wxCopyFile(tempFileBuf
, filename
); 
 449     wxRemoveFile(tempFileBuf
); 
 454 #if wxUSE_DRAG_AND_DROP 
 456 // ---------------------------------------------------------------------------- 
 457 // wxMetafileDataObject 
 458 // ---------------------------------------------------------------------------- 
 460 size_t wxMetafileDataObject::GetDataSize() const 
 462     return sizeof(METAFILEPICT
); 
 465 bool wxMetafileDataObject::GetDataHere(void *buf
) const 
 467     METAFILEPICT 
*mfpict 
= (METAFILEPICT 
*)buf
; 
 468     const wxMetafile
& mf 
= GetMetafile(); 
 470     wxCHECK_MSG( mf
.GetHMETAFILE(), false, _T("copying invalid metafile") ); 
 472     // doesn't seem to work with any other mapping mode... 
 473     mfpict
->mm   
= MM_ANISOTROPIC
; //mf.GetWindowsMappingMode(); 
 474     mfpict
->xExt 
= mf
.GetWidth(); 
 475     mfpict
->yExt 
= mf
.GetHeight(); 
 477     // transform the picture size to HIMETRIC units (0.01mm) - as we don't know 
 478     // what DC the picture will be rendered to, use the default display one 
 479     PixelToHIMETRIC(&mfpict
->xExt
, &mfpict
->yExt
); 
 481     mfpict
->hMF  
= CopyMetaFile((HMETAFILE
)mf
.GetHMETAFILE(), NULL
); 
 486 bool wxMetafileDataObject::SetData(size_t WXUNUSED(len
), const void *buf
) 
 488     const METAFILEPICT 
*mfpict 
= (const METAFILEPICT 
*)buf
; 
 491     mf
.SetWindowsMappingMode(mfpict
->mm
); 
 493     LONG w 
= mfpict
->xExt
, 
 495     if ( mfpict
->mm 
== MM_ANISOTROPIC 
) 
 497         // in this case xExt and yExt contain suggested size in HIMETRIC units 
 498         // (0.01 mm) - transform this to something more reasonable (pixels) 
 499         HIMETRICToPixel(&w
, &h
); 
 504     mf
.SetHMETAFILE((WXHANDLE
)mfpict
->hMF
); 
 506     wxCHECK_MSG( mfpict
->hMF
, false, _T("pasting invalid metafile") ); 
 513 #endif // wxUSE_DRAG_AND_DROP 
 515 #endif // wxUSE_METAFILE