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