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