]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/metafile.cpp
making ref counting behavior consistent, activating QD variante for polygon region...
[wxWidgets.git] / src / mac / carbon / metafile.cpp
CommitLineData
e9576ca5 1/////////////////////////////////////////////////////////////////////////////
e542ecc6 2// Name: src/mac/carbon/metafile.cpp
e9576ca5 3// Purpose: wxMetaFile, wxMetaFileDC etc. These classes are optional.
a31a5f85 4// Author: Stefan Csomor
e9576ca5
SC
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
a31a5f85 8// Copyright: (c) Stefan Csomor
65571936 9// Licence: wxWindows licence
e9576ca5 10/////////////////////////////////////////////////////////////////////////////
e542ecc6
DS
11//
12// Currently, the only purpose for making a metafile
13// is to put it on the clipboard.
e9576ca5 14
519cb848 15
e542ecc6 16#include "wx/wxprec.h"
519cb848 17
519cb848
SC
18#if wxUSE_METAFILE
19
20#ifndef WX_PRECOMP
274b7a40
DS
21 #include "wx/utils.h"
22 #include "wx/app.h"
519cb848
SC
23#endif
24
25#include "wx/metafile.h"
e9576ca5 26#include "wx/clipbrd.h"
6239ee05 27#include "wx/mac/uma.h"
8acd14d1 28#include "wx/graphics.h"
888dde65 29#include "wx/mac/carbon/metafile.h"
76a5e5d2 30
519cb848
SC
31#include <stdio.h>
32#include <string.h>
33
519cb848
SC
34IMPLEMENT_DYNAMIC_CLASS(wxMetafile, wxObject)
35IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC, wxDC)
888dde65 36IMPLEMENT_ABSTRACT_CLASS(wxMetafileDCImpl, wxGCDCImpl)
e9576ca5 37
6239ee05
SC
38#define M_METAFILEREFDATA( a ) ((wxMetafileRefData*)(a).GetRefData())
39
71cc158e
SC
40class wxMetafileRefData: public wxGDIRefData
41{
71cc158e 42public:
6239ee05 43 // creates a metafile from memory, assumes ownership
31c1cbc7 44 wxMetafileRefData(CFDataRef data);
6239ee05 45 // prepares a recording metafile
31c1cbc7 46 wxMetafileRefData( int width, int height);
6239ee05 47 // prepares a metafile to be read from a file (if filename is not empty)
31c1cbc7 48 wxMetafileRefData( const wxString& filename);
d3c7fc99 49 virtual ~wxMetafileRefData();
71cc158e 50
6239ee05
SC
51 void Init();
52
53 int GetWidth() const { return m_width; }
54 int GetHeight() const { return m_height; }
274b7a40 55
6239ee05
SC
56 CGPDFDocumentRef GetPDFDocument() const { return m_pdfDoc; }
57 void UpdateDocumentFromData() ;
58
59 const wxCFDataRef& GetData() const { return m_data; }
60 CGContextRef GetContext() const { return m_context; }
315e9e5a 61
6239ee05
SC
62 // ends the recording
63 void Close();
64private:
6239ee05
SC
65 wxCFDataRef m_data;
66 wxCFRef<CGPDFDocumentRef> m_pdfDoc;
67 CGContextRef m_context;
315e9e5a 68
6239ee05
SC
69 int m_width ;
70 int m_height ;
71cc158e
SC
71};
72
6239ee05
SC
73wxMetafileRefData::wxMetafileRefData(CFDataRef data) :
74 m_data(data)
75{
76 Init();
77 UpdateDocumentFromData();
78}
6239ee05
SC
79
80wxMetafileRefData::wxMetafileRefData( const wxString& filename )
519cb848 81{
6239ee05 82 Init();
315e9e5a 83
6239ee05
SC
84 if ( !filename.empty() )
85 {
dbe4a80c 86 wxCFRef<CFMutableStringRef> cfMutableString(CFStringCreateMutableCopy(NULL, 0, wxCFStringRef(filename)));
6239ee05
SC
87 CFStringNormalize(cfMutableString,kCFStringNormalizationFormD);
88 wxCFRef<CFURLRef> url(CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfMutableString , kCFURLPOSIXPathStyle, false));
89 m_pdfDoc.reset(CGPDFDocumentCreateWithURL(url));
90 }
6239ee05
SC
91}
92
93
94wxMetafileRefData::wxMetafileRefData( int width, int height)
95{
96 Init();
274b7a40 97
6239ee05
SC
98 m_width = width;
99 m_height = height;
315e9e5a 100
6239ee05
SC
101 CGRect r = CGRectMake( 0 , 0 , width , height );
102
103 CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);
104 m_data.reset(data);
fb728ebb 105 CGDataConsumerRef dataConsumer = wxMacCGDataConsumerCreateWithCFData(data);
6239ee05
SC
106 m_context = CGPDFContextCreate( dataConsumer, (width != 0 && height != 0) ? &r : NULL , NULL );
107 CGDataConsumerRelease( dataConsumer );
108 if ( m_context )
109 {
315e9e5a 110 CGPDFContextBeginPage(m_context, NULL);
6239ee05
SC
111
112 CGColorSpaceRef genericColorSpace = wxMacGetGenericRGBColorSpace();
113
114 CGContextSetFillColorSpace( m_context, genericColorSpace );
115 CGContextSetStrokeColorSpace( m_context, genericColorSpace );
116
117 CGContextTranslateCTM( m_context , 0 , height ) ;
118 CGContextScaleCTM( m_context , 1 , -1 ) ;
119 }
519cb848
SC
120}
121
274b7a40 122wxMetafileRefData::~wxMetafileRefData()
519cb848 123{
6239ee05 124}
274b7a40 125
6239ee05
SC
126void wxMetafileRefData::Init()
127{
6239ee05 128 m_context = NULL;
6239ee05
SC
129 m_width = -1;
130 m_height = -1;
519cb848
SC
131}
132
6239ee05 133void wxMetafileRefData::Close()
e9576ca5 134{
315e9e5a 135 CGPDFContextEndPage(m_context);
519cb848 136
6239ee05
SC
137 CGContextRelease(m_context);
138 m_context = NULL;
31c1cbc7 139
6239ee05 140 UpdateDocumentFromData();
6239ee05 141}
274b7a40 142
31c1cbc7 143void wxMetafileRefData::UpdateDocumentFromData()
6239ee05 144{
fb728ebb 145 wxCFRef<CGDataProviderRef> provider(wxMacCGDataProviderCreateWithCFData(m_data));
6239ee05
SC
146 m_pdfDoc.reset(CGPDFDocumentCreateWithProvider(provider));
147 if ( m_pdfDoc != NULL )
148 {
149 CGPDFPageRef page = CGPDFDocumentGetPage( m_pdfDoc, 1 );
150 CGRect rect = CGPDFPageGetBoxRect ( page, kCGPDFMediaBox);
31c1cbc7
VZ
151 m_width = wx_static_cast(int, rect.size.width);
152 m_height = wx_static_cast(int, rect.size.height);
6239ee05
SC
153 }
154}
6239ee05
SC
155
156wxMetaFile::wxMetaFile(const wxString& file)
157{
158 m_refData = new wxMetafileRefData(file);
e9576ca5
SC
159}
160
161wxMetaFile::~wxMetaFile()
162{
e9576ca5
SC
163}
164
b7cacb43 165bool wxMetaFile::IsOk() const
902725ee 166{
6239ee05 167 return (M_METAFILEDATA && (M_METAFILEDATA->GetData() != NULL));
71cc158e
SC
168}
169
902725ee
WS
170WXHMETAFILE wxMetaFile::GetHMETAFILE() const
171{
6239ee05 172 return (WXHMETAFILE) (CFDataRef) M_METAFILEDATA->GetData();
71cc158e
SC
173}
174
89954433 175bool wxMetaFile::SetClipboard(int WXUNUSED(width), int WXUNUSED(height))
e9576ca5 176{
902725ee
WS
177 bool success = true;
178
f0822896 179#if wxUSE_DRAG_AND_DROP
e542ecc6 180 if (m_refData == NULL)
902725ee
WS
181 return false;
182
274b7a40 183 bool alreadyOpen = wxTheClipboard->IsOpened();
e9576ca5
SC
184 if (!alreadyOpen)
185 {
f0822896 186 wxTheClipboard->Open();
a07c1212 187 wxTheClipboard->Clear();
e9576ca5 188 }
274b7a40
DS
189
190 wxDataObject *data = new wxMetafileDataObject( *this );
191 success = wxTheClipboard->SetData( data );
902725ee 192 if (!alreadyOpen)
e40298d5 193 wxTheClipboard->Close();
f0822896 194#endif
902725ee
WS
195
196 return success;
e9576ca5
SC
197}
198
76a5e5d2 199void wxMetafile::SetHMETAFILE(WXHMETAFILE mf)
2f1ae414 200{
274b7a40 201 UnRef();
902725ee 202
6239ee05 203 m_refData = new wxMetafileRefData((CFDataRef)mf);
6239ee05 204}
2f1ae414 205
276ee533 206#ifndef __LP64__
6239ee05
SC
207void wxMetafile::SetPICT(void* pictHandle)
208{
209 UnRef();
274b7a40 210
6239ee05
SC
211 Handle picHandle = (Handle) pictHandle;
212 HLock(picHandle);
213 CFDataRef data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault, (const UInt8*) *picHandle, GetHandleSize(picHandle), kCFAllocatorNull);
fb728ebb 214 wxCFRef<CGDataProviderRef> provider(wxMacCGDataProviderCreateWithCFData(data));
6239ee05
SC
215 QDPictRef pictRef = QDPictCreateWithProvider(provider);
216 CGRect rect = QDPictGetBounds(pictRef);
31c1cbc7
VZ
217 m_refData = new wxMetafileRefData(wx_static_cast(int, rect.size.width),
218 wx_static_cast(int, rect.size.height));
6239ee05
SC
219 QDPictDrawToCGContext( ((wxMetafileRefData*) m_refData)->GetContext(), rect, pictRef );
220 CFRelease( data );
221 QDPictRelease( pictRef );
222 ((wxMetafileRefData*) m_refData)->Close();
2f1ae414 223}
276ee533 224#endif
2f1ae414 225
e9576ca5
SC
226bool wxMetaFile::Play(wxDC *dc)
227{
e40298d5 228 if (!m_refData)
902725ee
WS
229 return false;
230
888dde65 231 if (!dc->IsOk())
902725ee
WS
232 return false;
233
e40298d5 234 {
888dde65
RR
235 wxDCImpl *impl = dc->GetImpl();
236 wxGCDCImpl *gc_impl = wxDynamicCast(impl, wxGCDCImpl);
237 if (gc_impl)
238 {
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 );
244 }
6239ee05
SC
245// CGContextTranslateCTM( cg, 0, bounds.size.width );
246// CGContextScaleCTM( cg, 1, -1 );
e40298d5 247 }
274b7a40 248
902725ee 249 return true;
e9576ca5
SC
250}
251
48de597b
SC
252wxSize wxMetaFile::GetSize() const
253{
e542ecc6 254 wxSize dataSize = wxDefaultSize;
274b7a40 255
e542ecc6 256 if (Ok())
48de597b 257 {
6239ee05
SC
258 dataSize.x = M_METAFILEDATA->GetWidth();
259 dataSize.y = M_METAFILEDATA->GetHeight();
48de597b
SC
260 }
261
e542ecc6 262 return dataSize;
48de597b
SC
263}
264
274b7a40 265// Metafile device context
e9576ca5 266
e9576ca5
SC
267// New constructor that takes origin and extent. If you use this, don't
268// give origin/extent arguments to wxMakeMetaFilePlaceable.
519cb848 269
888dde65
RR
270wxMetafileDCImpl::wxMetafileDCImpl(
271 wxDC *owner,
e542ecc6
DS
272 const wxString& filename,
273 int width, int height,
888dde65
RR
274 const wxString& WXUNUSED(description) ) :
275 wxGCDCImpl( owner )
e9576ca5 276{
c97c0054 277 wxASSERT_MSG( width != 0 || height != 0, wxT("no arbitration of metafile size supported") );
e542ecc6 278 wxASSERT_MSG( filename.empty(), wxT("no file based metafile support yet"));
274b7a40
DS
279
280 m_metaFile = new wxMetaFile( filename );
6239ee05
SC
281 wxMetafileRefData* metafiledata = new wxMetafileRefData(width, height);
282 m_metaFile->UnRef();
283 m_metaFile->SetRefData( metafiledata );
315e9e5a 284
6239ee05
SC
285 SetGraphicsContext( wxGraphicsContext::CreateFromNative(metafiledata->GetContext()));
286 m_ok = (m_graphicContext != NULL) ;
274b7a40
DS
287
288 SetMapMode( wxMM_TEXT );
e9576ca5
SC
289}
290
888dde65 291wxMetafileDCImpl::~wxMetafileDCImpl()
e9576ca5 292{
e9576ca5
SC
293}
294
888dde65 295void wxMetafileDCImpl::DoGetSize(int *width, int *height) const
48de597b 296{
e542ecc6 297 wxCHECK_RET( m_metaFile, wxT("GetSize() doesn't work without a metafile") );
48de597b 298
e542ecc6 299 wxSize sz = m_metaFile->GetSize();
274b7a40
DS
300 if (width)
301 (*width) = sz.x;
302 if (height)
303 (*height) = sz.y;
48de597b
SC
304}
305
888dde65 306wxMetaFile *wxMetafileDCImpl::Close()
e9576ca5 307{
6239ee05
SC
308 delete m_graphicContext;
309 m_graphicContext = NULL;
310 m_ok = false;
6239ee05
SC
311
312 M_METAFILEREFDATA(*m_metaFile)->Close();
313
e40298d5 314 return m_metaFile;
e9576ca5
SC
315}
316
a07c1212
SC
317#if wxUSE_DATAOBJ
318size_t wxMetafileDataObject::GetDataSize() const
319{
6239ee05
SC
320 CFIndex length = 0;
321 wxMetafileRefData* refData = M_METAFILEREFDATA(m_metafile);
322 if ( refData )
323 length = refData->GetData().GetLength();
324 return length;
a07c1212
SC
325}
326
327bool wxMetafileDataObject::GetDataHere(void *buf) const
328{
6239ee05 329 bool result = false;
315e9e5a 330
6239ee05
SC
331 wxMetafileRefData* refData = M_METAFILEREFDATA(m_metafile);
332 if ( refData )
31c1cbc7 333 {
6239ee05
SC
334 CFIndex length = refData->GetData().GetLength();
335 if ( length > 0 )
336 {
337 result = true ;
338 refData->GetData().GetBytes(CFRangeMake(0,length), (UInt8 *) buf);
339 }
31c1cbc7 340 }
e542ecc6 341 return result;
a07c1212
SC
342}
343
344bool wxMetafileDataObject::SetData(size_t len, const void *buf)
345{
6239ee05
SC
346 wxMetafileRefData* metafiledata = new wxMetafileRefData(wxCFRefFromGet(wxCFDataRef((UInt8*)buf, len).get()));
347 m_metafile.UnRef();
348 m_metafile.SetRefData( metafiledata );
e542ecc6 349 return true;
a07c1212
SC
350}
351#endif
352
e9576ca5 353#endif