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