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