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