]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/graphics.cpp
don't wake up on Windows messages when waiting for thread termination in a console...
[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
f43426c1 14#if wxUSE_GRAPHICS_CONTEXT && wxMAC_USE_CORE_GRAPHICS
50581042 15
83b96a06
PC
16#include "wx/graphics.h"
17
50581042 18#ifndef WX_PRECOMP
cc5de8fe 19 #include "wx/dcclient.h"
50581042 20 #include "wx/log.h"
50581042 21 #include "wx/region.h"
50581042
SC
22#endif
23
24#include "wx/mac/uma.h"
25
50581042
SC
26#ifdef __MSL__
27 #if __MSL__ >= 0x6000
28 #include "math.h"
29 // in case our functions were defined outside std, we make it known all the same
30 namespace std { }
31 using namespace std;
32 #endif
33#endif
34
35#include "wx/mac/private.h"
36
37#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
38typedef float CGFloat;
39#endif
277ccdaf
SC
40#ifndef wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
41#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
42 #define wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 1
43#else
44 #define wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 0
45#endif
46#endif
50581042 47
eec960fa
SC
48//-----------------------------------------------------------------------------
49// constants
50//-----------------------------------------------------------------------------
51
52#if !defined( __DARWIN__ ) || defined(__MWERKS__)
53#ifndef M_PI
54const double M_PI = 3.14159265358979;
55#endif
56#endif
57
58static const double RAD2DEG = 180.0 / M_PI;
59
50581042 60//
b7b40adb 61// Pen, Brushes and Fonts
50581042
SC
62//
63
b7b40adb
SC
64#pragma mark -
65#pragma mark wxMacCoreGraphicsPattern, ImagePattern, HatchPattern classes
66
67// CGPattern wrapper class: always allocate on heap, never call destructor
68
69class wxMacCoreGraphicsPattern
50581042 70{
50581042 71public :
b7b40adb 72 wxMacCoreGraphicsPattern() {}
50581042 73
b7b40adb
SC
74 // is guaranteed to be called only with a non-Null CGContextRef
75 virtual void Render( CGContextRef ctxRef ) = 0;
50581042 76
b7b40adb 77 operator CGPatternRef() const { return m_patternRef; }
50581042 78
b7b40adb
SC
79protected :
80 virtual ~wxMacCoreGraphicsPattern()
81 {
82 // as this is called only when the m_patternRef is been released;
83 // don't release it again
84 }
50581042 85
b7b40adb
SC
86 static void _Render( void *info, CGContextRef ctxRef )
87 {
88 wxMacCoreGraphicsPattern* self = (wxMacCoreGraphicsPattern*) info;
89 if ( self && ctxRef )
90 self->Render( ctxRef );
91 }
50581042 92
b7b40adb
SC
93 static void _Dispose( void *info )
94 {
95 wxMacCoreGraphicsPattern* self = (wxMacCoreGraphicsPattern*) info;
96 delete self;
97 }
50581042 98
b7b40adb 99 CGPatternRef m_patternRef;
50581042 100
b7b40adb
SC
101 static const CGPatternCallbacks ms_Callbacks;
102};
50581042 103
b7b40adb 104const CGPatternCallbacks wxMacCoreGraphicsPattern::ms_Callbacks = { 0, &wxMacCoreGraphicsPattern::_Render, &wxMacCoreGraphicsPattern::_Dispose };
50581042 105
b7b40adb
SC
106class ImagePattern : public wxMacCoreGraphicsPattern
107{
108public :
109 ImagePattern( const wxBitmap* bmp , const CGAffineTransform& transform )
110 {
111 wxASSERT( bmp && bmp->Ok() );
50581042 112
b7b40adb
SC
113 Init( (CGImageRef) bmp->CGImageCreate() , transform );
114 }
50581042 115
b7b40adb
SC
116 // ImagePattern takes ownership of CGImageRef passed in
117 ImagePattern( CGImageRef image , const CGAffineTransform& transform )
118 {
119 if ( image )
120 CFRetain( image );
121
122 Init( image , transform );
123 }
124
125 virtual void Render( CGContextRef ctxRef )
126 {
127 if (m_image != NULL)
128 HIViewDrawCGImage( ctxRef, &m_imageBounds, m_image );
129 }
130
131protected :
132 void Init( CGImageRef image, const CGAffineTransform& transform )
133 {
134 m_image = image;
135 if ( m_image )
136 {
137 m_imageBounds = CGRectMake( 0.0, 0.0, (CGFloat)CGImageGetWidth( m_image ), (CGFloat)CGImageGetHeight( m_image ) );
138 m_patternRef = CGPatternCreate(
139 this , m_imageBounds, transform ,
140 m_imageBounds.size.width, m_imageBounds.size.height,
141 kCGPatternTilingNoDistortion, true , &wxMacCoreGraphicsPattern::ms_Callbacks );
142 }
143 }
144
145 virtual ~ImagePattern()
146 {
147 if ( m_image )
148 CGImageRelease( m_image );
149 }
150
151 CGImageRef m_image;
152 CGRect m_imageBounds;
153};
154
155class HatchPattern : public wxMacCoreGraphicsPattern
156{
157public :
158 HatchPattern( int hatchstyle, const CGAffineTransform& transform )
159 {
160 m_hatch = hatchstyle;
161 m_imageBounds = CGRectMake( 0.0, 0.0, 8.0 , 8.0 );
162 m_patternRef = CGPatternCreate(
163 this , m_imageBounds, transform ,
164 m_imageBounds.size.width, m_imageBounds.size.height,
165 kCGPatternTilingNoDistortion, false , &wxMacCoreGraphicsPattern::ms_Callbacks );
166 }
167
168 void StrokeLineSegments( CGContextRef ctxRef , const CGPoint pts[] , size_t count )
169 {
170#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
277ccdaf 171 if ( CGContextStrokeLineSegments!=NULL )
b7b40adb
SC
172 {
173 CGContextStrokeLineSegments( ctxRef , pts , count );
174 }
175 else
176#endif
177 {
178 CGContextBeginPath( ctxRef );
179 for (size_t i = 0; i < count; i += 2)
180 {
181 CGContextMoveToPoint(ctxRef, pts[i].x, pts[i].y);
182 CGContextAddLineToPoint(ctxRef, pts[i+1].x, pts[i+1].y);
183 }
184 CGContextStrokePath(ctxRef);
185 }
186 }
187
188 virtual void Render( CGContextRef ctxRef )
189 {
190 switch ( m_hatch )
191 {
192 case wxBDIAGONAL_HATCH :
193 {
194 CGPoint pts[] =
195 {
196 { 8.0 , 0.0 } , { 0.0 , 8.0 }
197 };
198 StrokeLineSegments( ctxRef , pts , 2 );
199 }
200 break;
201
202 case wxCROSSDIAG_HATCH :
203 {
204 CGPoint pts[] =
205 {
206 { 0.0 , 0.0 } , { 8.0 , 8.0 } ,
207 { 8.0 , 0.0 } , { 0.0 , 8.0 }
208 };
209 StrokeLineSegments( ctxRef , pts , 4 );
210 }
211 break;
212
213 case wxFDIAGONAL_HATCH :
214 {
215 CGPoint pts[] =
216 {
217 { 0.0 , 0.0 } , { 8.0 , 8.0 }
218 };
219 StrokeLineSegments( ctxRef , pts , 2 );
220 }
221 break;
222
223 case wxCROSS_HATCH :
224 {
225 CGPoint pts[] =
226 {
227 { 0.0 , 4.0 } , { 8.0 , 4.0 } ,
228 { 4.0 , 0.0 } , { 4.0 , 8.0 } ,
229 };
230 StrokeLineSegments( ctxRef , pts , 4 );
231 }
232 break;
233
234 case wxHORIZONTAL_HATCH :
235 {
236 CGPoint pts[] =
237 {
238 { 0.0 , 4.0 } , { 8.0 , 4.0 } ,
239 };
240 StrokeLineSegments( ctxRef , pts , 2 );
241 }
242 break;
243
244 case wxVERTICAL_HATCH :
245 {
246 CGPoint pts[] =
247 {
248 { 4.0 , 0.0 } , { 4.0 , 8.0 } ,
249 };
250 StrokeLineSegments( ctxRef , pts , 2 );
251 }
252 break;
253
254 default:
255 break;
256 }
257 }
258
259protected :
260 virtual ~HatchPattern() {}
261
262 CGRect m_imageBounds;
263 int m_hatch;
264};
265
a26b7ab2 266class wxMacCoreGraphicsPenData : public wxGraphicsObjectRefData
b7b40adb
SC
267{
268public:
a26b7ab2
SC
269 wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer, const wxPen &pen );
270 ~wxMacCoreGraphicsPenData();
783d8bdf 271
b7b40adb
SC
272 void Init();
273 virtual void Apply( wxGraphicsContext* context );
274 virtual wxDouble GetWidth() { return m_width; }
783d8bdf 275
b7b40adb
SC
276protected :
277 CGLineCap m_cap;
278 wxMacCFRefHolder<CGColorRef> m_color;
279 wxMacCFRefHolder<CGColorSpaceRef> m_colorSpace;
280
281 CGLineJoin m_join;
282 CGFloat m_width;
783d8bdf 283
b7b40adb
SC
284 int m_count;
285 const CGFloat *m_lengths;
286 CGFloat *m_userLengths;
eec960fa 287
b7b40adb
SC
288
289 bool m_isPattern;
290 wxMacCFRefHolder<CGPatternRef> m_pattern;
291 CGFloat* m_patternColorComponents;
50581042
SC
292};
293
a26b7ab2
SC
294wxMacCoreGraphicsPenData::wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer, const wxPen &pen ) :
295 wxGraphicsObjectRefData( renderer )
50581042 296{
b7b40adb 297 Init();
783d8bdf
VZ
298
299 float components[4] = { pen.GetColour().Red() / 255.0 , pen.GetColour().Green() / 255.0 ,
b7b40adb
SC
300 pen.GetColour().Blue() / 255.0 , pen.GetColour().Alpha() / 255.0 } ;
301 m_color.Set( CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ) ;
302
303 // TODO: * m_dc->m_scaleX
304 m_width = pen.GetWidth();
305 if (m_width <= 0.0)
306 m_width = 0.1;
307
308 switch ( pen.GetCap() )
309 {
310 case wxCAP_ROUND :
311 m_cap = kCGLineCapRound;
312 break;
313
314 case wxCAP_PROJECTING :
315 m_cap = kCGLineCapSquare;
316 break;
317
318 case wxCAP_BUTT :
319 m_cap = kCGLineCapButt;
320 break;
321
322 default :
323 m_cap = kCGLineCapButt;
324 break;
325 }
326
327 switch ( pen.GetJoin() )
328 {
329 case wxJOIN_BEVEL :
330 m_join = kCGLineJoinBevel;
331 break;
332
333 case wxJOIN_MITER :
334 m_join = kCGLineJoinMiter;
335 break;
336
337 case wxJOIN_ROUND :
338 m_join = kCGLineJoinRound;
339 break;
340
341 default :
342 m_join = kCGLineJoinMiter;
343 break;
344 }
345
346 const CGFloat dashUnit = m_width < 1.0 ? 1.0 : m_width;
347
348 const CGFloat dotted[] = { dashUnit , dashUnit + 2.0 };
349 static const CGFloat short_dashed[] = { 9.0 , 6.0 };
350 static const CGFloat dashed[] = { 19.0 , 9.0 };
351 static const CGFloat dotted_dashed[] = { 9.0 , 6.0 , 3.0 , 3.0 };
352
353 switch ( pen.GetStyle() )
354 {
355 case wxSOLID :
356 break;
357
358 case wxDOT :
359 m_count = WXSIZEOF(dotted);
360 m_userLengths = new CGFloat[ m_count ] ;
361 memcpy( m_userLengths, dotted, sizeof(dotted) );
362 m_lengths = m_userLengths;
363 break;
364
365 case wxLONG_DASH :
366 m_count = WXSIZEOF(dashed);
367 m_lengths = dashed;
368 break;
369
370 case wxSHORT_DASH :
371 m_count = WXSIZEOF(short_dashed);
372 m_lengths = short_dashed;
373 break;
374
375 case wxDOT_DASH :
376 m_count = WXSIZEOF(dotted_dashed);
377 m_lengths = dotted_dashed;
378 break;
379
380 case wxUSER_DASH :
381 wxDash *dashes;
382 m_count = pen.GetDashes( &dashes );
383 if ((dashes != NULL) && (m_count > 0))
384 {
385 m_userLengths = new CGFloat[m_count];
386 for ( int i = 0; i < m_count; ++i )
387 {
388 m_userLengths[i] = dashes[i] * dashUnit;
389
390 if ( i % 2 == 1 && m_userLengths[i] < dashUnit + 2.0 )
391 m_userLengths[i] = dashUnit + 2.0;
392 else if ( i % 2 == 0 && m_userLengths[i] < dashUnit )
393 m_userLengths[i] = dashUnit;
394 }
395 }
396 m_lengths = m_userLengths;
397 break;
398
399 case wxSTIPPLE :
400 {
401 wxBitmap* bmp = pen.GetStipple();
402 if ( bmp && bmp->Ok() )
403 {
404 m_colorSpace.Set( CGColorSpaceCreatePattern( NULL ) );
74b357dd 405 m_pattern.Set( *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) );
b7b40adb
SC
406 m_patternColorComponents = new CGFloat[1] ;
407 m_patternColorComponents[0] = 1.0;
408 m_isPattern = true;
409 }
410 }
411 break;
412
413 default :
414 {
415 m_isPattern = true;
416 m_colorSpace.Set( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
74b357dd 417 m_pattern.Set( *( new HatchPattern( pen.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) );
b7b40adb
SC
418 m_patternColorComponents = new CGFloat[4] ;
419 m_patternColorComponents[0] = pen.GetColour().Red() / 255.0;
420 m_patternColorComponents[1] = pen.GetColour().Green() / 255.0;
421 m_patternColorComponents[2] = pen.GetColour().Blue() / 255.0;
422 m_patternColorComponents[3] = pen.GetColour().Alpha() / 255.0;
423 }
424 break;
425 }
426 if ((m_lengths != NULL) && (m_count > 0))
427 {
428 // force the line cap, otherwise we get artifacts (overlaps) and just solid lines
429 m_cap = kCGLineCapButt;
430 }
50581042
SC
431}
432
a26b7ab2 433wxMacCoreGraphicsPenData::~wxMacCoreGraphicsPenData()
50581042 434{
b7b40adb
SC
435 delete[] m_userLengths;
436 delete[] m_patternColorComponents;
50581042
SC
437}
438
a26b7ab2 439void wxMacCoreGraphicsPenData::Init()
50581042 440{
b7b40adb
SC
441 m_lengths = NULL;
442 m_userLengths = NULL;
783d8bdf 443 m_width = 0;
b7b40adb
SC
444 m_count = 0;
445 m_patternColorComponents = NULL;
446 m_isPattern = false;
50581042
SC
447}
448
a26b7ab2 449void wxMacCoreGraphicsPenData::Apply( wxGraphicsContext* context )
50581042 450{
b7b40adb
SC
451 CGContextRef cg = (CGContextRef) context->GetNativeContext();
452 CGContextSetLineWidth( cg , m_width );
453 CGContextSetLineJoin( cg , m_join );
454
455 CGContextSetLineDash( cg , 0 , m_lengths , m_count );
456 CGContextSetLineCap( cg , m_cap );
457
458 if ( m_isPattern )
459 {
74b357dd
SC
460 CGAffineTransform matrix = CGContextGetCTM( cg );
461 CGContextSetPatternPhase( cg, CGSizeMake(matrix.tx, matrix.ty) );
b7b40adb
SC
462 CGContextSetStrokeColorSpace( cg , m_colorSpace );
463 CGContextSetStrokePattern( cg, m_pattern , m_patternColorComponents );
464 }
465 else
466 {
277ccdaf
SC
467 if ( context->GetLogicalFunction() == wxINVERT || context->GetLogicalFunction() == wxXOR )
468 {
469 CGContextSetRGBStrokeColor( cg , 1.0, 1.0 , 1.0, 1.0 );
470 }
471 else
472 CGContextSetStrokeColorWithColor( cg , m_color );
b7b40adb 473 }
50581042
SC
474}
475
b7b40adb
SC
476//
477// Brush
478//
479
a26b7ab2 480class wxMacCoreGraphicsBrushData : public wxGraphicsObjectRefData
50581042 481{
b7b40adb 482public:
a26b7ab2
SC
483 wxMacCoreGraphicsBrushData( wxGraphicsRenderer* renderer );
484 wxMacCoreGraphicsBrushData( wxGraphicsRenderer* renderer, const wxBrush &brush );
485 ~wxMacCoreGraphicsBrushData ();
783d8bdf 486
b7b40adb 487 virtual void Apply( wxGraphicsContext* context );
783d8bdf 488 void CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
b7b40adb
SC
489 const wxColour&c1, const wxColour&c2 );
490 void CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
491 const wxColour &oColor, const wxColour &cColor );
783d8bdf 492
b7b40adb
SC
493 virtual bool IsShading() { return m_isShading; }
494 CGShadingRef GetShading() { return m_shading; }
495protected:
496 CGFunctionRef CreateGradientFunction( const wxColour& c1, const wxColour& c2 );
497 static void CalculateShadingValues (void *info, const CGFloat *in, CGFloat *out);
498 virtual void Init();
783d8bdf 499
b7b40adb
SC
500 wxMacCFRefHolder<CGColorRef> m_color;
501 wxMacCFRefHolder<CGColorSpaceRef> m_colorSpace;
502
503 bool m_isPattern;
504 wxMacCFRefHolder<CGPatternRef> m_pattern;
505 CGFloat* m_patternColorComponents;
783d8bdf 506
b7b40adb
SC
507 bool m_isShading;
508 CGFunctionRef m_gradientFunction;
509 CGShadingRef m_shading;
510 CGFloat *m_gradientComponents;
b7b40adb
SC
511};
512
a26b7ab2 513wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData( wxGraphicsRenderer* renderer) : wxGraphicsObjectRefData( renderer )
50581042 514{
b7b40adb 515 Init();
50581042
SC
516}
517
783d8bdf 518void wxMacCoreGraphicsBrushData::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
b7b40adb 519 const wxColour&c1, const wxColour&c2 )
50581042 520{
b7b40adb
SC
521 m_gradientFunction = CreateGradientFunction( c1, c2 );
522 m_shading = CGShadingCreateAxial( wxMacGetGenericRGBColorSpace(), CGPointMake(x1,y1), CGPointMake(x2,y2), m_gradientFunction, true, true ) ;
523 m_isShading = true ;
524}
783d8bdf 525
a26b7ab2 526void wxMacCoreGraphicsBrushData::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
b7b40adb
SC
527 const wxColour &oColor, const wxColour &cColor )
528{
529 m_gradientFunction = CreateGradientFunction( oColor, cColor );
530 m_shading = CGShadingCreateRadial( wxMacGetGenericRGBColorSpace(), CGPointMake(xo,yo), 0, CGPointMake(xc,yc), radius, m_gradientFunction, true, true ) ;
531 m_isShading = true ;
532}
783d8bdf 533
a26b7ab2 534wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData(wxGraphicsRenderer* renderer, const wxBrush &brush) : wxGraphicsObjectRefData( renderer )
b7b40adb
SC
535{
536 Init();
783d8bdf 537
b7b40adb
SC
538 if ( brush.GetStyle() == wxSOLID )
539 {
82f88f03
SC
540 if ( brush.MacGetBrushKind() == kwxMacBrushTheme )
541 {
542#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
543 if ( HIThemeBrushCreateCGColor != 0 )
544 {
545 CGColorRef color ;
546 HIThemeBrushCreateCGColor( brush.MacGetTheme(), &color );
547 m_color.Set( color ) ;
548 }
549 else
550#endif
551 {
552 // as close as we can get, unfortunately < 10.4 things get difficult
553 RGBColor color;
554 GetThemeBrushAsColor( brush.MacGetTheme(), 32, true, &color );
555 float components[4] = { (CGFloat) color.red / 65536,
556 (CGFloat) color.green / 65536, (CGFloat) color.blue / 65536, 1 } ;
557 m_color.Set( CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ) ;
558 }
559 }
560 else
561 {
562 float components[4] = { brush.GetColour().Red() / 255.0 , brush.GetColour().Green() / 255.0 ,
b7b40adb 563 brush.GetColour().Blue() / 255.0 , brush.GetColour().Alpha() / 255.0 } ;
82f88f03
SC
564 m_color.Set( CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ) ;
565 }
b7b40adb
SC
566 }
567 else if ( brush.IsHatch() )
568 {
569 m_isPattern = true;
570 m_colorSpace.Set( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
74b357dd 571 m_pattern.Set( *( new HatchPattern( brush.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) );
b7b40adb
SC
572
573 m_patternColorComponents = new CGFloat[4] ;
574 m_patternColorComponents[0] = brush.GetColour().Red() / 255.0;
575 m_patternColorComponents[1] = brush.GetColour().Green() / 255.0;
576 m_patternColorComponents[2] = brush.GetColour().Blue() / 255.0;
577 m_patternColorComponents[3] = brush.GetColour().Alpha() / 255.0;
578 }
579 else
580 {
581 // now brush is a bitmap
582 wxBitmap* bmp = brush.GetStipple();
583 if ( bmp && bmp->Ok() )
584 {
783d8bdf 585 m_isPattern = true;
b7b40adb
SC
586 m_patternColorComponents = new CGFloat[1] ;
587 m_patternColorComponents[0] = 1.0;
588 m_colorSpace.Set( CGColorSpaceCreatePattern( NULL ) );
74b357dd 589 m_pattern.Set( *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) );
b7b40adb
SC
590 }
591 }
50581042
SC
592}
593
a26b7ab2 594wxMacCoreGraphicsBrushData::~wxMacCoreGraphicsBrushData()
50581042 595{
b7b40adb
SC
596 if ( m_shading )
597 CGShadingRelease(m_shading);
783d8bdf 598
b7b40adb
SC
599 if( m_gradientFunction )
600 CGFunctionRelease(m_gradientFunction);
783d8bdf 601
b7b40adb
SC
602 delete[] m_gradientComponents;
603 delete[] m_patternColorComponents;
50581042
SC
604}
605
a26b7ab2 606void wxMacCoreGraphicsBrushData::Init()
50581042 607{
b7b40adb
SC
608 m_patternColorComponents = NULL;
609 m_gradientFunction = NULL;
610 m_shading = NULL;
611 m_isPattern = false;
612 m_gradientComponents = NULL;
613 m_isShading = false;
50581042
SC
614}
615
a26b7ab2 616void wxMacCoreGraphicsBrushData::Apply( wxGraphicsContext* context )
50581042 617{
b7b40adb 618 CGContextRef cg = (CGContextRef) context->GetNativeContext();
783d8bdf 619
b7b40adb 620 if ( m_isShading )
783d8bdf 621 {
74b357dd 622 // nothing to set as shades are processed by clipping using the path and filling
b7b40adb
SC
623 }
624 else
625 {
626 if ( m_isPattern )
627 {
74b357dd
SC
628 CGAffineTransform matrix = CGContextGetCTM( cg );
629 CGContextSetPatternPhase( cg, CGSizeMake(matrix.tx, matrix.ty) );
b7b40adb
SC
630 CGContextSetFillColorSpace( cg , m_colorSpace );
631 CGContextSetFillPattern( cg, m_pattern , m_patternColorComponents );
632 }
633 else
634 {
635 CGContextSetFillColorWithColor( cg, m_color );
636 }
637 }
50581042
SC
638}
639
a26b7ab2 640void wxMacCoreGraphicsBrushData::CalculateShadingValues (void *info, const CGFloat *in, CGFloat *out)
50581042 641{
b7b40adb
SC
642 CGFloat* colors = (CGFloat*) info ;
643 CGFloat f = *in;
644 for( int i = 0 ; i < 4 ; ++i )
645 {
646 out[i] = colors[i] + ( colors[4+i] - colors[i] ) * f;
647 }
50581042
SC
648}
649
a26b7ab2 650CGFunctionRef wxMacCoreGraphicsBrushData::CreateGradientFunction( const wxColour& c1, const wxColour& c2 )
50581042 651{
b7b40adb
SC
652 static const CGFunctionCallbacks callbacks = { 0, &CalculateShadingValues, NULL };
653 static const CGFloat input_value_range [2] = { 0, 1 };
654 static const CGFloat output_value_ranges [8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
655 m_gradientComponents = new CGFloat[8] ;
656 m_gradientComponents[0] = c1.Red() / 255.0;
657 m_gradientComponents[1] = c1.Green() / 255.0;
658 m_gradientComponents[2] = c1.Blue() / 255.0;
659 m_gradientComponents[3] = c1.Alpha() / 255.0;
660 m_gradientComponents[4] = c2.Red() / 255.0;
661 m_gradientComponents[5] = c2.Green() / 255.0;
662 m_gradientComponents[6] = c2.Blue() / 255.0;
663 m_gradientComponents[7] = c2.Alpha() / 255.0;
664
783d8bdf
VZ
665 return CGFunctionCreate ( m_gradientComponents, 1,
666 input_value_range,
667 4,
b7b40adb 668 output_value_ranges,
783d8bdf 669 &callbacks);
50581042
SC
670}
671
672//
b7b40adb 673// Font
50581042
SC
674//
675
a26b7ab2 676class wxMacCoreGraphicsFontData : public wxGraphicsObjectRefData
50581042 677{
50581042 678public:
a26b7ab2
SC
679 wxMacCoreGraphicsFontData( wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col );
680 ~wxMacCoreGraphicsFontData();
783d8bdf 681
b7b40adb
SC
682 virtual ATSUStyle GetATSUStyle() { return m_macATSUIStyle; }
683private :
684 ATSUStyle m_macATSUIStyle;
b7b40adb 685};
50581042 686
a26b7ab2 687wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col) : wxGraphicsObjectRefData( renderer )
b7b40adb
SC
688{
689 m_macATSUIStyle = NULL;
783d8bdf 690
b7b40adb 691 OSStatus status;
50581042 692
b7b40adb 693 status = ATSUCreateAndCopyStyle( (ATSUStyle) font.MacGetATSUStyle() , &m_macATSUIStyle );
50581042 694
b7b40adb 695 wxASSERT_MSG( status == noErr, wxT("couldn't create ATSU style") );
50581042 696
b7b40adb 697 // we need the scale here ...
50581042 698
b7b40adb
SC
699 Fixed atsuSize = IntToFixed( int( 1 * font.MacGetFontSize()) );
700 RGBColor atsuColor = MAC_WXCOLORREF( col.GetPixel() );
701 ATSUAttributeTag atsuTags[] =
702 {
703 kATSUSizeTag ,
704 kATSUColorTag ,
705 };
706 ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
707 {
708 sizeof( Fixed ) ,
709 sizeof( RGBColor ) ,
710 };
711 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
712 {
713 &atsuSize ,
714 &atsuColor ,
715 };
50581042 716
b7b40adb
SC
717 status = ::ATSUSetAttributes(
718 m_macATSUIStyle, sizeof(atsuTags) / sizeof(ATSUAttributeTag) ,
719 atsuTags, atsuSizes, atsuValues);
50581042 720
b7b40adb
SC
721 wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") );
722}
50581042 723
a26b7ab2 724wxMacCoreGraphicsFontData::~wxMacCoreGraphicsFontData()
b7b40adb
SC
725{
726 if ( m_macATSUIStyle )
727 {
728 ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
729 m_macATSUIStyle = NULL;
730 }
731}
50581042 732
b7b40adb
SC
733//
734// Graphics Matrix
735//
50581042 736
b7b40adb
SC
737//-----------------------------------------------------------------------------
738// wxMacCoreGraphicsMatrix declaration
739//-----------------------------------------------------------------------------
50581042 740
e3ff3591 741class WXDLLIMPEXP_CORE wxMacCoreGraphicsMatrixData : public wxGraphicsMatrixData
b7b40adb
SC
742{
743public :
783d8bdf
VZ
744 wxMacCoreGraphicsMatrixData(wxGraphicsRenderer* renderer) ;
745
746 virtual ~wxMacCoreGraphicsMatrixData() ;
747
e3ff3591 748 virtual wxGraphicsObjectRefData *Clone() const ;
b7b40adb 749
783d8bdf
VZ
750 // concatenates the matrix
751 virtual void Concat( const wxGraphicsMatrixData *t );
752
753 // sets the matrix to the respective values
754 virtual void Set(wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
755 wxDouble tx=0.0, wxDouble ty=0.0);
756
248802d0
RD
757 // gets the component valuess of the matrix
758 virtual void Get(wxDouble* a=NULL, wxDouble* b=NULL, wxDouble* c=NULL,
759 wxDouble* d=NULL, wxDouble* tx=NULL, wxDouble* ty=NULL) const;
760
783d8bdf
VZ
761 // makes this the inverse matrix
762 virtual void Invert();
763
764 // returns true if the elements of the transformation matrix are equal ?
e3ff3591 765 virtual bool IsEqual( const wxGraphicsMatrixData* t) const ;
783d8bdf
VZ
766
767 // return true if this is the identity matrix
768 virtual bool IsIdentity() const;
769
50581042 770 //
b7b40adb 771 // transformation
50581042 772 //
783d8bdf 773
b7b40adb
SC
774 // add the translation to this matrix
775 virtual void Translate( wxDouble dx , wxDouble dy );
50581042 776
b7b40adb
SC
777 // add the scale to this matrix
778 virtual void Scale( wxDouble xScale , wxDouble yScale );
50581042 779
b7b40adb 780 // add the rotation to this matrix (radians)
783d8bdf
VZ
781 virtual void Rotate( wxDouble angle );
782
50581042 783 //
b7b40adb 784 // apply the transforms
50581042 785 //
783d8bdf
VZ
786
787 // applies that matrix to the point
788 virtual void TransformPoint( wxDouble *x, wxDouble *y ) const;
789
790 // applies the matrix except for translations
791 virtual void TransformDistance( wxDouble *dx, wxDouble *dy ) const;
792
793 // returns the native representation
794 virtual void * GetNativeMatrix() const;
795
b7b40adb
SC
796private :
797 CGAffineTransform m_matrix;
b7b40adb 798} ;
50581042 799
50581042 800//-----------------------------------------------------------------------------
b7b40adb 801// wxMacCoreGraphicsMatrix implementation
50581042
SC
802//-----------------------------------------------------------------------------
803
e3ff3591 804wxMacCoreGraphicsMatrixData::wxMacCoreGraphicsMatrixData(wxGraphicsRenderer* renderer) : wxGraphicsMatrixData(renderer)
b7b40adb 805{
b7b40adb 806}
eec960fa 807
783d8bdf 808wxMacCoreGraphicsMatrixData::~wxMacCoreGraphicsMatrixData()
50581042 809{
50581042
SC
810}
811
783d8bdf 812wxGraphicsObjectRefData *wxMacCoreGraphicsMatrixData::Clone() const
50581042 813{
e3ff3591 814 wxMacCoreGraphicsMatrixData* m = new wxMacCoreGraphicsMatrixData(GetRenderer()) ;
b7b40adb
SC
815 m->m_matrix = m_matrix ;
816 return m;
817}
818
819// concatenates the matrix
783d8bdf 820void wxMacCoreGraphicsMatrixData::Concat( const wxGraphicsMatrixData *t )
b7b40adb
SC
821{
822 m_matrix = CGAffineTransformConcat(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix()) );
823}
824
b7b40adb 825// sets the matrix to the respective values
783d8bdf
VZ
826void wxMacCoreGraphicsMatrixData::Set(wxDouble a, wxDouble b, wxDouble c, wxDouble d,
827 wxDouble tx, wxDouble ty)
b7b40adb
SC
828{
829 m_matrix = CGAffineTransformMake(a,b,c,d,tx,ty);
50581042
SC
830}
831
248802d0
RD
832// gets the component valuess of the matrix
833void wxMacCoreGraphicsMatrixData::Get(wxDouble* a, wxDouble* b, wxDouble* c,
834 wxDouble* d, wxDouble* tx, wxDouble* ty) const
835{
836 if (a) *a = m_matrix.a;
837 if (b) *b = m_matrix.b;
838 if (c) *c = m_matrix.c;
839 if (d) *d = m_matrix.d;
840 if (tx) *tx= m_matrix.tx;
841 if (ty) *ty= m_matrix.ty;
842}
843
b7b40adb 844// makes this the inverse matrix
783d8bdf 845void wxMacCoreGraphicsMatrixData::Invert()
1056ddcf 846{
b7b40adb 847 m_matrix = CGAffineTransformInvert( m_matrix );
eec960fa
SC
848}
849
b7b40adb 850// returns true if the elements of the transformation matrix are equal ?
783d8bdf 851bool wxMacCoreGraphicsMatrixData::IsEqual( const wxGraphicsMatrixData* t) const
eec960fa 852{
2701ef7e 853 const CGAffineTransform* tm = (CGAffineTransform*) t->GetNativeMatrix();
23a3e8fb 854#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
6e25bf0f 855 if ( CGAffineTransformEqualToTransform!=NULL )
23a3e8fb
SC
856 {
857 return CGAffineTransformEqualToTransform(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix()));
858 }
859 else
860#endif
861 {
862 return (
863 m_matrix.a == tm->a &&
864 m_matrix.b == tm->b &&
865 m_matrix.c == tm->c &&
866 m_matrix.d == tm->d &&
867 m_matrix.tx == tm->tx &&
868 m_matrix.ty == tm->ty ) ;
869 }
1056ddcf
SC
870}
871
b7b40adb 872// return true if this is the identity matrix
e3ff3591 873bool wxMacCoreGraphicsMatrixData::IsIdentity() const
50581042 874{
2701ef7e
SC
875 return ( m_matrix.a == 1 && m_matrix.d == 1 &&
876 m_matrix.b == 0 && m_matrix.d == 0 && m_matrix.tx == 0 && m_matrix.ty == 0);
50581042
SC
877}
878
b7b40adb
SC
879//
880// transformation
881//
882
883// add the translation to this matrix
783d8bdf 884void wxMacCoreGraphicsMatrixData::Translate( wxDouble dx , wxDouble dy )
50581042 885{
b7b40adb
SC
886 m_matrix = CGAffineTransformTranslate( m_matrix, dx, dy);
887}
50581042 888
b7b40adb 889// add the scale to this matrix
783d8bdf 890void wxMacCoreGraphicsMatrixData::Scale( wxDouble xScale , wxDouble yScale )
b7b40adb
SC
891{
892 m_matrix = CGAffineTransformScale( m_matrix, xScale, yScale);
50581042
SC
893}
894
b7b40adb 895// add the rotation to this matrix (radians)
783d8bdf 896void wxMacCoreGraphicsMatrixData::Rotate( wxDouble angle )
eec960fa 897{
b7b40adb 898 m_matrix = CGAffineTransformRotate( m_matrix, angle);
eec960fa
SC
899}
900
b7b40adb
SC
901//
902// apply the transforms
903//
eec960fa 904
b7b40adb 905// applies that matrix to the point
e3ff3591 906void wxMacCoreGraphicsMatrixData::TransformPoint( wxDouble *x, wxDouble *y ) const
50581042 907{
2701ef7e 908 CGPoint pt = CGPointApplyAffineTransform( CGPointMake(*x,*y), m_matrix);
783d8bdf 909
2701ef7e
SC
910 *x = pt.x;
911 *y = pt.y;
1056ddcf
SC
912}
913
b7b40adb 914// applies the matrix except for translations
e3ff3591 915void wxMacCoreGraphicsMatrixData::TransformDistance( wxDouble *dx, wxDouble *dy ) const
1056ddcf 916{
2701ef7e
SC
917 CGSize sz = CGSizeApplyAffineTransform( CGSizeMake(*dx,*dy) , m_matrix );
918 *dx = sz.width;
919 *dy = sz.height;
b7b40adb
SC
920}
921
922// returns the native representation
783d8bdf 923void * wxMacCoreGraphicsMatrixData::GetNativeMatrix() const
1056ddcf 924{
b7b40adb 925 return (void*) &m_matrix;
50581042
SC
926}
927
b7b40adb
SC
928//
929// Graphics Path
930//
931
932//-----------------------------------------------------------------------------
933// wxMacCoreGraphicsPath declaration
934//-----------------------------------------------------------------------------
935
e3ff3591 936class WXDLLEXPORT wxMacCoreGraphicsPathData : public wxGraphicsPathData
50581042 937{
b7b40adb 938public :
e3ff3591 939 wxMacCoreGraphicsPathData( wxGraphicsRenderer* renderer, CGMutablePathRef path = NULL);
783d8bdf 940
e3ff3591 941 ~wxMacCoreGraphicsPathData();
1056ddcf 942
e3ff3591 943 virtual wxGraphicsObjectRefData *Clone() const;
1056ddcf 944
b7b40adb
SC
945 // begins a new subpath at (x,y)
946 virtual void MoveToPoint( wxDouble x, wxDouble y );
1056ddcf 947
783d8bdf 948 // adds a straight line from the current point to (x,y)
b7b40adb
SC
949 virtual void AddLineToPoint( wxDouble x, wxDouble y );
950
951 // adds a cubic Bezier curve from the current point, using two control points and an end point
952 virtual void AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y );
953
954 // closes the current sub-path
955 virtual void CloseSubpath();
956
957 // gets the last point of the current path, (0,0) if not yet set
e3ff3591 958 virtual void GetCurrentPoint( wxDouble* x, wxDouble* y) const;
b7b40adb
SC
959
960 // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
961 virtual void AddArc( wxDouble x, wxDouble y, wxDouble r, wxDouble startAngle, wxDouble endAngle, bool clockwise );
962
963 //
783d8bdf 964 // These are convenience functions which - if not available natively will be assembled
b7b40adb
SC
965 // using the primitives from above
966 //
967
968 // adds a quadratic Bezier curve from the current point, using a control point and an end point
969 virtual void AddQuadCurveToPoint( wxDouble cx, wxDouble cy, wxDouble x, wxDouble y );
970
783d8bdf 971 // appends a rectangle as a new closed subpath
b7b40adb
SC
972 virtual void AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
973
974 // appends an ellipsis as a new closed subpath fitting the passed rectangle
975 virtual void AddCircle( wxDouble x, wxDouble y, wxDouble r );
976
977 // 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)
978 virtual void AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r );
979
783d8bdf
VZ
980 // adds another path
981 virtual void AddPath( const wxGraphicsPathData* path );
982
983 // returns the native path
984 virtual void * GetNativePath() const { return m_path; }
985
986 // give the native path returned by GetNativePath() back (there might be some deallocations necessary)
987 virtual void UnGetNativePath(void *p) const {}
988
989 // transforms each point of this path by the matrix
990 virtual void Transform( const wxGraphicsMatrixData* matrix );
991
992 // gets the bounding box enclosing all points (possibly including control points)
993 virtual void GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *y) const;
994
995 virtual bool Contains( wxDouble x, wxDouble y, int fillStyle = wxODDEVEN_RULE) const;
b7b40adb
SC
996private :
997 CGMutablePathRef m_path;
998};
999
1000//-----------------------------------------------------------------------------
1001// wxMacCoreGraphicsPath implementation
1002//-----------------------------------------------------------------------------
1003
e3ff3591 1004wxMacCoreGraphicsPathData::wxMacCoreGraphicsPathData( wxGraphicsRenderer* renderer, CGMutablePathRef path) : wxGraphicsPathData(renderer)
b7b40adb 1005{
783d8bdf
VZ
1006 if ( path )
1007 m_path = path;
1008 else
1009 m_path = CGPathCreateMutable();
50581042
SC
1010}
1011
e3ff3591 1012wxMacCoreGraphicsPathData::~wxMacCoreGraphicsPathData()
50581042 1013{
b7b40adb
SC
1014 CGPathRelease( m_path );
1015}
50581042 1016
783d8bdf 1017wxGraphicsObjectRefData* wxMacCoreGraphicsPathData::Clone() const
b7b40adb 1018{
783d8bdf
VZ
1019 wxMacCoreGraphicsPathData* clone = new wxMacCoreGraphicsPathData(GetRenderer(),CGPathCreateMutableCopy(m_path));
1020 return clone ;
b7b40adb 1021}
1056ddcf 1022
1056ddcf 1023
b7b40adb 1024// opens (starts) a new subpath
e3ff3591 1025void wxMacCoreGraphicsPathData::MoveToPoint( wxDouble x1 , wxDouble y1 )
b7b40adb
SC
1026{
1027 CGPathMoveToPoint( m_path , NULL , x1 , y1 );
1028}
1056ddcf 1029
e3ff3591 1030void wxMacCoreGraphicsPathData::AddLineToPoint( wxDouble x1 , wxDouble y1 )
b7b40adb
SC
1031{
1032 CGPathAddLineToPoint( m_path , NULL , x1 , y1 );
50581042
SC
1033}
1034
e3ff3591 1035void wxMacCoreGraphicsPathData::AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y )
50581042 1036{
b7b40adb 1037 CGPathAddCurveToPoint( m_path , NULL , cx1 , cy1 , cx2, cy2, x , y );
50581042
SC
1038}
1039
e3ff3591 1040void wxMacCoreGraphicsPathData::AddQuadCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble x, wxDouble y )
50581042 1041{
b7b40adb 1042 CGPathAddQuadCurveToPoint( m_path , NULL , cx1 , cy1 , x , y );
50581042
SC
1043}
1044
e3ff3591 1045void wxMacCoreGraphicsPathData::AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
50581042 1046{
b7b40adb
SC
1047 CGRect cgRect = { { x , y } , { w , h } };
1048 CGPathAddRect( m_path , NULL , cgRect );
1049}
50581042 1050
e3ff3591 1051void wxMacCoreGraphicsPathData::AddCircle( wxDouble x, wxDouble y , wxDouble r )
b7b40adb
SC
1052{
1053 CGPathAddArc( m_path , NULL , x , y , r , 0.0 , 2 * M_PI , true );
50581042
SC
1054}
1055
b7b40adb 1056// adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
e3ff3591 1057void wxMacCoreGraphicsPathData::AddArc( wxDouble x, wxDouble y, wxDouble r, wxDouble startAngle, wxDouble endAngle, bool clockwise )
50581042 1058{
b7b40adb 1059 // inverse direction as we the 'normal' state is a y axis pointing down, ie mirrored to the standard core graphics setup
783d8bdf 1060 CGPathAddArc( m_path, NULL , x, y, r, startAngle, endAngle, !clockwise);
50581042
SC
1061}
1062
e3ff3591 1063void wxMacCoreGraphicsPathData::AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r )
50581042 1064{
783d8bdf 1065 CGPathAddArcToPoint( m_path, NULL , x1, y1, x2, y2, r);
50581042
SC
1066}
1067
e3ff3591 1068void wxMacCoreGraphicsPathData::AddPath( const wxGraphicsPathData* path )
50581042 1069{
783d8bdf 1070 CGPathAddPath( m_path , NULL, (CGPathRef) path->GetNativePath() );
50581042
SC
1071}
1072
b7b40adb 1073// closes the current subpath
e3ff3591 1074void wxMacCoreGraphicsPathData::CloseSubpath()
50581042 1075{
b7b40adb 1076 CGPathCloseSubpath( m_path );
50581042
SC
1077}
1078
b7b40adb 1079// gets the last point of the current path, (0,0) if not yet set
e3ff3591 1080void wxMacCoreGraphicsPathData::GetCurrentPoint( wxDouble* x, wxDouble* y) const
50581042 1081{
b7b40adb 1082 CGPoint p = CGPathGetCurrentPoint( m_path );
e3ff3591
SC
1083 *x = p.x;
1084 *y = p.y;
50581042
SC
1085}
1086
b7b40adb 1087// transforms each point of this path by the matrix
e3ff3591 1088void wxMacCoreGraphicsPathData::Transform( const wxGraphicsMatrixData* matrix )
50581042 1089{
783d8bdf
VZ
1090 CGMutablePathRef p = CGPathCreateMutable() ;
1091 CGPathAddPath( p, (CGAffineTransform*) matrix->GetNativeMatrix() , m_path );
1092 CGPathRelease( m_path );
1093 m_path = p;
50581042
SC
1094}
1095
b7b40adb 1096// gets the bounding box enclosing all points (possibly including control points)
e3ff3591 1097void wxMacCoreGraphicsPathData::GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) const
50581042 1098{
783d8bdf
VZ
1099 CGRect bounds = CGPathGetBoundingBox( m_path ) ;
1100 *x = bounds.origin.x;
1101 *y = bounds.origin.y;
1102 *w = bounds.size.width;
1103 *h = bounds.size.height;
50581042
SC
1104}
1105
e3ff3591 1106bool wxMacCoreGraphicsPathData::Contains( wxDouble x, wxDouble y, int fillStyle) const
50581042 1107{
23a3e8fb 1108#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
6e25bf0f 1109 if ( CGPathContainsPoint!=NULL )
23a3e8fb
SC
1110 {
1111 return CGPathContainsPoint( m_path, NULL, CGPointMake(x,y), fillStyle == wxODDEVEN_RULE );
1112 }
1113 else
1114#endif
1115 {
1116 // TODO : implementation for 10.3
1117 CGRect bounds = CGPathGetBoundingBox( m_path ) ;
1118 return CGRectContainsPoint( bounds, CGPointMake(x,y) ) == 1;
1119 }
50581042
SC
1120}
1121
b7b40adb
SC
1122//
1123// Graphics Context
1124//
50581042 1125
b7b40adb
SC
1126//-----------------------------------------------------------------------------
1127// wxMacCoreGraphicsContext declaration
1128//-----------------------------------------------------------------------------
1129
1130class WXDLLEXPORT wxMacCoreGraphicsContext : public wxGraphicsContext
1131{
1132public:
1133 wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext );
783d8bdf 1134
b7b40adb 1135 wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, WindowRef window );
783d8bdf 1136
b7b40adb 1137 wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, wxWindow* window );
783d8bdf 1138
b7b40adb 1139 wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer);
783d8bdf 1140
b7b40adb 1141 wxMacCoreGraphicsContext();
783d8bdf 1142
b7b40adb 1143 ~wxMacCoreGraphicsContext();
50581042 1144
783d8bdf 1145 void Init();
50581042 1146
b7b40adb
SC
1147 // push the current state of the context, ie the transformation matrix on a stack
1148 virtual void PushState();
50581042 1149
b7b40adb
SC
1150 // pops a stored state from the stack
1151 virtual void PopState();
50581042 1152
b7b40adb
SC
1153 // clips drawings to the region
1154 virtual void Clip( const wxRegion &region );
50581042 1155
b7b40adb
SC
1156 // clips drawings to the rect
1157 virtual void Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
783d8bdf 1158
b7b40adb
SC
1159 // resets the clipping to original extent
1160 virtual void ResetClip();
50581042 1161
b7b40adb 1162 virtual void * GetNativeContext();
783d8bdf 1163
277ccdaf 1164 bool SetLogicalFunction( int function );
b7b40adb
SC
1165 //
1166 // transformation
1167 //
783d8bdf 1168
b7b40adb
SC
1169 // translate
1170 virtual void Translate( wxDouble dx , wxDouble dy );
50581042 1171
b7b40adb
SC
1172 // scale
1173 virtual void Scale( wxDouble xScale , wxDouble yScale );
50581042 1174
b7b40adb
SC
1175 // rotate (radians)
1176 virtual void Rotate( wxDouble angle );
50581042 1177
783d8bdf
VZ
1178 // concatenates this transform with the current transform of this context
1179 virtual void ConcatTransform( const wxGraphicsMatrix& matrix );
50581042 1180
783d8bdf
VZ
1181 // sets the transform of this context
1182 virtual void SetTransform( const wxGraphicsMatrix& matrix );
50581042 1183
783d8bdf
VZ
1184 // gets the matrix of this context
1185 virtual wxGraphicsMatrix GetTransform() const;
b7b40adb
SC
1186 //
1187 // setting the paint
1188 //
783d8bdf 1189
b7b40adb 1190 // strokes along a path with the current pen
e3ff3591 1191 virtual void StrokePath( const wxGraphicsPath &path );
50581042 1192
b7b40adb 1193 // fills a path with the current brush
e3ff3591 1194 virtual void FillPath( const wxGraphicsPath &path, int fillStyle = wxODDEVEN_RULE );
50581042 1195
b7b40adb 1196 // draws a path by first filling and then stroking
e3ff3591 1197 virtual void DrawPath( const wxGraphicsPath &path, int fillStyle = wxODDEVEN_RULE );
b7b40adb
SC
1198
1199 virtual bool ShouldOffset() const
a54bae7a 1200 {
b7b40adb 1201 int penwidth = 0 ;
a26b7ab2 1202 if ( !m_pen.IsNull() )
50581042 1203 {
783d8bdf 1204 penwidth = (int)((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->GetWidth();
b7b40adb
SC
1205 if ( penwidth == 0 )
1206 penwidth = 1;
50581042 1207 }
783d8bdf 1208 return ( penwidth % 2 ) == 1;
50581042 1209 }
b7b40adb
SC
1210 //
1211 // text
1212 //
783d8bdf 1213
b7b40adb 1214 virtual void DrawText( const wxString &str, wxDouble x, wxDouble y );
50581042 1215
b7b40adb 1216 virtual void DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle );
50581042 1217
b7b40adb
SC
1218 virtual void GetTextExtent( const wxString &text, wxDouble *width, wxDouble *height,
1219 wxDouble *descent, wxDouble *externalLeading ) const;
50581042 1220
b7b40adb 1221 virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const;
50581042 1222
b7b40adb
SC
1223 //
1224 // image support
1225 //
50581042 1226
b7b40adb 1227 virtual void DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
50581042 1228
b7b40adb 1229 virtual void DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
50581042 1230
b7b40adb 1231 void SetNativeContext( CGContextRef cg );
783d8bdf 1232
b7b40adb
SC
1233 DECLARE_NO_COPY_CLASS(wxMacCoreGraphicsContext)
1234 DECLARE_DYNAMIC_CLASS(wxMacCoreGraphicsContext)
50581042 1235
b7b40adb
SC
1236private:
1237 void EnsureIsValid();
783d8bdf 1238
b7b40adb 1239 CGContextRef m_cgContext;
783d8bdf
VZ
1240 WindowRef m_windowRef;
1241 bool m_releaseContext;
549be226 1242 CGAffineTransform m_windowTransform;
783d8bdf
VZ
1243
1244 wxMacCFRefHolder<HIShapeRef> m_clipRgn;
50581042
SC
1245};
1246
b7b40adb
SC
1247//-----------------------------------------------------------------------------
1248// device context implementation
1249//
1250// more and more of the dc functionality should be implemented by calling
1251// the appropricate wxMacCoreGraphicsContext, but we will have to do that step by step
1252// also coordinate conversions should be moved to native matrix ops
1253//-----------------------------------------------------------------------------
50581042 1254
b7b40adb
SC
1255// we always stock two context states, one at entry, to be able to preserve the
1256// state we were called with, the other one after changing to HI Graphics orientation
1257// (this one is used for getting back clippings etc)
50581042 1258
b7b40adb
SC
1259//-----------------------------------------------------------------------------
1260// wxMacCoreGraphicsContext implementation
1261//-----------------------------------------------------------------------------
50581042 1262
b7b40adb 1263IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsContext, wxGraphicsContext)
50581042 1264
b7b40adb
SC
1265void wxMacCoreGraphicsContext::Init()
1266{
1267 m_cgContext = NULL;
783d8bdf 1268 m_releaseContext = false;
b7b40adb 1269 m_windowRef = NULL;
549be226 1270
b7b40adb
SC
1271 HIRect r = CGRectMake(0,0,0,0);
1272 m_clipRgn.Set(HIShapeCreateWithRect(&r));
1273}
50581042 1274
b7b40adb
SC
1275wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext ) : wxGraphicsContext(renderer)
1276{
783d8bdf 1277 Init();
549be226 1278 SetNativeContext(cgcontext);
b7b40adb 1279}
50581042 1280
b7b40adb
SC
1281wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, WindowRef window ): wxGraphicsContext(renderer)
1282{
783d8bdf
VZ
1283 Init();
1284 m_windowRef = window;
b7b40adb 1285}
50581042 1286
b7b40adb
SC
1287wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, wxWindow* window ): wxGraphicsContext(renderer)
1288{
783d8bdf
VZ
1289 Init();
1290 m_windowRef = (WindowRef) window->MacGetTopLevelWindowRef();
549be226
SC
1291 int originX , originY;
1292 originX = originY = 0;
1293 window->MacWindowToRootWindow( &originX , &originY );
1294 Rect bounds;
1295 GetWindowBounds( m_windowRef, kWindowContentRgn, &bounds );
1296
1297 m_windowTransform = CGAffineTransformMakeTranslation( 0 , bounds.bottom - bounds.top );
1298 m_windowTransform = CGAffineTransformScale( m_windowTransform , 1 , -1 );
1299 m_windowTransform = CGAffineTransformTranslate( m_windowTransform, originX, originY ) ;
b7b40adb 1300}
50581042 1301
b7b40adb
SC
1302wxMacCoreGraphicsContext::wxMacCoreGraphicsContext(wxGraphicsRenderer* renderer) : wxGraphicsContext(renderer)
1303{
783d8bdf 1304 Init();
b7b40adb 1305}
50581042 1306
b7b40adb
SC
1307wxMacCoreGraphicsContext::wxMacCoreGraphicsContext() : wxGraphicsContext(NULL)
1308{
783d8bdf 1309 Init();
b7b40adb
SC
1310 wxLogDebug(wxT("Illegal Constructor called"));
1311}
50581042 1312
b7b40adb
SC
1313wxMacCoreGraphicsContext::~wxMacCoreGraphicsContext()
1314{
549be226 1315 SetNativeContext(NULL);
b7b40adb 1316}
50581042 1317
b7b40adb
SC
1318void wxMacCoreGraphicsContext::EnsureIsValid()
1319{
783d8bdf
VZ
1320 if ( !m_cgContext )
1321 {
1322 OSStatus status = QDBeginCGContext( GetWindowPort( m_windowRef ) , &m_cgContext );
1323 wxASSERT_MSG( status == noErr , wxT("Cannot nest wxDCs on the same window") );
549be226
SC
1324
1325 CGContextConcatCTM( m_cgContext, m_windowTransform );
69541a2e
SC
1326 CGContextSaveGState( m_cgContext );
1327 m_releaseContext = true;
1328 if ( !HIShapeIsEmpty(m_clipRgn) )
1329 {
1acf0e5c
SC
1330 // the clip region is in device coordinates, so we convert this again to user coordinates
1331 wxMacCFRefHolder<HIMutableShapeRef> hishape ;
1332 hishape.Set( HIShapeCreateMutableCopy( m_clipRgn ) );
1333 CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero,m_windowTransform);
1334 HIShapeOffset( hishape, -transformedOrigin.x, -transformedOrigin.y );
1335 HIShapeReplacePathInCGContext( hishape, m_cgContext );
69541a2e
SC
1336 CGContextClip( m_cgContext );
1337 }
1338 CGContextSaveGState( m_cgContext );
1339 }
b7b40adb 1340}
50581042 1341
277ccdaf
SC
1342bool wxMacCoreGraphicsContext::SetLogicalFunction( int function )
1343{
1344 if (m_logicalFunction == function)
1345 return true;
1346
1347 EnsureIsValid();
1348
1349 bool retval = false;
1350
1351 if ( function == wxCOPY )
1352 {
1353 retval = true;
1354#if wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
1355 if ( CGContextSetBlendMode != NULL )
1356 {
1357 CGContextSetBlendMode( m_cgContext, kCGBlendModeNormal );
a54bae7a 1358 CGContextSetShouldAntialias( m_cgContext, true );
277ccdaf
SC
1359 }
1360#endif
1361 }
1362 else if ( function == wxINVERT || function == wxXOR )
1363 {
1364#if wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
1365 if ( CGContextSetBlendMode != NULL )
1366 {
1367 // change color to white
1368 CGContextSetBlendMode( m_cgContext, kCGBlendModeExclusion );
a54bae7a 1369 CGContextSetShouldAntialias( m_cgContext, false );
277ccdaf
SC
1370 retval = true;
1371 }
1372#endif
1373 }
1374
1375 if (retval)
1376 m_logicalFunction = function;
1377 return retval ;
1378}
50581042 1379
b7b40adb
SC
1380void wxMacCoreGraphicsContext::Clip( const wxRegion &region )
1381{
783d8bdf
VZ
1382 if( m_cgContext )
1383 {
1384 HIShapeRef shape = HIShapeCreateWithQDRgn( (RgnHandle) region.GetWXHRGN() );
1385 HIShapeReplacePathInCGContext( shape, m_cgContext );
1386 CGContextClip( m_cgContext );
1387 CFRelease( shape );
1388 }
1389 else
1390 {
1acf0e5c
SC
1391 // this offsetting to device coords is not really correct, but since we cannot apply affine transforms
1392 // to regions we try at least to have correct translations
1393 wxMacCFRefHolder<HIShapeRef> hishape ;
1394 hishape.Set( HIShapeCreateWithQDRgn( (RgnHandle) region.GetWXHRGN() ));
1395 HIMutableShapeRef mutableShape = HIShapeCreateMutableCopy( hishape );
1396
1397 CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero, m_windowTransform );
1398 HIShapeOffset( mutableShape, transformedOrigin.x, transformedOrigin.y );
1399 m_clipRgn.Set(mutableShape);
783d8bdf 1400 }
b7b40adb 1401}
50581042 1402
b7b40adb
SC
1403// clips drawings to the rect
1404void wxMacCoreGraphicsContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
1405{
783d8bdf
VZ
1406 HIRect r = CGRectMake( x , y , w , h );
1407 if ( m_cgContext )
1408 {
1409 CGContextClipToRect( m_cgContext, r );
1410 }
1411 else
1412 {
1acf0e5c
SC
1413 // the clipping itself must be stored as device coordinates, otherwise
1414 // we cannot apply it back correctly
1415 r.origin= CGPointApplyAffineTransform( r.origin, m_windowTransform );
783d8bdf
VZ
1416 m_clipRgn.Set(HIShapeCreateWithRect(&r));
1417 }
1418}
1419
1420 // resets the clipping to original extent
b7b40adb
SC
1421void wxMacCoreGraphicsContext::ResetClip()
1422{
783d8bdf
VZ
1423 if ( m_cgContext )
1424 {
a7868cdf
SC
1425 // there is no way for clearing the clip, we can only revert to the stored
1426 // state, but then we have to make sure everything else is NOT restored
1427 CGAffineTransform transform = CGContextGetCTM( m_cgContext );
783d8bdf
VZ
1428 CGContextRestoreGState( m_cgContext );
1429 CGContextSaveGState( m_cgContext );
a7868cdf
SC
1430 CGAffineTransform transformNew = CGContextGetCTM( m_cgContext );
1431 transformNew = CGAffineTransformInvert( transformNew ) ;
1432 CGContextConcatCTM( m_cgContext, transformNew);
1433 CGContextConcatCTM( m_cgContext, transform);
783d8bdf
VZ
1434 }
1435 else
1436 {
b7b40adb
SC
1437 HIRect r = CGRectMake(0,0,0,0);
1438 m_clipRgn.Set(HIShapeCreateWithRect(&r));
783d8bdf 1439 }
b7b40adb 1440}
50581042 1441
e3ff3591 1442void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath &path )
b7b40adb 1443{
a26b7ab2 1444 if ( m_pen.IsNull() )
b7b40adb 1445 return ;
50581042 1446
783d8bdf
VZ
1447 EnsureIsValid();
1448
b7b40adb
SC
1449 bool offset = ShouldOffset();
1450 if ( offset )
1451 CGContextTranslateCTM( m_cgContext, 0.5, 0.5 );
50581042 1452
a26b7ab2 1453 ((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->Apply(this);
e3ff3591 1454 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
b7b40adb 1455 CGContextStrokePath( m_cgContext );
50581042 1456
b7b40adb
SC
1457 if ( offset )
1458 CGContextTranslateCTM( m_cgContext, -0.5, -0.5 );
1459}
50581042 1460
e3ff3591 1461void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , int fillStyle )
783d8bdf 1462{
a26b7ab2 1463 if ( !m_brush.IsNull() && ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
b7b40adb
SC
1464 {
1465 // when using shading, we cannot draw pen and brush at the same time
1466 // revert to the base implementation of first filling and then stroking
1467 wxGraphicsContext::DrawPath( path, fillStyle );
1468 return;
1469 }
783d8bdf 1470
b7b40adb 1471 CGPathDrawingMode mode = kCGPathFill ;
a26b7ab2 1472 if ( m_brush.IsNull() )
b7b40adb 1473 {
a26b7ab2 1474 if ( m_pen.IsNull() )
b7b40adb
SC
1475 return;
1476 else
1477 mode = kCGPathStroke;
1478 }
1479 else
1480 {
a26b7ab2 1481 if ( m_pen.IsNull() )
b7b40adb
SC
1482 {
1483 if ( fillStyle == wxODDEVEN_RULE )
1484 mode = kCGPathEOFill;
1485 else
1486 mode = kCGPathFill;
1487 }
1488 else
1489 {
1490 if ( fillStyle == wxODDEVEN_RULE )
1491 mode = kCGPathEOFillStroke;
1492 else
1493 mode = kCGPathFillStroke;
1494 }
1495 }
783d8bdf
VZ
1496
1497 EnsureIsValid();
50581042 1498
a26b7ab2
SC
1499 if ( !m_brush.IsNull() )
1500 ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->Apply(this);
1501 if ( !m_pen.IsNull() )
1502 ((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->Apply(this);
50581042 1503
b7b40adb 1504 bool offset = ShouldOffset();
783d8bdf 1505
b7b40adb
SC
1506 if ( offset )
1507 CGContextTranslateCTM( m_cgContext, 0.5, 0.5 );
50581042 1508
e3ff3591 1509 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
b7b40adb 1510 CGContextDrawPath( m_cgContext , mode );
50581042 1511
b7b40adb
SC
1512 if ( offset )
1513 CGContextTranslateCTM( m_cgContext, -0.5, -0.5 );
1514}
50581042 1515
e3ff3591 1516void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath &path , int fillStyle )
b7b40adb 1517{
a26b7ab2 1518 if ( m_brush.IsNull() )
b7b40adb 1519 return;
783d8bdf
VZ
1520
1521 EnsureIsValid();
1522
a26b7ab2 1523 if ( ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
b7b40adb
SC
1524 {
1525 CGContextSaveGState( m_cgContext );
e3ff3591 1526 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
b7b40adb 1527 CGContextClip( m_cgContext );
a26b7ab2 1528 CGContextDrawShading( m_cgContext, ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->GetShading() );
b7b40adb
SC
1529 CGContextRestoreGState( m_cgContext);
1530 }
1531 else
783d8bdf 1532 {
a26b7ab2 1533 ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->Apply(this);
e3ff3591 1534 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
b7b40adb
SC
1535 if ( fillStyle == wxODDEVEN_RULE )
1536 CGContextEOFillPath( m_cgContext );
1537 else
1538 CGContextFillPath( m_cgContext );
50581042
SC
1539 }
1540}
1541
b7b40adb 1542void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg )
50581042 1543{
b7b40adb
SC
1544 // we allow either setting or clearing but not replacing
1545 wxASSERT( m_cgContext == NULL || cg == NULL );
50581042 1546
549be226
SC
1547 if ( m_cgContext )
1548 {
1549 // TODO : when is this necessary - should we add a Flush() method ? CGContextSynchronize( m_cgContext );
1550 CGContextRestoreGState( m_cgContext );
1551 CGContextRestoreGState( m_cgContext );
1552 if ( m_releaseContext )
1553 QDEndCGContext( GetWindowPort( m_windowRef ) , &m_cgContext);
1554 else
1555 CGContextRelease(m_cgContext);
1556 }
1557
1558
b7b40adb 1559 m_cgContext = cg;
549be226
SC
1560
1561 // FIXME: This check is needed because currently we need to use a DC/GraphicsContext
783d8bdf 1562 // in order to get font properties, like wxFont::GetPixelSize, but since we don't have
549be226
SC
1563 // a native window attached to use, I create a wxGraphicsContext with a NULL CGContextRef
1564 // for this one operation.
783d8bdf 1565
549be226 1566 // When wxFont::GetPixelSize on Mac no longer needs a graphics context, this check
783d8bdf 1567 // can be removed.
549be226
SC
1568 if (m_cgContext)
1569 {
1570 CGContextRetain(m_cgContext);
1571 CGContextSaveGState( m_cgContext );
1572 CGContextSaveGState( m_cgContext );
783d8bdf 1573 m_releaseContext = false;
549be226 1574 }
b7b40adb 1575}
50581042 1576
783d8bdf 1577void wxMacCoreGraphicsContext::Translate( wxDouble dx , wxDouble dy )
b7b40adb 1578{
783d8bdf 1579 if ( m_cgContext )
549be226
SC
1580 CGContextTranslateCTM( m_cgContext, dx, dy );
1581 else
1582 m_windowTransform = CGAffineTransformTranslate(m_windowTransform,dx,dy);
b7b40adb 1583}
50581042 1584
b7b40adb
SC
1585void wxMacCoreGraphicsContext::Scale( wxDouble xScale , wxDouble yScale )
1586{
783d8bdf 1587 if ( m_cgContext )
549be226
SC
1588 CGContextScaleCTM( m_cgContext , xScale , yScale );
1589 else
1590 m_windowTransform = CGAffineTransformScale(m_windowTransform,xScale,yScale);
b7b40adb 1591}
50581042 1592
b7b40adb
SC
1593void wxMacCoreGraphicsContext::Rotate( wxDouble angle )
1594{
783d8bdf 1595 if ( m_cgContext )
549be226
SC
1596 CGContextRotateCTM( m_cgContext , angle );
1597 else
1598 m_windowTransform = CGAffineTransformRotate(m_windowTransform,angle);
b7b40adb 1599}
50581042 1600
783d8bdf 1601void wxMacCoreGraphicsContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
b7b40adb 1602{
783d8bdf
VZ
1603 EnsureIsValid();
1604
b7b40adb
SC
1605 CGImageRef image = (CGImageRef)( bmp.CGImageCreate() );
1606 HIRect r = CGRectMake( x , y , w , h );
5f547a58
SC
1607 if ( bmp.GetDepth() == 1 )
1608 {
1609 // is is a mask, the '1' in the mask tell where to draw the current brush
1610 if ( !m_brush.IsNull() )
1611 {
1612 if ( ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
1613 {
1614 // TODO clip to mask
1615 /*
1616 CGContextSaveGState( m_cgContext );
1617 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
1618 CGContextClip( m_cgContext );
1619 CGContextDrawShading( m_cgContext, ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->GetShading() );
1620 CGContextRestoreGState( m_cgContext);
1621 */
1622 }
1623 else
1624 {
1625 ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->Apply(this);
1626 HIViewDrawCGImage( m_cgContext , &r , image );
1627 }
1628 }
1629 }
1630 else
1631 {
1632 HIViewDrawCGImage( m_cgContext , &r , image );
1633 }
b7b40adb
SC
1634 CGImageRelease( image );
1635}
50581042 1636
783d8bdf 1637void wxMacCoreGraphicsContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
b7b40adb 1638{
783d8bdf
VZ
1639 EnsureIsValid();
1640
b7b40adb
SC
1641 CGRect r = CGRectMake( 00 , 00 , w , h );
1642 CGContextSaveGState( m_cgContext );
1643 CGContextTranslateCTM( m_cgContext, x , y + h );
1644 CGContextScaleCTM( m_cgContext, 1, -1 );
1645 PlotIconRefInContext( m_cgContext , &r , kAlignNone , kTransformNone ,
1646 NULL , kPlotIconRefNormalFlags , MAC_WXHICON( icon.GetHICON() ) );
1647 CGContextRestoreGState( m_cgContext );
1648}
50581042 1649
b7b40adb
SC
1650void wxMacCoreGraphicsContext::PushState()
1651{
783d8bdf
VZ
1652 EnsureIsValid();
1653
b7b40adb
SC
1654 CGContextSaveGState( m_cgContext );
1655}
50581042 1656
783d8bdf 1657void wxMacCoreGraphicsContext::PopState()
b7b40adb 1658{
783d8bdf
VZ
1659 EnsureIsValid();
1660
b7b40adb 1661 CGContextRestoreGState( m_cgContext );
50581042
SC
1662}
1663
783d8bdf 1664void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y )
50581042
SC
1665{
1666 DrawText(str, x, y, 0.0);
1667}
1668
783d8bdf 1669void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle )
50581042 1670{
a26b7ab2 1671 if ( m_font.IsNull() )
b7b40adb 1672 return;
783d8bdf
VZ
1673
1674 EnsureIsValid();
1675
50581042
SC
1676 OSStatus status = noErr;
1677 ATSUTextLayout atsuLayout;
1678 UniCharCount chars = str.length();
1679 UniChar* ubuf = NULL;
1680
1681#if SIZEOF_WCHAR_T == 4
1682 wxMBConvUTF16 converter;
1683#if wxUSE_UNICODE
1684 size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 );
1685 ubuf = (UniChar*) malloc( unicharlen + 2 );
1686 converter.WC2MB( (char*) ubuf , str.wc_str(), unicharlen + 2 );
1687#else
1688 const wxWCharBuffer wchar = str.wc_str( wxConvLocal );
1689 size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 );
1690 ubuf = (UniChar*) malloc( unicharlen + 2 );
1691 converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 );
1692#endif
1693 chars = unicharlen / 2;
1694#else
1695#if wxUSE_UNICODE
1696 ubuf = (UniChar*) str.wc_str();
1697#else
1698 wxWCharBuffer wchar = str.wc_str( wxConvLocal );
1699 chars = wxWcslen( wchar.data() );
1700 ubuf = (UniChar*) wchar.data();
1701#endif
1702#endif
1703
a26b7ab2 1704 ATSUStyle style = (((wxMacCoreGraphicsFontData*)m_font.GetRefData())->GetATSUStyle());
50581042 1705 status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
b7b40adb 1706 &chars , &style , &atsuLayout );
50581042
SC
1707
1708 wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the rotated text") );
1709
1710 status = ::ATSUSetTransientFontMatching( atsuLayout , true );
1711 wxASSERT_MSG( status == noErr , wxT("couldn't setup transient font matching") );
1712
1713 int iAngle = int( angle * RAD2DEG );
1714 if ( abs(iAngle) > 0 )
1715 {
1716 Fixed atsuAngle = IntToFixed( iAngle );
1717 ATSUAttributeTag atsuTags[] =
1718 {
1719 kATSULineRotationTag ,
1720 };
1721 ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1722 {
1723 sizeof( Fixed ) ,
1724 };
1725 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1726 {
1727 &atsuAngle ,
1728 };
1729 status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag),
1730 atsuTags, atsuSizes, atsuValues );
1731 }
1732
1733 {
1734 ATSUAttributeTag atsuTags[] =
1735 {
1736 kATSUCGContextTag ,
1737 };
1738 ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1739 {
1740 sizeof( CGContextRef ) ,
1741 };
1742 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1743 {
1744 &m_cgContext ,
1745 };
1746 status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag),
1747 atsuTags, atsuSizes, atsuValues );
1748 }
1749
1750 ATSUTextMeasurement textBefore, textAfter;
1751 ATSUTextMeasurement ascent, descent;
1752
1753 status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1754 &textBefore , &textAfter, &ascent , &descent );
1755
1756 wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
1757
1758 Rect rect;
74b357dd
SC
1759 x += (int)(sin(angle) * FixedToInt(ascent));
1760 y += (int)(cos(angle) * FixedToInt(ascent));
50581042
SC
1761
1762 status = ::ATSUMeasureTextImage( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1763 IntToFixed(x) , IntToFixed(y) , &rect );
1764 wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
1765
1766 CGContextSaveGState(m_cgContext);
1767 CGContextTranslateCTM(m_cgContext, x, y);
1768 CGContextScaleCTM(m_cgContext, 1, -1);
1769 status = ::ATSUDrawText( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1770 IntToFixed(0) , IntToFixed(0) );
1771
1772 wxASSERT_MSG( status == noErr , wxT("couldn't draw the rotated text") );
1773
1774 CGContextRestoreGState(m_cgContext);
1775
1776 ::ATSUDisposeTextLayout(atsuLayout);
1777
1778#if SIZEOF_WCHAR_T == 4
1779 free( ubuf );
1780#endif
1781}
783d8bdf 1782
50581042
SC
1783void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
1784 wxDouble *descent, wxDouble *externalLeading ) const
1785{
a26b7ab2 1786 wxCHECK_RET( !m_font.IsNull(), wxT("wxDC(cg)::DoGetTextExtent - no valid font set") );
50581042
SC
1787
1788 OSStatus status = noErr;
783d8bdf 1789
50581042
SC
1790 ATSUTextLayout atsuLayout;
1791 UniCharCount chars = str.length();
1792 UniChar* ubuf = NULL;
1793
1794#if SIZEOF_WCHAR_T == 4
1795 wxMBConvUTF16 converter;
1796#if wxUSE_UNICODE
1797 size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 );
1798 ubuf = (UniChar*) malloc( unicharlen + 2 );
1799 converter.WC2MB( (char*) ubuf , str.wc_str(), unicharlen + 2 );
1800#else
1801 const wxWCharBuffer wchar = str.wc_str( wxConvLocal );
1802 size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 );
1803 ubuf = (UniChar*) malloc( unicharlen + 2 );
1804 converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 );
1805#endif
1806 chars = unicharlen / 2;
1807#else
1808#if wxUSE_UNICODE
1809 ubuf = (UniChar*) str.wc_str();
1810#else
1811 wxWCharBuffer wchar = str.wc_str( wxConvLocal );
1812 chars = wxWcslen( wchar.data() );
1813 ubuf = (UniChar*) wchar.data();
1814#endif
1815#endif
1816
a26b7ab2 1817 ATSUStyle style = (((wxMacCoreGraphicsFontData*)m_font.GetRefData())->GetATSUStyle());
50581042 1818 status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
b7b40adb 1819 &chars , &style , &atsuLayout );
50581042
SC
1820
1821 wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the text") );
1822
1823 ATSUTextMeasurement textBefore, textAfter;
1824 ATSUTextMeasurement textAscent, textDescent;
1825
1826 status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1827 &textBefore , &textAfter, &textAscent , &textDescent );
1828
1829 if ( height )
1830 *height = FixedToInt(textAscent + textDescent);
1831 if ( descent )
1832 *descent = FixedToInt(textDescent);
1833 if ( externalLeading )
1834 *externalLeading = 0;
1835 if ( width )
1836 *width = FixedToInt(textAfter - textBefore);
1837
1838 ::ATSUDisposeTextLayout(atsuLayout);
b9d495a0
SC
1839#if SIZEOF_WCHAR_T == 4
1840 free( ubuf ) ;
1841#endif
50581042
SC
1842}
1843
783d8bdf 1844void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const
50581042
SC
1845{
1846 widths.Empty();
1847 widths.Add(0, text.length());
1848
1849 if (text.empty())
1850 return;
1851
1852 ATSUTextLayout atsuLayout;
1853 UniCharCount chars = text.length();
1854 UniChar* ubuf = NULL;
1855
1856#if SIZEOF_WCHAR_T == 4
1857 wxMBConvUTF16 converter;
1858#if wxUSE_UNICODE
1859 size_t unicharlen = converter.WC2MB( NULL , text.wc_str() , 0 );
1860 ubuf = (UniChar*) malloc( unicharlen + 2 );
1861 converter.WC2MB( (char*) ubuf , text.wc_str(), unicharlen + 2 );
1862#else
1863 const wxWCharBuffer wchar = text.wc_str( wxConvLocal );
1864 size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 );
1865 ubuf = (UniChar*) malloc( unicharlen + 2 );
1866 converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 );
1867#endif
1868 chars = unicharlen / 2;
1869#else
1870#if wxUSE_UNICODE
1871 ubuf = (UniChar*) text.wc_str();
1872#else
1873 wxWCharBuffer wchar = text.wc_str( wxConvLocal );
1874 chars = wxWcslen( wchar.data() );
1875 ubuf = (UniChar*) wchar.data();
1876#endif
1877#endif
1878
a26b7ab2 1879 ATSUStyle style = (((wxMacCoreGraphicsFontData*)m_font.GetRefData())->GetATSUStyle());
83b96a06 1880 ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
b7b40adb 1881 &chars , &style , &atsuLayout );
50581042
SC
1882
1883 for ( int pos = 0; pos < (int)chars; pos ++ )
1884 {
1885 unsigned long actualNumberOfBounds = 0;
1886 ATSTrapezoid glyphBounds;
1887
1888 // We get a single bound, since the text should only require one. If it requires more, there is an issue
1889 OSStatus result;
1890 result = ATSUGetGlyphBounds( atsuLayout, 0, 0, kATSUFromTextBeginning, pos + 1,
1891 kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds );
1892 if (result != noErr || actualNumberOfBounds != 1 )
1893 return;
1894
1895 widths[pos] = FixedToInt( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
1896 //unsigned char uch = s[i];
1897 }
1898
1899 ::ATSUDisposeTextLayout(atsuLayout);
b9d495a0
SC
1900#if SIZEOF_WCHAR_T == 4
1901 free( ubuf ) ;
1902#endif
50581042
SC
1903}
1904
783d8bdf 1905void * wxMacCoreGraphicsContext::GetNativeContext()
50581042 1906{
783d8bdf 1907 return m_cgContext;
b7b40adb 1908}
50581042 1909
b7b40adb 1910// concatenates this transform with the current transform of this context
e3ff3591 1911void wxMacCoreGraphicsContext::ConcatTransform( const wxGraphicsMatrix& matrix )
b7b40adb 1912{
549be226
SC
1913 if ( m_cgContext )
1914 CGContextConcatCTM( m_cgContext, *(CGAffineTransform*) matrix.GetNativeMatrix());
1915 else
1916 m_windowTransform = CGAffineTransformConcat(m_windowTransform, *(CGAffineTransform*) matrix.GetNativeMatrix());
b7b40adb 1917}
50581042 1918
b7b40adb 1919// sets the transform of this context
e3ff3591 1920void wxMacCoreGraphicsContext::SetTransform( const wxGraphicsMatrix& matrix )
b7b40adb 1921{
549be226
SC
1922 if ( m_cgContext )
1923 {
1924 CGAffineTransform transform = CGContextGetCTM( m_cgContext );
1925 transform = CGAffineTransformInvert( transform ) ;
1926 CGContextConcatCTM( m_cgContext, transform);
1927 CGContextConcatCTM( m_cgContext, *(CGAffineTransform*) matrix.GetNativeMatrix());
1928 }
1929 else
1930 {
1931 m_windowTransform = *(CGAffineTransform*) matrix.GetNativeMatrix();
1932 }
b7b40adb 1933}
50581042 1934
b7b40adb 1935// gets the matrix of this context
e3ff3591 1936wxGraphicsMatrix wxMacCoreGraphicsContext::GetTransform() const
b7b40adb 1937{
daa6105f 1938 wxGraphicsMatrix m = CreateMatrix();
549be226
SC
1939 *((CGAffineTransform*) m.GetNativeMatrix()) = ( m_cgContext == NULL ? m_windowTransform :
1940 CGContextGetCTM( m_cgContext ));
daa6105f 1941 return m;
b7b40adb 1942}
50581042 1943
b7b40adb
SC
1944//
1945// Renderer
1946//
50581042 1947
b7b40adb
SC
1948//-----------------------------------------------------------------------------
1949// wxMacCoreGraphicsRenderer declaration
1950//-----------------------------------------------------------------------------
50581042 1951
b7b40adb
SC
1952class WXDLLIMPEXP_CORE wxMacCoreGraphicsRenderer : public wxGraphicsRenderer
1953{
1954public :
1955 wxMacCoreGraphicsRenderer() {}
50581042 1956
b7b40adb
SC
1957 virtual ~wxMacCoreGraphicsRenderer() {}
1958
783d8bdf
VZ
1959 // Context
1960
1961 virtual wxGraphicsContext * CreateContext( const wxWindowDC& dc);
b7b40adb 1962
783d8bdf 1963 virtual wxGraphicsContext * CreateContextFromNativeContext( void * context );
b7b40adb 1964
783d8bdf 1965 virtual wxGraphicsContext * CreateContextFromNativeWindow( void * window );
b7b40adb 1966
783d8bdf 1967 virtual wxGraphicsContext * CreateContext( wxWindow* window );
ad667945
SC
1968
1969 virtual wxGraphicsContext * CreateMeasuringContext();
783d8bdf
VZ
1970
1971 // Path
b7b40adb 1972
e3ff3591 1973 virtual wxGraphicsPath CreatePath();
b7b40adb 1974
783d8bdf
VZ
1975 // Matrix
1976
1977 virtual wxGraphicsMatrix CreateMatrix( wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
1978 wxDouble tx=0.0, wxDouble ty=0.0);
b7b40adb
SC
1979
1980
a26b7ab2 1981 virtual wxGraphicsPen CreatePen(const wxPen& pen) ;
783d8bdf 1982
a26b7ab2 1983 virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) ;
783d8bdf 1984
b7b40adb 1985 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
783d8bdf 1986 virtual wxGraphicsBrush CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
b7b40adb
SC
1987 const wxColour&c1, const wxColour&c2) ;
1988
783d8bdf 1989 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
b7b40adb 1990 // with radius r and color cColor
a26b7ab2 1991 virtual wxGraphicsBrush CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
b7b40adb
SC
1992 const wxColour &oColor, const wxColour &cColor) ;
1993
1994 // sets the font
a26b7ab2 1995 virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ;
b7b40adb
SC
1996
1997private :
1998 DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacCoreGraphicsRenderer)
1999} ;
2000
2001//-----------------------------------------------------------------------------
2002// wxMacCoreGraphicsRenderer implementation
2003//-----------------------------------------------------------------------------
2004
2005IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsRenderer,wxGraphicsRenderer)
2006
2007static wxMacCoreGraphicsRenderer gs_MacCoreGraphicsRenderer;
2008
2009wxGraphicsRenderer* wxGraphicsRenderer::GetDefaultRenderer()
2010{
783d8bdf 2011 return &gs_MacCoreGraphicsRenderer;
50581042
SC
2012}
2013
b7b40adb
SC
2014wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxWindowDC& dc)
2015{
2016 return new wxMacCoreGraphicsContext(this,(CGContextRef)dc.GetWindow()->MacGetCGContextRef() );
2017}
2018
2019wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeContext( void * context )
2020{
2021 return new wxMacCoreGraphicsContext(this,(CGContextRef)context);
2022}
2023
2024
2025wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeWindow( void * window )
2026{
2027 return new wxMacCoreGraphicsContext(this,(WindowRef)window);
2028}
2029
2030wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( wxWindow* window )
2031{
783d8bdf 2032 return new wxMacCoreGraphicsContext(this, window );
b7b40adb
SC
2033}
2034
ad667945
SC
2035wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateMeasuringContext()
2036{
2037 return new wxMacCoreGraphicsContext(this);
2038}
2039
b7b40adb
SC
2040// Path
2041
e3ff3591 2042wxGraphicsPath wxMacCoreGraphicsRenderer::CreatePath()
b7b40adb 2043{
e3ff3591
SC
2044 wxGraphicsPath m;
2045 m.SetRefData( new wxMacCoreGraphicsPathData(this));
2046 return m;
b7b40adb
SC
2047}
2048
2049
2050// Matrix
2051
783d8bdf
VZ
2052wxGraphicsMatrix wxMacCoreGraphicsRenderer::CreateMatrix( wxDouble a, wxDouble b, wxDouble c, wxDouble d,
2053 wxDouble tx, wxDouble ty)
1056ddcf 2054{
e3ff3591
SC
2055 wxGraphicsMatrix m;
2056 wxMacCoreGraphicsMatrixData* data = new wxMacCoreGraphicsMatrixData( this );
2057 data->Set( a,b,c,d,tx,ty ) ;
2058 m.SetRefData(data);
b7b40adb
SC
2059 return m;
2060}
2061
783d8bdf 2062wxGraphicsPen wxMacCoreGraphicsRenderer::CreatePen(const wxPen& pen)
b7b40adb
SC
2063{
2064 if ( !pen.Ok() || pen.GetStyle() == wxTRANSPARENT )
a26b7ab2 2065 return wxNullGraphicsPen;
b7b40adb 2066 else
a26b7ab2
SC
2067 {
2068 wxGraphicsPen p;
2069 p.SetRefData(new wxMacCoreGraphicsPenData( this, pen ));
2070 return p;
2071 }
1056ddcf
SC
2072}
2073
783d8bdf 2074wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateBrush(const wxBrush& brush )
50581042 2075{
b7b40adb 2076 if ( !brush.Ok() || brush.GetStyle() == wxTRANSPARENT )
a26b7ab2 2077 return wxNullGraphicsBrush;
b7b40adb 2078 else
a26b7ab2
SC
2079 {
2080 wxGraphicsBrush p;
2081 p.SetRefData(new wxMacCoreGraphicsBrushData( this, brush ));
2082 return p;
2083 }
50581042
SC
2084}
2085
b7b40adb 2086// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
783d8bdf
VZ
2087wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
2088 const wxColour&c1, const wxColour&c2)
1056ddcf 2089{
a26b7ab2
SC
2090 wxGraphicsBrush p;
2091 wxMacCoreGraphicsBrushData* d = new wxMacCoreGraphicsBrushData( this );
2092 d->CreateLinearGradientBrush(x1, y1, x2, y2, c1, c2);
2093 p.SetRefData(d);
2094 return p;
1056ddcf
SC
2095}
2096
783d8bdf 2097// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
b7b40adb 2098// with radius r and color cColor
a26b7ab2 2099wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
783d8bdf 2100 const wxColour &oColor, const wxColour &cColor)
1056ddcf 2101{
a26b7ab2
SC
2102 wxGraphicsBrush p;
2103 wxMacCoreGraphicsBrushData* d = new wxMacCoreGraphicsBrushData( this );
2104 d->CreateRadialGradientBrush(xo,yo,xc,yc,radius,oColor,cColor);
2105 p.SetRefData(d);
2106 return p;
1056ddcf
SC
2107}
2108
b7b40adb 2109// sets the font
783d8bdf 2110wxGraphicsFont wxMacCoreGraphicsRenderer::CreateFont( const wxFont &font , const wxColour &col )
513b47e9 2111{
b7b40adb 2112 if ( font.Ok() )
783d8bdf 2113 {
a26b7ab2
SC
2114 wxGraphicsFont p;
2115 p.SetRefData(new wxMacCoreGraphicsFontData( this , font, col ));
2116 return p;
2117 }
b7b40adb 2118 else
a26b7ab2 2119 return wxNullGraphicsFont;
513b47e9
SC
2120}
2121
b7b40adb
SC
2122
2123
50581042 2124#endif // wxMAC_USE_CORE_GRAPHICS