]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/metafile.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "metafile.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  40 #include "wx/metafile.h" 
  42 #if wxUSE_METAFILE && !defined(wxMETAFILE_IS_ENH) 
  44 #include "wx/clipbrd.h" 
  45 #include "wx/msw/private.h" 
  50 // ---------------------------------------------------------------------------- 
  52 // ---------------------------------------------------------------------------- 
  54 IMPLEMENT_DYNAMIC_CLASS(wxMetafile
, wxObject
) 
  55 IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC
, wxDC
) 
  57 // ============================================================================ 
  59 // ============================================================================ 
  61 // ---------------------------------------------------------------------------- 
  63 // ---------------------------------------------------------------------------- 
  67  * Currently, the only purpose for making a metafile is to put 
  68  * it on the clipboard. 
  71 wxMetafileRefData::wxMetafileRefData() 
  74     m_windowsMappingMode 
= wxMM_ANISOTROPIC
; 
  75     m_width 
= m_height 
= 0; 
  78 wxMetafileRefData::~wxMetafileRefData() 
  82         DeleteMetaFile((HMETAFILE
) m_metafile
); 
  87 // ---------------------------------------------------------------------------- 
  89 // ---------------------------------------------------------------------------- 
  91 wxMetafile::wxMetafile(const wxString
& file
) 
  93     m_refData 
= new wxMetafileRefData
; 
  95     M_METAFILEDATA
->m_windowsMappingMode 
= wxMM_ANISOTROPIC
; 
  96     M_METAFILEDATA
->m_metafile 
= 0; 
  98         M_METAFILEDATA
->m_metafile 
= (WXHANDLE
) GetMetaFile(file
); 
 101 wxMetafile::~wxMetafile() 
 105 bool wxMetafile::SetClipboard(int width
, int height
) 
 113     bool alreadyOpen 
= wxClipboardOpen(); 
 117         if (!wxEmptyClipboard()) 
 120     bool success 
= wxSetClipboardData(wxDF_METAFILE
, this, width
,height
); 
 128 bool wxMetafile::Play(wxDC 
*dc
) 
 135     if (dc
->GetHDC() && M_METAFILEDATA
->m_metafile
) 
 137         if ( !::PlayMetaFile(GetHdcOf(*dc
), (HMETAFILE
) 
 138                              M_METAFILEDATA
->m_metafile
) ) 
 140             wxLogLastError(_T("PlayMetaFile")); 
 149 void wxMetafile::SetHMETAFILE(WXHANDLE mf
) 
 152         m_refData 
= new wxMetafileRefData
; 
 154     M_METAFILEDATA
->m_metafile 
= mf
; 
 157 void wxMetafile::SetWindowsMappingMode(int mm
) 
 160         m_refData 
= new wxMetafileRefData
; 
 162     M_METAFILEDATA
->m_windowsMappingMode 
= mm
; 
 165 // ---------------------------------------------------------------------------- 
 166 // Metafile device context 
 167 // ---------------------------------------------------------------------------- 
 169 // Original constructor that does not takes origin and extent. If you use this, 
 170 // *DO* give origin/extent arguments to wxMakeMetafilePlaceable. 
 171 wxMetafileDC::wxMetafileDC(const wxString
& file
) 
 180     if (!file
.IsNull() && wxFileExists(file
)) 
 183     if (!file
.IsNull() && (file 
!= wxEmptyString
)) 
 184         m_hDC 
= (WXHDC
) CreateMetaFile(file
); 
 186         m_hDC 
= (WXHDC
) CreateMetaFile(NULL
); 
 188     m_ok 
= (m_hDC 
!= (WXHDC
) 0) ; 
 190     // Actual Windows mapping mode, for future reference. 
 191     m_windowsMappingMode 
= wxMM_TEXT
; 
 193     SetMapMode(wxMM_TEXT
); // NOTE: does not set HDC mapmode (this is correct) 
 196 // New constructor that takes origin and extent. If you use this, don't 
 197 // give origin/extent arguments to wxMakeMetafilePlaceable. 
 198 wxMetafileDC::wxMetafileDC(const wxString
& file
, int xext
, int yext
, int xorg
, int yorg
) 
 204     if ( !file
.IsEmpty() && wxFileExists(file
)) 
 206     m_hDC 
= (WXHDC
) CreateMetaFile(file
); 
 210     ::SetWindowOrgEx((HDC
) m_hDC
,xorg
,yorg
, NULL
); 
 211     ::SetWindowExtEx((HDC
) m_hDC
,xext
,yext
, NULL
); 
 213     // Actual Windows mapping mode, for future reference. 
 214     m_windowsMappingMode 
= wxMM_ANISOTROPIC
; 
 216     SetMapMode(wxMM_TEXT
); // NOTE: does not set HDC mapmode (this is correct) 
 219 wxMetafileDC::~wxMetafileDC() 
 224 void wxMetafileDC::GetTextExtent(const wxString
& string
, long *x
, long *y
, 
 225                                  long *descent
, long *externalLeading
, wxFont 
*theFont
, bool WXUNUSED(use16bit
)) const 
 227     wxFont 
*fontToUse 
= theFont
; 
 229         fontToUse 
= (wxFont
*) &m_font
; 
 231     HDC dc 
= GetDC(NULL
); 
 235     GetTextExtentPoint(dc
, WXSTRINGCAST string
, wxStrlen(WXSTRINGCAST string
), &sizeRect
); 
 236     GetTextMetrics(dc
, &tm
); 
 245         *descent 
= tm
.tmDescent
; 
 246     if ( externalLeading 
) 
 247         *externalLeading 
= tm
.tmExternalLeading
; 
 250 wxMetafile 
*wxMetafileDC::Close() 
 252     SelectOldObjects(m_hDC
); 
 253     HANDLE mf 
= CloseMetaFile((HDC
) m_hDC
); 
 257         wxMetafile 
*wx_mf 
= new wxMetafile
; 
 258         wx_mf
->SetHMETAFILE((WXHANDLE
) mf
); 
 259         wx_mf
->SetWindowsMappingMode(m_windowsMappingMode
); 
 265 void wxMetafileDC::SetMapMode(int mode
) 
 267     m_mappingMode 
= mode
; 
 269     //  int pixel_width = 0; 
 270     //  int pixel_height = 0; 
 272     //  int mm_height = 0; 
 274     float mm2pixelsX 
= 10.0; 
 275     float mm2pixelsY 
= 10.0; 
 281                 m_logicalScaleX 
= (float)(twips2mm 
* mm2pixelsX
); 
 282                 m_logicalScaleY 
= (float)(twips2mm 
* mm2pixelsY
); 
 287                 m_logicalScaleX 
= (float)(pt2mm 
* mm2pixelsX
); 
 288                 m_logicalScaleY 
= (float)(pt2mm 
* mm2pixelsY
); 
 293                 m_logicalScaleX 
= mm2pixelsX
; 
 294                 m_logicalScaleY 
= mm2pixelsY
; 
 299                 m_logicalScaleX 
= (float)(mm2pixelsX
/10.0); 
 300                 m_logicalScaleY 
= (float)(mm2pixelsY
/10.0); 
 306                 m_logicalScaleX 
= 1.0; 
 307                 m_logicalScaleY 
= 1.0; 
 313 // ---------------------------------------------------------------------------- 
 314 // wxMakeMetafilePlaceable 
 315 // ---------------------------------------------------------------------------- 
 326 struct mfPLACEABLEHEADER 
{ 
 335 struct mfPLACEABLEHEADER 
{ 
 346  * Pass filename of existing non-placeable metafile, and bounding box. 
 347  * Adds a placeable metafile header, sets the mapping mode to anisotropic, 
 348  * and sets the window origin and extent to mimic the wxMM_TEXT mapping mode. 
 352 bool wxMakeMetafilePlaceable(const wxString
& filename
, float scale
) 
 354     return wxMakeMetafilePlaceable(filename
, 0, 0, 0, 0, scale
, false); 
 357 bool wxMakeMetafilePlaceable(const wxString
& filename
, int x1
, int y1
, int x2
, int y2
, float scale
, bool useOriginAndExtent
) 
 359     // I'm not sure if this is the correct way of suggesting a scale 
 360     // to the client application, but it's the only way I can find. 
 361     int unitsPerInch 
= (int)(576/scale
); 
 363     mfPLACEABLEHEADER header
; 
 364     header
.key 
= 0x9AC6CDD7L
; 
 366     header
.bbox
.left 
= (int)(x1
); 
 367     header
.bbox
.top 
= (int)(y1
); 
 368     header
.bbox
.right 
= (int)(x2
); 
 369     header
.bbox
.bottom 
= (int)(y2
); 
 370     header
.inch 
= unitsPerInch
; 
 373     // Calculate checksum 
 375     mfPLACEABLEHEADER 
*pMFHead 
= &header
; 
 376     for (p 
=(WORD 
*)pMFHead
,pMFHead 
-> checksum 
= 0; 
 377             p 
< (WORD 
*)&pMFHead 
->checksum
; ++p
) 
 378         pMFHead 
->checksum 
^= *p
; 
 380     FILE *fd 
= wxFopen(filename
.fn_str(), _T("rb")); 
 381     if (!fd
) return false; 
 383     wxChar tempFileBuf
[256]; 
 384     wxGetTempFileName(wxT("mf"), tempFileBuf
); 
 385     FILE *fHandle 
= wxFopen(wxFNCONV(tempFileBuf
), _T("wb")); 
 388     fwrite((void *)&header
, sizeof(unsigned char), sizeof(mfPLACEABLEHEADER
), fHandle
); 
 390     // Calculate origin and extent 
 393     int extentX 
= x2 
- x1
; 
 394     int extentY 
= (y2 
- y1
); 
 396     // Read metafile header and write 
 397     METAHEADER metaHeader
; 
 398     fread((void *)&metaHeader
, sizeof(unsigned char), sizeof(metaHeader
), fd
); 
 400     if (useOriginAndExtent
) 
 401         metaHeader
.mtSize 
+= 15; 
 403         metaHeader
.mtSize 
+= 5; 
 405     fwrite((void *)&metaHeader
, sizeof(unsigned char), sizeof(metaHeader
), fHandle
); 
 407     // Write SetMapMode, SetWindowOrigin and SetWindowExt records 
 409     char originBuffer
[10]; 
 410     char extentBuffer
[10]; 
 411     METARECORD 
*modeRecord 
= (METARECORD 
*)&modeBuffer
; 
 413     METARECORD 
*originRecord 
= (METARECORD 
*)&originBuffer
; 
 414     METARECORD 
*extentRecord 
= (METARECORD 
*)&extentBuffer
; 
 416     modeRecord
->rdSize 
= 4; 
 417     modeRecord
->rdFunction 
= META_SETMAPMODE
; 
 418     modeRecord
->rdParm
[0] = MM_ANISOTROPIC
; 
 420     originRecord
->rdSize 
= 5; 
 421     originRecord
->rdFunction 
= META_SETWINDOWORG
; 
 422     originRecord
->rdParm
[0] = originY
; 
 423     originRecord
->rdParm
[1] = originX
; 
 425     extentRecord
->rdSize 
= 5; 
 426     extentRecord
->rdFunction 
= META_SETWINDOWEXT
; 
 427     extentRecord
->rdParm
[0] = extentY
; 
 428     extentRecord
->rdParm
[1] = extentX
; 
 430     fwrite((void *)modeBuffer
, sizeof(char), 8, fHandle
); 
 432     if (useOriginAndExtent
) 
 434         fwrite((void *)originBuffer
, sizeof(char), 10, fHandle
); 
 435         fwrite((void *)extentBuffer
, sizeof(char), 10, fHandle
); 
 449     wxRemoveFile(filename
); 
 450     wxCopyFile(tempFileBuf
, filename
); 
 451     wxRemoveFile(tempFileBuf
); 
 456 #if wxUSE_DRAG_AND_DROP 
 458 // ---------------------------------------------------------------------------- 
 459 // wxMetafileDataObject 
 460 // ---------------------------------------------------------------------------- 
 462 size_t wxMetafileDataObject::GetDataSize() const 
 464     return sizeof(METAFILEPICT
); 
 467 bool wxMetafileDataObject::GetDataHere(void *buf
) const 
 469     METAFILEPICT 
*mfpict 
= (METAFILEPICT 
*)buf
; 
 470     const wxMetafile
& mf 
= GetMetafile(); 
 472     wxCHECK_MSG( mf
.GetHMETAFILE(), false, _T("copying invalid metafile") ); 
 474     // doesn't seem to work with any other mapping mode... 
 475     mfpict
->mm   
= MM_ANISOTROPIC
; //mf.GetWindowsMappingMode(); 
 476     mfpict
->xExt 
= mf
.GetWidth(); 
 477     mfpict
->yExt 
= mf
.GetHeight(); 
 479     // transform the picture size to HIMETRIC units (0.01mm) - as we don't know 
 480     // what DC the picture will be rendered to, use the default display one 
 481     PixelToHIMETRIC(&mfpict
->xExt
, &mfpict
->yExt
); 
 483     mfpict
->hMF  
= CopyMetaFile((HMETAFILE
)mf
.GetHMETAFILE(), NULL
); 
 488 bool wxMetafileDataObject::SetData(size_t WXUNUSED(len
), const void *buf
) 
 490     const METAFILEPICT 
*mfpict 
= (const METAFILEPICT 
*)buf
; 
 493     mf
.SetWindowsMappingMode(mfpict
->mm
); 
 495     LONG w 
= mfpict
->xExt
, 
 497     if ( mfpict
->mm 
== MM_ANISOTROPIC 
) 
 499         // in this case xExt and yExt contain suggested size in HIMETRIC units 
 500         // (0.01 mm) - transform this to something more reasonable (pixels) 
 501         HIMETRICToPixel(&w
, &h
); 
 506     mf
.SetHMETAFILE((WXHANDLE
)mfpict
->hMF
); 
 508     wxCHECK_MSG( mfpict
->hMF
, false, _T("pasting invalid metafile") ); 
 515 #endif // wxUSE_DRAG_AND_DROP 
 517 #endif // wxUSE_METAFILE