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