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/uma.h" 
  28 #include "wx/graphics.h" 
  29 #include "wx/mac/carbon/metafile.h" 
  34 IMPLEMENT_DYNAMIC_CLASS(wxMetafile
, wxObject
) 
  35 IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC
, wxDC
) 
  36 IMPLEMENT_ABSTRACT_CLASS(wxMetafileDCImpl
, wxGCDCImpl
) 
  38 #define M_METAFILEREFDATA( a ) ((wxMetafileRefData*)(a).GetRefData()) 
  40 class wxMetafileRefData 
: public wxGDIRefData
 
  43     // default ctor needed for CreateGDIRefData(), must be initialized later 
  44     wxMetafileRefData() { Init(); } 
  46     // creates a metafile from memory, assumes ownership 
  47     wxMetafileRefData(CFDataRef data
); 
  49     // prepares a recording metafile 
  50     wxMetafileRefData( int width
, int height
); 
  52     // prepares a metafile to be read from a file (if filename is not empty) 
  53     wxMetafileRefData( const wxString
& filename
); 
  55     virtual ~wxMetafileRefData(); 
  57     virtual bool IsOk() const { return m_data 
!= NULL
; } 
  61     int GetWidth() const { return m_width
; } 
  62     int GetHeight() const { return m_height
; } 
  64     CGPDFDocumentRef 
GetPDFDocument() const { return m_pdfDoc
; } 
  65     void UpdateDocumentFromData() ; 
  67     const wxCFDataRef
& GetData() const { return m_data
; } 
  68     CGContextRef 
GetContext() const { return m_context
; } 
  74     wxCFRef
<CGPDFDocumentRef
> m_pdfDoc
; 
  75     CGContextRef m_context
; 
  81 wxMetafileRefData::wxMetafileRefData(CFDataRef data
) : 
  85     UpdateDocumentFromData(); 
  88 wxMetafileRefData::wxMetafileRefData( const wxString
& filename 
) 
  92     if ( !filename
.empty() ) 
  94         wxCFRef
<CFMutableStringRef
> cfMutableString(CFStringCreateMutableCopy(NULL
, 0, wxCFStringRef(filename
))); 
  95         CFStringNormalize(cfMutableString
,kCFStringNormalizationFormD
); 
  96         wxCFRef
<CFURLRef
> url(CFURLCreateWithFileSystemPath(kCFAllocatorDefault
, cfMutableString 
, kCFURLPOSIXPathStyle
, false)); 
  97         m_pdfDoc
.reset(CGPDFDocumentCreateWithURL(url
)); 
 102 wxMetafileRefData::wxMetafileRefData( int width
, int height
) 
 109     CGRect r 
= CGRectMake( 0 , 0 , width  
, height 
); 
 111     CFMutableDataRef data 
= CFDataCreateMutable(kCFAllocatorDefault
, 0); 
 113     CGDataConsumerRef dataConsumer 
= wxMacCGDataConsumerCreateWithCFData(data
); 
 114     m_context 
= CGPDFContextCreate( dataConsumer
, (width 
!= 0 && height 
!= 0) ? &r 
: NULL 
, NULL 
); 
 115     CGDataConsumerRelease( dataConsumer 
); 
 118         CGPDFContextBeginPage(m_context
, NULL
); 
 120         CGColorSpaceRef genericColorSpace  
= wxMacGetGenericRGBColorSpace(); 
 122         CGContextSetFillColorSpace( m_context
, genericColorSpace 
); 
 123         CGContextSetStrokeColorSpace( m_context
, genericColorSpace 
); 
 125         CGContextTranslateCTM( m_context 
, 0 ,  height 
) ; 
 126         CGContextScaleCTM( m_context 
, 1 , -1 ) ; 
 130 wxMetafileRefData::~wxMetafileRefData() 
 134 void wxMetafileRefData::Init() 
 141 void wxMetafileRefData::Close() 
 143     CGPDFContextEndPage(m_context
); 
 145     CGContextRelease(m_context
); 
 148     UpdateDocumentFromData(); 
 151 void wxMetafileRefData::UpdateDocumentFromData() 
 153     wxCFRef
<CGDataProviderRef
> provider(wxMacCGDataProviderCreateWithCFData(m_data
)); 
 154     m_pdfDoc
.reset(CGPDFDocumentCreateWithProvider(provider
)); 
 155     if ( m_pdfDoc 
!= NULL 
) 
 157         CGPDFPageRef page 
= CGPDFDocumentGetPage( m_pdfDoc
, 1 ); 
 158         CGRect rect 
= CGPDFPageGetBoxRect ( page
, kCGPDFMediaBox
); 
 159         m_width 
= wx_static_cast(int, rect
.size
.width
); 
 160         m_height 
= wx_static_cast(int, rect
.size
.height
); 
 164 wxMetaFile::wxMetaFile(const wxString
& file
) 
 166     m_refData 
= new wxMetafileRefData(file
); 
 169 wxMetaFile::~wxMetaFile() 
 173 wxGDIRefData 
*wxMetaFile::CreateGDIRefData() const 
 175     return new wxMetafileRefData
; 
 178 wxGDIRefData 
*wxMetaFile::CloneGDIRefData(const wxGDIRefData 
*data
) const 
 180     return new wxMetafileRefData(*wx_static_cast(const wxMetafileRefData 
*, data
)); 
 183 WXHMETAFILE 
wxMetaFile::GetHMETAFILE() const 
 185     return (WXHMETAFILE
) (CFDataRef
) M_METAFILEDATA
->GetData(); 
 188 bool wxMetaFile::SetClipboard(int WXUNUSED(width
), int WXUNUSED(height
)) 
 192 #if wxUSE_DRAG_AND_DROP 
 193     if (m_refData 
== NULL
) 
 196     bool alreadyOpen 
= wxTheClipboard
->IsOpened(); 
 199         wxTheClipboard
->Open(); 
 200         wxTheClipboard
->Clear(); 
 203     wxDataObject 
*data 
= new wxMetafileDataObject( *this ); 
 204     success 
= wxTheClipboard
->SetData( data 
); 
 206         wxTheClipboard
->Close(); 
 212 void wxMetafile::SetHMETAFILE(WXHMETAFILE mf
) 
 216     m_refData 
= new wxMetafileRefData((CFDataRef
)mf
); 
 220 void wxMetafile::SetPICT(void* pictHandle
) 
 224     Handle picHandle 
= (Handle
) pictHandle
; 
 226     CFDataRef data 
= CFDataCreateWithBytesNoCopy( kCFAllocatorDefault
, (const UInt8
*) *picHandle
, GetHandleSize(picHandle
), kCFAllocatorNull
); 
 227     wxCFRef
<CGDataProviderRef
> provider(wxMacCGDataProviderCreateWithCFData(data
)); 
 228     QDPictRef pictRef 
= QDPictCreateWithProvider(provider
); 
 229     CGRect rect 
= QDPictGetBounds(pictRef
); 
 230     m_refData 
= new wxMetafileRefData(wx_static_cast(int, rect
.size
.width
), 
 231                                       wx_static_cast(int, rect
.size
.height
)); 
 232     QDPictDrawToCGContext( ((wxMetafileRefData
*) m_refData
)->GetContext(), rect
, pictRef 
); 
 234     QDPictRelease( pictRef 
); 
 235     ((wxMetafileRefData
*) m_refData
)->Close(); 
 239 bool wxMetaFile::Play(wxDC 
*dc
) 
 248         wxDCImpl 
*impl 
= dc
->GetImpl(); 
 249         wxGCDCImpl 
*gc_impl 
= wxDynamicCast(impl
, wxGCDCImpl
); 
 252             CGContextRef cg 
= (CGContextRef
) (gc_impl
->GetGraphicsContext()->GetNativeContext()); 
 253             CGPDFDocumentRef doc 
= M_METAFILEDATA
->GetPDFDocument(); 
 254             CGPDFPageRef page 
= CGPDFDocumentGetPage( doc
, 1 ); 
 255             wxMacCGContextStateSaver 
save(cg
); 
 256             CGContextDrawPDFPage( cg
, page 
); 
 258 //        CGContextTranslateCTM( cg, 0, bounds.size.width ); 
 259 //        CGContextScaleCTM( cg, 1, -1 ); 
 265 wxSize 
wxMetaFile::GetSize() const 
 267     wxSize dataSize 
= wxDefaultSize
; 
 271         dataSize
.x 
= M_METAFILEDATA
->GetWidth(); 
 272         dataSize
.y 
= M_METAFILEDATA
->GetHeight(); 
 278 // Metafile device context 
 280 // New constructor that takes origin and extent. If you use this, don't 
 281 // give origin/extent arguments to wxMakeMetaFilePlaceable. 
 283 wxMetafileDCImpl::wxMetafileDCImpl( 
 285     const wxString
& filename
, 
 286     int width
, int height
, 
 287     const wxString
& WXUNUSED(description
) ) : 
 290     wxASSERT_MSG( width 
!= 0 || height 
!= 0, wxT("no arbitration of metafile size supported") ); 
 291     wxASSERT_MSG( filename
.empty(), wxT("no file based metafile support yet")); 
 293     m_metaFile 
= new wxMetaFile( filename 
); 
 294     wxMetafileRefData
* metafiledata 
= new wxMetafileRefData(width
, height
); 
 296     m_metaFile
->SetRefData( metafiledata 
); 
 298     SetGraphicsContext( wxGraphicsContext::CreateFromNative(metafiledata
->GetContext())); 
 299     m_ok 
= (m_graphicContext 
!= NULL
) ; 
 301     SetMapMode( wxMM_TEXT 
); 
 304 wxMetafileDCImpl::~wxMetafileDCImpl() 
 308 void wxMetafileDCImpl::DoGetSize(int *width
, int *height
) const 
 310     wxCHECK_RET( m_metaFile
, wxT("GetSize() doesn't work without a metafile") ); 
 312     wxSize sz 
= m_metaFile
->GetSize(); 
 319 wxMetaFile 
*wxMetafileDCImpl::Close() 
 321     delete m_graphicContext
; 
 322     m_graphicContext 
= NULL
; 
 325     M_METAFILEREFDATA(*m_metaFile
)->Close(); 
 331 size_t wxMetafileDataObject::GetDataSize() const 
 334     wxMetafileRefData
* refData 
= M_METAFILEREFDATA(m_metafile
); 
 336         length 
= refData
->GetData().GetLength(); 
 340 bool wxMetafileDataObject::GetDataHere(void *buf
) const 
 344     wxMetafileRefData
* refData 
= M_METAFILEREFDATA(m_metafile
); 
 347         CFIndex length 
= refData
->GetData().GetLength(); 
 351             refData
->GetData().GetBytes(CFRangeMake(0,length
), (UInt8 
*) buf
); 
 357 bool wxMetafileDataObject::SetData(size_t len
, const void *buf
) 
 359     wxMetafileRefData
* metafiledata 
= new wxMetafileRefData(wxCFRefFromGet(wxCFDataRef((UInt8
*)buf
, len
).get())); 
 361     m_metafile
.SetRefData( metafiledata 
);