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 // creates a metafile from memory, assumes ownership
42 wxMetafileRefData(CFDataRef data
);
43 // prepares a recording metafile
44 wxMetafileRefData( int width
, int height
);
45 // prepares a metafile to be read from a file (if filename is not empty)
46 wxMetafileRefData( const wxString
& filename
);
47 virtual ~wxMetafileRefData();
51 int GetWidth() const { return m_width
; }
52 int GetHeight() const { return m_height
; }
54 CGPDFDocumentRef
GetPDFDocument() const { return m_pdfDoc
; }
55 void UpdateDocumentFromData() ;
57 const wxCFDataRef
& GetData() const { return m_data
; }
58 CGContextRef
GetContext() const { return m_context
; }
64 wxCFRef
<CGPDFDocumentRef
> m_pdfDoc
;
65 CGContextRef m_context
;
71 wxMetafileRefData::wxMetafileRefData(CFDataRef data
) :
75 UpdateDocumentFromData();
78 wxMetafileRefData::wxMetafileRefData( const wxString
& filename
)
82 if ( !filename
.empty() )
84 wxCFRef
<CFMutableStringRef
> cfMutableString(CFStringCreateMutableCopy(NULL
, 0, wxMacCFStringHolder(filename
)));
85 CFStringNormalize(cfMutableString
,kCFStringNormalizationFormD
);
86 wxCFRef
<CFURLRef
> url(CFURLCreateWithFileSystemPath(kCFAllocatorDefault
, cfMutableString
, kCFURLPOSIXPathStyle
, false));
87 m_pdfDoc
.reset(CGPDFDocumentCreateWithURL(url
));
92 wxMetafileRefData::wxMetafileRefData( int width
, int height
)
99 CGRect r
= CGRectMake( 0 , 0 , width
, height
);
101 CFMutableDataRef data
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
103 CGDataConsumerRef dataConsumer
= wxMacCGDataConsumerCreateWithCFData(data
);
104 m_context
= CGPDFContextCreate( dataConsumer
, (width
!= 0 && height
!= 0) ? &r
: NULL
, NULL
);
105 CGDataConsumerRelease( dataConsumer
);
108 CGPDFContextBeginPage(m_context
, NULL
);
110 CGColorSpaceRef genericColorSpace
= wxMacGetGenericRGBColorSpace();
112 CGContextSetFillColorSpace( m_context
, genericColorSpace
);
113 CGContextSetStrokeColorSpace( m_context
, genericColorSpace
);
115 CGContextTranslateCTM( m_context
, 0 , height
) ;
116 CGContextScaleCTM( m_context
, 1 , -1 ) ;
120 wxMetafileRefData::~wxMetafileRefData()
124 void wxMetafileRefData::Init()
131 void wxMetafileRefData::Close()
133 CGPDFContextEndPage(m_context
);
135 CGContextRelease(m_context
);
138 UpdateDocumentFromData();
141 void wxMetafileRefData::UpdateDocumentFromData()
143 wxCFRef
<CGDataProviderRef
> provider(wxMacCGDataProviderCreateWithCFData(m_data
));
144 m_pdfDoc
.reset(CGPDFDocumentCreateWithProvider(provider
));
145 if ( m_pdfDoc
!= NULL
)
147 CGPDFPageRef page
= CGPDFDocumentGetPage( m_pdfDoc
, 1 );
148 CGRect rect
= CGPDFPageGetBoxRect ( page
, kCGPDFMediaBox
);
149 m_width
= wx_static_cast(int, rect
.size
.width
);
150 m_height
= wx_static_cast(int, rect
.size
.height
);
154 wxMetaFile::wxMetaFile(const wxString
& file
)
156 m_refData
= new wxMetafileRefData(file
);
159 wxMetaFile::~wxMetaFile()
163 bool wxMetaFile::IsOk() const
165 return (M_METAFILEDATA
&& (M_METAFILEDATA
->GetData() != NULL
));
168 WXHMETAFILE
wxMetaFile::GetHMETAFILE() const
170 return (WXHMETAFILE
) (CFDataRef
) M_METAFILEDATA
->GetData();
173 bool wxMetaFile::SetClipboard(int WXUNUSED(width
), int WXUNUSED(height
))
177 #if wxUSE_DRAG_AND_DROP
178 if (m_refData
== NULL
)
181 bool alreadyOpen
= wxTheClipboard
->IsOpened();
184 wxTheClipboard
->Open();
185 wxTheClipboard
->Clear();
188 wxDataObject
*data
= new wxMetafileDataObject( *this );
189 success
= wxTheClipboard
->SetData( data
);
191 wxTheClipboard
->Close();
197 void wxMetafile::SetHMETAFILE(WXHMETAFILE mf
)
201 m_refData
= new wxMetafileRefData((CFDataRef
)mf
);
205 void wxMetafile::SetPICT(void* pictHandle
)
209 Handle picHandle
= (Handle
) pictHandle
;
211 CFDataRef data
= CFDataCreateWithBytesNoCopy( kCFAllocatorDefault
, (const UInt8
*) *picHandle
, GetHandleSize(picHandle
), kCFAllocatorNull
);
212 wxCFRef
<CGDataProviderRef
> provider(wxMacCGDataProviderCreateWithCFData(data
));
213 QDPictRef pictRef
= QDPictCreateWithProvider(provider
);
214 CGRect rect
= QDPictGetBounds(pictRef
);
215 m_refData
= new wxMetafileRefData(wx_static_cast(int, rect
.size
.width
),
216 wx_static_cast(int, rect
.size
.height
));
217 QDPictDrawToCGContext( ((wxMetafileRefData
*) m_refData
)->GetContext(), rect
, pictRef
);
219 QDPictRelease( pictRef
);
220 ((wxMetafileRefData
*) m_refData
)->Close();
224 bool wxMetaFile::Play(wxDC
*dc
)
233 CGContextRef cg
= (CGContextRef
) dc
->GetGraphicsContext()->GetNativeContext();
234 CGPDFDocumentRef doc
= M_METAFILEDATA
->GetPDFDocument();
235 CGPDFPageRef page
= CGPDFDocumentGetPage( doc
, 1 );
236 wxMacCGContextStateSaver
save(cg
);
237 CGContextDrawPDFPage( cg
, page
);
238 // CGContextTranslateCTM( cg, 0, bounds.size.width );
239 // CGContextScaleCTM( cg, 1, -1 );
245 wxSize
wxMetaFile::GetSize() const
247 wxSize dataSize
= wxDefaultSize
;
251 dataSize
.x
= M_METAFILEDATA
->GetWidth();
252 dataSize
.y
= M_METAFILEDATA
->GetHeight();
258 // Metafile device context
260 // New constructor that takes origin and extent. If you use this, don't
261 // give origin/extent arguments to wxMakeMetaFilePlaceable.
263 wxMetaFileDC::wxMetaFileDC(
264 const wxString
& filename
,
265 int width
, int height
,
266 const wxString
& WXUNUSED(description
) )
268 wxASSERT_MSG( width
!= 0 || height
!= 0, wxT("no arbitration of metafile size supported") );
269 wxASSERT_MSG( filename
.empty(), wxT("no file based metafile support yet"));
271 m_metaFile
= new wxMetaFile( filename
);
272 wxMetafileRefData
* metafiledata
= new wxMetafileRefData(width
, height
);
274 m_metaFile
->SetRefData( metafiledata
);
276 SetGraphicsContext( wxGraphicsContext::CreateFromNative(metafiledata
->GetContext()));
277 m_ok
= (m_graphicContext
!= NULL
) ;
279 SetMapMode( wxMM_TEXT
);
282 wxMetaFileDC::~wxMetaFileDC()
286 void wxMetaFileDC::DoGetSize(int *width
, int *height
) const
288 wxCHECK_RET( m_metaFile
, wxT("GetSize() doesn't work without a metafile") );
290 wxSize sz
= m_metaFile
->GetSize();
297 wxMetaFile
*wxMetaFileDC::Close()
299 delete m_graphicContext
;
300 m_graphicContext
= NULL
;
303 M_METAFILEREFDATA(*m_metaFile
)->Close();
309 size_t wxMetafileDataObject::GetDataSize() const
312 wxMetafileRefData
* refData
= M_METAFILEREFDATA(m_metafile
);
314 length
= refData
->GetData().GetLength();
318 bool wxMetafileDataObject::GetDataHere(void *buf
) const
322 wxMetafileRefData
* refData
= M_METAFILEREFDATA(m_metafile
);
325 CFIndex length
= refData
->GetData().GetLength();
329 refData
->GetData().GetBytes(CFRangeMake(0,length
), (UInt8
*) buf
);
335 bool wxMetafileDataObject::SetData(size_t len
, const void *buf
)
337 wxMetafileRefData
* metafiledata
= new wxMetafileRefData(wxCFRefFromGet(wxCFDataRef((UInt8
*)buf
, len
).get()));
339 m_metafile
.SetRefData( metafiledata
);