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" 
  16 #if wxMAC_USE_CORE_GRAPHICS 
  20     #include "wx/dcmemory.h" 
  21     #include "wx/region.h" 
  24 #include "wx/mac/uma.h" 
  29         // in case our functions were defined outside std, we make it known all the same 
  35 #include "wx/mac/private.h" 
  38 #ifndef wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 
  39 #define wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 0 
  42 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 
  43 typedef float CGFloat 
; 
  46 //----------------------------------------------------------------------------- 
  48 //----------------------------------------------------------------------------- 
  50 #if !defined( __DARWIN__ ) || defined(__MWERKS__) 
  52 const double M_PI 
= 3.14159265358979 ; 
  56 static const double RAD2DEG 
= 180.0 / M_PI
; 
  61 // The textctrl implementation still needs that (needs what?) for the non-HIView implementation 
  63 wxMacWindowClipper::wxMacWindowClipper( const wxWindow
* win 
) : 
  64     wxMacPortSaver( (GrafPtr
) GetWindowPort( (WindowRef
) win
->MacGetTopLevelWindowRef() ) ) 
  66     m_newPort 
= (GrafPtr
) GetWindowPort( (WindowRef
) win
->MacGetTopLevelWindowRef() ) ; 
  67     m_formerClip 
= NewRgn() ; 
  68     m_newClip 
= NewRgn() ; 
  69     GetClip( m_formerClip 
) ; 
  73         // guard against half constructed objects, this just leads to a empty clip 
  77             win
->MacWindowToRootWindow( &x
, &y 
) ; 
  79             // get area including focus rect 
  80             CopyRgn( (RgnHandle
) ((wxWindow
*)win
)->MacGetVisibleRegion(true).GetWXHRGN() , m_newClip 
) ; 
  81             if ( !EmptyRgn( m_newClip 
) ) 
  82                 OffsetRgn( m_newClip 
, x 
, y 
) ; 
  85         SetClip( m_newClip 
) ; 
  89 wxMacWindowClipper::~wxMacWindowClipper() 
  91     SetPort( m_newPort 
) ; 
  92     SetClip( m_formerClip 
) ; 
  93     DisposeRgn( m_newClip 
) ; 
  94     DisposeRgn( m_formerClip 
) ; 
  97 wxMacWindowStateSaver::wxMacWindowStateSaver( const wxWindow
* win 
) : 
  98     wxMacWindowClipper( win 
) 
 100     // the port is already set at this point 
 101     m_newPort 
= (GrafPtr
) GetWindowPort( (WindowRef
) win
->MacGetTopLevelWindowRef() ) ; 
 102     GetThemeDrawingState( &m_themeDrawingState 
) ; 
 105 wxMacWindowStateSaver::~wxMacWindowStateSaver() 
 107     SetPort( m_newPort 
) ; 
 108     SetThemeDrawingState( m_themeDrawingState 
, true ) ; 
 111 // minimal implementation only used for appearance drawing < 10.3 
 113 #ifndef wxMAC_USE_CORE_GRAPHICS 
 114 wxMacPortSetter::wxMacPortSetter( const wxDC
* dc 
) : 
 115     m_ph( (GrafPtr
) dc
->m_macPort 
) 
 117     wxASSERT( dc
->Ok() ) ; 
 120 //    dc->MacSetupPort(&m_ph) ; 
 123 wxMacPortSetter::~wxMacPortSetter() 
 125 //    m_dc->MacCleanupPort(&m_ph) ; 
 132 //----------------------------------------------------------------------------- 
 134 //----------------------------------------------------------------------------- 
 136 static inline double DegToRad(double deg
) { return (deg 
* M_PI
) / 180.0; } 
 138 //----------------------------------------------------------------------------- 
 139 // device context implementation 
 141 // more and more of the dc functionality should be implemented by calling 
 142 // the appropricate wxMacCGContext, but we will have to do that step by step 
 143 // also coordinate conversions should be moved to native matrix ops 
 144 //----------------------------------------------------------------------------- 
 146 // we always stock two context states, one at entry, to be able to preserve the 
 147 // state we were called with, the other one after changing to HI Graphics orientation 
 148 // (this one is used for getting back clippings etc) 
 150 //----------------------------------------------------------------------------- 
 151 // wxGraphicPath implementation 
 152 //----------------------------------------------------------------------------- 
 154 #if !wxUSE_GRAPHICS_CONTEXT 
 156 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
) 
 158 wxMacCGPath::wxMacCGPath() 
 160     m_path 
= CGPathCreateMutable() ; 
 163 wxMacCGPath::~wxMacCGPath() 
 165     CGPathRelease( m_path 
) ; 
 168 // opens (starts) a new subpath 
 169 void wxMacCGPath::MoveToPoint( wxCoord x1 
, wxCoord y1 
) 
 171     CGPathMoveToPoint( m_path 
, NULL 
, x1 
, y1 
) ; 
 174 void wxMacCGPath::AddLineToPoint( wxCoord x1 
, wxCoord y1 
) 
 176     CGPathAddLineToPoint( m_path 
, NULL 
, x1 
, y1 
) ; 
 179 void wxMacCGPath::AddQuadCurveToPoint( wxCoord cx1
, wxCoord cy1
, wxCoord x1
, wxCoord y1 
) 
 181     CGPathAddQuadCurveToPoint( m_path 
, NULL 
, cx1 
, cy1 
, x1 
, y1 
); 
 184 void wxMacCGPath::AddRectangle( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h 
) 
 186     CGRect cgRect 
= { { x 
, y 
} , { w 
, h 
} } ; 
 187     CGPathAddRect( m_path 
, NULL 
, cgRect 
) ; 
 190 void wxMacCGPath::AddCircle( wxCoord x
, wxCoord y 
, wxCoord r 
) 
 192     CGPathAddArc( m_path 
, NULL 
, x 
, y 
, r 
, 0.0 , 2 * M_PI 
, true ) ; 
 195 // closes the current subpath 
 196 void wxMacCGPath::CloseSubpath() 
 198     CGPathCloseSubpath( m_path 
) ; 
 201 CGPathRef 
wxMacCGPath::GetPath() const 
 206 void wxMacCGPath::AddArcToPoint( wxCoord x1
, wxCoord y1 
, wxCoord x2
, wxCoord y2
, wxCoord r 
) 
 208     CGPathAddArcToPoint( m_path
, NULL 
, x1
, y1
, x2
, y2
, r
); 
 211 void wxMacCGPath::AddArc( wxCoord x
, wxCoord y
, wxCoord r
, double startAngle
, double endAngle
, bool clockwise 
) 
 213     CGPathAddArc( m_path
, NULL 
, x
, y
, r
, startAngle
, endAngle
, clockwise
); 
 216 //----------------------------------------------------------------------------- 
 217 // wxGraphicContext implementation 
 218 //----------------------------------------------------------------------------- 
 220 wxMacCGContext::wxMacCGContext( CGrafPtr port 
) 
 224     m_mode 
= kCGPathFill
; 
 225     m_macATSUIStyle 
= NULL 
; 
 228 wxMacCGContext::wxMacCGContext( CGContextRef cgcontext 
) 
 231     m_cgContext 
= cgcontext 
; 
 232     m_mode 
= kCGPathFill
; 
 233     m_macATSUIStyle 
= NULL 
; 
 234     CGContextSaveGState( m_cgContext 
) ; 
 235     CGContextSaveGState( m_cgContext 
) ; 
 238 wxMacCGContext::wxMacCGContext() 
 242     m_mode 
= kCGPathFill
; 
 243     m_macATSUIStyle 
= NULL 
; 
 246 wxMacCGContext::~wxMacCGContext() 
 250         CGContextSynchronize( m_cgContext 
) ; 
 251         CGContextRestoreGState( m_cgContext 
) ; 
 252         CGContextRestoreGState( m_cgContext 
) ; 
 256         QDEndCGContext( m_qdPort
, &m_cgContext 
) ; 
 261 void wxMacCGContext::Clip( const wxRegion 
®ion 
) 
 263 //    ClipCGContextToRegion ( m_cgContext, &bounds , (RgnHandle) dc->m_macCurrentClipRgn ) ; 
 266 void wxMacCGContext::StrokePath( const wxGraphicPath 
*p 
) 
 268     const wxMacCGPath
* path 
= dynamic_cast< const wxMacCGPath
*>( p 
) ; 
 270     int width 
= m_pen
.GetWidth(); 
 273     if ( m_pen
.GetStyle() == wxTRANSPARENT 
) 
 276     bool offset 
= ( width 
% 2 ) == 1 ; 
 279         CGContextTranslateCTM( m_cgContext
, 0.5, 0.5 ); 
 281     CGContextAddPath( m_cgContext 
, path
->GetPath() ) ; 
 282     CGContextStrokePath( m_cgContext 
) ; 
 285         CGContextTranslateCTM( m_cgContext
, -0.5, -0.5 ); 
 288 void wxMacCGContext::DrawPath( const wxGraphicPath 
*p 
, int fillStyle 
) 
 290     const wxMacCGPath
* path 
= dynamic_cast< const wxMacCGPath
*>( p 
) ; 
 291     CGPathDrawingMode mode 
= m_mode 
; 
 293     if ( fillStyle 
== wxODDEVEN_RULE 
) 
 295         if ( mode 
== kCGPathFill 
) 
 296             mode 
= kCGPathEOFill 
; 
 297         else if ( mode 
== kCGPathFillStroke 
) 
 298             mode 
= kCGPathEOFillStroke 
; 
 301     int width 
= m_pen
.GetWidth(); 
 304     if ( m_pen
.GetStyle() == wxTRANSPARENT 
) 
 307     bool offset 
= ( width 
% 2 ) == 1 ; 
 310         CGContextTranslateCTM( m_cgContext
, 0.5, 0.5 ); 
 312     CGContextAddPath( m_cgContext 
, path
->GetPath() ) ; 
 313     CGContextDrawPath( m_cgContext 
, mode 
) ; 
 316         CGContextTranslateCTM( m_cgContext
, -0.5, -0.5 ); 
 319 void wxMacCGContext::FillPath( const wxGraphicPath 
*p 
, const wxColor 
&fillColor 
, int fillStyle 
) 
 321     const wxMacCGPath
* path 
= dynamic_cast< const wxMacCGPath
*>( p 
) ; 
 322     CGContextSaveGState( m_cgContext 
) ; 
 324     RGBColor col 
= MAC_WXCOLORREF( fillColor
.GetPixel() ) ; 
 325     CGContextSetRGBFillColor( m_cgContext 
, col
.red 
/ 65536.0 , col
.green 
/ 65536.0 , col
.blue 
/ 65536.0 , 1.0 ) ; 
 326     CGPathDrawingMode mode 
= kCGPathFill 
; 
 328     if ( fillStyle 
== wxODDEVEN_RULE 
) 
 329         mode 
= kCGPathEOFill 
; 
 331     CGContextBeginPath( m_cgContext 
) ; 
 332     CGContextAddPath( m_cgContext 
, path
->GetPath() ) ; 
 333     CGContextClosePath( m_cgContext 
) ; 
 334     CGContextDrawPath( m_cgContext 
, mode 
) ; 
 336     CGContextRestoreGState( m_cgContext 
) ; 
 339 wxGraphicPath
* wxMacCGContext::CreatePath() 
 341     // make sure that we now have a real cgref, before doing 
 342     // anything with paths 
 343     CGContextRef cg 
= GetNativeContext() ; 
 346     return new wxMacCGPath() ; 
 349 // in case we only got a QDPort only create a cgref now 
 351 CGContextRef 
wxMacCGContext::GetNativeContext() 
 353     if ( m_cgContext 
== NULL 
) 
 356         OSStatus status 
= noErr
; 
 358         GetPortBounds( (CGrafPtr
) m_qdPort 
, &bounds 
) ; 
 359         status 
= QDBeginCGContext((CGrafPtr
) m_qdPort 
, &m_cgContext
) ; 
 361         CGContextSaveGState( m_cgContext 
) ; 
 363         wxASSERT_MSG( status 
== noErr 
, wxT("Cannot nest wxDCs on the same window") ) ; 
 365         CGContextTranslateCTM( m_cgContext 
, 0 , bounds
.bottom 
- bounds
.top 
) ; 
 366         CGContextScaleCTM( m_cgContext 
, 1 , -1 ) ; 
 368         CGContextSaveGState( m_cgContext 
) ; 
 370         SetBrush( m_brush 
) ; 
 376 void wxMacCGContext::SetNativeContext( CGContextRef cg 
) 
 378     // we allow either setting or clearing but not replacing 
 379     wxASSERT( m_cgContext 
== NULL 
|| cg 
== NULL 
) ; 
 382         CGContextSaveGState( cg 
) ; 
 386 void wxMacCGContext::Translate( wxCoord dx 
, wxCoord dy 
) 
 388     CGContextTranslateCTM( m_cgContext
, dx
, dy 
); 
 391 void wxMacCGContext::Scale( wxCoord xScale 
, wxCoord yScale 
) 
 393     CGContextScaleCTM( m_cgContext 
, xScale 
, yScale 
) ; 
 396 void wxMacCGContext::DrawBitmap( const wxBitmap 
&bmp
, wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h 
) 
 398     CGImageRef image 
= (CGImageRef
)( bmp
.CGImageCreate() ) ; 
 399     HIRect r 
= CGRectMake( 0 , 0 , w 
, h 
); 
 401     CGContextSaveGState( m_cgContext 
); 
 402     CGContextTranslateCTM( m_cgContext
, x 
, y 
+ h 
); 
 403     CGContextScaleCTM( m_cgContext
, 1, -1 ); 
 405     // in case image is a mask, set the foreground color 
 406     CGContextSetRGBFillColor( m_cgContext 
, m_textForegroundColor
.Red() / 255.0 , m_textForegroundColor
.Green() / 255.0 , 
 407         m_textForegroundColor
.Blue() / 255.0 , m_textForegroundColor
.Alpha() / 255.0 ) ; 
 408     CGContextDrawImage( m_cgContext
, r
, image 
); 
 409     CGContextRestoreGState( m_cgContext 
); 
 411     CGImageRelease( image 
) ; 
 414 void wxMacCGContext::DrawIcon( const wxIcon 
&icon
, wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h 
) 
 416     CGRect r 
= CGRectMake( 0 , 0 , w 
, h 
) ; 
 417     CGContextSaveGState( m_cgContext 
); 
 418     CGContextTranslateCTM( m_cgContext
, x 
, y 
+ h 
); 
 419     CGContextScaleCTM( m_cgContext
, 1, -1 ); 
 420     PlotIconRefInContext( m_cgContext 
, &r 
, kAlignNone 
, kTransformNone 
, 
 421         NULL 
, kPlotIconRefNormalFlags 
, MAC_WXHICON( icon
.GetHICON() ) ) ; 
 422     CGContextRestoreGState( m_cgContext 
) ; 
 425 void wxMacCGContext::PushState() 
 427     CGContextSaveGState( m_cgContext 
); 
 430 void wxMacCGContext::PopState() 
 432     CGContextRestoreGState( m_cgContext 
); 
 435 void wxMacCGContext::SetTextColor( const wxColour 
&col 
) 
 437     m_textForegroundColor 
= col 
; 
 441 #pragma mark wxMacCGPattern, ImagePattern, HatchPattern classes 
 443 // CGPattern wrapper class: always allocate on heap, never call destructor 
 450     // is guaranteed to be called only with a non-Null CGContextRef 
 451     virtual void Render( CGContextRef ctxRef 
) = 0 ; 
 453     operator CGPatternRef() const { return m_patternRef 
; } 
 456     virtual ~wxMacCGPattern() 
 458         // as this is called only when the m_patternRef is been released; 
 459         // don't release it again 
 462     static void _Render( void *info
, CGContextRef ctxRef 
) 
 464         wxMacCGPattern
* self 
= (wxMacCGPattern
*) info 
; 
 465         if ( self 
&& ctxRef 
) 
 466             self
->Render( ctxRef 
) ; 
 469     static void _Dispose( void *info 
) 
 471         wxMacCGPattern
* self 
= (wxMacCGPattern
*) info 
; 
 475     CGPatternRef m_patternRef 
; 
 477     static const CGPatternCallbacks ms_Callbacks 
; 
 480 const CGPatternCallbacks 
wxMacCGPattern::ms_Callbacks 
= { 0, &wxMacCGPattern::_Render
, &wxMacCGPattern::_Dispose 
}; 
 482 class ImagePattern 
: public wxMacCGPattern
 
 485     ImagePattern( const wxBitmap
* bmp 
, const CGAffineTransform
& transform 
) 
 487         wxASSERT( bmp 
&& bmp
->Ok() ) ; 
 489         Init( (CGImageRef
) bmp
->CGImageCreate() , transform 
) ; 
 492     // ImagePattern takes ownership of CGImageRef passed in 
 493     ImagePattern( CGImageRef image 
, const CGAffineTransform
& transform 
) 
 498         Init( image 
, transform 
) ; 
 501     virtual void Render( CGContextRef ctxRef 
) 
 504             HIViewDrawCGImage( ctxRef
, &m_imageBounds
, m_image 
); 
 508     void Init( CGImageRef image
, const CGAffineTransform
& transform 
) 
 513             m_imageBounds 
= CGRectMake( 0.0, 0.0, (CGFloat
)CGImageGetWidth( m_image 
), (CGFloat
)CGImageGetHeight( m_image 
) ) ; 
 514             m_patternRef 
= CGPatternCreate( 
 515                 this , m_imageBounds
, transform 
, 
 516                 m_imageBounds
.size
.width
, m_imageBounds
.size
.height
, 
 517                 kCGPatternTilingNoDistortion
, true , &wxMacCGPattern::ms_Callbacks 
) ; 
 521     virtual ~ImagePattern() 
 524             CGImageRelease( m_image 
) ; 
 528     CGRect m_imageBounds 
; 
 531 class HatchPattern 
: public wxMacCGPattern
 
 534     HatchPattern( int hatchstyle
, const CGAffineTransform
& transform 
) 
 536         m_hatch 
= hatchstyle 
; 
 537         m_imageBounds 
= CGRectMake( 0.0, 0.0, 8.0 , 8.0 ) ; 
 538         m_patternRef 
= CGPatternCreate( 
 539             this , m_imageBounds
, transform 
, 
 540             m_imageBounds
.size
.width
, m_imageBounds
.size
.height
, 
 541             kCGPatternTilingNoDistortion
, false , &wxMacCGPattern::ms_Callbacks 
) ; 
 544     void StrokeLineSegments( CGContextRef ctxRef 
, const CGPoint pts
[] , size_t count 
) 
 546 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 
 547         if ( UMAGetSystemVersion() >= 0x1040 ) 
 549             CGContextStrokeLineSegments( ctxRef 
, pts 
, count 
) ; 
 554             CGContextBeginPath( ctxRef 
); 
 555             for (size_t i 
= 0; i 
< count
; i 
+= 2) 
 557                 CGContextMoveToPoint(ctxRef
, pts
[i
].x
, pts
[i
].y
); 
 558                 CGContextAddLineToPoint(ctxRef
, pts
[i
+1].x
, pts
[i
+1].y
); 
 560             CGContextStrokePath(ctxRef
); 
 564     virtual void Render( CGContextRef ctxRef 
) 
 568             case wxBDIAGONAL_HATCH 
: 
 572                     { 8.0 , 0.0 } , { 0.0 , 8.0 } 
 574                     StrokeLineSegments( ctxRef 
, pts 
, 2 ) ; 
 578             case wxCROSSDIAG_HATCH 
: 
 582                         { 0.0 , 0.0 } , { 8.0 , 8.0 } , 
 583                         { 8.0 , 0.0 } , { 0.0 , 8.0 } 
 585                     StrokeLineSegments( ctxRef 
, pts 
, 4 ) ; 
 589             case wxFDIAGONAL_HATCH 
: 
 593                     { 0.0 , 0.0 } , { 8.0 , 8.0 } 
 595                     StrokeLineSegments( ctxRef 
, pts 
, 2 ) ; 
 603                     { 0.0 , 4.0 } , { 8.0 , 4.0 } , 
 604                     { 4.0 , 0.0 } , { 4.0 , 8.0 } , 
 606                     StrokeLineSegments( ctxRef 
, pts 
, 4 ) ; 
 610             case wxHORIZONTAL_HATCH 
: 
 614                     { 0.0 , 4.0 } , { 8.0 , 4.0 } , 
 616                     StrokeLineSegments( ctxRef 
, pts 
, 2 ) ; 
 620             case wxVERTICAL_HATCH 
: 
 624                     { 4.0 , 0.0 } , { 4.0 , 8.0 } , 
 626                     StrokeLineSegments( ctxRef 
, pts 
, 2 ) ; 
 636     virtual ~HatchPattern() {} 
 638     CGRect      m_imageBounds 
; 
 644 void wxMacCGContext::SetPen( const wxPen 
&pen 
) 
 647     if ( m_cgContext 
== NULL 
) 
 650     bool fill 
= m_brush
.GetStyle() != wxTRANSPARENT 
; 
 651     bool stroke 
= pen
.GetStyle() != wxTRANSPARENT 
; 
 654     // we can benchmark performance; should go into a setting eventually 
 655     CGContextSetShouldAntialias( m_cgContext 
, false ) ; 
 658     if ( fill 
|| stroke 
) 
 661         m_mode 
= kCGPathFill 
; // just a default 
 665             CGContextSetRGBStrokeColor( m_cgContext 
, pen
.GetColour().Red() / 255.0 , pen
.GetColour().Green() / 255.0 , 
 666                     pen
.GetColour().Blue() / 255.0 , pen
.GetColour().Alpha() / 255.0 ) ; 
 668             // TODO: * m_dc->m_scaleX 
 669             CGFloat penWidth 
= pen
.GetWidth(); 
 672             CGContextSetLineWidth( m_cgContext 
, penWidth 
) ; 
 675             switch ( pen
.GetCap() ) 
 678                     cap 
= kCGLineCapRound 
; 
 681                 case wxCAP_PROJECTING 
: 
 682                     cap 
= kCGLineCapSquare 
; 
 686                     cap 
= kCGLineCapButt 
; 
 690                     cap 
= kCGLineCapButt 
; 
 695             switch ( pen
.GetJoin() ) 
 698                     join 
= kCGLineJoinBevel 
; 
 702                     join 
= kCGLineJoinMiter 
; 
 706                     join 
= kCGLineJoinRound 
; 
 710                     join 
= kCGLineJoinMiter 
; 
 714             m_mode 
= kCGPathStroke 
; 
 717             const CGFloat 
*lengths 
= NULL 
; 
 718             CGFloat 
*userLengths 
= NULL 
; 
 720             const CGFloat dashUnit 
= penWidth 
< 1.0 ? 1.0 : penWidth
; 
 722             const CGFloat dotted
[] = { dashUnit 
, dashUnit 
+ 2.0 }; 
 723             const CGFloat short_dashed
[] = { 9.0 , 6.0 }; 
 724             const CGFloat dashed
[] = { 19.0 , 9.0 }; 
 725             const CGFloat dotted_dashed
[] = { 9.0 , 6.0 , 3.0 , 3.0 }; 
 727             switch ( pen
.GetStyle() ) 
 734                     count 
= WXSIZEOF(dotted
); 
 739                     count 
= WXSIZEOF(dashed
) ; 
 743                     lengths 
= short_dashed 
; 
 744                     count 
= WXSIZEOF(short_dashed
) ; 
 748                     lengths 
= dotted_dashed 
; 
 749                     count 
= WXSIZEOF(dotted_dashed
); 
 754                     count 
= pen
.GetDashes( &dashes 
) ; 
 755                     if ((dashes 
!= NULL
) && (count 
> 0)) 
 757                         userLengths 
= new CGFloat
[count
] ; 
 758                         for ( int i 
= 0 ; i 
< count 
; ++i 
) 
 760                             userLengths
[i
] = dashes
[i
] * dashUnit 
; 
 762                             if ( i 
% 2 == 1 && userLengths
[i
] < dashUnit 
+ 2.0 ) 
 763                                 userLengths
[i
] = dashUnit 
+ 2.0 ; 
 764                             else if ( i 
% 2 == 0 && userLengths
[i
] < dashUnit 
) 
 765                                 userLengths
[i
] = dashUnit 
; 
 768                     lengths 
= userLengths 
; 
 773                         CGFloat  alphaArray
[1] = { 1.0 } ; 
 774                         wxBitmap
* bmp 
= pen
.GetStipple() ; 
 775                         if ( bmp 
&& bmp
->Ok() ) 
 777                             wxMacCFRefHolder
<CGColorSpaceRef
> patternSpace( CGColorSpaceCreatePattern( NULL 
) ) ; 
 778                             CGContextSetStrokeColorSpace( m_cgContext 
, patternSpace 
) ; 
 779                             wxMacCFRefHolder
<CGPatternRef
> pattern( *( new ImagePattern( bmp 
, CGContextGetCTM( m_cgContext 
) ) ) ); 
 780                             CGContextSetStrokePattern( m_cgContext
, pattern 
, alphaArray 
) ; 
 787                         wxMacCFRefHolder
<CGColorSpaceRef
> patternSpace( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ) ; 
 788                         CGContextSetStrokeColorSpace( m_cgContext 
, patternSpace 
) ; 
 789                         wxMacCFRefHolder
<CGPatternRef
> pattern( *( new HatchPattern( pen
.GetStyle() , CGContextGetCTM( m_cgContext 
) ) ) ); 
 791                         CGFloat  colorArray
[4] = { pen
.GetColour().Red() / 255.0 , pen
.GetColour().Green() / 255.0 , 
 792                             pen
.GetColour().Blue() / 255.0 , pen
.GetColour().Alpha() / 255.0 } ; 
 794                         CGContextSetStrokePattern( m_cgContext
, pattern 
, colorArray 
) ; 
 799             if ((lengths 
!= NULL
) && (count 
> 0)) 
 801                 CGContextSetLineDash( m_cgContext 
, 0 , lengths 
, count 
) ; 
 802                 // force the line cap, otherwise we get artifacts (overlaps) and just solid lines 
 803                 cap 
= kCGLineCapButt 
; 
 807                CGContextSetLineDash( m_cgContext 
, 0 , NULL 
, 0 ) ; 
 810             CGContextSetLineCap( m_cgContext 
, cap 
) ; 
 811             CGContextSetLineJoin( m_cgContext 
, join 
) ; 
 813             delete[] userLengths 
; 
 816         if ( fill 
&& stroke 
) 
 817             m_mode 
= kCGPathFillStroke 
; 
 821 void wxMacCGContext::SetBrush( const wxBrush 
&brush 
) 
 824     if ( m_cgContext 
== NULL 
) 
 827     bool fill 
= brush
.GetStyle() != wxTRANSPARENT 
; 
 828     bool stroke 
= m_pen
.GetStyle() != wxTRANSPARENT 
; 
 831     // we can benchmark performance, should go into a setting later 
 832     CGContextSetShouldAntialias( m_cgContext 
, false ) ; 
 835     if ( fill 
|| stroke 
) 
 838         m_mode 
= kCGPathFill 
; // just a default 
 842             if ( brush
.GetStyle() == wxSOLID 
) 
 844                 CGContextSetRGBFillColor( m_cgContext 
, brush
.GetColour().Red() / 255.0 , brush
.GetColour().Green() / 255.0 , 
 845                     brush
.GetColour().Blue() / 255.0 , brush
.GetColour().Alpha() / 255.0 ) ; 
 847             else if ( brush
.IsHatch() ) 
 849                 wxMacCFRefHolder
<CGColorSpaceRef
> patternSpace( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ) ; 
 850                 CGContextSetFillColorSpace( m_cgContext 
, patternSpace 
) ; 
 851                 wxMacCFRefHolder
<CGPatternRef
> pattern( *( new HatchPattern( brush
.GetStyle() , CGContextGetCTM( m_cgContext 
) ) ) ); 
 853                 CGFloat  colorArray
[4] = { brush
.GetColour().Red() / 255.0 , brush
.GetColour().Green() / 255.0 , 
 854                     brush
.GetColour().Blue() / 255.0 , brush
.GetColour().Alpha() / 255.0 } ; 
 856                 CGContextSetFillPattern( m_cgContext
, pattern 
, colorArray 
) ; 
 860                 // now brush is a bitmap 
 861                 CGFloat  alphaArray
[1] = { 1.0 } ; 
 862                 wxBitmap
* bmp 
= brush
.GetStipple() ; 
 863                 if ( bmp 
&& bmp
->Ok() ) 
 865                     wxMacCFRefHolder
<CGColorSpaceRef
> patternSpace( CGColorSpaceCreatePattern( NULL 
) ) ; 
 866                     CGContextSetFillColorSpace( m_cgContext 
, patternSpace 
) ; 
 867                     wxMacCFRefHolder
<CGPatternRef
> pattern( *( new ImagePattern( bmp 
, CGContextGetCTM( m_cgContext 
) ) ) ); 
 868                     CGContextSetFillPattern( m_cgContext
, pattern 
, alphaArray 
) ; 
 872             m_mode 
= kCGPathFill 
; 
 875         if ( fill 
&& stroke 
) 
 876             m_mode 
= kCGPathFillStroke 
; 
 878             m_mode 
= kCGPathStroke 
; 
 882 void wxMacCGContext::DrawText( const wxString 
&str
, wxCoord x
, wxCoord y
, double angle 
) 
 884     OSStatus status 
= noErr 
; 
 885     ATSUTextLayout atsuLayout 
; 
 886     UniCharCount chars 
= str
.length() ; 
 887     UniChar
* ubuf 
= NULL 
; 
 889 #if SIZEOF_WCHAR_T == 4 
 890     wxMBConvUTF16 converter 
; 
 892     size_t unicharlen 
= converter
.WC2MB( NULL 
, str
.wc_str() , 0 ) ; 
 893     ubuf 
= (UniChar
*) malloc( unicharlen 
+ 2 ) ; 
 894     converter
.WC2MB( (char*) ubuf 
, str
.wc_str(), unicharlen 
+ 2 ) ; 
 896     const wxWCharBuffer wchar 
= str
.wc_str( wxConvLocal 
) ; 
 897     size_t unicharlen 
= converter
.WC2MB( NULL 
, wchar
.data() , 0 ) ; 
 898     ubuf 
= (UniChar
*) malloc( unicharlen 
+ 2 ) ; 
 899     converter
.WC2MB( (char*) ubuf 
, wchar
.data() , unicharlen 
+ 2 ) ; 
 901     chars 
= unicharlen 
/ 2 ; 
 904     ubuf 
= (UniChar
*) str
.wc_str() ; 
 906     wxWCharBuffer wchar 
= str
.wc_str( wxConvLocal 
) ; 
 907     chars 
= wxWcslen( wchar
.data() ) ; 
 908     ubuf 
= (UniChar
*) wchar
.data() ; 
 912     status 
= ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr
) ubuf 
, 0 , chars 
, chars 
, 1 , 
 913         &chars 
, (ATSUStyle
*) &m_macATSUIStyle 
, &atsuLayout 
) ; 
 915     wxASSERT_MSG( status 
== noErr 
, wxT("couldn't create the layout of the rotated text") ); 
 917     status 
= ::ATSUSetTransientFontMatching( atsuLayout 
, true ) ; 
 918     wxASSERT_MSG( status 
== noErr 
, wxT("couldn't setup transient font matching") ); 
 920     int iAngle 
= int( angle 
); 
 921     if ( abs(iAngle
) > 0 ) 
 923         Fixed atsuAngle 
= IntToFixed( iAngle 
) ; 
 924         ATSUAttributeTag atsuTags
[] = 
 926             kATSULineRotationTag 
, 
 928         ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] = 
 932         ATSUAttributeValuePtr    atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] = 
 936         status 
= ::ATSUSetLayoutControls(atsuLayout 
, sizeof(atsuTags
) / sizeof(ATSUAttributeTag
), 
 937             atsuTags
, atsuSizes
, atsuValues 
) ; 
 941         ATSUAttributeTag atsuTags
[] = 
 945         ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] = 
 947             sizeof( CGContextRef 
) , 
 949         ATSUAttributeValuePtr    atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] = 
 953         status 
= ::ATSUSetLayoutControls(atsuLayout 
, sizeof(atsuTags
) / sizeof(ATSUAttributeTag
), 
 954             atsuTags
, atsuSizes
, atsuValues 
) ; 
 957     ATSUTextMeasurement textBefore
, textAfter 
; 
 958     ATSUTextMeasurement ascent
, descent 
; 
 960     status 
= ::ATSUGetUnjustifiedBounds( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
, 
 961         &textBefore 
, &textAfter
, &ascent 
, &descent 
); 
 963     wxASSERT_MSG( status 
== noErr 
, wxT("couldn't measure the rotated text") ); 
 968     if ( m_backgroundMode == wxSOLID ) 
 970         wxGraphicPath* path = m_graphicContext->CreatePath() ; 
 971         path->MoveToPoint( drawX , drawY ) ; 
 972         path->AddLineToPoint( 
 973             (int) (drawX + sin(angle / RAD2DEG) * FixedToInt(ascent + descent)) , 
 974             (int) (drawY + cos(angle / RAD2DEG) * FixedToInt(ascent + descent)) ) ; 
 975         path->AddLineToPoint( 
 976             (int) (drawX + sin(angle / RAD2DEG) * FixedToInt(ascent + descent ) + cos(angle / RAD2DEG) * FixedToInt(textAfter)) , 
 977             (int) (drawY + cos(angle / RAD2DEG) * FixedToInt(ascent + descent) - sin(angle / RAD2DEG) * FixedToInt(textAfter)) ) ; 
 978         path->AddLineToPoint( 
 979             (int) (drawX + cos(angle / RAD2DEG) * FixedToInt(textAfter)) , 
 980             (int) (drawY - sin(angle / RAD2DEG) * FixedToInt(textAfter)) ) ; 
 982         m_graphicContext->FillPath( path , m_textBackgroundColour ) ; 
 986     x 
+= (int)(sin(angle 
/ RAD2DEG
) * FixedToInt(ascent
)); 
 987     y 
+= (int)(cos(angle 
/ RAD2DEG
) * FixedToInt(ascent
)); 
 989     status 
= ::ATSUMeasureTextImage( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
, 
 990         IntToFixed(x
) , IntToFixed(y
) , &rect 
); 
 991     wxASSERT_MSG( status 
== noErr 
, wxT("couldn't measure the rotated text") ); 
 993     CGContextSaveGState(m_cgContext
); 
 994     CGContextTranslateCTM(m_cgContext
, x
, y
); 
 995     CGContextScaleCTM(m_cgContext
, 1, -1); 
 996     status 
= ::ATSUDrawText( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
, 
 997         IntToFixed(0) , IntToFixed(0) ); 
 999     wxASSERT_MSG( status 
== noErr 
, wxT("couldn't draw the rotated text") ); 
1001     CGContextRestoreGState(m_cgContext
) ; 
1003     ::ATSUDisposeTextLayout(atsuLayout
); 
1005 #if SIZEOF_WCHAR_T == 4 
1010 void wxMacCGContext::GetTextExtent( const wxString 
&str
, wxCoord 
*width
, wxCoord 
*height
, 
1011                             wxCoord 
*descent
, wxCoord 
*externalLeading 
) const 
1013     wxCHECK_RET( m_macATSUIStyle 
!= NULL
, wxT("wxDC(cg)::DoGetTextExtent - no valid font set") ) ; 
1015     OSStatus status 
= noErr 
; 
1017     ATSUTextLayout atsuLayout 
; 
1018     UniCharCount chars 
= str
.length() ; 
1019     UniChar
* ubuf 
= NULL 
; 
1021 #if SIZEOF_WCHAR_T == 4 
1022     wxMBConvUTF16 converter 
; 
1024     size_t unicharlen 
= converter
.WC2MB( NULL 
, str
.wc_str() , 0 ) ; 
1025     ubuf 
= (UniChar
*) malloc( unicharlen 
+ 2 ) ; 
1026     converter
.WC2MB( (char*) ubuf 
, str
.wc_str(), unicharlen 
+ 2 ) ; 
1028     const wxWCharBuffer wchar 
= str
.wc_str( wxConvLocal 
) ; 
1029     size_t unicharlen 
= converter
.WC2MB( NULL 
, wchar
.data() , 0 ) ; 
1030     ubuf 
= (UniChar
*) malloc( unicharlen 
+ 2 ) ; 
1031     converter
.WC2MB( (char*) ubuf 
, wchar
.data() , unicharlen 
+ 2 ) ; 
1033     chars 
= unicharlen 
/ 2 ; 
1036     ubuf 
= (UniChar
*) str
.wc_str() ; 
1038     wxWCharBuffer wchar 
= str
.wc_str( wxConvLocal 
) ; 
1039     chars 
= wxWcslen( wchar
.data() ) ; 
1040     ubuf 
= (UniChar
*) wchar
.data() ; 
1044     status 
= ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr
) ubuf 
, 0 , chars 
, chars 
, 1 , 
1045         &chars 
, (ATSUStyle
*) &m_macATSUIStyle 
, &atsuLayout 
) ; 
1047     wxASSERT_MSG( status 
== noErr 
, wxT("couldn't create the layout of the text") ); 
1049     ATSUTextMeasurement textBefore
, textAfter 
; 
1050     ATSUTextMeasurement textAscent
, textDescent 
; 
1052     status 
= ::ATSUGetUnjustifiedBounds( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
, 
1053         &textBefore 
, &textAfter
, &textAscent 
, &textDescent 
); 
1056         *height 
= FixedToInt(textAscent 
+ textDescent
) ; 
1058         *descent 
= FixedToInt(textDescent
) ; 
1059     if ( externalLeading 
) 
1060         *externalLeading 
= 0 ; 
1062         *width 
= FixedToInt(textAfter 
- textBefore
) ; 
1064     ::ATSUDisposeTextLayout(atsuLayout
); 
1067 void wxMacCGContext::GetPartialTextExtents(const wxString
& text
, wxArrayInt
& widths
) const 
1070     widths
.Add(0, text
.length()); 
1075     ATSUTextLayout atsuLayout 
; 
1076     UniCharCount chars 
= text
.length() ; 
1077     UniChar
* ubuf 
= NULL 
; 
1079 #if SIZEOF_WCHAR_T == 4 
1080     wxMBConvUTF16 converter 
; 
1082     size_t unicharlen 
= converter
.WC2MB( NULL 
, text
.wc_str() , 0 ) ; 
1083     ubuf 
= (UniChar
*) malloc( unicharlen 
+ 2 ) ; 
1084     converter
.WC2MB( (char*) ubuf 
, text
.wc_str(), unicharlen 
+ 2 ) ; 
1086     const wxWCharBuffer wchar 
= text
.wc_str( wxConvLocal 
) ; 
1087     size_t unicharlen 
= converter
.WC2MB( NULL 
, wchar
.data() , 0 ) ; 
1088     ubuf 
= (UniChar
*) malloc( unicharlen 
+ 2 ) ; 
1089     converter
.WC2MB( (char*) ubuf 
, wchar
.data() , unicharlen 
+ 2 ) ; 
1091     chars 
= unicharlen 
/ 2 ; 
1094     ubuf 
= (UniChar
*) text
.wc_str() ; 
1096     wxWCharBuffer wchar 
= text
.wc_str( wxConvLocal 
) ; 
1097     chars 
= wxWcslen( wchar
.data() ) ; 
1098     ubuf 
= (UniChar
*) wchar
.data() ; 
1102     ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr
) ubuf 
, 0 , chars 
, chars 
, 1 , 
1103         &chars 
, (ATSUStyle
*) &m_macATSUIStyle 
, &atsuLayout 
) ; 
1105     for ( int pos 
= 0; pos 
< (int)chars
; pos 
++ ) 
1107         unsigned long actualNumberOfBounds 
= 0; 
1108         ATSTrapezoid glyphBounds
; 
1110         // We get a single bound, since the text should only require one. If it requires more, there is an issue 
1112         result 
= ATSUGetGlyphBounds( atsuLayout
, 0, 0, kATSUFromTextBeginning
, pos 
+ 1, 
1113             kATSUseDeviceOrigins
, 1, &glyphBounds
, &actualNumberOfBounds 
); 
1114         if (result 
!= noErr 
|| actualNumberOfBounds 
!= 1 ) 
1117         widths
[pos
] = FixedToInt( glyphBounds
.upperRight
.x 
- glyphBounds
.upperLeft
.x 
); 
1118         //unsigned char uch = s[i]; 
1121     ::ATSUDisposeTextLayout(atsuLayout
); 
1124 void wxMacCGContext::SetFont( const wxFont 
&font 
) 
1126     if ( m_macATSUIStyle 
) 
1128         ::ATSUDisposeStyle((ATSUStyle
)m_macATSUIStyle
); 
1129         m_macATSUIStyle 
= NULL 
; 
1136         status 
= ATSUCreateAndCopyStyle( (ATSUStyle
) font
.MacGetATSUStyle() , (ATSUStyle
*) &m_macATSUIStyle 
) ; 
1138         wxASSERT_MSG( status 
== noErr
, wxT("couldn't create ATSU style") ) ; 
1140         // we need the scale here ... 
1142         Fixed atsuSize 
= IntToFixed( int( /*m_scaleY*/ 1 * font
.MacGetFontSize()) ) ; 
1143         RGBColor atsuColor 
= MAC_WXCOLORREF( m_textForegroundColor
.GetPixel() ) ; 
1144         ATSUAttributeTag atsuTags
[] = 
1149         ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] = 
1152                 sizeof( RGBColor 
) , 
1154         ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] = 
1160         status 
= ::ATSUSetAttributes( 
1161             (ATSUStyle
)m_macATSUIStyle
, sizeof(atsuTags
) / sizeof(ATSUAttributeTag
) , 
1162             atsuTags
, atsuSizes
, atsuValues
); 
1164         wxASSERT_MSG( status 
== noErr 
, wxT("couldn't modify ATSU style") ) ; 
1175     m_mm_to_pix_x 
= mm2pt
; 
1176     m_mm_to_pix_y 
= mm2pt
; 
1178     m_externalDeviceOriginX 
= 0; 
1179     m_externalDeviceOriginY 
= 0; 
1180     m_logicalScaleX 
= 1.0; 
1181     m_logicalScaleY 
= 1.0; 
1186     m_needComputeScaleX 
= 
1187     m_needComputeScaleY 
= false; 
1190     m_macLocalOrigin
.x 
= 
1191     m_macLocalOrigin
.y 
= 0 ; 
1193     m_pen 
= *wxBLACK_PEN
; 
1194     m_font 
= *wxNORMAL_FONT
; 
1195     m_brush 
= *wxWHITE_BRUSH
; 
1197     m_macATSUIStyle 
= NULL 
; 
1198     m_graphicContext 
= NULL 
; 
1203     if ( m_macATSUIStyle 
) 
1205         ::ATSUDisposeStyle((ATSUStyle
)m_macATSUIStyle
); 
1206         m_macATSUIStyle 
= NULL 
; 
1209     delete m_graphicContext 
; 
1212 void wxDC::DoDrawBitmap( const wxBitmap 
&bmp
, wxCoord x
, wxCoord y
, bool useMask 
) 
1214     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawBitmap - invalid DC") ); 
1215     wxCHECK_RET( bmp
.Ok(), wxT("wxDC(cg)::DoDrawBitmap - invalid bitmap") ); 
1217     wxCoord xx 
= XLOG2DEVMAC(x
); 
1218     wxCoord yy 
= YLOG2DEVMAC(y
); 
1219     wxCoord w 
= bmp
.GetWidth(); 
1220     wxCoord h 
= bmp
.GetHeight(); 
1221     wxCoord ww 
= XLOG2DEVREL(w
); 
1222     wxCoord hh 
= YLOG2DEVREL(h
); 
1224     if ( bmp
.GetDepth()==1 ) 
1226         wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
1227         path
->AddRectangle( xx 
, yy 
, ww 
, hh 
) ; 
1228         m_graphicContext
->FillPath( path 
, m_textBackgroundColour
, wxODDEVEN_RULE
) ; 
1230         m_graphicContext
->DrawBitmap( bmp
, xx 
, yy 
, ww 
, hh 
) ; 
1234         m_graphicContext
->DrawBitmap( bmp
, xx 
, yy 
, ww 
, hh 
) ; 
1238 void wxDC::DoDrawIcon( const wxIcon 
&icon
, wxCoord x
, wxCoord y 
) 
1240     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawIcon - invalid DC") ); 
1241     wxCHECK_RET( icon
.Ok(), wxT("wxDC(cg)::DoDrawIcon - invalid icon") ); 
1243     wxCoord xx 
= XLOG2DEVMAC(x
); 
1244     wxCoord yy 
= YLOG2DEVMAC(y
); 
1245     wxCoord w 
= icon
.GetWidth(); 
1246     wxCoord h 
= icon
.GetHeight(); 
1247     wxCoord ww 
= XLOG2DEVREL(w
); 
1248     wxCoord hh 
= YLOG2DEVREL(h
); 
1250     m_graphicContext
->DrawIcon( icon 
, xx
, yy
, ww
, hh 
) ; 
1253 void wxDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
1255     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoSetClippingRegion - invalid DC") ); 
1257     wxCoord xx
, yy
, ww
, hh
; 
1258     xx 
= XLOG2DEVMAC(x
); 
1259     yy 
= YLOG2DEVMAC(y
); 
1260     ww 
= XLOG2DEVREL(width
); 
1261     hh 
= YLOG2DEVREL(height
); 
1263     CGContextRef cgContext 
= ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ; 
1264     CGRect clipRect 
= CGRectMake( xx 
, yy 
, ww
, hh 
) ; 
1265     CGContextClipToRect( cgContext 
, clipRect 
) ; 
1267 //    SetRectRgn( (RgnHandle) m_macCurrentClipRgn , xx , yy , xx + ww , yy + hh ) ; 
1268 //    SectRgn( (RgnHandle) m_macCurrentClipRgn , (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ; 
1272         m_clipX1 
= wxMax( m_clipX1
, xx 
); 
1273         m_clipY1 
= wxMax( m_clipY1
, yy 
); 
1274         m_clipX2 
= wxMin( m_clipX2
, (xx 
+ ww
) ); 
1275         m_clipY2 
= wxMin( m_clipY2
, (yy 
+ hh
) ); 
1287     // TODO: as soon as we don't reset the context for each operation anymore 
1288     // we have to update the context as well 
1291 void wxDC::DoSetClippingRegionAsRegion( const wxRegion 
®ion 
) 
1293     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoSetClippingRegionAsRegion - invalid DC") ); 
1297         DestroyClippingRegion(); 
1302     region
.GetBox( x
, y
, w
, h 
); 
1303     wxCoord xx
, yy
, ww
, hh
; 
1304     xx 
= XLOG2DEVMAC(x
); 
1305     yy 
= YLOG2DEVMAC(y
); 
1306     ww 
= XLOG2DEVREL(w
); 
1307     hh 
= YLOG2DEVREL(h
); 
1309     // if we have a scaling that we cannot map onto native regions 
1310     // we must use the box 
1311     if ( ww 
!= w 
|| hh 
!= h 
) 
1313         wxDC::DoSetClippingRegion( x
, y
, w
, h 
); 
1319             m_clipX1 
= wxMax( m_clipX1
, xx 
); 
1320             m_clipY1 
= wxMax( m_clipY1
, yy 
); 
1321             m_clipX2 
= wxMin( m_clipX2
, (xx 
+ ww
) ); 
1322             m_clipY2 
= wxMin( m_clipY2
, (yy 
+ hh
) ); 
1336 void wxDC::DestroyClippingRegion() 
1338     CGContextRef cgContext 
= ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ; 
1339     CGContextRestoreGState( cgContext 
); 
1340     CGContextSaveGState( cgContext 
); 
1342     m_graphicContext
->SetPen( m_pen 
) ; 
1343     m_graphicContext
->SetBrush( m_brush 
) ; 
1348 void wxDC::DoGetSizeMM( int* width
, int* height 
) const 
1354         *width 
= long( double(w
) / (m_scaleX 
* m_mm_to_pix_x
) ); 
1356         *height 
= long( double(h
) / (m_scaleY 
* m_mm_to_pix_y
) ); 
1359 void wxDC::SetTextForeground( const wxColour 
&col 
) 
1361     wxCHECK_RET( Ok(), wxT("wxDC(cg)::SetTextForeground - invalid DC") ); 
1363     if ( col 
!= m_textForegroundColour 
) 
1365         m_textForegroundColour 
= col
; 
1366         m_graphicContext
->SetTextColor( col 
); 
1367         // in the current implementation the font contains the text color 
1368         m_graphicContext
->SetFont(m_font
); 
1372 void wxDC::SetTextBackground( const wxColour 
&col 
) 
1374     wxCHECK_RET( Ok(), wxT("wxDC(cg)::SetTextBackground - invalid DC") ); 
1376     m_textBackgroundColour 
= col
; 
1379 void wxDC::SetMapMode( int mode 
) 
1384         SetLogicalScale( twips2mm 
* m_mm_to_pix_x
, twips2mm 
* m_mm_to_pix_y 
); 
1388         SetLogicalScale( pt2mm 
* m_mm_to_pix_x
, pt2mm 
* m_mm_to_pix_y 
); 
1392         SetLogicalScale( m_mm_to_pix_x
, m_mm_to_pix_y 
); 
1396         SetLogicalScale( m_mm_to_pix_x 
/ 10.0, m_mm_to_pix_y 
/ 10.0 ); 
1401         SetLogicalScale( 1.0, 1.0 ); 
1405     if (mode 
!= wxMM_TEXT
) 
1407         m_needComputeScaleX 
= 
1408         m_needComputeScaleY 
= true; 
1412 void wxDC::SetUserScale( double x
, double y 
) 
1414     // allow negative ? -> no 
1417     ComputeScaleAndOrigin(); 
1420 void wxDC::SetLogicalScale( double x
, double y 
) 
1423     m_logicalScaleX 
= x
; 
1424     m_logicalScaleY 
= y
; 
1425     ComputeScaleAndOrigin(); 
1428 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y 
) 
1430     m_logicalOriginX 
= x 
* m_signX
;   // is this still correct ? 
1431     m_logicalOriginY 
= y 
* m_signY
; 
1432     ComputeScaleAndOrigin(); 
1435 void wxDC::SetDeviceOrigin( wxCoord x
, wxCoord y 
) 
1437     m_externalDeviceOriginX 
= x
; 
1438     m_externalDeviceOriginY 
= y
; 
1439     ComputeScaleAndOrigin(); 
1442 void wxDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp 
) 
1444     m_signX 
= (xLeftRight 
?  1 : -1); 
1445     m_signY 
= (yBottomUp 
? -1 :  1); 
1446     ComputeScaleAndOrigin(); 
1449 wxSize 
wxDC::GetPPI() const 
1451     return wxSize(72, 72); 
1454 int wxDC::GetDepth() const 
1459 void wxDC::ComputeScaleAndOrigin() 
1461     // CMB: copy scale to see if it changes 
1462     double origScaleX 
= m_scaleX
; 
1463     double origScaleY 
= m_scaleY
; 
1464     m_scaleX 
= m_logicalScaleX 
* m_userScaleX
; 
1465     m_scaleY 
= m_logicalScaleY 
* m_userScaleY
; 
1466     m_deviceOriginX 
= m_externalDeviceOriginX
; 
1467     m_deviceOriginY 
= m_externalDeviceOriginY
; 
1469     // CMB: if scale has changed call SetPen to recalulate the line width 
1470     if (m_scaleX 
!= origScaleX 
|| m_scaleY 
!= origScaleY
) 
1472         // this is a bit artificial, but we need to force wxDC to think 
1473         // the pen has changed 
1474         wxPen 
pen( GetPen() ); 
1481 void wxDC::SetPalette( const wxPalette
& palette 
) 
1485 void wxDC::SetBackgroundMode( int mode 
) 
1487     m_backgroundMode 
= mode 
; 
1490 void wxDC::SetFont( const wxFont 
&font 
) 
1493     if ( m_graphicContext 
) 
1494         m_graphicContext
->SetFont( font 
) ; 
1497 void wxDC::SetPen( const wxPen 
&pen 
) 
1503     if ( m_graphicContext 
) 
1505         if ( m_pen
.GetStyle() == wxSOLID 
|| m_pen
.GetStyle() == wxTRANSPARENT 
) 
1507             m_graphicContext
->SetPen( m_pen 
) ; 
1511             // we have to compensate for moved device origins etc. otherwise patterned pens are standing still 
1512             // eg when using a wxScrollWindow and scrolling around 
1513             int origX 
= XLOG2DEVMAC( 0 ) ; 
1514             int origY 
= YLOG2DEVMAC( 0 ) ; 
1515             m_graphicContext
->Translate( origX 
, origY 
) ; 
1516             m_graphicContext
->SetPen( m_pen 
) ; 
1517             m_graphicContext
->Translate( -origX 
, -origY 
) ; 
1522 void wxDC::SetBrush( const wxBrush 
&brush 
) 
1524     if (m_brush 
== brush
) 
1528     if ( m_graphicContext 
) 
1530         if ( brush
.GetStyle() == wxSOLID 
|| brush
.GetStyle() == wxTRANSPARENT 
) 
1532             m_graphicContext
->SetBrush( m_brush 
) ; 
1536             // we have to compensate for moved device origins etc. otherwise patterned brushes are standing still 
1537             // eg when using a wxScrollWindow and scrolling around 
1538             int origX 
= XLOG2DEVMAC(0) ; 
1539             int origY 
= YLOG2DEVMAC(0) ; 
1540             m_graphicContext
->Translate( origX 
, origY 
) ; 
1541             m_graphicContext
->SetBrush( m_brush 
) ; 
1542             m_graphicContext
->Translate( -origX 
, -origY 
) ; 
1547 void wxDC::SetBackground( const wxBrush 
&brush 
) 
1549     if (m_backgroundBrush 
== brush
) 
1552     m_backgroundBrush 
= brush
; 
1553     if (!m_backgroundBrush
.Ok()) 
1557 void wxDC::SetLogicalFunction( int function 
) 
1559     if (m_logicalFunction 
== function
) 
1562     m_logicalFunction 
= function 
; 
1563 #if wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 
1564     CGContextRef cgContext 
= ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ; 
1565     if ( m_logicalFunction 
== wxCOPY 
) 
1566         CGContextSetBlendMode( cgContext
, kCGBlendModeNormal 
) ; 
1567     else if ( m_logicalFunction 
== wxINVERT 
) 
1568         CGContextSetBlendMode( cgContext
, kCGBlendModeExclusion 
) ; 
1570         CGContextSetBlendMode( cgContext
, kCGBlendModeNormal 
) ; 
1574 extern bool wxDoFloodFill(wxDC 
*dc
, wxCoord x
, wxCoord y
, 
1575                           const wxColour 
& col
, int style
); 
1577 bool wxDC::DoFloodFill(wxCoord x
, wxCoord y
, 
1578                        const wxColour
& col
, int style
) 
1580     return wxDoFloodFill(this, x
, y
, col
, style
); 
1583 bool wxDC::DoGetPixel( wxCoord x
, wxCoord y
, wxColour 
*col 
) const 
1585     wxCHECK_MSG( Ok(), false, wxT("wxDC(cg)::DoGetPixel - invalid DC") ); 
1589     wxMacPortSaver 
helper((CGrafPtr
)m_macPort
) ; 
1590     // NB: GetCPixel is a deprecated QD call, and a slow one at that 
1592         XLOG2DEVMAC(x
) + m_macLocalOriginInPort
.x 
- m_macLocalOrigin
.x
, 
1593         YLOG2DEVMAC(y
) + m_macLocalOriginInPort
.y 
- m_macLocalOrigin
.y
, &colour 
); 
1595     // convert from Mac colour to wx 
1601 void wxDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2 
) 
1603     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawLine - invalid DC") ); 
1605 #if !wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 
1606     if ( m_logicalFunction 
!= wxCOPY 
) 
1610     wxCoord xx1 
= XLOG2DEVMAC(x1
) ; 
1611     wxCoord yy1 
= YLOG2DEVMAC(y1
) ; 
1612     wxCoord xx2 
= XLOG2DEVMAC(x2
) ; 
1613     wxCoord yy2 
= YLOG2DEVMAC(y2
) ; 
1615     wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
1616     path
->MoveToPoint( xx1
, yy1 
) ; 
1617     path
->AddLineToPoint( xx2 
, yy2 
) ; 
1618     path
->CloseSubpath() ; 
1619     m_graphicContext
->StrokePath( path 
) ; 
1622     CalcBoundingBox(x1
, y1
); 
1623     CalcBoundingBox(x2
, y2
); 
1626 void wxDC::DoCrossHair( wxCoord x
, wxCoord y 
) 
1628     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoCrossHair - invalid DC") ); 
1630     if ( m_logicalFunction 
!= wxCOPY 
) 
1636     wxCoord xx 
= XLOG2DEVMAC(x
); 
1637     wxCoord yy 
= YLOG2DEVMAC(y
); 
1639     wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
1640     path
->MoveToPoint( XLOG2DEVMAC(0), yy 
) ; 
1641     path
->AddLineToPoint( XLOG2DEVMAC(w
), yy 
) ; 
1642     path
->CloseSubpath() ; 
1643     path
->MoveToPoint( xx
, YLOG2DEVMAC(0) ) ; 
1644     path
->AddLineToPoint( xx
, YLOG2DEVMAC(h
) ) ; 
1645     path
->CloseSubpath() ; 
1646     m_graphicContext
->StrokePath( path 
) ; 
1649     CalcBoundingBox(x
, y
); 
1650     CalcBoundingBox(x 
+ w
, y 
+ h
); 
1653 void wxDC::DoDrawArc( wxCoord x1
, wxCoord y1
, 
1654                       wxCoord x2
, wxCoord y2
, 
1655                       wxCoord xc
, wxCoord yc 
) 
1657     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawArc - invalid DC") ); 
1659     if ( m_logicalFunction 
!= wxCOPY 
) 
1662     wxCoord xx1 
= XLOG2DEVMAC(x1
); 
1663     wxCoord yy1 
= YLOG2DEVMAC(y1
); 
1664     wxCoord xx2 
= XLOG2DEVMAC(x2
); 
1665     wxCoord yy2 
= YLOG2DEVMAC(y2
); 
1666     wxCoord xxc 
= XLOG2DEVMAC(xc
); 
1667     wxCoord yyc 
= YLOG2DEVMAC(yc
); 
1669     double dx 
= xx1 
- xxc
; 
1670     double dy 
= yy1 
- yyc
; 
1671     double radius 
= sqrt((double)(dx 
* dx 
+ dy 
* dy
)); 
1672     wxCoord rad 
= (wxCoord
)radius
; 
1674     if (xx1 
== xx2 
&& yy1 
== yy2
) 
1679     else if (radius 
== 0.0) 
1685         sa 
= (xx1 
- xxc 
== 0) ? 
1686             (yy1 
- yyc 
< 0) ? 90.0 : -90.0 : 
1687         -atan2(double(yy1 
- yyc
), double(xx1 
- xxc
)) * RAD2DEG
; 
1688         ea 
= (xx2 
- xxc 
== 0) ? 
1689             (yy2 
- yyc 
< 0) ? 90.0 : -90.0 : 
1690         -atan2(double(yy2 
- yyc
), double(xx2 
- xxc
)) * RAD2DEG
; 
1693     bool fill 
= m_brush
.GetStyle() != wxTRANSPARENT 
; 
1695     wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
1696     m_graphicContext
->PushState() ; 
1697     m_graphicContext
->Translate( xxc
, yyc 
) ; 
1698     m_graphicContext
->Scale( 1, -1 ) ; 
1700         path
->MoveToPoint( 0, 0 ) ; 
1701     path
->AddArc( 0, 0, rad 
, DegToRad(sa
) , DegToRad(ea
), false ) ; 
1703         path
->AddLineToPoint( 0, 0 ) ; 
1704     m_graphicContext
->DrawPath( path 
) ; 
1705     m_graphicContext
->PopState() ; 
1709 void wxDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
, 
1710                               double sa
, double ea 
) 
1712     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawEllipticArc - invalid DC") ); 
1714     if ( m_logicalFunction 
!= wxCOPY 
) 
1717     wxCoord xx 
= XLOG2DEVMAC(x
); 
1718     wxCoord yy 
= YLOG2DEVMAC(y
); 
1719     wxCoord ww 
= m_signX 
* XLOG2DEVREL(w
); 
1720     wxCoord hh 
= m_signY 
* YLOG2DEVREL(h
); 
1722     // handle -ve width and/or height 
1734     bool fill 
= m_brush
.GetStyle() != wxTRANSPARENT 
; 
1736     wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
1737     m_graphicContext
->PushState() ; 
1738     m_graphicContext
->Translate( xx 
+ ww 
/ 2, yy 
+ hh 
/ 2 ) ; 
1739     m_graphicContext
->Scale( 1 * ww 
/ 2 , -1 * hh 
/ 2 ) ; 
1741         path
->MoveToPoint( 0, 0 ) ; 
1742     path
->AddArc( 0, 0, 1 , DegToRad(sa
) , DegToRad(ea
), false ) ; 
1744         path
->AddLineToPoint( 0, 0 ) ; 
1745     m_graphicContext
->DrawPath( path 
) ; 
1746     m_graphicContext
->PopState() ; 
1750 void wxDC::DoDrawPoint( wxCoord x
, wxCoord y 
) 
1752     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawPoint - invalid DC") ); 
1754     DoDrawLine( x 
, y 
, x 
+ 1 , y 
+ 1 ) ; 
1757 void wxDC::DoDrawLines(int n
, wxPoint points
[], 
1758                         wxCoord xoffset
, wxCoord yoffset
) 
1760     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawLines - invalid DC") ); 
1762 #if !wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 
1763     if ( m_logicalFunction 
!= wxCOPY 
) 
1767     wxCoord x1
, x2 
, y1 
, y2 
; 
1768     x1 
= XLOG2DEVMAC(points
[0].x 
+ xoffset
); 
1769     y1 
= YLOG2DEVMAC(points
[0].y 
+ yoffset
); 
1770     wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
1771     path
->MoveToPoint( x1 
, y1 
) ; 
1772     for (int i 
= 1; i 
< n
; i
++) 
1774         x2 
= XLOG2DEVMAC(points
[i
].x 
+ xoffset
); 
1775         y2 
= YLOG2DEVMAC(points
[i
].y 
+ yoffset
); 
1777         path
->AddLineToPoint( x2 
, y2 
) ; 
1780     m_graphicContext
->StrokePath( path 
) ; 
1785 void wxDC::DoDrawSpline(wxList 
*points
) 
1787     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawSpline - invalid DC") ); 
1789     if ( m_logicalFunction 
!= wxCOPY 
) 
1792     wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
1794     wxList::compatibility_iterator node 
= points
->GetFirst(); 
1795     if (node 
== wxList::compatibility_iterator()) 
1799     wxPoint 
*p 
= (wxPoint 
*)node
->GetData(); 
1804     node 
= node
->GetNext(); 
1805     p 
= (wxPoint 
*)node
->GetData(); 
1809     wxCoord cx1 
= ( x1 
+ x2 
) / 2; 
1810     wxCoord cy1 
= ( y1 
+ y2 
) / 2; 
1812     path
->MoveToPoint( XLOG2DEVMAC( x1 
) , YLOG2DEVMAC( y1 
) ) ; 
1813     path
->AddLineToPoint( XLOG2DEVMAC( cx1 
) , YLOG2DEVMAC( cy1 
) ) ; 
1816     while ((node 
= node
->GetNext()) != NULL
) 
1818     while ((node 
= node
->GetNext())) 
1819 #endif // !wxUSE_STL 
1821         p 
= (wxPoint 
*)node
->GetData(); 
1826         wxCoord cx4 
= (x1 
+ x2
) / 2; 
1827         wxCoord cy4 
= (y1 
+ y2
) / 2; 
1829         path
->AddQuadCurveToPoint( 
1830             XLOG2DEVMAC( x1 
) , YLOG2DEVMAC( y1 
) , 
1831             XLOG2DEVMAC( cx4 
) , YLOG2DEVMAC( cy4 
) ) ; 
1837     path
->AddLineToPoint( XLOG2DEVMAC( x2 
) , YLOG2DEVMAC( y2 
) ) ; 
1839     m_graphicContext
->StrokePath( path 
) ; 
1844 void wxDC::DoDrawPolygon( int n
, wxPoint points
[], 
1845                           wxCoord xoffset
, wxCoord yoffset
, 
1848     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawPolygon - invalid DC") ); 
1850     if ( n 
<= 0 || (m_brush
.GetStyle() == wxTRANSPARENT 
&& m_pen
.GetStyle() == wxTRANSPARENT 
) ) 
1852     if ( m_logicalFunction 
!= wxCOPY 
) 
1855     wxCoord x1
, x2 
, y1 
, y2 
; 
1856     x2 
= x1 
= XLOG2DEVMAC(points
[0].x 
+ xoffset
); 
1857     y2 
= y1 
= YLOG2DEVMAC(points
[0].y 
+ yoffset
); 
1859     wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
1860     path
->MoveToPoint( x1 
, y1 
) ; 
1861     for (int i 
= 1; i 
< n
; i
++) 
1863         x2 
= XLOG2DEVMAC(points
[i
].x 
+ xoffset
); 
1864         y2 
= YLOG2DEVMAC(points
[i
].y 
+ yoffset
); 
1866         path
->AddLineToPoint( x2 
, y2 
) ; 
1869     if ( x1 
!= x2 
|| y1 
!= y2 
) 
1870         path
->AddLineToPoint( x1
, y1 
) ; 
1872     path
->CloseSubpath() ; 
1873     m_graphicContext
->DrawPath( path 
, fillStyle 
) ; 
1878 void wxDC::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
) 
1880     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawRectangle - invalid DC") ); 
1882     if ( m_logicalFunction 
!= wxCOPY 
) 
1885     wxCoord xx 
= XLOG2DEVMAC(x
); 
1886     wxCoord yy 
= YLOG2DEVMAC(y
); 
1887     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
1888     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
1890     // CMB: draw nothing if transformed w or h is 0 
1891     if (ww 
== 0 || hh 
== 0) 
1894     // CMB: handle -ve width and/or height 
1906     int penwidth 
= m_pen
.GetWidth(); 
1907     if ( penwidth 
== 0 ) 
1909     if ( m_pen
.GetStyle() == wxTRANSPARENT 
) 
1912     bool offset 
= ( penwidth 
% 2 ) == 1 ; 
1914     wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
1915     // if we are offsetting the entire rectangle is moved 0.5, so the border line gets off by 1 
1917         path
->AddRectangle( xx 
, yy 
, ww
-1 , hh
-1 ) ; 
1919         path
->AddRectangle( xx 
, yy 
, ww 
, hh 
) ; 
1921     m_graphicContext
->DrawPath( path 
) ; 
1925 void wxDC::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, 
1926                                    wxCoord width
, wxCoord height
, 
1929     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawRoundedRectangle - invalid DC") ); 
1931     if ( m_logicalFunction 
!= wxCOPY 
) 
1935         radius 
= - radius 
* ((width 
< height
) ? width 
: height
); 
1936     wxCoord xx 
= XLOG2DEVMAC(x
); 
1937     wxCoord yy 
= YLOG2DEVMAC(y
); 
1938     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
1939     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
1941     // CMB: draw nothing if transformed w or h is 0 
1942     if (ww 
== 0 || hh 
== 0) 
1945     // CMB: handle -ve width and/or height 
1957     wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
1960         path
->AddRectangle( xx 
, yy 
, ww 
, hh 
) ; 
1961         m_graphicContext
->DrawPath( path 
) ; 
1965         path
->MoveToPoint( xx 
+ ww
, yy 
+ hh 
/ 2); 
1966         path
->AddArcToPoint(xx 
+ ww
, yy 
+ hh
, xx 
+ ww 
/ 2,yy 
+  hh
, radius
); 
1967         path
->AddArcToPoint(xx 
, yy 
+ hh
, xx 
, yy 
+ hh 
/ 2, radius
); 
1968         path
->AddArcToPoint(xx 
, yy 
, xx 
+ ww 
/ 2, yy 
, radius
); 
1969         path
->AddArcToPoint(xx 
+ ww
, yy 
, xx 
+ ww
, yy 
+ hh 
/ 2, radius
); 
1970         path
->CloseSubpath(); 
1971         m_graphicContext
->DrawPath( path 
) ; 
1976 void wxDC::DoDrawEllipse(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
) 
1978     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawEllipse - invalid DC") ); 
1980     if ( m_logicalFunction 
!= wxCOPY 
) 
1983     wxCoord xx 
= XLOG2DEVMAC(x
); 
1984     wxCoord yy 
= YLOG2DEVMAC(y
); 
1985     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
1986     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
1988     // CMB: draw nothing if transformed w or h is 0 
1989     if (ww 
== 0 || hh 
== 0) 
1992     // CMB: handle -ve width and/or height 
2004     wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
2005     m_graphicContext
->PushState() ; 
2006     m_graphicContext
->Translate(xx 
+ ww 
/ 2, yy 
+ hh 
/ 2); 
2007     m_graphicContext
->Scale(ww 
/ 2 , hh 
/ 2); 
2008     path
->AddArc( 0, 0, 1, 0 , 2 * M_PI 
, false ) ; 
2009     m_graphicContext
->DrawPath( path 
) ; 
2010     m_graphicContext
->PopState() ; 
2014 bool wxDC::CanDrawBitmap() const 
2020     wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
, 
2021     wxDC 
*source
, wxCoord xsrc
, wxCoord ysrc
, int logical_func 
, bool useMask
, 
2022     wxCoord xsrcMask
, wxCoord ysrcMask 
) 
2024     return DoStretchBlit( xdest
, ydest
, width
, height
, 
2025                            source
, xsrc
, ysrc
, width
, height
,  
2026                            logical_func
, useMask
, 
2027                            xsrcMask
, ysrcMask 
); 
2030 bool wxDC::DoStretchBlit(wxCoord xdest
, wxCoord ydest
, 
2031                          wxCoord dstWidth
, wxCoord dstHeight
, 
2033                          wxCoord xsrc
, wxCoord ysrc
, 
2034                          wxCoord srcWidth
, wxCoord srcHeight
, 
2035                          int logical_func 
= wxCOPY
, bool useMask 
= false, 
2036                          wxCoord xsrcMask 
= wxDefaultCoord
, wxCoord ysrcMask 
= wxDefaultCoord
); 
2038     wxCHECK_MSG( Ok(), false, wxT("wxDC(cg)::DoStretchBlit - invalid DC") ); 
2039     wxCHECK_MSG( source
->Ok(), false, wxT("wxDC(cg)::DoStretchBlit - invalid source DC") ); 
2041     if ( logical_func 
== wxNO_OP 
) 
2044     if (xsrcMask 
== -1 && ysrcMask 
== -1) 
2050     wxCoord yysrc 
= source
->YLOG2DEVMAC(ysrc
) ; 
2051     wxCoord xxsrc 
= source
->XLOG2DEVMAC(xsrc
) ; 
2052     wxCoord wwsrc 
= source
->XLOG2DEVREL(srcWidth
) ; 
2053     wxCoord hhsrc 
= source
->YLOG2DEVREL(srcHeight
) ; 
2055     wxCoord yydest 
= YLOG2DEVMAC(ydest
) ; 
2056     wxCoord xxdest 
= XLOG2DEVMAC(xdest
) ; 
2057     wxCoord wwdest 
= XLOG2DEVREL(dstWidth
) ; 
2058     wxCoord hhdest 
= YLOG2DEVREL(dstHeight
) ; 
2060     wxMemoryDC
* memdc 
= dynamic_cast<wxMemoryDC
*>(source
) ; 
2061     if ( memdc 
&& logical_func 
== wxCOPY 
) 
2063         wxBitmap blit 
= memdc
->GetSelectedObject() ; 
2065         wxASSERT_MSG( blit
.Ok() , wxT("Invalid bitmap for blitting") ) ; 
2067         wxCoord bmpwidth 
= blit
.GetWidth(); 
2068         wxCoord bmpheight 
= blit
.GetHeight(); 
2070         if ( xxsrc 
!= 0 || yysrc 
!= 0 || bmpwidth 
!= wwsrc 
|| bmpheight 
!= hhsrc 
) 
2072             wwsrc 
= wxMin( wwsrc 
, bmpwidth 
- xxsrc 
) ; 
2073             hhsrc 
= wxMin( hhsrc 
, bmpheight 
- yysrc 
) ; 
2074             if ( wwsrc 
> 0 && hhsrc 
> 0 ) 
2076                 if ( xxsrc 
>= 0 && yysrc 
>= 0 ) 
2078                     wxRect 
subrect( xxsrc
, yysrc
, wwsrc 
, hhsrc 
) ; 
2079                     // TODO we perhaps could add a DrawSubBitmap call to dc for performance reasons 
2080                     blit 
= blit
.GetSubBitmap( subrect 
) ; 
2084                     // in this case we'd probably have to adjust the different coordinates, but 
2085                     // we have to find out proper contract first 
2086                     blit 
= wxNullBitmap 
; 
2091                 blit 
= wxNullBitmap 
; 
2097             m_graphicContext
->DrawBitmap( blit
, xxdest 
, yydest 
, wwdest 
, hhdest 
) ; 
2102         wxFAIL_MSG( wxT("Blitting is only supported from bitmap contexts, and only with wxCOPY logical operation.") ) ; 
2109 void wxDC::DoDrawRotatedText(const wxString
& str
, wxCoord x
, wxCoord y
, 
2112     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawRotatedText - invalid DC") ); 
2113 //    wxCHECK_RET( m_macATSUIStyle != NULL, wxT("wxDC(cg)::DoDrawRotatedText - no valid font set") ); 
2115     if ( str
.length() == 0 ) 
2117     if ( m_logicalFunction 
!= wxCOPY 
) 
2120     int drawX 
= XLOG2DEVMAC(x
) ; 
2121     int drawY 
= YLOG2DEVMAC(y
) ; 
2123     m_graphicContext
->DrawText( str
, drawX 
,drawY 
, angle 
) ; 
2126 void wxDC::DoDrawText(const wxString
& strtext
, wxCoord x
, wxCoord y
) 
2128     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawText - invalid DC") ); 
2130     DoDrawRotatedText( strtext 
, x 
, y 
, 0.0 ) ; 
2133 bool wxDC::CanGetTextExtent() const 
2135     wxCHECK_MSG( Ok(), false, wxT("wxDC(cg)::CanGetTextExtent - invalid DC") ); 
2140 void wxDC::DoGetTextExtent( const wxString 
&str
, wxCoord 
*width
, wxCoord 
*height
, 
2141                             wxCoord 
*descent
, wxCoord 
*externalLeading 
, 
2142                             const wxFont 
*theFont 
) const 
2144     wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoGetTextExtent - invalid DC") ); 
2148         m_graphicContext
->SetFont( *theFont 
) ; 
2151     wxCoord h 
, d 
, e 
, w 
; 
2153     m_graphicContext
->GetTextExtent( str
, &w
, &h
, &d
, &e 
) ; 
2156         *height 
= YDEV2LOGREL( h 
) ; 
2158         *descent 
=YDEV2LOGREL( d
); 
2159     if ( externalLeading 
) 
2160         *externalLeading 
= YDEV2LOGREL( e
); 
2162         *width 
= XDEV2LOGREL( w 
) ; 
2166         m_graphicContext
->SetFont( m_font 
) ; 
2170 bool wxDC::DoGetPartialTextExtents(const wxString
& text
, wxArrayInt
& widths
) const 
2172     wxCHECK_MSG( Ok(), false, wxT("wxDC(cg)::DoGetPartialTextExtents - invalid DC") ); 
2174     m_graphicContext
->GetPartialTextExtents( text
, widths 
) ; 
2175     for ( size_t i 
= 0 ; i 
< widths
.GetCount() ; ++i 
) 
2176         widths
[i
] = XDEV2LOGREL( widths
[i
] ); 
2181 wxCoord 
wxDC::GetCharWidth(void) const 
2184     DoGetTextExtent( wxT("g") , &width 
, NULL 
, NULL 
, NULL 
, NULL 
) ; 
2189 wxCoord 
wxDC::GetCharHeight(void) const 
2192     DoGetTextExtent( wxT("g") , NULL 
, &height 
, NULL 
, NULL 
, NULL 
) ; 
2197 void wxDC::Clear(void) 
2199     wxCHECK_RET( Ok(), wxT("wxDC(cg)::Clear - invalid DC") ); 
2201     if (m_backgroundBrush
.Ok() && m_backgroundBrush
.GetStyle() != wxTRANSPARENT
) 
2203         HIRect rect 
= CGRectMake( -10000 , -10000 , 20000 , 20000 ) ; 
2204         CGContextRef cg 
= ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ; 
2205         switch ( m_backgroundBrush
.MacGetBrushKind() ) 
2207             case kwxMacBrushTheme 
: 
2209 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 
2210                     if ( HIThemeSetFill 
!= 0 ) 
2212                         HIThemeSetFill( m_backgroundBrush
.MacGetTheme(), NULL
, cg
, kHIThemeOrientationNormal 
); 
2213                         CGContextFillRect(cg
, rect
); 
2220                         GetThemeBrushAsColor( m_backgroundBrush
.MacGetTheme(), 32, true, &color 
); 
2221                         CGContextSetRGBFillColor( cg
, (CGFloat
) color
.red 
/ 65536, 
2222                             (CGFloat
) color
.green 
/ 65536, (CGFloat
) color
.blue 
/ 65536, 1 ); 
2223                             CGContextFillRect( cg
, rect 
); 
2226                     // reset to normal value 
2227                     RGBColor col 
= MAC_WXCOLORREF( GetBrush().GetColour().GetPixel() ) ; 
2228                     CGContextSetRGBFillColor( cg
, col
.red 
/ 65536.0, col
.green 
/ 65536.0, col
.blue 
/ 65536.0, 1.0 ); 
2232             case kwxMacBrushThemeBackground 
: 
2234                     wxFAIL_MSG( wxT("There shouldn't be theme backgrounds under Quartz") ) ; 
2236 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 
2237                     if ( UMAGetSystemVersion() >= 0x1030 ) 
2239                         HIThemeBackgroundDrawInfo drawInfo 
; 
2240                         drawInfo
.version 
= 0 ; 
2241                         drawInfo
.state 
= kThemeStateActive 
; 
2242                         drawInfo
.kind 
= m_backgroundBrush
.MacGetThemeBackground( NULL 
) ; 
2243                         if ( drawInfo
.kind 
== kThemeBackgroundMetal 
) 
2245                             HIThemeDrawBackground( &rect
, &drawInfo
, cg
, kHIThemeOrientationNormal 
) ; 
2246                             HIThemeApplyBackground( &rect
, &drawInfo
, cg
, kHIThemeOrientationNormal 
) ; 
2253             case kwxMacBrushColour 
: 
2255                     // FIXME: doesn't correctly render stippled brushes !! 
2256                     // FIXME: should this be replaced by ::SetBrush() ?? 
2258                     RGBColor col 
= MAC_WXCOLORREF( m_backgroundBrush
.GetColour().GetPixel()) ; 
2259                     CGContextSetRGBFillColor( cg 
, col
.red 
/ 65536.0 , col
.green 
/ 65536.0 , col
.blue 
/ 65536.0 , 1.0 ) ; 
2260                     CGContextFillRect(cg
, rect
); 
2262                     // reset to normal value 
2263                     col 
= MAC_WXCOLORREF( GetBrush().GetColour().GetPixel() ) ; 
2264                     CGContextSetRGBFillColor( cg 
, col
.red 
/ 65536.0 , col
.green 
/ 65536.0 , col
.blue 
/ 65536.0 , 1.0 ) ; 
2269                 wxFAIL_MSG( wxT("unknown brush kind") ) ; 
2279 // --------------------------------------------------------------------------- 
2280 // coordinates transformations 
2281 // --------------------------------------------------------------------------- 
2283     wxCoord XLOG2DEVMAC(wxCoord x) const 
2285         long new_x = x - m_logicalOriginX; 
2287             return (wxCoord)((double)new_x * m_scaleX + 0.5) * m_signX + m_deviceOriginX + m_macLocalOrigin.x; 
2289             return (wxCoord)((double)new_x * m_scaleX - 0.5) * m_signX + m_deviceOriginX + m_macLocalOrigin.x; 
2292     wxCoord YLOG2DEVMAC(wxCoord y) const 
2294         long new_y = y - m_logicalOriginY; 
2296             return (wxCoord)((double)new_y * m_scaleY + 0.5) * m_signY + m_deviceOriginY + m_macLocalOrigin.y; 
2298             return (wxCoord)((double)new_y * m_scaleY - 0.5) * m_signY + m_deviceOriginY + m_macLocalOrigin.y; 
2301 wxCoord wxDC::DeviceToLogicalX(wxCoord x) const 
2303     return wxRound((double)(x - m_deviceOriginX) / m_scaleX) * m_signX + m_logicalOriginX; 
2306 wxCoord wxDC::DeviceToLogicalY(wxCoord y) const 
2308     return wxRound((double)(y - m_deviceOriginY) / m_scaleY) * m_signY + m_logicalOriginY; 
2311 wxCoord wxDC::DeviceToLogicalXRel(wxCoord x) const 
2313     return wxRound((double)(x) / m_scaleX); 
2316 wxCoord wxDC::DeviceToLogicalYRel(wxCoord y) const 
2318     return wxRound((double)(y) / m_scaleY); 
2321 wxCoord wxDC::LogicalToDeviceX(wxCoord x) const 
2323     return wxRound((double)(x - m_logicalOriginX) * m_scaleX) * m_signX + m_deviceOriginX; 
2326 wxCoord wxDC::LogicalToDeviceY(wxCoord y) const 
2328     return wxRound((double)(y - m_logicalOriginY) * m_scaleY) * m_signY + m_deviceOriginY; 
2331 wxCoord wxDC::LogicalToDeviceXRel(wxCoord x) const 
2333     return wxRound((double)(x) * m_scaleX); 
2336 wxCoord wxDC::LogicalToDeviceYRel(wxCoord y) const 
2338     return wxRound((double)(y) * m_scaleY); 
2341 #endif // wxMAC_USE_CORE_GRAPHICS