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