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