]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/graphics.cpp
GTK+ doesn't like slider with min=max values
[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
c07e1e2c 699#if wxMAC_USE_ATSU_TEXT
b7b40adb 700 virtual ATSUStyle GetATSUStyle() { return m_macATSUIStyle; }
c07e1e2c
SC
701#endif
702#if wxMAC_USE_CORE_TEXT
703 CTFontRef GetCTFont() const { return m_ctFont ; }
704#endif
705 wxColour GetColour() const { return m_colour ; }
706
707 bool GetUnderlined() const { return m_underlined ; }
b7b40adb 708private :
c07e1e2c
SC
709 wxColour m_colour;
710 bool m_underlined;
711#if wxMAC_USE_ATSU_TEXT
b7b40adb 712 ATSUStyle m_macATSUIStyle;
c07e1e2c
SC
713#endif
714#if wxMAC_USE_CORE_TEXT
715 wxCFRef< CTFontRef > m_ctFont;
716#endif
b7b40adb 717};
50581042 718
a26b7ab2 719wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col) : wxGraphicsObjectRefData( renderer )
b7b40adb 720{
c07e1e2c
SC
721 m_colour = col;
722 m_underlined = font.GetUnderlined();
783d8bdf 723
d2d8b4db 724#if wxMAC_USE_CORE_TEXT
c07e1e2c
SC
725 m_ctFont.reset( wxCFRetain((CTFontRef) font.MacGetCTFont()) );
726#endif
727#if wxMAC_USE_ATSU_TEXT
e773889d
SC
728 OSStatus status = noErr;
729 m_macATSUIStyle = NULL;
50581042 730
b7b40adb 731 status = ATSUCreateAndCopyStyle( (ATSUStyle) font.MacGetATSUStyle() , &m_macATSUIStyle );
50581042 732
b7b40adb 733 wxASSERT_MSG( status == noErr, wxT("couldn't create ATSU style") );
50581042 734
b7b40adb 735 // we need the scale here ...
50581042 736
b7b40adb 737 Fixed atsuSize = IntToFixed( int( 1 * font.MacGetFontSize()) );
276ee533
SC
738 RGBColor atsuColor ;
739 col.GetRGBColor( &atsuColor );
b7b40adb
SC
740 ATSUAttributeTag atsuTags[] =
741 {
742 kATSUSizeTag ,
743 kATSUColorTag ,
744 };
745 ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
746 {
747 sizeof( Fixed ) ,
748 sizeof( RGBColor ) ,
749 };
750 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
751 {
752 &atsuSize ,
753 &atsuColor ,
754 };
50581042 755
b7b40adb
SC
756 status = ::ATSUSetAttributes(
757 m_macATSUIStyle, sizeof(atsuTags) / sizeof(ATSUAttributeTag) ,
758 atsuTags, atsuSizes, atsuValues);
50581042 759
b7b40adb 760 wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") );
c07e1e2c
SC
761#endif
762#if WXMAC_USE_CG_TEXT
1bd568fa 763#endif
b7b40adb 764}
50581042 765
a26b7ab2 766wxMacCoreGraphicsFontData::~wxMacCoreGraphicsFontData()
b7b40adb 767{
d2d8b4db 768#if wxMAC_USE_CORE_TEXT
c07e1e2c
SC
769#endif
770#if wxMAC_USE_ATSU_TEXT
b7b40adb
SC
771 if ( m_macATSUIStyle )
772 {
773 ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
774 m_macATSUIStyle = NULL;
775 }
c07e1e2c
SC
776#endif
777#if WXMAC_USE_CG_TEXT
1bd568fa 778#endif
b7b40adb 779}
50581042 780
b7b40adb
SC
781//
782// Graphics Matrix
783//
50581042 784
b7b40adb
SC
785//-----------------------------------------------------------------------------
786// wxMacCoreGraphicsMatrix declaration
787//-----------------------------------------------------------------------------
50581042 788
e3ff3591 789class WXDLLIMPEXP_CORE wxMacCoreGraphicsMatrixData : public wxGraphicsMatrixData
b7b40adb
SC
790{
791public :
783d8bdf
VZ
792 wxMacCoreGraphicsMatrixData(wxGraphicsRenderer* renderer) ;
793
794 virtual ~wxMacCoreGraphicsMatrixData() ;
795
e3ff3591 796 virtual wxGraphicsObjectRefData *Clone() const ;
b7b40adb 797
783d8bdf
VZ
798 // concatenates the matrix
799 virtual void Concat( const wxGraphicsMatrixData *t );
800
801 // sets the matrix to the respective values
802 virtual void Set(wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
803 wxDouble tx=0.0, wxDouble ty=0.0);
804
248802d0
RD
805 // gets the component valuess of the matrix
806 virtual void Get(wxDouble* a=NULL, wxDouble* b=NULL, wxDouble* c=NULL,
807 wxDouble* d=NULL, wxDouble* tx=NULL, wxDouble* ty=NULL) const;
808
783d8bdf
VZ
809 // makes this the inverse matrix
810 virtual void Invert();
811
812 // returns true if the elements of the transformation matrix are equal ?
e3ff3591 813 virtual bool IsEqual( const wxGraphicsMatrixData* t) const ;
783d8bdf
VZ
814
815 // return true if this is the identity matrix
816 virtual bool IsIdentity() const;
817
50581042 818 //
b7b40adb 819 // transformation
50581042 820 //
783d8bdf 821
b7b40adb
SC
822 // add the translation to this matrix
823 virtual void Translate( wxDouble dx , wxDouble dy );
50581042 824
b7b40adb
SC
825 // add the scale to this matrix
826 virtual void Scale( wxDouble xScale , wxDouble yScale );
50581042 827
b7b40adb 828 // add the rotation to this matrix (radians)
783d8bdf
VZ
829 virtual void Rotate( wxDouble angle );
830
50581042 831 //
b7b40adb 832 // apply the transforms
50581042 833 //
783d8bdf
VZ
834
835 // applies that matrix to the point
836 virtual void TransformPoint( wxDouble *x, wxDouble *y ) const;
837
838 // applies the matrix except for translations
839 virtual void TransformDistance( wxDouble *dx, wxDouble *dy ) const;
840
841 // returns the native representation
842 virtual void * GetNativeMatrix() const;
843
b7b40adb
SC
844private :
845 CGAffineTransform m_matrix;
b7b40adb 846} ;
50581042 847
50581042 848//-----------------------------------------------------------------------------
b7b40adb 849// wxMacCoreGraphicsMatrix implementation
50581042
SC
850//-----------------------------------------------------------------------------
851
e3ff3591 852wxMacCoreGraphicsMatrixData::wxMacCoreGraphicsMatrixData(wxGraphicsRenderer* renderer) : wxGraphicsMatrixData(renderer)
b7b40adb 853{
b7b40adb 854}
eec960fa 855
783d8bdf 856wxMacCoreGraphicsMatrixData::~wxMacCoreGraphicsMatrixData()
50581042 857{
50581042
SC
858}
859
783d8bdf 860wxGraphicsObjectRefData *wxMacCoreGraphicsMatrixData::Clone() const
50581042 861{
e3ff3591 862 wxMacCoreGraphicsMatrixData* m = new wxMacCoreGraphicsMatrixData(GetRenderer()) ;
b7b40adb
SC
863 m->m_matrix = m_matrix ;
864 return m;
865}
866
867// concatenates the matrix
783d8bdf 868void wxMacCoreGraphicsMatrixData::Concat( const wxGraphicsMatrixData *t )
b7b40adb
SC
869{
870 m_matrix = CGAffineTransformConcat(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix()) );
871}
872
b7b40adb 873// sets the matrix to the respective values
783d8bdf
VZ
874void wxMacCoreGraphicsMatrixData::Set(wxDouble a, wxDouble b, wxDouble c, wxDouble d,
875 wxDouble tx, wxDouble ty)
b7b40adb
SC
876{
877 m_matrix = CGAffineTransformMake(a,b,c,d,tx,ty);
50581042
SC
878}
879
248802d0
RD
880// gets the component valuess of the matrix
881void wxMacCoreGraphicsMatrixData::Get(wxDouble* a, wxDouble* b, wxDouble* c,
882 wxDouble* d, wxDouble* tx, wxDouble* ty) const
883{
884 if (a) *a = m_matrix.a;
885 if (b) *b = m_matrix.b;
886 if (c) *c = m_matrix.c;
887 if (d) *d = m_matrix.d;
888 if (tx) *tx= m_matrix.tx;
889 if (ty) *ty= m_matrix.ty;
890}
891
b7b40adb 892// makes this the inverse matrix
783d8bdf 893void wxMacCoreGraphicsMatrixData::Invert()
1056ddcf 894{
b7b40adb 895 m_matrix = CGAffineTransformInvert( m_matrix );
eec960fa
SC
896}
897
b7b40adb 898// returns true if the elements of the transformation matrix are equal ?
783d8bdf 899bool wxMacCoreGraphicsMatrixData::IsEqual( const wxGraphicsMatrixData* t) const
eec960fa 900{
e1673e52 901 return CGAffineTransformEqualToTransform(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix()));
1056ddcf
SC
902}
903
b7b40adb 904// return true if this is the identity matrix
e3ff3591 905bool wxMacCoreGraphicsMatrixData::IsIdentity() const
50581042 906{
2701ef7e
SC
907 return ( m_matrix.a == 1 && m_matrix.d == 1 &&
908 m_matrix.b == 0 && m_matrix.d == 0 && m_matrix.tx == 0 && m_matrix.ty == 0);
50581042
SC
909}
910
b7b40adb
SC
911//
912// transformation
913//
914
915// add the translation to this matrix
783d8bdf 916void wxMacCoreGraphicsMatrixData::Translate( wxDouble dx , wxDouble dy )
50581042 917{
b7b40adb
SC
918 m_matrix = CGAffineTransformTranslate( m_matrix, dx, dy);
919}
50581042 920
b7b40adb 921// add the scale to this matrix
783d8bdf 922void wxMacCoreGraphicsMatrixData::Scale( wxDouble xScale , wxDouble yScale )
b7b40adb
SC
923{
924 m_matrix = CGAffineTransformScale( m_matrix, xScale, yScale);
50581042
SC
925}
926
b7b40adb 927// add the rotation to this matrix (radians)
783d8bdf 928void wxMacCoreGraphicsMatrixData::Rotate( wxDouble angle )
eec960fa 929{
b7b40adb 930 m_matrix = CGAffineTransformRotate( m_matrix, angle);
eec960fa
SC
931}
932
b7b40adb
SC
933//
934// apply the transforms
935//
eec960fa 936
b7b40adb 937// applies that matrix to the point
e3ff3591 938void wxMacCoreGraphicsMatrixData::TransformPoint( wxDouble *x, wxDouble *y ) const
50581042 939{
2701ef7e 940 CGPoint pt = CGPointApplyAffineTransform( CGPointMake(*x,*y), m_matrix);
783d8bdf 941
2701ef7e
SC
942 *x = pt.x;
943 *y = pt.y;
1056ddcf
SC
944}
945
b7b40adb 946// applies the matrix except for translations
e3ff3591 947void wxMacCoreGraphicsMatrixData::TransformDistance( wxDouble *dx, wxDouble *dy ) const
1056ddcf 948{
2701ef7e
SC
949 CGSize sz = CGSizeApplyAffineTransform( CGSizeMake(*dx,*dy) , m_matrix );
950 *dx = sz.width;
951 *dy = sz.height;
b7b40adb
SC
952}
953
954// returns the native representation
783d8bdf 955void * wxMacCoreGraphicsMatrixData::GetNativeMatrix() const
1056ddcf 956{
b7b40adb 957 return (void*) &m_matrix;
50581042
SC
958}
959
b7b40adb
SC
960//
961// Graphics Path
962//
963
964//-----------------------------------------------------------------------------
965// wxMacCoreGraphicsPath declaration
966//-----------------------------------------------------------------------------
967
e3ff3591 968class WXDLLEXPORT wxMacCoreGraphicsPathData : public wxGraphicsPathData
50581042 969{
b7b40adb 970public :
e3ff3591 971 wxMacCoreGraphicsPathData( wxGraphicsRenderer* renderer, CGMutablePathRef path = NULL);
783d8bdf 972
e3ff3591 973 ~wxMacCoreGraphicsPathData();
1056ddcf 974
e3ff3591 975 virtual wxGraphicsObjectRefData *Clone() const;
1056ddcf 976
b7b40adb
SC
977 // begins a new subpath at (x,y)
978 virtual void MoveToPoint( wxDouble x, wxDouble y );
1056ddcf 979
783d8bdf 980 // adds a straight line from the current point to (x,y)
b7b40adb
SC
981 virtual void AddLineToPoint( wxDouble x, wxDouble y );
982
983 // adds a cubic Bezier curve from the current point, using two control points and an end point
984 virtual void AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y );
985
986 // closes the current sub-path
987 virtual void CloseSubpath();
988
989 // gets the last point of the current path, (0,0) if not yet set
e3ff3591 990 virtual void GetCurrentPoint( wxDouble* x, wxDouble* y) const;
b7b40adb
SC
991
992 // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
993 virtual void AddArc( wxDouble x, wxDouble y, wxDouble r, wxDouble startAngle, wxDouble endAngle, bool clockwise );
994
995 //
783d8bdf 996 // These are convenience functions which - if not available natively will be assembled
b7b40adb
SC
997 // using the primitives from above
998 //
999
1000 // adds a quadratic Bezier curve from the current point, using a control point and an end point
1001 virtual void AddQuadCurveToPoint( wxDouble cx, wxDouble cy, wxDouble x, wxDouble y );
1002
783d8bdf 1003 // appends a rectangle as a new closed subpath
b7b40adb
SC
1004 virtual void AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
1005
1006 // appends an ellipsis as a new closed subpath fitting the passed rectangle
1007 virtual void AddCircle( wxDouble x, wxDouble y, wxDouble r );
1008
1009 // draws a an arc to two tangents connecting (current) to (x1,y1) and (x1,y1) to (x2,y2), also a straight line from (current) to (x1,y1)
1010 virtual void AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r );
1011
783d8bdf
VZ
1012 // adds another path
1013 virtual void AddPath( const wxGraphicsPathData* path );
1014
1015 // returns the native path
1016 virtual void * GetNativePath() const { return m_path; }
1017
1018 // give the native path returned by GetNativePath() back (there might be some deallocations necessary)
89954433 1019 virtual void UnGetNativePath(void *WXUNUSED(p)) const {}
783d8bdf
VZ
1020
1021 // transforms each point of this path by the matrix
1022 virtual void Transform( const wxGraphicsMatrixData* matrix );
1023
1024 // gets the bounding box enclosing all points (possibly including control points)
1025 virtual void GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *y) const;
1026
1027 virtual bool Contains( wxDouble x, wxDouble y, int fillStyle = wxODDEVEN_RULE) const;
b7b40adb
SC
1028private :
1029 CGMutablePathRef m_path;
1030};
1031
1032//-----------------------------------------------------------------------------
1033// wxMacCoreGraphicsPath implementation
1034//-----------------------------------------------------------------------------
1035
e3ff3591 1036wxMacCoreGraphicsPathData::wxMacCoreGraphicsPathData( wxGraphicsRenderer* renderer, CGMutablePathRef path) : wxGraphicsPathData(renderer)
b7b40adb 1037{
783d8bdf
VZ
1038 if ( path )
1039 m_path = path;
1040 else
1041 m_path = CGPathCreateMutable();
50581042
SC
1042}
1043
e3ff3591 1044wxMacCoreGraphicsPathData::~wxMacCoreGraphicsPathData()
50581042 1045{
b7b40adb
SC
1046 CGPathRelease( m_path );
1047}
50581042 1048
783d8bdf 1049wxGraphicsObjectRefData* wxMacCoreGraphicsPathData::Clone() const
b7b40adb 1050{
783d8bdf
VZ
1051 wxMacCoreGraphicsPathData* clone = new wxMacCoreGraphicsPathData(GetRenderer(),CGPathCreateMutableCopy(m_path));
1052 return clone ;
b7b40adb 1053}
1056ddcf 1054
1056ddcf 1055
b7b40adb 1056// opens (starts) a new subpath
e3ff3591 1057void wxMacCoreGraphicsPathData::MoveToPoint( wxDouble x1 , wxDouble y1 )
b7b40adb
SC
1058{
1059 CGPathMoveToPoint( m_path , NULL , x1 , y1 );
1060}
1056ddcf 1061
e3ff3591 1062void wxMacCoreGraphicsPathData::AddLineToPoint( wxDouble x1 , wxDouble y1 )
b7b40adb
SC
1063{
1064 CGPathAddLineToPoint( m_path , NULL , x1 , y1 );
50581042
SC
1065}
1066
e3ff3591 1067void wxMacCoreGraphicsPathData::AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y )
50581042 1068{
b7b40adb 1069 CGPathAddCurveToPoint( m_path , NULL , cx1 , cy1 , cx2, cy2, x , y );
50581042
SC
1070}
1071
e3ff3591 1072void wxMacCoreGraphicsPathData::AddQuadCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble x, wxDouble y )
50581042 1073{
b7b40adb 1074 CGPathAddQuadCurveToPoint( m_path , NULL , cx1 , cy1 , x , y );
50581042
SC
1075}
1076
e3ff3591 1077void wxMacCoreGraphicsPathData::AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
50581042 1078{
b7b40adb
SC
1079 CGRect cgRect = { { x , y } , { w , h } };
1080 CGPathAddRect( m_path , NULL , cgRect );
1081}
50581042 1082
e3ff3591 1083void wxMacCoreGraphicsPathData::AddCircle( wxDouble x, wxDouble y , wxDouble r )
b7b40adb
SC
1084{
1085 CGPathAddArc( m_path , NULL , x , y , r , 0.0 , 2 * M_PI , true );
50581042
SC
1086}
1087
b7b40adb 1088// adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
e3ff3591 1089void wxMacCoreGraphicsPathData::AddArc( wxDouble x, wxDouble y, wxDouble r, wxDouble startAngle, wxDouble endAngle, bool clockwise )
50581042 1090{
b7b40adb 1091 // inverse direction as we the 'normal' state is a y axis pointing down, ie mirrored to the standard core graphics setup
783d8bdf 1092 CGPathAddArc( m_path, NULL , x, y, r, startAngle, endAngle, !clockwise);
50581042
SC
1093}
1094
e3ff3591 1095void wxMacCoreGraphicsPathData::AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r )
50581042 1096{
783d8bdf 1097 CGPathAddArcToPoint( m_path, NULL , x1, y1, x2, y2, r);
50581042
SC
1098}
1099
e3ff3591 1100void wxMacCoreGraphicsPathData::AddPath( const wxGraphicsPathData* path )
50581042 1101{
783d8bdf 1102 CGPathAddPath( m_path , NULL, (CGPathRef) path->GetNativePath() );
50581042
SC
1103}
1104
b7b40adb 1105// closes the current subpath
e3ff3591 1106void wxMacCoreGraphicsPathData::CloseSubpath()
50581042 1107{
b7b40adb 1108 CGPathCloseSubpath( m_path );
50581042
SC
1109}
1110
b7b40adb 1111// gets the last point of the current path, (0,0) if not yet set
e3ff3591 1112void wxMacCoreGraphicsPathData::GetCurrentPoint( wxDouble* x, wxDouble* y) const
50581042 1113{
b7b40adb 1114 CGPoint p = CGPathGetCurrentPoint( m_path );
e3ff3591
SC
1115 *x = p.x;
1116 *y = p.y;
50581042
SC
1117}
1118
b7b40adb 1119// transforms each point of this path by the matrix
e3ff3591 1120void wxMacCoreGraphicsPathData::Transform( const wxGraphicsMatrixData* matrix )
50581042 1121{
783d8bdf
VZ
1122 CGMutablePathRef p = CGPathCreateMutable() ;
1123 CGPathAddPath( p, (CGAffineTransform*) matrix->GetNativeMatrix() , m_path );
1124 CGPathRelease( m_path );
1125 m_path = p;
50581042
SC
1126}
1127
b7b40adb 1128// gets the bounding box enclosing all points (possibly including control points)
e3ff3591 1129void wxMacCoreGraphicsPathData::GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) const
50581042 1130{
783d8bdf
VZ
1131 CGRect bounds = CGPathGetBoundingBox( m_path ) ;
1132 *x = bounds.origin.x;
1133 *y = bounds.origin.y;
1134 *w = bounds.size.width;
1135 *h = bounds.size.height;
50581042
SC
1136}
1137
e3ff3591 1138bool wxMacCoreGraphicsPathData::Contains( wxDouble x, wxDouble y, int fillStyle) const
50581042 1139{
e1673e52 1140 return CGPathContainsPoint( m_path, NULL, CGPointMake(x,y), fillStyle == wxODDEVEN_RULE );
50581042
SC
1141}
1142
b7b40adb
SC
1143//
1144// Graphics Context
1145//
50581042 1146
b7b40adb
SC
1147//-----------------------------------------------------------------------------
1148// wxMacCoreGraphicsContext declaration
1149//-----------------------------------------------------------------------------
1150
1151class WXDLLEXPORT wxMacCoreGraphicsContext : public wxGraphicsContext
1152{
1153public:
6239ee05 1154 wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext, wxDouble width = 0, wxDouble height = 0 );
783d8bdf 1155
b7b40adb 1156 wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, WindowRef window );
783d8bdf 1157
b7b40adb 1158 wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, wxWindow* window );
783d8bdf 1159
b7b40adb 1160 wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer);
783d8bdf 1161
b7b40adb 1162 wxMacCoreGraphicsContext();
783d8bdf 1163
b7b40adb 1164 ~wxMacCoreGraphicsContext();
50581042 1165
783d8bdf 1166 void Init();
50581042 1167
6239ee05
SC
1168 // returns the size of the graphics context in device coordinates
1169 virtual void GetSize( wxDouble* width, wxDouble* height);
1170
1171 virtual void StartPage( wxDouble width, wxDouble height );
1172
1173 virtual void EndPage();
1174
1175 virtual void Flush();
1176
b7b40adb
SC
1177 // push the current state of the context, ie the transformation matrix on a stack
1178 virtual void PushState();
50581042 1179
b7b40adb
SC
1180 // pops a stored state from the stack
1181 virtual void PopState();
50581042 1182
b7b40adb
SC
1183 // clips drawings to the region
1184 virtual void Clip( const wxRegion &region );
50581042 1185
b7b40adb
SC
1186 // clips drawings to the rect
1187 virtual void Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
783d8bdf 1188
b7b40adb
SC
1189 // resets the clipping to original extent
1190 virtual void ResetClip();
50581042 1191
b7b40adb 1192 virtual void * GetNativeContext();
783d8bdf 1193
277ccdaf 1194 bool SetLogicalFunction( int function );
b7b40adb
SC
1195 //
1196 // transformation
1197 //
783d8bdf 1198
b7b40adb
SC
1199 // translate
1200 virtual void Translate( wxDouble dx , wxDouble dy );
50581042 1201
b7b40adb
SC
1202 // scale
1203 virtual void Scale( wxDouble xScale , wxDouble yScale );
50581042 1204
b7b40adb
SC
1205 // rotate (radians)
1206 virtual void Rotate( wxDouble angle );
50581042 1207
783d8bdf
VZ
1208 // concatenates this transform with the current transform of this context
1209 virtual void ConcatTransform( const wxGraphicsMatrix& matrix );
50581042 1210
783d8bdf
VZ
1211 // sets the transform of this context
1212 virtual void SetTransform( const wxGraphicsMatrix& matrix );
50581042 1213
783d8bdf
VZ
1214 // gets the matrix of this context
1215 virtual wxGraphicsMatrix GetTransform() const;
b7b40adb
SC
1216 //
1217 // setting the paint
1218 //
783d8bdf 1219
b7b40adb 1220 // strokes along a path with the current pen
e3ff3591 1221 virtual void StrokePath( const wxGraphicsPath &path );
50581042 1222
b7b40adb 1223 // fills a path with the current brush
e3ff3591 1224 virtual void FillPath( const wxGraphicsPath &path, int fillStyle = wxODDEVEN_RULE );
50581042 1225
b7b40adb 1226 // draws a path by first filling and then stroking
e3ff3591 1227 virtual void DrawPath( const wxGraphicsPath &path, int fillStyle = wxODDEVEN_RULE );
b7b40adb
SC
1228
1229 virtual bool ShouldOffset() const
a54bae7a 1230 {
b7b40adb 1231 int penwidth = 0 ;
a26b7ab2 1232 if ( !m_pen.IsNull() )
50581042 1233 {
783d8bdf 1234 penwidth = (int)((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->GetWidth();
b7b40adb
SC
1235 if ( penwidth == 0 )
1236 penwidth = 1;
50581042 1237 }
783d8bdf 1238 return ( penwidth % 2 ) == 1;
50581042 1239 }
b7b40adb
SC
1240 //
1241 // text
1242 //
783d8bdf 1243
b7b40adb 1244 virtual void DrawText( const wxString &str, wxDouble x, wxDouble y );
50581042 1245
b7b40adb 1246 virtual void DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle );
50581042 1247
b7b40adb
SC
1248 virtual void GetTextExtent( const wxString &text, wxDouble *width, wxDouble *height,
1249 wxDouble *descent, wxDouble *externalLeading ) const;
50581042 1250
b7b40adb 1251 virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const;
50581042 1252
b7b40adb
SC
1253 //
1254 // image support
1255 //
50581042 1256
b7b40adb 1257 virtual void DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
50581042 1258
b7b40adb 1259 virtual void DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
50581042 1260
b7b40adb 1261 void SetNativeContext( CGContextRef cg );
783d8bdf 1262
b7b40adb
SC
1263 DECLARE_NO_COPY_CLASS(wxMacCoreGraphicsContext)
1264 DECLARE_DYNAMIC_CLASS(wxMacCoreGraphicsContext)
50581042 1265
b7b40adb
SC
1266private:
1267 void EnsureIsValid();
783d8bdf 1268
b7b40adb 1269 CGContextRef m_cgContext;
783d8bdf
VZ
1270 WindowRef m_windowRef;
1271 bool m_releaseContext;
549be226 1272 CGAffineTransform m_windowTransform;
6239ee05
SC
1273 wxDouble m_width;
1274 wxDouble m_height;
783d8bdf
VZ
1275
1276 wxMacCFRefHolder<HIShapeRef> m_clipRgn;
50581042
SC
1277};
1278
b7b40adb
SC
1279//-----------------------------------------------------------------------------
1280// device context implementation
1281//
1282// more and more of the dc functionality should be implemented by calling
1283// the appropricate wxMacCoreGraphicsContext, but we will have to do that step by step
1284// also coordinate conversions should be moved to native matrix ops
1285//-----------------------------------------------------------------------------
50581042 1286
b7b40adb
SC
1287// we always stock two context states, one at entry, to be able to preserve the
1288// state we were called with, the other one after changing to HI Graphics orientation
1289// (this one is used for getting back clippings etc)
50581042 1290
b7b40adb
SC
1291//-----------------------------------------------------------------------------
1292// wxMacCoreGraphicsContext implementation
1293//-----------------------------------------------------------------------------
50581042 1294
b7b40adb 1295IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsContext, wxGraphicsContext)
50581042 1296
6239ee05
SC
1297class wxQuartzOffsetHelper
1298{
1299public :
1300 wxQuartzOffsetHelper( CGContextRef cg , bool offset )
1301 {
1302 m_cg = cg;
1303 m_offset = offset;
1304 if ( m_offset )
1305 CGContextTranslateCTM( m_cg, 0.5, 0.5 );
1306 }
1307 ~wxQuartzOffsetHelper( )
1308 {
1309 if ( m_offset )
1310 CGContextTranslateCTM( m_cg, -0.5, -0.5 );
1311 }
1312public :
1313 CGContextRef m_cg;
1314 bool m_offset;
1315} ;
1316
b7b40adb
SC
1317void wxMacCoreGraphicsContext::Init()
1318{
1319 m_cgContext = NULL;
783d8bdf 1320 m_releaseContext = false;
b7b40adb 1321 m_windowRef = NULL;
6239ee05
SC
1322 m_width = 0;
1323 m_height = 0;
549be226 1324
b7b40adb
SC
1325 HIRect r = CGRectMake(0,0,0,0);
1326 m_clipRgn.Set(HIShapeCreateWithRect(&r));
1327}
50581042 1328
6239ee05 1329wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext, wxDouble width, wxDouble height ) : wxGraphicsContext(renderer)
b7b40adb 1330{
783d8bdf 1331 Init();
549be226 1332 SetNativeContext(cgcontext);
6239ee05
SC
1333 m_width = width;
1334 m_height = height;
b7b40adb 1335}
50581042 1336
b7b40adb
SC
1337wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, WindowRef window ): wxGraphicsContext(renderer)
1338{
783d8bdf
VZ
1339 Init();
1340 m_windowRef = window;
b7b40adb 1341}
50581042 1342
b7b40adb
SC
1343wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, wxWindow* window ): wxGraphicsContext(renderer)
1344{
783d8bdf
VZ
1345 Init();
1346 m_windowRef = (WindowRef) window->MacGetTopLevelWindowRef();
549be226
SC
1347 int originX , originY;
1348 originX = originY = 0;
1349 window->MacWindowToRootWindow( &originX , &originY );
549be226 1350
1bd568fa
SC
1351 Rect bounds = { 0,0,0,0 };
1352#ifdef __LP64__
1353#else
1354 GetWindowBounds( m_windowRef, kWindowContentRgn, &bounds );
1355#endif
549be226
SC
1356 m_windowTransform = CGAffineTransformMakeTranslation( 0 , bounds.bottom - bounds.top );
1357 m_windowTransform = CGAffineTransformScale( m_windowTransform , 1 , -1 );
1358 m_windowTransform = CGAffineTransformTranslate( m_windowTransform, originX, originY ) ;
b7b40adb 1359}
50581042 1360
b7b40adb
SC
1361wxMacCoreGraphicsContext::wxMacCoreGraphicsContext(wxGraphicsRenderer* renderer) : wxGraphicsContext(renderer)
1362{
783d8bdf 1363 Init();
b7b40adb 1364}
50581042 1365
b7b40adb
SC
1366wxMacCoreGraphicsContext::wxMacCoreGraphicsContext() : wxGraphicsContext(NULL)
1367{
783d8bdf 1368 Init();
b7b40adb
SC
1369 wxLogDebug(wxT("Illegal Constructor called"));
1370}
50581042 1371
b7b40adb
SC
1372wxMacCoreGraphicsContext::~wxMacCoreGraphicsContext()
1373{
549be226 1374 SetNativeContext(NULL);
b7b40adb 1375}
50581042 1376
6239ee05
SC
1377void wxMacCoreGraphicsContext::GetSize( wxDouble* width, wxDouble* height)
1378{
1379 *width = m_width;
1380 *height = m_height;
1381}
1382
1383
1384void wxMacCoreGraphicsContext::StartPage( wxDouble width, wxDouble height )
1385{
1386 CGRect r;
1387 if ( width != 0 && height != 0)
1388 r = CGRectMake( 0 , 0 , width , height );
1389 else
1390 r = CGRectMake( 0 , 0 , m_width , m_height );
1391
1392 CGContextBeginPage(m_cgContext, &r );
1393// CGContextTranslateCTM( m_cgContext , 0 , height == 0 ? m_height : height );
1394// CGContextScaleCTM( m_cgContext , 1 , -1 );
1395}
1396
1397void wxMacCoreGraphicsContext::EndPage()
1398{
1399 CGContextEndPage(m_cgContext);
1400}
1401
1402void wxMacCoreGraphicsContext::Flush()
1403{
1404 CGContextFlush(m_cgContext);
1405}
1406
b7b40adb
SC
1407void wxMacCoreGraphicsContext::EnsureIsValid()
1408{
783d8bdf
VZ
1409 if ( !m_cgContext )
1410 {
6239ee05
SC
1411 OSStatus status =
1412#ifndef __LP64__
1413 QDBeginCGContext( GetWindowPort( m_windowRef ) , &m_cgContext );
1414#else
1415 paramErr;
1416#endif
783d8bdf 1417 wxASSERT_MSG( status == noErr , wxT("Cannot nest wxDCs on the same window") );
549be226
SC
1418
1419 CGContextConcatCTM( m_cgContext, m_windowTransform );
69541a2e
SC
1420 CGContextSaveGState( m_cgContext );
1421 m_releaseContext = true;
1422 if ( !HIShapeIsEmpty(m_clipRgn) )
1423 {
1acf0e5c
SC
1424 // the clip region is in device coordinates, so we convert this again to user coordinates
1425 wxMacCFRefHolder<HIMutableShapeRef> hishape ;
1426 hishape.Set( HIShapeCreateMutableCopy( m_clipRgn ) );
1427 CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero,m_windowTransform);
1428 HIShapeOffset( hishape, -transformedOrigin.x, -transformedOrigin.y );
1429 HIShapeReplacePathInCGContext( hishape, m_cgContext );
69541a2e
SC
1430 CGContextClip( m_cgContext );
1431 }
1432 CGContextSaveGState( m_cgContext );
1433 }
b7b40adb 1434}
50581042 1435
6239ee05
SC
1436// TODO test whether the private CGContextSetCompositeOperation works under 10.3 (using NSCompositingModes)
1437
277ccdaf
SC
1438bool wxMacCoreGraphicsContext::SetLogicalFunction( int function )
1439{
1440 if (m_logicalFunction == function)
1441 return true;
1442
1443 EnsureIsValid();
1444
1445 bool retval = false;
1446
1447 if ( function == wxCOPY )
1448 {
1449 retval = true;
e1673e52 1450 CGContextSetBlendMode( m_cgContext, kCGBlendModeNormal );
277ccdaf
SC
1451 }
1452 else if ( function == wxINVERT || function == wxXOR )
1453 {
e1673e52
SC
1454 // change color to white
1455 CGContextSetBlendMode( m_cgContext, kCGBlendModeExclusion );
1456 CGContextSetShouldAntialias( m_cgContext, false );
1457 retval = true;
277ccdaf
SC
1458 }
1459
1460 if (retval)
1461 m_logicalFunction = function;
1462 return retval ;
1463}
50581042 1464
b7b40adb
SC
1465void wxMacCoreGraphicsContext::Clip( const wxRegion &region )
1466{
783d8bdf
VZ
1467 if( m_cgContext )
1468 {
82c126e5 1469 HIShapeReplacePathInCGContext( region.GetWXHRGN() , m_cgContext );
783d8bdf 1470 CGContextClip( m_cgContext );
783d8bdf
VZ
1471 }
1472 else
1473 {
1acf0e5c
SC
1474 // this offsetting to device coords is not really correct, but since we cannot apply affine transforms
1475 // to regions we try at least to have correct translations
82c126e5 1476 HIMutableShapeRef mutableShape = HIShapeCreateMutableCopy( region.GetWXHRGN() );
1acf0e5c
SC
1477
1478 CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero, m_windowTransform );
1479 HIShapeOffset( mutableShape, transformedOrigin.x, transformedOrigin.y );
1480 m_clipRgn.Set(mutableShape);
783d8bdf 1481 }
b7b40adb 1482}
50581042 1483
b7b40adb
SC
1484// clips drawings to the rect
1485void wxMacCoreGraphicsContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
1486{
783d8bdf
VZ
1487 HIRect r = CGRectMake( x , y , w , h );
1488 if ( m_cgContext )
1489 {
1490 CGContextClipToRect( m_cgContext, r );
1491 }
1492 else
1493 {
1acf0e5c
SC
1494 // the clipping itself must be stored as device coordinates, otherwise
1495 // we cannot apply it back correctly
1496 r.origin= CGPointApplyAffineTransform( r.origin, m_windowTransform );
783d8bdf
VZ
1497 m_clipRgn.Set(HIShapeCreateWithRect(&r));
1498 }
1499}
1500
1501 // resets the clipping to original extent
b7b40adb
SC
1502void wxMacCoreGraphicsContext::ResetClip()
1503{
783d8bdf
VZ
1504 if ( m_cgContext )
1505 {
a7868cdf
SC
1506 // there is no way for clearing the clip, we can only revert to the stored
1507 // state, but then we have to make sure everything else is NOT restored
1508 CGAffineTransform transform = CGContextGetCTM( m_cgContext );
783d8bdf
VZ
1509 CGContextRestoreGState( m_cgContext );
1510 CGContextSaveGState( m_cgContext );
a7868cdf
SC
1511 CGAffineTransform transformNew = CGContextGetCTM( m_cgContext );
1512 transformNew = CGAffineTransformInvert( transformNew ) ;
1513 CGContextConcatCTM( m_cgContext, transformNew);
1514 CGContextConcatCTM( m_cgContext, transform);
783d8bdf
VZ
1515 }
1516 else
1517 {
b7b40adb
SC
1518 HIRect r = CGRectMake(0,0,0,0);
1519 m_clipRgn.Set(HIShapeCreateWithRect(&r));
783d8bdf 1520 }
b7b40adb 1521}
50581042 1522
e3ff3591 1523void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath &path )
b7b40adb 1524{
a26b7ab2 1525 if ( m_pen.IsNull() )
b7b40adb 1526 return ;
50581042 1527
783d8bdf
VZ
1528 EnsureIsValid();
1529
6239ee05 1530 wxQuartzOffsetHelper helper( m_cgContext , ShouldOffset() );
50581042 1531
a26b7ab2 1532 ((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->Apply(this);
e3ff3591 1533 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
b7b40adb 1534 CGContextStrokePath( m_cgContext );
b7b40adb 1535}
50581042 1536
e3ff3591 1537void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , int fillStyle )
783d8bdf 1538{
a26b7ab2 1539 if ( !m_brush.IsNull() && ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
b7b40adb
SC
1540 {
1541 // when using shading, we cannot draw pen and brush at the same time
1542 // revert to the base implementation of first filling and then stroking
1543 wxGraphicsContext::DrawPath( path, fillStyle );
1544 return;
1545 }
783d8bdf 1546
b7b40adb 1547 CGPathDrawingMode mode = kCGPathFill ;
a26b7ab2 1548 if ( m_brush.IsNull() )
b7b40adb 1549 {
a26b7ab2 1550 if ( m_pen.IsNull() )
b7b40adb
SC
1551 return;
1552 else
1553 mode = kCGPathStroke;
1554 }
1555 else
1556 {
a26b7ab2 1557 if ( m_pen.IsNull() )
b7b40adb
SC
1558 {
1559 if ( fillStyle == wxODDEVEN_RULE )
1560 mode = kCGPathEOFill;
1561 else
1562 mode = kCGPathFill;
1563 }
1564 else
1565 {
1566 if ( fillStyle == wxODDEVEN_RULE )
1567 mode = kCGPathEOFillStroke;
1568 else
1569 mode = kCGPathFillStroke;
1570 }
1571 }
783d8bdf
VZ
1572
1573 EnsureIsValid();
50581042 1574
a26b7ab2
SC
1575 if ( !m_brush.IsNull() )
1576 ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->Apply(this);
1577 if ( !m_pen.IsNull() )
1578 ((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->Apply(this);
50581042 1579
6239ee05 1580 wxQuartzOffsetHelper helper( m_cgContext , ShouldOffset() );
50581042 1581
e3ff3591 1582 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
b7b40adb 1583 CGContextDrawPath( m_cgContext , mode );
b7b40adb 1584}
50581042 1585
e3ff3591 1586void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath &path , int fillStyle )
b7b40adb 1587{
a26b7ab2 1588 if ( m_brush.IsNull() )
b7b40adb 1589 return;
783d8bdf
VZ
1590
1591 EnsureIsValid();
1592
a26b7ab2 1593 if ( ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
b7b40adb
SC
1594 {
1595 CGContextSaveGState( m_cgContext );
e3ff3591 1596 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
b7b40adb 1597 CGContextClip( m_cgContext );
a26b7ab2 1598 CGContextDrawShading( m_cgContext, ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->GetShading() );
b7b40adb
SC
1599 CGContextRestoreGState( m_cgContext);
1600 }
1601 else
783d8bdf 1602 {
a26b7ab2 1603 ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->Apply(this);
e3ff3591 1604 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
b7b40adb
SC
1605 if ( fillStyle == wxODDEVEN_RULE )
1606 CGContextEOFillPath( m_cgContext );
1607 else
1608 CGContextFillPath( m_cgContext );
50581042
SC
1609 }
1610}
1611
b7b40adb 1612void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg )
50581042 1613{
b7b40adb
SC
1614 // we allow either setting or clearing but not replacing
1615 wxASSERT( m_cgContext == NULL || cg == NULL );
50581042 1616
549be226
SC
1617 if ( m_cgContext )
1618 {
1619 // TODO : when is this necessary - should we add a Flush() method ? CGContextSynchronize( m_cgContext );
1620 CGContextRestoreGState( m_cgContext );
1621 CGContextRestoreGState( m_cgContext );
1622 if ( m_releaseContext )
6239ee05
SC
1623 {
1624#ifndef __LP64__
549be226 1625 QDEndCGContext( GetWindowPort( m_windowRef ) , &m_cgContext);
6239ee05
SC
1626#endif
1627 }
549be226
SC
1628 else
1629 CGContextRelease(m_cgContext);
1630 }
1631
1632
b7b40adb 1633 m_cgContext = cg;
549be226
SC
1634
1635 // FIXME: This check is needed because currently we need to use a DC/GraphicsContext
783d8bdf 1636 // in order to get font properties, like wxFont::GetPixelSize, but since we don't have
549be226
SC
1637 // a native window attached to use, I create a wxGraphicsContext with a NULL CGContextRef
1638 // for this one operation.
783d8bdf 1639
549be226 1640 // When wxFont::GetPixelSize on Mac no longer needs a graphics context, this check
783d8bdf 1641 // can be removed.
549be226
SC
1642 if (m_cgContext)
1643 {
1644 CGContextRetain(m_cgContext);
1645 CGContextSaveGState( m_cgContext );
1646 CGContextSaveGState( m_cgContext );
783d8bdf 1647 m_releaseContext = false;
549be226 1648 }
b7b40adb 1649}
50581042 1650
783d8bdf 1651void wxMacCoreGraphicsContext::Translate( wxDouble dx , wxDouble dy )
b7b40adb 1652{
783d8bdf 1653 if ( m_cgContext )
549be226
SC
1654 CGContextTranslateCTM( m_cgContext, dx, dy );
1655 else
1656 m_windowTransform = CGAffineTransformTranslate(m_windowTransform,dx,dy);
b7b40adb 1657}
50581042 1658
b7b40adb
SC
1659void wxMacCoreGraphicsContext::Scale( wxDouble xScale , wxDouble yScale )
1660{
783d8bdf 1661 if ( m_cgContext )
549be226
SC
1662 CGContextScaleCTM( m_cgContext , xScale , yScale );
1663 else
1664 m_windowTransform = CGAffineTransformScale(m_windowTransform,xScale,yScale);
b7b40adb 1665}
50581042 1666
b7b40adb
SC
1667void wxMacCoreGraphicsContext::Rotate( wxDouble angle )
1668{
783d8bdf 1669 if ( m_cgContext )
549be226
SC
1670 CGContextRotateCTM( m_cgContext , angle );
1671 else
1672 m_windowTransform = CGAffineTransformRotate(m_windowTransform,angle);
b7b40adb 1673}
50581042 1674
783d8bdf 1675void wxMacCoreGraphicsContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
b7b40adb 1676{
783d8bdf
VZ
1677 EnsureIsValid();
1678
968c951f 1679 CGImageRef image = (CGImageRef)( bmp.CreateCGImage() );
b7b40adb 1680 HIRect r = CGRectMake( x , y , w , h );
5f547a58
SC
1681 if ( bmp.GetDepth() == 1 )
1682 {
1683 // is is a mask, the '1' in the mask tell where to draw the current brush
1684 if ( !m_brush.IsNull() )
1685 {
1686 if ( ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
1687 {
1688 // TODO clip to mask
1689 /*
1690 CGContextSaveGState( m_cgContext );
1691 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
1692 CGContextClip( m_cgContext );
1693 CGContextDrawShading( m_cgContext, ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->GetShading() );
1694 CGContextRestoreGState( m_cgContext);
1695 */
1696 }
1697 else
1698 {
1699 ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->Apply(this);
276ee533 1700 wxMacDrawCGImage( m_cgContext , &r , image );
5f547a58
SC
1701 }
1702 }
1703 }
1704 else
1705 {
276ee533 1706 wxMacDrawCGImage( m_cgContext , &r , image );
5f547a58 1707 }
b7b40adb
SC
1708 CGImageRelease( image );
1709}
50581042 1710
783d8bdf 1711void wxMacCoreGraphicsContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
b7b40adb 1712{
783d8bdf
VZ
1713 EnsureIsValid();
1714
b7b40adb
SC
1715 CGRect r = CGRectMake( 00 , 00 , w , h );
1716 CGContextSaveGState( m_cgContext );
1717 CGContextTranslateCTM( m_cgContext, x , y + h );
1718 CGContextScaleCTM( m_cgContext, 1, -1 );
1719 PlotIconRefInContext( m_cgContext , &r , kAlignNone , kTransformNone ,
1720 NULL , kPlotIconRefNormalFlags , MAC_WXHICON( icon.GetHICON() ) );
1721 CGContextRestoreGState( m_cgContext );
1722}
50581042 1723
b7b40adb
SC
1724void wxMacCoreGraphicsContext::PushState()
1725{
783d8bdf
VZ
1726 EnsureIsValid();
1727
b7b40adb
SC
1728 CGContextSaveGState( m_cgContext );
1729}
50581042 1730
783d8bdf 1731void wxMacCoreGraphicsContext::PopState()
b7b40adb 1732{
783d8bdf
VZ
1733 EnsureIsValid();
1734
b7b40adb 1735 CGContextRestoreGState( m_cgContext );
50581042
SC
1736}
1737
783d8bdf 1738void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y )
50581042 1739{
1bd568fa
SC
1740 if ( m_font.IsNull() )
1741 return;
1742
1743 EnsureIsValid();
d2d8b4db 1744#if wxMAC_USE_CORE_TEXT
c07e1e2c
SC
1745 if ( UMAGetSystemVersion() >= 0x1050 )
1746 {
1747 wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
1748 wxMacCFStringHolder text(str, wxLocale::GetSystemEncoding() );
1749 CTFontRef font = fref->GetCTFont();
1750 CGColorRef col = fref->GetColour().GetPixel();
1751 CTUnderlineStyle ustyle = fref->GetUnderlined() ? kCTUnderlineStyleSingle : kCTUnderlineStyleNone ;
1752 wxCFRef<CFNumberRef> underlined( CFNumberCreate(NULL, kCFNumberSInt32Type, &ustyle) );
1753 CFStringRef keys[] = { kCTFontAttributeName , kCTForegroundColorAttributeName, kCTUnderlineStyleAttributeName };
1754 CFTypeRef values[] = { font, col, underlined };
1755 wxCFRef<CFDictionaryRef> attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**) &keys, (const void**) &values,
1756 WXSIZEOF( keys ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) );
1757 wxCFRef<CFAttributedStringRef> attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, attributes) );
1758 wxCFRef<CTLineRef> line( CTLineCreateWithAttributedString(attrtext) );
1759
1760 y += CTFontGetAscent(font);
1761
1762 CGContextSaveGState(m_cgContext);
1763 CGContextTranslateCTM(m_cgContext, x, y);
1764 CGContextScaleCTM(m_cgContext, 1, -1);
1765 CGContextSetTextPosition(m_cgContext, 0, 0);
1766 CTLineDraw( line, m_cgContext );
1767 CGContextRestoreGState(m_cgContext);
1768 return;
1769 }
1770#endif
1771#if wxMAC_USE_ATSU_TEXT
1772 {
1773 DrawText(str, x, y, 0.0);
1774 return;
1775 }
1776#endif
1777#if WXMAC_USE_CG_TEXT
1bd568fa
SC
1778 // TODO core graphics text implementation here
1779#endif
50581042
SC
1780}
1781
783d8bdf 1782void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle )
50581042 1783{
a26b7ab2 1784 if ( m_font.IsNull() )
b7b40adb 1785 return;
783d8bdf
VZ
1786
1787 EnsureIsValid();
d2d8b4db 1788#if wxMAC_USE_CORE_TEXT
c07e1e2c
SC
1789 if ( UMAGetSystemVersion() >= 0x1050 )
1790 {
1791 // default implementation takes care of rotation and calls non rotated DrawText afterwards
1792 wxGraphicsContext::DrawText( str, x, y, angle );
1793 return;
1794 }
1795#endif
1796#if wxMAC_USE_ATSU_TEXT
1797 {
1798 OSStatus status = noErr;
1799 ATSUTextLayout atsuLayout;
1800 UniCharCount chars = str.length();
1801 UniChar* ubuf = NULL;
1802
50581042 1803#if SIZEOF_WCHAR_T == 4
c07e1e2c 1804 wxMBConvUTF16 converter;
50581042 1805#if wxUSE_UNICODE
c07e1e2c
SC
1806 size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 );
1807 ubuf = (UniChar*) malloc( unicharlen + 2 );
1808 converter.WC2MB( (char*) ubuf , str.wc_str(), unicharlen + 2 );
50581042 1809#else
c07e1e2c
SC
1810 const wxWCharBuffer wchar = str.wc_str( wxConvLocal );
1811 size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 );
1812 ubuf = (UniChar*) malloc( unicharlen + 2 );
1813 converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 );
50581042 1814#endif
c07e1e2c 1815 chars = unicharlen / 2;
50581042
SC
1816#else
1817#if wxUSE_UNICODE
c07e1e2c 1818 ubuf = (UniChar*) str.wc_str();
50581042 1819#else
c07e1e2c
SC
1820 wxWCharBuffer wchar = str.wc_str( wxConvLocal );
1821 chars = wxWcslen( wchar.data() );
1822 ubuf = (UniChar*) wchar.data();
50581042
SC
1823#endif
1824#endif
c07e1e2c
SC
1825
1826 ATSUStyle style = (((wxMacCoreGraphicsFontData*)m_font.GetRefData())->GetATSUStyle());
1827 status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
1828 &chars , &style , &atsuLayout );
1829
1830 wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the rotated text") );
1831
1832 status = ::ATSUSetTransientFontMatching( atsuLayout , true );
1833 wxASSERT_MSG( status == noErr , wxT("couldn't setup transient font matching") );
1834
1835 int iAngle = int( angle * RAD2DEG );
1836 if ( abs(iAngle) > 0 )
50581042 1837 {
c07e1e2c
SC
1838 Fixed atsuAngle = IntToFixed( iAngle );
1839 ATSUAttributeTag atsuTags[] =
1840 {
1841 kATSULineRotationTag ,
1842 };
1843 ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1844 {
1845 sizeof( Fixed ) ,
1846 };
1847 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1848 {
1849 &atsuAngle ,
1850 };
1851 status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag),
1852 atsuTags, atsuSizes, atsuValues );
1853 }
1854
50581042 1855 {
c07e1e2c
SC
1856 ATSUAttributeTag atsuTags[] =
1857 {
1858 kATSUCGContextTag ,
1859 };
1860 ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1861 {
1862 sizeof( CGContextRef ) ,
1863 };
1864 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1865 {
1866 &m_cgContext ,
1867 };
1868 status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag),
1869 atsuTags, atsuSizes, atsuValues );
1870 }
1871
1872 ATSUTextMeasurement textBefore, textAfter;
1873 ATSUTextMeasurement ascent, descent;
1874
1875 status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1876 &textBefore , &textAfter, &ascent , &descent );
1877
1878 wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
1879
1880 Rect rect;
1881 x += (int)(sin(angle) * FixedToInt(ascent));
1882 y += (int)(cos(angle) * FixedToInt(ascent));
1883
1884 status = ::ATSUMeasureTextImage( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1885 IntToFixed(x) , IntToFixed(y) , &rect );
1886 wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
1887
1888 CGContextSaveGState(m_cgContext);
1889 CGContextTranslateCTM(m_cgContext, x, y);
1890 CGContextScaleCTM(m_cgContext, 1, -1);
1891 status = ::ATSUDrawText( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1892 IntToFixed(0) , IntToFixed(0) );
1893
1894 wxASSERT_MSG( status == noErr , wxT("couldn't draw the rotated text") );
1895
1896 CGContextRestoreGState(m_cgContext);
1897
1898 ::ATSUDisposeTextLayout(atsuLayout);
1899
50581042 1900#if SIZEOF_WCHAR_T == 4
c07e1e2c 1901 free( ubuf );
50581042 1902#endif
c07e1e2c
SC
1903 return;
1904 }
1905#endif
1906#if WXMAC_USE_CG_TEXT
1bd568fa
SC
1907 // default implementation takes care of rotation and calls non rotated DrawText afterwards
1908 wxGraphicsContext::DrawText( str, x, y, angle );
1909#endif
50581042 1910}
783d8bdf 1911
50581042
SC
1912void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
1913 wxDouble *descent, wxDouble *externalLeading ) const
1914{
a26b7ab2 1915 wxCHECK_RET( !m_font.IsNull(), wxT("wxDC(cg)::DoGetTextExtent - no valid font set") );
50581042 1916
6239ee05
SC
1917 if ( width )
1918 *width = 0;
1919 if ( height )
1920 *height = 0;
1921 if ( descent )
1922 *descent = 0;
1923 if ( externalLeading )
1924 *externalLeading = 0;
1925
1926 if (str.empty())
1927 return;
1928
d2d8b4db 1929#if wxMAC_USE_CORE_TEXT
c07e1e2c
SC
1930 if ( UMAGetSystemVersion() >= 0x1050 )
1931 {
1932 wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
1933 CTFontRef font = fref->GetCTFont();
1934
1935 wxMacCFStringHolder text(str, wxLocale::GetSystemEncoding() );
1936 CFStringRef keys[] = { kCTFontAttributeName };
1937 CFTypeRef values[] = { font };
1938 wxCFRef<CFDictionaryRef> attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**) &keys, (const void**) &values,
1939 WXSIZEOF( keys ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) );
1940 wxCFRef<CFAttributedStringRef> attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, attributes) );
1941 wxCFRef<CTLineRef> line( CTLineCreateWithAttributedString(attrtext) );
1942
1943 CGFloat w, a, d, l;
1944
1945 w = CTLineGetTypographicBounds(line, &a, &d, &l) ;
1946
1947 if ( height )
1948 *height = a+d+l;
1949 if ( descent )
1950 *descent = d;
1951 if ( externalLeading )
1952 *externalLeading = l;
1953 if ( width )
1954 *width = w;
1955 return;
1956 }
1957#endif
1958#if wxMAC_USE_ATSU_TEXT
1959 {
1960 OSStatus status = noErr;
1961
1962 ATSUTextLayout atsuLayout;
1963 UniCharCount chars = str.length();
1964 UniChar* ubuf = NULL;
1965
50581042 1966#if SIZEOF_WCHAR_T == 4
c07e1e2c 1967 wxMBConvUTF16 converter;
50581042 1968#if wxUSE_UNICODE
c07e1e2c
SC
1969 size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 );
1970 ubuf = (UniChar*) malloc( unicharlen + 2 );
1971 converter.WC2MB( (char*) ubuf , str.wc_str(), unicharlen + 2 );
50581042 1972#else
c07e1e2c
SC
1973 const wxWCharBuffer wchar = str.wc_str( wxConvLocal );
1974 size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 );
1975 ubuf = (UniChar*) malloc( unicharlen + 2 );
1976 converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 );
50581042 1977#endif
c07e1e2c 1978 chars = unicharlen / 2;
50581042
SC
1979#else
1980#if wxUSE_UNICODE
c07e1e2c 1981 ubuf = (UniChar*) str.wc_str();
50581042 1982#else
c07e1e2c
SC
1983 wxWCharBuffer wchar = str.wc_str( wxConvLocal );
1984 chars = wxWcslen( wchar.data() );
1985 ubuf = (UniChar*) wchar.data();
50581042
SC
1986#endif
1987#endif
c07e1e2c
SC
1988
1989 ATSUStyle style = (((wxMacCoreGraphicsFontData*)m_font.GetRefData())->GetATSUStyle());
1990 status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
1991 &chars , &style , &atsuLayout );
1992
1993 wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the text") );
1994
1995 ATSUTextMeasurement textBefore, textAfter;
1996 ATSUTextMeasurement textAscent, textDescent;
1997
1998 status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1999 &textBefore , &textAfter, &textAscent , &textDescent );
2000
2001 if ( height )
2002 *height = FixedToInt(textAscent + textDescent);
2003 if ( descent )
2004 *descent = FixedToInt(textDescent);
2005 if ( externalLeading )
2006 *externalLeading = 0;
2007 if ( width )
2008 *width = FixedToInt(textAfter - textBefore);
2009
2010 ::ATSUDisposeTextLayout(atsuLayout);
b9d495a0 2011#if SIZEOF_WCHAR_T == 4
c07e1e2c
SC
2012 free( ubuf ) ;
2013#endif
2014 return;
2015 }
b9d495a0 2016#endif
c07e1e2c 2017#if WXMAC_USE_CG_TEXT
1bd568fa
SC
2018 // TODO core graphics text implementation here
2019#endif
50581042
SC
2020}
2021
783d8bdf 2022void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const
50581042
SC
2023{
2024 widths.Empty();
2025 widths.Add(0, text.length());
2026
2027 if (text.empty())
2028 return;
2029
d2d8b4db 2030#if wxMAC_USE_CORE_TEXT
c07e1e2c
SC
2031 {
2032 wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
2033 CTFontRef font = fref->GetCTFont();
2034
2035 wxMacCFStringHolder t(text, wxLocale::GetSystemEncoding() );
2036 CFStringRef keys[] = { kCTFontAttributeName };
2037 CFTypeRef values[] = { font };
2038 wxCFRef<CFDictionaryRef> attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**) &keys, (const void**) &values,
2039 WXSIZEOF( keys ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) );
2040 wxCFRef<CFAttributedStringRef> attrtext( CFAttributedStringCreate(kCFAllocatorDefault, t, attributes) );
2041 wxCFRef<CTLineRef> line( CTLineCreateWithAttributedString(attrtext) );
2042
2043 int chars = text.length();
2044 for ( int pos = 0; pos < (int)chars; pos ++ )
2045 {
2046 widths[pos] = CTLineGetOffsetForStringIndex( line, pos+1 , NULL )+0.5;
2047 }
2048
2049 return;
2050 }
2051#endif
2052#if wxMAC_USE_ATSU_TEXT
2053 {
2054 ATSUTextLayout atsuLayout;
2055 UniCharCount chars = text.length();
2056 UniChar* ubuf = NULL;
2057
50581042 2058#if SIZEOF_WCHAR_T == 4
c07e1e2c 2059 wxMBConvUTF16 converter;
50581042 2060#if wxUSE_UNICODE
c07e1e2c
SC
2061 size_t unicharlen = converter.WC2MB( NULL , text.wc_str() , 0 );
2062 ubuf = (UniChar*) malloc( unicharlen + 2 );
2063 converter.WC2MB( (char*) ubuf , text.wc_str(), unicharlen + 2 );
50581042 2064#else
c07e1e2c
SC
2065 const wxWCharBuffer wchar = text.wc_str( wxConvLocal );
2066 size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 );
2067 ubuf = (UniChar*) malloc( unicharlen + 2 );
2068 converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 );
50581042 2069#endif
c07e1e2c 2070 chars = unicharlen / 2;
50581042
SC
2071#else
2072#if wxUSE_UNICODE
c07e1e2c 2073 ubuf = (UniChar*) text.wc_str();
50581042 2074#else
c07e1e2c
SC
2075 wxWCharBuffer wchar = text.wc_str( wxConvLocal );
2076 chars = wxWcslen( wchar.data() );
2077 ubuf = (UniChar*) wchar.data();
50581042
SC
2078#endif
2079#endif
c07e1e2c
SC
2080
2081 ATSUStyle style = (((wxMacCoreGraphicsFontData*)m_font.GetRefData())->GetATSUStyle());
2082 ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
2083 &chars , &style , &atsuLayout );
2084
2085 for ( int pos = 0; pos < (int)chars; pos ++ )
2086 {
2087 unsigned long actualNumberOfBounds = 0;
2088 ATSTrapezoid glyphBounds;
2089
2090 // We get a single bound, since the text should only require one. If it requires more, there is an issue
2091 OSStatus result;
2092 result = ATSUGetGlyphBounds( atsuLayout, 0, 0, kATSUFromTextBeginning, pos + 1,
2093 kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds );
2094 if (result != noErr || actualNumberOfBounds != 1 )
2095 return;
2096
2097 widths[pos] = FixedToInt( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
2098 //unsigned char uch = s[i];
2099 }
2100
2101 ::ATSUDisposeTextLayout(atsuLayout);
b9d495a0 2102#if SIZEOF_WCHAR_T == 4
c07e1e2c
SC
2103 free( ubuf ) ;
2104#endif
2105 }
b9d495a0 2106#endif
c07e1e2c 2107#if WXMAC_USE_CG_TEXT
1bd568fa
SC
2108 // TODO core graphics text implementation here
2109#endif
50581042
SC
2110}
2111
783d8bdf 2112void * wxMacCoreGraphicsContext::GetNativeContext()
50581042 2113{
783d8bdf 2114 return m_cgContext;
b7b40adb 2115}
50581042 2116
b7b40adb 2117// concatenates this transform with the current transform of this context
e3ff3591 2118void wxMacCoreGraphicsContext::ConcatTransform( const wxGraphicsMatrix& matrix )
b7b40adb 2119{
549be226
SC
2120 if ( m_cgContext )
2121 CGContextConcatCTM( m_cgContext, *(CGAffineTransform*) matrix.GetNativeMatrix());
2122 else
2123 m_windowTransform = CGAffineTransformConcat(m_windowTransform, *(CGAffineTransform*) matrix.GetNativeMatrix());
b7b40adb 2124}
50581042 2125
b7b40adb 2126// sets the transform of this context
e3ff3591 2127void wxMacCoreGraphicsContext::SetTransform( const wxGraphicsMatrix& matrix )
b7b40adb 2128{
549be226
SC
2129 if ( m_cgContext )
2130 {
2131 CGAffineTransform transform = CGContextGetCTM( m_cgContext );
2132 transform = CGAffineTransformInvert( transform ) ;
2133 CGContextConcatCTM( m_cgContext, transform);
2134 CGContextConcatCTM( m_cgContext, *(CGAffineTransform*) matrix.GetNativeMatrix());
2135 }
2136 else
2137 {
2138 m_windowTransform = *(CGAffineTransform*) matrix.GetNativeMatrix();
2139 }
b7b40adb 2140}
50581042 2141
b7b40adb 2142// gets the matrix of this context
e3ff3591 2143wxGraphicsMatrix wxMacCoreGraphicsContext::GetTransform() const
b7b40adb 2144{
daa6105f 2145 wxGraphicsMatrix m = CreateMatrix();
549be226
SC
2146 *((CGAffineTransform*) m.GetNativeMatrix()) = ( m_cgContext == NULL ? m_windowTransform :
2147 CGContextGetCTM( m_cgContext ));
daa6105f 2148 return m;
b7b40adb 2149}
50581042 2150
b7b40adb
SC
2151//
2152// Renderer
2153//
50581042 2154
b7b40adb
SC
2155//-----------------------------------------------------------------------------
2156// wxMacCoreGraphicsRenderer declaration
2157//-----------------------------------------------------------------------------
50581042 2158
b7b40adb
SC
2159class WXDLLIMPEXP_CORE wxMacCoreGraphicsRenderer : public wxGraphicsRenderer
2160{
2161public :
2162 wxMacCoreGraphicsRenderer() {}
50581042 2163
b7b40adb
SC
2164 virtual ~wxMacCoreGraphicsRenderer() {}
2165
783d8bdf
VZ
2166 // Context
2167
2168 virtual wxGraphicsContext * CreateContext( const wxWindowDC& dc);
b7b40adb 2169
783d8bdf 2170 virtual wxGraphicsContext * CreateContextFromNativeContext( void * context );
b7b40adb 2171
783d8bdf 2172 virtual wxGraphicsContext * CreateContextFromNativeWindow( void * window );
b7b40adb 2173
783d8bdf 2174 virtual wxGraphicsContext * CreateContext( wxWindow* window );
ad667945
SC
2175
2176 virtual wxGraphicsContext * CreateMeasuringContext();
783d8bdf
VZ
2177
2178 // Path
b7b40adb 2179
e3ff3591 2180 virtual wxGraphicsPath CreatePath();
b7b40adb 2181
783d8bdf
VZ
2182 // Matrix
2183
2184 virtual wxGraphicsMatrix CreateMatrix( wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
2185 wxDouble tx=0.0, wxDouble ty=0.0);
b7b40adb
SC
2186
2187
a26b7ab2 2188 virtual wxGraphicsPen CreatePen(const wxPen& pen) ;
783d8bdf 2189
a26b7ab2 2190 virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) ;
783d8bdf 2191
b7b40adb 2192 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
783d8bdf 2193 virtual wxGraphicsBrush CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
b7b40adb
SC
2194 const wxColour&c1, const wxColour&c2) ;
2195
783d8bdf 2196 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
b7b40adb 2197 // with radius r and color cColor
a26b7ab2 2198 virtual wxGraphicsBrush CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
b7b40adb
SC
2199 const wxColour &oColor, const wxColour &cColor) ;
2200
2201 // sets the font
a26b7ab2 2202 virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ;
b7b40adb
SC
2203
2204private :
2205 DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacCoreGraphicsRenderer)
2206} ;
2207
2208//-----------------------------------------------------------------------------
2209// wxMacCoreGraphicsRenderer implementation
2210//-----------------------------------------------------------------------------
2211
2212IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsRenderer,wxGraphicsRenderer)
2213
2214static wxMacCoreGraphicsRenderer gs_MacCoreGraphicsRenderer;
2215
2216wxGraphicsRenderer* wxGraphicsRenderer::GetDefaultRenderer()
2217{
783d8bdf 2218 return &gs_MacCoreGraphicsRenderer;
50581042
SC
2219}
2220
b7b40adb
SC
2221wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxWindowDC& dc)
2222{
d9485f89
RD
2223 wxMemoryDC* mdc = wxDynamicCast(&dc, wxMemoryDC);
2224 if ( mdc )
2225 {
2226 return new wxMacCoreGraphicsContext(this,
2227 (CGContextRef)mdc->GetGraphicsContext()->GetNativeContext());
2228 }
2229 else
2230 {
2231 return new wxMacCoreGraphicsContext(this,(CGContextRef)dc.GetWindow()->MacGetCGContextRef() );
2232 }
b7b40adb
SC
2233}
2234
2235wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeContext( void * context )
2236{
2237 return new wxMacCoreGraphicsContext(this,(CGContextRef)context);
2238}
2239
2240
2241wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeWindow( void * window )
2242{
2243 return new wxMacCoreGraphicsContext(this,(WindowRef)window);
2244}
2245
2246wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( wxWindow* window )
2247{
783d8bdf 2248 return new wxMacCoreGraphicsContext(this, window );
b7b40adb
SC
2249}
2250
ad667945
SC
2251wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateMeasuringContext()
2252{
2253 return new wxMacCoreGraphicsContext(this);
2254}
2255
b7b40adb
SC
2256// Path
2257
e3ff3591 2258wxGraphicsPath wxMacCoreGraphicsRenderer::CreatePath()
b7b40adb 2259{
e3ff3591
SC
2260 wxGraphicsPath m;
2261 m.SetRefData( new wxMacCoreGraphicsPathData(this));
2262 return m;
b7b40adb
SC
2263}
2264
2265
2266// Matrix
2267
783d8bdf
VZ
2268wxGraphicsMatrix wxMacCoreGraphicsRenderer::CreateMatrix( wxDouble a, wxDouble b, wxDouble c, wxDouble d,
2269 wxDouble tx, wxDouble ty)
1056ddcf 2270{
e3ff3591
SC
2271 wxGraphicsMatrix m;
2272 wxMacCoreGraphicsMatrixData* data = new wxMacCoreGraphicsMatrixData( this );
2273 data->Set( a,b,c,d,tx,ty ) ;
2274 m.SetRefData(data);
b7b40adb
SC
2275 return m;
2276}
2277
783d8bdf 2278wxGraphicsPen wxMacCoreGraphicsRenderer::CreatePen(const wxPen& pen)
b7b40adb
SC
2279{
2280 if ( !pen.Ok() || pen.GetStyle() == wxTRANSPARENT )
a26b7ab2 2281 return wxNullGraphicsPen;
b7b40adb 2282 else
a26b7ab2
SC
2283 {
2284 wxGraphicsPen p;
2285 p.SetRefData(new wxMacCoreGraphicsPenData( this, pen ));
2286 return p;
2287 }
1056ddcf
SC
2288}
2289
783d8bdf 2290wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateBrush(const wxBrush& brush )
50581042 2291{
b7b40adb 2292 if ( !brush.Ok() || brush.GetStyle() == wxTRANSPARENT )
a26b7ab2 2293 return wxNullGraphicsBrush;
b7b40adb 2294 else
a26b7ab2
SC
2295 {
2296 wxGraphicsBrush p;
2297 p.SetRefData(new wxMacCoreGraphicsBrushData( this, brush ));
2298 return p;
2299 }
50581042
SC
2300}
2301
b7b40adb 2302// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
783d8bdf
VZ
2303wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
2304 const wxColour&c1, const wxColour&c2)
1056ddcf 2305{
a26b7ab2
SC
2306 wxGraphicsBrush p;
2307 wxMacCoreGraphicsBrushData* d = new wxMacCoreGraphicsBrushData( this );
2308 d->CreateLinearGradientBrush(x1, y1, x2, y2, c1, c2);
2309 p.SetRefData(d);
2310 return p;
1056ddcf
SC
2311}
2312
783d8bdf 2313// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
b7b40adb 2314// with radius r and color cColor
a26b7ab2 2315wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
783d8bdf 2316 const wxColour &oColor, const wxColour &cColor)
1056ddcf 2317{
a26b7ab2
SC
2318 wxGraphicsBrush p;
2319 wxMacCoreGraphicsBrushData* d = new wxMacCoreGraphicsBrushData( this );
2320 d->CreateRadialGradientBrush(xo,yo,xc,yc,radius,oColor,cColor);
2321 p.SetRefData(d);
2322 return p;
1056ddcf
SC
2323}
2324
b7b40adb 2325// sets the font
783d8bdf 2326wxGraphicsFont wxMacCoreGraphicsRenderer::CreateFont( const wxFont &font , const wxColour &col )
513b47e9 2327{
b7b40adb 2328 if ( font.Ok() )
783d8bdf 2329 {
a26b7ab2
SC
2330 wxGraphicsFont p;
2331 p.SetRefData(new wxMacCoreGraphicsFontData( this , font, col ));
2332 return p;
2333 }
b7b40adb 2334 else
a26b7ab2 2335 return wxNullGraphicsFont;
513b47e9
SC
2336}
2337
fb728ebb
SC
2338//
2339// CoreGraphics Helper Methods
2340//
2341
2342// Data Providers and Consumers
2343
2344size_t UMAPutBytesCFRefCallback( void *info, const void *bytes, size_t count )
2345{
2346 CFMutableDataRef data = (CFMutableDataRef) info;
2347 if ( data )
2348 {
2349 CFDataAppendBytes( data, (const UInt8*) bytes, count );
2350 }
2351 return count;
2352}
2353
2354void wxMacReleaseCFDataProviderCallback(void *info,
2355 const void *WXUNUSED(data),
2356 size_t WXUNUSED(count))
2357{
2358 if ( info )
2359 CFRelease( (CFDataRef) info );
2360}
2361
2362void wxMacReleaseCFDataConsumerCallback( void *info )
2363{
2364 if ( info )
2365 CFRelease( (CFDataRef) info );
2366}
2367
2368CGDataProviderRef wxMacCGDataProviderCreateWithCFData( CFDataRef data )
2369{
2370 if ( data == NULL )
2371 return NULL;
2372
2373 return CGDataProviderCreateWithCFData( data );
2374}
2375
2376CGDataConsumerRef wxMacCGDataConsumerCreateWithCFData( CFMutableDataRef data )
2377{
2378 if ( data == NULL )
2379 return NULL;
2380
2381 return CGDataConsumerCreateWithCFData( data );
2382}
2383
2384void wxMacReleaseMemoryBufferProviderCallback(void *info, const void *data, size_t WXUNUSED(size))
2385{
2386 wxMemoryBuffer* membuf = (wxMemoryBuffer*) info ;
2387
2388 wxASSERT( data == membuf->GetData() ) ;
2389
2390 delete membuf ;
2391}
2392
2393CGDataProviderRef wxMacCGDataProviderCreateWithMemoryBuffer( const wxMemoryBuffer& buf )
2394{
2395 wxMemoryBuffer* b = new wxMemoryBuffer( buf );
2396 if ( b->GetDataLen() == 0 )
2397 return NULL;
2398
2399 return CGDataProviderCreateWithData( b , (const void *) b->GetData() , b->GetDataLen() ,
2400 wxMacReleaseMemoryBufferProviderCallback );
2401}