+
+void wxMacCGContext::PushState()
+{
+ CGContextSaveGState( m_cgContext );
+}
+
+void wxMacCGContext::PopState()
+{
+ CGContextRestoreGState( m_cgContext );
+}
+
+void wxMacCGContext::SetTextColor( const wxColour &col )
+{
+ m_textForegroundColor = col ;
+}
+
+#pragma mark -
+#pragma mark wxMacCGPattern, ImagePattern, HatchPattern classes
+
+// CGPattern wrapper class: always allocate on heap, never call destructor
+
+class wxMacCGPattern
+{
+public :
+ wxMacCGPattern() {}
+
+ // 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 ~wxMacCGPattern()
+ {
+ // as this is called only when the m_patternRef is been released;
+ // don't release it again
+ }
+
+ static void _Render( void *info, CGContextRef ctxRef )
+ {
+ wxMacCGPattern* self = (wxMacCGPattern*) info ;
+ if ( self && ctxRef )
+ self->Render( ctxRef ) ;
+ }
+
+ static void _Dispose( void *info )
+ {
+ wxMacCGPattern* self = (wxMacCGPattern*) info ;
+ delete self ;
+ }
+
+ CGPatternRef m_patternRef ;
+
+ static const CGPatternCallbacks ms_Callbacks ;
+} ;
+
+const CGPatternCallbacks wxMacCGPattern::ms_Callbacks = { 0, &wxMacCGPattern::_Render, &wxMacCGPattern::_Dispose };
+
+class ImagePattern : public wxMacCGPattern
+{
+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 , &wxMacCGPattern::ms_Callbacks ) ;
+ }
+ }
+
+ virtual ~ImagePattern()
+ {
+ if ( m_image )
+ CGImageRelease( m_image ) ;
+ }
+
+ CGImageRef m_image ;
+ CGRect m_imageBounds ;
+} ;
+
+class HatchPattern : public wxMacCGPattern
+{
+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 , &wxMacCGPattern::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 ( UMAGetSystemVersion() >= 0x1040 )
+ {
+ 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 ;
+};
+
+#pragma mark -