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"
33 IMPLEMENT_DYNAMIC_CLASS(wxMetafile
, wxObject
)
34 IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC
, wxDC
)
36 #define M_METAFILEREFDATA( a ) ((wxMetafileRefData*)(a).GetRefData())
38 class wxMetafileRefData
: public wxGDIRefData
41 #if wxMAC_USE_CORE_GRAPHICS
42 // creates a metafile from memory, assumes ownership
43 wxMetafileRefData(CFDataRef data
);
45 // creates a metafile from memory, assumes ownership
46 wxMetafileRefData(PicHandle data
);
48 // prepares a recording metafile
49 wxMetafileRefData( int width
, int height
);
50 // prepares a metafile to be read from a file (if filename is not empty)
51 wxMetafileRefData( const wxString
& filename
);
52 virtual ~wxMetafileRefData();
56 int GetWidth() const { return m_width
; }
57 int GetHeight() const { return m_height
; }
59 #if wxMAC_USE_CORE_GRAPHICS
60 CGPDFDocumentRef
GetPDFDocument() const { return m_pdfDoc
; }
61 void UpdateDocumentFromData() ;
63 const wxCFDataRef
& GetData() const { return m_data
; }
64 CGContextRef
GetContext() const { return m_context
; }
66 PicHandle
GetHandle() const { return m_metafile
; }
71 #if wxMAC_USE_CORE_GRAPHICS
73 wxCFRef
<CGPDFDocumentRef
> m_pdfDoc
;
74 CGContextRef m_context
;
82 #if !wxMAC_USE_CORE_GRAPHICS
83 wxMetafileRefData::wxMetafileRefData(PicHandle pict
)
89 wxMacGetPictureBounds( m_metafile
, &r
);
90 m_width
= r
.right
- r
.left
;
91 m_height
= r
.bottom
- r
.top
;
94 wxMetafileRefData::wxMetafileRefData(CFDataRef data
) :
98 UpdateDocumentFromData();
102 wxMetafileRefData::wxMetafileRefData( const wxString
& filename
)
105 #if wxMAC_USE_CORE_GRAPHICS
106 if ( !filename
.empty() )
108 wxCFRef
<CFMutableStringRef
> cfMutableString(CFStringCreateMutableCopy(NULL
, 0, wxMacCFStringHolder(filename
)));
109 CFStringNormalize(cfMutableString
,kCFStringNormalizationFormD
);
110 wxCFRef
<CFURLRef
> url(CFURLCreateWithFileSystemPath(kCFAllocatorDefault
, cfMutableString
, kCFURLPOSIXPathStyle
, false));
111 m_pdfDoc
.reset(CGPDFDocumentCreateWithURL(url
));
114 wxASSERT_MSG( filename
.empty(), wxT("no file-based metafile support yet") );
120 wxMetafileRefData::wxMetafileRefData( int width
, int height
)
126 #if wxMAC_USE_CORE_GRAPHICS
127 CGRect r
= CGRectMake( 0 , 0 , width
, height
);
129 CFMutableDataRef data
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
131 CGDataConsumerRef dataConsumer
= UMACGDataConsumerCreateWithCFData(data
);
132 m_context
= CGPDFContextCreate( dataConsumer
, (width
!= 0 && height
!= 0) ? &r
: NULL
, NULL
);
133 CGDataConsumerRelease( dataConsumer
);
136 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
137 if ( &CGPDFContextBeginPage
!= NULL
)
138 CGPDFContextBeginPage(m_context
, NULL
);
141 CGContextBeginPage(m_context
, &r
);
143 CGColorSpaceRef genericColorSpace
= wxMacGetGenericRGBColorSpace();
145 CGContextSetFillColorSpace( m_context
, genericColorSpace
);
146 CGContextSetStrokeColorSpace( m_context
, genericColorSpace
);
148 CGContextTranslateCTM( m_context
, 0 , height
) ;
149 CGContextScaleCTM( m_context
, 1 , -1 ) ;
152 Rect r
= { 0, 0, height
, width
};
153 m_metafile
= OpenPicture( &r
) ;
157 wxMetafileRefData::~wxMetafileRefData()
159 #if! wxMAC_USE_CORE_GRAPHICS
162 KillPicture( (PicHandle
)m_metafile
);
168 void wxMetafileRefData::Init()
170 #if wxMAC_USE_CORE_GRAPHICS
179 void wxMetafileRefData::Close()
181 #if wxMAC_USE_CORE_GRAPHICS
182 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
183 if ( &CGPDFContextEndPage
!= NULL
)
184 CGPDFContextEndPage(m_context
);
187 CGContextEndPage(m_context
);
189 CGContextRelease(m_context
);
192 UpdateDocumentFromData();
198 #if wxMAC_USE_CORE_GRAPHICS
199 void wxMetafileRefData::UpdateDocumentFromData()
201 wxCFRef
<CGDataProviderRef
> provider(UMACGDataProviderCreateWithCFData(m_data
));
202 m_pdfDoc
.reset(CGPDFDocumentCreateWithProvider(provider
));
203 if ( m_pdfDoc
!= NULL
)
205 CGPDFPageRef page
= CGPDFDocumentGetPage( m_pdfDoc
, 1 );
206 CGRect rect
= CGPDFPageGetBoxRect ( page
, kCGPDFMediaBox
);
207 m_width
= rect
.size
.width
;
208 m_height
= rect
.size
.height
;
213 wxMetaFile::wxMetaFile(const wxString
& file
)
215 m_refData
= new wxMetafileRefData(file
);
218 wxMetaFile::~wxMetaFile()
222 bool wxMetaFile::IsOk() const
224 #if wxMAC_USE_CORE_GRAPHICS
225 return (M_METAFILEDATA
&& (M_METAFILEDATA
->GetData() != NULL
));
227 return (M_METAFILEDATA
&& (M_METAFILEDATA
->GetHandle() != NULL
));
231 WXHMETAFILE
wxMetaFile::GetHMETAFILE() const
233 #if wxMAC_USE_CORE_GRAPHICS
234 return (WXHMETAFILE
) (CFDataRef
) M_METAFILEDATA
->GetData();
236 return (WXHMETAFILE
) M_METAFILEDATA
->GetHandle();
240 bool wxMetaFile::SetClipboard(int WXUNUSED(width
), int WXUNUSED(height
))
244 #if wxUSE_DRAG_AND_DROP
245 if (m_refData
== NULL
)
248 bool alreadyOpen
= wxTheClipboard
->IsOpened();
251 wxTheClipboard
->Open();
252 wxTheClipboard
->Clear();
255 wxDataObject
*data
= new wxMetafileDataObject( *this );
256 success
= wxTheClipboard
->SetData( data
);
258 wxTheClipboard
->Close();
264 void wxMetafile::SetHMETAFILE(WXHMETAFILE mf
)
268 #if wxMAC_USE_CORE_GRAPHICS
269 m_refData
= new wxMetafileRefData((CFDataRef
)mf
);
271 m_refData
= new wxMetafileRefData((PicHandle
)mf
);
275 void wxMetafile::SetPICT(void* pictHandle
)
279 #if wxMAC_USE_CORE_GRAPHICS
280 Handle picHandle
= (Handle
) pictHandle
;
282 CFDataRef data
= CFDataCreateWithBytesNoCopy( kCFAllocatorDefault
, (const UInt8
*) *picHandle
, GetHandleSize(picHandle
), kCFAllocatorNull
);
283 wxCFRef
<CGDataProviderRef
> provider(UMACGDataProviderCreateWithCFData(data
));
284 QDPictRef pictRef
= QDPictCreateWithProvider(provider
);
285 CGRect rect
= QDPictGetBounds(pictRef
);
286 m_refData
= new wxMetafileRefData( rect
.size
.width
, rect
.size
.height
);
287 QDPictDrawToCGContext( ((wxMetafileRefData
*) m_refData
)->GetContext(), rect
, pictRef
);
289 QDPictRelease( pictRef
);
290 ((wxMetafileRefData
*) m_refData
)->Close();
292 m_refData
= new wxMetafileRefData((PicHandle
)pictHandle
);
296 bool wxMetaFile::Play(wxDC
*dc
)
305 #if wxMAC_USE_CORE_GRAPHICS
306 CGContextRef cg
= (CGContextRef
) dc
->GetGraphicsContext()->GetNativeContext();
307 CGPDFDocumentRef doc
= M_METAFILEDATA
->GetPDFDocument();
308 CGPDFPageRef page
= CGPDFDocumentGetPage( doc
, 1 );
309 wxMacCGContextStateSaver
save(cg
);
310 CGContextDrawPDFPage( cg
, page
);
311 // CGContextTranslateCTM( cg, 0, bounds.size.width );
312 // CGContextScaleCTM( cg, 1, -1 );
314 PicHandle pict
= (PicHandle
)GetHMETAFILE();
315 wxMacPortSetter
helper( dc
);
317 DrawPicture( pict
, wxMacGetPictureBounds( pict
, &picFrame
) );
324 wxSize
wxMetaFile::GetSize() const
326 wxSize dataSize
= wxDefaultSize
;
330 dataSize
.x
= M_METAFILEDATA
->GetWidth();
331 dataSize
.y
= M_METAFILEDATA
->GetHeight();
337 // Metafile device context
339 // New constructor that takes origin and extent. If you use this, don't
340 // give origin/extent arguments to wxMakeMetaFilePlaceable.
342 wxMetaFileDC::wxMetaFileDC(
343 const wxString
& filename
,
344 int width
, int height
,
345 const wxString
& WXUNUSED(description
) )
347 wxASSERT_MSG( width
!= 0 || height
!= 0, wxT("no arbitration of metafile size supported") );
348 wxASSERT_MSG( filename
.empty(), wxT("no file based metafile support yet"));
350 m_metaFile
= new wxMetaFile( filename
);
351 wxMetafileRefData
* metafiledata
= new wxMetafileRefData(width
, height
);
353 m_metaFile
->SetRefData( metafiledata
);
354 #if wxMAC_USE_CORE_GRAPHICS
355 SetGraphicsContext( wxGraphicsContext::CreateFromNative(metafiledata
->GetContext()));
356 m_ok
= (m_graphicContext
!= NULL
) ;
358 Rect r
= { 0, 0, height
, width
};
359 RectRgn( (RgnHandle
)m_macBoundaryClipRgn
, &r
);
360 CopyRgn( (RgnHandle
)m_macBoundaryClipRgn
, (RgnHandle
)m_macCurrentClipRgn
);
361 ::GetPort( (GrafPtr
*)&m_macPort
);
365 SetMapMode( wxMM_TEXT
);
368 wxMetaFileDC::~wxMetaFileDC()
372 void wxMetaFileDC::DoGetSize(int *width
, int *height
) const
374 wxCHECK_RET( m_metaFile
, wxT("GetSize() doesn't work without a metafile") );
376 wxSize sz
= m_metaFile
->GetSize();
383 wxMetaFile
*wxMetaFileDC::Close()
385 #if wxMAC_USE_CORE_GRAPHICS
386 delete m_graphicContext
;
387 m_graphicContext
= NULL
;
391 M_METAFILEREFDATA(*m_metaFile
)->Close();
397 size_t wxMetafileDataObject::GetDataSize() const
399 #if wxMAC_USE_CORE_GRAPHICS
401 wxMetafileRefData
* refData
= M_METAFILEREFDATA(m_metafile
);
403 length
= refData
->GetData().GetLength();
406 return GetHandleSize( (Handle
) (*((wxMetafile
*)&m_metafile
)).GetHMETAFILE() );
410 bool wxMetafileDataObject::GetDataHere(void *buf
) const
413 #if wxMAC_USE_CORE_GRAPHICS
414 wxMetafileRefData
* refData
= M_METAFILEREFDATA(m_metafile
);
417 CFIndex length
= refData
->GetData().GetLength();
421 refData
->GetData().GetBytes(CFRangeMake(0,length
), (UInt8
*) buf
);
425 Handle pictH
= (Handle
)(*((wxMetafile
*)&m_metafile
)).GetHMETAFILE();
426 result
= (pictH
!= NULL
);
429 memcpy( buf
, *pictH
, GetHandleSize( pictH
) );
435 bool wxMetafileDataObject::SetData(size_t len
, const void *buf
)
437 #if wxMAC_USE_CORE_GRAPHICS
438 wxMetafileRefData
* metafiledata
= new wxMetafileRefData(wxCFRefFromGet(wxCFDataRef((UInt8
*)buf
, len
).get()));
440 m_metafile
.SetRefData( metafiledata
);
442 Handle handle
= NewHandle( len
);
443 SetHandleSize( handle
, len
);
444 memcpy( *handle
, buf
, len
);
445 m_metafile
.SetHMETAFILE( (WXHMETAFILE
) handle
);