]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/graphics.cpp
Reverted winundef.h removal - without it build fails on GetWindowStyle later.
[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
f43426c1 14#if wxUSE_GRAPHICS_CONTEXT && wxMAC_USE_CORE_GRAPHICS
50581042 15
83b96a06
PC
16#include "wx/graphics.h"
17
50581042 18#ifndef WX_PRECOMP
cc5de8fe 19 #include "wx/dcclient.h"
50581042 20 #include "wx/log.h"
50581042 21 #include "wx/region.h"
50581042
SC
22#endif
23
24#include "wx/mac/uma.h"
25
50581042
SC
26#ifdef __MSL__
27 #if __MSL__ >= 0x6000
28 #include "math.h"
29 // in case our functions were defined outside std, we make it known all the same
30 namespace std { }
31 using namespace std;
32 #endif
33#endif
34
35#include "wx/mac/private.h"
36
37#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
38typedef float CGFloat;
39#endif
40
eec960fa
SC
41//-----------------------------------------------------------------------------
42// constants
43//-----------------------------------------------------------------------------
44
45#if !defined( __DARWIN__ ) || defined(__MWERKS__)
46#ifndef M_PI
47const double M_PI = 3.14159265358979;
48#endif
49#endif
50
51static const double RAD2DEG = 180.0 / M_PI;
52
50581042 53//
b7b40adb 54// Pen, Brushes and Fonts
50581042
SC
55//
56
b7b40adb
SC
57#pragma mark -
58#pragma mark wxMacCoreGraphicsPattern, ImagePattern, HatchPattern classes
59
60// CGPattern wrapper class: always allocate on heap, never call destructor
61
62class wxMacCoreGraphicsPattern
50581042 63{
50581042 64public :
b7b40adb 65 wxMacCoreGraphicsPattern() {}
50581042 66
b7b40adb
SC
67 // is guaranteed to be called only with a non-Null CGContextRef
68 virtual void Render( CGContextRef ctxRef ) = 0;
50581042 69
b7b40adb 70 operator CGPatternRef() const { return m_patternRef; }
50581042 71
b7b40adb
SC
72protected :
73 virtual ~wxMacCoreGraphicsPattern()
74 {
75 // as this is called only when the m_patternRef is been released;
76 // don't release it again
77 }
50581042 78
b7b40adb
SC
79 static void _Render( void *info, CGContextRef ctxRef )
80 {
81 wxMacCoreGraphicsPattern* self = (wxMacCoreGraphicsPattern*) info;
82 if ( self && ctxRef )
83 self->Render( ctxRef );
84 }
50581042 85
b7b40adb
SC
86 static void _Dispose( void *info )
87 {
88 wxMacCoreGraphicsPattern* self = (wxMacCoreGraphicsPattern*) info;
89 delete self;
90 }
50581042 91
b7b40adb 92 CGPatternRef m_patternRef;
50581042 93
b7b40adb
SC
94 static const CGPatternCallbacks ms_Callbacks;
95};
50581042 96
b7b40adb 97const CGPatternCallbacks wxMacCoreGraphicsPattern::ms_Callbacks = { 0, &wxMacCoreGraphicsPattern::_Render, &wxMacCoreGraphicsPattern::_Dispose };
50581042 98
b7b40adb
SC
99class ImagePattern : public wxMacCoreGraphicsPattern
100{
101public :
102 ImagePattern( const wxBitmap* bmp , const CGAffineTransform& transform )
103 {
104 wxASSERT( bmp && bmp->Ok() );
50581042 105
b7b40adb
SC
106 Init( (CGImageRef) bmp->CGImageCreate() , transform );
107 }
50581042 108
b7b40adb
SC
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
124protected :
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
148class HatchPattern : public wxMacCoreGraphicsPattern
149{
150public :
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
252protected :
253 virtual ~HatchPattern() {}
254
255 CGRect m_imageBounds;
256 int m_hatch;
257};
258
259class wxMacCoreGraphicsPen : public wxGraphicsPen
260{
261public:
262 wxMacCoreGraphicsPen();
263 wxMacCoreGraphicsPen( wxGraphicsRenderer* renderer, const wxPen &pen );
264 ~wxMacCoreGraphicsPen();
50581042 265
b7b40adb
SC
266 void Init();
267 virtual void Apply( wxGraphicsContext* context );
268 virtual wxDouble GetWidth() { return m_width; }
269
270protected :
271 CGLineCap m_cap;
272 wxMacCFRefHolder<CGColorRef> m_color;
273 wxMacCFRefHolder<CGColorSpaceRef> m_colorSpace;
274
275 CGLineJoin m_join;
276 CGFloat m_width;
9985801d 277
b7b40adb
SC
278 int m_count;
279 const CGFloat *m_lengths;
280 CGFloat *m_userLengths;
eec960fa 281
b7b40adb
SC
282
283 bool m_isPattern;
284 wxMacCFRefHolder<CGPatternRef> m_pattern;
285 CGFloat* m_patternColorComponents;
50581042 286private :
b7b40adb 287DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacCoreGraphicsPen)
50581042
SC
288};
289
b7b40adb 290IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsPen,wxGraphicsPen)
eec960fa 291
b7b40adb
SC
292wxMacCoreGraphicsPen::wxMacCoreGraphicsPen() : wxGraphicsPen( NULL )
293{
294 wxLogDebug(wxT("Illegal Constructor called"));
295}
eec960fa 296
b7b40adb
SC
297wxMacCoreGraphicsPen::wxMacCoreGraphicsPen( wxGraphicsRenderer* renderer, const wxPen &pen ) :
298 wxGraphicsPen( renderer )
50581042 299{
b7b40adb
SC
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 }
50581042
SC
434}
435
b7b40adb 436wxMacCoreGraphicsPen::~wxMacCoreGraphicsPen()
50581042 437{
b7b40adb
SC
438 delete[] m_userLengths;
439 delete[] m_patternColorComponents;
50581042
SC
440}
441
b7b40adb 442void wxMacCoreGraphicsPen::Init()
50581042 443{
b7b40adb
SC
444 m_lengths = NULL;
445 m_userLengths = NULL;
446 m_width = NULL;
447 m_count = 0;
448 m_patternColorComponents = NULL;
449 m_isPattern = false;
50581042
SC
450}
451
b7b40adb 452void wxMacCoreGraphicsPen::Apply( wxGraphicsContext* context )
50581042 453{
b7b40adb
SC
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 }
50581042
SC
470}
471
b7b40adb
SC
472//
473// Brush
474//
475
476class wxMacCoreGraphicsBrush : public wxGraphicsBrush
50581042 477{
b7b40adb
SC
478public:
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; }
492protected:
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;
508private :
509DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacCoreGraphicsBrush)
510};
511
512IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsBrush,wxGraphicsBrush)
513
514wxMacCoreGraphicsBrush::wxMacCoreGraphicsBrush() : wxGraphicsBrush( NULL )
515{
516 wxLogDebug(wxT("Illegal Constructor called"));
50581042
SC
517}
518
b7b40adb 519wxMacCoreGraphicsBrush::wxMacCoreGraphicsBrush( wxGraphicsRenderer* renderer) : wxGraphicsBrush( renderer )
50581042 520{
b7b40adb 521 Init();
50581042
SC
522}
523
b7b40adb
SC
524void wxMacCoreGraphicsBrush::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
525 const wxColour&c1, const wxColour&c2 )
50581042 526{
b7b40adb
SC
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
532void 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
540wxMacCoreGraphicsBrush::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 }
50581042
SC
575}
576
b7b40adb 577wxMacCoreGraphicsBrush::~wxMacCoreGraphicsBrush()
50581042 578{
b7b40adb
SC
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;
50581042
SC
587}
588
b7b40adb 589void wxMacCoreGraphicsBrush::Init()
50581042 590{
b7b40adb
SC
591 m_patternColorComponents = NULL;
592 m_gradientFunction = NULL;
593 m_shading = NULL;
594 m_isPattern = false;
595 m_gradientComponents = NULL;
596 m_isShading = false;
50581042
SC
597}
598
b7b40adb 599void wxMacCoreGraphicsBrush::Apply( wxGraphicsContext* context )
50581042 600{
b7b40adb
SC
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 }
50581042
SC
618}
619
b7b40adb 620void wxMacCoreGraphicsBrush::CalculateShadingValues (void *info, const CGFloat *in, CGFloat *out)
50581042 621{
b7b40adb
SC
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 }
50581042
SC
628}
629
b7b40adb 630CGFunctionRef wxMacCoreGraphicsBrush::CreateGradientFunction( const wxColour& c1, const wxColour& c2 )
50581042 631{
b7b40adb
SC
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);
50581042
SC
650}
651
652//
b7b40adb 653// Font
50581042
SC
654//
655
b7b40adb 656class wxMacCoreGraphicsFont : public wxGraphicsFont
50581042 657{
50581042 658public:
b7b40adb
SC
659 wxMacCoreGraphicsFont();
660 wxMacCoreGraphicsFont( wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col );
661 ~wxMacCoreGraphicsFont();
1056ddcf 662
b7b40adb
SC
663 virtual void Apply( wxGraphicsContext* context );
664 virtual ATSUStyle GetATSUStyle() { return m_macATSUIStyle; }
665private :
666 ATSUStyle m_macATSUIStyle;
667DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacCoreGraphicsFont)
668};
50581042 669
b7b40adb 670IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsFont,wxGraphicsFont)
50581042 671
b7b40adb
SC
672wxMacCoreGraphicsFont::wxMacCoreGraphicsFont() : wxGraphicsFont( NULL )
673{
674 wxLogDebug(wxT("Illegal Constructor called"));
675}
1056ddcf 676
b7b40adb
SC
677wxMacCoreGraphicsFont::wxMacCoreGraphicsFont(wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col) : wxGraphicsFont( renderer )
678{
679 m_macATSUIStyle = NULL;
50581042 680
b7b40adb 681 OSStatus status;
50581042 682
b7b40adb 683 status = ATSUCreateAndCopyStyle( (ATSUStyle) font.MacGetATSUStyle() , &m_macATSUIStyle );
50581042 684
b7b40adb 685 wxASSERT_MSG( status == noErr, wxT("couldn't create ATSU style") );
50581042 686
b7b40adb 687 // we need the scale here ...
50581042 688
b7b40adb
SC
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 };
50581042 706
b7b40adb
SC
707 status = ::ATSUSetAttributes(
708 m_macATSUIStyle, sizeof(atsuTags) / sizeof(ATSUAttributeTag) ,
709 atsuTags, atsuSizes, atsuValues);
50581042 710
b7b40adb
SC
711 wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") );
712}
50581042 713
b7b40adb
SC
714wxMacCoreGraphicsFont::~wxMacCoreGraphicsFont()
715{
716 if ( m_macATSUIStyle )
717 {
718 ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
719 m_macATSUIStyle = NULL;
720 }
721}
50581042 722
b7b40adb
SC
723void wxMacCoreGraphicsFont::Apply( wxGraphicsContext* WXUNUSED(context) )
724{
725 // nothing to do here
726}
50581042 727
b7b40adb
SC
728//
729// Graphics Matrix
730//
50581042 731
b7b40adb
SC
732//-----------------------------------------------------------------------------
733// wxMacCoreGraphicsMatrix declaration
734//-----------------------------------------------------------------------------
50581042 735
b7b40adb
SC
736class WXDLLIMPEXP_CORE wxMacCoreGraphicsMatrix : public wxGraphicsMatrix
737{
738public :
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
50581042 767 //
b7b40adb 768 // transformation
50581042
SC
769 //
770
b7b40adb
SC
771 // add the translation to this matrix
772 virtual void Translate( wxDouble dx , wxDouble dy );
50581042 773
b7b40adb
SC
774 // add the scale to this matrix
775 virtual void Scale( wxDouble xScale , wxDouble yScale );
50581042 776
b7b40adb
SC
777 // add the rotation to this matrix (radians)
778 virtual void Rotate( wxDouble angle );
779
50581042 780 //
b7b40adb 781 // apply the transforms
50581042 782 //
b7b40adb
SC
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
793private :
794 CGAffineTransform m_matrix;
50581042 795
b7b40adb
SC
796 DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacCoreGraphicsMatrix)
797} ;
50581042 798
50581042 799//-----------------------------------------------------------------------------
b7b40adb 800// wxMacCoreGraphicsMatrix implementation
50581042
SC
801//-----------------------------------------------------------------------------
802
b7b40adb 803IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsMatrix, wxGraphicsMatrix)
50581042 804
b7b40adb
SC
805wxMacCoreGraphicsMatrix::wxMacCoreGraphicsMatrix() : wxGraphicsMatrix(NULL)
806{
807 wxLogDebug(wxT("Illegal Constructor called"));
808}
50581042 809
b7b40adb
SC
810wxMacCoreGraphicsMatrix::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}
eec960fa 815
b7b40adb 816wxMacCoreGraphicsMatrix::~wxMacCoreGraphicsMatrix()
50581042 817{
50581042
SC
818}
819
b7b40adb 820wxGraphicsMatrix *wxMacCoreGraphicsMatrix::Clone() const
50581042 821{
b7b40adb
SC
822 wxMacCoreGraphicsMatrix* m = new wxMacCoreGraphicsMatrix(GetRenderer()) ;
823 m->m_matrix = m_matrix ;
824 return m;
825}
826
827// concatenates the matrix
828void wxMacCoreGraphicsMatrix::Concat( const wxGraphicsMatrix *t )
829{
830 m_matrix = CGAffineTransformConcat(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix()) );
831}
832
833// copies the passed in matrix
834void wxMacCoreGraphicsMatrix::Copy( const wxGraphicsMatrix *t )
835{
836 m_matrix = *((CGAffineTransform*) t->GetNativeMatrix());
837}
838
839// sets the matrix to the respective values
840void 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);
50581042
SC
844}
845
b7b40adb
SC
846// makes this the inverse matrix
847void wxMacCoreGraphicsMatrix::Invert()
1056ddcf 848{
b7b40adb 849 m_matrix = CGAffineTransformInvert( m_matrix );
eec960fa
SC
850}
851
b7b40adb
SC
852// returns true if the elements of the transformation matrix are equal ?
853bool wxMacCoreGraphicsMatrix::IsEqual( const wxGraphicsMatrix* t) const
eec960fa 854{
2701ef7e
SC
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
b7b40adb 864 return CGAffineTransformEqualToTransform(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix()));
1056ddcf
SC
865}
866
b7b40adb
SC
867// return true if this is the identity matrix
868bool wxMacCoreGraphicsMatrix::IsIdentity()
50581042 869{
2701ef7e
SC
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);
50581042
SC
872}
873
b7b40adb
SC
874//
875// transformation
876//
877
878// add the translation to this matrix
879void wxMacCoreGraphicsMatrix::Translate( wxDouble dx , wxDouble dy )
50581042 880{
b7b40adb
SC
881 m_matrix = CGAffineTransformTranslate( m_matrix, dx, dy);
882}
50581042 883
b7b40adb
SC
884// add the scale to this matrix
885void wxMacCoreGraphicsMatrix::Scale( wxDouble xScale , wxDouble yScale )
886{
887 m_matrix = CGAffineTransformScale( m_matrix, xScale, yScale);
50581042
SC
888}
889
b7b40adb
SC
890// add the rotation to this matrix (radians)
891void wxMacCoreGraphicsMatrix::Rotate( wxDouble angle )
eec960fa 892{
b7b40adb 893 m_matrix = CGAffineTransformRotate( m_matrix, angle);
eec960fa
SC
894}
895
b7b40adb
SC
896//
897// apply the transforms
898//
eec960fa 899
b7b40adb
SC
900// applies that matrix to the point
901void wxMacCoreGraphicsMatrix::TransformPoint( wxDouble *x, wxDouble *y )
50581042 902{
2701ef7e 903 CGPoint pt = CGPointApplyAffineTransform( CGPointMake(*x,*y), m_matrix);
b7b40adb 904
2701ef7e
SC
905 *x = pt.x;
906 *y = pt.y;
1056ddcf
SC
907}
908
b7b40adb
SC
909// applies the matrix except for translations
910void wxMacCoreGraphicsMatrix::TransformDistance( wxDouble *dx, wxDouble *dy )
1056ddcf 911{
2701ef7e
SC
912 CGSize sz = CGSizeApplyAffineTransform( CGSizeMake(*dx,*dy) , m_matrix );
913 *dx = sz.width;
914 *dy = sz.height;
b7b40adb
SC
915}
916
917// returns the native representation
918void * wxMacCoreGraphicsMatrix::GetNativeMatrix() const
1056ddcf 919{
b7b40adb 920 return (void*) &m_matrix;
50581042
SC
921}
922
b7b40adb
SC
923//
924// Graphics Path
925//
926
927//-----------------------------------------------------------------------------
928// wxMacCoreGraphicsPath declaration
929//-----------------------------------------------------------------------------
930
931class WXDLLEXPORT wxMacCoreGraphicsPath : public wxGraphicsPath
50581042 932{
b7b40adb
SC
933public :
934 wxMacCoreGraphicsPath( wxGraphicsRenderer* renderer, CGMutablePathRef path = NULL);
935
936 wxMacCoreGraphicsPath();
937
938 ~wxMacCoreGraphicsPath();
1056ddcf 939
b7b40adb 940 virtual wxGraphicsPath *Clone() const;
1056ddcf 941
b7b40adb
SC
942 // begins a new subpath at (x,y)
943 virtual void MoveToPoint( wxDouble x, wxDouble y );
1056ddcf 944
b7b40adb
SC
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)
994private :
995 CGMutablePathRef m_path;
996};
997
998//-----------------------------------------------------------------------------
999// wxMacCoreGraphicsPath implementation
1000//-----------------------------------------------------------------------------
1001
1002IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsPath, wxGraphicsPath)
1003
1004wxMacCoreGraphicsPath::wxMacCoreGraphicsPath() : wxGraphicsPath(NULL)
1005{
1006 wxLogDebug(wxT("Illegal Constructor called"));
1007}
1008
1009
1010wxMacCoreGraphicsPath::wxMacCoreGraphicsPath( wxGraphicsRenderer* renderer, CGMutablePathRef path) : wxGraphicsPath(renderer)
1011{
1012 if ( path )
1013 m_path = path;
1014 else
1015 m_path = CGPathCreateMutable();
50581042
SC
1016}
1017
b7b40adb 1018wxMacCoreGraphicsPath::~wxMacCoreGraphicsPath()
50581042 1019{
b7b40adb
SC
1020 CGPathRelease( m_path );
1021}
50581042 1022
b7b40adb
SC
1023wxGraphicsPath* wxMacCoreGraphicsPath::Clone() const
1024{
1025 wxMacCoreGraphicsPath* clone = new wxMacCoreGraphicsPath(GetRenderer(),CGPathCreateMutableCopy(m_path));
1026 return clone ;
1027}
1056ddcf 1028
1056ddcf 1029
b7b40adb
SC
1030// opens (starts) a new subpath
1031void wxMacCoreGraphicsPath::MoveToPoint( wxDouble x1 , wxDouble y1 )
1032{
1033 CGPathMoveToPoint( m_path , NULL , x1 , y1 );
1034}
1056ddcf 1035
b7b40adb
SC
1036void wxMacCoreGraphicsPath::AddLineToPoint( wxDouble x1 , wxDouble y1 )
1037{
1038 CGPathAddLineToPoint( m_path , NULL , x1 , y1 );
50581042
SC
1039}
1040
b7b40adb 1041void wxMacCoreGraphicsPath::AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y )
50581042 1042{
b7b40adb 1043 CGPathAddCurveToPoint( m_path , NULL , cx1 , cy1 , cx2, cy2, x , y );
50581042
SC
1044}
1045
b7b40adb 1046void wxMacCoreGraphicsPath::AddQuadCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble x, wxDouble y )
50581042 1047{
b7b40adb 1048 CGPathAddQuadCurveToPoint( m_path , NULL , cx1 , cy1 , x , y );
50581042
SC
1049}
1050
b7b40adb 1051void wxMacCoreGraphicsPath::AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
50581042 1052{
b7b40adb
SC
1053 CGRect cgRect = { { x , y } , { w , h } };
1054 CGPathAddRect( m_path , NULL , cgRect );
1055}
50581042 1056
b7b40adb
SC
1057void wxMacCoreGraphicsPath::AddCircle( wxDouble x, wxDouble y , wxDouble r )
1058{
1059 CGPathAddArc( m_path , NULL , x , y , r , 0.0 , 2 * M_PI , true );
50581042
SC
1060}
1061
b7b40adb
SC
1062// adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
1063void wxMacCoreGraphicsPath::AddArc( wxDouble x, wxDouble y, wxDouble r, wxDouble startAngle, wxDouble endAngle, bool clockwise )
50581042 1064{
b7b40adb
SC
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);
50581042
SC
1067}
1068
b7b40adb 1069void wxMacCoreGraphicsPath::AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r )
50581042 1070{
b7b40adb 1071 CGPathAddArcToPoint( m_path, NULL , x1, y1, x2, y2, r);
50581042
SC
1072}
1073
b7b40adb 1074void wxMacCoreGraphicsPath::AddPath( const wxGraphicsPath* path )
50581042 1075{
b7b40adb 1076 CGPathAddPath( m_path , NULL, (CGPathRef) path->GetNativePath() );
50581042
SC
1077}
1078
b7b40adb
SC
1079// closes the current subpath
1080void wxMacCoreGraphicsPath::CloseSubpath()
50581042 1081{
b7b40adb 1082 CGPathCloseSubpath( m_path );
50581042
SC
1083}
1084
b7b40adb
SC
1085// gets the last point of the current path, (0,0) if not yet set
1086void wxMacCoreGraphicsPath::GetCurrentPoint( wxDouble& x, wxDouble&y)
50581042 1087{
b7b40adb
SC
1088 CGPoint p = CGPathGetCurrentPoint( m_path );
1089 x = p.x;
1090 y = p.y;
50581042
SC
1091}
1092
b7b40adb
SC
1093// transforms each point of this path by the matrix
1094void wxMacCoreGraphicsPath::Transform( wxGraphicsMatrix* matrix )
50581042 1095{
b7b40adb
SC
1096 CGMutablePathRef p = CGPathCreateMutable() ;
1097 CGPathAddPath( p, (CGAffineTransform*) matrix->GetNativeMatrix() , m_path );
1098 CGPathRelease( m_path );
1099 m_path = p;
50581042
SC
1100}
1101
b7b40adb
SC
1102// gets the bounding box enclosing all points (possibly including control points)
1103void wxMacCoreGraphicsPath::GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h)
50581042 1104{
b7b40adb
SC
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;
50581042
SC
1110}
1111
b7b40adb 1112bool wxMacCoreGraphicsPath::Contains( wxDouble x, wxDouble y, int fillStyle)
50581042 1113{
b7b40adb 1114 return CGPathContainsPoint( m_path, NULL, CGPointMake(x,y), fillStyle == wxODDEVEN_RULE );
50581042
SC
1115}
1116
50581042 1117
b7b40adb
SC
1118//
1119// Graphics Pen
1120//
50581042 1121
b7b40adb
SC
1122//-----------------------------------------------------------------------------
1123// wxMacCoreGraphicsPen declaration
1124//-----------------------------------------------------------------------------
50581042 1125
50581042 1126
b7b40adb
SC
1127//
1128// Graphics Context
1129//
50581042 1130
b7b40adb
SC
1131//-----------------------------------------------------------------------------
1132// wxMacCoreGraphicsContext declaration
1133//-----------------------------------------------------------------------------
1134
1135class WXDLLEXPORT wxMacCoreGraphicsContext : public wxGraphicsContext
1136{
1137public:
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();
50581042 1149
b7b40adb 1150 void Init();
50581042 1151
b7b40adb
SC
1152 // push the current state of the context, ie the transformation matrix on a stack
1153 virtual void PushState();
50581042 1154
b7b40adb
SC
1155 // pops a stored state from the stack
1156 virtual void PopState();
50581042 1157
b7b40adb
SC
1158 // clips drawings to the region
1159 virtual void Clip( const wxRegion &region );
50581042 1160
b7b40adb
SC
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();
50581042 1166
b7b40adb
SC
1167 virtual void * GetNativeContext();
1168
1169 //
1170 // transformation
1171 //
1172
1173 // translate
1174 virtual void Translate( wxDouble dx , wxDouble dy );
50581042 1175
b7b40adb
SC
1176 // scale
1177 virtual void Scale( wxDouble xScale , wxDouble yScale );
50581042 1178
b7b40adb
SC
1179 // rotate (radians)
1180 virtual void Rotate( wxDouble angle );
50581042 1181
b7b40adb
SC
1182 // concatenates this transform with the current transform of this context
1183 virtual void ConcatTransform( const wxGraphicsMatrix* matrix );
50581042 1184
b7b40adb
SC
1185 // sets the transform of this context
1186 virtual void SetTransform( const wxGraphicsMatrix* matrix );
50581042 1187
b7b40adb
SC
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 );
50581042 1199
b7b40adb
SC
1200 // sets the font
1201 virtual void SetFont( wxGraphicsFont* font, bool release = true );
50581042 1202
b7b40adb
SC
1203 // strokes along a path with the current pen
1204 virtual void StrokePath( const wxGraphicsPath *path );
50581042 1205
b7b40adb
SC
1206 // fills a path with the current brush
1207 virtual void FillPath( const wxGraphicsPath *path, int fillStyle = wxWINDING_RULE );
50581042 1208
b7b40adb
SC
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
50581042 1213 {
b7b40adb
SC
1214 int penwidth = 0 ;
1215 if ( m_pen )
50581042 1216 {
b7b40adb
SC
1217 penwidth = m_pen->GetWidth();
1218 if ( penwidth == 0 )
1219 penwidth = 1;
50581042 1220 }
b7b40adb 1221 return ( penwidth % 2 ) == 1;
50581042 1222 }
b7b40adb
SC
1223 //
1224 // text
1225 //
1226
1227 virtual void DrawText( const wxString &str, wxDouble x, wxDouble y );
50581042 1228
b7b40adb 1229 virtual void DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle );
50581042 1230
b7b40adb
SC
1231 virtual void GetTextExtent( const wxString &text, wxDouble *width, wxDouble *height,
1232 wxDouble *descent, wxDouble *externalLeading ) const;
50581042 1233
b7b40adb 1234 virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const;
50581042 1235
b7b40adb
SC
1236 //
1237 // image support
1238 //
50581042 1239
b7b40adb 1240 virtual void DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
50581042 1241
b7b40adb 1242 virtual void DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
50581042 1243
b7b40adb
SC
1244 void SetNativeContext( CGContextRef cg );
1245
1246 DECLARE_NO_COPY_CLASS(wxMacCoreGraphicsContext)
1247 DECLARE_DYNAMIC_CLASS(wxMacCoreGraphicsContext)
50581042 1248
b7b40adb
SC
1249private:
1250 void EnsureIsValid();
50581042 1251
b7b40adb
SC
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;
50581042
SC
1258};
1259
b7b40adb
SC
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//-----------------------------------------------------------------------------
50581042 1267
b7b40adb
SC
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)
50581042 1271
b7b40adb
SC
1272//-----------------------------------------------------------------------------
1273// wxMacCoreGraphicsContext implementation
1274//-----------------------------------------------------------------------------
50581042 1275
b7b40adb 1276IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsContext, wxGraphicsContext)
50581042 1277
b7b40adb
SC
1278void 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}
50581042 1288
b7b40adb
SC
1289wxMacCoreGraphicsContext::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}
50581042 1306
b7b40adb
SC
1307wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, WindowRef window ): wxGraphicsContext(renderer)
1308{
1309 Init();
1310 m_windowRef = window;
1311}
50581042 1312
b7b40adb
SC
1313wxMacCoreGraphicsContext::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}
50581042 1320
b7b40adb
SC
1321wxMacCoreGraphicsContext::wxMacCoreGraphicsContext(wxGraphicsRenderer* renderer) : wxGraphicsContext(renderer)
1322{
1323 Init();
1324}
50581042 1325
b7b40adb
SC
1326wxMacCoreGraphicsContext::wxMacCoreGraphicsContext() : wxGraphicsContext(NULL)
1327{
1328 Init();
1329 wxLogDebug(wxT("Illegal Constructor called"));
1330}
50581042 1331
b7b40adb
SC
1332wxMacCoreGraphicsContext::~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 }
50581042 1344
b7b40adb
SC
1345 if ( m_releaseContext )
1346 QDEndCGContext( GetWindowPort( m_windowRef ) , &m_cgContext);
1347}
50581042 1348
b7b40adb
SC
1349void 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}
50581042 1370
50581042 1371
b7b40adb
SC
1372void 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}
50581042 1386
b7b40adb
SC
1387// clips drawings to the rect
1388void 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
1402void 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}
50581042 1415
b7b40adb
SC
1416void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath *path )
1417{
1418 if ( m_pen == NULL )
1419 return ;
50581042 1420
b7b40adb
SC
1421 EnsureIsValid();
1422
1423 bool offset = ShouldOffset();
1424 if ( offset )
1425 CGContextTranslateCTM( m_cgContext, 0.5, 0.5 );
50581042 1426
b7b40adb
SC
1427 m_pen->Apply(this);
1428 CGContextAddPath( m_cgContext , (CGPathRef) path->GetNativePath() );
1429 CGContextStrokePath( m_cgContext );
50581042 1430
b7b40adb
SC
1431 if ( offset )
1432 CGContextTranslateCTM( m_cgContext, -0.5, -0.5 );
1433}
50581042 1434
b7b40adb
SC
1435void 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();
50581042 1472
b7b40adb
SC
1473 if ( m_brush )
1474 m_brush->Apply(this);
07c7a3f1
SC
1475 if ( m_pen )
1476 m_pen->Apply(this);
50581042 1477
b7b40adb
SC
1478 bool offset = ShouldOffset();
1479
1480 if ( offset )
1481 CGContextTranslateCTM( m_cgContext, 0.5, 0.5 );
50581042 1482
b7b40adb
SC
1483 CGContextAddPath( m_cgContext , (CGPathRef) path->GetNativePath() );
1484 CGContextDrawPath( m_cgContext , mode );
50581042 1485
b7b40adb
SC
1486 if ( offset )
1487 CGContextTranslateCTM( m_cgContext, -0.5, -0.5 );
1488}
50581042 1489
b7b40adb
SC
1490void 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 );
50581042
SC
1513 }
1514}
1515
b7b40adb 1516void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg )
50581042 1517{
b7b40adb
SC
1518 // we allow either setting or clearing but not replacing
1519 wxASSERT( m_cgContext == NULL || cg == NULL );
50581042 1520
b7b40adb
SC
1521 if ( cg )
1522 CGContextSaveGState( cg );
1523 m_cgContext = cg;
1524}
50581042 1525
b7b40adb
SC
1526void wxMacCoreGraphicsContext::Translate( wxDouble dx , wxDouble dy )
1527{
1528 EnsureIsValid();
1529
1530 CGContextTranslateCTM( m_cgContext, dx, dy );
1531}
50581042 1532
b7b40adb
SC
1533void wxMacCoreGraphicsContext::Scale( wxDouble xScale , wxDouble yScale )
1534{
1535 EnsureIsValid();
1536
1537 CGContextScaleCTM( m_cgContext , xScale , yScale );
1538}
50581042 1539
b7b40adb
SC
1540void wxMacCoreGraphicsContext::Rotate( wxDouble angle )
1541{
1542 EnsureIsValid();
1543
1544 CGContextRotateCTM( m_cgContext , angle );
1545}
50581042 1546
b7b40adb
SC
1547void 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}
50581042 1556
b7b40adb
SC
1557void 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}
50581042 1569
b7b40adb
SC
1570void wxMacCoreGraphicsContext::PushState()
1571{
1572 EnsureIsValid();
1573
1574 CGContextSaveGState( m_cgContext );
1575}
50581042 1576
b7b40adb
SC
1577void wxMacCoreGraphicsContext::PopState()
1578{
1579 EnsureIsValid();
1580
1581 CGContextRestoreGState( m_cgContext );
50581042
SC
1582}
1583
b7b40adb
SC
1584// sets the pen
1585void wxMacCoreGraphicsContext::SetPen( wxGraphicsPen* pen , bool release )
50581042 1586{
b7b40adb 1587 wxGraphicsContext::SetPen( pen, release );
50581042
SC
1588}
1589
b7b40adb
SC
1590// sets the brush for filling
1591void wxMacCoreGraphicsContext::SetBrush( wxGraphicsBrush* brush , bool release )
50581042 1592{
b7b40adb 1593 wxGraphicsContext::SetBrush( brush, release );
50581042
SC
1594}
1595
b7b40adb
SC
1596// sets the font
1597void wxMacCoreGraphicsContext::SetFont( wxGraphicsFont* font, bool release )
1598{
1599 wxGraphicsContext::SetFont( font, release );
1600}
50581042
SC
1601
1602void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y )
1603{
1604 DrawText(str, x, y, 0.0);
1605}
1606
38af4365 1607void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle )
50581042 1608{
b7b40adb
SC
1609 if ( m_font == NULL )
1610 return;
1611
1612 EnsureIsValid();
1613
50581042
SC
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
b7b40adb 1642 ATSUStyle style = (((wxMacCoreGraphicsFont*)m_font)->GetATSUStyle());
50581042 1643 status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
b7b40adb 1644 &chars , &style , &atsuLayout );
50581042
SC
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
1741void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
1742 wxDouble *descent, wxDouble *externalLeading ) const
1743{
b7b40adb 1744 wxCHECK_RET( m_font != NULL, wxT("wxDC(cg)::DoGetTextExtent - no valid font set") );
50581042
SC
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
b7b40adb 1775 ATSUStyle style = (((wxMacCoreGraphicsFont*)m_font)->GetATSUStyle());
50581042 1776 status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
b7b40adb 1777 &chars , &style , &atsuLayout );
50581042
SC
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
1799void 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
b7b40adb 1834 ATSUStyle style = (((wxMacCoreGraphicsFont*)m_font)->GetATSUStyle());
83b96a06 1835 ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
b7b40adb 1836 &chars , &style , &atsuLayout );
50581042
SC
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
b7b40adb 1857void * wxMacCoreGraphicsContext::GetNativeContext()
50581042 1858{
b7b40adb
SC
1859 return m_cgContext;
1860}
50581042 1861
b7b40adb
SC
1862// concatenates this transform with the current transform of this context
1863void wxMacCoreGraphicsContext::ConcatTransform( const wxGraphicsMatrix* matrix )
1864{
1865}
50581042 1866
b7b40adb
SC
1867// sets the transform of this context
1868void wxMacCoreGraphicsContext::SetTransform( const wxGraphicsMatrix* matrix )
1869{
1870}
50581042 1871
b7b40adb
SC
1872// gets the matrix of this context
1873void wxMacCoreGraphicsContext::GetTransform( wxGraphicsMatrix* matrix )
1874{
1875}
50581042 1876
b7b40adb
SC
1877//
1878// Renderer
1879//
50581042 1880
b7b40adb
SC
1881//-----------------------------------------------------------------------------
1882// wxMacCoreGraphicsRenderer declaration
1883//-----------------------------------------------------------------------------
50581042 1884
b7b40adb
SC
1885class WXDLLIMPEXP_CORE wxMacCoreGraphicsRenderer : public wxGraphicsRenderer
1886{
1887public :
1888 wxMacCoreGraphicsRenderer() {}
50581042 1889
b7b40adb
SC
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
1928private :
1929 DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacCoreGraphicsRenderer)
1930} ;
1931
1932//-----------------------------------------------------------------------------
1933// wxMacCoreGraphicsRenderer implementation
1934//-----------------------------------------------------------------------------
1935
1936IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsRenderer,wxGraphicsRenderer)
1937
1938static wxMacCoreGraphicsRenderer gs_MacCoreGraphicsRenderer;
1939
1940wxGraphicsRenderer* wxGraphicsRenderer::GetDefaultRenderer()
1941{
1942 return &gs_MacCoreGraphicsRenderer;
50581042
SC
1943}
1944
b7b40adb
SC
1945wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxWindowDC& dc)
1946{
1947 return new wxMacCoreGraphicsContext(this,(CGContextRef)dc.GetWindow()->MacGetCGContextRef() );
1948}
1949
1950wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeContext( void * context )
1951{
1952 return new wxMacCoreGraphicsContext(this,(CGContextRef)context);
1953}
1954
1955
1956wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeWindow( void * window )
1957{
1958 return new wxMacCoreGraphicsContext(this,(WindowRef)window);
1959}
1960
1961wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( wxWindow* window )
1962{
1963 return new wxMacCoreGraphicsContext(this, window );
1964}
1965
1966// Path
1967
1968wxGraphicsPath * wxMacCoreGraphicsRenderer::CreatePath()
1969{
1970 return new wxMacCoreGraphicsPath( this );
1971}
1972
1973
1974// Matrix
1975
1976wxGraphicsMatrix * wxMacCoreGraphicsRenderer::CreateMatrix( wxDouble a, wxDouble b, wxDouble c, wxDouble d,
1977 wxDouble tx, wxDouble ty)
1978
1056ddcf 1979{
b7b40adb
SC
1980 wxMacCoreGraphicsMatrix* m = new wxMacCoreGraphicsMatrix( this );
1981 m->Set( a,b,c,d,tx,ty ) ;
1982 return m;
1983}
1984
1985wxGraphicsPen* wxMacCoreGraphicsRenderer::CreatePen(const wxPen& pen)
1986{
1987 if ( !pen.Ok() || pen.GetStyle() == wxTRANSPARENT )
1988 return NULL;
1989 else
1990 return new wxMacCoreGraphicsPen( this, pen );
1056ddcf
SC
1991}
1992
b7b40adb 1993wxGraphicsBrush* wxMacCoreGraphicsRenderer::CreateBrush(const wxBrush& brush )
50581042 1994{
b7b40adb
SC
1995 if ( !brush.Ok() || brush.GetStyle() == wxTRANSPARENT )
1996 return NULL;
1997 else
1998 return new wxMacCoreGraphicsBrush( this, brush );
50581042
SC
1999}
2000
b7b40adb
SC
2001// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
2002wxGraphicsBrush* wxMacCoreGraphicsRenderer::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
2003 const wxColour&c1, const wxColour&c2)
1056ddcf 2004{
b7b40adb
SC
2005 wxMacCoreGraphicsBrush* brush = new wxMacCoreGraphicsBrush(this);
2006 brush->CreateLinearGradientBrush(x1, y1, x2, y2, c1, c2);
2007 return brush;
1056ddcf
SC
2008}
2009
b7b40adb
SC
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
2012wxGraphicsBrush* wxMacCoreGraphicsRenderer::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
2013 const wxColour &oColor, const wxColour &cColor)
1056ddcf 2014{
b7b40adb
SC
2015 wxMacCoreGraphicsBrush* brush = new wxMacCoreGraphicsBrush(this);
2016 brush->CreateRadialGradientBrush(xo,yo,xc,yc,radius,oColor,cColor);
2017 return brush;
1056ddcf
SC
2018}
2019
b7b40adb
SC
2020// sets the font
2021wxGraphicsFont* wxMacCoreGraphicsRenderer::CreateFont( const wxFont &font , const wxColour &col )
513b47e9 2022{
b7b40adb
SC
2023 if ( font.Ok() )
2024 return new wxMacCoreGraphicsFont( this , font, col );
2025 else
2026 return NULL;
513b47e9
SC
2027}
2028
b7b40adb
SC
2029
2030
50581042 2031#endif // wxMAC_USE_CORE_GRAPHICS