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