1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) Stefan Csomor 
   9 // Licence:       wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation "dc.h" 
  16 #include "wx/wxprec.h" 
  20 #if wxMAC_USE_CORE_GRAPHICS 
  23 #include "wx/mac/uma.h" 
  24 #include "wx/dcmemory.h" 
  25 #include "wx/dcprint.h" 
  26 #include "wx/region.h" 
  36 #include "wx/mac/private.h" 
  37 #include <ATSUnicode.h> 
  38 #include <TextCommon.h> 
  39 #include <TextEncodingConverter.h> 
  41 #include <CGContext.h> 
  43 #if !USE_SHARED_LIBRARY 
  44 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
) 
  47 //----------------------------------------------------------------------------- 
  49 //----------------------------------------------------------------------------- 
  51 #if !defined( __DARWIN__ ) || defined(__MWERKS__) 
  53 const double M_PI 
= 3.14159265358979 ; 
  56 const double RAD2DEG  
= 180.0 / M_PI
; 
  57 const short kEmulatedMode 
= -1 ; 
  58 const short kUnsupportedMode 
= -2 ; 
  60 extern TECObjectRef s_TECNativeCToUnicode 
; 
  63 // The text ctrl implementation still needs that for the non hiview implementation 
  65 wxMacWindowClipper::wxMacWindowClipper( const wxWindow
* win 
) : 
  66     wxMacPortSaver( (GrafPtr
) GetWindowPort((WindowRef
) win
->MacGetTopLevelWindowRef()) ) 
  68     m_newPort 
=(GrafPtr
) GetWindowPort((WindowRef
) win
->MacGetTopLevelWindowRef()) ; 
  69     m_formerClip 
= NewRgn() ; 
  70     m_newClip 
= NewRgn() ; 
  71     GetClip( m_formerClip 
) ; 
  75         // guard against half constructed objects, this just leads to a empty clip 
  79             win
->MacWindowToRootWindow( &x
,&y 
) ; 
  80             // get area including focus rect 
  81             CopyRgn( (RgnHandle
) ((wxWindow
*)win
)->MacGetVisibleRegion(true).GetWXHRGN() , m_newClip 
) ; 
  82             if ( !EmptyRgn( m_newClip 
) ) 
  83                 OffsetRgn( m_newClip 
, x 
, y 
) ; 
  86         SetClip( m_newClip 
) ; 
  90 wxMacWindowClipper::~wxMacWindowClipper()  
  92     SetPort( m_newPort 
) ; 
  93     SetClip( m_formerClip 
) ; 
  94     DisposeRgn( m_newClip 
) ; 
  95     DisposeRgn( m_formerClip 
) ; 
  98 wxMacWindowStateSaver::wxMacWindowStateSaver( const wxWindow
* win 
) : 
  99     wxMacWindowClipper( win 
) 
 101     // the port is already set at this point 
 102     m_newPort 
=(GrafPtr
) GetWindowPort((WindowRef
) win
->MacGetTopLevelWindowRef()) ; 
 103     GetThemeDrawingState( &m_themeDrawingState 
) ; 
 106 wxMacWindowStateSaver::~wxMacWindowStateSaver()  
 108     SetPort( m_newPort 
) ; 
 109     SetThemeDrawingState( m_themeDrawingState 
, true ) ; 
 112 // minimal implementation only used for appearance drawing < 10.3 
 114 wxMacPortSetter::wxMacPortSetter( const wxDC
* dc 
) : 
 115     m_ph( (GrafPtr
) dc
->m_macPort 
) 
 117     wxASSERT( dc
->Ok() ) ; 
 119 //    dc->MacSetupPort(&m_ph) ; 
 121 wxMacPortSetter::~wxMacPortSetter() 
 123 //    m_dc->MacCleanupPort(&m_ph) ; 
 126 //----------------------------------------------------------------------------- 
 128 //----------------------------------------------------------------------------- 
 130 static inline double dmin(double a
, double b
) { return a 
< b 
? a 
: b
; } 
 131 static inline double dmax(double a
, double b
) { return a 
> b 
? a 
: b
; } 
 132 static inline double DegToRad(double deg
) { return (deg 
* M_PI
) / 180.0; } 
 134 //----------------------------------------------------------------------------- 
 135 // device context implementation 
 137 // more and more of the dc functionality should be implemented by calling 
 138 // the appropricate wxMacCGContext, but we will have to do that step by step 
 139 // also coordinate conversions should be moved to native matrix ops 
 140 //----------------------------------------------------------------------------- 
 142 wxMacCGPath::wxMacCGPath() 
 144     m_path 
= CGPathCreateMutable() ; 
 147 wxMacCGPath::~wxMacCGPath() 
 149     CGPathRelease( m_path 
) ; 
 152 //  Starts a new subpath at 
 153 void wxMacCGPath::MoveToPoint( wxCoord x1 
, wxCoord y1 
) 
 155     CGPathMoveToPoint( m_path 
, NULL 
, x1 
, y1 
) ; 
 158 void wxMacCGPath::AddLineToPoint( wxCoord x1 
, wxCoord y1 
)  
 160     CGPathAddLineToPoint( m_path 
, NULL 
, x1 
, y1 
) ; 
 163 void wxMacCGPath::AddRectangle( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h 
) 
 165     CGRect cgRect 
= { { x 
, y 
} , { w 
, h 
} } ; 
 166     CGPathAddRect( m_path 
, NULL 
, cgRect 
) ; 
 169 void wxMacCGPath::AddCircle( wxCoord x
, wxCoord y 
, wxCoord r 
) 
 171     CGPathAddArc( m_path 
, NULL 
, x 
, y 
, r 
, 0.0 , 2 * M_PI 
, true ) ; 
 174 // closes the current subpath 
 175 void wxMacCGPath::CloseSubpath() 
 177     CGPathCloseSubpath( m_path 
) ; 
 180 CGPathRef 
wxMacCGPath::GetPath() const  
 185 // we always stock two context states, one at entry, the other one after  
 186 // changing to HI Graphics orientation (this one is used for getting back clippings etc) 
 188 wxMacCGContext::wxMacCGContext( CGrafPtr port 
)  
 194 wxMacCGContext::wxMacCGContext( CGContextRef cgcontext 
) 
 197     m_cgContext 
= cgcontext 
; 
 198     CGContextSaveGState( m_cgContext 
) ; 
 199     CGContextSaveGState( m_cgContext 
) ; 
 202 wxMacCGContext::wxMacCGContext() 
 208 wxMacCGContext::~wxMacCGContext()  
 212         CGContextSynchronize( m_cgContext 
) ; 
 213         CGContextRestoreGState( m_cgContext 
) ; 
 214         CGContextRestoreGState( m_cgContext 
) ; 
 217         CGContextRelease( m_cgContext 
) ; 
 221 void wxMacCGContext::Clip( const wxRegion 
®ion 
) 
 223 //        ClipCGContextToRegion ( m_cgContext, &bounds , (RgnHandle) dc->m_macCurrentClipRgn ) ; 
 226 void wxMacCGContext::StrokePath( const wxGraphicPath 
*p 
)  
 228     const wxMacCGPath
* path 
= dynamic_cast< const wxMacCGPath
*>( p 
) ; 
 229     CGContextBeginPath( m_cgContext 
) ; 
 230     CGContextAddPath( m_cgContext 
, path
->GetPath() ) ; 
 231     CGContextClosePath( m_cgContext 
) ; 
 232     CGContextStrokePath( m_cgContext 
) ; 
 235 void wxMacCGContext::DrawPath( const wxGraphicPath 
*p 
, int fillStyle 
)  
 237     const wxMacCGPath
* path 
= dynamic_cast< const wxMacCGPath
*>( p 
) ; 
 238     CGPathDrawingMode mode 
= m_mode 
; 
 239     if ( fillStyle 
== wxODDEVEN_RULE 
) 
 241         if ( mode 
== kCGPathFill 
) 
 242             mode 
= kCGPathEOFill 
; 
 243         else if ( mode 
== kCGPathFillStroke 
) 
 244             mode 
= kCGPathEOFillStroke 
; 
 246     CGContextBeginPath( m_cgContext 
) ; 
 247     CGContextAddPath( m_cgContext 
, path
->GetPath() ) ; 
 248     CGContextClosePath( m_cgContext 
) ; 
 249     CGContextDrawPath( m_cgContext 
, mode 
) ; 
 252 void wxMacCGContext::FillPath( const wxGraphicPath 
*p 
, const wxColor 
&fillColor 
, int fillStyle 
)  
 254     const wxMacCGPath
* path 
= dynamic_cast< const wxMacCGPath
*>( p 
) ; 
 255     CGContextSaveGState( m_cgContext 
) ; 
 257     RGBColor col 
= MAC_WXCOLORREF( fillColor
.GetPixel() ) ; 
 258     CGContextSetRGBFillColor( m_cgContext 
, col
.red 
/ 65536.0 , col
.green 
/ 65536.0 , col
.blue 
/ 65536.0 , 1.0 ) ; 
 259     CGPathDrawingMode mode 
= kCGPathFill 
; 
 261     if ( fillStyle 
== wxODDEVEN_RULE 
) 
 262         mode 
= kCGPathEOFill 
; 
 264     CGContextBeginPath( m_cgContext 
) ; 
 265     CGContextAddPath( m_cgContext 
, path
->GetPath() ) ; 
 266     CGContextClosePath( m_cgContext 
) ; 
 267     CGContextDrawPath( m_cgContext 
, mode 
) ; 
 269     CGContextRestoreGState( m_cgContext 
) ; 
 272 wxGraphicPath
* wxMacCGContext::CreatePath()  
 274     // make sure that we now have a real cgref, before doing 
 275     // anything with paths 
 276     CGContextRef cg 
= GetNativeContext() ; 
 278     return new wxMacCGPath() ;  
 281 // in case we only got a QDPort only create a cgref now 
 283 CGContextRef 
wxMacCGContext::GetNativeContext()  
 285     if( m_cgContext 
== NULL 
) 
 288         GetPortBounds( (CGrafPtr
) m_qdPort 
, &bounds 
) ; 
 289         OSStatus status 
= CreateCGContextForPort((CGrafPtr
) m_qdPort 
, &m_cgContext
) ; 
 290         CGContextSaveGState( m_cgContext 
) ; 
 292         wxASSERT_MSG( status 
== noErr 
, wxT("Cannot nest wxDCs on the same window") ) ; 
 293         CGContextTranslateCTM( m_cgContext 
, 0 , bounds
.bottom 
- bounds
.top 
) ; 
 294         CGContextScaleCTM( m_cgContext 
, 1 , -1 ) ; 
 296         CGContextSaveGState( m_cgContext 
) ; 
 298         SetBrush( m_brush 
) ; 
 303 void wxMacCGContext::SetNativeContext( CGContextRef cg 
)  
 305     wxASSERT( m_cgContext 
== NULL 
) ; 
 307     CGContextSaveGState( m_cgContext 
) ; 
 310 void wxMacCGContext::SetPen( const wxPen 
&pen 
) 
 313     if ( m_cgContext 
== NULL 
) 
 315     bool fill 
= m_brush
.GetStyle() != wxTRANSPARENT 
; 
 316     bool stroke 
= pen
.GetStyle() != wxTRANSPARENT 
; 
 319     // we can benchmark performance, should go into a setting later 
 320     CGContextSetShouldAntialias( m_cgContext 
, false ) ; 
 325         m_mode 
= kCGPathFill 
; // just a default 
 329             m_mode 
= kCGPathFill 
; 
 333             RGBColor col 
= MAC_WXCOLORREF( pen
.GetColour().GetPixel() ) ; 
 334             CGContextSetRGBStrokeColor( m_cgContext 
, col
.red 
/ 65536.0 , col
.green 
/ 65536.0 , col
.blue 
/ 65536.0 , 1.0 ) ; 
 337             switch( pen
.GetCap() ) 
 340                     cap 
= kCGLineCapRound 
; 
 342                 case wxCAP_PROJECTING 
: 
 343                     cap 
= kCGLineCapSquare 
; 
 346                     cap 
= kCGLineCapButt 
; 
 349                     cap 
= kCGLineCapButt 
; 
 352             CGContextSetLineCap( m_cgContext 
, cap 
) ; 
 355             switch( pen
.GetJoin() ) 
 358                     join 
= kCGLineJoinBevel 
; 
 361                     join 
= kCGLineJoinMiter 
; 
 364                     join 
= kCGLineJoinRound 
; 
 367                     join 
= kCGLineJoinMiter 
; 
 370             CGContextSetLineJoin( m_cgContext 
, join 
) ; 
 372             CGContextSetLineWidth( m_cgContext 
, pen
.GetWidth() == 0 ? 0.1 :  pen
.GetWidth() /* TODO * m_dc->m_scaleX */ ) ;  
 374             m_mode 
= kCGPathStroke 
; 
 376             const float *lengths 
= NULL 
; 
 377             float *userLengths 
= NULL 
; 
 379             const float dotted
[] = { 3 , 3 }; 
 380             const float dashed
[] = { 19 , 9 }; 
 381             const float short_dashed
[] = { 9 , 6 }; 
 382             const float dotted_dashed
[] = { 9 , 6 , 3 , 3 }; 
 384             switch( pen
.GetStyle() ) 
 390                     count 
= WXSIZEOF(dotted
); 
 394                     count 
= WXSIZEOF(dashed
) ; 
 397                     lengths 
= short_dashed 
; 
 398                     count 
= WXSIZEOF(short_dashed
) ; 
 401                     lengths 
= dotted_dashed 
; 
 402                     count 
= WXSIZEOF(dotted_dashed
); 
 406                     count 
= pen
.GetDashes( &dashes 
) ; 
 409                         userLengths 
= new float[count
] ; 
 410                         for( int i 
= 0 ; i 
< count 
; ++i 
) 
 411                             userLengths
[i
] = dashes
[i
] ; 
 413                     lengths 
= userLengths 
; 
 419             CGContextSetLineDash( m_cgContext 
, 0 , lengths 
, count 
) ; 
 420             delete[] userLengths 
; 
 421             // we need to change the cap, otherwise everything overlaps 
 422             // and we get solid lines 
 424                 CGContextSetLineCap( m_cgContext 
, kCGLineCapButt 
) ; 
 426         if ( fill 
&& stroke 
) 
 428             m_mode 
= kCGPathFillStroke 
; 
 433 void wxMacCGContext::SetBrush( const wxBrush 
&brush 
) 
 436     if ( m_cgContext 
== NULL 
) 
 439     bool fill 
= brush
.GetStyle() != wxTRANSPARENT 
; 
 440     bool stroke 
= m_pen
.GetStyle() != wxTRANSPARENT 
; 
 443     // we can benchmark performance, should go into a setting later 
 444     CGContextSetShouldAntialias( m_cgContext 
, false ) ; 
 450         m_mode 
= kCGPathFill 
; // just a default 
 454             RGBColor col 
= MAC_WXCOLORREF( brush
.GetColour().GetPixel() ) ; 
 455             CGContextSetRGBFillColor( m_cgContext 
, col
.red 
/ 65536.0 , col
.green 
/ 65536.0 , col
.blue 
/ 65536.0 , 1.0 ) ; 
 456             m_mode 
= kCGPathFill 
; 
 460             m_mode 
= kCGPathStroke 
; 
 462         if ( fill 
&& stroke 
) 
 464             m_mode 
= kCGPathFillStroke 
; 
 470 void AddEllipticArcToPath(CGContextRef c
, CGPoint center
, float a
, float b
, float fromDegree 
, float toDegree 
) 
 472     CGContextSaveGState(c
); 
 473     CGContextTranslateCTM(c
, center
.x
, center
.y
); 
 474     CGContextScaleCTM(c
, a
, b
); 
 475     CGContextMoveToPoint(c
, 1, 0); 
 476     CGContextAddArc(c
, 0, 0, 1, DegToRad(fromDegree
), DegToRad(toDegree
), 0); 
 477     CGContextClosePath(c
); 
 478     CGContextRestoreGState(c
); 
 481 void AddRoundedRectToPath(CGContextRef c
, CGRect rect
, float ovalWidth
, 
 485     if (ovalWidth 
== 0 || ovalHeight 
== 0)  
 487         CGContextAddRect(c
, rect
); 
 490     CGContextSaveGState(c
); 
 491     CGContextTranslateCTM(c
, CGRectGetMinX(rect
), CGRectGetMinY(rect
)); 
 492     CGContextScaleCTM(c
, ovalWidth
, ovalHeight
); 
 493     fw 
= CGRectGetWidth(rect
) / ovalWidth
; 
 494     fh 
= CGRectGetHeight(rect
) / ovalHeight
; 
 495     CGContextMoveToPoint(c
, fw
, fh
/2); 
 496     CGContextAddArcToPoint(c
, fw
, fh
, fw
/2, fh
, 1); 
 497     CGContextAddArcToPoint(c
, 0, fh
, 0, fh
/2, 1); 
 498     CGContextAddArcToPoint(c
, 0, 0, fw
/2, 0, 1); 
 499     CGContextAddArcToPoint(c
, fw
, 0, fw
, fh
/2, 1); 
 500     CGContextClosePath(c
); 
 501     CGContextRestoreGState(c
); 
 508     m_mm_to_pix_x 
= mm2pt
; 
 509     m_mm_to_pix_y 
= mm2pt
; 
 510     m_internalDeviceOriginX 
= 0; 
 511     m_internalDeviceOriginY 
= 0; 
 512     m_externalDeviceOriginX 
= 0; 
 513     m_externalDeviceOriginY 
= 0; 
 514     m_logicalScaleX 
= 1.0; 
 515     m_logicalScaleY 
= 1.0; 
 520     m_needComputeScaleX 
= FALSE
; 
 521     m_needComputeScaleY 
= FALSE
; 
 525     m_macLocalOrigin
.x 
= m_macLocalOrigin
.y 
= 0 ; 
 527     m_pen 
= *wxBLACK_PEN
; 
 528     m_font 
= *wxNORMAL_FONT
; 
 529     m_brush 
= *wxWHITE_BRUSH
; 
 531     m_macATSUIStyle 
= NULL 
; 
 533     m_graphicContext 
= NULL 
; 
 538     if( m_macATSUIStyle 
) 
 540         ::ATSUDisposeStyle((ATSUStyle
)m_macATSUIStyle
); 
 541         m_macATSUIStyle 
= NULL 
; 
 544     delete m_graphicContext 
;   
 547 void wxDC::DoDrawBitmap( const wxBitmap 
&bmp
, wxCoord x
, wxCoord y
, bool useMask 
) 
 549     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 550     wxCHECK_RET( bmp
.Ok(), wxT("invalid bitmap") ); 
 551     wxCoord xx 
= XLOG2DEVMAC(x
); 
 552     wxCoord yy 
= YLOG2DEVMAC(y
); 
 553     wxCoord w 
= bmp
.GetWidth(); 
 554     wxCoord h 
= bmp
.GetHeight(); 
 555     wxCoord ww 
= XLOG2DEVREL(w
); 
 556     wxCoord hh 
= YLOG2DEVREL(h
); 
 558     CGContextRef cg 
= ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ; 
 559     CGImageRef image 
= (CGImageRef
)( bmp
.CGImageCreate() ) ; 
 560     HIRect r 
= CGRectMake( xx 
, yy 
, ww 
, hh 
) ; 
 561     HIViewDrawCGImage( cg 
, &r 
, image 
) ; 
 562     CGImageRelease( image 
) ; 
 565 void wxDC::DoDrawIcon( const wxIcon 
&icon
, wxCoord x
, wxCoord y 
) 
 567     wxCHECK_RET(Ok(), wxT("Invalid dc  wxDC::DoDrawIcon")); 
 568     wxCHECK_RET(icon
.Ok(), wxT("Invalid icon wxDC::DoDrawIcon")); 
 570     wxCoord xx 
= XLOG2DEVMAC(x
); 
 571     wxCoord yy 
= YLOG2DEVMAC(y
); 
 572     wxCoord w 
= icon
.GetWidth(); 
 573     wxCoord h 
= icon
.GetHeight(); 
 574     wxCoord ww 
= XLOG2DEVREL(w
); 
 575     wxCoord hh 
= YLOG2DEVREL(h
); 
 577     CGContextRef cg 
= ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ; 
 578     CGRect r 
= CGRectMake( 00 , 00 , ww 
, hh 
) ; 
 579     CGContextSaveGState(cg
);     
 580     CGContextTranslateCTM(cg
, xx 
, yy 
+ hh 
); 
 581     CGContextScaleCTM(cg
, 1, -1); 
 582     PlotIconRefInContext( cg 
, &r 
, kAlignNone 
, kTransformNone 
, 
 583         NULL 
, kPlotIconRefNormalFlags 
, MAC_WXHICON( icon
.GetHICON() ) ) ; 
 584     CGContextRestoreGState( cg 
) ; 
 587 void wxDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 589     wxCHECK_RET(Ok(), wxT("wxDC::DoSetClippingRegion  Invalid DC")); 
 590     wxCoord xx
, yy
, ww
, hh
; 
 593     ww 
= XLOG2DEVREL(width
); 
 594     hh 
= YLOG2DEVREL(height
); 
 596     CGContextRef cgContext 
= ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ; 
 597     CGRect clipRect 
= CGRectMake( xx 
,yy 
, ww
, hh 
) ; 
 598     CGContextClipToRect( cgContext 
, clipRect 
) ; 
 600 //    SetRectRgn( (RgnHandle) m_macCurrentClipRgn , xx , yy , xx + ww , yy + hh ) ; 
 601 //    SectRgn( (RgnHandle) m_macCurrentClipRgn , (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ; 
 604         m_clipX1 
= wxMax( m_clipX1 
, xx 
); 
 605         m_clipY1 
= wxMax( m_clipY1 
, yy 
); 
 606         m_clipX2 
= wxMin( m_clipX2
, (xx 
+ ww
)); 
 607         m_clipY2 
= wxMin( m_clipY2
, (yy 
+ hh
)); 
 617     // TODO as soon as we don't reset the context for each operation anymore 
 618     // we have to update the context as well 
 621 void wxDC::DoSetClippingRegionAsRegion( const wxRegion 
®ion  
) 
 623     wxCHECK_RET( Ok(), wxT("invalid window dc") ) ; 
 626         DestroyClippingRegion(); 
 630     region
.GetBox( x
, y
, w
, h 
); 
 631     wxCoord xx
, yy
, ww
, hh
; 
 636     // if we have a scaling that we cannot map onto native regions 
 637     // we must use the box 
 638     if ( ww 
!= w 
|| hh 
!= h 
) 
 640         wxDC::DoSetClippingRegion( x
, y
, w
, h 
); 
 645         CopyRgn( (RgnHandle) region.GetWXHRGN() , (RgnHandle) m_macCurrentClipRgn ) ; 
 646         if ( xx != x || yy != y ) 
 648             OffsetRgn( (RgnHandle) m_macCurrentClipRgn , xx - x , yy - y ) ; 
 650         SectRgn( (RgnHandle) m_macCurrentClipRgn , (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ; 
 654             m_clipX1 
= wxMax( m_clipX1 
, xx 
); 
 655             m_clipY1 
= wxMax( m_clipY1 
, yy 
); 
 656             m_clipX2 
= wxMin( m_clipX2
, (xx 
+ ww
)); 
 657             m_clipY2 
= wxMin( m_clipY2
, (yy 
+ hh
)); 
 670 void wxDC::DestroyClippingRegion() 
 672 //    CopyRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ; 
 673     CGContextRef cgContext 
= ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ; 
 674     CGContextRestoreGState( cgContext 
);     
 675     CGContextSaveGState( cgContext 
);     
 677     SetBrush( m_brush 
) ; 
 681 void wxDC::DoGetSizeMM( int* width
, int* height 
) const 
 686     *width 
= long( double(w
) / (m_scaleX
*m_mm_to_pix_x
) ); 
 687     *height 
= long( double(h
) / (m_scaleY
*m_mm_to_pix_y
) ); 
 690 void wxDC::SetTextForeground( const wxColour 
&col 
) 
 692     wxCHECK_RET(Ok(), wxT("Invalid DC")); 
 693     if ( col 
!= m_textForegroundColour 
) 
 695         m_textForegroundColour 
= col
; 
 700 void wxDC::SetTextBackground( const wxColour 
&col 
) 
 702     wxCHECK_RET(Ok(), wxT("Invalid DC")); 
 703     m_textBackgroundColour 
= col
; 
 706 void wxDC::SetMapMode( int mode 
) 
 711         SetLogicalScale( twips2mm
*m_mm_to_pix_x
, twips2mm
*m_mm_to_pix_y 
); 
 714         SetLogicalScale( pt2mm
*m_mm_to_pix_x
, pt2mm
*m_mm_to_pix_y 
); 
 717         SetLogicalScale( m_mm_to_pix_x
, m_mm_to_pix_y 
); 
 720         SetLogicalScale( m_mm_to_pix_x
/10.0, m_mm_to_pix_y
/10.0 ); 
 724         SetLogicalScale( 1.0, 1.0 ); 
 727     if (mode 
!= wxMM_TEXT
) 
 729         m_needComputeScaleX 
= TRUE
; 
 730         m_needComputeScaleY 
= TRUE
; 
 734 void wxDC::SetUserScale( double x
, double y 
) 
 736     // allow negative ? -> no 
 739     ComputeScaleAndOrigin(); 
 742 void wxDC::SetLogicalScale( double x
, double y 
) 
 747     ComputeScaleAndOrigin(); 
 750 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y 
) 
 752     m_logicalOriginX 
= x 
* m_signX
;   // is this still correct ? 
 753     m_logicalOriginY 
= y 
* m_signY
; 
 754     ComputeScaleAndOrigin(); 
 757 void wxDC::SetDeviceOrigin( wxCoord x
, wxCoord y 
) 
 759     m_externalDeviceOriginX 
= x
; 
 760     m_externalDeviceOriginY 
= y
; 
 761     ComputeScaleAndOrigin(); 
 764 void wxDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp 
) 
 766     m_signX 
= (xLeftRight 
?  1 : -1); 
 767     m_signY 
= (yBottomUp  
? -1 :  1); 
 768     ComputeScaleAndOrigin(); 
 771 wxSize 
wxDC::GetPPI() const 
 773     return wxSize(72, 72); 
 776 int wxDC::GetDepth() const 
 781 void wxDC::ComputeScaleAndOrigin() 
 783     // CMB: copy scale to see if it changes 
 784     double origScaleX 
= m_scaleX
; 
 785     double origScaleY 
= m_scaleY
; 
 786     m_scaleX 
= m_logicalScaleX 
* m_userScaleX
; 
 787     m_scaleY 
= m_logicalScaleY 
* m_userScaleY
; 
 788     m_deviceOriginX 
= m_internalDeviceOriginX 
+ m_externalDeviceOriginX
; 
 789     m_deviceOriginY 
= m_internalDeviceOriginY 
+ m_externalDeviceOriginY
; 
 790     // CMB: if scale has changed call SetPen to recalulate the line width 
 791     if (m_scaleX 
!= origScaleX 
|| m_scaleY 
!= origScaleY
) 
 793         // this is a bit artificial, but we need to force wxDC to think 
 794         // the pen has changed 
 801 void  wxDC::SetPalette( const wxPalette
& palette 
) 
 805 void  wxDC::SetBackgroundMode( int mode 
) 
 807     m_backgroundMode 
= mode 
; 
 810 void  wxDC::SetFont( const wxFont 
&font 
) 
 816 void  wxDC::SetPen( const wxPen 
&pen 
) 
 821     if ( m_graphicContext 
) 
 823         m_graphicContext
->SetPen( m_pen 
) ; 
 827 void  wxDC::SetBrush( const wxBrush 
&brush 
) 
 829     if (m_brush 
== brush
) 
 832     if ( m_graphicContext 
) 
 834         m_graphicContext
->SetBrush( m_brush 
) ; 
 838 void  wxDC::SetBackground( const wxBrush 
&brush 
) 
 840     if (m_backgroundBrush 
== brush
) 
 842     m_backgroundBrush 
= brush
; 
 843     if (!m_backgroundBrush
.Ok()) 
 847 void  wxDC::SetLogicalFunction( int function 
) 
 849     if (m_logicalFunction 
== function
) 
 851     m_logicalFunction 
= function 
; 
 854 extern bool wxDoFloodFill(wxDC 
*dc
, wxCoord x
, wxCoord y
, 
 855                           const wxColour 
& col
, int style
); 
 857 bool wxDC::DoFloodFill(wxCoord x
, wxCoord y
, 
 858                        const wxColour
& col
, int style
) 
 860     return wxDoFloodFill(this, x
, y
, col
, style
); 
 863 bool  wxDC::DoGetPixel( wxCoord x
, wxCoord y
, wxColour 
*col 
) const 
 865     wxCHECK_MSG( Ok(), false, wxT("wxDC::DoGetPixel  Invalid DC") ); 
 866     wxCHECK_MSG( Ok(), false, wxT("wxDC::DoGetPixel  Invalid DC") ); 
 867     wxMacPortSaver 
helper((CGrafPtr
)m_macPort
) ; 
 870         XLOG2DEVMAC(x
) + m_macLocalOriginInPort
.x 
- m_macLocalOrigin
.x
,  
 871         YLOG2DEVMAC(y
) + m_macLocalOriginInPort
.y 
- m_macLocalOrigin
.y
, &colour 
); 
 872     // Convert from Mac colour to wx 
 873     col
->Set( colour
.red   
>> 8, 
 879 void  wxDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2 
) 
 881     wxCHECK_RET(Ok(), wxT("Invalid DC")); 
 883     if ( m_logicalFunction 
!= wxCOPY 
) 
 886     wxCoord xx1 
= XLOG2DEVMAC(x1
) ; 
 887     wxCoord yy1 
= YLOG2DEVMAC(y1
) ; 
 888     wxCoord xx2 
= XLOG2DEVMAC(x2
) ; 
 889     wxCoord yy2 
= YLOG2DEVMAC(y2
) ; 
 891     wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
 892     path
->MoveToPoint( xx1 
, yy1 
) ; 
 893     path
->AddLineToPoint( xx2 
, yy2 
) ; 
 894     path
->CloseSubpath() ; 
 895     m_graphicContext
->StrokePath( path 
) ; 
 898     CalcBoundingBox(x1
, y1
); 
 899     CalcBoundingBox(x2
, y2
); 
 902 void  wxDC::DoCrossHair( wxCoord x
, wxCoord y 
) 
 904     wxCHECK_RET( Ok(), wxT("wxDC::DoCrossHair  Invalid window dc") ); 
 906     if ( m_logicalFunction 
!= wxCOPY 
) 
 912     wxCoord xx 
= XLOG2DEVMAC(x
); 
 913     wxCoord yy 
= YLOG2DEVMAC(y
); 
 915     wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
 916     path
->MoveToPoint( XLOG2DEVMAC(0), yy  
) ; 
 917     path
->AddLineToPoint( XLOG2DEVMAC(w
), yy 
) ; 
 918     path
->CloseSubpath() ; 
 919     path
->MoveToPoint( xx
, YLOG2DEVMAC(0) ) ; 
 920     path
->AddLineToPoint( xx
, YLOG2DEVMAC(h
) ) ; 
 921     path
->CloseSubpath() ; 
 922     m_graphicContext
->StrokePath( path 
) ; 
 925     CalcBoundingBox(x
, y
); 
 926     CalcBoundingBox(x
+w
, y
+h
); 
 930 * To draw arcs properly the angles need to be converted from the WX style: 
 931 * Angles start on the +ve X axis and go anti-clockwise (As you would draw on 
 932 * a normal axis on paper). 
 935 * Angles start on the +ve y axis and go clockwise. 
 938 static double wxConvertWXangleToMACangle(double angle
) 
 940     double newAngle 
= 90 - angle 
; 
 946 void  wxDC::DoDrawArc( wxCoord x1
, wxCoord y1
, 
 947                       wxCoord x2
, wxCoord y2
, 
 948                       wxCoord xc
, wxCoord yc 
) 
 950     wxCHECK_RET(Ok(), wxT("wxDC::DoDrawArc  Invalid DC")); 
 952     if ( m_logicalFunction 
!= wxCOPY 
) 
 955     wxCoord xx1 
= XLOG2DEVMAC(x1
); 
 956     wxCoord yy1 
= YLOG2DEVMAC(y1
); 
 957     wxCoord xx2 
= XLOG2DEVMAC(x2
); 
 958     wxCoord yy2 
= YLOG2DEVMAC(y2
); 
 959     wxCoord xxc 
= XLOG2DEVMAC(xc
); 
 960     wxCoord yyc 
= YLOG2DEVMAC(yc
); 
 961     double dx 
= xx1 
- xxc
; 
 962     double dy 
= yy1 
- yyc
; 
 963     double radius 
= sqrt((double)(dx
*dx
+dy
*dy
)); 
 964     wxCoord rad   
= (wxCoord
)radius
; 
 965     double radius1
, radius2
; 
 966     if (xx1 
== xx2 
&& yy1 
== yy2
) 
 971     else if (radius 
== 0.0) 
 973         radius1 
= radius2 
= 0.0; 
 977         radius1 
= (xx1 
- xxc 
== 0) ? 
 978             (yy1 
- yyc 
< 0) ? 90.0 : -90.0 : 
 979         -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
; 
 980         radius2 
= (xx2 
- xxc 
== 0) ? 
 981             (yy2 
- yyc 
< 0) ? 90.0 : -90.0 : 
 982         -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
; 
 984     wxCoord alpha2 
= wxCoord(radius2 
- radius1
); 
 985     wxCoord alpha1 
= wxCoord(wxConvertWXangleToMACangle(radius1
)); 
 986     if( (xx1 
> xx2
) || (yy1 
> yy2
) ) { 
 989     wxMacCGContext
* mctx 
= ((wxMacCGContext
*) m_graphicContext
) ; 
 990     CGContextRef ctx 
= mctx
->GetNativeContext() ; 
 991     AddEllipticArcToPath( ctx 
, CGPointMake( xxc 
, yyc 
) , rad 
, rad 
, alpha1 
, alpha2 
) ; 
 992     CGContextDrawPath( ctx 
, mctx
->GetDrawingMode() ) ; 
 995 void  wxDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
, 
 996                               double sa
, double ea 
) 
 998     wxCHECK_RET(Ok(), wxT("wxDC::DoDrawEllepticArc  Invalid DC")); 
1000     if ( m_logicalFunction 
!= wxCOPY 
) 
1003     double angle 
= sa 
- ea
;  // Order important Mac in opposite direction to wx 
1004     // we have to make sure that the filling is always counter-clockwise 
1007     wxCoord xx 
= XLOG2DEVMAC(x
); 
1008     wxCoord yy 
= YLOG2DEVMAC(y
); 
1009     wxCoord ww 
= m_signX 
* XLOG2DEVREL(w
); 
1010     wxCoord hh 
= m_signY 
* YLOG2DEVREL(h
); 
1011     // handle -ve width and/or height 
1012     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
1013     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
1014     sa 
= wxConvertWXangleToMACangle(sa
); 
1015     wxMacCGContext
* mctx 
= ((wxMacCGContext
*) m_graphicContext
) ; 
1016     CGContextRef ctx 
= mctx
->GetNativeContext() ; 
1017     AddEllipticArcToPath( ctx  
, CGPointMake( xx 
+ ww 
/ 2 , yy 
+ hh 
/ 2 ) , ww 
/ 2 , hh 
/ 2 , sa 
, angle
) ; 
1018     CGContextDrawPath( ctx 
, mctx
->GetDrawingMode() ) ; 
1021 void  wxDC::DoDrawPoint( wxCoord x
, wxCoord y 
) 
1023     wxCHECK_RET(Ok(), wxT("Invalid DC")); 
1024     DoDrawLine( x 
, y 
, x 
+ 1 , y 
+ 1 ) ; 
1027 void  wxDC::DoDrawLines(int n
, wxPoint points
[], 
1028                         wxCoord xoffset
, wxCoord yoffset
) 
1030     wxCHECK_RET(Ok(), wxT("Invalid DC")); 
1032     if ( m_logicalFunction 
!= wxCOPY 
) 
1035     wxCoord x1
, x2 
, y1 
, y2 
; 
1036     x1 
= XLOG2DEVMAC(points
[0].x 
+ xoffset
); 
1037     y1 
= YLOG2DEVMAC(points
[0].y 
+ yoffset
); 
1038     wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
1039     path
->MoveToPoint( x1 
, y1 
) ; 
1040     for (int i 
= 1; i 
< n
; i
++) 
1042         x2 
= XLOG2DEVMAC(points
[i
].x 
+ xoffset
); 
1043         y2 
= YLOG2DEVMAC(points
[i
].y 
+ yoffset
); 
1045         path
->AddLineToPoint( x2 
, y2 
) ; 
1047     m_graphicContext
->StrokePath( path 
) ; 
1051 void  wxDC::DoDrawPolygon(int n
, wxPoint points
[], 
1052                           wxCoord xoffset
, wxCoord yoffset
, 
1055     wxCHECK_RET(Ok(), wxT("Invalid DC")); 
1056         wxCoord x1
, x2 
, y1 
, y2 
; 
1057     if ( n
== 0 || (m_brush
.GetStyle() == wxTRANSPARENT 
&& m_pen
.GetStyle() == wxTRANSPARENT 
) ) 
1060     if ( m_logicalFunction 
!= wxCOPY 
) 
1063     x2 
= x1 
= XLOG2DEVMAC(points
[0].x 
+ xoffset
); 
1064     y2 
= y1 
= YLOG2DEVMAC(points
[0].y 
+ yoffset
); 
1066     wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
1067     path
->MoveToPoint( x1 
, y1 
) ; 
1068     for (int i 
= 1; i 
< n
; i
++) 
1070         x2 
= XLOG2DEVMAC(points
[i
].x 
+ xoffset
); 
1071         y2 
= YLOG2DEVMAC(points
[i
].y 
+ yoffset
); 
1073         path
->AddLineToPoint( x2 
, y2 
) ; 
1075     if ( x1 
!= x2 
|| y1 
!= y2 
) 
1077         path
->AddLineToPoint( x1
,y1 
) ; 
1079     path
->CloseSubpath() ; 
1080     m_graphicContext
->DrawPath( path 
, fillStyle 
) ; 
1084 void wxDC::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
) 
1086     wxCHECK_RET(Ok(), wxT("Invalid DC")); 
1088     if ( m_logicalFunction 
!= wxCOPY 
) 
1091     wxCoord xx 
= XLOG2DEVMAC(x
); 
1092     wxCoord yy 
= YLOG2DEVMAC(y
); 
1093     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
1094     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
1095     // CMB: draw nothing if transformed w or h is 0 
1096     if (ww 
== 0 || hh 
== 0) 
1098     // CMB: handle -ve width and/or height 
1109     wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
1110     path
->AddRectangle(xx 
,yy 
, ww 
, hh 
) ; 
1111     m_graphicContext
->DrawPath( path 
) ; 
1115 void  wxDC::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, 
1116                                    wxCoord width
, wxCoord height
, 
1119     wxCHECK_RET(Ok(), wxT("Invalid DC")); 
1121     if ( m_logicalFunction 
!= wxCOPY 
) 
1126         radius 
= - radius 
* ((width 
< height
) ? width 
: height
); 
1127     wxCoord xx 
= XLOG2DEVMAC(x
); 
1128     wxCoord yy 
= YLOG2DEVMAC(y
); 
1129     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
1130     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
1131     // CMB: draw nothing if transformed w or h is 0 
1132     if (ww 
== 0 || hh 
== 0) 
1134     // CMB: handle -ve width and/or height 
1145     wxMacCGContext
* mctx 
= ((wxMacCGContext
*) m_graphicContext
) ; 
1146     CGContextRef ctx 
= mctx
->GetNativeContext() ; 
1147     AddRoundedRectToPath( ctx  
, CGRectMake( xx 
, yy 
, ww 
, hh 
) , 16 ,16  ) ; 
1148     CGContextDrawPath( ctx 
, mctx
->GetDrawingMode() ) ; 
1151 void  wxDC::DoDrawEllipse(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
) 
1153     wxCHECK_RET(Ok(), wxT("Invalid DC")); 
1155     if ( m_logicalFunction 
!= wxCOPY 
) 
1158     wxCoord xx 
= XLOG2DEVMAC(x
); 
1159     wxCoord yy 
= YLOG2DEVMAC(y
); 
1160     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
1161     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
1162     // CMB: draw nothing if transformed w or h is 0 
1163     if (ww 
== 0 || hh 
== 0) 
1165     // CMB: handle -ve width and/or height 
1177     wxMacCGContext
* mctx 
= ((wxMacCGContext
*) m_graphicContext
) ; 
1178     CGContextRef ctx 
= mctx
->GetNativeContext() ; 
1179     if ( width 
== height 
) 
1181         CGContextBeginPath(ctx
); 
1182         CGContextAddArc(ctx 
, 
1189         CGContextClosePath(ctx
); 
1191         CGContextDrawPath( ctx 
, mctx
->GetDrawingMode() ) ; 
1195         AddEllipticArcToPath( ctx 
, CGPointMake( xx 
+ ww 
/ 2 , yy 
+ hh 
/ 2 ) , ww 
/ 2 , hh 
/ 2 , 0 , 360) ; 
1196         CGContextDrawPath( ctx 
, mctx
->GetDrawingMode() ) ; 
1200 bool  wxDC::CanDrawBitmap(void) const 
1205 bool  wxDC::DoBlit(wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
, 
1206                    wxDC 
*source
, wxCoord xsrc
, wxCoord ysrc
, int logical_func 
, bool useMask
, 
1207                    wxCoord xsrcMask
,  wxCoord ysrcMask 
) 
1209     wxCHECK_MSG(Ok(), false, wxT("wxDC::DoBlit Illegal dc")); 
1210     wxCHECK_MSG(source
->Ok(), false, wxT("wxDC::DoBlit  Illegal source DC")); 
1211     if ( logical_func 
== wxNO_OP 
) 
1213     if (xsrcMask 
== -1 && ysrcMask 
== -1) 
1215         xsrcMask 
= xsrc
; ysrcMask 
= ysrc
; 
1218     wxCoord yysrc 
= source
->YLOG2DEVMAC(ysrc
) ; 
1219     wxCoord xxsrc 
= source
->XLOG2DEVMAC(xsrc
)  ; 
1220     wxCoord wwsrc 
= source
->XLOG2DEVREL(width 
) ; 
1221     wxCoord hhsrc 
= source
->YLOG2DEVREL(height
) ; 
1223     wxCoord yydest 
= YLOG2DEVMAC(ydest
) ; 
1224     wxCoord xxdest 
= XLOG2DEVMAC(xdest
) ; 
1225     wxCoord wwdest 
= XLOG2DEVREL(width 
) ; 
1226     wxCoord hhdest 
= YLOG2DEVREL(height
) ; 
1228     wxMemoryDC
* memdc 
= dynamic_cast<wxMemoryDC
*>(source
) ; 
1229     if ( memdc 
&& logical_func 
== wxCOPY 
) 
1231         wxBitmap blit 
= memdc
->GetSelectedObject() ; 
1232         wxASSERT_MSG( blit
.Ok() , wxT("Invalid bitmap for blitting") ) ; 
1234         wxCoord bmpwidth 
= blit
.GetWidth(); 
1235         wxCoord bmpheight 
= blit
.GetHeight(); 
1237         if ( xxsrc 
!= 0 || yysrc 
!= 0 || bmpwidth 
!= wwsrc 
|| bmpheight 
!= hhsrc 
) 
1239             wwsrc 
= wxMin( wwsrc 
, bmpwidth 
- xxsrc 
) ; 
1240             hhsrc 
= wxMin( hhsrc 
, bmpheight 
- yysrc 
) ; 
1241             if ( wwsrc 
> 0 && hhsrc 
> 0 ) 
1243                 if ( xxsrc 
>= 0 && yysrc 
>= 0 ) 
1245                     wxRect 
subrect( xxsrc
, yysrc
, wwsrc 
, hhsrc 
) ; 
1246                     blit 
= blit
.GetSubBitmap( subrect 
) ; 
1250                     // in this case we'd probably have to adjust the different coordinates, but 
1251                     // we have to find out proper contract first 
1252                     blit 
= wxNullBitmap 
; 
1257                 blit 
= wxNullBitmap 
; 
1262             CGContextRef cg 
= ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ; 
1263             CGImageRef image 
= (CGImageRef
)( blit
.CGImageCreate() ) ; 
1264             HIRect r 
= CGRectMake( xxdest 
, yydest 
, wwdest 
, hhdest 
) ; 
1265             HIViewDrawCGImage( cg 
, &r 
, image 
) ; 
1266             CGImageRelease( image 
) ; 
1273         CGContextRef cg = (wxMacCGContext*)(source->GetGraphicContext())->GetNativeContext() ; 
1274         void *data = CGBitmapContextGetData( cg ) ; 
1276         return FALSE 
; // wxFAIL_MSG( wxT("Blitting is only supported from bitmap contexts") ) ; 
1281 void  wxDC::DoDrawRotatedText(const wxString
& str
, wxCoord x
, wxCoord y
, 
1284     wxCHECK_RET( Ok(), wxT("wxDC::DoDrawRotatedText  Invalid window dc") ); 
1286     if ( str
.Length() == 0 ) 
1289     if ( m_logicalFunction 
!= wxCOPY 
) 
1292     wxCHECK_RET( m_macATSUIStyle 
!= NULL 
, wxT("No valid font set") ) ; 
1294     OSStatus status 
= noErr 
; 
1295     ATSUTextLayout atsuLayout 
; 
1296     UniCharCount chars 
= str
.Length() ; 
1297     UniChar
* ubuf 
= NULL 
; 
1298 #if SIZEOF_WCHAR_T == 4 
1299         wxMBConvUTF16BE converter 
; 
1301         size_t unicharlen 
= converter
.WC2MB( NULL 
, str
.wc_str() , 0 ) ; 
1302         ubuf 
= (UniChar
*) malloc( unicharlen 
+ 2 ) ; 
1303         converter
.WC2MB( (char*) ubuf 
, str
.wc_str(), unicharlen 
+ 2 ) ; 
1305     const wxWCharBuffer wchar 
= str
.wc_str( wxConvLocal 
) ; 
1306         size_t unicharlen 
= converter
.WC2MB( NULL 
, wchar
.data()  , 0 ) ; 
1307         ubuf 
= (UniChar
*) malloc( unicharlen 
+ 2 ) ; 
1308         converter
.WC2MB( (char*) ubuf 
, wchar
.data() , unicharlen 
+ 2 ) ; 
1310     chars 
= unicharlen 
/ 2 ; 
1313     ubuf 
= (UniChar
*) str
.wc_str() ; 
1315     wxWCharBuffer wchar 
= str
.wc_str( wxConvLocal 
) ; 
1316     chars 
= wxWcslen( wchar
.data() ) ; 
1317     ubuf 
= (UniChar
*) wchar
.data() ; 
1321     int drawX 
= XLOG2DEVMAC(x
) ; 
1322     int drawY 
= YLOG2DEVMAC(y
) ; 
1324     status 
= ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr
) ubuf 
, 0 , chars 
, chars 
, 1 , 
1325         &chars 
, (ATSUStyle
*) &m_macATSUIStyle 
, &atsuLayout 
) ; 
1327     wxASSERT_MSG( status 
== noErr 
, wxT("couldn't create the layout of the rotated text") ); 
1328     int iAngle 
= int( angle 
); 
1332     if ( abs(iAngle
) > 0 ) 
1334         Fixed atsuAngle 
= IntToFixed( iAngle 
) ; 
1335         ATSUAttributeTag atsuTags
[] = 
1337             kATSULineRotationTag 
, 
1339         ByteCount atsuSizes
[sizeof(atsuTags
)/sizeof(ATSUAttributeTag
)] = 
1343         ATSUAttributeValuePtr    atsuValues
[sizeof(atsuTags
)/sizeof(ATSUAttributeTag
)] = 
1347         status 
= ::ATSUSetLayoutControls(atsuLayout 
, sizeof(atsuTags
)/sizeof(ATSUAttributeTag
), 
1348             atsuTags
, atsuSizes
, atsuValues 
) ; 
1351         CGContextRef cgContext 
= ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ; 
1352         ATSUAttributeTag atsuTags
[] = 
1356         ByteCount atsuSizes
[sizeof(atsuTags
)/sizeof(ATSUAttributeTag
)] = 
1358             sizeof( CGContextRef 
) , 
1360         ATSUAttributeValuePtr    atsuValues
[sizeof(atsuTags
)/sizeof(ATSUAttributeTag
)] = 
1364         status 
= ::ATSUSetLayoutControls(atsuLayout 
, sizeof(atsuTags
)/sizeof(ATSUAttributeTag
), 
1365             atsuTags
, atsuSizes
, atsuValues 
) ; 
1368     ATSUTextMeasurement textBefore 
; 
1369     ATSUTextMeasurement textAfter 
; 
1370     ATSUTextMeasurement ascent 
; 
1371     ATSUTextMeasurement descent 
; 
1373     status 
= ::ATSUGetUnjustifiedBounds( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
, 
1374         &textBefore 
, &textAfter
, &ascent 
, &descent 
); 
1375     wxASSERT_MSG( status 
== noErr 
, wxT("couldn't measure the rotated text") ); 
1379     if ( m_backgroundMode 
== wxSOLID 
) 
1381         wxGraphicPath
* path 
= m_graphicContext
->CreatePath() ; 
1385         path
->AddLineToPoint(  
1386             (int) (drawX 
+ sin(angle
/RAD2DEG
) * FixedToInt(ascent 
+ descent
)) ,  
1387             (int) (drawY 
+ cos(angle
/RAD2DEG
) * FixedToInt(ascent 
+ descent
)) ) ; 
1388         path
->AddLineToPoint(  
1389             (int) (drawX 
+ sin(angle
/RAD2DEG
) * FixedToInt(ascent 
+ descent 
) + cos(angle
/RAD2DEG
) * FixedToInt(textAfter
)) , 
1390             (int) (drawY 
+ cos(angle
/RAD2DEG
) * FixedToInt(ascent 
+ descent
) - sin(angle
/RAD2DEG
) * FixedToInt(textAfter
)) ) ; 
1391         path
->AddLineToPoint(  
1392             (int) (drawX 
+ cos(angle
/RAD2DEG
) * FixedToInt(textAfter
)) ,  
1393             (int) (drawY 
- sin(angle
/RAD2DEG
) * FixedToInt(textAfter
)) ) ; 
1395         m_graphicContext
->FillPath( path 
, m_textBackgroundColour 
) ; 
1399     drawX 
+= (int)(sin(angle
/RAD2DEG
) * FixedToInt(ascent
)); 
1400     drawY 
+= (int)(cos(angle
/RAD2DEG
) * FixedToInt(ascent
)); 
1402     status 
= ::ATSUMeasureTextImage( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
, 
1403         IntToFixed(drawX
) , IntToFixed(drawY
) , &rect 
); 
1404     wxASSERT_MSG( status 
== noErr 
, wxT("couldn't measure the rotated text") ); 
1406     CGContextSaveGState(((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext());     
1407     CGContextTranslateCTM(((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext(), drawX
, drawY
); 
1408     CGContextScaleCTM(((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext(), 1, -1); 
1409     status 
= ::ATSUDrawText( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
, 
1410         IntToFixed(0) , IntToFixed(0) ); 
1411     wxASSERT_MSG( status 
== noErr 
, wxT("couldn't draw the rotated text") ); 
1412     CGContextRestoreGState( ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ) ; 
1414     CalcBoundingBox(XDEV2LOG(rect
.left
), YDEV2LOG(rect
.top
) ); 
1415     CalcBoundingBox(XDEV2LOG(rect
.right
), YDEV2LOG(rect
.bottom
) ); 
1417     ::ATSUDisposeTextLayout(atsuLayout
); 
1418 #if SIZEOF_WCHAR_T == 4 
1423 void  wxDC::DoDrawText(const wxString
& strtext
, wxCoord x
, wxCoord y
) 
1425     wxCHECK_RET(Ok(), wxT("wxDC::DoDrawText  Invalid DC")); 
1426     DoDrawRotatedText( strtext 
, x 
, y 
, 0.0 ) ; 
1429 bool  wxDC::CanGetTextExtent() const 
1431     wxCHECK_MSG(Ok(), false, wxT("Invalid DC")); 
1435 void  wxDC::DoGetTextExtent( const wxString 
&str
, wxCoord 
*width
, wxCoord 
*height
, 
1436                             wxCoord 
*descent
, wxCoord 
*externalLeading 
, 
1437                             wxFont 
*theFont 
) const 
1439     wxCHECK_RET(Ok(), wxT("Invalid DC")); 
1440     wxFont formerFont 
= m_font 
; 
1443         // work around the constness 
1444         *((wxFont
*)(&m_font
)) = *theFont 
; 
1448     if ( str
.Length() == 0 ) 
1451     wxCHECK_RET( m_macATSUIStyle 
!= NULL 
, wxT("No valid font set") ) ; 
1453     OSStatus status 
= noErr 
; 
1454     ATSUTextLayout atsuLayout 
; 
1455     UniCharCount chars 
= str
.Length() ; 
1456     UniChar
* ubuf 
= NULL 
; 
1457 #if SIZEOF_WCHAR_T == 4 
1458         wxMBConvUTF16BE converter 
; 
1460         size_t unicharlen 
= converter
.WC2MB( NULL 
, str
.wc_str() , 0 ) ; 
1461         ubuf 
= (UniChar
*) malloc( unicharlen 
+ 2 ) ; 
1462         converter
.WC2MB( (char*) ubuf 
, str
.wc_str(), unicharlen 
+ 2 ) ; 
1464     const wxWCharBuffer wchar 
= str
.wc_str( wxConvLocal 
) ; 
1465         size_t unicharlen 
= converter
.WC2MB( NULL 
, wchar
.data()  , 0 ) ; 
1466         ubuf 
= (UniChar
*) malloc( unicharlen 
+ 2 ) ; 
1467         converter
.WC2MB( (char*) ubuf 
, wchar
.data() , unicharlen 
+ 2 ) ; 
1469     chars 
= unicharlen 
/ 2 ; 
1472     ubuf 
= (UniChar
*) str
.wc_str() ; 
1474     wxWCharBuffer wchar 
= str
.wc_str( wxConvLocal 
) ; 
1475     chars 
= wxWcslen( wchar
.data() ) ; 
1476     ubuf 
= (UniChar
*) wchar
.data() ; 
1481     status 
= ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr
) ubuf 
, 0 , chars 
, chars 
, 1 , 
1482         &chars 
, (ATSUStyle
*) &m_macATSUIStyle 
, &atsuLayout 
) ; 
1484     wxASSERT_MSG( status 
== noErr 
, wxT("couldn't create the layout of the text") ); 
1486     ATSUTextMeasurement textBefore 
; 
1487     ATSUTextMeasurement textAfter 
; 
1488     ATSUTextMeasurement textAscent 
; 
1489     ATSUTextMeasurement textDescent 
; 
1491     status 
= ::ATSUGetUnjustifiedBounds( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
, 
1492         &textBefore 
, &textAfter
, &textAscent 
, &textDescent 
); 
1495         *height 
= YDEV2LOGREL( FixedToInt(textAscent 
+ textDescent
) ) ; 
1497         *descent 
=YDEV2LOGREL( FixedToInt(textDescent
) ); 
1498     if ( externalLeading 
) 
1499         *externalLeading 
= 0 ; 
1501         *width 
= XDEV2LOGREL( FixedToInt(textAfter 
- textBefore
) ) ; 
1503     ::ATSUDisposeTextLayout(atsuLayout
); 
1504 #if SIZEOF_WCHAR_T == 4 
1509         // work around the constness 
1510         *((wxFont
*)(&m_font
)) = formerFont 
; 
1516 bool wxDC::DoGetPartialTextExtents(const wxString
& text
, wxArrayInt
& widths
) const 
1518     wxCHECK_MSG(Ok(), false, wxT("Invalid DC")); 
1521     widths
.Add(0, text
.Length()); 
1523     if (text
.Length() == 0) 
1526     ATSUTextLayout atsuLayout 
; 
1527     UniCharCount chars 
= text
.Length() ; 
1528     UniChar
* ubuf 
= NULL 
; 
1529 #if SIZEOF_WCHAR_T == 4 
1530     wxMBConvUTF16BE converter 
; 
1532     size_t unicharlen 
= converter
.WC2MB( NULL 
, text
.wc_str() , 0 ) ; 
1533     ubuf 
= (UniChar
*) malloc( unicharlen 
+ 2 ) ; 
1534     converter
.WC2MB( (char*) ubuf 
, text
.wc_str(), unicharlen 
+ 2 ) ; 
1536     const wxWCharBuffer wchar 
= text
.wc_str( wxConvLocal 
) ; 
1537     size_t unicharlen 
= converter
.WC2MB( NULL 
, wchar
.data()  , 0 ) ; 
1538     ubuf 
= (UniChar
*) malloc( unicharlen 
+ 2 ) ; 
1539     converter
.WC2MB( (char*) ubuf 
, wchar
.data() , unicharlen 
+ 2 ) ; 
1541     chars 
= unicharlen 
/ 2 ; 
1544     ubuf 
= (UniChar
*) text
.wc_str() ; 
1546     wxWCharBuffer wchar 
= text
.wc_str( wxConvLocal 
) ; 
1547     chars 
= wxWcslen( wchar
.data() ) ; 
1548     ubuf 
= (UniChar
*) wchar
.data() ; 
1553     status 
= ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr
) ubuf 
, 0 , chars 
, chars 
, 1 , 
1554         &chars 
, (ATSUStyle
*) &m_macATSUIStyle 
, &atsuLayout 
) ; 
1556         for ( int pos 
= 0; pos 
< chars
; pos 
++ ) { 
1557                         unsigned long actualNumberOfBounds 
= 0; 
1558                         ATSTrapezoid glyphBounds
; 
1560                         // We get a single bound, since the text should only require one. If it requires more, there is an issue 
1562                         result 
= ATSUGetGlyphBounds( atsuLayout
, 0, 0, kATSUFromTextBeginning
, pos 
+ 1, kATSUseDeviceOrigins
, 1, &glyphBounds
, &actualNumberOfBounds 
); 
1563                         if (result 
!= noErr 
|| actualNumberOfBounds 
!= 1 ) 
1568                         widths
[pos
] = XDEV2LOGREL(FixedToInt( glyphBounds
.upperRight
.x 
- glyphBounds
.upperLeft
.x 
)); 
1569                         //unsigned char uch = s[i]; 
1572     ::ATSUDisposeTextLayout(atsuLayout
); 
1576 wxCoord   
wxDC::GetCharWidth(void) const 
1579     DoGetTextExtent(wxT("g") , &width 
, NULL 
, NULL 
, NULL 
, NULL 
) ; 
1583 wxCoord   
wxDC::GetCharHeight(void) const 
1586     DoGetTextExtent(wxT("g") , NULL 
, &height 
, NULL 
, NULL 
, NULL 
) ; 
1590 void  wxDC::Clear(void) 
1592     wxCHECK_RET(Ok(), wxT("Invalid DC")); 
1594     if ( m_backgroundBrush
.Ok() && m_backgroundBrush
.GetStyle() != wxTRANSPARENT
) 
1596         HIRect rect 
= CGRectMake( -10000 , -10000 , 20000 , 20000 ) ; 
1597         CGContextRef cg 
= ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ; 
1598         switch( m_backgroundBrush
.MacGetBrushKind() ) 
1600             case kwxMacBrushTheme 
: 
1602 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 
1603                     if ( HIThemeSetFill 
!= 0 ) 
1605                         HIThemeSetFill( m_backgroundBrush
.MacGetTheme() , cg 
) ; 
1606                         CGContextFillRect(cg
, rect
); 
1613                                         GetThemeBrushAsColor( m_backgroundBrush
.MacGetTheme() , 32, true, &color 
); 
1614                                         CGContextSetRGBFillColor( cg 
, (float) color
.red 
/ 65536, 
1615                                                         (float) color
.green 
/ 65536, (float) color
.blue 
/ 65536, 1 ); 
1616                                         CGContextFillRect( cg
, rect 
); 
1618                     // reset to normal value 
1619                     RGBColor col 
= MAC_WXCOLORREF( GetBrush().GetColour().GetPixel() ) ; 
1620                     CGContextSetRGBFillColor( cg 
, col
.red 
/ 65536.0 , col
.green 
/ 65536.0 , col
.blue 
/ 65536.0 , 1.0 ) ; 
1623             case kwxMacBrushThemeBackground 
: 
1625                     wxFAIL_MSG( wxT("There shouldn't be theme backgrounds under Quartz") ) ; 
1626 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 
1627                     if ( UMAGetSystemVersion() >= 0x1030 ) 
1629                         HIThemeBackgroundDrawInfo drawInfo 
; 
1630                         drawInfo
.version 
= 0 ; 
1631                         drawInfo
.state 
= kThemeStateActive 
; 
1632                         drawInfo
.kind 
= m_backgroundBrush
.MacGetThemeBackground(NULL
) ; 
1633                         if ( drawInfo
.kind 
== kThemeBackgroundMetal 
) 
1634                             HIThemeDrawBackground( &rect 
, &drawInfo
, cg 
, 
1635                                 kHIThemeOrientationNormal
) ; 
1636                             HIThemeApplyBackground( &rect 
, &drawInfo
, cg 
, 
1637                                 kHIThemeOrientationNormal
) ; 
1645             case kwxMacBrushColour 
: 
1647                 RGBColor col 
= MAC_WXCOLORREF( m_backgroundBrush
.GetColour().GetPixel()) ; 
1648                 CGContextSetRGBFillColor( cg 
, col
.red 
/ 65536.0 , col
.green 
/ 65536.0 , col
.blue 
/ 65536.0 , 1.0 ) ; 
1649                 CGContextFillRect(cg
, rect
); 
1651                 // reset to normal value 
1652                 col 
= MAC_WXCOLORREF( GetBrush().GetColour().GetPixel() ) ; 
1653                 CGContextSetRGBFillColor( cg 
, col
.red 
/ 65536.0 , col
.green 
/ 65536.0 , col
.blue 
/ 65536.0 , 1.0 ) ; 
1660 void wxDC::MacInstallFont() const 
1662     wxCHECK_RET(Ok(), wxT("Invalid DC")); 
1664     if( m_macATSUIStyle 
) 
1666         ::ATSUDisposeStyle((ATSUStyle
)m_macATSUIStyle
); 
1667         m_macATSUIStyle 
= NULL 
; 
1672         OSStatus status 
= noErr 
; 
1673         status 
= ATSUCreateAndCopyStyle( (ATSUStyle
) m_font
.MacGetATSUStyle() , (ATSUStyle
*) &m_macATSUIStyle 
) ; 
1674         wxASSERT_MSG( status 
== noErr 
, wxT("couldn't set create ATSU style") ) ; 
1676         Fixed atsuSize 
= IntToFixed( int(m_scaleY 
* m_font
.MacGetFontSize()) ) ; 
1677         RGBColor atsuColor 
= MAC_WXCOLORREF( m_textForegroundColour
.GetPixel() ) ; 
1678         ATSUAttributeTag atsuTags
[] = 
1683         ByteCount atsuSizes
[sizeof(atsuTags
)/sizeof(ATSUAttributeTag
)] = 
1686                 sizeof( RGBColor 
) , 
1688     //    Boolean kTrue = true ; 
1689     //    Boolean kFalse = false ; 
1691     //    ATSUVerticalCharacterType kHorizontal = kATSUStronglyHorizontal; 
1692         ATSUAttributeValuePtr    atsuValues
[sizeof(atsuTags
)/sizeof(ATSUAttributeTag
)] = 
1697         status 
= ::ATSUSetAttributes((ATSUStyle
)m_macATSUIStyle
, sizeof(atsuTags
)/sizeof(ATSUAttributeTag
) , 
1698             atsuTags
, atsuSizes
, atsuValues
); 
1700         wxASSERT_MSG( status 
== noErr 
, wxT("couldn't Modify ATSU style") ) ; 
1704 // --------------------------------------------------------------------------- 
1705 // coordinates transformations 
1706 // --------------------------------------------------------------------------- 
1708 wxCoord 
wxDCBase::DeviceToLogicalX(wxCoord x
) const 
1710     return ((wxDC 
*)this)->XDEV2LOG(x
); 
1713 wxCoord 
wxDCBase::DeviceToLogicalY(wxCoord y
) const 
1715     return ((wxDC 
*)this)->YDEV2LOG(y
); 
1718 wxCoord 
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const 
1720     return ((wxDC 
*)this)->XDEV2LOGREL(x
); 
1723 wxCoord 
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const 
1725     return ((wxDC 
*)this)->YDEV2LOGREL(y
); 
1728 wxCoord 
wxDCBase::LogicalToDeviceX(wxCoord x
) const 
1730     return ((wxDC 
*)this)->XLOG2DEV(x
); 
1733 wxCoord 
wxDCBase::LogicalToDeviceY(wxCoord y
) const 
1735     return ((wxDC 
*)this)->YLOG2DEV(y
); 
1738 wxCoord 
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const 
1740     return ((wxDC 
*)this)->XLOG2DEVREL(x
); 
1743 wxCoord 
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const 
1745     return ((wxDC 
*)this)->YLOG2DEVREL(y
); 
1748 #endif // wxMAC_USE_CORE_GRAPHICS