1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/carbon/metafile.cpp
3 // Purpose: wxMetaFile, wxMetaFileDC etc. These classes are optional.
4 // Author: Stefan Csomor
7 // Copyright: (c) Stefan Csomor
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // Currently, the only purpose for making a metafile
12 // is to put it on the clipboard.
15 #include "wx/wxprec.h"
24 #include "wx/metafile.h"
25 #include "wx/clipbrd.h"
26 #include "wx/osx/private.h"
27 #include "wx/graphics.h"
28 #include "wx/osx/metafile.h"
33 IMPLEMENT_DYNAMIC_CLASS(wxMetafile
, wxObject
)
34 IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC
, wxDC
)
35 IMPLEMENT_ABSTRACT_CLASS(wxMetafileDCImpl
, wxGCDCImpl
)
37 #define M_METAFILEREFDATA( a ) ((wxMetafileRefData*)(a).GetRefData())
39 class wxMetafileRefData
: public wxGDIRefData
42 // default ctor needed for CreateGDIRefData(), must be initialized later
43 wxMetafileRefData() { Init(); }
45 // creates a metafile from memory, assumes ownership
46 wxMetafileRefData(CFDataRef data
);
48 // prepares a recording metafile
49 wxMetafileRefData( int width
, int height
);
51 // prepares a metafile to be read from a file (if filename is not empty)
52 wxMetafileRefData( const wxString
& filename
);
54 virtual ~wxMetafileRefData();
56 virtual bool IsOk() const { return m_data
!= NULL
; }
60 int GetWidth() const { return m_width
; }
61 int GetHeight() const { return m_height
; }
63 CGPDFDocumentRef
GetPDFDocument() const { return m_pdfDoc
; }
64 void UpdateDocumentFromData() ;
66 const wxCFDataRef
& GetData() const { return m_data
; }
67 CGContextRef
GetContext() const { return m_context
; }
73 wxCFRef
<CGPDFDocumentRef
> m_pdfDoc
;
74 CGContextRef m_context
;
80 // Our m_pdfDoc field can't be easily (deep) copied and so we don't define a
82 wxDECLARE_NO_COPY_CLASS(wxMetafileRefData
);
85 wxMetafileRefData::wxMetafileRefData(CFDataRef data
) :
89 UpdateDocumentFromData();
92 wxMetafileRefData::wxMetafileRefData( const wxString
& filename
)
96 if ( !filename
.empty() )
98 wxCFRef
<CFMutableStringRef
> cfMutableString(CFStringCreateMutableCopy(NULL
, 0, wxCFStringRef(filename
)));
99 CFStringNormalize(cfMutableString
,kCFStringNormalizationFormD
);
100 wxCFRef
<CFURLRef
> url(CFURLCreateWithFileSystemPath(kCFAllocatorDefault
, cfMutableString
, kCFURLPOSIXPathStyle
, false));
101 m_pdfDoc
.reset(CGPDFDocumentCreateWithURL(url
));
106 wxMetafileRefData::wxMetafileRefData( int width
, int height
)
113 CGRect r
= CGRectMake( 0 , 0 , width
, height
);
115 CFMutableDataRef data
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
117 CGDataConsumerRef dataConsumer
= wxMacCGDataConsumerCreateWithCFData(data
);
118 m_context
= CGPDFContextCreate( dataConsumer
, (width
!= 0 && height
!= 0) ? &r
: NULL
, NULL
);
119 CGDataConsumerRelease( dataConsumer
);
122 CGPDFContextBeginPage(m_context
, NULL
);
124 CGColorSpaceRef genericColorSpace
= wxMacGetGenericRGBColorSpace();
126 CGContextSetFillColorSpace( m_context
, genericColorSpace
);
127 CGContextSetStrokeColorSpace( m_context
, genericColorSpace
);
129 CGContextTranslateCTM( m_context
, 0 , height
) ;
130 CGContextScaleCTM( m_context
, 1 , -1 ) ;
134 wxMetafileRefData::~wxMetafileRefData()
138 void wxMetafileRefData::Init()
145 void wxMetafileRefData::Close()
147 CGPDFContextEndPage(m_context
);
149 CGContextRelease(m_context
);
152 UpdateDocumentFromData();
155 void wxMetafileRefData::UpdateDocumentFromData()
157 wxCFRef
<CGDataProviderRef
> provider(wxMacCGDataProviderCreateWithCFData(m_data
));
158 m_pdfDoc
.reset(CGPDFDocumentCreateWithProvider(provider
));
159 if ( m_pdfDoc
!= NULL
)
161 CGPDFPageRef page
= CGPDFDocumentGetPage( m_pdfDoc
, 1 );
162 CGRect rect
= CGPDFPageGetBoxRect ( page
, kCGPDFMediaBox
);
163 m_width
= static_cast<int>(rect
.size
.width
);
164 m_height
= static_cast<int>(rect
.size
.height
);
168 wxMetaFile::wxMetaFile(const wxString
& file
)
170 m_refData
= new wxMetafileRefData(file
);
173 wxMetaFile::~wxMetaFile()
177 wxGDIRefData
*wxMetaFile::CreateGDIRefData() const
179 return new wxMetafileRefData
;
183 wxMetaFile::CloneGDIRefData(const wxGDIRefData
* WXUNUSED(data
)) const
185 wxFAIL_MSG( wxS("Cloning metafiles is not implemented in wxCarbon.") );
187 return new wxMetafileRefData
;
190 WXHMETAFILE
wxMetaFile::GetHMETAFILE() const
192 return (WXHMETAFILE
) (CFDataRef
) M_METAFILEDATA
->GetData();
195 bool wxMetaFile::SetClipboard(int WXUNUSED(width
), int WXUNUSED(height
))
199 #if wxUSE_DRAG_AND_DROP
200 if (m_refData
== NULL
)
203 bool alreadyOpen
= wxTheClipboard
->IsOpened();
206 wxTheClipboard
->Open();
207 wxTheClipboard
->Clear();
210 wxDataObject
*data
= new wxMetafileDataObject( *this );
211 success
= wxTheClipboard
->SetData( data
);
213 wxTheClipboard
->Close();
219 void wxMetafile::SetHMETAFILE(WXHMETAFILE mf
)
223 m_refData
= new wxMetafileRefData((CFDataRef
)mf
);
226 bool wxMetaFile::Play(wxDC
*dc
)
235 wxDCImpl
*impl
= dc
->GetImpl();
236 wxGCDCImpl
*gc_impl
= wxDynamicCast(impl
, wxGCDCImpl
);
239 CGContextRef cg
= (CGContextRef
) (gc_impl
->GetGraphicsContext()->GetNativeContext());
240 CGPDFDocumentRef doc
= M_METAFILEDATA
->GetPDFDocument();
241 CGPDFPageRef page
= CGPDFDocumentGetPage( doc
, 1 );
242 wxMacCGContextStateSaver
save(cg
);
243 CGContextDrawPDFPage( cg
, page
);
245 // CGContextTranslateCTM( cg, 0, bounds.size.width );
246 // CGContextScaleCTM( cg, 1, -1 );
252 wxSize
wxMetaFile::GetSize() const
254 wxSize dataSize
= wxDefaultSize
;
258 dataSize
.x
= M_METAFILEDATA
->GetWidth();
259 dataSize
.y
= M_METAFILEDATA
->GetHeight();
265 // Metafile device context
267 // New constructor that takes origin and extent. If you use this, don't
268 // give origin/extent arguments to wxMakeMetaFilePlaceable.
270 wxMetafileDCImpl::wxMetafileDCImpl(
272 const wxString
& filename
,
273 int width
, int height
,
274 const wxString
& WXUNUSED(description
) ) :
277 wxASSERT_MSG( width
!= 0 || height
!= 0, wxT("no arbitration of metafile size supported") );
278 wxASSERT_MSG( filename
.empty(), wxT("no file based metafile support yet"));
280 m_metaFile
= new wxMetaFile( filename
);
281 wxMetafileRefData
* metafiledata
= new wxMetafileRefData(width
, height
);
283 m_metaFile
->SetRefData( metafiledata
);
285 SetGraphicsContext( wxGraphicsContext::CreateFromNative(metafiledata
->GetContext()));
286 m_ok
= (m_graphicContext
!= NULL
) ;
288 SetMapMode( wxMM_TEXT
);
291 wxMetafileDCImpl::~wxMetafileDCImpl()
295 void wxMetafileDCImpl::DoGetSize(int *width
, int *height
) const
297 wxCHECK_RET( m_metaFile
, wxT("GetSize() doesn't work without a metafile") );
299 wxSize sz
= m_metaFile
->GetSize();
306 wxMetaFile
*wxMetafileDCImpl::Close()
308 wxDELETE(m_graphicContext
);
311 M_METAFILEREFDATA(*m_metaFile
)->Close();
317 size_t wxMetafileDataObject::GetDataSize() const
320 wxMetafileRefData
* refData
= M_METAFILEREFDATA(m_metafile
);
322 length
= refData
->GetData().GetLength();
326 bool wxMetafileDataObject::GetDataHere(void *buf
) const
330 wxMetafileRefData
* refData
= M_METAFILEREFDATA(m_metafile
);
333 CFIndex length
= refData
->GetData().GetLength();
337 refData
->GetData().GetBytes(CFRangeMake(0,length
), (UInt8
*) buf
);
343 bool wxMetafileDataObject::SetData(size_t len
, const void *buf
)
345 wxMetafileRefData
* metafiledata
= new wxMetafileRefData(wxCFRefFromGet(wxCFDataRef((UInt8
*)buf
, len
).get()));
347 m_metafile
.SetRefData( metafiledata
);