]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/metafile.cpp
minimize overlay area to avoid eg scrolling artifacts when using a caret
[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/private.h"
28 #include "wx/graphics.h"
29
30 #include <stdio.h>
31 #include <string.h>
32
33 IMPLEMENT_DYNAMIC_CLASS(wxMetafile, wxObject)
34 IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC, wxDC)
35
36 class wxMetafileRefData: public wxGDIRefData
37 {
38 friend class WXDLLEXPORT wxMetafile;
39
40 public:
41 wxMetafileRefData();
42 virtual ~wxMetafileRefData();
43
44 private:
45 PicHandle m_metafile;
46
47 #if wxMAC_USE_CORE_GRAPHICS
48 QDPictRef m_qdPictRef;
49 #endif
50 };
51
52 wxMetafileRefData::wxMetafileRefData()
53 {
54 m_metafile = NULL;
55
56 #if wxMAC_USE_CORE_GRAPHICS
57 m_qdPictRef = NULL;
58 #endif
59 }
60
61 wxMetafileRefData::~wxMetafileRefData()
62 {
63 if (m_metafile)
64 {
65 #ifndef __LP64__
66 KillPicture( (PicHandle)m_metafile );
67 m_metafile = NULL;
68
69 #if wxMAC_USE_CORE_GRAPHICS
70 QDPictRelease( m_qdPictRef );
71 m_qdPictRef = NULL;
72 #endif
73 #endif
74 }
75 }
76
77 wxMetaFile::wxMetaFile(const wxString& file)
78 {
79 m_refData = new wxMetafileRefData;
80
81 M_METAFILEDATA->m_metafile = NULL;
82 wxASSERT_MSG( file.empty(), wxT("no file-based metafile support yet") );
83
84 #if 0
85 if (!file.IsNull() && (file.Cmp("") == 0))
86 M_METAFILEDATA->m_metafile = (WXHANDLE) GetMetaFile( file );
87 #endif
88 }
89
90 wxMetaFile::~wxMetaFile()
91 {
92 }
93
94 bool wxMetaFile::IsOk() const
95 {
96 return (M_METAFILEDATA && (M_METAFILEDATA->m_metafile != NULL));
97 }
98
99 WXHMETAFILE wxMetaFile::GetHMETAFILE() const
100 {
101 return (WXHMETAFILE) M_METAFILEDATA->m_metafile;
102 }
103
104 bool wxMetaFile::SetClipboard(int width, int height)
105 {
106 bool success = true;
107
108 #if wxUSE_DRAG_AND_DROP
109 // TODO: to finish this port, we need the data object first
110 if (m_refData == NULL)
111 return false;
112
113 bool alreadyOpen = wxTheClipboard->IsOpened();
114 if (!alreadyOpen)
115 {
116 wxTheClipboard->Open();
117 wxTheClipboard->Clear();
118 }
119
120 wxDataObject *data = new wxMetafileDataObject( *this );
121 success = wxTheClipboard->SetData( data );
122 if (!alreadyOpen)
123 wxTheClipboard->Close();
124 #endif
125
126 return success;
127 }
128
129 void wxMetafile::SetHMETAFILE(WXHMETAFILE mf)
130 {
131 UnRef();
132
133 m_refData = new wxMetafileRefData;
134
135 M_METAFILEDATA->m_metafile = (PicHandle)mf;
136
137 #if wxMAC_USE_CORE_GRAPHICS
138 size_t sz = GetHandleSize( (Handle) M_METAFILEDATA->m_metafile );
139 wxMemoryBuffer* membuf = new wxMemoryBuffer( sz );
140 void *data = membuf->GetWriteBuf( sz );
141
142 memcpy( data, *M_METAFILEDATA->m_metafile, sz );
143 membuf->UngetWriteBuf( sz );
144 CGDataProviderRef provider = CGDataProviderCreateWithData(
145 membuf, data, sz, wxMacMemoryBufferReleaseProc );
146 M_METAFILEDATA->m_qdPictRef = NULL;
147
148 #ifndef __LP64__
149 if (provider != NULL)
150 {
151 M_METAFILEDATA->m_qdPictRef = QDPictCreateWithProvider( provider );
152 CGDataProviderRelease( provider );
153 }
154 #endif
155 #endif
156 }
157
158 bool wxMetaFile::Play(wxDC *dc)
159 {
160 if (!m_refData)
161 return false;
162
163 if (!dc->Ok())
164 return false;
165
166 {
167 #if wxMAC_USE_CORE_GRAPHICS
168 #ifndef __LP64__
169 QDPictRef cgPictRef = M_METAFILEDATA->m_qdPictRef;
170 CGContextRef cg = (CGContextRef) dc->GetGraphicsContext()->GetNativeContext();
171 CGRect bounds = QDPictGetBounds( cgPictRef );
172
173 CGContextSaveGState( cg );
174 CGContextTranslateCTM( cg, 0, bounds.size.width );
175 CGContextScaleCTM( cg, 1, -1 );
176 QDPictDrawToCGContext( cg, bounds, cgPictRef );
177 CGContextRestoreGState( cg );
178 #endif
179 #else
180 PicHandle pict = (PicHandle)GetHMETAFILE();
181 wxMacPortSetter helper( dc );
182 Rect picFrame;
183 DrawPicture( pict, wxMacGetPictureBounds( pict, &picFrame ) );
184 #endif
185 }
186
187 return true;
188 }
189
190 wxSize wxMetaFile::GetSize() const
191 {
192 wxSize dataSize = wxDefaultSize;
193
194 if (Ok())
195 {
196 #ifndef __LP64__
197 PicHandle pict = (PicHandle)GetHMETAFILE();
198 Rect r;
199 wxMacGetPictureBounds( pict, &r );
200 dataSize.x = r.right - r.left;
201 dataSize.y = r.bottom - r.top;
202 #endif
203 }
204
205 return dataSize;
206 }
207
208 // Metafile device context
209
210 // New constructor that takes origin and extent. If you use this, don't
211 // give origin/extent arguments to wxMakeMetaFilePlaceable.
212
213 wxMetaFileDC::wxMetaFileDC(
214 const wxString& filename,
215 int width, int height,
216 const wxString& WXUNUSED(description) )
217 {
218 wxASSERT_MSG( width <= 0 || height <= 0, wxT("no arbitration of metafile size supported") );
219 wxASSERT_MSG( filename.empty(), wxT("no file based metafile support yet"));
220
221 m_metaFile = new wxMetaFile( filename );
222
223 #if wxMAC_USE_CORE_GRAPHICS
224 #else
225 Rect r = { 0, 0, height, width };
226
227 RectRgn( (RgnHandle)m_macBoundaryClipRgn, &r );
228 CopyRgn( (RgnHandle)m_macBoundaryClipRgn, (RgnHandle)m_macCurrentClipRgn );
229
230 m_metaFile->SetHMETAFILE( (WXHMETAFILE)OpenPicture( &r ) );
231 ::GetPort( (GrafPtr*)&m_macPort );
232
233 m_ok = true;
234 #endif
235
236 SetMapMode( wxMM_TEXT );
237 }
238
239 wxMetaFileDC::~wxMetaFileDC()
240 {
241 }
242
243 void wxMetaFileDC::DoGetSize(int *width, int *height) const
244 {
245 wxCHECK_RET( m_metaFile, wxT("GetSize() doesn't work without a metafile") );
246
247 wxSize sz = m_metaFile->GetSize();
248 if (width)
249 (*width) = sz.x;
250 if (height)
251 (*height) = sz.y;
252 }
253
254 wxMetaFile *wxMetaFileDC::Close()
255 {
256 #ifndef __LP64__
257 ClosePicture();
258 #endif
259 return m_metaFile;
260 }
261
262 #if wxUSE_DATAOBJ
263 size_t wxMetafileDataObject::GetDataSize() const
264 {
265 return GetHandleSize( (Handle) (*((wxMetafile*)&m_metafile)).GetHMETAFILE() );
266 }
267
268 bool wxMetafileDataObject::GetDataHere(void *buf) const
269 {
270 Handle pictH = (Handle)(*((wxMetafile*)&m_metafile)).GetHMETAFILE();
271 bool result = (pictH != NULL);
272
273 if (result)
274 memcpy( buf, *pictH, GetHandleSize( pictH ) );
275
276 return result;
277 }
278
279 bool wxMetafileDataObject::SetData(size_t len, const void *buf)
280 {
281 Handle handle = NewHandle( len );
282 SetHandleSize( handle, len );
283 memcpy( *handle, buf, len );
284 m_metafile.SetHMETAFILE( (WXHMETAFILE) handle );
285
286 return true;
287 }
288 #endif
289
290 #endif