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