1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/dccg.cpp
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
14 #include "wx/graphics.h"
15 #include "wx/private/graphics.h"
18 #include "wx/dcclient.h"
19 #include "wx/dcmemory.h"
20 #include "wx/dcprint.h"
22 #include "wx/region.h"
31 // in case our functions were defined outside std, we make it known all the same
38 #include "wx/osx/private.h"
39 #include "wx/osx/dcprint.h"
40 #include "wx/osx/dcclient.h"
41 #include "wx/osx/dcmemory.h"
43 #include "wx/osx/uma.h"
45 #include "wx/osx/private.h"
49 #include "CoreServices/CoreServices.h"
50 #include "ApplicationServices/ApplicationServices.h"
51 #include "wx/osx/core/cfstring.h"
52 #include "wx/cocoa/dcclient.h"
57 CGColorSpaceRef
wxMacGetGenericRGBColorSpace()
59 static wxCFRef
<CGColorSpaceRef
> genericRGBColorSpace
;
61 if (genericRGBColorSpace
== NULL
)
63 genericRGBColorSpace
.reset( CGColorSpaceCreateWithName( kCGColorSpaceGenericRGB
) );
66 return genericRGBColorSpace
;
69 int UMAGetSystemVersion()
75 #define wxOSX_USE_CORE_TEXT 1
79 //-----------------------------------------------------------------------------
81 //-----------------------------------------------------------------------------
83 #if !defined( __DARWIN__ ) || defined(__MWERKS__)
85 const double M_PI
= 3.14159265358979;
89 static const double RAD2DEG
= 180.0 / M_PI
;
92 // Pen, Brushes and Fonts
96 #pragma mark wxMacCoreGraphicsPattern, ImagePattern, HatchPattern classes
98 OSStatus
wxMacDrawCGImage(
99 CGContextRef inContext
,
100 const CGRect
* inBounds
,
104 return HIViewDrawCGImage( inContext
, inBounds
, inImage
);
107 CGContextDrawImage(inContext
, *inBounds
, inImage
);
112 CGColorRef
wxMacCreateCGColor( const wxColour
& col
)
114 CGColorRef retval
= 0;
116 retval
= col
.CreateCGColor();
118 // TODO add conversion NSColor - CGColorRef (obj-c)
119 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
120 if ( CGColorCreateGenericRGB
)
121 retval
= CGColorCreateGenericRGB( col
.Red() / 255.0 , col
.Green() / 255.0, col
.Blue() / 255.0, col
.Alpha() / 255.0 );
125 CGFloat components
[4] = { col
.Red() / 255.0, col
.Green() / 255.0, col
.Blue() / 255.0, col
.Alpha() / 255.0 } ;
126 retval
= CGColorCreate( wxMacGetGenericRGBColorSpace() , components
) ;
133 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && wxOSX_USE_CORE_TEXT
135 CTFontRef
wxMacCreateCTFont( const wxFont
& font
)
138 return wxCFRetain((CTFontRef
) font
.MacGetCTFont());
140 return CTFontCreateWithName( wxCFStringRef( font
.GetFaceName(), wxLocale::GetSystemEncoding() ) , font
.GetPointSize() , NULL
);
146 // CGPattern wrapper class: always allocate on heap, never call destructor
148 class wxMacCoreGraphicsPattern
151 wxMacCoreGraphicsPattern() {}
153 // is guaranteed to be called only with a non-Null CGContextRef
154 virtual void Render( CGContextRef ctxRef
) = 0;
156 operator CGPatternRef() const { return m_patternRef
; }
159 virtual ~wxMacCoreGraphicsPattern()
161 // as this is called only when the m_patternRef is been released;
162 // don't release it again
165 static void _Render( void *info
, CGContextRef ctxRef
)
167 wxMacCoreGraphicsPattern
* self
= (wxMacCoreGraphicsPattern
*) info
;
168 if ( self
&& ctxRef
)
169 self
->Render( ctxRef
);
172 static void _Dispose( void *info
)
174 wxMacCoreGraphicsPattern
* self
= (wxMacCoreGraphicsPattern
*) info
;
178 CGPatternRef m_patternRef
;
180 static const CGPatternCallbacks ms_Callbacks
;
183 const CGPatternCallbacks
wxMacCoreGraphicsPattern::ms_Callbacks
= { 0, &wxMacCoreGraphicsPattern::_Render
, &wxMacCoreGraphicsPattern::_Dispose
};
185 class ImagePattern
: public wxMacCoreGraphicsPattern
188 ImagePattern( const wxBitmap
* bmp
, const CGAffineTransform
& transform
)
190 wxASSERT( bmp
&& bmp
->Ok() );
192 Init( (CGImageRef
) bmp
->CreateCGImage() , transform
);
196 // ImagePattern takes ownership of CGImageRef passed in
197 ImagePattern( CGImageRef image
, const CGAffineTransform
& transform
)
202 Init( image
, transform
);
205 virtual void Render( CGContextRef ctxRef
)
208 wxMacDrawCGImage( ctxRef
, &m_imageBounds
, m_image
);
212 void Init( CGImageRef image
, const CGAffineTransform
& transform
)
217 m_imageBounds
= CGRectMake( (CGFloat
) 0.0, (CGFloat
) 0.0, (CGFloat
)CGImageGetWidth( m_image
), (CGFloat
)CGImageGetHeight( m_image
) );
218 m_patternRef
= CGPatternCreate(
219 this , m_imageBounds
, transform
,
220 m_imageBounds
.size
.width
, m_imageBounds
.size
.height
,
221 kCGPatternTilingNoDistortion
, true , &wxMacCoreGraphicsPattern::ms_Callbacks
);
225 virtual ~ImagePattern()
228 CGImageRelease( m_image
);
232 CGRect m_imageBounds
;
235 class HatchPattern
: public wxMacCoreGraphicsPattern
238 HatchPattern( int hatchstyle
, const CGAffineTransform
& transform
)
240 m_hatch
= hatchstyle
;
241 m_imageBounds
= CGRectMake( (CGFloat
) 0.0, (CGFloat
) 0.0, (CGFloat
) 8.0 , (CGFloat
) 8.0 );
242 m_patternRef
= CGPatternCreate(
243 this , m_imageBounds
, transform
,
244 m_imageBounds
.size
.width
, m_imageBounds
.size
.height
,
245 kCGPatternTilingNoDistortion
, false , &wxMacCoreGraphicsPattern::ms_Callbacks
);
248 void StrokeLineSegments( CGContextRef ctxRef
, const CGPoint pts
[] , size_t count
)
250 CGContextStrokeLineSegments( ctxRef
, pts
, count
);
253 virtual void Render( CGContextRef ctxRef
)
257 case wxBDIAGONAL_HATCH
:
261 { (CGFloat
) 8.0 , (CGFloat
) 0.0 } , { (CGFloat
) 0.0 , (CGFloat
) 8.0 }
263 StrokeLineSegments( ctxRef
, pts
, 2 );
267 case wxCROSSDIAG_HATCH
:
271 { (CGFloat
) 0.0 , (CGFloat
) 0.0 } , { (CGFloat
) 8.0 , (CGFloat
) 8.0 } ,
272 { (CGFloat
) 8.0 , (CGFloat
) 0.0 } , { (CGFloat
) 0.0 , (CGFloat
) 8.0 }
274 StrokeLineSegments( ctxRef
, pts
, 4 );
278 case wxFDIAGONAL_HATCH
:
282 { (CGFloat
) 0.0 , (CGFloat
) 0.0 } , { (CGFloat
) 8.0 , (CGFloat
) 8.0 }
284 StrokeLineSegments( ctxRef
, pts
, 2 );
292 { (CGFloat
) 0.0 , (CGFloat
) 4.0 } , { (CGFloat
) 8.0 , (CGFloat
) 4.0 } ,
293 { (CGFloat
) 4.0 , (CGFloat
) 0.0 } , { (CGFloat
) 4.0 , (CGFloat
) 8.0 } ,
295 StrokeLineSegments( ctxRef
, pts
, 4 );
299 case wxHORIZONTAL_HATCH
:
303 { (CGFloat
) 0.0 , (CGFloat
) 4.0 } , { (CGFloat
) 8.0 , (CGFloat
) 4.0 } ,
305 StrokeLineSegments( ctxRef
, pts
, 2 );
309 case wxVERTICAL_HATCH
:
313 { (CGFloat
) 4.0 , (CGFloat
) 0.0 } , { (CGFloat
) 4.0 , (CGFloat
) 8.0 } ,
315 StrokeLineSegments( ctxRef
, pts
, 2 );
325 virtual ~HatchPattern() {}
327 CGRect m_imageBounds
;
331 class wxMacCoreGraphicsPenData
: public wxGraphicsObjectRefData
334 wxMacCoreGraphicsPenData( wxGraphicsRenderer
* renderer
, const wxPen
&pen
);
335 ~wxMacCoreGraphicsPenData();
338 virtual void Apply( wxGraphicsContext
* context
);
339 virtual wxDouble
GetWidth() { return m_width
; }
343 wxCFRef
<CGColorRef
> m_color
;
344 wxCFRef
<CGColorSpaceRef
> m_colorSpace
;
350 const CGFloat
*m_lengths
;
351 CGFloat
*m_userLengths
;
355 wxCFRef
<CGPatternRef
> m_pattern
;
356 CGFloat
* m_patternColorComponents
;
359 wxMacCoreGraphicsPenData::wxMacCoreGraphicsPenData( wxGraphicsRenderer
* renderer
, const wxPen
&pen
) :
360 wxGraphicsObjectRefData( renderer
)
364 m_color
.reset( wxMacCreateCGColor( pen
.GetColour() ) ) ;
366 // TODO: * m_dc->m_scaleX
367 m_width
= pen
.GetWidth();
369 m_width
= (CGFloat
) 0.1;
371 switch ( pen
.GetCap() )
374 m_cap
= kCGLineCapRound
;
377 case wxCAP_PROJECTING
:
378 m_cap
= kCGLineCapSquare
;
382 m_cap
= kCGLineCapButt
;
386 m_cap
= kCGLineCapButt
;
390 switch ( pen
.GetJoin() )
393 m_join
= kCGLineJoinBevel
;
397 m_join
= kCGLineJoinMiter
;
401 m_join
= kCGLineJoinRound
;
405 m_join
= kCGLineJoinMiter
;
409 const CGFloat dashUnit
= m_width
< 1.0 ? (CGFloat
) 1.0 : m_width
;
411 const CGFloat dotted
[] = { (CGFloat
) dashUnit
, (CGFloat
) (dashUnit
+ 2.0) };
412 static const CGFloat short_dashed
[] = { (CGFloat
) 9.0 , (CGFloat
) 6.0 };
413 static const CGFloat dashed
[] = { (CGFloat
) 19.0 , (CGFloat
) 9.0 };
414 static const CGFloat dotted_dashed
[] = { (CGFloat
) 9.0 , (CGFloat
) 6.0 , (CGFloat
) 3.0 , (CGFloat
) 3.0 };
416 switch ( pen
.GetStyle() )
422 m_count
= WXSIZEOF(dotted
);
423 m_userLengths
= new CGFloat
[ m_count
] ;
424 memcpy( m_userLengths
, dotted
, sizeof(dotted
) );
425 m_lengths
= m_userLengths
;
429 m_count
= WXSIZEOF(dashed
);
434 m_count
= WXSIZEOF(short_dashed
);
435 m_lengths
= short_dashed
;
439 m_count
= WXSIZEOF(dotted_dashed
);
440 m_lengths
= dotted_dashed
;
445 m_count
= pen
.GetDashes( &dashes
);
446 if ((dashes
!= NULL
) && (m_count
> 0))
448 m_userLengths
= new CGFloat
[m_count
];
449 for ( int i
= 0; i
< m_count
; ++i
)
451 m_userLengths
[i
] = dashes
[i
] * dashUnit
;
453 if ( i
% 2 == 1 && m_userLengths
[i
] < dashUnit
+ 2.0 )
454 m_userLengths
[i
] = (CGFloat
) (dashUnit
+ 2.0);
455 else if ( i
% 2 == 0 && m_userLengths
[i
] < dashUnit
)
456 m_userLengths
[i
] = dashUnit
;
459 m_lengths
= m_userLengths
;
464 wxBitmap
* bmp
= pen
.GetStipple();
465 if ( bmp
&& bmp
->Ok() )
467 m_colorSpace
.reset( CGColorSpaceCreatePattern( NULL
) );
468 m_pattern
.reset( (CGPatternRef
) *( new ImagePattern( bmp
, CGAffineTransformMakeScale( 1,-1 ) ) ) );
469 m_patternColorComponents
= new CGFloat
[1] ;
470 m_patternColorComponents
[0] = (CGFloat
) 1.0;
479 m_colorSpace
.reset( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
480 m_pattern
.reset( (CGPatternRef
) *( new HatchPattern( pen
.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) );
481 m_patternColorComponents
= new CGFloat
[4] ;
482 m_patternColorComponents
[0] = (CGFloat
) (pen
.GetColour().Red() / 255.0);
483 m_patternColorComponents
[1] = (CGFloat
) (pen
.GetColour().Green() / 255.0);
484 m_patternColorComponents
[2] = (CGFloat
) (pen
.GetColour().Blue() / 255.0);
485 m_patternColorComponents
[3] = (CGFloat
) (pen
.GetColour().Alpha() / 255.0);
489 if ((m_lengths
!= NULL
) && (m_count
> 0))
491 // force the line cap, otherwise we get artifacts (overlaps) and just solid lines
492 m_cap
= kCGLineCapButt
;
496 wxMacCoreGraphicsPenData::~wxMacCoreGraphicsPenData()
498 delete[] m_userLengths
;
499 delete[] m_patternColorComponents
;
502 void wxMacCoreGraphicsPenData::Init()
505 m_userLengths
= NULL
;
508 m_patternColorComponents
= NULL
;
512 void wxMacCoreGraphicsPenData::Apply( wxGraphicsContext
* context
)
514 CGContextRef cg
= (CGContextRef
) context
->GetNativeContext();
515 CGContextSetLineWidth( cg
, m_width
);
516 CGContextSetLineJoin( cg
, m_join
);
518 CGContextSetLineDash( cg
, 0 , m_lengths
, m_count
);
519 CGContextSetLineCap( cg
, m_cap
);
523 CGAffineTransform matrix
= CGContextGetCTM( cg
);
524 CGContextSetPatternPhase( cg
, CGSizeMake(matrix
.tx
, matrix
.ty
) );
525 CGContextSetStrokeColorSpace( cg
, m_colorSpace
);
526 CGContextSetStrokePattern( cg
, m_pattern
, m_patternColorComponents
);
530 if ( context
->GetLogicalFunction() == wxINVERT
|| context
->GetLogicalFunction() == wxXOR
)
532 CGContextSetRGBStrokeColor( cg
, (CGFloat
) 1.0,(CGFloat
) 1.0 , (CGFloat
) 1.0, (CGFloat
) 1.0 );
535 CGContextSetStrokeColorWithColor( cg
, m_color
);
543 static const char *gs_stripedback_xpm
[] = {
544 /* columns rows colors chars-per-pixel */
555 wxBitmap
gs_stripedback_bmp( wxImage( (const char* const* ) gs_stripedback_xpm
), -1 ) ;
557 // make sure we all use one class for all conversions from wx to native colour
559 class wxMacCoreGraphicsColour
562 wxMacCoreGraphicsColour();
563 wxMacCoreGraphicsColour(const wxBrush
&brush
);
564 ~wxMacCoreGraphicsColour();
566 void Apply( CGContextRef cgContext
);
569 wxCFRef
<CGColorRef
> m_color
;
570 wxCFRef
<CGColorSpaceRef
> m_colorSpace
;
573 wxCFRef
<CGPatternRef
> m_pattern
;
574 CGFloat
* m_patternColorComponents
;
577 wxMacCoreGraphicsColour::~wxMacCoreGraphicsColour()
579 delete[] m_patternColorComponents
;
582 void wxMacCoreGraphicsColour::Init()
585 m_patternColorComponents
= NULL
;
588 void wxMacCoreGraphicsColour::Apply( CGContextRef cgContext
)
592 CGAffineTransform matrix
= CGContextGetCTM( cgContext
);
593 CGContextSetPatternPhase( cgContext
, CGSizeMake(matrix
.tx
, matrix
.ty
) );
594 CGContextSetFillColorSpace( cgContext
, m_colorSpace
);
595 CGContextSetFillPattern( cgContext
, m_pattern
, m_patternColorComponents
);
599 CGContextSetFillColorWithColor( cgContext
, m_color
);
603 wxMacCoreGraphicsColour::wxMacCoreGraphicsColour()
608 wxMacCoreGraphicsColour::wxMacCoreGraphicsColour( const wxBrush
&brush
)
611 if ( brush
.GetStyle() == wxSOLID
)
613 m_color
.reset( wxMacCreateCGColor( brush
.GetColour() ));
615 else if ( brush
.IsHatch() )
618 m_colorSpace
.reset( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
619 m_pattern
.reset( (CGPatternRef
) *( new HatchPattern( brush
.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) );
621 m_patternColorComponents
= new CGFloat
[4] ;
622 m_patternColorComponents
[0] = (CGFloat
) (brush
.GetColour().Red() / 255.0);
623 m_patternColorComponents
[1] = (CGFloat
) (brush
.GetColour().Green() / 255.0);
624 m_patternColorComponents
[2] = (CGFloat
) (brush
.GetColour().Blue() / 255.0);
625 m_patternColorComponents
[3] = (CGFloat
) (brush
.GetColour().Alpha() / 255.0);
629 // now brush is a bitmap
630 wxBitmap
* bmp
= brush
.GetStipple();
631 if ( bmp
&& bmp
->Ok() )
634 m_patternColorComponents
= new CGFloat
[1] ;
635 m_patternColorComponents
[0] = (CGFloat
) 1.0;
636 m_colorSpace
.reset( CGColorSpaceCreatePattern( NULL
) );
637 m_pattern
.reset( (CGPatternRef
) *( new ImagePattern( bmp
, CGAffineTransformMakeScale( 1,-1 ) ) ) );
642 class wxMacCoreGraphicsBrushData
: public wxGraphicsObjectRefData
645 wxMacCoreGraphicsBrushData( wxGraphicsRenderer
* renderer
);
646 wxMacCoreGraphicsBrushData( wxGraphicsRenderer
* renderer
, const wxBrush
&brush
);
647 ~wxMacCoreGraphicsBrushData ();
649 virtual void Apply( wxGraphicsContext
* context
);
650 void CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
651 const wxColour
&c1
, const wxColour
&c2
);
652 void CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
653 const wxColour
&oColor
, const wxColour
&cColor
);
655 virtual bool IsShading() { return m_isShading
; }
656 CGShadingRef
GetShading() { return m_shading
; }
658 CGFunctionRef
CreateGradientFunction( const wxColour
& c1
, const wxColour
& c2
);
659 static void CalculateShadingValues (void *info
, const CGFloat
*in
, CGFloat
*out
);
662 wxMacCoreGraphicsColour m_cgColor
;
665 CGFunctionRef m_gradientFunction
;
666 CGShadingRef m_shading
;
667 CGFloat
*m_gradientComponents
;
670 wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData( wxGraphicsRenderer
* renderer
) : wxGraphicsObjectRefData( renderer
)
675 void wxMacCoreGraphicsBrushData::CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
676 const wxColour
&c1
, const wxColour
&c2
)
678 m_gradientFunction
= CreateGradientFunction( c1
, c2
);
679 m_shading
= CGShadingCreateAxial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat
) x1
, (CGFloat
) y1
),
680 CGPointMake((CGFloat
) x2
,(CGFloat
) y2
), m_gradientFunction
, true, true ) ;
684 void wxMacCoreGraphicsBrushData::CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
685 const wxColour
&oColor
, const wxColour
&cColor
)
687 m_gradientFunction
= CreateGradientFunction( oColor
, cColor
);
688 m_shading
= CGShadingCreateRadial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat
) xo
,(CGFloat
) yo
), 0,
689 CGPointMake((CGFloat
) xc
,(CGFloat
) yc
), (CGFloat
) radius
, m_gradientFunction
, true, true ) ;
693 wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData(wxGraphicsRenderer
* renderer
, const wxBrush
&brush
) : wxGraphicsObjectRefData( renderer
),
700 wxMacCoreGraphicsBrushData::~wxMacCoreGraphicsBrushData()
703 CGShadingRelease(m_shading
);
705 if( m_gradientFunction
)
706 CGFunctionRelease(m_gradientFunction
);
708 delete[] m_gradientComponents
;
711 void wxMacCoreGraphicsBrushData::Init()
713 m_gradientFunction
= NULL
;
715 m_gradientComponents
= NULL
;
719 void wxMacCoreGraphicsBrushData::Apply( wxGraphicsContext
* context
)
721 CGContextRef cg
= (CGContextRef
) context
->GetNativeContext();
725 // nothing to set as shades are processed by clipping using the path and filling
729 m_cgColor
.Apply( cg
);
733 void wxMacCoreGraphicsBrushData::CalculateShadingValues (void *info
, const CGFloat
*in
, CGFloat
*out
)
735 CGFloat
* colors
= (CGFloat
*) info
;
737 for( int i
= 0 ; i
< 4 ; ++i
)
739 out
[i
] = colors
[i
] + ( colors
[4+i
] - colors
[i
] ) * f
;
743 CGFunctionRef
wxMacCoreGraphicsBrushData::CreateGradientFunction( const wxColour
& c1
, const wxColour
& c2
)
745 static const CGFunctionCallbacks callbacks
= { 0, &CalculateShadingValues
, NULL
};
746 static const CGFloat input_value_range
[2] = { 0, 1 };
747 static const CGFloat output_value_ranges
[8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
748 m_gradientComponents
= new CGFloat
[8] ;
749 m_gradientComponents
[0] = (CGFloat
) (c1
.Red() / 255.0);
750 m_gradientComponents
[1] = (CGFloat
) (c1
.Green() / 255.0);
751 m_gradientComponents
[2] = (CGFloat
) (c1
.Blue() / 255.0);
752 m_gradientComponents
[3] = (CGFloat
) (c1
.Alpha() / 255.0);
753 m_gradientComponents
[4] = (CGFloat
) (c2
.Red() / 255.0);
754 m_gradientComponents
[5] = (CGFloat
) (c2
.Green() / 255.0);
755 m_gradientComponents
[6] = (CGFloat
) (c2
.Blue() / 255.0);
756 m_gradientComponents
[7] = (CGFloat
) (c2
.Alpha() / 255.0);
758 return CGFunctionCreate ( m_gradientComponents
, 1,
771 extern UIFont
* CreateUIFont( const wxFont
& font
);
772 extern void DrawTextInContext( CGContextRef context
, CGPoint where
, UIFont
*font
, NSString
* text
);
773 extern CGSize
MeasureTextInContext( UIFont
*font
, NSString
* text
);
777 class wxMacCoreGraphicsFontData
: public wxGraphicsObjectRefData
780 wxMacCoreGraphicsFontData( wxGraphicsRenderer
* renderer
, const wxFont
&font
, const wxColour
& col
);
781 ~wxMacCoreGraphicsFontData();
783 #if wxOSX_USE_ATSU_TEXT
784 virtual ATSUStyle
GetATSUStyle() { return m_macATSUIStyle
; }
786 #if wxOSX_USE_CORE_TEXT
787 CTFontRef
GetCTFont() const { return m_ctFont
; }
789 wxColour
GetColour() const { return m_colour
; }
791 bool GetUnderlined() const { return m_underlined
; }
793 UIFont
* GetUIFont() const { return m_uiFont
; }
798 #if wxOSX_USE_ATSU_TEXT
799 ATSUStyle m_macATSUIStyle
;
801 #if wxOSX_USE_CORE_TEXT
802 wxCFRef
< CTFontRef
> m_ctFont
;
809 wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer
* renderer
, const wxFont
&font
, const wxColour
& col
) : wxGraphicsObjectRefData( renderer
)
812 m_underlined
= font
.GetUnderlined();
814 #if wxOSX_USE_CORE_TEXT
815 m_ctFont
.reset( wxMacCreateCTFont( font
) );
818 m_uiFont
= CreateUIFont(font
);
819 wxMacCocoaRetain( m_uiFont
);
821 #if wxOSX_USE_ATSU_TEXT
822 OSStatus status
= noErr
;
823 m_macATSUIStyle
= NULL
;
825 status
= ATSUCreateAndCopyStyle( (ATSUStyle
) font
.MacGetATSUStyle() , &m_macATSUIStyle
);
827 wxASSERT_MSG( status
== noErr
, wxT("couldn't create ATSU style") );
829 // we need the scale here ...
831 Fixed atsuSize
= IntToFixed( int( 1 * font
.MacGetFontSize()) );
833 col
.GetRGBColor( &atsuColor
);
834 ATSUAttributeTag atsuTags
[] =
839 ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
844 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
850 status
= ::ATSUSetAttributes(
851 m_macATSUIStyle
, sizeof(atsuTags
) / sizeof(ATSUAttributeTag
) ,
852 atsuTags
, atsuSizes
, atsuValues
);
854 wxASSERT_MSG( status
== noErr
, wxT("couldn't modify ATSU style") );
858 wxMacCoreGraphicsFontData::~wxMacCoreGraphicsFontData()
860 #if wxOSX_USE_CORE_TEXT
862 #if wxOSX_USE_ATSU_TEXT
863 if ( m_macATSUIStyle
)
865 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUIStyle
);
866 m_macATSUIStyle
= NULL
;
870 wxMacCocoaRelease( m_uiFont
);
874 class wxMacCoreGraphicsBitmapData
: public wxGraphicsObjectRefData
877 wxMacCoreGraphicsBitmapData( wxGraphicsRenderer
* renderer
, CGImageRef bitmap
, bool monochrome
);
878 ~wxMacCoreGraphicsBitmapData();
880 virtual CGImageRef
GetBitmap() { return m_bitmap
; }
881 bool IsMonochrome() { return m_monochrome
; }
887 wxMacCoreGraphicsBitmapData::wxMacCoreGraphicsBitmapData( wxGraphicsRenderer
* renderer
, CGImageRef bitmap
, bool monochrome
) : wxGraphicsObjectRefData( renderer
),
888 m_bitmap(bitmap
), m_monochrome(monochrome
)
892 wxMacCoreGraphicsBitmapData::~wxMacCoreGraphicsBitmapData()
894 CGImageRelease( m_bitmap
);
901 //-----------------------------------------------------------------------------
902 // wxMacCoreGraphicsMatrix declaration
903 //-----------------------------------------------------------------------------
905 class WXDLLIMPEXP_CORE wxMacCoreGraphicsMatrixData
: public wxGraphicsMatrixData
908 wxMacCoreGraphicsMatrixData(wxGraphicsRenderer
* renderer
) ;
910 virtual ~wxMacCoreGraphicsMatrixData() ;
912 virtual wxGraphicsObjectRefData
*Clone() const ;
914 // concatenates the matrix
915 virtual void Concat( const wxGraphicsMatrixData
*t
);
917 // sets the matrix to the respective values
918 virtual void Set(wxDouble a
=1.0, wxDouble b
=0.0, wxDouble c
=0.0, wxDouble d
=1.0,
919 wxDouble tx
=0.0, wxDouble ty
=0.0);
921 // gets the component valuess of the matrix
922 virtual void Get(wxDouble
* a
=NULL
, wxDouble
* b
=NULL
, wxDouble
* c
=NULL
,
923 wxDouble
* d
=NULL
, wxDouble
* tx
=NULL
, wxDouble
* ty
=NULL
) const;
925 // makes this the inverse matrix
926 virtual void Invert();
928 // returns true if the elements of the transformation matrix are equal ?
929 virtual bool IsEqual( const wxGraphicsMatrixData
* t
) const ;
931 // return true if this is the identity matrix
932 virtual bool IsIdentity() const;
938 // add the translation to this matrix
939 virtual void Translate( wxDouble dx
, wxDouble dy
);
941 // add the scale to this matrix
942 virtual void Scale( wxDouble xScale
, wxDouble yScale
);
944 // add the rotation to this matrix (radians)
945 virtual void Rotate( wxDouble angle
);
948 // apply the transforms
951 // applies that matrix to the point
952 virtual void TransformPoint( wxDouble
*x
, wxDouble
*y
) const;
954 // applies the matrix except for translations
955 virtual void TransformDistance( wxDouble
*dx
, wxDouble
*dy
) const;
957 // returns the native representation
958 virtual void * GetNativeMatrix() const;
961 CGAffineTransform m_matrix
;
964 //-----------------------------------------------------------------------------
965 // wxMacCoreGraphicsMatrix implementation
966 //-----------------------------------------------------------------------------
968 wxMacCoreGraphicsMatrixData::wxMacCoreGraphicsMatrixData(wxGraphicsRenderer
* renderer
) : wxGraphicsMatrixData(renderer
)
972 wxMacCoreGraphicsMatrixData::~wxMacCoreGraphicsMatrixData()
976 wxGraphicsObjectRefData
*wxMacCoreGraphicsMatrixData::Clone() const
978 wxMacCoreGraphicsMatrixData
* m
= new wxMacCoreGraphicsMatrixData(GetRenderer()) ;
979 m
->m_matrix
= m_matrix
;
983 // concatenates the matrix
984 void wxMacCoreGraphicsMatrixData::Concat( const wxGraphicsMatrixData
*t
)
986 m_matrix
= CGAffineTransformConcat(m_matrix
, *((CGAffineTransform
*) t
->GetNativeMatrix()) );
989 // sets the matrix to the respective values
990 void wxMacCoreGraphicsMatrixData::Set(wxDouble a
, wxDouble b
, wxDouble c
, wxDouble d
,
991 wxDouble tx
, wxDouble ty
)
993 m_matrix
= CGAffineTransformMake((CGFloat
) a
,(CGFloat
) b
,(CGFloat
) c
,(CGFloat
) d
,(CGFloat
) tx
,(CGFloat
) ty
);
996 // gets the component valuess of the matrix
997 void wxMacCoreGraphicsMatrixData::Get(wxDouble
* a
, wxDouble
* b
, wxDouble
* c
,
998 wxDouble
* d
, wxDouble
* tx
, wxDouble
* ty
) const
1000 if (a
) *a
= m_matrix
.a
;
1001 if (b
) *b
= m_matrix
.b
;
1002 if (c
) *c
= m_matrix
.c
;
1003 if (d
) *d
= m_matrix
.d
;
1004 if (tx
) *tx
= m_matrix
.tx
;
1005 if (ty
) *ty
= m_matrix
.ty
;
1008 // makes this the inverse matrix
1009 void wxMacCoreGraphicsMatrixData::Invert()
1011 m_matrix
= CGAffineTransformInvert( m_matrix
);
1014 // returns true if the elements of the transformation matrix are equal ?
1015 bool wxMacCoreGraphicsMatrixData::IsEqual( const wxGraphicsMatrixData
* t
) const
1017 return CGAffineTransformEqualToTransform(m_matrix
, *((CGAffineTransform
*) t
->GetNativeMatrix()));
1020 // return true if this is the identity matrix
1021 bool wxMacCoreGraphicsMatrixData::IsIdentity() const
1023 return ( m_matrix
.a
== 1 && m_matrix
.d
== 1 &&
1024 m_matrix
.b
== 0 && m_matrix
.d
== 0 && m_matrix
.tx
== 0 && m_matrix
.ty
== 0);
1031 // add the translation to this matrix
1032 void wxMacCoreGraphicsMatrixData::Translate( wxDouble dx
, wxDouble dy
)
1034 m_matrix
= CGAffineTransformTranslate( m_matrix
, (CGFloat
) dx
, (CGFloat
) dy
);
1037 // add the scale to this matrix
1038 void wxMacCoreGraphicsMatrixData::Scale( wxDouble xScale
, wxDouble yScale
)
1040 m_matrix
= CGAffineTransformScale( m_matrix
, (CGFloat
) xScale
, (CGFloat
) yScale
);
1043 // add the rotation to this matrix (radians)
1044 void wxMacCoreGraphicsMatrixData::Rotate( wxDouble angle
)
1046 m_matrix
= CGAffineTransformRotate( m_matrix
, (CGFloat
) angle
);
1050 // apply the transforms
1053 // applies that matrix to the point
1054 void wxMacCoreGraphicsMatrixData::TransformPoint( wxDouble
*x
, wxDouble
*y
) const
1056 CGPoint pt
= CGPointApplyAffineTransform( CGPointMake((CGFloat
) *x
,(CGFloat
) *y
), m_matrix
);
1062 // applies the matrix except for translations
1063 void wxMacCoreGraphicsMatrixData::TransformDistance( wxDouble
*dx
, wxDouble
*dy
) const
1065 CGSize sz
= CGSizeApplyAffineTransform( CGSizeMake((CGFloat
) *dx
,(CGFloat
) *dy
) , m_matrix
);
1070 // returns the native representation
1071 void * wxMacCoreGraphicsMatrixData::GetNativeMatrix() const
1073 return (void*) &m_matrix
;
1080 //-----------------------------------------------------------------------------
1081 // wxMacCoreGraphicsPath declaration
1082 //-----------------------------------------------------------------------------
1084 class WXDLLEXPORT wxMacCoreGraphicsPathData
: public wxGraphicsPathData
1087 wxMacCoreGraphicsPathData( wxGraphicsRenderer
* renderer
, CGMutablePathRef path
= NULL
);
1089 ~wxMacCoreGraphicsPathData();
1091 virtual wxGraphicsObjectRefData
*Clone() const;
1093 // begins a new subpath at (x,y)
1094 virtual void MoveToPoint( wxDouble x
, wxDouble y
);
1096 // adds a straight line from the current point to (x,y)
1097 virtual void AddLineToPoint( wxDouble x
, wxDouble y
);
1099 // adds a cubic Bezier curve from the current point, using two control points and an end point
1100 virtual void AddCurveToPoint( wxDouble cx1
, wxDouble cy1
, wxDouble cx2
, wxDouble cy2
, wxDouble x
, wxDouble y
);
1102 // closes the current sub-path
1103 virtual void CloseSubpath();
1105 // gets the last point of the current path, (0,0) if not yet set
1106 virtual void GetCurrentPoint( wxDouble
* x
, wxDouble
* y
) const;
1108 // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
1109 virtual void AddArc( wxDouble x
, wxDouble y
, wxDouble r
, wxDouble startAngle
, wxDouble endAngle
, bool clockwise
);
1112 // These are convenience functions which - if not available natively will be assembled
1113 // using the primitives from above
1116 // adds a quadratic Bezier curve from the current point, using a control point and an end point
1117 virtual void AddQuadCurveToPoint( wxDouble cx
, wxDouble cy
, wxDouble x
, wxDouble y
);
1119 // appends a rectangle as a new closed subpath
1120 virtual void AddRectangle( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
1122 // appends an ellipsis as a new closed subpath fitting the passed rectangle
1123 virtual void AddCircle( wxDouble x
, wxDouble y
, wxDouble r
);
1125 // 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)
1126 virtual void AddArcToPoint( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
, wxDouble r
);
1128 // adds another path
1129 virtual void AddPath( const wxGraphicsPathData
* path
);
1131 // returns the native path
1132 virtual void * GetNativePath() const { return m_path
; }
1134 // give the native path returned by GetNativePath() back (there might be some deallocations necessary)
1135 virtual void UnGetNativePath(void *WXUNUSED(p
)) const {}
1137 // transforms each point of this path by the matrix
1138 virtual void Transform( const wxGraphicsMatrixData
* matrix
);
1140 // gets the bounding box enclosing all points (possibly including control points)
1141 virtual void GetBox(wxDouble
*x
, wxDouble
*y
, wxDouble
*w
, wxDouble
*y
) const;
1143 virtual bool Contains( wxDouble x
, wxDouble y
, int fillStyle
= wxODDEVEN_RULE
) const;
1145 CGMutablePathRef m_path
;
1148 //-----------------------------------------------------------------------------
1149 // wxMacCoreGraphicsPath implementation
1150 //-----------------------------------------------------------------------------
1152 wxMacCoreGraphicsPathData::wxMacCoreGraphicsPathData( wxGraphicsRenderer
* renderer
, CGMutablePathRef path
) : wxGraphicsPathData(renderer
)
1157 m_path
= CGPathCreateMutable();
1160 wxMacCoreGraphicsPathData::~wxMacCoreGraphicsPathData()
1162 CGPathRelease( m_path
);
1165 wxGraphicsObjectRefData
* wxMacCoreGraphicsPathData::Clone() const
1167 wxMacCoreGraphicsPathData
* clone
= new wxMacCoreGraphicsPathData(GetRenderer(),CGPathCreateMutableCopy(m_path
));
1172 // opens (starts) a new subpath
1173 void wxMacCoreGraphicsPathData::MoveToPoint( wxDouble x1
, wxDouble y1
)
1175 CGPathMoveToPoint( m_path
, NULL
, (CGFloat
) x1
, (CGFloat
) y1
);
1178 void wxMacCoreGraphicsPathData::AddLineToPoint( wxDouble x1
, wxDouble y1
)
1180 CGPathAddLineToPoint( m_path
, NULL
, (CGFloat
) x1
, (CGFloat
) y1
);
1183 void wxMacCoreGraphicsPathData::AddCurveToPoint( wxDouble cx1
, wxDouble cy1
, wxDouble cx2
, wxDouble cy2
, wxDouble x
, wxDouble y
)
1185 CGPathAddCurveToPoint( m_path
, NULL
, (CGFloat
) cx1
, (CGFloat
) cy1
, (CGFloat
) cx2
, (CGFloat
) cy2
, (CGFloat
) x
, (CGFloat
) y
);
1188 void wxMacCoreGraphicsPathData::AddQuadCurveToPoint( wxDouble cx1
, wxDouble cy1
, wxDouble x
, wxDouble y
)
1190 CGPathAddQuadCurveToPoint( m_path
, NULL
, (CGFloat
) cx1
, (CGFloat
) cy1
, (CGFloat
) x
, (CGFloat
) y
);
1193 void wxMacCoreGraphicsPathData::AddRectangle( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1195 CGRect cgRect
= { { (CGFloat
) x
, (CGFloat
) y
} , { (CGFloat
) w
, (CGFloat
) h
} };
1196 CGPathAddRect( m_path
, NULL
, cgRect
);
1199 void wxMacCoreGraphicsPathData::AddCircle( wxDouble x
, wxDouble y
, wxDouble r
)
1201 CGPathAddArc( m_path
, NULL
, (CGFloat
) x
, (CGFloat
) y
, (CGFloat
) r
, (CGFloat
) 0.0 , (CGFloat
) (2 * M_PI
) , true );
1204 // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
1205 void wxMacCoreGraphicsPathData::AddArc( wxDouble x
, wxDouble y
, wxDouble r
, wxDouble startAngle
, wxDouble endAngle
, bool clockwise
)
1207 // inverse direction as we the 'normal' state is a y axis pointing down, ie mirrored to the standard core graphics setup
1208 CGPathAddArc( m_path
, NULL
, (CGFloat
) x
, (CGFloat
) y
, (CGFloat
) r
, (CGFloat
) startAngle
, (CGFloat
) endAngle
, !clockwise
);
1211 void wxMacCoreGraphicsPathData::AddArcToPoint( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
, wxDouble r
)
1213 CGPathAddArcToPoint( m_path
, NULL
, (CGFloat
) x1
, (CGFloat
) y1
, (CGFloat
) x2
, (CGFloat
) y2
, (CGFloat
) r
);
1216 void wxMacCoreGraphicsPathData::AddPath( const wxGraphicsPathData
* path
)
1218 CGPathAddPath( m_path
, NULL
, (CGPathRef
) path
->GetNativePath() );
1221 // closes the current subpath
1222 void wxMacCoreGraphicsPathData::CloseSubpath()
1224 CGPathCloseSubpath( m_path
);
1227 // gets the last point of the current path, (0,0) if not yet set
1228 void wxMacCoreGraphicsPathData::GetCurrentPoint( wxDouble
* x
, wxDouble
* y
) const
1230 CGPoint p
= CGPathGetCurrentPoint( m_path
);
1235 // transforms each point of this path by the matrix
1236 void wxMacCoreGraphicsPathData::Transform( const wxGraphicsMatrixData
* matrix
)
1238 CGMutablePathRef p
= CGPathCreateMutable() ;
1239 CGPathAddPath( p
, (CGAffineTransform
*) matrix
->GetNativeMatrix() , m_path
);
1240 CGPathRelease( m_path
);
1244 // gets the bounding box enclosing all points (possibly including control points)
1245 void wxMacCoreGraphicsPathData::GetBox(wxDouble
*x
, wxDouble
*y
, wxDouble
*w
, wxDouble
*h
) const
1247 CGRect bounds
= CGPathGetBoundingBox( m_path
) ;
1248 *x
= bounds
.origin
.x
;
1249 *y
= bounds
.origin
.y
;
1250 *w
= bounds
.size
.width
;
1251 *h
= bounds
.size
.height
;
1254 bool wxMacCoreGraphicsPathData::Contains( wxDouble x
, wxDouble y
, int fillStyle
) const
1256 return CGPathContainsPoint( m_path
, NULL
, CGPointMake((CGFloat
) x
,(CGFloat
) y
), fillStyle
== wxODDEVEN_RULE
);
1263 //-----------------------------------------------------------------------------
1264 // wxMacCoreGraphicsContext declaration
1265 //-----------------------------------------------------------------------------
1267 class WXDLLEXPORT wxMacCoreGraphicsContext
: public wxGraphicsContext
1270 wxMacCoreGraphicsContext( wxGraphicsRenderer
* renderer
, CGContextRef cgcontext
, wxDouble width
= 0, wxDouble height
= 0 );
1272 #if wxOSX_USE_CARBON
1273 wxMacCoreGraphicsContext( wxGraphicsRenderer
* renderer
, WindowRef window
);
1276 wxMacCoreGraphicsContext( wxGraphicsRenderer
* renderer
, wxWindow
* window
);
1278 wxMacCoreGraphicsContext( wxGraphicsRenderer
* renderer
);
1280 wxMacCoreGraphicsContext();
1282 ~wxMacCoreGraphicsContext();
1286 // returns the size of the graphics context in device coordinates
1287 virtual void GetSize( wxDouble
* width
, wxDouble
* height
);
1289 virtual void StartPage( wxDouble width
, wxDouble height
);
1291 virtual void EndPage();
1293 virtual void Flush();
1295 // push the current state of the context, ie the transformation matrix on a stack
1296 virtual void PushState();
1298 // pops a stored state from the stack
1299 virtual void PopState();
1301 // clips drawings to the region
1302 virtual void Clip( const wxRegion
®ion
);
1304 // clips drawings to the rect
1305 virtual void Clip( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
1307 // resets the clipping to original extent
1308 virtual void ResetClip();
1310 virtual void * GetNativeContext();
1312 bool SetLogicalFunction( int function
);
1318 virtual void Translate( wxDouble dx
, wxDouble dy
);
1321 virtual void Scale( wxDouble xScale
, wxDouble yScale
);
1324 virtual void Rotate( wxDouble angle
);
1326 // concatenates this transform with the current transform of this context
1327 virtual void ConcatTransform( const wxGraphicsMatrix
& matrix
);
1329 // sets the transform of this context
1330 virtual void SetTransform( const wxGraphicsMatrix
& matrix
);
1332 // gets the matrix of this context
1333 virtual wxGraphicsMatrix
GetTransform() const;
1335 // setting the paint
1338 // strokes along a path with the current pen
1339 virtual void StrokePath( const wxGraphicsPath
&path
);
1341 // fills a path with the current brush
1342 virtual void FillPath( const wxGraphicsPath
&path
, int fillStyle
= wxODDEVEN_RULE
);
1344 // draws a path by first filling and then stroking
1345 virtual void DrawPath( const wxGraphicsPath
&path
, int fillStyle
= wxODDEVEN_RULE
);
1347 virtual bool ShouldOffset() const
1350 if ( !m_pen
.IsNull() )
1352 penwidth
= (int)((wxMacCoreGraphicsPenData
*)m_pen
.GetRefData())->GetWidth();
1353 if ( penwidth
== 0 )
1356 return ( penwidth
% 2 ) == 1;
1362 virtual void DrawText( const wxString
&str
, wxDouble x
, wxDouble y
);
1364 virtual void DrawText( const wxString
&str
, wxDouble x
, wxDouble y
, wxDouble angle
);
1366 virtual void GetTextExtent( const wxString
&text
, wxDouble
*width
, wxDouble
*height
,
1367 wxDouble
*descent
, wxDouble
*externalLeading
) const;
1369 virtual void GetPartialTextExtents(const wxString
& text
, wxArrayDouble
& widths
) const;
1375 virtual void DrawBitmap( const wxBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
1377 virtual void DrawBitmap( const wxGraphicsBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
1379 virtual void DrawIcon( const wxIcon
&icon
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
1381 void SetNativeContext( CGContextRef cg
);
1383 DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacCoreGraphicsContext
)
1386 void EnsureIsValid();
1388 CGContextRef m_cgContext
;
1389 #if wxOSX_USE_CARBON
1390 WindowRef m_windowRef
;
1392 bool m_releaseContext
;
1393 CGAffineTransform m_windowTransform
;
1397 #if wxOSX_USE_CARBON
1398 wxCFRef
<HIShapeRef
> m_clipRgn
;
1402 //-----------------------------------------------------------------------------
1403 // device context implementation
1405 // more and more of the dc functionality should be implemented by calling
1406 // the appropricate wxMacCoreGraphicsContext, but we will have to do that step by step
1407 // also coordinate conversions should be moved to native matrix ops
1408 //-----------------------------------------------------------------------------
1410 // we always stock two context states, one at entry, to be able to preserve the
1411 // state we were called with, the other one after changing to HI Graphics orientation
1412 // (this one is used for getting back clippings etc)
1414 //-----------------------------------------------------------------------------
1415 // wxMacCoreGraphicsContext implementation
1416 //-----------------------------------------------------------------------------
1418 IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsContext
, wxGraphicsContext
)
1420 class wxQuartzOffsetHelper
1423 wxQuartzOffsetHelper( CGContextRef cg
, bool offset
)
1428 CGContextTranslateCTM( m_cg
, (CGFloat
) 0.5, (CGFloat
) 0.5 );
1430 ~wxQuartzOffsetHelper( )
1433 CGContextTranslateCTM( m_cg
, (CGFloat
) -0.5, (CGFloat
) -0.5 );
1440 void wxMacCoreGraphicsContext::Init()
1443 m_releaseContext
= false;
1444 #if wxOSX_USE_CARBON
1451 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer
* renderer
, CGContextRef cgcontext
, wxDouble width
, wxDouble height
) : wxGraphicsContext(renderer
)
1454 SetNativeContext(cgcontext
);
1459 #if wxOSX_USE_CARBON
1460 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer
* renderer
, WindowRef window
): wxGraphicsContext(renderer
)
1463 m_windowRef
= window
;
1467 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer
* renderer
, wxWindow
* window
): wxGraphicsContext(renderer
)
1471 int originX
, originY
;
1472 originX
= originY
= 0;
1474 Rect bounds
= { 0,0,0,0 };
1475 #if defined(__WXCOCOA__) || !wxOSX_USE_CARBON
1477 m_windowRef
= (WindowRef
) window
->MacGetTopLevelWindowRef();
1478 window
->MacWindowToRootWindow( &originX
, &originY
);
1479 GetWindowBounds( m_windowRef
, kWindowContentRgn
, &bounds
);
1481 m_windowTransform
= CGAffineTransformMakeTranslation( 0 , bounds
.bottom
- bounds
.top
);
1482 m_windowTransform
= CGAffineTransformScale( m_windowTransform
, 1 , -1 );
1483 m_windowTransform
= CGAffineTransformTranslate( m_windowTransform
, originX
, originY
) ;
1486 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext(wxGraphicsRenderer
* renderer
) : wxGraphicsContext(renderer
)
1491 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext() : wxGraphicsContext(NULL
)
1494 wxLogDebug(wxT("Illegal Constructor called"));
1497 wxMacCoreGraphicsContext::~wxMacCoreGraphicsContext()
1499 SetNativeContext(NULL
);
1502 void wxMacCoreGraphicsContext::GetSize( wxDouble
* width
, wxDouble
* height
)
1509 void wxMacCoreGraphicsContext::StartPage( wxDouble width
, wxDouble height
)
1512 if ( width
!= 0 && height
!= 0)
1513 r
= CGRectMake( (CGFloat
) 0.0 , (CGFloat
) 0.0 , (CGFloat
) width
, (CGFloat
) height
);
1515 r
= CGRectMake( (CGFloat
) 0.0 , (CGFloat
) 0.0 , (CGFloat
) m_width
, (CGFloat
) m_height
);
1517 CGContextBeginPage(m_cgContext
, &r
);
1518 // CGContextTranslateCTM( m_cgContext , 0 , height == 0 ? m_height : height );
1519 // CGContextScaleCTM( m_cgContext , 1 , -1 );
1522 void wxMacCoreGraphicsContext::EndPage()
1524 CGContextEndPage(m_cgContext
);
1527 void wxMacCoreGraphicsContext::Flush()
1529 CGContextFlush(m_cgContext
);
1532 void wxMacCoreGraphicsContext::EnsureIsValid()
1536 #if defined(__WXCOCOA__) || ! wxOSX_USE_CARBON
1537 wxFAIL_MSG("Cannot create wxDCs lazily");
1539 OSStatus status
= QDBeginCGContext( GetWindowPort( m_windowRef
) , &m_cgContext
);
1540 if ( status
!= noErr
)
1542 wxFAIL_MSG("Cannot nest wxDCs on the same window");
1545 CGContextConcatCTM( m_cgContext
, m_windowTransform
);
1546 CGContextSaveGState( m_cgContext
);
1547 m_releaseContext
= true;
1548 if ( m_clipRgn
.get() )
1550 // the clip region is in device coordinates, so we convert this again to user coordinates
1551 wxCFRef
<HIMutableShapeRef
> hishape( HIShapeCreateMutableCopy( m_clipRgn
) );
1552 CGPoint transformedOrigin
= CGPointApplyAffineTransform( CGPointZero
,m_windowTransform
);
1553 HIShapeOffset( hishape
, -transformedOrigin
.x
, -transformedOrigin
.y
);
1554 // if the shape is empty, HIShapeReplacePathInCGContext doesn't work
1555 if ( HIShapeIsEmpty(hishape
))
1557 CGRect empty
= CGRectMake( 0,0,0,0 );
1558 CGContextClipToRect( m_cgContext
, empty
);
1562 HIShapeReplacePathInCGContext( hishape
, m_cgContext
);
1563 CGContextClip( m_cgContext
);
1566 CGContextSaveGState( m_cgContext
);
1571 // TODO test whether the private CGContextSetCompositeOperation works under 10.3 (using NSCompositingModes)
1573 bool wxMacCoreGraphicsContext::SetLogicalFunction( int function
)
1575 if (m_logicalFunction
== function
)
1580 bool retval
= false;
1581 bool shouldAntiAlias
= true;
1582 CGBlendMode mode
= kCGBlendModeNormal
;
1584 #if defined(__WXMAC__) && ( wxOSX_USE_IPHONE || ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 ) )
1585 #if wxOSX_USE_IPHONE
1588 if ( UMAGetSystemVersion() >= 0x1050 )
1594 // TODO find best corresponding porter duff modes
1596 mode
= kCGBlendModeCopy
;
1599 mode
= kCGBlendModeClear
;
1602 mode
= kCGBlendModeXOR
;
1603 shouldAntiAlias
= false;
1613 if ( function
== wxCOPY
)
1617 else if ( function
== wxINVERT
|| function
== wxXOR
)
1619 // change color to white
1620 mode
= kCGBlendModeExclusion
;
1621 shouldAntiAlias
= false;
1628 m_logicalFunction
= function
;
1629 CGContextSetBlendMode( m_cgContext
, mode
);
1630 CGContextSetShouldAntialias(m_cgContext
, shouldAntiAlias
);
1635 void wxMacCoreGraphicsContext::Clip( const wxRegion
®ion
)
1637 #if wxOSX_USE_CARBON
1640 wxCFRef
<HIShapeRef
> shape
= wxCFRefFromGet(region
.GetWXHRGN());
1641 // if the shape is empty, HIShapeReplacePathInCGContext doesn't work
1642 if ( HIShapeIsEmpty(shape
))
1644 CGRect empty
= CGRectMake( 0,0,0,0 );
1645 CGContextClipToRect( m_cgContext
, empty
);
1649 HIShapeReplacePathInCGContext( shape
, m_cgContext
);
1650 CGContextClip( m_cgContext
);
1655 // this offsetting to device coords is not really correct, but since we cannot apply affine transforms
1656 // to regions we try at least to have correct translations
1657 HIMutableShapeRef mutableShape
= HIShapeCreateMutableCopy( region
.GetWXHRGN() );
1659 CGPoint transformedOrigin
= CGPointApplyAffineTransform( CGPointZero
, m_windowTransform
);
1660 HIShapeOffset( mutableShape
, transformedOrigin
.x
, transformedOrigin
.y
);
1661 m_clipRgn
.reset(mutableShape
);
1664 // allow usage as measuring context
1665 // wxASSERT_MSG( m_cgContext != NULL, "Needs a valid context for clipping" );
1669 // clips drawings to the rect
1670 void wxMacCoreGraphicsContext::Clip( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1672 CGRect r
= CGRectMake( (CGFloat
) x
, (CGFloat
) y
, (CGFloat
) w
, (CGFloat
) h
);
1675 CGContextClipToRect( m_cgContext
, r
);
1679 #if wxOSX_USE_CARBON
1680 // the clipping itself must be stored as device coordinates, otherwise
1681 // we cannot apply it back correctly
1682 r
.origin
= CGPointApplyAffineTransform( r
.origin
, m_windowTransform
);
1683 m_clipRgn
.reset(HIShapeCreateWithRect(&r
));
1685 // allow usage as measuring context
1686 // wxFAIL_MSG( "Needs a valid context for clipping" );
1691 // resets the clipping to original extent
1692 void wxMacCoreGraphicsContext::ResetClip()
1696 // there is no way for clearing the clip, we can only revert to the stored
1697 // state, but then we have to make sure everything else is NOT restored
1698 CGAffineTransform transform
= CGContextGetCTM( m_cgContext
);
1699 CGContextRestoreGState( m_cgContext
);
1700 CGContextSaveGState( m_cgContext
);
1701 CGAffineTransform transformNew
= CGContextGetCTM( m_cgContext
);
1702 transformNew
= CGAffineTransformInvert( transformNew
) ;
1703 CGContextConcatCTM( m_cgContext
, transformNew
);
1704 CGContextConcatCTM( m_cgContext
, transform
);
1708 #if wxOSX_USE_CARBON
1711 // allow usage as measuring context
1712 // wxFAIL_MSG( "Needs a valid context for clipping" );
1717 void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath
&path
)
1719 if ( m_pen
.IsNull() )
1724 wxQuartzOffsetHelper
helper( m_cgContext
, ShouldOffset() );
1726 ((wxMacCoreGraphicsPenData
*)m_pen
.GetRefData())->Apply(this);
1727 CGContextAddPath( m_cgContext
, (CGPathRef
) path
.GetNativePath() );
1728 CGContextStrokePath( m_cgContext
);
1731 void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath
&path
, int fillStyle
)
1733 if ( !m_brush
.IsNull() && ((wxMacCoreGraphicsBrushData
*)m_brush
.GetRefData())->IsShading() )
1735 // when using shading, we cannot draw pen and brush at the same time
1736 // revert to the base implementation of first filling and then stroking
1737 wxGraphicsContext::DrawPath( path
, fillStyle
);
1741 CGPathDrawingMode mode
= kCGPathFill
;
1742 if ( m_brush
.IsNull() )
1744 if ( m_pen
.IsNull() )
1747 mode
= kCGPathStroke
;
1751 if ( m_pen
.IsNull() )
1753 if ( fillStyle
== wxODDEVEN_RULE
)
1754 mode
= kCGPathEOFill
;
1760 if ( fillStyle
== wxODDEVEN_RULE
)
1761 mode
= kCGPathEOFillStroke
;
1763 mode
= kCGPathFillStroke
;
1769 if ( !m_brush
.IsNull() )
1770 ((wxMacCoreGraphicsBrushData
*)m_brush
.GetRefData())->Apply(this);
1771 if ( !m_pen
.IsNull() )
1772 ((wxMacCoreGraphicsPenData
*)m_pen
.GetRefData())->Apply(this);
1774 wxQuartzOffsetHelper
helper( m_cgContext
, ShouldOffset() );
1776 CGContextAddPath( m_cgContext
, (CGPathRef
) path
.GetNativePath() );
1777 CGContextDrawPath( m_cgContext
, mode
);
1780 void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath
&path
, int fillStyle
)
1782 if ( m_brush
.IsNull() )
1787 if ( ((wxMacCoreGraphicsBrushData
*)m_brush
.GetRefData())->IsShading() )
1789 CGContextSaveGState( m_cgContext
);
1790 CGContextAddPath( m_cgContext
, (CGPathRef
) path
.GetNativePath() );
1791 CGContextClip( m_cgContext
);
1792 CGContextDrawShading( m_cgContext
, ((wxMacCoreGraphicsBrushData
*)m_brush
.GetRefData())->GetShading() );
1793 CGContextRestoreGState( m_cgContext
);
1797 ((wxMacCoreGraphicsBrushData
*)m_brush
.GetRefData())->Apply(this);
1798 CGContextAddPath( m_cgContext
, (CGPathRef
) path
.GetNativePath() );
1799 if ( fillStyle
== wxODDEVEN_RULE
)
1800 CGContextEOFillPath( m_cgContext
);
1802 CGContextFillPath( m_cgContext
);
1806 void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg
)
1808 // we allow either setting or clearing but not replacing
1809 wxASSERT( m_cgContext
== NULL
|| cg
== NULL
);
1813 // TODO : when is this necessary - should we add a Flush() method ? CGContextSynchronize( m_cgContext );
1814 CGContextRestoreGState( m_cgContext
);
1815 CGContextRestoreGState( m_cgContext
);
1816 if ( m_releaseContext
)
1818 #if wxOSX_USE_CARBON
1819 QDEndCGContext( GetWindowPort( m_windowRef
) , &m_cgContext
);
1823 CGContextRelease(m_cgContext
);
1829 // FIXME: This check is needed because currently we need to use a DC/GraphicsContext
1830 // in order to get font properties, like wxFont::GetPixelSize, but since we don't have
1831 // a native window attached to use, I create a wxGraphicsContext with a NULL CGContextRef
1832 // for this one operation.
1834 // When wxFont::GetPixelSize on Mac no longer needs a graphics context, this check
1838 CGContextRetain(m_cgContext
);
1839 CGContextSaveGState( m_cgContext
);
1840 CGContextSetTextMatrix( m_cgContext
, CGAffineTransformIdentity
);
1841 CGContextSaveGState( m_cgContext
);
1842 m_releaseContext
= false;
1846 void wxMacCoreGraphicsContext::Translate( wxDouble dx
, wxDouble dy
)
1849 CGContextTranslateCTM( m_cgContext
, (CGFloat
) dx
, (CGFloat
) dy
);
1851 m_windowTransform
= CGAffineTransformTranslate(m_windowTransform
, (CGFloat
) dx
, (CGFloat
) dy
);
1854 void wxMacCoreGraphicsContext::Scale( wxDouble xScale
, wxDouble yScale
)
1857 CGContextScaleCTM( m_cgContext
, (CGFloat
) xScale
, (CGFloat
) yScale
);
1859 m_windowTransform
= CGAffineTransformScale(m_windowTransform
, (CGFloat
) xScale
, (CGFloat
) yScale
);
1862 void wxMacCoreGraphicsContext::Rotate( wxDouble angle
)
1865 CGContextRotateCTM( m_cgContext
, (CGFloat
) angle
);
1867 m_windowTransform
= CGAffineTransformRotate(m_windowTransform
, (CGFloat
) angle
);
1870 void wxMacCoreGraphicsContext::DrawBitmap( const wxBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1872 wxGraphicsBitmap bitmap
= GetRenderer()->CreateBitmap(bmp
);
1873 DrawBitmap(bitmap
, x
, y
, w
, h
);
1876 void wxMacCoreGraphicsContext::DrawBitmap( const wxGraphicsBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1880 wxMacCoreGraphicsBitmapData
* refdata
=static_cast<wxMacCoreGraphicsBitmapData
*>(bmp
.GetRefData());
1881 CGImageRef image
= refdata
->GetBitmap();
1882 CGRect r
= CGRectMake( (CGFloat
) x
, (CGFloat
) y
, (CGFloat
) w
, (CGFloat
) h
);
1883 if ( refdata
->IsMonochrome() == 1 )
1885 // is is a mask, the '1' in the mask tell where to draw the current brush
1886 if ( !m_brush
.IsNull() )
1888 if ( ((wxMacCoreGraphicsBrushData
*)m_brush
.GetRefData())->IsShading() )
1890 // TODO clip to mask
1892 CGContextSaveGState( m_cgContext );
1893 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
1894 CGContextClip( m_cgContext );
1895 CGContextDrawShading( m_cgContext, ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->GetShading() );
1896 CGContextRestoreGState( m_cgContext);
1901 ((wxMacCoreGraphicsBrushData
*)m_brush
.GetRefData())->Apply(this);
1902 wxMacDrawCGImage( m_cgContext
, &r
, image
);
1908 wxMacDrawCGImage( m_cgContext
, &r
, image
);
1913 void wxMacCoreGraphicsContext::DrawIcon( const wxIcon
&icon
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1917 CGRect r
= CGRectMake( (CGFloat
) 0.0 , (CGFloat
) 0.0 , (CGFloat
) w
, (CGFloat
) h
);
1918 CGContextSaveGState( m_cgContext
);
1919 CGContextTranslateCTM( m_cgContext
,(CGFloat
) x
,(CGFloat
) (y
+ h
) );
1920 CGContextScaleCTM( m_cgContext
, 1, -1 );
1921 #if wxOSX_USE_CARBON
1922 PlotIconRefInContext( m_cgContext
, &r
, kAlignNone
, kTransformNone
,
1923 NULL
, kPlotIconRefNormalFlags
, MAC_WXHICON( icon
.GetHICON() ) );
1925 CGContextRestoreGState( m_cgContext
);
1928 void wxMacCoreGraphicsContext::PushState()
1932 CGContextSaveGState( m_cgContext
);
1935 void wxMacCoreGraphicsContext::PopState()
1939 CGContextRestoreGState( m_cgContext
);
1942 void wxMacCoreGraphicsContext::DrawText( const wxString
&str
, wxDouble x
, wxDouble y
)
1944 wxCHECK_RET( !m_font
.IsNull(), wxT("wxMacCoreGraphicsContext::DrawText - no valid font set") );
1947 #if wxOSX_USE_CORE_TEXT
1948 if ( UMAGetSystemVersion() >= 0x1050 )
1950 wxMacCoreGraphicsFontData
* fref
= (wxMacCoreGraphicsFontData
*)m_font
.GetRefData();
1951 wxCFStringRef
text(str
, wxLocale::GetSystemEncoding() );
1952 CTFontRef font
= fref
->GetCTFont();
1953 CGColorRef col
= wxMacCreateCGColor( fref
->GetColour() );
1954 CTUnderlineStyle ustyle
= fref
->GetUnderlined() ? kCTUnderlineStyleSingle
: kCTUnderlineStyleNone
;
1955 wxCFRef
<CFNumberRef
> underlined( CFNumberCreate(NULL
, kCFNumberSInt32Type
, &ustyle
) );
1956 CFStringRef keys
[] = { kCTFontAttributeName
, kCTForegroundColorAttributeName
, kCTUnderlineStyleAttributeName
};
1957 CFTypeRef values
[] = { font
, col
, underlined
};
1958 wxCFRef
<CFDictionaryRef
> attributes( CFDictionaryCreate(kCFAllocatorDefault
, (const void**) &keys
, (const void**) &values
,
1959 WXSIZEOF( keys
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
) );
1960 wxCFRef
<CFAttributedStringRef
> attrtext( CFAttributedStringCreate(kCFAllocatorDefault
, text
, attributes
) );
1961 wxCFRef
<CTLineRef
> line( CTLineCreateWithAttributedString(attrtext
) );
1963 y
+= CTFontGetAscent(font
);
1965 CGContextSaveGState(m_cgContext
);
1966 CGContextTranslateCTM(m_cgContext
, x
, y
);
1967 CGContextScaleCTM(m_cgContext
, 1, -1);
1968 CGContextSetTextPosition(m_cgContext
, 0, 0);
1969 CTLineDraw( line
, m_cgContext
);
1970 CGContextRestoreGState(m_cgContext
);
1975 #if wxOSX_USE_ATSU_TEXT
1977 DrawText(str
, x
, y
, 0.0);
1981 #if wxOSX_USE_IPHONE
1982 wxMacCoreGraphicsFontData
* fref
= (wxMacCoreGraphicsFontData
*)m_font
.GetRefData();
1984 CGContextSaveGState(m_cgContext
);
1986 CGColorRef col
= wxMacCreateCGColor( fref
->GetColour() );
1987 CGContextSetTextDrawingMode (m_cgContext
, kCGTextFill
);
1988 CGContextSetFillColorWithColor( m_cgContext
, col
);
1990 wxCFStringRef
text(str
, wxLocale::GetSystemEncoding() );
1991 DrawTextInContext( m_cgContext
, CGPointMake( x
, y
), fref
->GetUIFont() , text
.AsNSString() );
1993 CGContextRestoreGState(m_cgContext
);
1998 void wxMacCoreGraphicsContext::DrawText( const wxString
&str
, wxDouble x
, wxDouble y
, wxDouble angle
)
2000 wxCHECK_RET( !m_font
.IsNull(), wxT("wxMacCoreGraphicsContext::DrawText - no valid font set") );
2003 #if wxOSX_USE_CORE_TEXT
2004 if ( UMAGetSystemVersion() >= 0x1050 )
2006 // default implementation takes care of rotation and calls non rotated DrawText afterwards
2007 wxGraphicsContext::DrawText( str
, x
, y
, angle
);
2011 #if wxOSX_USE_ATSU_TEXT
2013 OSStatus status
= noErr
;
2014 ATSUTextLayout atsuLayout
;
2015 wxMacUniCharBuffer
unibuf( str
);
2016 UniCharCount chars
= unibuf
.GetChars();
2018 ATSUStyle style
= (((wxMacCoreGraphicsFontData
*)m_font
.GetRefData())->GetATSUStyle());
2019 status
= ::ATSUCreateTextLayoutWithTextPtr( unibuf
.GetBuffer() , 0 , chars
, chars
, 1 ,
2020 &chars
, &style
, &atsuLayout
);
2022 wxASSERT_MSG( status
== noErr
, wxT("couldn't create the layout of the rotated text") );
2024 status
= ::ATSUSetTransientFontMatching( atsuLayout
, true );
2025 wxASSERT_MSG( status
== noErr
, wxT("couldn't setup transient font matching") );
2027 int iAngle
= int( angle
* RAD2DEG
);
2028 if ( abs(iAngle
) > 0 )
2030 Fixed atsuAngle
= IntToFixed( iAngle
);
2031 ATSUAttributeTag atsuTags
[] =
2033 kATSULineRotationTag
,
2035 ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
2039 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
2043 status
= ::ATSUSetLayoutControls(atsuLayout
, sizeof(atsuTags
) / sizeof(ATSUAttributeTag
),
2044 atsuTags
, atsuSizes
, atsuValues
);
2048 ATSUAttributeTag atsuTags
[] =
2052 ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
2054 sizeof( CGContextRef
) ,
2056 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
2060 status
= ::ATSUSetLayoutControls(atsuLayout
, sizeof(atsuTags
) / sizeof(ATSUAttributeTag
),
2061 atsuTags
, atsuSizes
, atsuValues
);
2064 ATSUTextMeasurement textBefore
, textAfter
;
2065 ATSUTextMeasurement ascent
, descent
;
2067 status
= ::ATSUGetUnjustifiedBounds( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
2068 &textBefore
, &textAfter
, &ascent
, &descent
);
2070 wxASSERT_MSG( status
== noErr
, wxT("couldn't measure the rotated text") );
2073 x
+= (int)(sin(angle
) * FixedToInt(ascent
));
2074 y
+= (int)(cos(angle
) * FixedToInt(ascent
));
2076 status
= ::ATSUMeasureTextImage( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
2077 IntToFixed(x
) , IntToFixed(y
) , &rect
);
2078 wxASSERT_MSG( status
== noErr
, wxT("couldn't measure the rotated text") );
2080 CGContextSaveGState(m_cgContext
);
2081 CGContextTranslateCTM(m_cgContext
, (CGFloat
) x
, (CGFloat
) y
);
2082 CGContextScaleCTM(m_cgContext
, 1, -1);
2083 status
= ::ATSUDrawText( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
2084 IntToFixed(0) , IntToFixed(0) );
2086 wxASSERT_MSG( status
== noErr
, wxT("couldn't draw the rotated text") );
2088 CGContextRestoreGState(m_cgContext
);
2090 ::ATSUDisposeTextLayout(atsuLayout
);
2095 #if wxOSX_USE_IPHONE
2096 // default implementation takes care of rotation and calls non rotated DrawText afterwards
2097 wxGraphicsContext::DrawText( str
, x
, y
, angle
);
2101 void wxMacCoreGraphicsContext::GetTextExtent( const wxString
&str
, wxDouble
*width
, wxDouble
*height
,
2102 wxDouble
*descent
, wxDouble
*externalLeading
) const
2104 wxCHECK_RET( !m_font
.IsNull(), wxT("wxMacCoreGraphicsContext::GetTextExtent - no valid font set") );
2112 if ( externalLeading
)
2113 *externalLeading
= 0;
2118 #if wxOSX_USE_CORE_TEXT
2119 if ( UMAGetSystemVersion() >= 0x1050 )
2121 wxMacCoreGraphicsFontData
* fref
= (wxMacCoreGraphicsFontData
*)m_font
.GetRefData();
2122 CTFontRef font
= fref
->GetCTFont();
2124 wxCFStringRef
text(str
, wxLocale::GetSystemEncoding() );
2125 CFStringRef keys
[] = { kCTFontAttributeName
};
2126 CFTypeRef values
[] = { font
};
2127 wxCFRef
<CFDictionaryRef
> attributes( CFDictionaryCreate(kCFAllocatorDefault
, (const void**) &keys
, (const void**) &values
,
2128 WXSIZEOF( keys
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
) );
2129 wxCFRef
<CFAttributedStringRef
> attrtext( CFAttributedStringCreate(kCFAllocatorDefault
, text
, attributes
) );
2130 wxCFRef
<CTLineRef
> line( CTLineCreateWithAttributedString(attrtext
) );
2134 w
= CTLineGetTypographicBounds(line
, &a
, &d
, &l
) ;
2140 if ( externalLeading
)
2141 *externalLeading
= l
;
2147 #if wxOSX_USE_ATSU_TEXT
2149 OSStatus status
= noErr
;
2151 ATSUTextLayout atsuLayout
;
2152 wxMacUniCharBuffer
unibuf( str
);
2153 UniCharCount chars
= unibuf
.GetChars();
2155 ATSUStyle style
= (((wxMacCoreGraphicsFontData
*)m_font
.GetRefData())->GetATSUStyle());
2156 status
= ::ATSUCreateTextLayoutWithTextPtr( unibuf
.GetBuffer() , 0 , chars
, chars
, 1 ,
2157 &chars
, &style
, &atsuLayout
);
2159 wxASSERT_MSG( status
== noErr
, wxT("couldn't create the layout of the text") );
2161 status
= ::ATSUSetTransientFontMatching( atsuLayout
, true );
2162 wxASSERT_MSG( status
== noErr
, wxT("couldn't setup transient font matching") );
2164 ATSUTextMeasurement textBefore
, textAfter
;
2165 ATSUTextMeasurement textAscent
, textDescent
;
2167 status
= ::ATSUGetUnjustifiedBounds( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
2168 &textBefore
, &textAfter
, &textAscent
, &textDescent
);
2171 *height
= FixedToInt(textAscent
+ textDescent
);
2173 *descent
= FixedToInt(textDescent
);
2174 if ( externalLeading
)
2175 *externalLeading
= 0;
2177 *width
= FixedToInt(textAfter
- textBefore
);
2179 ::ATSUDisposeTextLayout(atsuLayout
);
2184 #if wxOSX_USE_IPHONE
2185 wxMacCoreGraphicsFontData
* fref
= (wxMacCoreGraphicsFontData
*)m_font
.GetRefData();
2187 wxCFStringRef
text(str
, wxLocale::GetSystemEncoding() );
2188 CGSize sz
= MeasureTextInContext( fref
->GetUIFont() , text
.AsNSString() );
2191 *height
= sz
.height
;
2194 *descent = FixedToInt(textDescent);
2195 if ( externalLeading )
2196 *externalLeading = 0;
2203 void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString
& text
, wxArrayDouble
& widths
) const
2206 widths
.Add(0, text
.length());
2208 wxCHECK_RET( !m_font
.IsNull(), wxT("wxMacCoreGraphicsContext::DrawText - no valid font set") );
2213 #if wxOSX_USE_CORE_TEXT
2215 wxMacCoreGraphicsFontData
* fref
= (wxMacCoreGraphicsFontData
*)m_font
.GetRefData();
2216 CTFontRef font
= fref
->GetCTFont();
2218 wxCFStringRef
t(text
, wxLocale::GetSystemEncoding() );
2219 CFStringRef keys
[] = { kCTFontAttributeName
};
2220 CFTypeRef values
[] = { font
};
2221 wxCFRef
<CFDictionaryRef
> attributes( CFDictionaryCreate(kCFAllocatorDefault
, (const void**) &keys
, (const void**) &values
,
2222 WXSIZEOF( keys
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
) );
2223 wxCFRef
<CFAttributedStringRef
> attrtext( CFAttributedStringCreate(kCFAllocatorDefault
, t
, attributes
) );
2224 wxCFRef
<CTLineRef
> line( CTLineCreateWithAttributedString(attrtext
) );
2226 int chars
= text
.length();
2227 for ( int pos
= 0; pos
< (int)chars
; pos
++ )
2229 widths
[pos
] = CTLineGetOffsetForStringIndex( line
, pos
+1 , NULL
)+0.5;
2235 #if wxOSX_USE_ATSU_TEXT
2237 OSStatus status
= noErr
;
2238 ATSUTextLayout atsuLayout
;
2239 wxMacUniCharBuffer
unibuf( text
);
2240 UniCharCount chars
= unibuf
.GetChars();
2242 ATSUStyle style
= (((wxMacCoreGraphicsFontData
*)m_font
.GetRefData())->GetATSUStyle());
2243 status
= ::ATSUCreateTextLayoutWithTextPtr( unibuf
.GetBuffer() , 0 , chars
, chars
, 1 ,
2244 &chars
, &style
, &atsuLayout
);
2246 wxASSERT_MSG( status
== noErr
, wxT("couldn't create the layout of the text") );
2248 status
= ::ATSUSetTransientFontMatching( atsuLayout
, true );
2249 wxASSERT_MSG( status
== noErr
, wxT("couldn't setup transient font matching") );
2251 // new implementation from JS, keep old one just in case
2253 for ( int pos
= 0; pos
< (int)chars
; pos
++ )
2255 unsigned long actualNumberOfBounds
= 0;
2256 ATSTrapezoid glyphBounds
;
2258 // We get a single bound, since the text should only require one. If it requires more, there is an issue
2260 result
= ATSUGetGlyphBounds( atsuLayout
, 0, 0, kATSUFromTextBeginning
, pos
+ 1,
2261 kATSUseDeviceOrigins
, 1, &glyphBounds
, &actualNumberOfBounds
);
2262 if (result
!= noErr
|| actualNumberOfBounds
!= 1 )
2265 widths
[pos
] = FixedToInt( glyphBounds
.upperRight
.x
- glyphBounds
.upperLeft
.x
);
2266 //unsigned char uch = s[i];
2269 ATSLayoutRecord
*layoutRecords
= NULL
;
2270 ItemCount glyphCount
= 0;
2272 // Get the glyph extents
2273 OSStatus err
= ::ATSUDirectGetLayoutDataArrayPtrFromTextLayout(atsuLayout
,
2275 kATSUDirectDataLayoutRecordATSLayoutRecordCurrent
,
2279 wxASSERT(glyphCount
== (text
.length()+1));
2281 if ( err
== noErr
&& glyphCount
== (text
.length()+1))
2283 for ( int pos
= 1; pos
< (int)glyphCount
; pos
++ )
2285 widths
[pos
-1] = FixedToInt( layoutRecords
[pos
].realPos
);
2289 ::ATSUDirectReleaseLayoutDataArrayPtr(NULL
,
2290 kATSUDirectDataLayoutRecordATSLayoutRecordCurrent
,
2291 (void **) &layoutRecords
);
2293 ::ATSUDisposeTextLayout(atsuLayout
);
2296 #if wxOSX_USE_IPHONE
2297 // TODO core graphics text implementation here
2301 void * wxMacCoreGraphicsContext::GetNativeContext()
2306 // concatenates this transform with the current transform of this context
2307 void wxMacCoreGraphicsContext::ConcatTransform( const wxGraphicsMatrix
& matrix
)
2310 CGContextConcatCTM( m_cgContext
, *(CGAffineTransform
*) matrix
.GetNativeMatrix());
2312 m_windowTransform
= CGAffineTransformConcat(m_windowTransform
, *(CGAffineTransform
*) matrix
.GetNativeMatrix());
2315 // sets the transform of this context
2316 void wxMacCoreGraphicsContext::SetTransform( const wxGraphicsMatrix
& matrix
)
2320 CGAffineTransform transform
= CGContextGetCTM( m_cgContext
);
2321 transform
= CGAffineTransformInvert( transform
) ;
2322 CGContextConcatCTM( m_cgContext
, transform
);
2323 CGContextConcatCTM( m_cgContext
, *(CGAffineTransform
*) matrix
.GetNativeMatrix());
2327 m_windowTransform
= *(CGAffineTransform
*) matrix
.GetNativeMatrix();
2331 // gets the matrix of this context
2332 wxGraphicsMatrix
wxMacCoreGraphicsContext::GetTransform() const
2334 wxGraphicsMatrix m
= CreateMatrix();
2335 *((CGAffineTransform
*) m
.GetNativeMatrix()) = ( m_cgContext
== NULL
? m_windowTransform
:
2336 CGContextGetCTM( m_cgContext
));
2344 //-----------------------------------------------------------------------------
2345 // wxMacCoreGraphicsRenderer declaration
2346 //-----------------------------------------------------------------------------
2348 class WXDLLIMPEXP_CORE wxMacCoreGraphicsRenderer
: public wxGraphicsRenderer
2351 wxMacCoreGraphicsRenderer() {}
2353 virtual ~wxMacCoreGraphicsRenderer() {}
2357 virtual wxGraphicsContext
* CreateContext( const wxWindowDC
& dc
);
2358 virtual wxGraphicsContext
* CreateContext( const wxMemoryDC
& dc
);
2359 #if wxUSE_PRINTING_ARCHITECTURE
2360 virtual wxGraphicsContext
* CreateContext( const wxPrinterDC
& dc
);
2363 virtual wxGraphicsContext
* CreateContextFromNativeContext( void * context
);
2365 virtual wxGraphicsContext
* CreateContextFromNativeWindow( void * window
);
2367 virtual wxGraphicsContext
* CreateContext( wxWindow
* window
);
2369 virtual wxGraphicsContext
* CreateMeasuringContext();
2373 virtual wxGraphicsPath
CreatePath();
2377 virtual wxGraphicsMatrix
CreateMatrix( wxDouble a
=1.0, wxDouble b
=0.0, wxDouble c
=0.0, wxDouble d
=1.0,
2378 wxDouble tx
=0.0, wxDouble ty
=0.0);
2381 virtual wxGraphicsPen
CreatePen(const wxPen
& pen
) ;
2383 virtual wxGraphicsBrush
CreateBrush(const wxBrush
& brush
) ;
2385 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
2386 virtual wxGraphicsBrush
CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
2387 const wxColour
&c1
, const wxColour
&c2
) ;
2389 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
2390 // with radius r and color cColor
2391 virtual wxGraphicsBrush
CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
2392 const wxColour
&oColor
, const wxColour
&cColor
) ;
2395 virtual wxGraphicsFont
CreateFont( const wxFont
&font
, const wxColour
&col
= *wxBLACK
) ;
2397 // create a native bitmap representation
2398 virtual wxGraphicsBitmap
CreateBitmap( const wxBitmap
&bitmap
) ;
2400 // create a native bitmap representation
2401 virtual wxGraphicsBitmap
CreateSubBitmap( const wxGraphicsBitmap
&bitmap
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
) ;
2403 DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacCoreGraphicsRenderer
)
2406 //-----------------------------------------------------------------------------
2407 // wxMacCoreGraphicsRenderer implementation
2408 //-----------------------------------------------------------------------------
2410 IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsRenderer
,wxGraphicsRenderer
)
2412 static wxMacCoreGraphicsRenderer gs_MacCoreGraphicsRenderer
;
2414 wxGraphicsRenderer
* wxGraphicsRenderer::GetDefaultRenderer()
2416 return &gs_MacCoreGraphicsRenderer
;
2419 #if defined( __WXCOCOA__ ) || wxOSX_USE_COCOA
2420 extern CGContextRef
wxMacGetContextFromCurrentNSContext() ;
2423 wxGraphicsContext
* wxMacCoreGraphicsRenderer::CreateContext( const wxWindowDC
& dc
)
2425 const wxDCImpl
* impl
= dc
.GetImpl();
2426 wxWindowDCImpl
*win_impl
= wxDynamicCast( impl
, wxWindowDCImpl
);
2430 win_impl
->GetSize( &w
, &h
);
2431 CGContextRef cgctx
= 0;
2433 cgctx
= (CGContextRef
)(win_impl
->GetWindow()->MacGetCGContextRef());
2435 cgctx
= wxMacGetContextFromCurrentNSContext() ;
2437 return new wxMacCoreGraphicsContext( this, cgctx
, (wxDouble
) w
, (wxDouble
) h
);
2442 wxGraphicsContext
* wxMacCoreGraphicsRenderer::CreateContext( const wxMemoryDC
& dc
)
2445 const wxDCImpl
* impl
= dc
.GetImpl();
2446 wxMemoryDCImpl
*mem_impl
= wxDynamicCast( impl
, wxMemoryDCImpl
);
2450 mem_impl
->GetSize( &w
, &h
);
2451 return new wxMacCoreGraphicsContext( this,
2452 (CGContextRef
)(mem_impl
->GetGraphicsContext()->GetNativeContext()), (wxDouble
) w
, (wxDouble
) h
);
2458 #if wxUSE_PRINTING_ARCHITECTURE
2459 wxGraphicsContext
* wxMacCoreGraphicsRenderer::CreateContext( const wxPrinterDC
& dc
)
2462 const wxDCImpl
* impl
= dc
.GetImpl();
2463 wxPrinterDCImpl
*print_impl
= wxDynamicCast( impl
, wxPrinterDCImpl
);
2467 print_impl
->GetSize( &w
, &h
);
2468 return new wxMacCoreGraphicsContext( this,
2469 (CGContextRef
)(print_impl
->GetGraphicsContext()->GetNativeContext()), (wxDouble
) w
, (wxDouble
) h
);
2476 wxGraphicsContext
* wxMacCoreGraphicsRenderer::CreateContextFromNativeContext( void * context
)
2478 return new wxMacCoreGraphicsContext(this,(CGContextRef
)context
);
2481 wxGraphicsContext
* wxMacCoreGraphicsRenderer::CreateContextFromNativeWindow( void * window
)
2483 #if wxOSX_USE_CARBON
2484 return new wxMacCoreGraphicsContext(this,(WindowRef
)window
);
2490 wxGraphicsContext
* wxMacCoreGraphicsRenderer::CreateContext( wxWindow
* window
)
2492 return new wxMacCoreGraphicsContext(this, window
);
2495 wxGraphicsContext
* wxMacCoreGraphicsRenderer::CreateMeasuringContext()
2497 return new wxMacCoreGraphicsContext(this);
2502 wxGraphicsPath
wxMacCoreGraphicsRenderer::CreatePath()
2505 m
.SetRefData( new wxMacCoreGraphicsPathData(this));
2512 wxGraphicsMatrix
wxMacCoreGraphicsRenderer::CreateMatrix( wxDouble a
, wxDouble b
, wxDouble c
, wxDouble d
,
2513 wxDouble tx
, wxDouble ty
)
2516 wxMacCoreGraphicsMatrixData
* data
= new wxMacCoreGraphicsMatrixData( this );
2517 data
->Set( a
,b
,c
,d
,tx
,ty
) ;
2522 wxGraphicsPen
wxMacCoreGraphicsRenderer::CreatePen(const wxPen
& pen
)
2524 if ( !pen
.Ok() || pen
.GetStyle() == wxTRANSPARENT
)
2525 return wxNullGraphicsPen
;
2529 p
.SetRefData(new wxMacCoreGraphicsPenData( this, pen
));
2534 wxGraphicsBrush
wxMacCoreGraphicsRenderer::CreateBrush(const wxBrush
& brush
)
2536 if ( !brush
.Ok() || brush
.GetStyle() == wxTRANSPARENT
)
2537 return wxNullGraphicsBrush
;
2541 p
.SetRefData(new wxMacCoreGraphicsBrushData( this, brush
));
2546 wxGraphicsBitmap
wxMacCoreGraphicsRenderer::CreateBitmap( const wxBitmap
& bmp
)
2552 p
.SetRefData(new wxMacCoreGraphicsBitmapData( this , bmp
.CreateCGImage(), bmp
.GetDepth() == 1 ) );
2557 return wxNullGraphicsBitmap
;
2560 wxGraphicsBitmap
wxMacCoreGraphicsRenderer::CreateSubBitmap( const wxGraphicsBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
2562 wxMacCoreGraphicsBitmapData
* refdata
=static_cast<wxMacCoreGraphicsBitmapData
*>(bmp
.GetRefData());
2563 CGImageRef img
= refdata
->GetBitmap();
2567 CGImageRef subimg
= CGImageCreateWithImageInRect(img
,CGRectMake( (CGFloat
) x
, (CGFloat
) y
, (CGFloat
) w
, (CGFloat
) h
));
2568 p
.SetRefData(new wxMacCoreGraphicsBitmapData( this , subimg
, refdata
->IsMonochrome() ) );
2572 return wxNullGraphicsBitmap
;
2575 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
2576 wxGraphicsBrush
wxMacCoreGraphicsRenderer::CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
2577 const wxColour
&c1
, const wxColour
&c2
)
2580 wxMacCoreGraphicsBrushData
* d
= new wxMacCoreGraphicsBrushData( this );
2581 d
->CreateLinearGradientBrush(x1
, y1
, x2
, y2
, c1
, c2
);
2586 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
2587 // with radius r and color cColor
2588 wxGraphicsBrush
wxMacCoreGraphicsRenderer::CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
2589 const wxColour
&oColor
, const wxColour
&cColor
)
2592 wxMacCoreGraphicsBrushData
* d
= new wxMacCoreGraphicsBrushData( this );
2593 d
->CreateRadialGradientBrush(xo
,yo
,xc
,yc
,radius
,oColor
,cColor
);
2599 wxGraphicsFont
wxMacCoreGraphicsRenderer::CreateFont( const wxFont
&font
, const wxColour
&col
)
2604 p
.SetRefData(new wxMacCoreGraphicsFontData( this , font
, col
));
2608 return wxNullGraphicsFont
;
2612 // CoreGraphics Helper Methods
2615 // Data Providers and Consumers
2617 size_t UMAPutBytesCFRefCallback( void *info
, const void *bytes
, size_t count
)
2619 CFMutableDataRef data
= (CFMutableDataRef
) info
;
2622 CFDataAppendBytes( data
, (const UInt8
*) bytes
, count
);
2627 void wxMacReleaseCFDataProviderCallback(void *info
,
2628 const void *WXUNUSED(data
),
2629 size_t WXUNUSED(count
))
2632 CFRelease( (CFDataRef
) info
);
2635 void wxMacReleaseCFDataConsumerCallback( void *info
)
2638 CFRelease( (CFDataRef
) info
);
2641 CGDataProviderRef
wxMacCGDataProviderCreateWithCFData( CFDataRef data
)
2646 return CGDataProviderCreateWithCFData( data
);
2649 CGDataConsumerRef
wxMacCGDataConsumerCreateWithCFData( CFMutableDataRef data
)
2654 return CGDataConsumerCreateWithCFData( data
);
2658 wxMacReleaseMemoryBufferProviderCallback(void *info
,
2659 const void * WXUNUSED_UNLESS_DEBUG(data
),
2660 size_t WXUNUSED(size
))
2662 wxMemoryBuffer
* membuf
= (wxMemoryBuffer
*) info
;
2664 wxASSERT( data
== membuf
->GetData() ) ;
2669 CGDataProviderRef
wxMacCGDataProviderCreateWithMemoryBuffer( const wxMemoryBuffer
& buf
)
2671 wxMemoryBuffer
* b
= new wxMemoryBuffer( buf
);
2672 if ( b
->GetDataLen() == 0 )
2675 return CGDataProviderCreateWithData( b
, (const void *) b
->GetData() , b
->GetDataLen() ,
2676 wxMacReleaseMemoryBufferProviderCallback
);