+#if !defined( __DARWIN__ ) || defined(__MWERKS__)
+#ifndef M_PI
+const double M_PI = 3.14159265358979;
+#endif
+#endif
+
+static const double RAD2DEG = 180.0 / M_PI;
+
+//
+// Pen, Brushes and Fonts
+//
+
+#pragma mark -
+#pragma mark wxMacCoreGraphicsPattern, ImagePattern, HatchPattern classes
+
+// CGPattern wrapper class: always allocate on heap, never call destructor
+
+class wxMacCoreGraphicsPattern
+{
+public :
+ wxMacCoreGraphicsPattern() {}
+
+ // is guaranteed to be called only with a non-Null CGContextRef
+ virtual void Render( CGContextRef ctxRef ) = 0;
+
+ operator CGPatternRef() const { return m_patternRef; }
+
+protected :
+ virtual ~wxMacCoreGraphicsPattern()
+ {
+ // as this is called only when the m_patternRef is been released;
+ // don't release it again
+ }
+
+ static void _Render( void *info, CGContextRef ctxRef )
+ {
+ wxMacCoreGraphicsPattern* self = (wxMacCoreGraphicsPattern*) info;
+ if ( self && ctxRef )
+ self->Render( ctxRef );
+ }
+
+ static void _Dispose( void *info )
+ {
+ wxMacCoreGraphicsPattern* self = (wxMacCoreGraphicsPattern*) info;
+ delete self;
+ }
+
+ CGPatternRef m_patternRef;
+
+ static const CGPatternCallbacks ms_Callbacks;
+};
+
+const CGPatternCallbacks wxMacCoreGraphicsPattern::ms_Callbacks = { 0, &wxMacCoreGraphicsPattern::_Render, &wxMacCoreGraphicsPattern::_Dispose };
+
+class ImagePattern : public wxMacCoreGraphicsPattern
+{
+public :
+ ImagePattern( const wxBitmap* bmp , const CGAffineTransform& transform )
+ {
+ wxASSERT( bmp && bmp->Ok() );
+
+ Init( (CGImageRef) bmp->CGImageCreate() , transform );
+ }
+
+ // ImagePattern takes ownership of CGImageRef passed in
+ ImagePattern( CGImageRef image , const CGAffineTransform& transform )
+ {
+ if ( image )
+ CFRetain( image );
+
+ Init( image , transform );
+ }
+
+ virtual void Render( CGContextRef ctxRef )
+ {
+ if (m_image != NULL)
+ HIViewDrawCGImage( ctxRef, &m_imageBounds, m_image );
+ }
+
+protected :
+ void Init( CGImageRef image, const CGAffineTransform& transform )
+ {
+ m_image = image;
+ if ( m_image )
+ {
+ m_imageBounds = CGRectMake( 0.0, 0.0, (CGFloat)CGImageGetWidth( m_image ), (CGFloat)CGImageGetHeight( m_image ) );
+ m_patternRef = CGPatternCreate(
+ this , m_imageBounds, transform ,
+ m_imageBounds.size.width, m_imageBounds.size.height,
+ kCGPatternTilingNoDistortion, true , &wxMacCoreGraphicsPattern::ms_Callbacks );
+ }
+ }
+
+ virtual ~ImagePattern()
+ {
+ if ( m_image )
+ CGImageRelease( m_image );
+ }
+
+ CGImageRef m_image;
+ CGRect m_imageBounds;
+};
+
+class HatchPattern : public wxMacCoreGraphicsPattern
+{
+public :
+ HatchPattern( int hatchstyle, const CGAffineTransform& transform )
+ {
+ m_hatch = hatchstyle;
+ m_imageBounds = CGRectMake( 0.0, 0.0, 8.0 , 8.0 );
+ m_patternRef = CGPatternCreate(
+ this , m_imageBounds, transform ,
+ m_imageBounds.size.width, m_imageBounds.size.height,
+ kCGPatternTilingNoDistortion, false , &wxMacCoreGraphicsPattern::ms_Callbacks );
+ }
+
+ void StrokeLineSegments( CGContextRef ctxRef , const CGPoint pts[] , size_t count )
+ {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if ( CGContextStrokeLineSegments!=NULL )
+ {
+ CGContextStrokeLineSegments( ctxRef , pts , count );
+ }
+ else
+#endif
+ {
+ CGContextBeginPath( ctxRef );
+ for (size_t i = 0; i < count; i += 2)
+ {
+ CGContextMoveToPoint(ctxRef, pts[i].x, pts[i].y);
+ CGContextAddLineToPoint(ctxRef, pts[i+1].x, pts[i+1].y);
+ }
+ CGContextStrokePath(ctxRef);
+ }
+ }
+
+ virtual void Render( CGContextRef ctxRef )
+ {
+ switch ( m_hatch )
+ {
+ case wxBDIAGONAL_HATCH :
+ {
+ CGPoint pts[] =
+ {
+ { 8.0 , 0.0 } , { 0.0 , 8.0 }
+ };
+ StrokeLineSegments( ctxRef , pts , 2 );
+ }
+ break;
+
+ case wxCROSSDIAG_HATCH :
+ {
+ CGPoint pts[] =
+ {
+ { 0.0 , 0.0 } , { 8.0 , 8.0 } ,
+ { 8.0 , 0.0 } , { 0.0 , 8.0 }
+ };
+ StrokeLineSegments( ctxRef , pts , 4 );
+ }
+ break;
+
+ case wxFDIAGONAL_HATCH :
+ {
+ CGPoint pts[] =
+ {
+ { 0.0 , 0.0 } , { 8.0 , 8.0 }
+ };
+ StrokeLineSegments( ctxRef , pts , 2 );
+ }
+ break;
+
+ case wxCROSS_HATCH :
+ {
+ CGPoint pts[] =
+ {
+ { 0.0 , 4.0 } , { 8.0 , 4.0 } ,
+ { 4.0 , 0.0 } , { 4.0 , 8.0 } ,
+ };
+ StrokeLineSegments( ctxRef , pts , 4 );
+ }
+ break;
+
+ case wxHORIZONTAL_HATCH :
+ {
+ CGPoint pts[] =
+ {
+ { 0.0 , 4.0 } , { 8.0 , 4.0 } ,
+ };
+ StrokeLineSegments( ctxRef , pts , 2 );
+ }
+ break;
+
+ case wxVERTICAL_HATCH :
+ {
+ CGPoint pts[] =
+ {
+ { 4.0 , 0.0 } , { 4.0 , 8.0 } ,
+ };
+ StrokeLineSegments( ctxRef , pts , 2 );
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+protected :
+ virtual ~HatchPattern() {}
+
+ CGRect m_imageBounds;
+ int m_hatch;
+};
+
+class wxMacCoreGraphicsPenData : public wxGraphicsObjectRefData
+{
+public:
+ wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer, const wxPen &pen );
+ ~wxMacCoreGraphicsPenData();
+
+ void Init();
+ virtual void Apply( wxGraphicsContext* context );
+ virtual wxDouble GetWidth() { return m_width; }
+
+protected :
+ CGLineCap m_cap;
+ wxMacCFRefHolder<CGColorRef> m_color;
+ wxMacCFRefHolder<CGColorSpaceRef> m_colorSpace;
+
+ CGLineJoin m_join;
+ CGFloat m_width;
+
+ int m_count;
+ const CGFloat *m_lengths;
+ CGFloat *m_userLengths;
+
+
+ bool m_isPattern;
+ wxMacCFRefHolder<CGPatternRef> m_pattern;
+ CGFloat* m_patternColorComponents;
+};
+
+wxMacCoreGraphicsPenData::wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer, const wxPen &pen ) :
+ wxGraphicsObjectRefData( renderer )
+{
+ Init();
+
+ CGFloat components[4] = { pen.GetColour().Red() / 255.0 , pen.GetColour().Green() / 255.0 ,
+ pen.GetColour().Blue() / 255.0 , pen.GetColour().Alpha() / 255.0 } ;
+ m_color.Set( CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ) ;
+
+ // TODO: * m_dc->m_scaleX
+ m_width = pen.GetWidth();
+ if (m_width <= 0.0)
+ m_width = 0.1;
+
+ switch ( pen.GetCap() )
+ {
+ case wxCAP_ROUND :
+ m_cap = kCGLineCapRound;
+ break;
+
+ case wxCAP_PROJECTING :
+ m_cap = kCGLineCapSquare;
+ break;
+
+ case wxCAP_BUTT :
+ m_cap = kCGLineCapButt;
+ break;
+
+ default :
+ m_cap = kCGLineCapButt;
+ break;
+ }
+
+ switch ( pen.GetJoin() )
+ {
+ case wxJOIN_BEVEL :
+ m_join = kCGLineJoinBevel;
+ break;
+
+ case wxJOIN_MITER :
+ m_join = kCGLineJoinMiter;
+ break;
+
+ case wxJOIN_ROUND :
+ m_join = kCGLineJoinRound;
+ break;
+
+ default :
+ m_join = kCGLineJoinMiter;
+ break;
+ }
+
+ const CGFloat dashUnit = m_width < 1.0 ? 1.0 : m_width;
+
+ const CGFloat dotted[] = { dashUnit , dashUnit + 2.0 };
+ static const CGFloat short_dashed[] = { 9.0 , 6.0 };
+ static const CGFloat dashed[] = { 19.0 , 9.0 };
+ static const CGFloat dotted_dashed[] = { 9.0 , 6.0 , 3.0 , 3.0 };
+
+ switch ( pen.GetStyle() )
+ {
+ case wxSOLID :
+ break;
+
+ case wxDOT :
+ m_count = WXSIZEOF(dotted);
+ m_userLengths = new CGFloat[ m_count ] ;
+ memcpy( m_userLengths, dotted, sizeof(dotted) );
+ m_lengths = m_userLengths;
+ break;
+
+ case wxLONG_DASH :
+ m_count = WXSIZEOF(dashed);
+ m_lengths = dashed;
+ break;
+
+ case wxSHORT_DASH :
+ m_count = WXSIZEOF(short_dashed);
+ m_lengths = short_dashed;
+ break;
+
+ case wxDOT_DASH :
+ m_count = WXSIZEOF(dotted_dashed);
+ m_lengths = dotted_dashed;
+ break;
+
+ case wxUSER_DASH :
+ wxDash *dashes;
+ m_count = pen.GetDashes( &dashes );
+ if ((dashes != NULL) && (m_count > 0))
+ {
+ m_userLengths = new CGFloat[m_count];
+ for ( int i = 0; i < m_count; ++i )
+ {
+ m_userLengths[i] = dashes[i] * dashUnit;
+
+ if ( i % 2 == 1 && m_userLengths[i] < dashUnit + 2.0 )
+ m_userLengths[i] = dashUnit + 2.0;
+ else if ( i % 2 == 0 && m_userLengths[i] < dashUnit )
+ m_userLengths[i] = dashUnit;
+ }
+ }
+ m_lengths = m_userLengths;
+ break;
+
+ case wxSTIPPLE :
+ {
+ wxBitmap* bmp = pen.GetStipple();
+ if ( bmp && bmp->Ok() )
+ {
+ m_colorSpace.Set( CGColorSpaceCreatePattern( NULL ) );
+ m_pattern.Set( *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) );
+ m_patternColorComponents = new CGFloat[1] ;
+ m_patternColorComponents[0] = 1.0;
+ m_isPattern = true;
+ }
+ }
+ break;
+
+ default :
+ {
+ m_isPattern = true;
+ m_colorSpace.Set( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
+ m_pattern.Set( *( new HatchPattern( pen.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) );
+ m_patternColorComponents = new CGFloat[4] ;
+ m_patternColorComponents[0] = pen.GetColour().Red() / 255.0;
+ m_patternColorComponents[1] = pen.GetColour().Green() / 255.0;
+ m_patternColorComponents[2] = pen.GetColour().Blue() / 255.0;
+ m_patternColorComponents[3] = pen.GetColour().Alpha() / 255.0;
+ }
+ break;
+ }
+ if ((m_lengths != NULL) && (m_count > 0))
+ {
+ // force the line cap, otherwise we get artifacts (overlaps) and just solid lines
+ m_cap = kCGLineCapButt;
+ }
+}
+
+wxMacCoreGraphicsPenData::~wxMacCoreGraphicsPenData()
+{
+ delete[] m_userLengths;
+ delete[] m_patternColorComponents;
+}
+
+void wxMacCoreGraphicsPenData::Init()
+{
+ m_lengths = NULL;
+ m_userLengths = NULL;
+ m_width = 0;
+ m_count = 0;
+ m_patternColorComponents = NULL;
+ m_isPattern = false;
+}
+
+void wxMacCoreGraphicsPenData::Apply( wxGraphicsContext* context )
+{
+ CGContextRef cg = (CGContextRef) context->GetNativeContext();
+ CGContextSetLineWidth( cg , m_width );
+ CGContextSetLineJoin( cg , m_join );
+
+ CGContextSetLineDash( cg , 0 , m_lengths , m_count );
+ CGContextSetLineCap( cg , m_cap );
+
+ if ( m_isPattern )
+ {
+ CGAffineTransform matrix = CGContextGetCTM( cg );
+ CGContextSetPatternPhase( cg, CGSizeMake(matrix.tx, matrix.ty) );
+ CGContextSetStrokeColorSpace( cg , m_colorSpace );
+ CGContextSetStrokePattern( cg, m_pattern , m_patternColorComponents );
+ }
+ else
+ {
+ if ( context->GetLogicalFunction() == wxINVERT || context->GetLogicalFunction() == wxXOR )
+ {
+ CGContextSetRGBStrokeColor( cg , 1.0, 1.0 , 1.0, 1.0 );
+ }
+ else
+ CGContextSetStrokeColorWithColor( cg , m_color );
+ }
+}
+
+//
+// Brush
+//
+
+static const char *gs_stripedback_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"4 4 2 1",
+". c #F0F0F0",
+"X c #ECECEC",
+/* pixels */
+"....",
+"....",
+"XXXX",
+"XXXX"
+};
+
+wxBitmap gs_stripedback_bmp( wxImage( (const char* const* ) gs_stripedback_xpm ), -1 ) ;
+
+wxMacCoreGraphicsColour::~wxMacCoreGraphicsColour()
+{
+ delete[] m_patternColorComponents;
+}
+
+void wxMacCoreGraphicsColour::Init()
+{
+ m_isPattern = false;
+ m_patternColorComponents = NULL;
+}
+
+void wxMacCoreGraphicsColour::Apply( CGContextRef cgContext )
+{
+ if ( m_isPattern )
+ {
+ CGAffineTransform matrix = CGContextGetCTM( cgContext );
+ CGContextSetPatternPhase( cgContext, CGSizeMake(matrix.tx, matrix.ty) );
+ CGContextSetFillColorSpace( cgContext , m_colorSpace );
+ CGContextSetFillPattern( cgContext, m_pattern , m_patternColorComponents );
+ }
+ else
+ {
+ CGContextSetFillColorWithColor( cgContext, m_color );
+ }
+}
+
+wxMacCoreGraphicsColour::wxMacCoreGraphicsColour()
+{
+ Init();
+}
+
+wxMacCoreGraphicsColour::wxMacCoreGraphicsColour( const wxBrush &brush )
+{
+ Init();
+ if ( brush.GetStyle() == wxSOLID )
+ {
+ if ( brush.MacGetBrushKind() == kwxMacBrushTheme )
+ {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if ( UMAGetSystemVersion() >= 0x1040 )
+ {
+ CGColorRef color ;
+ HIThemeBrushCreateCGColor( brush.MacGetTheme(), &color );
+ m_color.Set( color ) ;
+ }
+ else
+#endif
+ {
+ if( brush.MacGetTheme() == kThemeBrushDialogBackgroundActive )
+ {
+ // striped background is a pattern, we have to emulate it
+
+ m_isPattern = true;
+ m_patternColorComponents = new CGFloat[1] ;
+ m_patternColorComponents[0] = 1.0;
+ m_colorSpace.Set( CGColorSpaceCreatePattern( NULL ) );
+ m_pattern.Set( *( new ImagePattern( &gs_stripedback_bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) );
+ }
+ else
+ {
+ // as close as we can get, unfortunately < 10.4 things get difficult
+ RGBColor color;
+ GetThemeBrushAsColor( brush.MacGetTheme(), 32, true, &color );
+ CGFloat components[4] = { (CGFloat) color.red / 65536,
+ (CGFloat) color.green / 65536, (CGFloat) color.blue / 65536, 1 } ;
+ m_color.Set( CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ) ;
+ }
+ }
+ }
+ else
+ {
+ CGFloat components[4] = { brush.GetColour().Red() / 255.0 , brush.GetColour().Green() / 255.0 ,
+ brush.GetColour().Blue() / 255.0 , brush.GetColour().Alpha() / 255.0 } ;
+ m_color.Set( CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ) ;
+ }
+ }
+ else if ( brush.IsHatch() )
+ {
+ m_isPattern = true;
+ m_colorSpace.Set( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
+ m_pattern.Set( *( new HatchPattern( brush.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) );
+
+ m_patternColorComponents = new CGFloat[4] ;
+ m_patternColorComponents[0] = brush.GetColour().Red() / 255.0;
+ m_patternColorComponents[1] = brush.GetColour().Green() / 255.0;
+ m_patternColorComponents[2] = brush.GetColour().Blue() / 255.0;
+ m_patternColorComponents[3] = brush.GetColour().Alpha() / 255.0;
+ }
+ else
+ {
+ // now brush is a bitmap
+ wxBitmap* bmp = brush.GetStipple();
+ if ( bmp && bmp->Ok() )
+ {
+ m_isPattern = true;
+ m_patternColorComponents = new CGFloat[1] ;
+ m_patternColorComponents[0] = 1.0;
+ m_colorSpace.Set( CGColorSpaceCreatePattern( NULL ) );
+ m_pattern.Set( *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) );
+ }
+ }
+}
+
+class wxMacCoreGraphicsBrushData : public wxGraphicsObjectRefData
+{
+public:
+ wxMacCoreGraphicsBrushData( wxGraphicsRenderer* renderer );
+ wxMacCoreGraphicsBrushData( wxGraphicsRenderer* renderer, const wxBrush &brush );
+ ~wxMacCoreGraphicsBrushData ();
+
+ virtual void Apply( wxGraphicsContext* context );
+ void CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
+ const wxColour&c1, const wxColour&c2 );
+ void CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
+ const wxColour &oColor, const wxColour &cColor );
+
+ virtual bool IsShading() { return m_isShading; }
+ CGShadingRef GetShading() { return m_shading; }
+protected:
+ CGFunctionRef CreateGradientFunction( const wxColour& c1, const wxColour& c2 );
+ static void CalculateShadingValues (void *info, const CGFloat *in, CGFloat *out);
+ virtual void Init();
+
+ wxMacCoreGraphicsColour m_cgColor;
+
+ bool m_isShading;
+ CGFunctionRef m_gradientFunction;
+ CGShadingRef m_shading;
+ CGFloat *m_gradientComponents;
+};
+
+wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData( wxGraphicsRenderer* renderer) : wxGraphicsObjectRefData( renderer )
+{
+ Init();
+}
+
+void wxMacCoreGraphicsBrushData::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
+ const wxColour&c1, const wxColour&c2 )
+{
+ m_gradientFunction = CreateGradientFunction( c1, c2 );
+ m_shading = CGShadingCreateAxial( wxMacGetGenericRGBColorSpace(), CGPointMake(x1,y1), CGPointMake(x2,y2), m_gradientFunction, true, true ) ;
+ m_isShading = true ;
+}
+
+void wxMacCoreGraphicsBrushData::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
+ const wxColour &oColor, const wxColour &cColor )
+{
+ m_gradientFunction = CreateGradientFunction( oColor, cColor );
+ m_shading = CGShadingCreateRadial( wxMacGetGenericRGBColorSpace(), CGPointMake(xo,yo), 0, CGPointMake(xc,yc), radius, m_gradientFunction, true, true ) ;
+ m_isShading = true ;
+}
+
+wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData(wxGraphicsRenderer* renderer, const wxBrush &brush) : wxGraphicsObjectRefData( renderer ),
+ m_cgColor( brush )
+{
+ Init();
+
+}
+
+wxMacCoreGraphicsBrushData::~wxMacCoreGraphicsBrushData()
+{
+ if ( m_shading )
+ CGShadingRelease(m_shading);
+
+ if( m_gradientFunction )
+ CGFunctionRelease(m_gradientFunction);
+
+ delete[] m_gradientComponents;
+}
+
+void wxMacCoreGraphicsBrushData::Init()
+{
+ m_gradientFunction = NULL;
+ m_shading = NULL;
+ m_gradientComponents = NULL;
+ m_isShading = false;
+}
+
+void wxMacCoreGraphicsBrushData::Apply( wxGraphicsContext* context )
+{
+ CGContextRef cg = (CGContextRef) context->GetNativeContext();
+
+ if ( m_isShading )
+ {
+ // nothing to set as shades are processed by clipping using the path and filling
+ }
+ else
+ {
+ m_cgColor.Apply( cg );
+ }
+}
+
+void wxMacCoreGraphicsBrushData::CalculateShadingValues (void *info, const CGFloat *in, CGFloat *out)
+{
+ CGFloat* colors = (CGFloat*) info ;
+ CGFloat f = *in;
+ for( int i = 0 ; i < 4 ; ++i )
+ {
+ out[i] = colors[i] + ( colors[4+i] - colors[i] ) * f;
+ }
+}
+
+CGFunctionRef wxMacCoreGraphicsBrushData::CreateGradientFunction( const wxColour& c1, const wxColour& c2 )
+{
+ static const CGFunctionCallbacks callbacks = { 0, &CalculateShadingValues, NULL };
+ static const CGFloat input_value_range [2] = { 0, 1 };
+ static const CGFloat output_value_ranges [8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
+ m_gradientComponents = new CGFloat[8] ;
+ m_gradientComponents[0] = c1.Red() / 255.0;
+ m_gradientComponents[1] = c1.Green() / 255.0;
+ m_gradientComponents[2] = c1.Blue() / 255.0;
+ m_gradientComponents[3] = c1.Alpha() / 255.0;
+ m_gradientComponents[4] = c2.Red() / 255.0;
+ m_gradientComponents[5] = c2.Green() / 255.0;
+ m_gradientComponents[6] = c2.Blue() / 255.0;
+ m_gradientComponents[7] = c2.Alpha() / 255.0;
+
+ return CGFunctionCreate ( m_gradientComponents, 1,
+ input_value_range,
+ 4,
+ output_value_ranges,
+ &callbacks);
+}
+
+//
+// Font
+//
+
+class wxMacCoreGraphicsFontData : public wxGraphicsObjectRefData
+{
+public:
+ wxMacCoreGraphicsFontData( wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col );
+ ~wxMacCoreGraphicsFontData();
+
+ virtual ATSUStyle GetATSUStyle() { return m_macATSUIStyle; }
+private :
+ ATSUStyle m_macATSUIStyle;
+};
+
+wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col) : wxGraphicsObjectRefData( renderer )
+{
+ m_macATSUIStyle = NULL;
+
+ OSStatus status;
+
+ status = ATSUCreateAndCopyStyle( (ATSUStyle) font.MacGetATSUStyle() , &m_macATSUIStyle );
+
+ wxASSERT_MSG( status == noErr, wxT("couldn't create ATSU style") );
+
+ // we need the scale here ...
+
+ Fixed atsuSize = IntToFixed( int( 1 * font.MacGetFontSize()) );
+ RGBColor atsuColor = MAC_WXCOLORREF( col.GetPixel() );
+ ATSUAttributeTag atsuTags[] =
+ {
+ kATSUSizeTag ,
+ kATSUColorTag ,
+ };
+ ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
+ {
+ sizeof( Fixed ) ,
+ sizeof( RGBColor ) ,
+ };
+ ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
+ {
+ &atsuSize ,
+ &atsuColor ,
+ };
+
+ status = ::ATSUSetAttributes(
+ m_macATSUIStyle, sizeof(atsuTags) / sizeof(ATSUAttributeTag) ,
+ atsuTags, atsuSizes, atsuValues);
+
+ wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") );
+}
+
+wxMacCoreGraphicsFontData::~wxMacCoreGraphicsFontData()
+{
+ if ( m_macATSUIStyle )
+ {
+ ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
+ m_macATSUIStyle = NULL;
+ }
+}
+
+//
+// Graphics Matrix
+//
+
+//-----------------------------------------------------------------------------
+// wxMacCoreGraphicsMatrix declaration
+//-----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_CORE wxMacCoreGraphicsMatrixData : public wxGraphicsMatrixData
+{
+public :
+ wxMacCoreGraphicsMatrixData(wxGraphicsRenderer* renderer) ;
+
+ virtual ~wxMacCoreGraphicsMatrixData() ;
+
+ virtual wxGraphicsObjectRefData *Clone() const ;
+
+ // concatenates the matrix
+ virtual void Concat( const wxGraphicsMatrixData *t );
+
+ // sets the matrix to the respective values
+ virtual void Set(wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
+ wxDouble tx=0.0, wxDouble ty=0.0);
+
+ // gets the component valuess of the matrix
+ virtual void Get(wxDouble* a=NULL, wxDouble* b=NULL, wxDouble* c=NULL,
+ wxDouble* d=NULL, wxDouble* tx=NULL, wxDouble* ty=NULL) const;
+
+ // makes this the inverse matrix
+ virtual void Invert();
+
+ // returns true if the elements of the transformation matrix are equal ?
+ virtual bool IsEqual( const wxGraphicsMatrixData* t) const ;
+
+ // return true if this is the identity matrix
+ virtual bool IsIdentity() const;
+
+ //
+ // transformation
+ //
+
+ // add the translation to this matrix
+ virtual void Translate( wxDouble dx , wxDouble dy );
+
+ // add the scale to this matrix
+ virtual void Scale( wxDouble xScale , wxDouble yScale );
+
+ // add the rotation to this matrix (radians)
+ virtual void Rotate( wxDouble angle );
+
+ //
+ // apply the transforms
+ //
+
+ // applies that matrix to the point
+ virtual void TransformPoint( wxDouble *x, wxDouble *y ) const;
+
+ // applies the matrix except for translations
+ virtual void TransformDistance( wxDouble *dx, wxDouble *dy ) const;
+
+ // returns the native representation
+ virtual void * GetNativeMatrix() const;
+
+private :
+ CGAffineTransform m_matrix;
+} ;
+
+//-----------------------------------------------------------------------------
+// wxMacCoreGraphicsMatrix implementation
+//-----------------------------------------------------------------------------
+
+wxMacCoreGraphicsMatrixData::wxMacCoreGraphicsMatrixData(wxGraphicsRenderer* renderer) : wxGraphicsMatrixData(renderer)
+{
+}
+
+wxMacCoreGraphicsMatrixData::~wxMacCoreGraphicsMatrixData()
+{
+}
+
+wxGraphicsObjectRefData *wxMacCoreGraphicsMatrixData::Clone() const
+{
+ wxMacCoreGraphicsMatrixData* m = new wxMacCoreGraphicsMatrixData(GetRenderer()) ;
+ m->m_matrix = m_matrix ;
+ return m;
+}
+
+// concatenates the matrix
+void wxMacCoreGraphicsMatrixData::Concat( const wxGraphicsMatrixData *t )
+{
+ m_matrix = CGAffineTransformConcat(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix()) );
+}
+
+// sets the matrix to the respective values
+void wxMacCoreGraphicsMatrixData::Set(wxDouble a, wxDouble b, wxDouble c, wxDouble d,
+ wxDouble tx, wxDouble ty)
+{
+ m_matrix = CGAffineTransformMake(a,b,c,d,tx,ty);
+}
+
+// gets the component valuess of the matrix
+void wxMacCoreGraphicsMatrixData::Get(wxDouble* a, wxDouble* b, wxDouble* c,
+ wxDouble* d, wxDouble* tx, wxDouble* ty) const
+{
+ if (a) *a = m_matrix.a;
+ if (b) *b = m_matrix.b;
+ if (c) *c = m_matrix.c;
+ if (d) *d = m_matrix.d;
+ if (tx) *tx= m_matrix.tx;
+ if (ty) *ty= m_matrix.ty;
+}
+
+// makes this the inverse matrix
+void wxMacCoreGraphicsMatrixData::Invert()
+{
+ m_matrix = CGAffineTransformInvert( m_matrix );
+}
+
+// returns true if the elements of the transformation matrix are equal ?
+bool wxMacCoreGraphicsMatrixData::IsEqual( const wxGraphicsMatrixData* t) const
+{
+ const CGAffineTransform* tm = (CGAffineTransform*) t->GetNativeMatrix();
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if ( CGAffineTransformEqualToTransform!=NULL )
+ {
+ return CGAffineTransformEqualToTransform(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix()));
+ }
+ else