]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/graphics.cpp
Query value from the model column given by col->GetModelColumn()
[wxWidgets.git] / src / mac / carbon / graphics.cpp
CommitLineData
50581042
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/mac/carbon/dccg.cpp
3// Purpose: wxDC class
4// Author: Stefan Csomor
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
8// Copyright: (c) Stefan Csomor
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#include "wx/wxprec.h"
13
83b96a06 14#include "wx/graphics.h"
a6ab887b 15#include "wx/private/graphics.h"
83b96a06 16
50581042 17#ifndef WX_PRECOMP
cc5de8fe 18 #include "wx/dcclient.h"
d9485f89 19 #include "wx/dcmemory.h"
50581042 20 #include "wx/log.h"
50581042 21 #include "wx/region.h"
6239ee05 22 #include "wx/image.h"
fb9cc37f 23 #include "wx/icon.h"
50581042
SC
24#endif
25
87fe0f75 26
50581042
SC
27#ifdef __MSL__
28 #if __MSL__ >= 0x6000
29 #include "math.h"
30 // in case our functions were defined outside std, we make it known all the same
31 namespace std { }
32 using namespace std;
33 #endif
34#endif
35
5252d9e4
SC
36#ifdef __WXMAC__
37 #include "wx/mac/uma.h"
87fe0f75 38 #include "wx/mac/dcprint.h"
5252d9e4
SC
39#else
40 #include "CoreServices/CoreServices.h"
41 #include "ApplicationServices/ApplicationServices.h"
42 #include "wx/mac/corefoundation/cfstring.h"
43 #include "wx/cocoa/dcclient.h"
44#endif
45
46#ifdef __WXCOCOA__
47
48CGColorSpaceRef wxMacGetGenericRGBColorSpace()
49{
50 static wxCFRef<CGColorSpaceRef> genericRGBColorSpace;
51
52 if (genericRGBColorSpace == NULL)
53 {
54 genericRGBColorSpace.reset( CGColorSpaceCreateWithName( kCGColorSpaceGenericRGB ) );
55 }
56
57 return genericRGBColorSpace;
58}
59
60int UMAGetSystemVersion()
61{
62 return 0x1050;
63}
64
65
66#define wxMAC_USE_CORE_TEXT 1
67
68#endif
50581042 69
eec960fa
SC
70//-----------------------------------------------------------------------------
71// constants
72//-----------------------------------------------------------------------------
73
74#if !defined( __DARWIN__ ) || defined(__MWERKS__)
75#ifndef M_PI
76const double M_PI = 3.14159265358979;
77#endif
78#endif
79
80static const double RAD2DEG = 180.0 / M_PI;
81
50581042 82//
b7b40adb 83// Pen, Brushes and Fonts
50581042
SC
84//
85
b7b40adb
SC
86#pragma mark -
87#pragma mark wxMacCoreGraphicsPattern, ImagePattern, HatchPattern classes
88
276ee533
SC
89OSStatus wxMacDrawCGImage(
90 CGContextRef inContext,
5252d9e4 91 const CGRect * inBounds,
947f3b35 92 CGImageRef inImage)
276ee533 93{
947f3b35 94#if defined( __LP64__ ) || defined(__WXCOCOA__)
276ee533
SC
95 // todo flip
96 CGContextDrawImage(inContext, *inBounds, inImage );
1bd568fa 97 return noErr;
276ee533 98#else
1bd568fa 99 return HIViewDrawCGImage( inContext, inBounds, inImage );
276ee533
SC
100#endif
101}
102
5252d9e4
SC
103CGColorRef wxMacCreateCGColor( const wxColour& col )
104{
105 CGColorRef retval = 0;
106#ifdef __WXMAC__
107 retval = col.CreateCGColor();
108#else
109// TODO add conversion NSColor - CGColorRef (obj-c)
110#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
111 if ( CGColorCreateGenericRGB )
112 retval = CGColorCreateGenericRGB( col.Red() / 255.0 , col.Green() / 255.0, col.Blue() / 255.0, col.Alpha() / 255.0 );
113 else
114#endif
115 {
947f3b35 116 CGFloat components[4] = { col.Red() / 255.0, col.Green() / 255.0, col.Blue() / 255.0, col.Alpha() / 255.0 } ;
5252d9e4
SC
117 retval = CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ;
118 }
119
120#endif
121 return retval;
122}
123
124#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && defined(wxMAC_USE_CORE_TEXT)
125
126CTFontRef wxMacCreateCTFont( const wxFont& font )
127{
128#ifdef __WXMAC__
129 return wxCFRetain((CTFontRef) font.MacGetCTFont());
130#else
131 return CTFontCreateWithName( wxCFStringRef( font.GetFaceName(), wxLocale::GetSystemEncoding() ) , font.GetPointSize() , NULL );
132#endif
133}
134
135#endif
136
b7b40adb
SC
137// CGPattern wrapper class: always allocate on heap, never call destructor
138
139class wxMacCoreGraphicsPattern
50581042 140{
50581042 141public :
b7b40adb 142 wxMacCoreGraphicsPattern() {}
50581042 143
b7b40adb
SC
144 // is guaranteed to be called only with a non-Null CGContextRef
145 virtual void Render( CGContextRef ctxRef ) = 0;
50581042 146
b7b40adb 147 operator CGPatternRef() const { return m_patternRef; }
50581042 148
b7b40adb
SC
149protected :
150 virtual ~wxMacCoreGraphicsPattern()
151 {
152 // as this is called only when the m_patternRef is been released;
153 // don't release it again
154 }
50581042 155
b7b40adb
SC
156 static void _Render( void *info, CGContextRef ctxRef )
157 {
158 wxMacCoreGraphicsPattern* self = (wxMacCoreGraphicsPattern*) info;
159 if ( self && ctxRef )
160 self->Render( ctxRef );
161 }
50581042 162
b7b40adb
SC
163 static void _Dispose( void *info )
164 {
165 wxMacCoreGraphicsPattern* self = (wxMacCoreGraphicsPattern*) info;
166 delete self;
167 }
50581042 168
b7b40adb 169 CGPatternRef m_patternRef;
50581042 170
b7b40adb
SC
171 static const CGPatternCallbacks ms_Callbacks;
172};
50581042 173
b7b40adb 174const CGPatternCallbacks wxMacCoreGraphicsPattern::ms_Callbacks = { 0, &wxMacCoreGraphicsPattern::_Render, &wxMacCoreGraphicsPattern::_Dispose };
50581042 175
b7b40adb
SC
176class ImagePattern : public wxMacCoreGraphicsPattern
177{
178public :
179 ImagePattern( const wxBitmap* bmp , const CGAffineTransform& transform )
180 {
181 wxASSERT( bmp && bmp->Ok() );
5252d9e4 182#ifdef __WXMAC__
968c951f 183 Init( (CGImageRef) bmp->CreateCGImage() , transform );
5252d9e4 184#endif
b7b40adb 185 }
50581042 186
b7b40adb
SC
187 // ImagePattern takes ownership of CGImageRef passed in
188 ImagePattern( CGImageRef image , const CGAffineTransform& transform )
189 {
190 if ( image )
191 CFRetain( image );
192
193 Init( image , transform );
194 }
195
196 virtual void Render( CGContextRef ctxRef )
197 {
198 if (m_image != NULL)
276ee533 199 wxMacDrawCGImage( ctxRef, &m_imageBounds, m_image );
b7b40adb
SC
200 }
201
202protected :
203 void Init( CGImageRef image, const CGAffineTransform& transform )
204 {
205 m_image = image;
206 if ( m_image )
207 {
35c72e51 208 m_imageBounds = CGRectMake( (CGFloat) 0.0, (CGFloat) 0.0, (CGFloat)CGImageGetWidth( m_image ), (CGFloat)CGImageGetHeight( m_image ) );
b7b40adb
SC
209 m_patternRef = CGPatternCreate(
210 this , m_imageBounds, transform ,
211 m_imageBounds.size.width, m_imageBounds.size.height,
212 kCGPatternTilingNoDistortion, true , &wxMacCoreGraphicsPattern::ms_Callbacks );
213 }
214 }
215
216 virtual ~ImagePattern()
217 {
218 if ( m_image )
219 CGImageRelease( m_image );
220 }
221
222 CGImageRef m_image;
223 CGRect m_imageBounds;
224};
225
226class HatchPattern : public wxMacCoreGraphicsPattern
227{
228public :
229 HatchPattern( int hatchstyle, const CGAffineTransform& transform )
230 {
231 m_hatch = hatchstyle;
35c72e51 232 m_imageBounds = CGRectMake( (CGFloat) 0.0, (CGFloat) 0.0, (CGFloat) 8.0 , (CGFloat) 8.0 );
b7b40adb
SC
233 m_patternRef = CGPatternCreate(
234 this , m_imageBounds, transform ,
235 m_imageBounds.size.width, m_imageBounds.size.height,
236 kCGPatternTilingNoDistortion, false , &wxMacCoreGraphicsPattern::ms_Callbacks );
237 }
238
239 void StrokeLineSegments( CGContextRef ctxRef , const CGPoint pts[] , size_t count )
240 {
e1673e52 241 CGContextStrokeLineSegments( ctxRef , pts , count );
b7b40adb
SC
242 }
243
244 virtual void Render( CGContextRef ctxRef )
245 {
246 switch ( m_hatch )
247 {
248 case wxBDIAGONAL_HATCH :
249 {
250 CGPoint pts[] =
251 {
35c72e51 252 { (CGFloat) 8.0 , (CGFloat) 0.0 } , { (CGFloat) 0.0 , (CGFloat) 8.0 }
b7b40adb
SC
253 };
254 StrokeLineSegments( ctxRef , pts , 2 );
255 }
256 break;
257
258 case wxCROSSDIAG_HATCH :
259 {
260 CGPoint pts[] =
261 {
35c72e51
SC
262 { (CGFloat) 0.0 , (CGFloat) 0.0 } , { (CGFloat) 8.0 , (CGFloat) 8.0 } ,
263 { (CGFloat) 8.0 , (CGFloat) 0.0 } , { (CGFloat) 0.0 , (CGFloat) 8.0 }
b7b40adb
SC
264 };
265 StrokeLineSegments( ctxRef , pts , 4 );
266 }
267 break;
268
269 case wxFDIAGONAL_HATCH :
270 {
271 CGPoint pts[] =
272 {
35c72e51 273 { (CGFloat) 0.0 , (CGFloat) 0.0 } , { (CGFloat) 8.0 , (CGFloat) 8.0 }
b7b40adb
SC
274 };
275 StrokeLineSegments( ctxRef , pts , 2 );
276 }
277 break;
278
279 case wxCROSS_HATCH :
280 {
281 CGPoint pts[] =
282 {
35c72e51
SC
283 { (CGFloat) 0.0 , (CGFloat) 4.0 } , { (CGFloat) 8.0 , (CGFloat) 4.0 } ,
284 { (CGFloat) 4.0 , (CGFloat) 0.0 } , { (CGFloat) 4.0 , (CGFloat) 8.0 } ,
b7b40adb
SC
285 };
286 StrokeLineSegments( ctxRef , pts , 4 );
287 }
288 break;
289
290 case wxHORIZONTAL_HATCH :
291 {
292 CGPoint pts[] =
293 {
35c72e51 294 { (CGFloat) 0.0 , (CGFloat) 4.0 } , { (CGFloat) 8.0 , (CGFloat) 4.0 } ,
b7b40adb
SC
295 };
296 StrokeLineSegments( ctxRef , pts , 2 );
297 }
298 break;
299
300 case wxVERTICAL_HATCH :
301 {
302 CGPoint pts[] =
303 {
35c72e51 304 { (CGFloat) 4.0 , (CGFloat) 0.0 } , { (CGFloat) 4.0 , (CGFloat) 8.0 } ,
b7b40adb
SC
305 };
306 StrokeLineSegments( ctxRef , pts , 2 );
307 }
308 break;
309
310 default:
311 break;
312 }
313 }
314
315protected :
316 virtual ~HatchPattern() {}
317
318 CGRect m_imageBounds;
319 int m_hatch;
320};
321
a26b7ab2 322class wxMacCoreGraphicsPenData : public wxGraphicsObjectRefData
b7b40adb
SC
323{
324public:
a26b7ab2
SC
325 wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer, const wxPen &pen );
326 ~wxMacCoreGraphicsPenData();
783d8bdf 327
b7b40adb
SC
328 void Init();
329 virtual void Apply( wxGraphicsContext* context );
330 virtual wxDouble GetWidth() { return m_width; }
783d8bdf 331
b7b40adb
SC
332protected :
333 CGLineCap m_cap;
7a7697aa
SC
334 wxCFRef<CGColorRef> m_color;
335 wxCFRef<CGColorSpaceRef> m_colorSpace;
b7b40adb
SC
336
337 CGLineJoin m_join;
338 CGFloat m_width;
783d8bdf 339
b7b40adb
SC
340 int m_count;
341 const CGFloat *m_lengths;
342 CGFloat *m_userLengths;
eec960fa 343
b7b40adb
SC
344
345 bool m_isPattern;
7a7697aa 346 wxCFRef<CGPatternRef> m_pattern;
b7b40adb 347 CGFloat* m_patternColorComponents;
50581042
SC
348};
349
a26b7ab2
SC
350wxMacCoreGraphicsPenData::wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer, const wxPen &pen ) :
351 wxGraphicsObjectRefData( renderer )
50581042 352{
b7b40adb 353 Init();
783d8bdf 354
5252d9e4 355 m_color.reset( wxMacCreateCGColor( pen.GetColour() ) ) ;
b7b40adb
SC
356
357 // TODO: * m_dc->m_scaleX
358 m_width = pen.GetWidth();
359 if (m_width <= 0.0)
35c72e51 360 m_width = (CGFloat) 0.1;
b7b40adb
SC
361
362 switch ( pen.GetCap() )
363 {
364 case wxCAP_ROUND :
365 m_cap = kCGLineCapRound;
366 break;
367
368 case wxCAP_PROJECTING :
369 m_cap = kCGLineCapSquare;
370 break;
371
372 case wxCAP_BUTT :
373 m_cap = kCGLineCapButt;
374 break;
375
376 default :
377 m_cap = kCGLineCapButt;
378 break;
379 }
380
381 switch ( pen.GetJoin() )
382 {
383 case wxJOIN_BEVEL :
384 m_join = kCGLineJoinBevel;
385 break;
386
387 case wxJOIN_MITER :
388 m_join = kCGLineJoinMiter;
389 break;
390
391 case wxJOIN_ROUND :
392 m_join = kCGLineJoinRound;
393 break;
394
395 default :
396 m_join = kCGLineJoinMiter;
397 break;
398 }
399
35c72e51 400 const CGFloat dashUnit = m_width < 1.0 ? (CGFloat) 1.0 : m_width;
b7b40adb 401
35c72e51
SC
402 const CGFloat dotted[] = { (CGFloat) dashUnit , (CGFloat) (dashUnit + 2.0) };
403 static const CGFloat short_dashed[] = { (CGFloat) 9.0 , (CGFloat) 6.0 };
404 static const CGFloat dashed[] = { (CGFloat) 19.0 , (CGFloat) 9.0 };
405 static const CGFloat dotted_dashed[] = { (CGFloat) 9.0 , (CGFloat) 6.0 , (CGFloat) 3.0 , (CGFloat) 3.0 };
b7b40adb
SC
406
407 switch ( pen.GetStyle() )
408 {
409 case wxSOLID :
410 break;
411
412 case wxDOT :
413 m_count = WXSIZEOF(dotted);
414 m_userLengths = new CGFloat[ m_count ] ;
415 memcpy( m_userLengths, dotted, sizeof(dotted) );
416 m_lengths = m_userLengths;
417 break;
418
419 case wxLONG_DASH :
420 m_count = WXSIZEOF(dashed);
421 m_lengths = dashed;
422 break;
423
424 case wxSHORT_DASH :
425 m_count = WXSIZEOF(short_dashed);
426 m_lengths = short_dashed;
427 break;
428
429 case wxDOT_DASH :
430 m_count = WXSIZEOF(dotted_dashed);
431 m_lengths = dotted_dashed;
432 break;
433
434 case wxUSER_DASH :
435 wxDash *dashes;
436 m_count = pen.GetDashes( &dashes );
437 if ((dashes != NULL) && (m_count > 0))
438 {
439 m_userLengths = new CGFloat[m_count];
440 for ( int i = 0; i < m_count; ++i )
441 {
442 m_userLengths[i] = dashes[i] * dashUnit;
443
444 if ( i % 2 == 1 && m_userLengths[i] < dashUnit + 2.0 )
35c72e51 445 m_userLengths[i] = (CGFloat) (dashUnit + 2.0);
b7b40adb
SC
446 else if ( i % 2 == 0 && m_userLengths[i] < dashUnit )
447 m_userLengths[i] = dashUnit;
448 }
449 }
450 m_lengths = m_userLengths;
451 break;
452
453 case wxSTIPPLE :
454 {
455 wxBitmap* bmp = pen.GetStipple();
456 if ( bmp && bmp->Ok() )
457 {
7a7697aa
SC
458 m_colorSpace.reset( CGColorSpaceCreatePattern( NULL ) );
459 m_pattern.reset( (CGPatternRef) *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) );
b7b40adb 460 m_patternColorComponents = new CGFloat[1] ;
35c72e51 461 m_patternColorComponents[0] = (CGFloat) 1.0;
b7b40adb
SC
462 m_isPattern = true;
463 }
464 }
465 break;
466
467 default :
468 {
469 m_isPattern = true;
7a7697aa
SC
470 m_colorSpace.reset( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
471 m_pattern.reset( (CGPatternRef) *( new HatchPattern( pen.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) );
b7b40adb 472 m_patternColorComponents = new CGFloat[4] ;
35c72e51
SC
473 m_patternColorComponents[0] = (CGFloat) (pen.GetColour().Red() / 255.0);
474 m_patternColorComponents[1] = (CGFloat) (pen.GetColour().Green() / 255.0);
475 m_patternColorComponents[2] = (CGFloat) (pen.GetColour().Blue() / 255.0);
476 m_patternColorComponents[3] = (CGFloat) (pen.GetColour().Alpha() / 255.0);
b7b40adb
SC
477 }
478 break;
479 }
480 if ((m_lengths != NULL) && (m_count > 0))
481 {
482 // force the line cap, otherwise we get artifacts (overlaps) and just solid lines
483 m_cap = kCGLineCapButt;
484 }
50581042
SC
485}
486
a26b7ab2 487wxMacCoreGraphicsPenData::~wxMacCoreGraphicsPenData()
50581042 488{
b7b40adb
SC
489 delete[] m_userLengths;
490 delete[] m_patternColorComponents;
50581042
SC
491}
492
a26b7ab2 493void wxMacCoreGraphicsPenData::Init()
50581042 494{
b7b40adb
SC
495 m_lengths = NULL;
496 m_userLengths = NULL;
783d8bdf 497 m_width = 0;
b7b40adb
SC
498 m_count = 0;
499 m_patternColorComponents = NULL;
500 m_isPattern = false;
50581042
SC
501}
502
a26b7ab2 503void wxMacCoreGraphicsPenData::Apply( wxGraphicsContext* context )
50581042 504{
b7b40adb
SC
505 CGContextRef cg = (CGContextRef) context->GetNativeContext();
506 CGContextSetLineWidth( cg , m_width );
507 CGContextSetLineJoin( cg , m_join );
508
509 CGContextSetLineDash( cg , 0 , m_lengths , m_count );
510 CGContextSetLineCap( cg , m_cap );
511
512 if ( m_isPattern )
513 {
74b357dd
SC
514 CGAffineTransform matrix = CGContextGetCTM( cg );
515 CGContextSetPatternPhase( cg, CGSizeMake(matrix.tx, matrix.ty) );
b7b40adb
SC
516 CGContextSetStrokeColorSpace( cg , m_colorSpace );
517 CGContextSetStrokePattern( cg, m_pattern , m_patternColorComponents );
518 }
519 else
520 {
277ccdaf
SC
521 if ( context->GetLogicalFunction() == wxINVERT || context->GetLogicalFunction() == wxXOR )
522 {
35c72e51 523 CGContextSetRGBStrokeColor( cg , (CGFloat) 1.0,(CGFloat) 1.0 , (CGFloat) 1.0, (CGFloat) 1.0 );
277ccdaf
SC
524 }
525 else
526 CGContextSetStrokeColorWithColor( cg , m_color );
b7b40adb 527 }
50581042
SC
528}
529
b7b40adb
SC
530//
531// Brush
532//
533
6239ee05
SC
534static const char *gs_stripedback_xpm[] = {
535/* columns rows colors chars-per-pixel */
536"4 4 2 1",
537". c #F0F0F0",
538"X c #ECECEC",
539/* pixels */
540"....",
541"....",
542"XXXX",
543"XXXX"
b7b40adb
SC
544};
545
6239ee05
SC
546wxBitmap gs_stripedback_bmp( wxImage( (const char* const* ) gs_stripedback_xpm ), -1 ) ;
547
a01d9a25
SC
548// make sure we all use one class for all conversions from wx to native colour
549
550class wxMacCoreGraphicsColour
551{
552 public:
553 wxMacCoreGraphicsColour();
554 wxMacCoreGraphicsColour(const wxBrush &brush);
555 ~wxMacCoreGraphicsColour();
947f3b35 556
a01d9a25
SC
557 void Apply( CGContextRef cgContext );
558 protected:
559 void Init();
7a7697aa
SC
560 wxCFRef<CGColorRef> m_color;
561 wxCFRef<CGColorSpaceRef> m_colorSpace;
947f3b35 562
a01d9a25 563 bool m_isPattern;
7a7697aa 564 wxCFRef<CGPatternRef> m_pattern;
a01d9a25
SC
565 CGFloat* m_patternColorComponents;
566} ;
567
6239ee05 568wxMacCoreGraphicsColour::~wxMacCoreGraphicsColour()
50581042 569{
6239ee05 570 delete[] m_patternColorComponents;
50581042
SC
571}
572
6239ee05 573void wxMacCoreGraphicsColour::Init()
50581042 574{
6239ee05
SC
575 m_isPattern = false;
576 m_patternColorComponents = NULL;
b7b40adb 577}
783d8bdf 578
6239ee05 579void wxMacCoreGraphicsColour::Apply( CGContextRef cgContext )
b7b40adb 580{
6239ee05
SC
581 if ( m_isPattern )
582 {
583 CGAffineTransform matrix = CGContextGetCTM( cgContext );
584 CGContextSetPatternPhase( cgContext, CGSizeMake(matrix.tx, matrix.ty) );
585 CGContextSetFillColorSpace( cgContext , m_colorSpace );
586 CGContextSetFillPattern( cgContext, m_pattern , m_patternColorComponents );
587 }
588 else
589 {
590 CGContextSetFillColorWithColor( cgContext, m_color );
591 }
b7b40adb 592}
783d8bdf 593
947f3b35 594wxMacCoreGraphicsColour::wxMacCoreGraphicsColour()
b7b40adb
SC
595{
596 Init();
6239ee05 597}
783d8bdf 598
6239ee05
SC
599wxMacCoreGraphicsColour::wxMacCoreGraphicsColour( const wxBrush &brush )
600{
601 Init();
b7b40adb
SC
602 if ( brush.GetStyle() == wxSOLID )
603 {
5252d9e4 604 m_color.reset( wxMacCreateCGColor( brush.GetColour() ));
b7b40adb
SC
605 }
606 else if ( brush.IsHatch() )
607 {
608 m_isPattern = true;
7a7697aa
SC
609 m_colorSpace.reset( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
610 m_pattern.reset( (CGPatternRef) *( new HatchPattern( brush.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) );
b7b40adb
SC
611
612 m_patternColorComponents = new CGFloat[4] ;
35c72e51
SC
613 m_patternColorComponents[0] = (CGFloat) (brush.GetColour().Red() / 255.0);
614 m_patternColorComponents[1] = (CGFloat) (brush.GetColour().Green() / 255.0);
615 m_patternColorComponents[2] = (CGFloat) (brush.GetColour().Blue() / 255.0);
616 m_patternColorComponents[3] = (CGFloat) (brush.GetColour().Alpha() / 255.0);
b7b40adb
SC
617 }
618 else
619 {
620 // now brush is a bitmap
621 wxBitmap* bmp = brush.GetStipple();
622 if ( bmp && bmp->Ok() )
623 {
783d8bdf 624 m_isPattern = true;
b7b40adb 625 m_patternColorComponents = new CGFloat[1] ;
35c72e51 626 m_patternColorComponents[0] = (CGFloat) 1.0;
7a7697aa
SC
627 m_colorSpace.reset( CGColorSpaceCreatePattern( NULL ) );
628 m_pattern.reset( (CGPatternRef) *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) );
b7b40adb
SC
629 }
630 }
50581042
SC
631}
632
6239ee05
SC
633class wxMacCoreGraphicsBrushData : public wxGraphicsObjectRefData
634{
635public:
636 wxMacCoreGraphicsBrushData( wxGraphicsRenderer* renderer );
637 wxMacCoreGraphicsBrushData( wxGraphicsRenderer* renderer, const wxBrush &brush );
638 ~wxMacCoreGraphicsBrushData ();
639
640 virtual void Apply( wxGraphicsContext* context );
641 void CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
642 const wxColour&c1, const wxColour&c2 );
643 void CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
644 const wxColour &oColor, const wxColour &cColor );
645
646 virtual bool IsShading() { return m_isShading; }
647 CGShadingRef GetShading() { return m_shading; }
648protected:
649 CGFunctionRef CreateGradientFunction( const wxColour& c1, const wxColour& c2 );
650 static void CalculateShadingValues (void *info, const CGFloat *in, CGFloat *out);
651 virtual void Init();
652
653 wxMacCoreGraphicsColour m_cgColor;
654
655 bool m_isShading;
656 CGFunctionRef m_gradientFunction;
657 CGShadingRef m_shading;
658 CGFloat *m_gradientComponents;
659};
660
661wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData( wxGraphicsRenderer* renderer) : wxGraphicsObjectRefData( renderer )
662{
663 Init();
664}
665
666void wxMacCoreGraphicsBrushData::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
667 const wxColour&c1, const wxColour&c2 )
668{
669 m_gradientFunction = CreateGradientFunction( c1, c2 );
35c72e51
SC
670 m_shading = CGShadingCreateAxial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat) x1, (CGFloat) y1),
671 CGPointMake((CGFloat) x2,(CGFloat) y2), m_gradientFunction, true, true ) ;
6239ee05
SC
672 m_isShading = true ;
673}
674
675void wxMacCoreGraphicsBrushData::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
676 const wxColour &oColor, const wxColour &cColor )
677{
678 m_gradientFunction = CreateGradientFunction( oColor, cColor );
35c72e51
SC
679 m_shading = CGShadingCreateRadial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat) xo,(CGFloat) yo), 0,
680 CGPointMake((CGFloat) xc,(CGFloat) yc), (CGFloat) radius, m_gradientFunction, true, true ) ;
6239ee05
SC
681 m_isShading = true ;
682}
683
684wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData(wxGraphicsRenderer* renderer, const wxBrush &brush) : wxGraphicsObjectRefData( renderer ),
685 m_cgColor( brush )
686{
687 Init();
688
689}
690
a26b7ab2 691wxMacCoreGraphicsBrushData::~wxMacCoreGraphicsBrushData()
50581042 692{
b7b40adb
SC
693 if ( m_shading )
694 CGShadingRelease(m_shading);
783d8bdf 695
b7b40adb
SC
696 if( m_gradientFunction )
697 CGFunctionRelease(m_gradientFunction);
783d8bdf 698
b7b40adb 699 delete[] m_gradientComponents;
50581042
SC
700}
701
a26b7ab2 702void wxMacCoreGraphicsBrushData::Init()
50581042 703{
b7b40adb
SC
704 m_gradientFunction = NULL;
705 m_shading = NULL;
b7b40adb
SC
706 m_gradientComponents = NULL;
707 m_isShading = false;
50581042
SC
708}
709
a26b7ab2 710void wxMacCoreGraphicsBrushData::Apply( wxGraphicsContext* context )
50581042 711{
b7b40adb 712 CGContextRef cg = (CGContextRef) context->GetNativeContext();
783d8bdf 713
b7b40adb 714 if ( m_isShading )
783d8bdf 715 {
74b357dd 716 // nothing to set as shades are processed by clipping using the path and filling
b7b40adb
SC
717 }
718 else
719 {
6239ee05 720 m_cgColor.Apply( cg );
b7b40adb 721 }
50581042
SC
722}
723
a26b7ab2 724void wxMacCoreGraphicsBrushData::CalculateShadingValues (void *info, const CGFloat *in, CGFloat *out)
50581042 725{
b7b40adb
SC
726 CGFloat* colors = (CGFloat*) info ;
727 CGFloat f = *in;
728 for( int i = 0 ; i < 4 ; ++i )
729 {
730 out[i] = colors[i] + ( colors[4+i] - colors[i] ) * f;
731 }
50581042
SC
732}
733
a26b7ab2 734CGFunctionRef wxMacCoreGraphicsBrushData::CreateGradientFunction( const wxColour& c1, const wxColour& c2 )
50581042 735{
b7b40adb
SC
736 static const CGFunctionCallbacks callbacks = { 0, &CalculateShadingValues, NULL };
737 static const CGFloat input_value_range [2] = { 0, 1 };
738 static const CGFloat output_value_ranges [8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
739 m_gradientComponents = new CGFloat[8] ;
35c72e51
SC
740 m_gradientComponents[0] = (CGFloat) (c1.Red() / 255.0);
741 m_gradientComponents[1] = (CGFloat) (c1.Green() / 255.0);
742 m_gradientComponents[2] = (CGFloat) (c1.Blue() / 255.0);
743 m_gradientComponents[3] = (CGFloat) (c1.Alpha() / 255.0);
744 m_gradientComponents[4] = (CGFloat) (c2.Red() / 255.0);
745 m_gradientComponents[5] = (CGFloat) (c2.Green() / 255.0);
746 m_gradientComponents[6] = (CGFloat) (c2.Blue() / 255.0);
747 m_gradientComponents[7] = (CGFloat) (c2.Alpha() / 255.0);
b7b40adb 748
783d8bdf
VZ
749 return CGFunctionCreate ( m_gradientComponents, 1,
750 input_value_range,
751 4,
b7b40adb 752 output_value_ranges,
783d8bdf 753 &callbacks);
50581042
SC
754}
755
756//
b7b40adb 757// Font
50581042
SC
758//
759
a26b7ab2 760class wxMacCoreGraphicsFontData : public wxGraphicsObjectRefData
50581042 761{
50581042 762public:
a26b7ab2
SC
763 wxMacCoreGraphicsFontData( wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col );
764 ~wxMacCoreGraphicsFontData();
783d8bdf 765
c07e1e2c 766#if wxMAC_USE_ATSU_TEXT
b7b40adb 767 virtual ATSUStyle GetATSUStyle() { return m_macATSUIStyle; }
c07e1e2c
SC
768#endif
769#if wxMAC_USE_CORE_TEXT
770 CTFontRef GetCTFont() const { return m_ctFont ; }
771#endif
772 wxColour GetColour() const { return m_colour ; }
947f3b35 773
c07e1e2c 774 bool GetUnderlined() const { return m_underlined ; }
b7b40adb 775private :
c07e1e2c
SC
776 wxColour m_colour;
777 bool m_underlined;
778#if wxMAC_USE_ATSU_TEXT
b7b40adb 779 ATSUStyle m_macATSUIStyle;
c07e1e2c
SC
780#endif
781#if wxMAC_USE_CORE_TEXT
782 wxCFRef< CTFontRef > m_ctFont;
783#endif
b7b40adb 784};
50581042 785
a26b7ab2 786wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col) : wxGraphicsObjectRefData( renderer )
b7b40adb 787{
c07e1e2c
SC
788 m_colour = col;
789 m_underlined = font.GetUnderlined();
783d8bdf 790
d2d8b4db 791#if wxMAC_USE_CORE_TEXT
5252d9e4 792 m_ctFont.reset( wxMacCreateCTFont( font ) );
c07e1e2c
SC
793#endif
794#if wxMAC_USE_ATSU_TEXT
e773889d
SC
795 OSStatus status = noErr;
796 m_macATSUIStyle = NULL;
50581042 797
b7b40adb 798 status = ATSUCreateAndCopyStyle( (ATSUStyle) font.MacGetATSUStyle() , &m_macATSUIStyle );
50581042 799
b7b40adb 800 wxASSERT_MSG( status == noErr, wxT("couldn't create ATSU style") );
50581042 801
b7b40adb 802 // we need the scale here ...
50581042 803
b7b40adb 804 Fixed atsuSize = IntToFixed( int( 1 * font.MacGetFontSize()) );
276ee533
SC
805 RGBColor atsuColor ;
806 col.GetRGBColor( &atsuColor );
b7b40adb
SC
807 ATSUAttributeTag atsuTags[] =
808 {
809 kATSUSizeTag ,
810 kATSUColorTag ,
811 };
812 ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
813 {
814 sizeof( Fixed ) ,
815 sizeof( RGBColor ) ,
816 };
817 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
818 {
819 &atsuSize ,
820 &atsuColor ,
821 };
50581042 822
b7b40adb
SC
823 status = ::ATSUSetAttributes(
824 m_macATSUIStyle, sizeof(atsuTags) / sizeof(ATSUAttributeTag) ,
825 atsuTags, atsuSizes, atsuValues);
50581042 826
b7b40adb 827 wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") );
c07e1e2c 828#endif
0fa6a0ac 829#if wxMAC_USE_CG_TEXT
1bd568fa 830#endif
b7b40adb 831}
50581042 832
a26b7ab2 833wxMacCoreGraphicsFontData::~wxMacCoreGraphicsFontData()
b7b40adb 834{
d2d8b4db 835#if wxMAC_USE_CORE_TEXT
c07e1e2c
SC
836#endif
837#if wxMAC_USE_ATSU_TEXT
b7b40adb
SC
838 if ( m_macATSUIStyle )
839 {
840 ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
841 m_macATSUIStyle = NULL;
842 }
c07e1e2c 843#endif
0fa6a0ac 844#if wxMAC_USE_CG_TEXT
1bd568fa 845#endif
b7b40adb 846}
50581042 847
5252d9e4
SC
848class wxMacCoreGraphicsBitmapData : public wxGraphicsObjectRefData
849{
850public:
35c72e51 851 wxMacCoreGraphicsBitmapData( wxGraphicsRenderer* renderer, CGImageRef bitmap, bool monochrome );
5252d9e4
SC
852 ~wxMacCoreGraphicsBitmapData();
853
854 virtual CGImageRef GetBitmap() { return m_bitmap; }
35c72e51 855 bool IsMonochrome() { return m_monochrome; }
5252d9e4
SC
856private :
857 CGImageRef m_bitmap;
35c72e51 858 bool m_monochrome;
5252d9e4
SC
859};
860
35c72e51
SC
861wxMacCoreGraphicsBitmapData::wxMacCoreGraphicsBitmapData( wxGraphicsRenderer* renderer, CGImageRef bitmap, bool monochrome ) : wxGraphicsObjectRefData( renderer ),
862 m_bitmap(bitmap), m_monochrome(monochrome)
5252d9e4 863{
5252d9e4
SC
864}
865
866wxMacCoreGraphicsBitmapData::~wxMacCoreGraphicsBitmapData()
867{
868 CGImageRelease( m_bitmap );
869}
870
b7b40adb
SC
871//
872// Graphics Matrix
873//
50581042 874
b7b40adb
SC
875//-----------------------------------------------------------------------------
876// wxMacCoreGraphicsMatrix declaration
877//-----------------------------------------------------------------------------
50581042 878
e3ff3591 879class WXDLLIMPEXP_CORE wxMacCoreGraphicsMatrixData : public wxGraphicsMatrixData
b7b40adb
SC
880{
881public :
783d8bdf
VZ
882 wxMacCoreGraphicsMatrixData(wxGraphicsRenderer* renderer) ;
883
884 virtual ~wxMacCoreGraphicsMatrixData() ;
885
e3ff3591 886 virtual wxGraphicsObjectRefData *Clone() const ;
b7b40adb 887
783d8bdf
VZ
888 // concatenates the matrix
889 virtual void Concat( const wxGraphicsMatrixData *t );
890
891 // sets the matrix to the respective values
892 virtual void Set(wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
893 wxDouble tx=0.0, wxDouble ty=0.0);
894
248802d0
RD
895 // gets the component valuess of the matrix
896 virtual void Get(wxDouble* a=NULL, wxDouble* b=NULL, wxDouble* c=NULL,
897 wxDouble* d=NULL, wxDouble* tx=NULL, wxDouble* ty=NULL) const;
947f3b35 898
783d8bdf
VZ
899 // makes this the inverse matrix
900 virtual void Invert();
901
902 // returns true if the elements of the transformation matrix are equal ?
e3ff3591 903 virtual bool IsEqual( const wxGraphicsMatrixData* t) const ;
783d8bdf
VZ
904
905 // return true if this is the identity matrix
906 virtual bool IsIdentity() const;
907
50581042 908 //
b7b40adb 909 // transformation
50581042 910 //
783d8bdf 911
b7b40adb
SC
912 // add the translation to this matrix
913 virtual void Translate( wxDouble dx , wxDouble dy );
50581042 914
b7b40adb
SC
915 // add the scale to this matrix
916 virtual void Scale( wxDouble xScale , wxDouble yScale );
50581042 917
b7b40adb 918 // add the rotation to this matrix (radians)
783d8bdf
VZ
919 virtual void Rotate( wxDouble angle );
920
50581042 921 //
b7b40adb 922 // apply the transforms
50581042 923 //
783d8bdf
VZ
924
925 // applies that matrix to the point
926 virtual void TransformPoint( wxDouble *x, wxDouble *y ) const;
927
928 // applies the matrix except for translations
929 virtual void TransformDistance( wxDouble *dx, wxDouble *dy ) const;
930
931 // returns the native representation
932 virtual void * GetNativeMatrix() const;
933
b7b40adb
SC
934private :
935 CGAffineTransform m_matrix;
b7b40adb 936} ;
50581042 937
50581042 938//-----------------------------------------------------------------------------
b7b40adb 939// wxMacCoreGraphicsMatrix implementation
50581042
SC
940//-----------------------------------------------------------------------------
941
e3ff3591 942wxMacCoreGraphicsMatrixData::wxMacCoreGraphicsMatrixData(wxGraphicsRenderer* renderer) : wxGraphicsMatrixData(renderer)
b7b40adb 943{
b7b40adb 944}
eec960fa 945
783d8bdf 946wxMacCoreGraphicsMatrixData::~wxMacCoreGraphicsMatrixData()
50581042 947{
50581042
SC
948}
949
783d8bdf 950wxGraphicsObjectRefData *wxMacCoreGraphicsMatrixData::Clone() const
50581042 951{
e3ff3591 952 wxMacCoreGraphicsMatrixData* m = new wxMacCoreGraphicsMatrixData(GetRenderer()) ;
b7b40adb
SC
953 m->m_matrix = m_matrix ;
954 return m;
955}
956
957// concatenates the matrix
783d8bdf 958void wxMacCoreGraphicsMatrixData::Concat( const wxGraphicsMatrixData *t )
b7b40adb
SC
959{
960 m_matrix = CGAffineTransformConcat(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix()) );
961}
962
b7b40adb 963// sets the matrix to the respective values
783d8bdf
VZ
964void wxMacCoreGraphicsMatrixData::Set(wxDouble a, wxDouble b, wxDouble c, wxDouble d,
965 wxDouble tx, wxDouble ty)
b7b40adb 966{
35c72e51 967 m_matrix = CGAffineTransformMake((CGFloat) a,(CGFloat) b,(CGFloat) c,(CGFloat) d,(CGFloat) tx,(CGFloat) ty);
50581042
SC
968}
969
248802d0
RD
970// gets the component valuess of the matrix
971void wxMacCoreGraphicsMatrixData::Get(wxDouble* a, wxDouble* b, wxDouble* c,
972 wxDouble* d, wxDouble* tx, wxDouble* ty) const
973{
974 if (a) *a = m_matrix.a;
975 if (b) *b = m_matrix.b;
976 if (c) *c = m_matrix.c;
977 if (d) *d = m_matrix.d;
978 if (tx) *tx= m_matrix.tx;
979 if (ty) *ty= m_matrix.ty;
980}
981
b7b40adb 982// makes this the inverse matrix
783d8bdf 983void wxMacCoreGraphicsMatrixData::Invert()
1056ddcf 984{
b7b40adb 985 m_matrix = CGAffineTransformInvert( m_matrix );
eec960fa
SC
986}
987
b7b40adb 988// returns true if the elements of the transformation matrix are equal ?
783d8bdf 989bool wxMacCoreGraphicsMatrixData::IsEqual( const wxGraphicsMatrixData* t) const
eec960fa 990{
e1673e52 991 return CGAffineTransformEqualToTransform(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix()));
1056ddcf
SC
992}
993
b7b40adb 994// return true if this is the identity matrix
e3ff3591 995bool wxMacCoreGraphicsMatrixData::IsIdentity() const
50581042 996{
2701ef7e
SC
997 return ( m_matrix.a == 1 && m_matrix.d == 1 &&
998 m_matrix.b == 0 && m_matrix.d == 0 && m_matrix.tx == 0 && m_matrix.ty == 0);
50581042
SC
999}
1000
b7b40adb
SC
1001//
1002// transformation
1003//
1004
1005// add the translation to this matrix
783d8bdf 1006void wxMacCoreGraphicsMatrixData::Translate( wxDouble dx , wxDouble dy )
50581042 1007{
35c72e51 1008 m_matrix = CGAffineTransformTranslate( m_matrix, (CGFloat) dx, (CGFloat) dy);
b7b40adb 1009}
50581042 1010
b7b40adb 1011// add the scale to this matrix
783d8bdf 1012void wxMacCoreGraphicsMatrixData::Scale( wxDouble xScale , wxDouble yScale )
b7b40adb 1013{
35c72e51 1014 m_matrix = CGAffineTransformScale( m_matrix, (CGFloat) xScale, (CGFloat) yScale);
50581042
SC
1015}
1016
b7b40adb 1017// add the rotation to this matrix (radians)
783d8bdf 1018void wxMacCoreGraphicsMatrixData::Rotate( wxDouble angle )
eec960fa 1019{
35c72e51 1020 m_matrix = CGAffineTransformRotate( m_matrix, (CGFloat) angle);
eec960fa
SC
1021}
1022
b7b40adb
SC
1023//
1024// apply the transforms
1025//
eec960fa 1026
b7b40adb 1027// applies that matrix to the point
e3ff3591 1028void wxMacCoreGraphicsMatrixData::TransformPoint( wxDouble *x, wxDouble *y ) const
50581042 1029{
35c72e51 1030 CGPoint pt = CGPointApplyAffineTransform( CGPointMake((CGFloat) *x,(CGFloat) *y), m_matrix);
783d8bdf 1031
2701ef7e
SC
1032 *x = pt.x;
1033 *y = pt.y;
1056ddcf
SC
1034}
1035
b7b40adb 1036// applies the matrix except for translations
e3ff3591 1037void wxMacCoreGraphicsMatrixData::TransformDistance( wxDouble *dx, wxDouble *dy ) const
1056ddcf 1038{
35c72e51 1039 CGSize sz = CGSizeApplyAffineTransform( CGSizeMake((CGFloat) *dx,(CGFloat) *dy) , m_matrix );
2701ef7e
SC
1040 *dx = sz.width;
1041 *dy = sz.height;
b7b40adb
SC
1042}
1043
1044// returns the native representation
783d8bdf 1045void * wxMacCoreGraphicsMatrixData::GetNativeMatrix() const
1056ddcf 1046{
b7b40adb 1047 return (void*) &m_matrix;
50581042
SC
1048}
1049
b7b40adb
SC
1050//
1051// Graphics Path
1052//
1053
1054//-----------------------------------------------------------------------------
1055// wxMacCoreGraphicsPath declaration
1056//-----------------------------------------------------------------------------
1057
e3ff3591 1058class WXDLLEXPORT wxMacCoreGraphicsPathData : public wxGraphicsPathData
50581042 1059{
b7b40adb 1060public :
e3ff3591 1061 wxMacCoreGraphicsPathData( wxGraphicsRenderer* renderer, CGMutablePathRef path = NULL);
783d8bdf 1062
e3ff3591 1063 ~wxMacCoreGraphicsPathData();
1056ddcf 1064
e3ff3591 1065 virtual wxGraphicsObjectRefData *Clone() const;
1056ddcf 1066
b7b40adb
SC
1067 // begins a new subpath at (x,y)
1068 virtual void MoveToPoint( wxDouble x, wxDouble y );
1056ddcf 1069
783d8bdf 1070 // adds a straight line from the current point to (x,y)
b7b40adb
SC
1071 virtual void AddLineToPoint( wxDouble x, wxDouble y );
1072
1073 // adds a cubic Bezier curve from the current point, using two control points and an end point
1074 virtual void AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y );
1075
1076 // closes the current sub-path
1077 virtual void CloseSubpath();
1078
1079 // gets the last point of the current path, (0,0) if not yet set
e3ff3591 1080 virtual void GetCurrentPoint( wxDouble* x, wxDouble* y) const;
b7b40adb
SC
1081
1082 // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
1083 virtual void AddArc( wxDouble x, wxDouble y, wxDouble r, wxDouble startAngle, wxDouble endAngle, bool clockwise );
1084
1085 //
783d8bdf 1086 // These are convenience functions which - if not available natively will be assembled
b7b40adb
SC
1087 // using the primitives from above
1088 //
1089
1090 // adds a quadratic Bezier curve from the current point, using a control point and an end point
1091 virtual void AddQuadCurveToPoint( wxDouble cx, wxDouble cy, wxDouble x, wxDouble y );
1092
783d8bdf 1093 // appends a rectangle as a new closed subpath
b7b40adb
SC
1094 virtual void AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
1095
1096 // appends an ellipsis as a new closed subpath fitting the passed rectangle
1097 virtual void AddCircle( wxDouble x, wxDouble y, wxDouble r );
1098
1099 // draws a an arc to two tangents connecting (current) to (x1,y1) and (x1,y1) to (x2,y2), also a straight line from (current) to (x1,y1)
1100 virtual void AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r );
1101
783d8bdf
VZ
1102 // adds another path
1103 virtual void AddPath( const wxGraphicsPathData* path );
1104
1105 // returns the native path
1106 virtual void * GetNativePath() const { return m_path; }
1107
1108 // give the native path returned by GetNativePath() back (there might be some deallocations necessary)
89954433 1109 virtual void UnGetNativePath(void *WXUNUSED(p)) const {}
783d8bdf
VZ
1110
1111 // transforms each point of this path by the matrix
1112 virtual void Transform( const wxGraphicsMatrixData* matrix );
1113
1114 // gets the bounding box enclosing all points (possibly including control points)
1115 virtual void GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *y) const;
1116
1117 virtual bool Contains( wxDouble x, wxDouble y, int fillStyle = wxODDEVEN_RULE) const;
b7b40adb
SC
1118private :
1119 CGMutablePathRef m_path;
1120};
1121
1122//-----------------------------------------------------------------------------
1123// wxMacCoreGraphicsPath implementation
1124//-----------------------------------------------------------------------------
1125
e3ff3591 1126wxMacCoreGraphicsPathData::wxMacCoreGraphicsPathData( wxGraphicsRenderer* renderer, CGMutablePathRef path) : wxGraphicsPathData(renderer)
b7b40adb 1127{
783d8bdf
VZ
1128 if ( path )
1129 m_path = path;
1130 else
1131 m_path = CGPathCreateMutable();
50581042
SC
1132}
1133
e3ff3591 1134wxMacCoreGraphicsPathData::~wxMacCoreGraphicsPathData()
50581042 1135{
b7b40adb
SC
1136 CGPathRelease( m_path );
1137}
50581042 1138
783d8bdf 1139wxGraphicsObjectRefData* wxMacCoreGraphicsPathData::Clone() const
b7b40adb 1140{
783d8bdf
VZ
1141 wxMacCoreGraphicsPathData* clone = new wxMacCoreGraphicsPathData(GetRenderer(),CGPathCreateMutableCopy(m_path));
1142 return clone ;
b7b40adb 1143}
1056ddcf 1144
1056ddcf 1145
b7b40adb 1146// opens (starts) a new subpath
e3ff3591 1147void wxMacCoreGraphicsPathData::MoveToPoint( wxDouble x1 , wxDouble y1 )
b7b40adb 1148{
35c72e51 1149 CGPathMoveToPoint( m_path , NULL , (CGFloat) x1 , (CGFloat) y1 );
b7b40adb 1150}
1056ddcf 1151
e3ff3591 1152void wxMacCoreGraphicsPathData::AddLineToPoint( wxDouble x1 , wxDouble y1 )
b7b40adb 1153{
35c72e51 1154 CGPathAddLineToPoint( m_path , NULL , (CGFloat) x1 , (CGFloat) y1 );
50581042
SC
1155}
1156
e3ff3591 1157void wxMacCoreGraphicsPathData::AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y )
50581042 1158{
35c72e51 1159 CGPathAddCurveToPoint( m_path , NULL , (CGFloat) cx1 , (CGFloat) cy1 , (CGFloat) cx2, (CGFloat) cy2, (CGFloat) x , (CGFloat) y );
50581042
SC
1160}
1161
e3ff3591 1162void wxMacCoreGraphicsPathData::AddQuadCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble x, wxDouble y )
50581042 1163{
35c72e51 1164 CGPathAddQuadCurveToPoint( m_path , NULL , (CGFloat) cx1 , (CGFloat) cy1 , (CGFloat) x , (CGFloat) y );
50581042
SC
1165}
1166
e3ff3591 1167void wxMacCoreGraphicsPathData::AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
50581042 1168{
35c72e51 1169 CGRect cgRect = { { (CGFloat) x , (CGFloat) y } , { (CGFloat) w , (CGFloat) h } };
b7b40adb
SC
1170 CGPathAddRect( m_path , NULL , cgRect );
1171}
50581042 1172
e3ff3591 1173void wxMacCoreGraphicsPathData::AddCircle( wxDouble x, wxDouble y , wxDouble r )
b7b40adb 1174{
35c72e51 1175 CGPathAddArc( m_path , NULL , (CGFloat) x , (CGFloat) y , (CGFloat) r , (CGFloat) 0.0 , (CGFloat) (2 * M_PI) , true );
50581042
SC
1176}
1177
b7b40adb 1178// adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
e3ff3591 1179void wxMacCoreGraphicsPathData::AddArc( wxDouble x, wxDouble y, wxDouble r, wxDouble startAngle, wxDouble endAngle, bool clockwise )
50581042 1180{
b7b40adb 1181 // inverse direction as we the 'normal' state is a y axis pointing down, ie mirrored to the standard core graphics setup
35c72e51 1182 CGPathAddArc( m_path, NULL , (CGFloat) x, (CGFloat) y, (CGFloat) r, (CGFloat) startAngle, (CGFloat) endAngle, !clockwise);
50581042
SC
1183}
1184
e3ff3591 1185void wxMacCoreGraphicsPathData::AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r )
50581042 1186{
35c72e51 1187 CGPathAddArcToPoint( m_path, NULL , (CGFloat) x1, (CGFloat) y1, (CGFloat) x2, (CGFloat) y2, (CGFloat) r);
50581042
SC
1188}
1189
e3ff3591 1190void wxMacCoreGraphicsPathData::AddPath( const wxGraphicsPathData* path )
50581042 1191{
783d8bdf 1192 CGPathAddPath( m_path , NULL, (CGPathRef) path->GetNativePath() );
50581042
SC
1193}
1194
b7b40adb 1195// closes the current subpath
e3ff3591 1196void wxMacCoreGraphicsPathData::CloseSubpath()
50581042 1197{
b7b40adb 1198 CGPathCloseSubpath( m_path );
50581042
SC
1199}
1200
b7b40adb 1201// gets the last point of the current path, (0,0) if not yet set
e3ff3591 1202void wxMacCoreGraphicsPathData::GetCurrentPoint( wxDouble* x, wxDouble* y) const
50581042 1203{
b7b40adb 1204 CGPoint p = CGPathGetCurrentPoint( m_path );
e3ff3591
SC
1205 *x = p.x;
1206 *y = p.y;
50581042
SC
1207}
1208
b7b40adb 1209// transforms each point of this path by the matrix
e3ff3591 1210void wxMacCoreGraphicsPathData::Transform( const wxGraphicsMatrixData* matrix )
50581042 1211{
783d8bdf
VZ
1212 CGMutablePathRef p = CGPathCreateMutable() ;
1213 CGPathAddPath( p, (CGAffineTransform*) matrix->GetNativeMatrix() , m_path );
1214 CGPathRelease( m_path );
1215 m_path = p;
50581042
SC
1216}
1217
b7b40adb 1218// gets the bounding box enclosing all points (possibly including control points)
e3ff3591 1219void wxMacCoreGraphicsPathData::GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) const
50581042 1220{
783d8bdf
VZ
1221 CGRect bounds = CGPathGetBoundingBox( m_path ) ;
1222 *x = bounds.origin.x;
1223 *y = bounds.origin.y;
1224 *w = bounds.size.width;
1225 *h = bounds.size.height;
50581042
SC
1226}
1227
e3ff3591 1228bool wxMacCoreGraphicsPathData::Contains( wxDouble x, wxDouble y, int fillStyle) const
50581042 1229{
35c72e51 1230 return CGPathContainsPoint( m_path, NULL, CGPointMake((CGFloat) x,(CGFloat) y), fillStyle == wxODDEVEN_RULE );
50581042
SC
1231}
1232
b7b40adb
SC
1233//
1234// Graphics Context
1235//
50581042 1236
b7b40adb
SC
1237//-----------------------------------------------------------------------------
1238// wxMacCoreGraphicsContext declaration
1239//-----------------------------------------------------------------------------
1240
1241class WXDLLEXPORT wxMacCoreGraphicsContext : public wxGraphicsContext
1242{
1243public:
6239ee05 1244 wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext, wxDouble width = 0, wxDouble height = 0 );
783d8bdf 1245
b7b40adb 1246 wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, WindowRef window );
783d8bdf 1247
b7b40adb 1248 wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, wxWindow* window );
783d8bdf 1249
b7b40adb 1250 wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer);
783d8bdf 1251
b7b40adb 1252 wxMacCoreGraphicsContext();
783d8bdf 1253
b7b40adb 1254 ~wxMacCoreGraphicsContext();
50581042 1255
783d8bdf 1256 void Init();
50581042 1257
6239ee05
SC
1258 // returns the size of the graphics context in device coordinates
1259 virtual void GetSize( wxDouble* width, wxDouble* height);
1260
1261 virtual void StartPage( wxDouble width, wxDouble height );
947f3b35 1262
6239ee05
SC
1263 virtual void EndPage();
1264
1265 virtual void Flush();
1266
b7b40adb
SC
1267 // push the current state of the context, ie the transformation matrix on a stack
1268 virtual void PushState();
50581042 1269
b7b40adb
SC
1270 // pops a stored state from the stack
1271 virtual void PopState();
50581042 1272
b7b40adb
SC
1273 // clips drawings to the region
1274 virtual void Clip( const wxRegion &region );
50581042 1275
b7b40adb
SC
1276 // clips drawings to the rect
1277 virtual void Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
783d8bdf 1278
b7b40adb
SC
1279 // resets the clipping to original extent
1280 virtual void ResetClip();
50581042 1281
b7b40adb 1282 virtual void * GetNativeContext();
783d8bdf 1283
277ccdaf 1284 bool SetLogicalFunction( int function );
b7b40adb
SC
1285 //
1286 // transformation
1287 //
783d8bdf 1288
b7b40adb
SC
1289 // translate
1290 virtual void Translate( wxDouble dx , wxDouble dy );
50581042 1291
b7b40adb
SC
1292 // scale
1293 virtual void Scale( wxDouble xScale , wxDouble yScale );
50581042 1294
b7b40adb
SC
1295 // rotate (radians)
1296 virtual void Rotate( wxDouble angle );
50581042 1297
783d8bdf
VZ
1298 // concatenates this transform with the current transform of this context
1299 virtual void ConcatTransform( const wxGraphicsMatrix& matrix );
50581042 1300
783d8bdf
VZ
1301 // sets the transform of this context
1302 virtual void SetTransform( const wxGraphicsMatrix& matrix );
50581042 1303
783d8bdf
VZ
1304 // gets the matrix of this context
1305 virtual wxGraphicsMatrix GetTransform() const;
b7b40adb
SC
1306 //
1307 // setting the paint
1308 //
783d8bdf 1309
b7b40adb 1310 // strokes along a path with the current pen
e3ff3591 1311 virtual void StrokePath( const wxGraphicsPath &path );
50581042 1312
b7b40adb 1313 // fills a path with the current brush
e3ff3591 1314 virtual void FillPath( const wxGraphicsPath &path, int fillStyle = wxODDEVEN_RULE );
50581042 1315
b7b40adb 1316 // draws a path by first filling and then stroking
e3ff3591 1317 virtual void DrawPath( const wxGraphicsPath &path, int fillStyle = wxODDEVEN_RULE );
b7b40adb
SC
1318
1319 virtual bool ShouldOffset() const
947f3b35 1320 {
b7b40adb 1321 int penwidth = 0 ;
a26b7ab2 1322 if ( !m_pen.IsNull() )
50581042 1323 {
783d8bdf 1324 penwidth = (int)((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->GetWidth();
b7b40adb
SC
1325 if ( penwidth == 0 )
1326 penwidth = 1;
50581042 1327 }
783d8bdf 1328 return ( penwidth % 2 ) == 1;
50581042 1329 }
b7b40adb
SC
1330 //
1331 // text
1332 //
783d8bdf 1333
b7b40adb 1334 virtual void DrawText( const wxString &str, wxDouble x, wxDouble y );
50581042 1335
b7b40adb 1336 virtual void DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle );
50581042 1337
b7b40adb
SC
1338 virtual void GetTextExtent( const wxString &text, wxDouble *width, wxDouble *height,
1339 wxDouble *descent, wxDouble *externalLeading ) const;
50581042 1340
b7b40adb 1341 virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const;
50581042 1342
b7b40adb
SC
1343 //
1344 // image support
1345 //
50581042 1346
b7b40adb 1347 virtual void DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
50581042 1348
5252d9e4
SC
1349 virtual void DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
1350
b7b40adb 1351 virtual void DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
50581042 1352
b7b40adb 1353 void SetNativeContext( CGContextRef cg );
783d8bdf 1354
b7b40adb
SC
1355 DECLARE_NO_COPY_CLASS(wxMacCoreGraphicsContext)
1356 DECLARE_DYNAMIC_CLASS(wxMacCoreGraphicsContext)
50581042 1357
b7b40adb
SC
1358private:
1359 void EnsureIsValid();
783d8bdf 1360
b7b40adb 1361 CGContextRef m_cgContext;
783d8bdf
VZ
1362 WindowRef m_windowRef;
1363 bool m_releaseContext;
549be226 1364 CGAffineTransform m_windowTransform;
6239ee05
SC
1365 wxDouble m_width;
1366 wxDouble m_height;
783d8bdf 1367
7a7697aa 1368 wxCFRef<HIShapeRef> m_clipRgn;
50581042
SC
1369};
1370
b7b40adb
SC
1371//-----------------------------------------------------------------------------
1372// device context implementation
1373//
1374// more and more of the dc functionality should be implemented by calling
1375// the appropricate wxMacCoreGraphicsContext, but we will have to do that step by step
1376// also coordinate conversions should be moved to native matrix ops
1377//-----------------------------------------------------------------------------
50581042 1378
b7b40adb
SC
1379// we always stock two context states, one at entry, to be able to preserve the
1380// state we were called with, the other one after changing to HI Graphics orientation
1381// (this one is used for getting back clippings etc)
50581042 1382
b7b40adb
SC
1383//-----------------------------------------------------------------------------
1384// wxMacCoreGraphicsContext implementation
1385//-----------------------------------------------------------------------------
50581042 1386
b7b40adb 1387IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsContext, wxGraphicsContext)
50581042 1388
6239ee05
SC
1389class wxQuartzOffsetHelper
1390{
1391public :
1392 wxQuartzOffsetHelper( CGContextRef cg , bool offset )
1393 {
1394 m_cg = cg;
1395 m_offset = offset;
1396 if ( m_offset )
35c72e51 1397 CGContextTranslateCTM( m_cg, (CGFloat) 0.5, (CGFloat) 0.5 );
6239ee05
SC
1398 }
1399 ~wxQuartzOffsetHelper( )
1400 {
1401 if ( m_offset )
35c72e51 1402 CGContextTranslateCTM( m_cg, (CGFloat) -0.5, (CGFloat) -0.5 );
6239ee05
SC
1403 }
1404public :
1405 CGContextRef m_cg;
1406 bool m_offset;
1407} ;
1408
b7b40adb
SC
1409void wxMacCoreGraphicsContext::Init()
1410{
1411 m_cgContext = NULL;
783d8bdf 1412 m_releaseContext = false;
b7b40adb 1413 m_windowRef = NULL;
6239ee05
SC
1414 m_width = 0;
1415 m_height = 0;
5252d9e4 1416 CGRect r = CGRectMake(0,0,0,0);
7a7697aa 1417 m_clipRgn.reset(HIShapeCreateWithRect(&r));
b7b40adb 1418}
50581042 1419
6239ee05 1420wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext, wxDouble width, wxDouble height ) : wxGraphicsContext(renderer)
b7b40adb 1421{
783d8bdf 1422 Init();
549be226 1423 SetNativeContext(cgcontext);
6239ee05
SC
1424 m_width = width;
1425 m_height = height;
b7b40adb 1426}
50581042 1427
b7b40adb
SC
1428wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, WindowRef window ): wxGraphicsContext(renderer)
1429{
783d8bdf
VZ
1430 Init();
1431 m_windowRef = window;
b7b40adb 1432}
50581042 1433
b7b40adb
SC
1434wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, wxWindow* window ): wxGraphicsContext(renderer)
1435{
783d8bdf 1436 Init();
5252d9e4 1437
549be226
SC
1438 int originX , originY;
1439 originX = originY = 0;
549be226 1440
1bd568fa 1441 Rect bounds = { 0,0,0,0 };
5252d9e4 1442#if defined( __LP64__ ) || defined(__WXCOCOA__)
1bd568fa 1443#else
5252d9e4
SC
1444 m_windowRef = (WindowRef) window->MacGetTopLevelWindowRef();
1445 window->MacWindowToRootWindow( &originX , &originY );
1bd568fa
SC
1446 GetWindowBounds( m_windowRef, kWindowContentRgn, &bounds );
1447#endif
549be226
SC
1448 m_windowTransform = CGAffineTransformMakeTranslation( 0 , bounds.bottom - bounds.top );
1449 m_windowTransform = CGAffineTransformScale( m_windowTransform , 1 , -1 );
1450 m_windowTransform = CGAffineTransformTranslate( m_windowTransform, originX, originY ) ;
b7b40adb 1451}
50581042 1452
b7b40adb
SC
1453wxMacCoreGraphicsContext::wxMacCoreGraphicsContext(wxGraphicsRenderer* renderer) : wxGraphicsContext(renderer)
1454{
783d8bdf 1455 Init();
b7b40adb 1456}
50581042 1457
b7b40adb
SC
1458wxMacCoreGraphicsContext::wxMacCoreGraphicsContext() : wxGraphicsContext(NULL)
1459{
783d8bdf 1460 Init();
b7b40adb
SC
1461 wxLogDebug(wxT("Illegal Constructor called"));
1462}
50581042 1463
b7b40adb
SC
1464wxMacCoreGraphicsContext::~wxMacCoreGraphicsContext()
1465{
549be226 1466 SetNativeContext(NULL);
b7b40adb 1467}
50581042 1468
6239ee05
SC
1469void wxMacCoreGraphicsContext::GetSize( wxDouble* width, wxDouble* height)
1470{
1471 *width = m_width;
1472 *height = m_height;
1473}
1474
1475
1476void wxMacCoreGraphicsContext::StartPage( wxDouble width, wxDouble height )
1477{
1478 CGRect r;
1479 if ( width != 0 && height != 0)
35c72e51 1480 r = CGRectMake( (CGFloat) 0.0 , (CGFloat) 0.0 , (CGFloat) width , (CGFloat) height );
6239ee05 1481 else
35c72e51 1482 r = CGRectMake( (CGFloat) 0.0 , (CGFloat) 0.0 , (CGFloat) m_width , (CGFloat) m_height );
947f3b35 1483
6239ee05
SC
1484 CGContextBeginPage(m_cgContext, &r );
1485// CGContextTranslateCTM( m_cgContext , 0 , height == 0 ? m_height : height );
1486// CGContextScaleCTM( m_cgContext , 1 , -1 );
1487}
947f3b35 1488
6239ee05
SC
1489void wxMacCoreGraphicsContext::EndPage()
1490{
1491 CGContextEndPage(m_cgContext);
1492}
1493
1494void wxMacCoreGraphicsContext::Flush()
1495{
1496 CGContextFlush(m_cgContext);
1497}
1498
b7b40adb
SC
1499void wxMacCoreGraphicsContext::EnsureIsValid()
1500{
783d8bdf
VZ
1501 if ( !m_cgContext )
1502 {
947f3b35 1503 OSStatus status =
5252d9e4 1504#if ! ( defined( __LP64__ ) || defined(__WXCOCOA__) )
6239ee05
SC
1505 QDBeginCGContext( GetWindowPort( m_windowRef ) , &m_cgContext );
1506#else
1507 paramErr;
1508#endif
947f3b35
VZ
1509 if ( status != noErr )
1510 {
1511 wxFAIL_MSG("Cannot nest wxDCs on the same window");
1512 }
549be226
SC
1513
1514 CGContextConcatCTM( m_cgContext, m_windowTransform );
947f3b35
VZ
1515 CGContextSaveGState( m_cgContext );
1516 m_releaseContext = true;
1517 if ( !HIShapeIsEmpty(m_clipRgn) )
1518 {
1acf0e5c 1519 // the clip region is in device coordinates, so we convert this again to user coordinates
7a7697aa 1520 wxCFRef<HIMutableShapeRef> hishape( HIShapeCreateMutableCopy( m_clipRgn ) );
1acf0e5c
SC
1521 CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero,m_windowTransform);
1522 HIShapeOffset( hishape, -transformedOrigin.x, -transformedOrigin.y );
947f3b35
VZ
1523 HIShapeReplacePathInCGContext( hishape, m_cgContext );
1524 CGContextClip( m_cgContext );
1525 }
1526 CGContextSaveGState( m_cgContext );
1527 }
b7b40adb 1528}
50581042 1529
6239ee05
SC
1530// TODO test whether the private CGContextSetCompositeOperation works under 10.3 (using NSCompositingModes)
1531
277ccdaf
SC
1532bool wxMacCoreGraphicsContext::SetLogicalFunction( int function )
1533{
1534 if (m_logicalFunction == function)
1535 return true;
1536
1537 EnsureIsValid();
947f3b35 1538
277ccdaf 1539 bool retval = false;
dbe4a80c
SC
1540 bool shouldAntiAlias = true;
1541 CGBlendMode mode = kCGBlendModeNormal;
947f3b35 1542
5252d9e4 1543#if defined(__WXMAC__) && ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 )
dbe4a80c 1544 if ( UMAGetSystemVersion() >= 0x1050 )
277ccdaf
SC
1545 {
1546 retval = true;
dbe4a80c
SC
1547 switch ( function )
1548 {
1549 // TODO find best corresponding porter duff modes
1550 case wxCOPY :
1551 mode = kCGBlendModeCopy;
1552 break;
1553 case wxCLEAR :
1554 mode = kCGBlendModeClear;
1555 break;
1556 case wxXOR :
1557 mode = kCGBlendModeXOR;
1558 shouldAntiAlias = false;
947f3b35 1559 break;
dbe4a80c
SC
1560 default :
1561 retval = false;
1562 break;
1563 }
277ccdaf 1564 }
dbe4a80c
SC
1565 else
1566#endif
277ccdaf 1567 {
dbe4a80c
SC
1568 if ( function == wxCOPY )
1569 {
1570 retval = true;
1571 }
1572 else if ( function == wxINVERT || function == wxXOR )
1573 {
1574 // change color to white
1575 mode = kCGBlendModeExclusion;
1576 shouldAntiAlias = false;
1577 retval = true;
1578 }
277ccdaf 1579 }
947f3b35 1580
277ccdaf 1581 if (retval)
dbe4a80c 1582 {
277ccdaf 1583 m_logicalFunction = function;
dbe4a80c
SC
1584 CGContextSetBlendMode( m_cgContext, mode );
1585 CGContextSetShouldAntialias(m_cgContext, shouldAntiAlias);
1586 }
277ccdaf
SC
1587 return retval ;
1588}
50581042 1589
b7b40adb
SC
1590void wxMacCoreGraphicsContext::Clip( const wxRegion &region )
1591{
5252d9e4 1592#ifdef __WXMAC__
783d8bdf
VZ
1593 if( m_cgContext )
1594 {
82c126e5 1595 HIShapeReplacePathInCGContext( region.GetWXHRGN() , m_cgContext );
783d8bdf 1596 CGContextClip( m_cgContext );
783d8bdf
VZ
1597 }
1598 else
1599 {
1acf0e5c
SC
1600 // this offsetting to device coords is not really correct, but since we cannot apply affine transforms
1601 // to regions we try at least to have correct translations
82c126e5 1602 HIMutableShapeRef mutableShape = HIShapeCreateMutableCopy( region.GetWXHRGN() );
947f3b35 1603
1acf0e5c
SC
1604 CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero, m_windowTransform );
1605 HIShapeOffset( mutableShape, transformedOrigin.x, transformedOrigin.y );
7a7697aa 1606 m_clipRgn.reset(mutableShape);
783d8bdf 1607 }
5252d9e4 1608#endif
b7b40adb 1609}
50581042 1610
b7b40adb
SC
1611// clips drawings to the rect
1612void wxMacCoreGraphicsContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
1613{
35c72e51 1614 CGRect r = CGRectMake( (CGFloat) x , (CGFloat) y , (CGFloat) w , (CGFloat) h );
783d8bdf
VZ
1615 if ( m_cgContext )
1616 {
1617 CGContextClipToRect( m_cgContext, r );
1618 }
1619 else
1620 {
947f3b35 1621 // the clipping itself must be stored as device coordinates, otherwise
1acf0e5c
SC
1622 // we cannot apply it back correctly
1623 r.origin= CGPointApplyAffineTransform( r.origin, m_windowTransform );
7a7697aa 1624 m_clipRgn.reset(HIShapeCreateWithRect(&r));
783d8bdf
VZ
1625 }
1626}
1627
1628 // resets the clipping to original extent
b7b40adb
SC
1629void wxMacCoreGraphicsContext::ResetClip()
1630{
783d8bdf
VZ
1631 if ( m_cgContext )
1632 {
a7868cdf
SC
1633 // there is no way for clearing the clip, we can only revert to the stored
1634 // state, but then we have to make sure everything else is NOT restored
1635 CGAffineTransform transform = CGContextGetCTM( m_cgContext );
783d8bdf
VZ
1636 CGContextRestoreGState( m_cgContext );
1637 CGContextSaveGState( m_cgContext );
a7868cdf
SC
1638 CGAffineTransform transformNew = CGContextGetCTM( m_cgContext );
1639 transformNew = CGAffineTransformInvert( transformNew ) ;
1640 CGContextConcatCTM( m_cgContext, transformNew);
1641 CGContextConcatCTM( m_cgContext, transform);
783d8bdf
VZ
1642 }
1643 else
1644 {
5252d9e4 1645 CGRect r = CGRectMake(0,0,0,0);
7a7697aa 1646 m_clipRgn.reset(HIShapeCreateWithRect(&r));
783d8bdf 1647 }
b7b40adb 1648}
50581042 1649
e3ff3591 1650void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath &path )
b7b40adb 1651{
a26b7ab2 1652 if ( m_pen.IsNull() )
b7b40adb 1653 return ;
50581042 1654
783d8bdf
VZ
1655 EnsureIsValid();
1656
6239ee05 1657 wxQuartzOffsetHelper helper( m_cgContext , ShouldOffset() );
50581042 1658
a26b7ab2 1659 ((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->Apply(this);
e3ff3591 1660 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
b7b40adb 1661 CGContextStrokePath( m_cgContext );
b7b40adb 1662}
50581042 1663
e3ff3591 1664void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , int fillStyle )
783d8bdf 1665{
a26b7ab2 1666 if ( !m_brush.IsNull() && ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
b7b40adb
SC
1667 {
1668 // when using shading, we cannot draw pen and brush at the same time
1669 // revert to the base implementation of first filling and then stroking
1670 wxGraphicsContext::DrawPath( path, fillStyle );
1671 return;
1672 }
783d8bdf 1673
b7b40adb 1674 CGPathDrawingMode mode = kCGPathFill ;
a26b7ab2 1675 if ( m_brush.IsNull() )
b7b40adb 1676 {
a26b7ab2 1677 if ( m_pen.IsNull() )
b7b40adb
SC
1678 return;
1679 else
1680 mode = kCGPathStroke;
1681 }
1682 else
1683 {
a26b7ab2 1684 if ( m_pen.IsNull() )
b7b40adb
SC
1685 {
1686 if ( fillStyle == wxODDEVEN_RULE )
1687 mode = kCGPathEOFill;
1688 else
1689 mode = kCGPathFill;
1690 }
1691 else
1692 {
1693 if ( fillStyle == wxODDEVEN_RULE )
1694 mode = kCGPathEOFillStroke;
1695 else
1696 mode = kCGPathFillStroke;
1697 }
1698 }
783d8bdf
VZ
1699
1700 EnsureIsValid();
50581042 1701
a26b7ab2
SC
1702 if ( !m_brush.IsNull() )
1703 ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->Apply(this);
1704 if ( !m_pen.IsNull() )
1705 ((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->Apply(this);
50581042 1706
6239ee05 1707 wxQuartzOffsetHelper helper( m_cgContext , ShouldOffset() );
50581042 1708
e3ff3591 1709 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
b7b40adb 1710 CGContextDrawPath( m_cgContext , mode );
b7b40adb 1711}
50581042 1712
e3ff3591 1713void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath &path , int fillStyle )
b7b40adb 1714{
a26b7ab2 1715 if ( m_brush.IsNull() )
b7b40adb 1716 return;
783d8bdf
VZ
1717
1718 EnsureIsValid();
1719
a26b7ab2 1720 if ( ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
b7b40adb
SC
1721 {
1722 CGContextSaveGState( m_cgContext );
e3ff3591 1723 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
b7b40adb 1724 CGContextClip( m_cgContext );
a26b7ab2 1725 CGContextDrawShading( m_cgContext, ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->GetShading() );
b7b40adb
SC
1726 CGContextRestoreGState( m_cgContext);
1727 }
1728 else
783d8bdf 1729 {
a26b7ab2 1730 ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->Apply(this);
e3ff3591 1731 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
b7b40adb
SC
1732 if ( fillStyle == wxODDEVEN_RULE )
1733 CGContextEOFillPath( m_cgContext );
1734 else
1735 CGContextFillPath( m_cgContext );
50581042
SC
1736 }
1737}
1738
b7b40adb 1739void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg )
50581042 1740{
b7b40adb
SC
1741 // we allow either setting or clearing but not replacing
1742 wxASSERT( m_cgContext == NULL || cg == NULL );
50581042 1743
549be226
SC
1744 if ( m_cgContext )
1745 {
1746 // TODO : when is this necessary - should we add a Flush() method ? CGContextSynchronize( m_cgContext );
1747 CGContextRestoreGState( m_cgContext );
1748 CGContextRestoreGState( m_cgContext );
1749 if ( m_releaseContext )
6239ee05 1750 {
5252d9e4 1751#if ! ( defined( __LP64__ ) || defined(__WXCOCOA__) )
549be226 1752 QDEndCGContext( GetWindowPort( m_windowRef ) , &m_cgContext);
6239ee05
SC
1753#endif
1754 }
549be226
SC
1755 else
1756 CGContextRelease(m_cgContext);
1757 }
1758
1759
b7b40adb 1760 m_cgContext = cg;
549be226
SC
1761
1762 // FIXME: This check is needed because currently we need to use a DC/GraphicsContext
783d8bdf 1763 // in order to get font properties, like wxFont::GetPixelSize, but since we don't have
549be226
SC
1764 // a native window attached to use, I create a wxGraphicsContext with a NULL CGContextRef
1765 // for this one operation.
783d8bdf 1766
549be226 1767 // When wxFont::GetPixelSize on Mac no longer needs a graphics context, this check
783d8bdf 1768 // can be removed.
549be226
SC
1769 if (m_cgContext)
1770 {
1771 CGContextRetain(m_cgContext);
1772 CGContextSaveGState( m_cgContext );
5252d9e4 1773 CGContextSetTextMatrix( m_cgContext, CGAffineTransformIdentity );
549be226 1774 CGContextSaveGState( m_cgContext );
783d8bdf 1775 m_releaseContext = false;
549be226 1776 }
b7b40adb 1777}
50581042 1778
783d8bdf 1779void wxMacCoreGraphicsContext::Translate( wxDouble dx , wxDouble dy )
b7b40adb 1780{
783d8bdf 1781 if ( m_cgContext )
35c72e51 1782 CGContextTranslateCTM( m_cgContext, (CGFloat) dx, (CGFloat) dy );
549be226 1783 else
35c72e51 1784 m_windowTransform = CGAffineTransformTranslate(m_windowTransform, (CGFloat) dx, (CGFloat) dy);
b7b40adb 1785}
50581042 1786
b7b40adb
SC
1787void wxMacCoreGraphicsContext::Scale( wxDouble xScale , wxDouble yScale )
1788{
783d8bdf 1789 if ( m_cgContext )
35c72e51 1790 CGContextScaleCTM( m_cgContext , (CGFloat) xScale , (CGFloat) yScale );
549be226 1791 else
35c72e51 1792 m_windowTransform = CGAffineTransformScale(m_windowTransform, (CGFloat) xScale, (CGFloat) yScale);
b7b40adb 1793}
50581042 1794
b7b40adb
SC
1795void wxMacCoreGraphicsContext::Rotate( wxDouble angle )
1796{
783d8bdf 1797 if ( m_cgContext )
35c72e51 1798 CGContextRotateCTM( m_cgContext , (CGFloat) angle );
549be226 1799 else
35c72e51 1800 m_windowTransform = CGAffineTransformRotate(m_windowTransform, (CGFloat) angle);
b7b40adb 1801}
50581042 1802
783d8bdf 1803void wxMacCoreGraphicsContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
b7b40adb 1804{
5252d9e4
SC
1805 wxGraphicsBitmap bitmap = GetRenderer()->CreateBitmap(bmp);
1806 DrawBitmap(bitmap, x, y, w, h);
1807}
783d8bdf 1808
5252d9e4
SC
1809void wxMacCoreGraphicsContext::DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
1810{
1811 EnsureIsValid();
1812#ifdef __WXMAC__
35c72e51
SC
1813 wxMacCoreGraphicsBitmapData* refdata =static_cast<wxMacCoreGraphicsBitmapData*>(bmp.GetRefData());
1814 CGImageRef image = refdata->GetBitmap();
1815 CGRect r = CGRectMake( (CGFloat) x , (CGFloat) y , (CGFloat) w , (CGFloat) h );
1816 if ( refdata->IsMonochrome() == 1 )
5f547a58
SC
1817 {
1818 // is is a mask, the '1' in the mask tell where to draw the current brush
1819 if ( !m_brush.IsNull() )
1820 {
1821 if ( ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
1822 {
1823 // TODO clip to mask
1824 /*
1825 CGContextSaveGState( m_cgContext );
1826 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
1827 CGContextClip( m_cgContext );
1828 CGContextDrawShading( m_cgContext, ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->GetShading() );
1829 CGContextRestoreGState( m_cgContext);
1830 */
1831 }
1832 else
1833 {
1834 ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->Apply(this);
276ee533 1835 wxMacDrawCGImage( m_cgContext , &r , image );
5f547a58
SC
1836 }
1837 }
1838 }
1839 else
1840 {
276ee533 1841 wxMacDrawCGImage( m_cgContext , &r , image );
5f547a58 1842 }
5252d9e4 1843#endif
b7b40adb 1844}
50581042 1845
783d8bdf 1846void wxMacCoreGraphicsContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
b7b40adb 1847{
783d8bdf
VZ
1848 EnsureIsValid();
1849
35c72e51 1850 CGRect r = CGRectMake( (CGFloat) 0.0 , (CGFloat) 0.0 , (CGFloat) w , (CGFloat) h );
b7b40adb 1851 CGContextSaveGState( m_cgContext );
35c72e51 1852 CGContextTranslateCTM( m_cgContext,(CGFloat) x ,(CGFloat) (y + h) );
b7b40adb 1853 CGContextScaleCTM( m_cgContext, 1, -1 );
5252d9e4 1854#ifdef __WXMAC__
b7b40adb
SC
1855 PlotIconRefInContext( m_cgContext , &r , kAlignNone , kTransformNone ,
1856 NULL , kPlotIconRefNormalFlags , MAC_WXHICON( icon.GetHICON() ) );
5252d9e4 1857#endif
b7b40adb
SC
1858 CGContextRestoreGState( m_cgContext );
1859}
50581042 1860
b7b40adb
SC
1861void wxMacCoreGraphicsContext::PushState()
1862{
783d8bdf
VZ
1863 EnsureIsValid();
1864
b7b40adb
SC
1865 CGContextSaveGState( m_cgContext );
1866}
50581042 1867
783d8bdf 1868void wxMacCoreGraphicsContext::PopState()
b7b40adb 1869{
783d8bdf
VZ
1870 EnsureIsValid();
1871
b7b40adb 1872 CGContextRestoreGState( m_cgContext );
50581042
SC
1873}
1874
783d8bdf 1875void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y )
50581042 1876{
1bd568fa
SC
1877 if ( m_font.IsNull() )
1878 return;
947f3b35 1879
1bd568fa 1880 EnsureIsValid();
d2d8b4db 1881#if wxMAC_USE_CORE_TEXT
c07e1e2c
SC
1882 if ( UMAGetSystemVersion() >= 0x1050 )
1883 {
1884 wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
dbe4a80c 1885 wxCFStringRef text(str, wxLocale::GetSystemEncoding() );
c07e1e2c 1886 CTFontRef font = fref->GetCTFont();
5252d9e4 1887 CGColorRef col = wxMacCreateCGColor( fref->GetColour() );
c07e1e2c 1888 CTUnderlineStyle ustyle = fref->GetUnderlined() ? kCTUnderlineStyleSingle : kCTUnderlineStyleNone ;
947f3b35 1889 wxCFRef<CFNumberRef> underlined( CFNumberCreate(NULL, kCFNumberSInt32Type, &ustyle) );
a6ab887b 1890 CFStringRef keys[] = { kCTFontAttributeName , kCTForegroundColorAttributeName, kCTUnderlineStyleAttributeName };
c07e1e2c 1891 CFTypeRef values[] = { font, col, underlined };
947f3b35 1892 wxCFRef<CFDictionaryRef> attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**) &keys, (const void**) &values,
c07e1e2c
SC
1893 WXSIZEOF( keys ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) );
1894 wxCFRef<CFAttributedStringRef> attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, attributes) );
1895 wxCFRef<CTLineRef> line( CTLineCreateWithAttributedString(attrtext) );
947f3b35 1896
c07e1e2c 1897 y += CTFontGetAscent(font);
947f3b35 1898
c07e1e2c
SC
1899 CGContextSaveGState(m_cgContext);
1900 CGContextTranslateCTM(m_cgContext, x, y);
1901 CGContextScaleCTM(m_cgContext, 1, -1);
1902 CGContextSetTextPosition(m_cgContext, 0, 0);
1903 CTLineDraw( line, m_cgContext );
1904 CGContextRestoreGState(m_cgContext);
5252d9e4 1905 CFRelease( col );
c07e1e2c
SC
1906 return;
1907 }
1908#endif
1909#if wxMAC_USE_ATSU_TEXT
1910 {
1911 DrawText(str, x, y, 0.0);
1912 return;
1913 }
1914#endif
0fa6a0ac 1915#if wxMAC_USE_CG_TEXT
1bd568fa
SC
1916 // TODO core graphics text implementation here
1917#endif
50581042
SC
1918}
1919
783d8bdf 1920void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle )
50581042 1921{
a26b7ab2 1922 if ( m_font.IsNull() )
b7b40adb 1923 return;
783d8bdf
VZ
1924
1925 EnsureIsValid();
d2d8b4db 1926#if wxMAC_USE_CORE_TEXT
c07e1e2c
SC
1927 if ( UMAGetSystemVersion() >= 0x1050 )
1928 {
1929 // default implementation takes care of rotation and calls non rotated DrawText afterwards
1930 wxGraphicsContext::DrawText( str, x, y, angle );
1931 return;
1932 }
1933#endif
1934#if wxMAC_USE_ATSU_TEXT
1935 {
1936 OSStatus status = noErr;
1937 ATSUTextLayout atsuLayout;
dbe4a80c
SC
1938 wxMacUniCharBuffer unibuf( str );
1939 UniCharCount chars = unibuf.GetChars();
1940
c07e1e2c 1941 ATSUStyle style = (((wxMacCoreGraphicsFontData*)m_font.GetRefData())->GetATSUStyle());
dbe4a80c 1942 status = ::ATSUCreateTextLayoutWithTextPtr( unibuf.GetBuffer() , 0 , chars , chars , 1 ,
c07e1e2c 1943 &chars , &style , &atsuLayout );
947f3b35 1944
c07e1e2c 1945 wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the rotated text") );
947f3b35 1946
c07e1e2c
SC
1947 status = ::ATSUSetTransientFontMatching( atsuLayout , true );
1948 wxASSERT_MSG( status == noErr , wxT("couldn't setup transient font matching") );
947f3b35 1949
c07e1e2c
SC
1950 int iAngle = int( angle * RAD2DEG );
1951 if ( abs(iAngle) > 0 )
50581042 1952 {
c07e1e2c
SC
1953 Fixed atsuAngle = IntToFixed( iAngle );
1954 ATSUAttributeTag atsuTags[] =
1955 {
1956 kATSULineRotationTag ,
1957 };
1958 ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1959 {
1960 sizeof( Fixed ) ,
1961 };
1962 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1963 {
1964 &atsuAngle ,
1965 };
1966 status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag),
1967 atsuTags, atsuSizes, atsuValues );
1968 }
947f3b35 1969
50581042 1970 {
c07e1e2c
SC
1971 ATSUAttributeTag atsuTags[] =
1972 {
1973 kATSUCGContextTag ,
1974 };
1975 ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1976 {
1977 sizeof( CGContextRef ) ,
1978 };
1979 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1980 {
1981 &m_cgContext ,
1982 };
1983 status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag),
1984 atsuTags, atsuSizes, atsuValues );
1985 }
947f3b35 1986
c07e1e2c
SC
1987 ATSUTextMeasurement textBefore, textAfter;
1988 ATSUTextMeasurement ascent, descent;
947f3b35 1989
c07e1e2c
SC
1990 status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1991 &textBefore , &textAfter, &ascent , &descent );
947f3b35 1992
c07e1e2c 1993 wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
947f3b35 1994
c07e1e2c
SC
1995 Rect rect;
1996 x += (int)(sin(angle) * FixedToInt(ascent));
1997 y += (int)(cos(angle) * FixedToInt(ascent));
947f3b35 1998
c07e1e2c
SC
1999 status = ::ATSUMeasureTextImage( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
2000 IntToFixed(x) , IntToFixed(y) , &rect );
2001 wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
947f3b35 2002
c07e1e2c 2003 CGContextSaveGState(m_cgContext);
35c72e51 2004 CGContextTranslateCTM(m_cgContext, (CGFloat) x, (CGFloat) y);
c07e1e2c
SC
2005 CGContextScaleCTM(m_cgContext, 1, -1);
2006 status = ::ATSUDrawText( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
2007 IntToFixed(0) , IntToFixed(0) );
947f3b35 2008
c07e1e2c 2009 wxASSERT_MSG( status == noErr , wxT("couldn't draw the rotated text") );
947f3b35 2010
c07e1e2c 2011 CGContextRestoreGState(m_cgContext);
947f3b35 2012
c07e1e2c 2013 ::ATSUDisposeTextLayout(atsuLayout);
947f3b35 2014
c07e1e2c
SC
2015 return;
2016 }
2017#endif
0fa6a0ac 2018#if wxMAC_USE_CG_TEXT
1bd568fa
SC
2019 // default implementation takes care of rotation and calls non rotated DrawText afterwards
2020 wxGraphicsContext::DrawText( str, x, y, angle );
2021#endif
50581042 2022}
783d8bdf 2023
50581042
SC
2024void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
2025 wxDouble *descent, wxDouble *externalLeading ) const
2026{
a26b7ab2 2027 wxCHECK_RET( !m_font.IsNull(), wxT("wxDC(cg)::DoGetTextExtent - no valid font set") );
50581042 2028
6239ee05
SC
2029 if ( width )
2030 *width = 0;
2031 if ( height )
2032 *height = 0;
2033 if ( descent )
2034 *descent = 0;
2035 if ( externalLeading )
2036 *externalLeading = 0;
947f3b35 2037
6239ee05
SC
2038 if (str.empty())
2039 return;
2040
d2d8b4db 2041#if wxMAC_USE_CORE_TEXT
c07e1e2c
SC
2042 if ( UMAGetSystemVersion() >= 0x1050 )
2043 {
2044 wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
2045 CTFontRef font = fref->GetCTFont();
2046
dbe4a80c 2047 wxCFStringRef text(str, wxLocale::GetSystemEncoding() );
c07e1e2c
SC
2048 CFStringRef keys[] = { kCTFontAttributeName };
2049 CFTypeRef values[] = { font };
947f3b35 2050 wxCFRef<CFDictionaryRef> attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**) &keys, (const void**) &values,
c07e1e2c
SC
2051 WXSIZEOF( keys ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) );
2052 wxCFRef<CFAttributedStringRef> attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, attributes) );
2053 wxCFRef<CTLineRef> line( CTLineCreateWithAttributedString(attrtext) );
947f3b35 2054
c07e1e2c 2055 CGFloat w, a, d, l;
947f3b35 2056
c07e1e2c 2057 w = CTLineGetTypographicBounds(line, &a, &d, &l) ;
947f3b35 2058
c07e1e2c
SC
2059 if ( height )
2060 *height = a+d+l;
2061 if ( descent )
2062 *descent = d;
2063 if ( externalLeading )
2064 *externalLeading = l;
2065 if ( width )
2066 *width = w;
2067 return;
2068 }
2069#endif
2070#if wxMAC_USE_ATSU_TEXT
2071 {
2072 OSStatus status = noErr;
947f3b35 2073
c07e1e2c 2074 ATSUTextLayout atsuLayout;
dbe4a80c
SC
2075 wxMacUniCharBuffer unibuf( str );
2076 UniCharCount chars = unibuf.GetChars();
947f3b35 2077
c07e1e2c 2078 ATSUStyle style = (((wxMacCoreGraphicsFontData*)m_font.GetRefData())->GetATSUStyle());
dbe4a80c 2079 status = ::ATSUCreateTextLayoutWithTextPtr( unibuf.GetBuffer() , 0 , chars , chars , 1 ,
c07e1e2c 2080 &chars , &style , &atsuLayout );
947f3b35 2081
c07e1e2c 2082 wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the text") );
947f3b35 2083
eb61203f
SC
2084 status = ::ATSUSetTransientFontMatching( atsuLayout , true );
2085 wxASSERT_MSG( status == noErr , wxT("couldn't setup transient font matching") );
2086
c07e1e2c
SC
2087 ATSUTextMeasurement textBefore, textAfter;
2088 ATSUTextMeasurement textAscent, textDescent;
947f3b35 2089
c07e1e2c
SC
2090 status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
2091 &textBefore , &textAfter, &textAscent , &textDescent );
947f3b35 2092
c07e1e2c
SC
2093 if ( height )
2094 *height = FixedToInt(textAscent + textDescent);
2095 if ( descent )
2096 *descent = FixedToInt(textDescent);
2097 if ( externalLeading )
2098 *externalLeading = 0;
2099 if ( width )
2100 *width = FixedToInt(textAfter - textBefore);
947f3b35 2101
c07e1e2c 2102 ::ATSUDisposeTextLayout(atsuLayout);
dbe4a80c 2103
c07e1e2c
SC
2104 return;
2105 }
b9d495a0 2106#endif
0fa6a0ac 2107#if wxMAC_USE_CG_TEXT
1bd568fa
SC
2108 // TODO core graphics text implementation here
2109#endif
50581042
SC
2110}
2111
783d8bdf 2112void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const
50581042
SC
2113{
2114 widths.Empty();
2115 widths.Add(0, text.length());
2116
2117 if (text.empty())
2118 return;
2119
d2d8b4db 2120#if wxMAC_USE_CORE_TEXT
c07e1e2c
SC
2121 {
2122 wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
2123 CTFontRef font = fref->GetCTFont();
947f3b35 2124
dbe4a80c 2125 wxCFStringRef t(text, wxLocale::GetSystemEncoding() );
c07e1e2c
SC
2126 CFStringRef keys[] = { kCTFontAttributeName };
2127 CFTypeRef values[] = { font };
947f3b35 2128 wxCFRef<CFDictionaryRef> attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**) &keys, (const void**) &values,
c07e1e2c
SC
2129 WXSIZEOF( keys ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) );
2130 wxCFRef<CFAttributedStringRef> attrtext( CFAttributedStringCreate(kCFAllocatorDefault, t, attributes) );
2131 wxCFRef<CTLineRef> line( CTLineCreateWithAttributedString(attrtext) );
947f3b35 2132
c07e1e2c
SC
2133 int chars = text.length();
2134 for ( int pos = 0; pos < (int)chars; pos ++ )
2135 {
2136 widths[pos] = CTLineGetOffsetForStringIndex( line, pos+1 , NULL )+0.5;
2137 }
947f3b35 2138
c07e1e2c
SC
2139 return;
2140 }
2141#endif
2142#if wxMAC_USE_ATSU_TEXT
2143 {
eb61203f 2144 OSStatus status = noErr;
c07e1e2c 2145 ATSUTextLayout atsuLayout;
dbe4a80c
SC
2146 wxMacUniCharBuffer unibuf( text );
2147 UniCharCount chars = unibuf.GetChars();
947f3b35 2148
c07e1e2c 2149 ATSUStyle style = (((wxMacCoreGraphicsFontData*)m_font.GetRefData())->GetATSUStyle());
eb61203f 2150 status = ::ATSUCreateTextLayoutWithTextPtr( unibuf.GetBuffer() , 0 , chars , chars , 1 ,
c07e1e2c 2151 &chars , &style , &atsuLayout );
947f3b35 2152
eb61203f 2153 wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the text") );
947f3b35 2154
eb61203f
SC
2155 status = ::ATSUSetTransientFontMatching( atsuLayout , true );
2156 wxASSERT_MSG( status == noErr , wxT("couldn't setup transient font matching") );
2157
cb751f46
SC
2158// new implementation from JS, keep old one just in case
2159#if 0
c07e1e2c
SC
2160 for ( int pos = 0; pos < (int)chars; pos ++ )
2161 {
2162 unsigned long actualNumberOfBounds = 0;
2163 ATSTrapezoid glyphBounds;
947f3b35 2164
c07e1e2c
SC
2165 // We get a single bound, since the text should only require one. If it requires more, there is an issue
2166 OSStatus result;
2167 result = ATSUGetGlyphBounds( atsuLayout, 0, 0, kATSUFromTextBeginning, pos + 1,
2168 kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds );
2169 if (result != noErr || actualNumberOfBounds != 1 )
2170 return;
947f3b35 2171
c07e1e2c
SC
2172 widths[pos] = FixedToInt( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
2173 //unsigned char uch = s[i];
2174 }
cb751f46
SC
2175#else
2176 ATSLayoutRecord *layoutRecords = NULL;
2177 ItemCount glyphCount = 0;
2178
2179 // Get the glyph extents
2180 OSStatus err = ::ATSUDirectGetLayoutDataArrayPtrFromTextLayout(atsuLayout,
2181 0,
2182 kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
2183 (void **)
2184 &layoutRecords,
2185 &glyphCount);
2186 wxASSERT(glyphCount == (text.length()+1));
2187
2188 if ( err == noErr && glyphCount == (text.length()+1))
2189 {
2190 for ( int pos = 1; pos < (int)glyphCount ; pos ++ )
2191 {
2192 widths[pos-1] = FixedToInt( layoutRecords[pos].realPos );
2193 }
2194 }
2195
2196 ::ATSUDirectReleaseLayoutDataArrayPtr(NULL,
2197 kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
2198 (void **) &layoutRecords);
2199#endif
c07e1e2c 2200 ::ATSUDisposeTextLayout(atsuLayout);
c07e1e2c 2201 }
b9d495a0 2202#endif
0fa6a0ac 2203#if wxMAC_USE_CG_TEXT
1bd568fa
SC
2204 // TODO core graphics text implementation here
2205#endif
50581042
SC
2206}
2207
783d8bdf 2208void * wxMacCoreGraphicsContext::GetNativeContext()
50581042 2209{
783d8bdf 2210 return m_cgContext;
b7b40adb 2211}
50581042 2212
b7b40adb 2213// concatenates this transform with the current transform of this context
e3ff3591 2214void wxMacCoreGraphicsContext::ConcatTransform( const wxGraphicsMatrix& matrix )
b7b40adb 2215{
549be226
SC
2216 if ( m_cgContext )
2217 CGContextConcatCTM( m_cgContext, *(CGAffineTransform*) matrix.GetNativeMatrix());
2218 else
2219 m_windowTransform = CGAffineTransformConcat(m_windowTransform, *(CGAffineTransform*) matrix.GetNativeMatrix());
b7b40adb 2220}
50581042 2221
b7b40adb 2222// sets the transform of this context
e3ff3591 2223void wxMacCoreGraphicsContext::SetTransform( const wxGraphicsMatrix& matrix )
b7b40adb 2224{
549be226
SC
2225 if ( m_cgContext )
2226 {
2227 CGAffineTransform transform = CGContextGetCTM( m_cgContext );
2228 transform = CGAffineTransformInvert( transform ) ;
2229 CGContextConcatCTM( m_cgContext, transform);
2230 CGContextConcatCTM( m_cgContext, *(CGAffineTransform*) matrix.GetNativeMatrix());
2231 }
2232 else
2233 {
2234 m_windowTransform = *(CGAffineTransform*) matrix.GetNativeMatrix();
2235 }
b7b40adb 2236}
50581042 2237
b7b40adb 2238// gets the matrix of this context
e3ff3591 2239wxGraphicsMatrix wxMacCoreGraphicsContext::GetTransform() const
b7b40adb 2240{
daa6105f 2241 wxGraphicsMatrix m = CreateMatrix();
549be226
SC
2242 *((CGAffineTransform*) m.GetNativeMatrix()) = ( m_cgContext == NULL ? m_windowTransform :
2243 CGContextGetCTM( m_cgContext ));
daa6105f 2244 return m;
b7b40adb 2245}
50581042 2246
b7b40adb
SC
2247//
2248// Renderer
2249//
50581042 2250
b7b40adb
SC
2251//-----------------------------------------------------------------------------
2252// wxMacCoreGraphicsRenderer declaration
2253//-----------------------------------------------------------------------------
50581042 2254
b7b40adb
SC
2255class WXDLLIMPEXP_CORE wxMacCoreGraphicsRenderer : public wxGraphicsRenderer
2256{
2257public :
2258 wxMacCoreGraphicsRenderer() {}
50581042 2259
b7b40adb
SC
2260 virtual ~wxMacCoreGraphicsRenderer() {}
2261
783d8bdf
VZ
2262 // Context
2263
2264 virtual wxGraphicsContext * CreateContext( const wxWindowDC& dc);
888dde65 2265 virtual wxGraphicsContext * CreateContext( const wxMemoryDC& dc);
0b822969 2266 virtual wxGraphicsContext * CreateContext( const wxPrinterDC& dc);
b7b40adb 2267
783d8bdf 2268 virtual wxGraphicsContext * CreateContextFromNativeContext( void * context );
b7b40adb 2269
783d8bdf 2270 virtual wxGraphicsContext * CreateContextFromNativeWindow( void * window );
b7b40adb 2271
783d8bdf 2272 virtual wxGraphicsContext * CreateContext( wxWindow* window );
947f3b35 2273
ad667945 2274 virtual wxGraphicsContext * CreateMeasuringContext();
783d8bdf
VZ
2275
2276 // Path
b7b40adb 2277
e3ff3591 2278 virtual wxGraphicsPath CreatePath();
b7b40adb 2279
783d8bdf
VZ
2280 // Matrix
2281
2282 virtual wxGraphicsMatrix CreateMatrix( wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
2283 wxDouble tx=0.0, wxDouble ty=0.0);
b7b40adb
SC
2284
2285
a26b7ab2 2286 virtual wxGraphicsPen CreatePen(const wxPen& pen) ;
783d8bdf 2287
a26b7ab2 2288 virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) ;
783d8bdf 2289
b7b40adb 2290 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
783d8bdf 2291 virtual wxGraphicsBrush CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
b7b40adb
SC
2292 const wxColour&c1, const wxColour&c2) ;
2293
783d8bdf 2294 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
b7b40adb 2295 // with radius r and color cColor
a26b7ab2 2296 virtual wxGraphicsBrush CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
b7b40adb
SC
2297 const wxColour &oColor, const wxColour &cColor) ;
2298
2299 // sets the font
a26b7ab2 2300 virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ;
b7b40adb 2301
5252d9e4
SC
2302 // create a native bitmap representation
2303 virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) ;
947f3b35 2304
5252d9e4
SC
2305 // create a native bitmap representation
2306 virtual wxGraphicsBitmap CreateSubBitmap( const wxGraphicsBitmap &bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h ) ;
b7b40adb
SC
2307private :
2308 DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacCoreGraphicsRenderer)
2309} ;
2310
2311//-----------------------------------------------------------------------------
2312// wxMacCoreGraphicsRenderer implementation
2313//-----------------------------------------------------------------------------
2314
2315IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsRenderer,wxGraphicsRenderer)
2316
2317static wxMacCoreGraphicsRenderer gs_MacCoreGraphicsRenderer;
2318
2319wxGraphicsRenderer* wxGraphicsRenderer::GetDefaultRenderer()
2320{
783d8bdf 2321 return &gs_MacCoreGraphicsRenderer;
50581042
SC
2322}
2323
5252d9e4
SC
2324#ifdef __WXCOCOA__
2325extern CGContextRef wxMacGetContextFromCurrentNSContext() ;
2326#endif
2327
888dde65 2328wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxWindowDC& dc )
b7b40adb 2329{
888dde65
RR
2330 const wxDCImpl* impl = dc.GetImpl();
2331 wxWindowDCImpl *win_impl = wxDynamicCast( impl, wxWindowDCImpl );
2332 if (win_impl)
5252d9e4
SC
2333 {
2334 int w, h;
2335 win_impl->GetSize( &w, &h );
2336 CGContextRef cgctx = 0;
2337#ifdef __WXMAC__
2338 cgctx = (CGContextRef)(win_impl->GetWindow()->MacGetCGContextRef());
2339#else
2340 cgctx = wxMacGetContextFromCurrentNSContext() ;
2341#endif
2342 return new wxMacCoreGraphicsContext( this, cgctx, (wxDouble) w, (wxDouble) h );
2343 }
888dde65
RR
2344 return NULL;
2345}
2346
2347wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxMemoryDC& dc )
2348{
5252d9e4 2349#ifdef __WXMAC__
888dde65
RR
2350 const wxDCImpl* impl = dc.GetImpl();
2351 wxMemoryDCImpl *mem_impl = wxDynamicCast( impl, wxMemoryDCImpl );
2352 if (mem_impl)
5252d9e4
SC
2353 {
2354 int w, h;
2355 mem_impl->GetSize( &w, &h );
947f3b35 2356 return new wxMacCoreGraphicsContext( this,
5252d9e4
SC
2357 (CGContextRef)(mem_impl->GetGraphicsContext()->GetNativeContext()), (wxDouble) w, (wxDouble) h );
2358 }
2359#endif
888dde65 2360 return NULL;
b7b40adb
SC
2361}
2362
0b822969
RR
2363wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxPrinterDC& dc )
2364{
2365#ifdef __WXMAC__
2366 const wxDCImpl* impl = dc.GetImpl();
87fe0f75
SC
2367 wxPrinterDCImpl *print_impl = wxDynamicCast( impl, wxPrinterDCImpl );
2368 if (print_impl)
2369 {
2370 int w, h;
2371 print_impl->GetSize( &w, &h );
2372 return new wxMacCoreGraphicsContext( this,
2373 (CGContextRef)(print_impl->GetGraphicsContext()->GetNativeContext()), (wxDouble) w, (wxDouble) h );
2374 }
0b822969
RR
2375#endif
2376 return NULL;
2377}
2378
b7b40adb
SC
2379wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeContext( void * context )
2380{
2381 return new wxMacCoreGraphicsContext(this,(CGContextRef)context);
2382}
2383
2384
2385wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeWindow( void * window )
2386{
2387 return new wxMacCoreGraphicsContext(this,(WindowRef)window);
2388}
2389
2390wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( wxWindow* window )
2391{
783d8bdf 2392 return new wxMacCoreGraphicsContext(this, window );
b7b40adb
SC
2393}
2394
ad667945
SC
2395wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateMeasuringContext()
2396{
2397 return new wxMacCoreGraphicsContext(this);
2398}
2399
b7b40adb
SC
2400// Path
2401
e3ff3591 2402wxGraphicsPath wxMacCoreGraphicsRenderer::CreatePath()
b7b40adb 2403{
e3ff3591
SC
2404 wxGraphicsPath m;
2405 m.SetRefData( new wxMacCoreGraphicsPathData(this));
2406 return m;
b7b40adb
SC
2407}
2408
2409
2410// Matrix
2411
783d8bdf
VZ
2412wxGraphicsMatrix wxMacCoreGraphicsRenderer::CreateMatrix( wxDouble a, wxDouble b, wxDouble c, wxDouble d,
2413 wxDouble tx, wxDouble ty)
1056ddcf 2414{
e3ff3591
SC
2415 wxGraphicsMatrix m;
2416 wxMacCoreGraphicsMatrixData* data = new wxMacCoreGraphicsMatrixData( this );
2417 data->Set( a,b,c,d,tx,ty ) ;
2418 m.SetRefData(data);
b7b40adb
SC
2419 return m;
2420}
2421
783d8bdf 2422wxGraphicsPen wxMacCoreGraphicsRenderer::CreatePen(const wxPen& pen)
b7b40adb
SC
2423{
2424 if ( !pen.Ok() || pen.GetStyle() == wxTRANSPARENT )
a26b7ab2 2425 return wxNullGraphicsPen;
b7b40adb 2426 else
a26b7ab2
SC
2427 {
2428 wxGraphicsPen p;
2429 p.SetRefData(new wxMacCoreGraphicsPenData( this, pen ));
2430 return p;
2431 }
1056ddcf
SC
2432}
2433
783d8bdf 2434wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateBrush(const wxBrush& brush )
50581042 2435{
b7b40adb 2436 if ( !brush.Ok() || brush.GetStyle() == wxTRANSPARENT )
a26b7ab2 2437 return wxNullGraphicsBrush;
b7b40adb 2438 else
a26b7ab2
SC
2439 {
2440 wxGraphicsBrush p;
2441 p.SetRefData(new wxMacCoreGraphicsBrushData( this, brush ));
2442 return p;
2443 }
50581042
SC
2444}
2445
5252d9e4
SC
2446wxGraphicsBitmap wxMacCoreGraphicsRenderer::CreateBitmap( const wxBitmap& bmp )
2447{
2448 if ( bmp.Ok() )
2449 {
2450 wxGraphicsBitmap p;
2451#ifdef __WXMAC__
35c72e51 2452 p.SetRefData(new wxMacCoreGraphicsBitmapData( this , bmp.CreateCGImage(), bmp.GetDepth() == 1 ) );
5252d9e4
SC
2453#endif
2454 return p;
2455 }
2456 else
2457 return wxNullGraphicsBitmap;
2458}
2459
947f3b35 2460wxGraphicsBitmap wxMacCoreGraphicsRenderer::CreateSubBitmap( const wxGraphicsBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
5252d9e4 2461{
35c72e51
SC
2462 wxMacCoreGraphicsBitmapData* refdata =static_cast<wxMacCoreGraphicsBitmapData*>(bmp.GetRefData());
2463 CGImageRef img = refdata->GetBitmap();
5252d9e4
SC
2464 if ( img )
2465 {
2466 wxGraphicsBitmap p;
35c72e51
SC
2467 CGImageRef subimg = CGImageCreateWithImageInRect(img,CGRectMake( (CGFloat) x , (CGFloat) y , (CGFloat) w , (CGFloat) h ));
2468 p.SetRefData(new wxMacCoreGraphicsBitmapData( this , subimg, refdata->IsMonochrome() ) );
5252d9e4
SC
2469 return p;
2470 }
2471 else
2472 return wxNullGraphicsBitmap;
2473}
2474
b7b40adb 2475// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
783d8bdf
VZ
2476wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
2477 const wxColour&c1, const wxColour&c2)
1056ddcf 2478{
a26b7ab2
SC
2479 wxGraphicsBrush p;
2480 wxMacCoreGraphicsBrushData* d = new wxMacCoreGraphicsBrushData( this );
2481 d->CreateLinearGradientBrush(x1, y1, x2, y2, c1, c2);
2482 p.SetRefData(d);
2483 return p;
1056ddcf
SC
2484}
2485
783d8bdf 2486// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
b7b40adb 2487// with radius r and color cColor
a26b7ab2 2488wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
783d8bdf 2489 const wxColour &oColor, const wxColour &cColor)
1056ddcf 2490{
a26b7ab2
SC
2491 wxGraphicsBrush p;
2492 wxMacCoreGraphicsBrushData* d = new wxMacCoreGraphicsBrushData( this );
2493 d->CreateRadialGradientBrush(xo,yo,xc,yc,radius,oColor,cColor);
2494 p.SetRefData(d);
2495 return p;
1056ddcf
SC
2496}
2497
b7b40adb 2498// sets the font
783d8bdf 2499wxGraphicsFont wxMacCoreGraphicsRenderer::CreateFont( const wxFont &font , const wxColour &col )
513b47e9 2500{
b7b40adb 2501 if ( font.Ok() )
783d8bdf 2502 {
a26b7ab2
SC
2503 wxGraphicsFont p;
2504 p.SetRefData(new wxMacCoreGraphicsFontData( this , font, col ));
2505 return p;
2506 }
b7b40adb 2507 else
a26b7ab2 2508 return wxNullGraphicsFont;
513b47e9
SC
2509}
2510
fb728ebb
SC
2511//
2512// CoreGraphics Helper Methods
2513//
2514
2515// Data Providers and Consumers
2516
2517size_t UMAPutBytesCFRefCallback( void *info, const void *bytes, size_t count )
2518{
2519 CFMutableDataRef data = (CFMutableDataRef) info;
2520 if ( data )
2521 {
2522 CFDataAppendBytes( data, (const UInt8*) bytes, count );
2523 }
2524 return count;
2525}
2526
2527void wxMacReleaseCFDataProviderCallback(void *info,
2528 const void *WXUNUSED(data),
2529 size_t WXUNUSED(count))
2530{
2531 if ( info )
2532 CFRelease( (CFDataRef) info );
2533}
2534
2535void wxMacReleaseCFDataConsumerCallback( void *info )
2536{
2537 if ( info )
2538 CFRelease( (CFDataRef) info );
2539}
2540
2541CGDataProviderRef wxMacCGDataProviderCreateWithCFData( CFDataRef data )
2542{
2543 if ( data == NULL )
2544 return NULL;
2545
2546 return CGDataProviderCreateWithCFData( data );
2547}
2548
2549CGDataConsumerRef wxMacCGDataConsumerCreateWithCFData( CFMutableDataRef data )
2550{
2551 if ( data == NULL )
2552 return NULL;
2553
2554 return CGDataConsumerCreateWithCFData( data );
2555}
2556
947f3b35
VZ
2557void
2558wxMacReleaseMemoryBufferProviderCallback(void *info,
2559 const void * WXUNUSED_UNLESS_DEBUG(data),
2560 size_t WXUNUSED(size))
fb728ebb
SC
2561{
2562 wxMemoryBuffer* membuf = (wxMemoryBuffer*) info ;
2563
2564 wxASSERT( data == membuf->GetData() ) ;
2565
2566 delete membuf ;
2567}
2568
2569CGDataProviderRef wxMacCGDataProviderCreateWithMemoryBuffer( const wxMemoryBuffer& buf )
2570{
2571 wxMemoryBuffer* b = new wxMemoryBuffer( buf );
2572 if ( b->GetDataLen() == 0 )
2573 return NULL;
947f3b35 2574
fb728ebb
SC
2575 return CGDataProviderCreateWithData( b , (const void *) b->GetData() , b->GetDataLen() ,
2576 wxMacReleaseMemoryBufferProviderCallback );
947f3b35 2577}