1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/mac/carbon/metafile.cpp 
   3 // Purpose:     wxMetaFile, wxMetaFileDC etc. These classes are optional. 
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) Stefan Csomor 
   9 // Licence:       wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // Currently, the only purpose for making a metafile 
  13 // is to put it on the clipboard. 
  16 #include "wx/wxprec.h" 
  25 #include "wx/metafile.h" 
  26 #include "wx/clipbrd.h" 
  27 #include "wx/mac/private.h" 
  28 #include "wx/graphics.h" 
  33 IMPLEMENT_DYNAMIC_CLASS(wxMetafile
, wxObject
) 
  34 IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC
, wxDC
) 
  36 class wxMetafileRefData
: public wxGDIRefData
 
  38     friend class WXDLLEXPORT wxMetafile
; 
  42     virtual ~wxMetafileRefData(); 
  47 #if wxMAC_USE_CORE_GRAPHICS 
  48     QDPictRef m_qdPictRef
; 
  52 wxMetafileRefData::wxMetafileRefData() 
  56 #if wxMAC_USE_CORE_GRAPHICS 
  61 wxMetafileRefData::~wxMetafileRefData() 
  66         KillPicture( (PicHandle
)m_metafile 
); 
  69 #if wxMAC_USE_CORE_GRAPHICS 
  70         QDPictRelease( m_qdPictRef 
); 
  77 wxMetaFile::wxMetaFile(const wxString
& file
) 
  79     m_refData 
= new wxMetafileRefData
; 
  81     M_METAFILEDATA
->m_metafile 
= NULL
; 
  82     wxASSERT_MSG( file
.empty(), wxT("no file-based metafile support yet") ); 
  85     if (!file
.IsNull() && (file
.Cmp("") == 0)) 
  86         M_METAFILEDATA
->m_metafile 
= (WXHANDLE
) GetMetaFile( file 
); 
  90 wxMetaFile::~wxMetaFile() 
  94 bool wxMetaFile::IsOk() const 
  96     return (M_METAFILEDATA 
&& (M_METAFILEDATA
->m_metafile 
!= NULL
)); 
  99 WXHMETAFILE 
wxMetaFile::GetHMETAFILE() const 
 101     return (WXHMETAFILE
) M_METAFILEDATA
->m_metafile
; 
 104 bool wxMetaFile::SetClipboard(int width
, int height
) 
 108 #if wxUSE_DRAG_AND_DROP 
 109     // TODO: to finish this port, we need the data object first 
 110     if (m_refData 
== NULL
) 
 113     bool alreadyOpen 
= wxTheClipboard
->IsOpened(); 
 116         wxTheClipboard
->Open(); 
 117         wxTheClipboard
->Clear(); 
 120     wxDataObject 
*data 
= new wxMetafileDataObject( *this ); 
 121     success 
= wxTheClipboard
->SetData( data 
); 
 123         wxTheClipboard
->Close(); 
 129 void wxMetafile::SetHMETAFILE(WXHMETAFILE mf
) 
 133     m_refData 
= new wxMetafileRefData
; 
 135     M_METAFILEDATA
->m_metafile 
= (PicHandle
)mf
; 
 137 #if wxMAC_USE_CORE_GRAPHICS 
 138     size_t sz 
= GetHandleSize( (Handle
) M_METAFILEDATA
->m_metafile 
); 
 139     wxMemoryBuffer
* membuf 
= new wxMemoryBuffer( sz 
); 
 140     void *data 
= membuf
->GetWriteBuf( sz 
); 
 142     memcpy( data
, *M_METAFILEDATA
->m_metafile
, sz 
); 
 143     membuf
->UngetWriteBuf( sz 
); 
 144     CGDataProviderRef provider 
= CGDataProviderCreateWithData( 
 145         membuf
, data
, sz
, wxMacMemoryBufferReleaseProc 
); 
 146     M_METAFILEDATA
->m_qdPictRef 
= NULL
; 
 149     if (provider 
!= NULL
) 
 151         M_METAFILEDATA
->m_qdPictRef 
= QDPictCreateWithProvider( provider 
); 
 152         CGDataProviderRelease( provider 
); 
 158 bool wxMetaFile::Play(wxDC 
*dc
) 
 167 #if wxMAC_USE_CORE_GRAPHICS 
 169         QDPictRef cgPictRef 
= M_METAFILEDATA
->m_qdPictRef
; 
 170         CGContextRef cg 
= (CGContextRef
) dc
->GetGraphicsContext()->GetNativeContext(); 
 171         CGRect bounds 
= QDPictGetBounds( cgPictRef 
); 
 173         CGContextSaveGState( cg 
); 
 174         CGContextTranslateCTM( cg
, 0, bounds
.size
.width 
); 
 175         CGContextScaleCTM( cg
, 1, -1 ); 
 176         QDPictDrawToCGContext( cg
, bounds
, cgPictRef 
); 
 177         CGContextRestoreGState( cg 
); 
 180         PicHandle pict 
= (PicHandle
)GetHMETAFILE(); 
 181         wxMacPortSetter 
helper( dc 
); 
 183         DrawPicture( pict
, wxMacGetPictureBounds( pict
, &picFrame 
) ); 
 190 wxSize 
wxMetaFile::GetSize() const 
 192     wxSize dataSize 
= wxDefaultSize
; 
 197        PicHandle pict 
= (PicHandle
)GetHMETAFILE(); 
 199         wxMacGetPictureBounds( pict
, &r 
); 
 200         dataSize
.x 
= r
.right 
- r
.left
; 
 201         dataSize
.y 
= r
.bottom 
- r
.top
; 
 208 // Metafile device context 
 210 // New constructor that takes origin and extent. If you use this, don't 
 211 // give origin/extent arguments to wxMakeMetaFilePlaceable. 
 213 wxMetaFileDC::wxMetaFileDC( 
 214     const wxString
& filename
, 
 215     int width
, int height
, 
 216     const wxString
& WXUNUSED(description
) ) 
 218     wxASSERT_MSG( width 
<= 0 || height 
<= 0, wxT("no arbitration of metafile size supported") ); 
 219     wxASSERT_MSG( filename
.empty(), wxT("no file based metafile support yet")); 
 221     m_metaFile 
= new wxMetaFile( filename 
); 
 223 #if wxMAC_USE_CORE_GRAPHICS 
 225     Rect r 
= { 0, 0, height
, width 
}; 
 227     RectRgn( (RgnHandle
)m_macBoundaryClipRgn
, &r 
); 
 228     CopyRgn( (RgnHandle
)m_macBoundaryClipRgn
, (RgnHandle
)m_macCurrentClipRgn 
); 
 230     m_metaFile
->SetHMETAFILE( (WXHMETAFILE
)OpenPicture( &r 
) ); 
 231     ::GetPort( (GrafPtr
*)&m_macPort 
); 
 236     SetMapMode( wxMM_TEXT 
); 
 239 wxMetaFileDC::~wxMetaFileDC() 
 243 void wxMetaFileDC::DoGetSize(int *width
, int *height
) const 
 245     wxCHECK_RET( m_metaFile
, wxT("GetSize() doesn't work without a metafile") ); 
 247     wxSize sz 
= m_metaFile
->GetSize(); 
 254 wxMetaFile 
*wxMetaFileDC::Close() 
 263 size_t wxMetafileDataObject::GetDataSize() const 
 265     return GetHandleSize( (Handle
) (*((wxMetafile
*)&m_metafile
)).GetHMETAFILE() ); 
 268 bool wxMetafileDataObject::GetDataHere(void *buf
) const 
 270     Handle pictH 
= (Handle
)(*((wxMetafile
*)&m_metafile
)).GetHMETAFILE(); 
 271     bool result 
= (pictH 
!= NULL
); 
 274         memcpy( buf
, *pictH
, GetHandleSize( pictH 
) ); 
 279 bool wxMetafileDataObject::SetData(size_t len
, const void *buf
) 
 281     Handle handle 
= NewHandle( len 
); 
 282     SetHandleSize( handle
, len 
); 
 283     memcpy( *handle
, buf
, len 
); 
 284     m_metafile
.SetHMETAFILE( (WXHMETAFILE
) handle 
);