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