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/uma.h"
39 #include "wx/osx/dcprint.h"
41 #include "CoreServices/CoreServices.h"
42 #include "ApplicationServices/ApplicationServices.h"
43 #include "wx/osx/core/cfstring.h"
44 #include "wx/cocoa/dcclient.h"
49 CGColorSpaceRef
wxMacGetGenericRGBColorSpace()
51 static wxCFRef
<CGColorSpaceRef
> genericRGBColorSpace
;
53 if (genericRGBColorSpace
== NULL
)
55 genericRGBColorSpace
.reset( CGColorSpaceCreateWithName( kCGColorSpaceGenericRGB
) );
58 return genericRGBColorSpace
;
61 int UMAGetSystemVersion()
67 #define wxMAC_USE_CORE_TEXT 1
71 //-----------------------------------------------------------------------------
73 //-----------------------------------------------------------------------------
75 #if !defined( __DARWIN__ ) || defined(__MWERKS__)
77 const double M_PI
= 3.14159265358979;
81 static const double RAD2DEG
= 180.0 / M_PI
;
84 // Pen, Brushes and Fonts
88 #pragma mark wxMacCoreGraphicsPattern, ImagePattern, HatchPattern classes
90 OSStatus
wxMacDrawCGImage(
91 CGContextRef inContext
,
92 const CGRect
* inBounds
,
95 #if defined( __LP64__ ) || defined(__WXCOCOA__)
97 CGContextDrawImage(inContext
, *inBounds
, inImage
);
100 return HIViewDrawCGImage( inContext
, inBounds
, inImage
);
104 CGColorRef
wxMacCreateCGColor( const wxColour
& col
)
106 CGColorRef retval
= 0;
108 retval
= col
.CreateCGColor();
110 // TODO add conversion NSColor - CGColorRef (obj-c)
111 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
112 if ( CGColorCreateGenericRGB
)
113 retval
= CGColorCreateGenericRGB( col
.Red() / 255.0 , col
.Green() / 255.0, col
.Blue() / 255.0, col
.Alpha() / 255.0 );
117 CGFloat components
[4] = { col
.Red() / 255.0, col
.Green() / 255.0, col
.Blue() / 255.0, col
.Alpha() / 255.0 } ;
118 retval
= CGColorCreate( wxMacGetGenericRGBColorSpace() , components
) ;
125 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && defined(wxMAC_USE_CORE_TEXT)
127 CTFontRef
wxMacCreateCTFont( const wxFont
& font
)
130 return wxCFRetain((CTFontRef
) font
.MacGetCTFont());
132 return CTFontCreateWithName( wxCFStringRef( font
.GetFaceName(), wxLocale::GetSystemEncoding() ) , font
.GetPointSize() , NULL
);
138 // CGPattern wrapper class: always allocate on heap, never call destructor
140 class wxMacCoreGraphicsPattern
143 wxMacCoreGraphicsPattern() {}
145 // is guaranteed to be called only with a non-Null CGContextRef
146 virtual void Render( CGContextRef ctxRef
) = 0;
148 operator CGPatternRef() const { return m_patternRef
; }
151 virtual ~wxMacCoreGraphicsPattern()
153 // as this is called only when the m_patternRef is been released;
154 // don't release it again
157 static void _Render( void *info
, CGContextRef ctxRef
)
159 wxMacCoreGraphicsPattern
* self
= (wxMacCoreGraphicsPattern
*) info
;
160 if ( self
&& ctxRef
)
161 self
->Render( ctxRef
);
164 static void _Dispose( void *info
)
166 wxMacCoreGraphicsPattern
* self
= (wxMacCoreGraphicsPattern
*) info
;
170 CGPatternRef m_patternRef
;
172 static const CGPatternCallbacks ms_Callbacks
;
175 const CGPatternCallbacks
wxMacCoreGraphicsPattern::ms_Callbacks
= { 0, &wxMacCoreGraphicsPattern::_Render
, &wxMacCoreGraphicsPattern::_Dispose
};
177 class ImagePattern
: public wxMacCoreGraphicsPattern
180 ImagePattern( const wxBitmap
* bmp
, const CGAffineTransform
& transform
)
182 wxASSERT( bmp
&& bmp
->Ok() );
184 Init( (CGImageRef
) bmp
->CreateCGImage() , transform
);
188 // ImagePattern takes ownership of CGImageRef passed in
189 ImagePattern( CGImageRef image
, const CGAffineTransform
& transform
)
194 Init( image
, transform
);
197 virtual void Render( CGContextRef ctxRef
)
200 wxMacDrawCGImage( ctxRef
, &m_imageBounds
, m_image
);
204 void Init( CGImageRef image
, const CGAffineTransform
& transform
)
209 m_imageBounds
= CGRectMake( (CGFloat
) 0.0, (CGFloat
) 0.0, (CGFloat
)CGImageGetWidth( m_image
), (CGFloat
)CGImageGetHeight( m_image
) );
210 m_patternRef
= CGPatternCreate(
211 this , m_imageBounds
, transform
,
212 m_imageBounds
.size
.width
, m_imageBounds
.size
.height
,
213 kCGPatternTilingNoDistortion
, true , &wxMacCoreGraphicsPattern::ms_Callbacks
);
217 virtual ~ImagePattern()
220 CGImageRelease( m_image
);
224 CGRect m_imageBounds
;
227 class HatchPattern
: public wxMacCoreGraphicsPattern
230 HatchPattern( int hatchstyle
, const CGAffineTransform
& transform
)
232 m_hatch
= hatchstyle
;
233 m_imageBounds
= CGRectMake( (CGFloat
) 0.0, (CGFloat
) 0.0, (CGFloat
) 8.0 , (CGFloat
) 8.0 );
234 m_patternRef
= CGPatternCreate(
235 this , m_imageBounds
, transform
,
236 m_imageBounds
.size
.width
, m_imageBounds
.size
.height
,
237 kCGPatternTilingNoDistortion
, false , &wxMacCoreGraphicsPattern::ms_Callbacks
);
240 void StrokeLineSegments( CGContextRef ctxRef
, const CGPoint pts
[] , size_t count
)
242 CGContextStrokeLineSegments( ctxRef
, pts
, count
);
245 virtual void Render( CGContextRef ctxRef
)
249 case wxBDIAGONAL_HATCH
:
253 { (CGFloat
) 8.0 , (CGFloat
) 0.0 } , { (CGFloat
) 0.0 , (CGFloat
) 8.0 }
255 StrokeLineSegments( ctxRef
, pts
, 2 );
259 case wxCROSSDIAG_HATCH
:
263 { (CGFloat
) 0.0 , (CGFloat
) 0.0 } , { (CGFloat
) 8.0 , (CGFloat
) 8.0 } ,
264 { (CGFloat
) 8.0 , (CGFloat
) 0.0 } , { (CGFloat
) 0.0 , (CGFloat
) 8.0 }
266 StrokeLineSegments( ctxRef
, pts
, 4 );
270 case wxFDIAGONAL_HATCH
:
274 { (CGFloat
) 0.0 , (CGFloat
) 0.0 } , { (CGFloat
) 8.0 , (CGFloat
) 8.0 }
276 StrokeLineSegments( ctxRef
, pts
, 2 );
284 { (CGFloat
) 0.0 , (CGFloat
) 4.0 } , { (CGFloat
) 8.0 , (CGFloat
) 4.0 } ,
285 { (CGFloat
) 4.0 , (CGFloat
) 0.0 } , { (CGFloat
) 4.0 , (CGFloat
) 8.0 } ,
287 StrokeLineSegments( ctxRef
, pts
, 4 );
291 case wxHORIZONTAL_HATCH
:
295 { (CGFloat
) 0.0 , (CGFloat
) 4.0 } , { (CGFloat
) 8.0 , (CGFloat
) 4.0 } ,
297 StrokeLineSegments( ctxRef
, pts
, 2 );
301 case wxVERTICAL_HATCH
:
305 { (CGFloat
) 4.0 , (CGFloat
) 0.0 } , { (CGFloat
) 4.0 , (CGFloat
) 8.0 } ,
307 StrokeLineSegments( ctxRef
, pts
, 2 );
317 virtual ~HatchPattern() {}
319 CGRect m_imageBounds
;
323 class wxMacCoreGraphicsPenData
: public wxGraphicsObjectRefData
326 wxMacCoreGraphicsPenData( wxGraphicsRenderer
* renderer
, const wxPen
&pen
);
327 ~wxMacCoreGraphicsPenData();
330 virtual void Apply( wxGraphicsContext
* context
);
331 virtual wxDouble
GetWidth() { return m_width
; }
335 wxCFRef
<CGColorRef
> m_color
;
336 wxCFRef
<CGColorSpaceRef
> m_colorSpace
;
342 const CGFloat
*m_lengths
;
343 CGFloat
*m_userLengths
;
347 wxCFRef
<CGPatternRef
> m_pattern
;
348 CGFloat
* m_patternColorComponents
;
351 wxMacCoreGraphicsPenData::wxMacCoreGraphicsPenData( wxGraphicsRenderer
* renderer
, const wxPen
&pen
) :
352 wxGraphicsObjectRefData( renderer
)
356 m_color
.reset( wxMacCreateCGColor( pen
.GetColour() ) ) ;
358 // TODO: * m_dc->m_scaleX
359 m_width
= pen
.GetWidth();
361 m_width
= (CGFloat
) 0.1;
363 switch ( pen
.GetCap() )
366 m_cap
= kCGLineCapRound
;
369 case wxCAP_PROJECTING
:
370 m_cap
= kCGLineCapSquare
;
374 m_cap
= kCGLineCapButt
;
378 m_cap
= kCGLineCapButt
;
382 switch ( pen
.GetJoin() )
385 m_join
= kCGLineJoinBevel
;
389 m_join
= kCGLineJoinMiter
;
393 m_join
= kCGLineJoinRound
;
397 m_join
= kCGLineJoinMiter
;
401 const CGFloat dashUnit
= m_width
< 1.0 ? (CGFloat
) 1.0 : m_width
;
403 const CGFloat dotted
[] = { (CGFloat
) dashUnit
, (CGFloat
) (dashUnit
+ 2.0) };
404 static const CGFloat short_dashed
[] = { (CGFloat
) 9.0 , (CGFloat
) 6.0 };
405 static const CGFloat dashed
[] = { (CGFloat
) 19.0 , (CGFloat
) 9.0 };
406 static const CGFloat dotted_dashed
[] = { (CGFloat
) 9.0 , (CGFloat
) 6.0 , (CGFloat
) 3.0 , (CGFloat
) 3.0 };
408 switch ( pen
.GetStyle() )
414 m_count
= WXSIZEOF(dotted
);
415 m_userLengths
= new CGFloat
[ m_count
] ;
416 memcpy( m_userLengths
, dotted
, sizeof(dotted
) );
417 m_lengths
= m_userLengths
;
421 m_count
= WXSIZEOF(dashed
);
426 m_count
= WXSIZEOF(short_dashed
);
427 m_lengths
= short_dashed
;
431 m_count
= WXSIZEOF(dotted_dashed
);
432 m_lengths
= dotted_dashed
;
437 m_count
= pen
.GetDashes( &dashes
);
438 if ((dashes
!= NULL
) && (m_count
> 0))
440 m_userLengths
= new CGFloat
[m_count
];
441 for ( int i
= 0; i
< m_count
; ++i
)
443 m_userLengths
[i
] = dashes
[i
] * dashUnit
;
445 if ( i
% 2 == 1 && m_userLengths
[i
] < dashUnit
+ 2.0 )
446 m_userLengths
[i
] = (CGFloat
) (dashUnit
+ 2.0);
447 else if ( i
% 2 == 0 && m_userLengths
[i
] < dashUnit
)
448 m_userLengths
[i
] = dashUnit
;
451 m_lengths
= m_userLengths
;
456 wxBitmap
* bmp
= pen
.GetStipple();
457 if ( bmp
&& bmp
->Ok() )
459 m_colorSpace
.reset( CGColorSpaceCreatePattern( NULL
) );
460 m_pattern
.reset( (CGPatternRef
) *( new ImagePattern( bmp
, CGAffineTransformMakeScale( 1,-1 ) ) ) );
461 m_patternColorComponents
= new CGFloat
[1] ;
462 m_patternColorComponents
[0] = (CGFloat
) 1.0;
471 m_colorSpace
.reset( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
472 m_pattern
.reset( (CGPatternRef
) *( new HatchPattern( pen
.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) );
473 m_patternColorComponents
= new CGFloat
[4] ;
474 m_patternColorComponents
[0] = (CGFloat
) (pen
.GetColour().Red() / 255.0);
475 m_patternColorComponents
[1] = (CGFloat
) (pen
.GetColour().Green() / 255.0);
476 m_patternColorComponents
[2] = (CGFloat
) (pen
.GetColour().Blue() / 255.0);
477 m_patternColorComponents
[3] = (CGFloat
) (pen
.GetColour().Alpha() / 255.0);
481 if ((m_lengths
!= NULL
) && (m_count
> 0))
483 // force the line cap, otherwise we get artifacts (overlaps) and just solid lines
484 m_cap
= kCGLineCapButt
;
488 wxMacCoreGraphicsPenData::~wxMacCoreGraphicsPenData()
490 delete[] m_userLengths
;
491 delete[] m_patternColorComponents
;
494 void wxMacCoreGraphicsPenData::Init()
497 m_userLengths
= NULL
;
500 m_patternColorComponents
= NULL
;
504 void wxMacCoreGraphicsPenData::Apply( wxGraphicsContext
* context
)
506 CGContextRef cg
= (CGContextRef
) context
->GetNativeContext();
507 CGContextSetLineWidth( cg
, m_width
);
508 CGContextSetLineJoin( cg
, m_join
);
510 CGContextSetLineDash( cg
, 0 , m_lengths
, m_count
);
511 CGContextSetLineCap( cg
, m_cap
);
515 CGAffineTransform matrix
= CGContextGetCTM( cg
);
516 CGContextSetPatternPhase( cg
, CGSizeMake(matrix
.tx
, matrix
.ty
) );
517 CGContextSetStrokeColorSpace( cg
, m_colorSpace
);
518 CGContextSetStrokePattern( cg
, m_pattern
, m_patternColorComponents
);
522 if ( context
->GetLogicalFunction() == wxINVERT
|| context
->GetLogicalFunction() == wxXOR
)
524 CGContextSetRGBStrokeColor( cg
, (CGFloat
) 1.0,(CGFloat
) 1.0 , (CGFloat
) 1.0, (CGFloat
) 1.0 );
527 CGContextSetStrokeColorWithColor( cg
, m_color
);
535 static const char *gs_stripedback_xpm
[] = {
536 /* columns rows colors chars-per-pixel */
547 wxBitmap
gs_stripedback_bmp( wxImage( (const char* const* ) gs_stripedback_xpm
), -1 ) ;
549 // make sure we all use one class for all conversions from wx to native colour
551 class wxMacCoreGraphicsColour
554 wxMacCoreGraphicsColour();
555 wxMacCoreGraphicsColour(const wxBrush
&brush
);
556 ~wxMacCoreGraphicsColour();
558 void Apply( CGContextRef cgContext
);
561 wxCFRef
<CGColorRef
> m_color
;
562 wxCFRef
<CGColorSpaceRef
> m_colorSpace
;
565 wxCFRef
<CGPatternRef
> m_pattern
;
566 CGFloat
* m_patternColorComponents
;
569 wxMacCoreGraphicsColour::~wxMacCoreGraphicsColour()
571 delete[] m_patternColorComponents
;
574 void wxMacCoreGraphicsColour::Init()
577 m_patternColorComponents
= NULL
;
580 void wxMacCoreGraphicsColour::Apply( CGContextRef cgContext
)
584 CGAffineTransform matrix
= CGContextGetCTM( cgContext
);
585 CGContextSetPatternPhase( cgContext
, CGSizeMake(matrix
.tx
, matrix
.ty
) );
586 CGContextSetFillColorSpace( cgContext
, m_colorSpace
);
587 CGContextSetFillPattern( cgContext
, m_pattern
, m_patternColorComponents
);
591 CGContextSetFillColorWithColor( cgContext
, m_color
);
595 wxMacCoreGraphicsColour::wxMacCoreGraphicsColour()
600 wxMacCoreGraphicsColour::wxMacCoreGraphicsColour( const wxBrush
&brush
)
603 if ( brush
.GetStyle() == wxSOLID
)
605 m_color
.reset( wxMacCreateCGColor( brush
.GetColour() ));
607 else if ( brush
.IsHatch() )
610 m_colorSpace
.reset( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
611 m_pattern
.reset( (CGPatternRef
) *( new HatchPattern( brush
.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) );
613 m_patternColorComponents
= new CGFloat
[4] ;
614 m_patternColorComponents
[0] = (CGFloat
) (brush
.GetColour().Red() / 255.0);
615 m_patternColorComponents
[1] = (CGFloat
) (brush
.GetColour().Green() / 255.0);
616 m_patternColorComponents
[2] = (CGFloat
) (brush
.GetColour().Blue() / 255.0);
617 m_patternColorComponents
[3] = (CGFloat
) (brush
.GetColour().Alpha() / 255.0);
621 // now brush is a bitmap
622 wxBitmap
* bmp
= brush
.GetStipple();
623 if ( bmp
&& bmp
->Ok() )
626 m_patternColorComponents
= new CGFloat
[1] ;
627 m_patternColorComponents
[0] = (CGFloat
) 1.0;
628 m_colorSpace
.reset( CGColorSpaceCreatePattern( NULL
) );
629 m_pattern
.reset( (CGPatternRef
) *( new ImagePattern( bmp
, CGAffineTransformMakeScale( 1,-1 ) ) ) );
634 class wxMacCoreGraphicsBrushData
: public wxGraphicsObjectRefData
637 wxMacCoreGraphicsBrushData( wxGraphicsRenderer
* renderer
);
638 wxMacCoreGraphicsBrushData( wxGraphicsRenderer
* renderer
, const wxBrush
&brush
);
639 ~wxMacCoreGraphicsBrushData ();
641 virtual void Apply( wxGraphicsContext
* context
);
642 void CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
643 const wxColour
&c1
, const wxColour
&c2
);
644 void CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
645 const wxColour
&oColor
, const wxColour
&cColor
);
647 virtual bool IsShading() { return m_isShading
; }
648 CGShadingRef
GetShading() { return m_shading
; }
650 CGFunctionRef
CreateGradientFunction( const wxColour
& c1
, const wxColour
& c2
);
651 static void CalculateShadingValues (void *info
, const CGFloat
*in
, CGFloat
*out
);
654 wxMacCoreGraphicsColour m_cgColor
;
657 CGFunctionRef m_gradientFunction
;
658 CGShadingRef m_shading
;
659 CGFloat
*m_gradientComponents
;
662 wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData( wxGraphicsRenderer
* renderer
) : wxGraphicsObjectRefData( renderer
)
667 void wxMacCoreGraphicsBrushData::CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
668 const wxColour
&c1
, const wxColour
&c2
)
670 m_gradientFunction
= CreateGradientFunction( c1
, c2
);
671 m_shading
= CGShadingCreateAxial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat
) x1
, (CGFloat
) y1
),
672 CGPointMake((CGFloat
) x2
,(CGFloat
) y2
), m_gradientFunction
, true, true ) ;
676 void wxMacCoreGraphicsBrushData::CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
677 const wxColour
&oColor
, const wxColour
&cColor
)
679 m_gradientFunction
= CreateGradientFunction( oColor
, cColor
);
680 m_shading
= CGShadingCreateRadial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat
) xo
,(CGFloat
) yo
), 0,
681 CGPointMake((CGFloat
) xc
,(CGFloat
) yc
), (CGFloat
) radius
, m_gradientFunction
, true, true ) ;
685 wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData(wxGraphicsRenderer
* renderer
, const wxBrush
&brush
) : wxGraphicsObjectRefData( renderer
),
692 wxMacCoreGraphicsBrushData::~wxMacCoreGraphicsBrushData()
695 CGShadingRelease(m_shading
);
697 if( m_gradientFunction
)
698 CGFunctionRelease(m_gradientFunction
);
700 delete[] m_gradientComponents
;
703 void wxMacCoreGraphicsBrushData::Init()
705 m_gradientFunction
= NULL
;
707 m_gradientComponents
= NULL
;
711 void wxMacCoreGraphicsBrushData::Apply( wxGraphicsContext
* context
)
713 CGContextRef cg
= (CGContextRef
) context
->GetNativeContext();
717 // nothing to set as shades are processed by clipping using the path and filling
721 m_cgColor
.Apply( cg
);
725 void wxMacCoreGraphicsBrushData::CalculateShadingValues (void *info
, const CGFloat
*in
, CGFloat
*out
)
727 CGFloat
* colors
= (CGFloat
*) info
;
729 for( int i
= 0 ; i
< 4 ; ++i
)
731 out
[i
] = colors
[i
] + ( colors
[4+i
] - colors
[i
] ) * f
;
735 CGFunctionRef
wxMacCoreGraphicsBrushData::CreateGradientFunction( const wxColour
& c1
, const wxColour
& c2
)
737 static const CGFunctionCallbacks callbacks
= { 0, &CalculateShadingValues
, NULL
};
738 static const CGFloat input_value_range
[2] = { 0, 1 };
739 static const CGFloat output_value_ranges
[8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
740 m_gradientComponents
= new CGFloat
[8] ;
741 m_gradientComponents
[0] = (CGFloat
) (c1
.Red() / 255.0);
742 m_gradientComponents
[1] = (CGFloat
) (c1
.Green() / 255.0);
743 m_gradientComponents
[2] = (CGFloat
) (c1
.Blue() / 255.0);
744 m_gradientComponents
[3] = (CGFloat
) (c1
.Alpha() / 255.0);
745 m_gradientComponents
[4] = (CGFloat
) (c2
.Red() / 255.0);
746 m_gradientComponents
[5] = (CGFloat
) (c2
.Green() / 255.0);
747 m_gradientComponents
[6] = (CGFloat
) (c2
.Blue() / 255.0);
748 m_gradientComponents
[7] = (CGFloat
) (c2
.Alpha() / 255.0);
750 return CGFunctionCreate ( m_gradientComponents
, 1,
761 class wxMacCoreGraphicsFontData
: public wxGraphicsObjectRefData
764 wxMacCoreGraphicsFontData( wxGraphicsRenderer
* renderer
, const wxFont
&font
, const wxColour
& col
);
765 ~wxMacCoreGraphicsFontData();
767 #if wxMAC_USE_ATSU_TEXT
768 virtual ATSUStyle
GetATSUStyle() { return m_macATSUIStyle
; }
770 #if wxMAC_USE_CORE_TEXT
771 CTFontRef
GetCTFont() const { return m_ctFont
; }
773 wxColour
GetColour() const { return m_colour
; }
775 bool GetUnderlined() const { return m_underlined
; }
779 #if wxMAC_USE_ATSU_TEXT
780 ATSUStyle m_macATSUIStyle
;
782 #if wxMAC_USE_CORE_TEXT
783 wxCFRef
< CTFontRef
> m_ctFont
;
787 wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer
* renderer
, const wxFont
&font
, const wxColour
& col
) : wxGraphicsObjectRefData( renderer
)
790 m_underlined
= font
.GetUnderlined();
792 #if wxMAC_USE_CORE_TEXT
793 m_ctFont
.reset( wxMacCreateCTFont( font
) );
795 #if wxMAC_USE_ATSU_TEXT
796 OSStatus status
= noErr
;
797 m_macATSUIStyle
= NULL
;
799 status
= ATSUCreateAndCopyStyle( (ATSUStyle
) font
.MacGetATSUStyle() , &m_macATSUIStyle
);
801 wxASSERT_MSG( status
== noErr
, wxT("couldn't create ATSU style") );
803 // we need the scale here ...
805 Fixed atsuSize
= IntToFixed( int( 1 * font
.MacGetFontSize()) );
807 col
.GetRGBColor( &atsuColor
);
808 ATSUAttributeTag atsuTags
[] =
813 ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
818 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
824 status
= ::ATSUSetAttributes(
825 m_macATSUIStyle
, sizeof(atsuTags
) / sizeof(ATSUAttributeTag
) ,
826 atsuTags
, atsuSizes
, atsuValues
);
828 wxASSERT_MSG( status
== noErr
, wxT("couldn't modify ATSU style") );
830 #if wxMAC_USE_CG_TEXT
834 wxMacCoreGraphicsFontData::~wxMacCoreGraphicsFontData()
836 #if wxMAC_USE_CORE_TEXT
838 #if wxMAC_USE_ATSU_TEXT
839 if ( m_macATSUIStyle
)
841 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUIStyle
);
842 m_macATSUIStyle
= NULL
;
845 #if wxMAC_USE_CG_TEXT
849 class wxMacCoreGraphicsBitmapData
: public wxGraphicsObjectRefData
852 wxMacCoreGraphicsBitmapData( wxGraphicsRenderer
* renderer
, CGImageRef bitmap
, bool monochrome
);
853 ~wxMacCoreGraphicsBitmapData();
855 virtual CGImageRef
GetBitmap() { return m_bitmap
; }
856 bool IsMonochrome() { return m_monochrome
; }
862 wxMacCoreGraphicsBitmapData::wxMacCoreGraphicsBitmapData( wxGraphicsRenderer
* renderer
, CGImageRef bitmap
, bool monochrome
) : wxGraphicsObjectRefData( renderer
),
863 m_bitmap(bitmap
), m_monochrome(monochrome
)
867 wxMacCoreGraphicsBitmapData::~wxMacCoreGraphicsBitmapData()
869 CGImageRelease( m_bitmap
);
876 //-----------------------------------------------------------------------------
877 // wxMacCoreGraphicsMatrix declaration
878 //-----------------------------------------------------------------------------
880 class WXDLLIMPEXP_CORE wxMacCoreGraphicsMatrixData
: public wxGraphicsMatrixData
883 wxMacCoreGraphicsMatrixData(wxGraphicsRenderer
* renderer
) ;
885 virtual ~wxMacCoreGraphicsMatrixData() ;
887 virtual wxGraphicsObjectRefData
*Clone() const ;
889 // concatenates the matrix
890 virtual void Concat( const wxGraphicsMatrixData
*t
);
892 // sets the matrix to the respective values
893 virtual void Set(wxDouble a
=1.0, wxDouble b
=0.0, wxDouble c
=0.0, wxDouble d
=1.0,
894 wxDouble tx
=0.0, wxDouble ty
=0.0);
896 // gets the component valuess of the matrix
897 virtual void Get(wxDouble
* a
=NULL
, wxDouble
* b
=NULL
, wxDouble
* c
=NULL
,
898 wxDouble
* d
=NULL
, wxDouble
* tx
=NULL
, wxDouble
* ty
=NULL
) const;
900 // makes this the inverse matrix
901 virtual void Invert();
903 // returns true if the elements of the transformation matrix are equal ?
904 virtual bool IsEqual( const wxGraphicsMatrixData
* t
) const ;
906 // return true if this is the identity matrix
907 virtual bool IsIdentity() const;
913 // add the translation to this matrix
914 virtual void Translate( wxDouble dx
, wxDouble dy
);
916 // add the scale to this matrix
917 virtual void Scale( wxDouble xScale
, wxDouble yScale
);
919 // add the rotation to this matrix (radians)
920 virtual void Rotate( wxDouble angle
);
923 // apply the transforms
926 // applies that matrix to the point
927 virtual void TransformPoint( wxDouble
*x
, wxDouble
*y
) const;
929 // applies the matrix except for translations
930 virtual void TransformDistance( wxDouble
*dx
, wxDouble
*dy
) const;
932 // returns the native representation
933 virtual void * GetNativeMatrix() const;
936 CGAffineTransform m_matrix
;
939 //-----------------------------------------------------------------------------
940 // wxMacCoreGraphicsMatrix implementation
941 //-----------------------------------------------------------------------------
943 wxMacCoreGraphicsMatrixData::wxMacCoreGraphicsMatrixData(wxGraphicsRenderer
* renderer
) : wxGraphicsMatrixData(renderer
)
947 wxMacCoreGraphicsMatrixData::~wxMacCoreGraphicsMatrixData()
951 wxGraphicsObjectRefData
*wxMacCoreGraphicsMatrixData::Clone() const
953 wxMacCoreGraphicsMatrixData
* m
= new wxMacCoreGraphicsMatrixData(GetRenderer()) ;
954 m
->m_matrix
= m_matrix
;
958 // concatenates the matrix
959 void wxMacCoreGraphicsMatrixData::Concat( const wxGraphicsMatrixData
*t
)
961 m_matrix
= CGAffineTransformConcat(m_matrix
, *((CGAffineTransform
*) t
->GetNativeMatrix()) );
964 // sets the matrix to the respective values
965 void wxMacCoreGraphicsMatrixData::Set(wxDouble a
, wxDouble b
, wxDouble c
, wxDouble d
,
966 wxDouble tx
, wxDouble ty
)
968 m_matrix
= CGAffineTransformMake((CGFloat
) a
,(CGFloat
) b
,(CGFloat
) c
,(CGFloat
) d
,(CGFloat
) tx
,(CGFloat
) ty
);
971 // gets the component valuess of the matrix
972 void wxMacCoreGraphicsMatrixData::Get(wxDouble
* a
, wxDouble
* b
, wxDouble
* c
,
973 wxDouble
* d
, wxDouble
* tx
, wxDouble
* ty
) const
975 if (a
) *a
= m_matrix
.a
;
976 if (b
) *b
= m_matrix
.b
;
977 if (c
) *c
= m_matrix
.c
;
978 if (d
) *d
= m_matrix
.d
;
979 if (tx
) *tx
= m_matrix
.tx
;
980 if (ty
) *ty
= m_matrix
.ty
;
983 // makes this the inverse matrix
984 void wxMacCoreGraphicsMatrixData::Invert()
986 m_matrix
= CGAffineTransformInvert( m_matrix
);
989 // returns true if the elements of the transformation matrix are equal ?
990 bool wxMacCoreGraphicsMatrixData::IsEqual( const wxGraphicsMatrixData
* t
) const
992 return CGAffineTransformEqualToTransform(m_matrix
, *((CGAffineTransform
*) t
->GetNativeMatrix()));
995 // return true if this is the identity matrix
996 bool wxMacCoreGraphicsMatrixData::IsIdentity() const
998 return ( m_matrix
.a
== 1 && m_matrix
.d
== 1 &&
999 m_matrix
.b
== 0 && m_matrix
.d
== 0 && m_matrix
.tx
== 0 && m_matrix
.ty
== 0);
1006 // add the translation to this matrix
1007 void wxMacCoreGraphicsMatrixData::Translate( wxDouble dx
, wxDouble dy
)
1009 m_matrix
= CGAffineTransformTranslate( m_matrix
, (CGFloat
) dx
, (CGFloat
) dy
);
1012 // add the scale to this matrix
1013 void wxMacCoreGraphicsMatrixData::Scale( wxDouble xScale
, wxDouble yScale
)
1015 m_matrix
= CGAffineTransformScale( m_matrix
, (CGFloat
) xScale
, (CGFloat
) yScale
);
1018 // add the rotation to this matrix (radians)
1019 void wxMacCoreGraphicsMatrixData::Rotate( wxDouble angle
)
1021 m_matrix
= CGAffineTransformRotate( m_matrix
, (CGFloat
) angle
);
1025 // apply the transforms
1028 // applies that matrix to the point
1029 void wxMacCoreGraphicsMatrixData::TransformPoint( wxDouble
*x
, wxDouble
*y
) const
1031 CGPoint pt
= CGPointApplyAffineTransform( CGPointMake((CGFloat
) *x
,(CGFloat
) *y
), m_matrix
);
1037 // applies the matrix except for translations
1038 void wxMacCoreGraphicsMatrixData::TransformDistance( wxDouble
*dx
, wxDouble
*dy
) const
1040 CGSize sz
= CGSizeApplyAffineTransform( CGSizeMake((CGFloat
) *dx
,(CGFloat
) *dy
) , m_matrix
);
1045 // returns the native representation
1046 void * wxMacCoreGraphicsMatrixData::GetNativeMatrix() const
1048 return (void*) &m_matrix
;
1055 //-----------------------------------------------------------------------------
1056 // wxMacCoreGraphicsPath declaration
1057 //-----------------------------------------------------------------------------
1059 class WXDLLEXPORT wxMacCoreGraphicsPathData
: public wxGraphicsPathData
1062 wxMacCoreGraphicsPathData( wxGraphicsRenderer
* renderer
, CGMutablePathRef path
= NULL
);
1064 ~wxMacCoreGraphicsPathData();
1066 virtual wxGraphicsObjectRefData
*Clone() const;
1068 // begins a new subpath at (x,y)
1069 virtual void MoveToPoint( wxDouble x
, wxDouble y
);
1071 // adds a straight line from the current point to (x,y)
1072 virtual void AddLineToPoint( wxDouble x
, wxDouble y
);
1074 // adds a cubic Bezier curve from the current point, using two control points and an end point
1075 virtual void AddCurveToPoint( wxDouble cx1
, wxDouble cy1
, wxDouble cx2
, wxDouble cy2
, wxDouble x
, wxDouble y
);
1077 // closes the current sub-path
1078 virtual void CloseSubpath();
1080 // gets the last point of the current path, (0,0) if not yet set
1081 virtual void GetCurrentPoint( wxDouble
* x
, wxDouble
* y
) const;
1083 // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
1084 virtual void AddArc( wxDouble x
, wxDouble y
, wxDouble r
, wxDouble startAngle
, wxDouble endAngle
, bool clockwise
);
1087 // These are convenience functions which - if not available natively will be assembled
1088 // using the primitives from above
1091 // adds a quadratic Bezier curve from the current point, using a control point and an end point
1092 virtual void AddQuadCurveToPoint( wxDouble cx
, wxDouble cy
, wxDouble x
, wxDouble y
);
1094 // appends a rectangle as a new closed subpath
1095 virtual void AddRectangle( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
1097 // appends an ellipsis as a new closed subpath fitting the passed rectangle
1098 virtual void AddCircle( wxDouble x
, wxDouble y
, wxDouble r
);
1100 // 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)
1101 virtual void AddArcToPoint( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
, wxDouble r
);
1103 // adds another path
1104 virtual void AddPath( const wxGraphicsPathData
* path
);
1106 // returns the native path
1107 virtual void * GetNativePath() const { return m_path
; }
1109 // give the native path returned by GetNativePath() back (there might be some deallocations necessary)
1110 virtual void UnGetNativePath(void *WXUNUSED(p
)) const {}
1112 // transforms each point of this path by the matrix
1113 virtual void Transform( const wxGraphicsMatrixData
* matrix
);
1115 // gets the bounding box enclosing all points (possibly including control points)
1116 virtual void GetBox(wxDouble
*x
, wxDouble
*y
, wxDouble
*w
, wxDouble
*y
) const;
1118 virtual bool Contains( wxDouble x
, wxDouble y
, int fillStyle
= wxODDEVEN_RULE
) const;
1120 CGMutablePathRef m_path
;
1123 //-----------------------------------------------------------------------------
1124 // wxMacCoreGraphicsPath implementation
1125 //-----------------------------------------------------------------------------
1127 wxMacCoreGraphicsPathData::wxMacCoreGraphicsPathData( wxGraphicsRenderer
* renderer
, CGMutablePathRef path
) : wxGraphicsPathData(renderer
)
1132 m_path
= CGPathCreateMutable();
1135 wxMacCoreGraphicsPathData::~wxMacCoreGraphicsPathData()
1137 CGPathRelease( m_path
);
1140 wxGraphicsObjectRefData
* wxMacCoreGraphicsPathData::Clone() const
1142 wxMacCoreGraphicsPathData
* clone
= new wxMacCoreGraphicsPathData(GetRenderer(),CGPathCreateMutableCopy(m_path
));
1147 // opens (starts) a new subpath
1148 void wxMacCoreGraphicsPathData::MoveToPoint( wxDouble x1
, wxDouble y1
)
1150 CGPathMoveToPoint( m_path
, NULL
, (CGFloat
) x1
, (CGFloat
) y1
);
1153 void wxMacCoreGraphicsPathData::AddLineToPoint( wxDouble x1
, wxDouble y1
)
1155 CGPathAddLineToPoint( m_path
, NULL
, (CGFloat
) x1
, (CGFloat
) y1
);
1158 void wxMacCoreGraphicsPathData::AddCurveToPoint( wxDouble cx1
, wxDouble cy1
, wxDouble cx2
, wxDouble cy2
, wxDouble x
, wxDouble y
)
1160 CGPathAddCurveToPoint( m_path
, NULL
, (CGFloat
) cx1
, (CGFloat
) cy1
, (CGFloat
) cx2
, (CGFloat
) cy2
, (CGFloat
) x
, (CGFloat
) y
);
1163 void wxMacCoreGraphicsPathData::AddQuadCurveToPoint( wxDouble cx1
, wxDouble cy1
, wxDouble x
, wxDouble y
)
1165 CGPathAddQuadCurveToPoint( m_path
, NULL
, (CGFloat
) cx1
, (CGFloat
) cy1
, (CGFloat
) x
, (CGFloat
) y
);
1168 void wxMacCoreGraphicsPathData::AddRectangle( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1170 CGRect cgRect
= { { (CGFloat
) x
, (CGFloat
) y
} , { (CGFloat
) w
, (CGFloat
) h
} };
1171 CGPathAddRect( m_path
, NULL
, cgRect
);
1174 void wxMacCoreGraphicsPathData::AddCircle( wxDouble x
, wxDouble y
, wxDouble r
)
1176 CGPathAddArc( m_path
, NULL
, (CGFloat
) x
, (CGFloat
) y
, (CGFloat
) r
, (CGFloat
) 0.0 , (CGFloat
) (2 * M_PI
) , true );
1179 // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
1180 void wxMacCoreGraphicsPathData::AddArc( wxDouble x
, wxDouble y
, wxDouble r
, wxDouble startAngle
, wxDouble endAngle
, bool clockwise
)
1182 // inverse direction as we the 'normal' state is a y axis pointing down, ie mirrored to the standard core graphics setup
1183 CGPathAddArc( m_path
, NULL
, (CGFloat
) x
, (CGFloat
) y
, (CGFloat
) r
, (CGFloat
) startAngle
, (CGFloat
) endAngle
, !clockwise
);
1186 void wxMacCoreGraphicsPathData::AddArcToPoint( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
, wxDouble r
)
1188 CGPathAddArcToPoint( m_path
, NULL
, (CGFloat
) x1
, (CGFloat
) y1
, (CGFloat
) x2
, (CGFloat
) y2
, (CGFloat
) r
);
1191 void wxMacCoreGraphicsPathData::AddPath( const wxGraphicsPathData
* path
)
1193 CGPathAddPath( m_path
, NULL
, (CGPathRef
) path
->GetNativePath() );
1196 // closes the current subpath
1197 void wxMacCoreGraphicsPathData::CloseSubpath()
1199 CGPathCloseSubpath( m_path
);
1202 // gets the last point of the current path, (0,0) if not yet set
1203 void wxMacCoreGraphicsPathData::GetCurrentPoint( wxDouble
* x
, wxDouble
* y
) const
1205 CGPoint p
= CGPathGetCurrentPoint( m_path
);
1210 // transforms each point of this path by the matrix
1211 void wxMacCoreGraphicsPathData::Transform( const wxGraphicsMatrixData
* matrix
)
1213 CGMutablePathRef p
= CGPathCreateMutable() ;
1214 CGPathAddPath( p
, (CGAffineTransform
*) matrix
->GetNativeMatrix() , m_path
);
1215 CGPathRelease( m_path
);
1219 // gets the bounding box enclosing all points (possibly including control points)
1220 void wxMacCoreGraphicsPathData::GetBox(wxDouble
*x
, wxDouble
*y
, wxDouble
*w
, wxDouble
*h
) const
1222 CGRect bounds
= CGPathGetBoundingBox( m_path
) ;
1223 *x
= bounds
.origin
.x
;
1224 *y
= bounds
.origin
.y
;
1225 *w
= bounds
.size
.width
;
1226 *h
= bounds
.size
.height
;
1229 bool wxMacCoreGraphicsPathData::Contains( wxDouble x
, wxDouble y
, int fillStyle
) const
1231 return CGPathContainsPoint( m_path
, NULL
, CGPointMake((CGFloat
) x
,(CGFloat
) y
), fillStyle
== wxODDEVEN_RULE
);
1238 //-----------------------------------------------------------------------------
1239 // wxMacCoreGraphicsContext declaration
1240 //-----------------------------------------------------------------------------
1242 class WXDLLEXPORT wxMacCoreGraphicsContext
: public wxGraphicsContext
1245 wxMacCoreGraphicsContext( wxGraphicsRenderer
* renderer
, CGContextRef cgcontext
, wxDouble width
= 0, wxDouble height
= 0 );
1247 wxMacCoreGraphicsContext( wxGraphicsRenderer
* renderer
, WindowRef window
);
1249 wxMacCoreGraphicsContext( wxGraphicsRenderer
* renderer
, wxWindow
* window
);
1251 wxMacCoreGraphicsContext( wxGraphicsRenderer
* renderer
);
1253 wxMacCoreGraphicsContext();
1255 ~wxMacCoreGraphicsContext();
1259 // returns the size of the graphics context in device coordinates
1260 virtual void GetSize( wxDouble
* width
, wxDouble
* height
);
1262 virtual void StartPage( wxDouble width
, wxDouble height
);
1264 virtual void EndPage();
1266 virtual void Flush();
1268 // push the current state of the context, ie the transformation matrix on a stack
1269 virtual void PushState();
1271 // pops a stored state from the stack
1272 virtual void PopState();
1274 // clips drawings to the region
1275 virtual void Clip( const wxRegion
®ion
);
1277 // clips drawings to the rect
1278 virtual void Clip( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
1280 // resets the clipping to original extent
1281 virtual void ResetClip();
1283 virtual void * GetNativeContext();
1285 bool SetLogicalFunction( int function
);
1291 virtual void Translate( wxDouble dx
, wxDouble dy
);
1294 virtual void Scale( wxDouble xScale
, wxDouble yScale
);
1297 virtual void Rotate( wxDouble angle
);
1299 // concatenates this transform with the current transform of this context
1300 virtual void ConcatTransform( const wxGraphicsMatrix
& matrix
);
1302 // sets the transform of this context
1303 virtual void SetTransform( const wxGraphicsMatrix
& matrix
);
1305 // gets the matrix of this context
1306 virtual wxGraphicsMatrix
GetTransform() const;
1308 // setting the paint
1311 // strokes along a path with the current pen
1312 virtual void StrokePath( const wxGraphicsPath
&path
);
1314 // fills a path with the current brush
1315 virtual void FillPath( const wxGraphicsPath
&path
, int fillStyle
= wxODDEVEN_RULE
);
1317 // draws a path by first filling and then stroking
1318 virtual void DrawPath( const wxGraphicsPath
&path
, int fillStyle
= wxODDEVEN_RULE
);
1320 virtual bool ShouldOffset() const
1323 if ( !m_pen
.IsNull() )
1325 penwidth
= (int)((wxMacCoreGraphicsPenData
*)m_pen
.GetRefData())->GetWidth();
1326 if ( penwidth
== 0 )
1329 return ( penwidth
% 2 ) == 1;
1335 virtual void DrawText( const wxString
&str
, wxDouble x
, wxDouble y
);
1337 virtual void DrawText( const wxString
&str
, wxDouble x
, wxDouble y
, wxDouble angle
);
1339 virtual void GetTextExtent( const wxString
&text
, wxDouble
*width
, wxDouble
*height
,
1340 wxDouble
*descent
, wxDouble
*externalLeading
) const;
1342 virtual void GetPartialTextExtents(const wxString
& text
, wxArrayDouble
& widths
) const;
1348 virtual void DrawBitmap( const wxBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
1350 virtual void DrawBitmap( const wxGraphicsBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
1352 virtual void DrawIcon( const wxIcon
&icon
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
);
1354 void SetNativeContext( CGContextRef cg
);
1356 DECLARE_NO_COPY_CLASS(wxMacCoreGraphicsContext
)
1357 DECLARE_DYNAMIC_CLASS(wxMacCoreGraphicsContext
)
1360 void EnsureIsValid();
1362 CGContextRef m_cgContext
;
1363 WindowRef m_windowRef
;
1364 bool m_releaseContext
;
1365 CGAffineTransform m_windowTransform
;
1369 wxCFRef
<HIShapeRef
> m_clipRgn
;
1372 //-----------------------------------------------------------------------------
1373 // device context implementation
1375 // more and more of the dc functionality should be implemented by calling
1376 // the appropricate wxMacCoreGraphicsContext, but we will have to do that step by step
1377 // also coordinate conversions should be moved to native matrix ops
1378 //-----------------------------------------------------------------------------
1380 // we always stock two context states, one at entry, to be able to preserve the
1381 // state we were called with, the other one after changing to HI Graphics orientation
1382 // (this one is used for getting back clippings etc)
1384 //-----------------------------------------------------------------------------
1385 // wxMacCoreGraphicsContext implementation
1386 //-----------------------------------------------------------------------------
1388 IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsContext
, wxGraphicsContext
)
1390 class wxQuartzOffsetHelper
1393 wxQuartzOffsetHelper( CGContextRef cg
, bool offset
)
1398 CGContextTranslateCTM( m_cg
, (CGFloat
) 0.5, (CGFloat
) 0.5 );
1400 ~wxQuartzOffsetHelper( )
1403 CGContextTranslateCTM( m_cg
, (CGFloat
) -0.5, (CGFloat
) -0.5 );
1410 void wxMacCoreGraphicsContext::Init()
1413 m_releaseContext
= false;
1419 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer
* renderer
, CGContextRef cgcontext
, wxDouble width
, wxDouble height
) : wxGraphicsContext(renderer
)
1422 SetNativeContext(cgcontext
);
1427 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer
* renderer
, WindowRef window
): wxGraphicsContext(renderer
)
1430 m_windowRef
= window
;
1433 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer
* renderer
, wxWindow
* window
): wxGraphicsContext(renderer
)
1437 int originX
, originY
;
1438 originX
= originY
= 0;
1440 Rect bounds
= { 0,0,0,0 };
1441 #if defined( __LP64__ ) || defined(__WXCOCOA__)
1443 m_windowRef
= (WindowRef
) window
->MacGetTopLevelWindowRef();
1444 window
->MacWindowToRootWindow( &originX
, &originY
);
1445 GetWindowBounds( m_windowRef
, kWindowContentRgn
, &bounds
);
1447 m_windowTransform
= CGAffineTransformMakeTranslation( 0 , bounds
.bottom
- bounds
.top
);
1448 m_windowTransform
= CGAffineTransformScale( m_windowTransform
, 1 , -1 );
1449 m_windowTransform
= CGAffineTransformTranslate( m_windowTransform
, originX
, originY
) ;
1452 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext(wxGraphicsRenderer
* renderer
) : wxGraphicsContext(renderer
)
1457 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext() : wxGraphicsContext(NULL
)
1460 wxLogDebug(wxT("Illegal Constructor called"));
1463 wxMacCoreGraphicsContext::~wxMacCoreGraphicsContext()
1465 SetNativeContext(NULL
);
1468 void wxMacCoreGraphicsContext::GetSize( wxDouble
* width
, wxDouble
* height
)
1475 void wxMacCoreGraphicsContext::StartPage( wxDouble width
, wxDouble height
)
1478 if ( width
!= 0 && height
!= 0)
1479 r
= CGRectMake( (CGFloat
) 0.0 , (CGFloat
) 0.0 , (CGFloat
) width
, (CGFloat
) height
);
1481 r
= CGRectMake( (CGFloat
) 0.0 , (CGFloat
) 0.0 , (CGFloat
) m_width
, (CGFloat
) m_height
);
1483 CGContextBeginPage(m_cgContext
, &r
);
1484 // CGContextTranslateCTM( m_cgContext , 0 , height == 0 ? m_height : height );
1485 // CGContextScaleCTM( m_cgContext , 1 , -1 );
1488 void wxMacCoreGraphicsContext::EndPage()
1490 CGContextEndPage(m_cgContext
);
1493 void wxMacCoreGraphicsContext::Flush()
1495 CGContextFlush(m_cgContext
);
1498 void wxMacCoreGraphicsContext::EnsureIsValid()
1503 #if ! ( defined( __LP64__ ) || defined(__WXCOCOA__) )
1504 QDBeginCGContext( GetWindowPort( m_windowRef
) , &m_cgContext
);
1508 if ( status
!= noErr
)
1510 wxFAIL_MSG("Cannot nest wxDCs on the same window");
1513 CGContextConcatCTM( m_cgContext
, m_windowTransform
);
1514 CGContextSaveGState( m_cgContext
);
1515 m_releaseContext
= true;
1516 if ( m_clipRgn
.get() )
1518 // the clip region is in device coordinates, so we convert this again to user coordinates
1519 wxCFRef
<HIMutableShapeRef
> hishape( HIShapeCreateMutableCopy( m_clipRgn
) );
1520 CGPoint transformedOrigin
= CGPointApplyAffineTransform( CGPointZero
,m_windowTransform
);
1521 HIShapeOffset( hishape
, -transformedOrigin
.x
, -transformedOrigin
.y
);
1522 // if the shape is empty, HIShapeReplacePathInCGContext doesn't work
1523 if ( HIShapeIsEmpty(hishape
))
1525 CGRect empty
= CGRectMake( 0,0,0,0 );
1526 CGContextClipToRect( m_cgContext
, empty
);
1530 HIShapeReplacePathInCGContext( hishape
, m_cgContext
);
1531 CGContextClip( m_cgContext
);
1534 CGContextSaveGState( m_cgContext
);
1538 // TODO test whether the private CGContextSetCompositeOperation works under 10.3 (using NSCompositingModes)
1540 bool wxMacCoreGraphicsContext::SetLogicalFunction( int function
)
1542 if (m_logicalFunction
== function
)
1547 bool retval
= false;
1548 bool shouldAntiAlias
= true;
1549 CGBlendMode mode
= kCGBlendModeNormal
;
1551 #if defined(__WXMAC__) && ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 )
1552 if ( UMAGetSystemVersion() >= 0x1050 )
1557 // TODO find best corresponding porter duff modes
1559 mode
= kCGBlendModeCopy
;
1562 mode
= kCGBlendModeClear
;
1565 mode
= kCGBlendModeXOR
;
1566 shouldAntiAlias
= false;
1576 if ( function
== wxCOPY
)
1580 else if ( function
== wxINVERT
|| function
== wxXOR
)
1582 // change color to white
1583 mode
= kCGBlendModeExclusion
;
1584 shouldAntiAlias
= false;
1591 m_logicalFunction
= function
;
1592 CGContextSetBlendMode( m_cgContext
, mode
);
1593 CGContextSetShouldAntialias(m_cgContext
, shouldAntiAlias
);
1598 void wxMacCoreGraphicsContext::Clip( const wxRegion
®ion
)
1603 wxCFRef
<HIShapeRef
> shape
= wxCFRefFromGet(region
.GetWXHRGN());
1604 // if the shape is empty, HIShapeReplacePathInCGContext doesn't work
1605 if ( HIShapeIsEmpty(shape
))
1607 CGRect empty
= CGRectMake( 0,0,0,0 );
1608 CGContextClipToRect( m_cgContext
, empty
);
1612 HIShapeReplacePathInCGContext( shape
, m_cgContext
);
1613 CGContextClip( m_cgContext
);
1618 // this offsetting to device coords is not really correct, but since we cannot apply affine transforms
1619 // to regions we try at least to have correct translations
1620 HIMutableShapeRef mutableShape
= HIShapeCreateMutableCopy( region
.GetWXHRGN() );
1622 CGPoint transformedOrigin
= CGPointApplyAffineTransform( CGPointZero
, m_windowTransform
);
1623 HIShapeOffset( mutableShape
, transformedOrigin
.x
, transformedOrigin
.y
);
1624 m_clipRgn
.reset(mutableShape
);
1629 // clips drawings to the rect
1630 void wxMacCoreGraphicsContext::Clip( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1632 CGRect r
= CGRectMake( (CGFloat
) x
, (CGFloat
) y
, (CGFloat
) w
, (CGFloat
) h
);
1635 CGContextClipToRect( m_cgContext
, r
);
1639 // the clipping itself must be stored as device coordinates, otherwise
1640 // we cannot apply it back correctly
1641 r
.origin
= CGPointApplyAffineTransform( r
.origin
, m_windowTransform
);
1642 m_clipRgn
.reset(HIShapeCreateWithRect(&r
));
1646 // resets the clipping to original extent
1647 void wxMacCoreGraphicsContext::ResetClip()
1651 // there is no way for clearing the clip, we can only revert to the stored
1652 // state, but then we have to make sure everything else is NOT restored
1653 CGAffineTransform transform
= CGContextGetCTM( m_cgContext
);
1654 CGContextRestoreGState( m_cgContext
);
1655 CGContextSaveGState( m_cgContext
);
1656 CGAffineTransform transformNew
= CGContextGetCTM( m_cgContext
);
1657 transformNew
= CGAffineTransformInvert( transformNew
) ;
1658 CGContextConcatCTM( m_cgContext
, transformNew
);
1659 CGContextConcatCTM( m_cgContext
, transform
);
1667 void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath
&path
)
1669 if ( m_pen
.IsNull() )
1674 wxQuartzOffsetHelper
helper( m_cgContext
, ShouldOffset() );
1676 ((wxMacCoreGraphicsPenData
*)m_pen
.GetRefData())->Apply(this);
1677 CGContextAddPath( m_cgContext
, (CGPathRef
) path
.GetNativePath() );
1678 CGContextStrokePath( m_cgContext
);
1681 void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath
&path
, int fillStyle
)
1683 if ( !m_brush
.IsNull() && ((wxMacCoreGraphicsBrushData
*)m_brush
.GetRefData())->IsShading() )
1685 // when using shading, we cannot draw pen and brush at the same time
1686 // revert to the base implementation of first filling and then stroking
1687 wxGraphicsContext::DrawPath( path
, fillStyle
);
1691 CGPathDrawingMode mode
= kCGPathFill
;
1692 if ( m_brush
.IsNull() )
1694 if ( m_pen
.IsNull() )
1697 mode
= kCGPathStroke
;
1701 if ( m_pen
.IsNull() )
1703 if ( fillStyle
== wxODDEVEN_RULE
)
1704 mode
= kCGPathEOFill
;
1710 if ( fillStyle
== wxODDEVEN_RULE
)
1711 mode
= kCGPathEOFillStroke
;
1713 mode
= kCGPathFillStroke
;
1719 if ( !m_brush
.IsNull() )
1720 ((wxMacCoreGraphicsBrushData
*)m_brush
.GetRefData())->Apply(this);
1721 if ( !m_pen
.IsNull() )
1722 ((wxMacCoreGraphicsPenData
*)m_pen
.GetRefData())->Apply(this);
1724 wxQuartzOffsetHelper
helper( m_cgContext
, ShouldOffset() );
1726 CGContextAddPath( m_cgContext
, (CGPathRef
) path
.GetNativePath() );
1727 CGContextDrawPath( m_cgContext
, mode
);
1730 void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath
&path
, int fillStyle
)
1732 if ( m_brush
.IsNull() )
1737 if ( ((wxMacCoreGraphicsBrushData
*)m_brush
.GetRefData())->IsShading() )
1739 CGContextSaveGState( m_cgContext
);
1740 CGContextAddPath( m_cgContext
, (CGPathRef
) path
.GetNativePath() );
1741 CGContextClip( m_cgContext
);
1742 CGContextDrawShading( m_cgContext
, ((wxMacCoreGraphicsBrushData
*)m_brush
.GetRefData())->GetShading() );
1743 CGContextRestoreGState( m_cgContext
);
1747 ((wxMacCoreGraphicsBrushData
*)m_brush
.GetRefData())->Apply(this);
1748 CGContextAddPath( m_cgContext
, (CGPathRef
) path
.GetNativePath() );
1749 if ( fillStyle
== wxODDEVEN_RULE
)
1750 CGContextEOFillPath( m_cgContext
);
1752 CGContextFillPath( m_cgContext
);
1756 void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg
)
1758 // we allow either setting or clearing but not replacing
1759 wxASSERT( m_cgContext
== NULL
|| cg
== NULL
);
1763 // TODO : when is this necessary - should we add a Flush() method ? CGContextSynchronize( m_cgContext );
1764 CGContextRestoreGState( m_cgContext
);
1765 CGContextRestoreGState( m_cgContext
);
1766 if ( m_releaseContext
)
1768 #if ! ( defined( __LP64__ ) || defined(__WXCOCOA__) )
1769 QDEndCGContext( GetWindowPort( m_windowRef
) , &m_cgContext
);
1773 CGContextRelease(m_cgContext
);
1779 // FIXME: This check is needed because currently we need to use a DC/GraphicsContext
1780 // in order to get font properties, like wxFont::GetPixelSize, but since we don't have
1781 // a native window attached to use, I create a wxGraphicsContext with a NULL CGContextRef
1782 // for this one operation.
1784 // When wxFont::GetPixelSize on Mac no longer needs a graphics context, this check
1788 CGContextRetain(m_cgContext
);
1789 CGContextSaveGState( m_cgContext
);
1790 CGContextSetTextMatrix( m_cgContext
, CGAffineTransformIdentity
);
1791 CGContextSaveGState( m_cgContext
);
1792 m_releaseContext
= false;
1796 void wxMacCoreGraphicsContext::Translate( wxDouble dx
, wxDouble dy
)
1799 CGContextTranslateCTM( m_cgContext
, (CGFloat
) dx
, (CGFloat
) dy
);
1801 m_windowTransform
= CGAffineTransformTranslate(m_windowTransform
, (CGFloat
) dx
, (CGFloat
) dy
);
1804 void wxMacCoreGraphicsContext::Scale( wxDouble xScale
, wxDouble yScale
)
1807 CGContextScaleCTM( m_cgContext
, (CGFloat
) xScale
, (CGFloat
) yScale
);
1809 m_windowTransform
= CGAffineTransformScale(m_windowTransform
, (CGFloat
) xScale
, (CGFloat
) yScale
);
1812 void wxMacCoreGraphicsContext::Rotate( wxDouble angle
)
1815 CGContextRotateCTM( m_cgContext
, (CGFloat
) angle
);
1817 m_windowTransform
= CGAffineTransformRotate(m_windowTransform
, (CGFloat
) angle
);
1820 void wxMacCoreGraphicsContext::DrawBitmap( const wxBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1822 wxGraphicsBitmap bitmap
= GetRenderer()->CreateBitmap(bmp
);
1823 DrawBitmap(bitmap
, x
, y
, w
, h
);
1826 void wxMacCoreGraphicsContext::DrawBitmap( const wxGraphicsBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1830 wxMacCoreGraphicsBitmapData
* refdata
=static_cast<wxMacCoreGraphicsBitmapData
*>(bmp
.GetRefData());
1831 CGImageRef image
= refdata
->GetBitmap();
1832 CGRect r
= CGRectMake( (CGFloat
) x
, (CGFloat
) y
, (CGFloat
) w
, (CGFloat
) h
);
1833 if ( refdata
->IsMonochrome() == 1 )
1835 // is is a mask, the '1' in the mask tell where to draw the current brush
1836 if ( !m_brush
.IsNull() )
1838 if ( ((wxMacCoreGraphicsBrushData
*)m_brush
.GetRefData())->IsShading() )
1840 // TODO clip to mask
1842 CGContextSaveGState( m_cgContext );
1843 CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
1844 CGContextClip( m_cgContext );
1845 CGContextDrawShading( m_cgContext, ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->GetShading() );
1846 CGContextRestoreGState( m_cgContext);
1851 ((wxMacCoreGraphicsBrushData
*)m_brush
.GetRefData())->Apply(this);
1852 wxMacDrawCGImage( m_cgContext
, &r
, image
);
1858 wxMacDrawCGImage( m_cgContext
, &r
, image
);
1863 void wxMacCoreGraphicsContext::DrawIcon( const wxIcon
&icon
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
1867 CGRect r
= CGRectMake( (CGFloat
) 0.0 , (CGFloat
) 0.0 , (CGFloat
) w
, (CGFloat
) h
);
1868 CGContextSaveGState( m_cgContext
);
1869 CGContextTranslateCTM( m_cgContext
,(CGFloat
) x
,(CGFloat
) (y
+ h
) );
1870 CGContextScaleCTM( m_cgContext
, 1, -1 );
1872 PlotIconRefInContext( m_cgContext
, &r
, kAlignNone
, kTransformNone
,
1873 NULL
, kPlotIconRefNormalFlags
, MAC_WXHICON( icon
.GetHICON() ) );
1875 CGContextRestoreGState( m_cgContext
);
1878 void wxMacCoreGraphicsContext::PushState()
1882 CGContextSaveGState( m_cgContext
);
1885 void wxMacCoreGraphicsContext::PopState()
1889 CGContextRestoreGState( m_cgContext
);
1892 void wxMacCoreGraphicsContext::DrawText( const wxString
&str
, wxDouble x
, wxDouble y
)
1894 if ( m_font
.IsNull() )
1898 #if wxMAC_USE_CORE_TEXT
1899 if ( UMAGetSystemVersion() >= 0x1050 )
1901 wxMacCoreGraphicsFontData
* fref
= (wxMacCoreGraphicsFontData
*)m_font
.GetRefData();
1902 wxCFStringRef
text(str
, wxLocale::GetSystemEncoding() );
1903 CTFontRef font
= fref
->GetCTFont();
1904 CGColorRef col
= wxMacCreateCGColor( fref
->GetColour() );
1905 CTUnderlineStyle ustyle
= fref
->GetUnderlined() ? kCTUnderlineStyleSingle
: kCTUnderlineStyleNone
;
1906 wxCFRef
<CFNumberRef
> underlined( CFNumberCreate(NULL
, kCFNumberSInt32Type
, &ustyle
) );
1907 CFStringRef keys
[] = { kCTFontAttributeName
, kCTForegroundColorAttributeName
, kCTUnderlineStyleAttributeName
};
1908 CFTypeRef values
[] = { font
, col
, underlined
};
1909 wxCFRef
<CFDictionaryRef
> attributes( CFDictionaryCreate(kCFAllocatorDefault
, (const void**) &keys
, (const void**) &values
,
1910 WXSIZEOF( keys
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
) );
1911 wxCFRef
<CFAttributedStringRef
> attrtext( CFAttributedStringCreate(kCFAllocatorDefault
, text
, attributes
) );
1912 wxCFRef
<CTLineRef
> line( CTLineCreateWithAttributedString(attrtext
) );
1914 y
+= CTFontGetAscent(font
);
1916 CGContextSaveGState(m_cgContext
);
1917 CGContextTranslateCTM(m_cgContext
, x
, y
);
1918 CGContextScaleCTM(m_cgContext
, 1, -1);
1919 CGContextSetTextPosition(m_cgContext
, 0, 0);
1920 CTLineDraw( line
, m_cgContext
);
1921 CGContextRestoreGState(m_cgContext
);
1926 #if wxMAC_USE_ATSU_TEXT
1928 DrawText(str
, x
, y
, 0.0);
1932 #if wxMAC_USE_CG_TEXT
1933 // TODO core graphics text implementation here
1937 void wxMacCoreGraphicsContext::DrawText( const wxString
&str
, wxDouble x
, wxDouble y
, wxDouble angle
)
1939 if ( m_font
.IsNull() )
1943 #if wxMAC_USE_CORE_TEXT
1944 if ( UMAGetSystemVersion() >= 0x1050 )
1946 // default implementation takes care of rotation and calls non rotated DrawText afterwards
1947 wxGraphicsContext::DrawText( str
, x
, y
, angle
);
1951 #if wxMAC_USE_ATSU_TEXT
1953 OSStatus status
= noErr
;
1954 ATSUTextLayout atsuLayout
;
1955 wxMacUniCharBuffer
unibuf( str
);
1956 UniCharCount chars
= unibuf
.GetChars();
1958 ATSUStyle style
= (((wxMacCoreGraphicsFontData
*)m_font
.GetRefData())->GetATSUStyle());
1959 status
= ::ATSUCreateTextLayoutWithTextPtr( unibuf
.GetBuffer() , 0 , chars
, chars
, 1 ,
1960 &chars
, &style
, &atsuLayout
);
1962 wxASSERT_MSG( status
== noErr
, wxT("couldn't create the layout of the rotated text") );
1964 status
= ::ATSUSetTransientFontMatching( atsuLayout
, true );
1965 wxASSERT_MSG( status
== noErr
, wxT("couldn't setup transient font matching") );
1967 int iAngle
= int( angle
* RAD2DEG
);
1968 if ( abs(iAngle
) > 0 )
1970 Fixed atsuAngle
= IntToFixed( iAngle
);
1971 ATSUAttributeTag atsuTags
[] =
1973 kATSULineRotationTag
,
1975 ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
1979 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
1983 status
= ::ATSUSetLayoutControls(atsuLayout
, sizeof(atsuTags
) / sizeof(ATSUAttributeTag
),
1984 atsuTags
, atsuSizes
, atsuValues
);
1988 ATSUAttributeTag atsuTags
[] =
1992 ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
1994 sizeof( CGContextRef
) ,
1996 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
2000 status
= ::ATSUSetLayoutControls(atsuLayout
, sizeof(atsuTags
) / sizeof(ATSUAttributeTag
),
2001 atsuTags
, atsuSizes
, atsuValues
);
2004 ATSUTextMeasurement textBefore
, textAfter
;
2005 ATSUTextMeasurement ascent
, descent
;
2007 status
= ::ATSUGetUnjustifiedBounds( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
2008 &textBefore
, &textAfter
, &ascent
, &descent
);
2010 wxASSERT_MSG( status
== noErr
, wxT("couldn't measure the rotated text") );
2013 x
+= (int)(sin(angle
) * FixedToInt(ascent
));
2014 y
+= (int)(cos(angle
) * FixedToInt(ascent
));
2016 status
= ::ATSUMeasureTextImage( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
2017 IntToFixed(x
) , IntToFixed(y
) , &rect
);
2018 wxASSERT_MSG( status
== noErr
, wxT("couldn't measure the rotated text") );
2020 CGContextSaveGState(m_cgContext
);
2021 CGContextTranslateCTM(m_cgContext
, (CGFloat
) x
, (CGFloat
) y
);
2022 CGContextScaleCTM(m_cgContext
, 1, -1);
2023 status
= ::ATSUDrawText( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
2024 IntToFixed(0) , IntToFixed(0) );
2026 wxASSERT_MSG( status
== noErr
, wxT("couldn't draw the rotated text") );
2028 CGContextRestoreGState(m_cgContext
);
2030 ::ATSUDisposeTextLayout(atsuLayout
);
2035 #if wxMAC_USE_CG_TEXT
2036 // default implementation takes care of rotation and calls non rotated DrawText afterwards
2037 wxGraphicsContext::DrawText( str
, x
, y
, angle
);
2041 void wxMacCoreGraphicsContext::GetTextExtent( const wxString
&str
, wxDouble
*width
, wxDouble
*height
,
2042 wxDouble
*descent
, wxDouble
*externalLeading
) const
2044 wxCHECK_RET( !m_font
.IsNull(), wxT("wxDC(cg)::DoGetTextExtent - no valid font set") );
2052 if ( externalLeading
)
2053 *externalLeading
= 0;
2058 #if wxMAC_USE_CORE_TEXT
2059 if ( UMAGetSystemVersion() >= 0x1050 )
2061 wxMacCoreGraphicsFontData
* fref
= (wxMacCoreGraphicsFontData
*)m_font
.GetRefData();
2062 CTFontRef font
= fref
->GetCTFont();
2064 wxCFStringRef
text(str
, wxLocale::GetSystemEncoding() );
2065 CFStringRef keys
[] = { kCTFontAttributeName
};
2066 CFTypeRef values
[] = { font
};
2067 wxCFRef
<CFDictionaryRef
> attributes( CFDictionaryCreate(kCFAllocatorDefault
, (const void**) &keys
, (const void**) &values
,
2068 WXSIZEOF( keys
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
) );
2069 wxCFRef
<CFAttributedStringRef
> attrtext( CFAttributedStringCreate(kCFAllocatorDefault
, text
, attributes
) );
2070 wxCFRef
<CTLineRef
> line( CTLineCreateWithAttributedString(attrtext
) );
2074 w
= CTLineGetTypographicBounds(line
, &a
, &d
, &l
) ;
2080 if ( externalLeading
)
2081 *externalLeading
= l
;
2087 #if wxMAC_USE_ATSU_TEXT
2089 OSStatus status
= noErr
;
2091 ATSUTextLayout atsuLayout
;
2092 wxMacUniCharBuffer
unibuf( str
);
2093 UniCharCount chars
= unibuf
.GetChars();
2095 ATSUStyle style
= (((wxMacCoreGraphicsFontData
*)m_font
.GetRefData())->GetATSUStyle());
2096 status
= ::ATSUCreateTextLayoutWithTextPtr( unibuf
.GetBuffer() , 0 , chars
, chars
, 1 ,
2097 &chars
, &style
, &atsuLayout
);
2099 wxASSERT_MSG( status
== noErr
, wxT("couldn't create the layout of the text") );
2101 status
= ::ATSUSetTransientFontMatching( atsuLayout
, true );
2102 wxASSERT_MSG( status
== noErr
, wxT("couldn't setup transient font matching") );
2104 ATSUTextMeasurement textBefore
, textAfter
;
2105 ATSUTextMeasurement textAscent
, textDescent
;
2107 status
= ::ATSUGetUnjustifiedBounds( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
2108 &textBefore
, &textAfter
, &textAscent
, &textDescent
);
2111 *height
= FixedToInt(textAscent
+ textDescent
);
2113 *descent
= FixedToInt(textDescent
);
2114 if ( externalLeading
)
2115 *externalLeading
= 0;
2117 *width
= FixedToInt(textAfter
- textBefore
);
2119 ::ATSUDisposeTextLayout(atsuLayout
);
2124 #if wxMAC_USE_CG_TEXT
2125 // TODO core graphics text implementation here
2129 void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString
& text
, wxArrayDouble
& widths
) const
2132 widths
.Add(0, text
.length());
2137 #if wxMAC_USE_CORE_TEXT
2139 wxMacCoreGraphicsFontData
* fref
= (wxMacCoreGraphicsFontData
*)m_font
.GetRefData();
2140 CTFontRef font
= fref
->GetCTFont();
2142 wxCFStringRef
t(text
, wxLocale::GetSystemEncoding() );
2143 CFStringRef keys
[] = { kCTFontAttributeName
};
2144 CFTypeRef values
[] = { font
};
2145 wxCFRef
<CFDictionaryRef
> attributes( CFDictionaryCreate(kCFAllocatorDefault
, (const void**) &keys
, (const void**) &values
,
2146 WXSIZEOF( keys
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
) );
2147 wxCFRef
<CFAttributedStringRef
> attrtext( CFAttributedStringCreate(kCFAllocatorDefault
, t
, attributes
) );
2148 wxCFRef
<CTLineRef
> line( CTLineCreateWithAttributedString(attrtext
) );
2150 int chars
= text
.length();
2151 for ( int pos
= 0; pos
< (int)chars
; pos
++ )
2153 widths
[pos
] = CTLineGetOffsetForStringIndex( line
, pos
+1 , NULL
)+0.5;
2159 #if wxMAC_USE_ATSU_TEXT
2161 OSStatus status
= noErr
;
2162 ATSUTextLayout atsuLayout
;
2163 wxMacUniCharBuffer
unibuf( text
);
2164 UniCharCount chars
= unibuf
.GetChars();
2166 ATSUStyle style
= (((wxMacCoreGraphicsFontData
*)m_font
.GetRefData())->GetATSUStyle());
2167 status
= ::ATSUCreateTextLayoutWithTextPtr( unibuf
.GetBuffer() , 0 , chars
, chars
, 1 ,
2168 &chars
, &style
, &atsuLayout
);
2170 wxASSERT_MSG( status
== noErr
, wxT("couldn't create the layout of the text") );
2172 status
= ::ATSUSetTransientFontMatching( atsuLayout
, true );
2173 wxASSERT_MSG( status
== noErr
, wxT("couldn't setup transient font matching") );
2175 // new implementation from JS, keep old one just in case
2177 for ( int pos
= 0; pos
< (int)chars
; pos
++ )
2179 unsigned long actualNumberOfBounds
= 0;
2180 ATSTrapezoid glyphBounds
;
2182 // We get a single bound, since the text should only require one. If it requires more, there is an issue
2184 result
= ATSUGetGlyphBounds( atsuLayout
, 0, 0, kATSUFromTextBeginning
, pos
+ 1,
2185 kATSUseDeviceOrigins
, 1, &glyphBounds
, &actualNumberOfBounds
);
2186 if (result
!= noErr
|| actualNumberOfBounds
!= 1 )
2189 widths
[pos
] = FixedToInt( glyphBounds
.upperRight
.x
- glyphBounds
.upperLeft
.x
);
2190 //unsigned char uch = s[i];
2193 ATSLayoutRecord
*layoutRecords
= NULL
;
2194 ItemCount glyphCount
= 0;
2196 // Get the glyph extents
2197 OSStatus err
= ::ATSUDirectGetLayoutDataArrayPtrFromTextLayout(atsuLayout
,
2199 kATSUDirectDataLayoutRecordATSLayoutRecordCurrent
,
2203 wxASSERT(glyphCount
== (text
.length()+1));
2205 if ( err
== noErr
&& glyphCount
== (text
.length()+1))
2207 for ( int pos
= 1; pos
< (int)glyphCount
; pos
++ )
2209 widths
[pos
-1] = FixedToInt( layoutRecords
[pos
].realPos
);
2213 ::ATSUDirectReleaseLayoutDataArrayPtr(NULL
,
2214 kATSUDirectDataLayoutRecordATSLayoutRecordCurrent
,
2215 (void **) &layoutRecords
);
2217 ::ATSUDisposeTextLayout(atsuLayout
);
2220 #if wxMAC_USE_CG_TEXT
2221 // TODO core graphics text implementation here
2225 void * wxMacCoreGraphicsContext::GetNativeContext()
2230 // concatenates this transform with the current transform of this context
2231 void wxMacCoreGraphicsContext::ConcatTransform( const wxGraphicsMatrix
& matrix
)
2234 CGContextConcatCTM( m_cgContext
, *(CGAffineTransform
*) matrix
.GetNativeMatrix());
2236 m_windowTransform
= CGAffineTransformConcat(m_windowTransform
, *(CGAffineTransform
*) matrix
.GetNativeMatrix());
2239 // sets the transform of this context
2240 void wxMacCoreGraphicsContext::SetTransform( const wxGraphicsMatrix
& matrix
)
2244 CGAffineTransform transform
= CGContextGetCTM( m_cgContext
);
2245 transform
= CGAffineTransformInvert( transform
) ;
2246 CGContextConcatCTM( m_cgContext
, transform
);
2247 CGContextConcatCTM( m_cgContext
, *(CGAffineTransform
*) matrix
.GetNativeMatrix());
2251 m_windowTransform
= *(CGAffineTransform
*) matrix
.GetNativeMatrix();
2255 // gets the matrix of this context
2256 wxGraphicsMatrix
wxMacCoreGraphicsContext::GetTransform() const
2258 wxGraphicsMatrix m
= CreateMatrix();
2259 *((CGAffineTransform
*) m
.GetNativeMatrix()) = ( m_cgContext
== NULL
? m_windowTransform
:
2260 CGContextGetCTM( m_cgContext
));
2268 //-----------------------------------------------------------------------------
2269 // wxMacCoreGraphicsRenderer declaration
2270 //-----------------------------------------------------------------------------
2272 class WXDLLIMPEXP_CORE wxMacCoreGraphicsRenderer
: public wxGraphicsRenderer
2275 wxMacCoreGraphicsRenderer() {}
2277 virtual ~wxMacCoreGraphicsRenderer() {}
2281 virtual wxGraphicsContext
* CreateContext( const wxWindowDC
& dc
);
2282 virtual wxGraphicsContext
* CreateContext( const wxMemoryDC
& dc
);
2283 virtual wxGraphicsContext
* CreateContext( const wxPrinterDC
& dc
);
2285 virtual wxGraphicsContext
* CreateContextFromNativeContext( void * context
);
2287 virtual wxGraphicsContext
* CreateContextFromNativeWindow( void * window
);
2289 virtual wxGraphicsContext
* CreateContext( wxWindow
* window
);
2291 virtual wxGraphicsContext
* CreateMeasuringContext();
2295 virtual wxGraphicsPath
CreatePath();
2299 virtual wxGraphicsMatrix
CreateMatrix( wxDouble a
=1.0, wxDouble b
=0.0, wxDouble c
=0.0, wxDouble d
=1.0,
2300 wxDouble tx
=0.0, wxDouble ty
=0.0);
2303 virtual wxGraphicsPen
CreatePen(const wxPen
& pen
) ;
2305 virtual wxGraphicsBrush
CreateBrush(const wxBrush
& brush
) ;
2307 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
2308 virtual wxGraphicsBrush
CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
2309 const wxColour
&c1
, const wxColour
&c2
) ;
2311 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
2312 // with radius r and color cColor
2313 virtual wxGraphicsBrush
CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
2314 const wxColour
&oColor
, const wxColour
&cColor
) ;
2317 virtual wxGraphicsFont
CreateFont( const wxFont
&font
, const wxColour
&col
= *wxBLACK
) ;
2319 // create a native bitmap representation
2320 virtual wxGraphicsBitmap
CreateBitmap( const wxBitmap
&bitmap
) ;
2322 // create a native bitmap representation
2323 virtual wxGraphicsBitmap
CreateSubBitmap( const wxGraphicsBitmap
&bitmap
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
) ;
2325 DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacCoreGraphicsRenderer
)
2328 //-----------------------------------------------------------------------------
2329 // wxMacCoreGraphicsRenderer implementation
2330 //-----------------------------------------------------------------------------
2332 IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsRenderer
,wxGraphicsRenderer
)
2334 static wxMacCoreGraphicsRenderer gs_MacCoreGraphicsRenderer
;
2336 wxGraphicsRenderer
* wxGraphicsRenderer::GetDefaultRenderer()
2338 return &gs_MacCoreGraphicsRenderer
;
2342 extern CGContextRef
wxMacGetContextFromCurrentNSContext() ;
2345 wxGraphicsContext
* wxMacCoreGraphicsRenderer::CreateContext( const wxWindowDC
& dc
)
2347 const wxDCImpl
* impl
= dc
.GetImpl();
2348 wxWindowDCImpl
*win_impl
= wxDynamicCast( impl
, wxWindowDCImpl
);
2352 win_impl
->GetSize( &w
, &h
);
2353 CGContextRef cgctx
= 0;
2355 cgctx
= (CGContextRef
)(win_impl
->GetWindow()->MacGetCGContextRef());
2357 cgctx
= wxMacGetContextFromCurrentNSContext() ;
2359 return new wxMacCoreGraphicsContext( this, cgctx
, (wxDouble
) w
, (wxDouble
) h
);
2364 wxGraphicsContext
* wxMacCoreGraphicsRenderer::CreateContext( const wxMemoryDC
& dc
)
2367 const wxDCImpl
* impl
= dc
.GetImpl();
2368 wxMemoryDCImpl
*mem_impl
= wxDynamicCast( impl
, wxMemoryDCImpl
);
2372 mem_impl
->GetSize( &w
, &h
);
2373 return new wxMacCoreGraphicsContext( this,
2374 (CGContextRef
)(mem_impl
->GetGraphicsContext()->GetNativeContext()), (wxDouble
) w
, (wxDouble
) h
);
2380 wxGraphicsContext
* wxMacCoreGraphicsRenderer::CreateContext( const wxPrinterDC
& dc
)
2383 const wxDCImpl
* impl
= dc
.GetImpl();
2384 wxPrinterDCImpl
*print_impl
= wxDynamicCast( impl
, wxPrinterDCImpl
);
2388 print_impl
->GetSize( &w
, &h
);
2389 return new wxMacCoreGraphicsContext( this,
2390 (CGContextRef
)(print_impl
->GetGraphicsContext()->GetNativeContext()), (wxDouble
) w
, (wxDouble
) h
);
2396 wxGraphicsContext
* wxMacCoreGraphicsRenderer::CreateContextFromNativeContext( void * context
)
2398 return new wxMacCoreGraphicsContext(this,(CGContextRef
)context
);
2402 wxGraphicsContext
* wxMacCoreGraphicsRenderer::CreateContextFromNativeWindow( void * window
)
2404 return new wxMacCoreGraphicsContext(this,(WindowRef
)window
);
2407 wxGraphicsContext
* wxMacCoreGraphicsRenderer::CreateContext( wxWindow
* window
)
2409 return new wxMacCoreGraphicsContext(this, window
);
2412 wxGraphicsContext
* wxMacCoreGraphicsRenderer::CreateMeasuringContext()
2414 return new wxMacCoreGraphicsContext(this);
2419 wxGraphicsPath
wxMacCoreGraphicsRenderer::CreatePath()
2422 m
.SetRefData( new wxMacCoreGraphicsPathData(this));
2429 wxGraphicsMatrix
wxMacCoreGraphicsRenderer::CreateMatrix( wxDouble a
, wxDouble b
, wxDouble c
, wxDouble d
,
2430 wxDouble tx
, wxDouble ty
)
2433 wxMacCoreGraphicsMatrixData
* data
= new wxMacCoreGraphicsMatrixData( this );
2434 data
->Set( a
,b
,c
,d
,tx
,ty
) ;
2439 wxGraphicsPen
wxMacCoreGraphicsRenderer::CreatePen(const wxPen
& pen
)
2441 if ( !pen
.Ok() || pen
.GetStyle() == wxTRANSPARENT
)
2442 return wxNullGraphicsPen
;
2446 p
.SetRefData(new wxMacCoreGraphicsPenData( this, pen
));
2451 wxGraphicsBrush
wxMacCoreGraphicsRenderer::CreateBrush(const wxBrush
& brush
)
2453 if ( !brush
.Ok() || brush
.GetStyle() == wxTRANSPARENT
)
2454 return wxNullGraphicsBrush
;
2458 p
.SetRefData(new wxMacCoreGraphicsBrushData( this, brush
));
2463 wxGraphicsBitmap
wxMacCoreGraphicsRenderer::CreateBitmap( const wxBitmap
& bmp
)
2469 p
.SetRefData(new wxMacCoreGraphicsBitmapData( this , bmp
.CreateCGImage(), bmp
.GetDepth() == 1 ) );
2474 return wxNullGraphicsBitmap
;
2477 wxGraphicsBitmap
wxMacCoreGraphicsRenderer::CreateSubBitmap( const wxGraphicsBitmap
&bmp
, wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
2479 wxMacCoreGraphicsBitmapData
* refdata
=static_cast<wxMacCoreGraphicsBitmapData
*>(bmp
.GetRefData());
2480 CGImageRef img
= refdata
->GetBitmap();
2484 CGImageRef subimg
= CGImageCreateWithImageInRect(img
,CGRectMake( (CGFloat
) x
, (CGFloat
) y
, (CGFloat
) w
, (CGFloat
) h
));
2485 p
.SetRefData(new wxMacCoreGraphicsBitmapData( this , subimg
, refdata
->IsMonochrome() ) );
2489 return wxNullGraphicsBitmap
;
2492 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
2493 wxGraphicsBrush
wxMacCoreGraphicsRenderer::CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
2494 const wxColour
&c1
, const wxColour
&c2
)
2497 wxMacCoreGraphicsBrushData
* d
= new wxMacCoreGraphicsBrushData( this );
2498 d
->CreateLinearGradientBrush(x1
, y1
, x2
, y2
, c1
, c2
);
2503 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
2504 // with radius r and color cColor
2505 wxGraphicsBrush
wxMacCoreGraphicsRenderer::CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
2506 const wxColour
&oColor
, const wxColour
&cColor
)
2509 wxMacCoreGraphicsBrushData
* d
= new wxMacCoreGraphicsBrushData( this );
2510 d
->CreateRadialGradientBrush(xo
,yo
,xc
,yc
,radius
,oColor
,cColor
);
2516 wxGraphicsFont
wxMacCoreGraphicsRenderer::CreateFont( const wxFont
&font
, const wxColour
&col
)
2521 p
.SetRefData(new wxMacCoreGraphicsFontData( this , font
, col
));
2525 return wxNullGraphicsFont
;
2529 // CoreGraphics Helper Methods
2532 // Data Providers and Consumers
2534 size_t UMAPutBytesCFRefCallback( void *info
, const void *bytes
, size_t count
)
2536 CFMutableDataRef data
= (CFMutableDataRef
) info
;
2539 CFDataAppendBytes( data
, (const UInt8
*) bytes
, count
);
2544 void wxMacReleaseCFDataProviderCallback(void *info
,
2545 const void *WXUNUSED(data
),
2546 size_t WXUNUSED(count
))
2549 CFRelease( (CFDataRef
) info
);
2552 void wxMacReleaseCFDataConsumerCallback( void *info
)
2555 CFRelease( (CFDataRef
) info
);
2558 CGDataProviderRef
wxMacCGDataProviderCreateWithCFData( CFDataRef data
)
2563 return CGDataProviderCreateWithCFData( data
);
2566 CGDataConsumerRef
wxMacCGDataConsumerCreateWithCFData( CFMutableDataRef data
)
2571 return CGDataConsumerCreateWithCFData( data
);
2575 wxMacReleaseMemoryBufferProviderCallback(void *info
,
2576 const void * WXUNUSED_UNLESS_DEBUG(data
),
2577 size_t WXUNUSED(size
))
2579 wxMemoryBuffer
* membuf
= (wxMemoryBuffer
*) info
;
2581 wxASSERT( data
== membuf
->GetData() ) ;
2586 CGDataProviderRef
wxMacCGDataProviderCreateWithMemoryBuffer( const wxMemoryBuffer
& buf
)
2588 wxMemoryBuffer
* b
= new wxMemoryBuffer( buf
);
2589 if ( b
->GetDataLen() == 0 )
2592 return CGDataProviderCreateWithData( b
, (const void *) b
->GetData() , b
->GetDataLen() ,
2593 wxMacReleaseMemoryBufferProviderCallback
);