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
) ;
76 win
->MacWindowToRootWindow( &x
,&y
) ;
77 // get area including focus rect
78 CopyRgn( (RgnHandle
) ((wxWindow
*)win
)->MacGetVisibleRegion(true).GetWXHRGN() , m_newClip
) ;
79 if ( !EmptyRgn( m_newClip
) )
80 OffsetRgn( m_newClip
, x
, y
) ;
82 SetClip( m_newClip
) ;
86 wxMacWindowClipper::~wxMacWindowClipper()
88 SetPort( m_newPort
) ;
89 SetClip( m_formerClip
) ;
90 DisposeRgn( m_newClip
) ;
91 DisposeRgn( m_formerClip
) ;
94 wxMacWindowStateSaver::wxMacWindowStateSaver( const wxWindow
* win
) :
95 wxMacWindowClipper( win
)
97 // the port is already set at this point
98 m_newPort
=(GrafPtr
) GetWindowPort((WindowRef
) win
->MacGetTopLevelWindowRef()) ;
99 GetThemeDrawingState( &m_themeDrawingState
) ;
102 wxMacWindowStateSaver::~wxMacWindowStateSaver()
104 SetPort( m_newPort
) ;
105 SetThemeDrawingState( m_themeDrawingState
, true ) ;
108 //-----------------------------------------------------------------------------
110 //-----------------------------------------------------------------------------
112 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
113 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
114 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
116 //-----------------------------------------------------------------------------
117 // device context implementation
119 // more and more of the dc functionality should be implemented by calling
120 // the appropricate wxMacCGContext, but we will have to do that step by step
121 // also coordinate conversions should be moved to native matrix ops
122 //-----------------------------------------------------------------------------
124 wxMacCGPath::wxMacCGPath()
126 m_path
= CGPathCreateMutable() ;
129 wxMacCGPath::~wxMacCGPath()
131 CGPathRelease( m_path
) ;
134 // Starts a new subpath at
135 void wxMacCGPath::MoveToPoint( wxCoord x1
, wxCoord y1
)
137 CGPathMoveToPoint( m_path
, NULL
, x1
, y1
) ;
140 void wxMacCGPath::AddLineToPoint( wxCoord x1
, wxCoord y1
)
142 CGPathAddLineToPoint( m_path
, NULL
, x1
, y1
) ;
145 void wxMacCGPath::AddRectangle( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
147 CGRect cgRect
= { { x
, y
} , { w
, h
} } ;
148 CGPathAddRect( m_path
, NULL
, cgRect
) ;
151 void wxMacCGPath::AddCircle( wxCoord x
, wxCoord y
, wxCoord r
)
153 CGPathAddArc( m_path
, NULL
, x
, y
, r
, 0.0 , 2 * M_PI
, true ) ;
156 // closes the current subpath
157 void wxMacCGPath::CloseSubpath()
159 CGPathCloseSubpath( m_path
) ;
162 CGPathRef
wxMacCGPath::GetPath() const
168 wxMacCGContext::wxMacCGContext( CGrafPtr port
)
172 GetPortBounds( (CGrafPtr
) port
, &bounds
) ;
173 OSStatus status
= QDBeginCGContext( (CGrafPtr
) port
, &m_cgContext
) ;
175 wxASSERT_MSG( status
== noErr
, wxT("Cannot nest wxDCs on the same window") ) ;
176 CGContextTranslateCTM( m_cgContext
, 0 , bounds
.bottom
- bounds
.top
) ;
177 CGContextScaleCTM( m_cgContext
, 1 , -1 ) ;
180 wxMacCGContext::wxMacCGContext( CGContextRef cgcontext
)
183 m_cgContext
= cgcontext
;
186 wxMacCGContext::wxMacCGContext()
192 wxMacCGContext::~wxMacCGContext()
195 QDEndCGContext( m_qdPort
, &m_cgContext
) ;
199 void wxMacCGContext::Clip( const wxRegion
®ion
)
201 // ClipCGContextToRegion ( m_cgContext, &bounds , (RgnHandle) dc->m_macCurrentClipRgn ) ;
204 void wxMacCGContext::StrokePath( const wxGraphicPath
*p
)
206 const wxMacCGPath
* path
= dynamic_cast< const wxMacCGPath
*>( p
) ;
207 CGContextBeginPath( m_cgContext
) ;
208 CGContextAddPath( m_cgContext
, path
->GetPath() ) ;
209 CGContextClosePath( m_cgContext
) ;
210 CGContextStrokePath( m_cgContext
) ;
213 void wxMacCGContext::DrawPath( const wxGraphicPath
*p
, int fillStyle
)
215 const wxMacCGPath
* path
= dynamic_cast< const wxMacCGPath
*>( p
) ;
216 CGPathDrawingMode mode
= m_mode
;
217 if ( fillStyle
== wxODDEVEN_RULE
)
219 if ( mode
== kCGPathFill
)
220 mode
= kCGPathEOFill
;
221 else if ( mode
== kCGPathFillStroke
)
222 mode
= kCGPathEOFillStroke
;
224 CGContextBeginPath( m_cgContext
) ;
225 CGContextAddPath( m_cgContext
, path
->GetPath() ) ;
226 CGContextClosePath( m_cgContext
) ;
227 CGContextDrawPath( m_cgContext
, mode
) ;
230 void wxMacCGContext::FillPath( const wxGraphicPath
*p
, const wxColor
&fillColor
, int fillStyle
)
232 const wxMacCGPath
* path
= dynamic_cast< const wxMacCGPath
*>( p
) ;
233 CGContextSaveGState( m_cgContext
) ;
235 RGBColor col
= MAC_WXCOLORREF( fillColor
.GetPixel() ) ;
236 CGContextSetRGBFillColor( m_cgContext
, col
.red
/ 65536.0 , col
.green
/ 65536.0 , col
.blue
/ 65536.0 , 1.0 ) ;
237 CGPathDrawingMode mode
= kCGPathFill
;
239 if ( fillStyle
== wxODDEVEN_RULE
)
240 mode
= kCGPathEOFill
;
242 CGContextBeginPath( m_cgContext
) ;
243 CGContextAddPath( m_cgContext
, path
->GetPath() ) ;
244 CGContextClosePath( m_cgContext
) ;
245 CGContextDrawPath( m_cgContext
, mode
) ;
247 CGContextRestoreGState( m_cgContext
) ;
250 wxGraphicPath
* wxMacCGContext::CreatePath() { return new wxMacCGPath() ; }
251 CGContextRef
wxMacCGContext::GetNativeContext() { return m_cgContext
; }
252 void wxMacCGContext::SetNativeContext( CGContextRef cg
) { m_cgContext
= cg
; }
254 void wxMacCGContext::SetPen( const wxPen
&pen
)
256 bool fill
= m_brush
.GetStyle() != wxTRANSPARENT
;
257 bool stroke
= pen
.GetStyle() != wxTRANSPARENT
;
260 // we can benchmark performance, should go into a setting later
261 CGContextSetShouldAntialias( m_cgContext
, false ) ;
266 m_mode
= kCGPathFill
; // just a default
270 m_mode
= kCGPathFill
;
274 RGBColor col
= MAC_WXCOLORREF( pen
.GetColour().GetPixel() ) ;
275 CGContextSetRGBStrokeColor( m_cgContext
, col
.red
/ 65536.0 , col
.green
/ 65536.0 , col
.blue
/ 65536.0 , 1.0 ) ;
278 switch( pen
.GetCap() )
281 cap
= kCGLineCapRound
;
283 case wxCAP_PROJECTING
:
284 cap
= kCGLineCapSquare
;
287 cap
= kCGLineCapButt
;
290 cap
= kCGLineCapButt
;
293 CGContextSetLineCap( m_cgContext
, cap
) ;
296 switch( pen
.GetJoin() )
299 join
= kCGLineJoinBevel
;
302 join
= kCGLineJoinMiter
;
305 join
= kCGLineJoinRound
;
308 join
= kCGLineJoinMiter
;
311 CGContextSetLineJoin( m_cgContext
, join
) ;
313 CGContextSetLineWidth( m_cgContext
, pen
.GetWidth() == 0 ? 0.1 : pen
.GetWidth() /* TODO * m_dc->m_scaleX */ ) ;
315 m_mode
= kCGPathStroke
;
317 const float *lengths
= NULL
;
318 float *userLengths
= NULL
;
320 const float dotted
[] = { 3 , 3 };
321 const float dashed
[] = { 19 , 9 };
322 const float short_dashed
[] = { 9 , 6 };
323 const float dotted_dashed
[] = { 9 , 6 , 3 , 3 };
325 switch( pen
.GetStyle() )
331 count
= WXSIZEOF(dotted
);
335 count
= WXSIZEOF(dashed
) ;
338 lengths
= short_dashed
;
339 count
= WXSIZEOF(short_dashed
) ;
342 lengths
= dotted_dashed
;
343 count
= WXSIZEOF(dotted_dashed
);
347 count
= pen
.GetDashes( &dashes
) ;
350 userLengths
= new float[count
] ;
351 for( int i
= 0 ; i
< count
; ++i
)
352 userLengths
[i
] = dashes
[i
] ;
354 lengths
= userLengths
;
360 CGContextSetLineDash( m_cgContext
, 0 , lengths
, count
) ;
361 delete[] userLengths
;
362 // we need to change the cap, otherwise everything overlaps
363 // and we get solid lines
365 CGContextSetLineCap( m_cgContext
, kCGLineCapButt
) ;
367 if ( fill
&& stroke
)
369 m_mode
= kCGPathFillStroke
;
374 void wxMacCGContext::SetBrush( const wxBrush
&brush
)
376 bool fill
= brush
.GetStyle() != wxTRANSPARENT
;
377 bool stroke
= m_pen
.GetStyle() != wxTRANSPARENT
;
380 // we can benchmark performance, should go into a setting later
381 CGContextSetShouldAntialias( m_cgContext
, false ) ;
387 m_mode
= kCGPathFill
; // just a default
391 RGBColor col
= MAC_WXCOLORREF( brush
.GetColour().GetPixel() ) ;
392 CGContextSetRGBFillColor( m_cgContext
, col
.red
/ 65536.0 , col
.green
/ 65536.0 , col
.blue
/ 65536.0 , 1.0 ) ;
393 m_mode
= kCGPathFill
;
397 m_mode
= kCGPathStroke
;
399 if ( fill
&& stroke
)
401 m_mode
= kCGPathFillStroke
;
407 // snippets from Sketch Sample from Apple :
409 #define kGenericRGBProfilePathStr "/System/Library/ColorSync/Profiles/Generic RGB Profile.icc"
411 This function locates, opens, and returns the profile reference for the calibrated
412 Generic RGB color space. It is up to the caller to call CMCloseProfile when done
413 with the profile reference this function returns.
415 CMProfileRef
wxMacOpenGenericProfile(void)
417 static CMProfileRef cachedRGBProfileRef
= NULL
;
419 // we only create the profile reference once
420 if (cachedRGBProfileRef
== NULL
)
422 CMProfileLocation loc
;
424 loc
.locType
= cmPathBasedProfile
;
425 strcpy(loc
.u
.pathLoc
.path
, kGenericRGBProfilePathStr
);
427 verify_noerr( CMOpenProfile(&cachedRGBProfileRef
, &loc
) );
430 if (cachedRGBProfileRef
)
432 // clone the profile reference so that the caller has their own reference, not our cached one
433 CMCloneProfileRef(cachedRGBProfileRef
);
436 return cachedRGBProfileRef
;
440 Return the generic RGB color space. This is a 'get' function and the caller should
441 not release the returned value unless the caller retains it first. Usually callers
442 of this routine will immediately use the returned colorspace with CoreGraphics
443 so they typically do not need to retain it themselves.
445 This function creates the generic RGB color space once and hangs onto it so it can
446 return it whenever this function is called.
449 CGColorSpaceRef
wxMacGetGenericRGBColorSpace()
451 static CGColorSpaceRef genericRGBColorSpace
= NULL
;
453 if (genericRGBColorSpace
== NULL
)
455 CMProfileRef genericRGBProfile
= wxMacOpenGenericProfile();
457 if (genericRGBProfile
)
459 genericRGBColorSpace
= CGColorSpaceCreateWithPlatformColorSpace(genericRGBProfile
);
460 wxASSERT_MSG( genericRGBColorSpace
!= NULL
, wxT("couldn't create the generic RGB color space") ) ;
462 // we opened the profile so it is up to us to close it
463 CMCloseProfile(genericRGBProfile
);
466 return genericRGBColorSpace
;
469 void AddEllipticArcToPath(CGContextRef c
, CGPoint center
, float a
, float b
, float fromDegree
, float toDegree
)
471 CGContextSaveGState(c
);
472 CGContextTranslateCTM(c
, center
.x
, center
.y
);
473 CGContextScaleCTM(c
, a
, b
);
474 CGContextMoveToPoint(c
, 1, 0);
475 CGContextAddArc(c
, 0, 0, 1, DegToRad(fromDegree
), DegToRad(toDegree
), 0);
476 CGContextClosePath(c
);
477 CGContextRestoreGState(c
);
480 void AddRoundedRectToPath(CGContextRef c
, CGRect rect
, float ovalWidth
,
484 if (ovalWidth
== 0 || ovalHeight
== 0)
486 CGContextAddRect(c
, rect
);
489 CGContextSaveGState(c
);
490 CGContextTranslateCTM(c
, CGRectGetMinX(rect
), CGRectGetMinY(rect
));
491 CGContextScaleCTM(c
, ovalWidth
, ovalHeight
);
492 fw
= CGRectGetWidth(rect
) / ovalWidth
;
493 fh
= CGRectGetHeight(rect
) / ovalHeight
;
494 CGContextMoveToPoint(c
, fw
, fh
/2);
495 CGContextAddArcToPoint(c
, fw
, fh
, fw
/2, fh
, 1);
496 CGContextAddArcToPoint(c
, 0, fh
, 0, fh
/2, 1);
497 CGContextAddArcToPoint(c
, 0, 0, fw
/2, 0, 1);
498 CGContextAddArcToPoint(c
, fw
, 0, fw
, fh
/2, 1);
499 CGContextClosePath(c
);
500 CGContextRestoreGState(c
);
507 m_mm_to_pix_x
= mm2pt
;
508 m_mm_to_pix_y
= mm2pt
;
509 m_internalDeviceOriginX
= 0;
510 m_internalDeviceOriginY
= 0;
511 m_externalDeviceOriginX
= 0;
512 m_externalDeviceOriginY
= 0;
513 m_logicalScaleX
= 1.0;
514 m_logicalScaleY
= 1.0;
519 m_needComputeScaleX
= FALSE
;
520 m_needComputeScaleY
= FALSE
;
524 m_macLocalOrigin
.x
= m_macLocalOrigin
.y
= 0 ;
526 m_pen
= *wxBLACK_PEN
;
527 m_font
= *wxNORMAL_FONT
;
528 m_brush
= *wxWHITE_BRUSH
;
530 m_macATSUIStyle
= NULL
;
532 m_graphicContext
= NULL
;
537 if( m_macATSUIStyle
)
539 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUIStyle
);
540 m_macATSUIStyle
= NULL
;
543 delete m_graphicContext
;
546 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
, wxCoord x
, wxCoord y
, bool useMask
)
548 wxCHECK_RET( Ok(), wxT("invalid window dc") );
549 wxCHECK_RET( bmp
.Ok(), wxT("invalid bitmap") );
550 wxCoord xx
= XLOG2DEVMAC(x
);
551 wxCoord yy
= YLOG2DEVMAC(y
);
552 wxCoord w
= bmp
.GetWidth();
553 wxCoord h
= bmp
.GetHeight();
554 wxCoord ww
= XLOG2DEVREL(w
);
555 wxCoord hh
= YLOG2DEVREL(h
);
557 CGContextRef cg
= dynamic_cast<wxMacCGContext
*>(m_graphicContext
)->GetNativeContext() ;
558 CGImageRef image
= (CGImageRef
)( bmp
.CGImageCreate() ) ;
559 HIRect r
= CGRectMake( xx
, yy
, ww
, hh
) ;
560 HIViewDrawCGImage( cg
, &r
, image
) ;
561 CGImageRelease( image
) ;
564 void wxDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
566 wxCHECK_RET(Ok(), wxT("Invalid dc wxDC::DoDrawIcon"));
567 wxCHECK_RET(icon
.Ok(), wxT("Invalid icon wxDC::DoDrawIcon"));
569 wxCoord xx
= XLOG2DEVMAC(x
);
570 wxCoord yy
= YLOG2DEVMAC(y
);
571 wxCoord w
= icon
.GetWidth();
572 wxCoord h
= icon
.GetHeight();
573 wxCoord ww
= XLOG2DEVREL(w
);
574 wxCoord hh
= YLOG2DEVREL(h
);
576 CGContextRef cg
= dynamic_cast<wxMacCGContext
*>(m_graphicContext
)->GetNativeContext() ;
577 CGRect r
= CGRectMake( 00 , 00 , ww
, hh
) ;
578 CGContextSaveGState(cg
);
579 CGContextTranslateCTM(cg
, xx
, yy
+ hh
);
580 CGContextScaleCTM(cg
, 1, -1);
581 PlotIconRefInContext( cg
, &r
, kAlignNone
, kTransformNone
,
582 NULL
, kPlotIconRefNormalFlags
, MAC_WXHICON( icon
.GetHICON() ) ) ;
583 CGContextRestoreGState( cg
) ;
586 void wxDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
588 wxCHECK_RET(Ok(), wxT("wxDC::DoSetClippingRegion Invalid DC"));
589 wxCoord xx
, yy
, ww
, hh
;
592 ww
= XLOG2DEVREL(width
);
593 hh
= YLOG2DEVREL(height
);
594 // SetRectRgn( (RgnHandle) m_macCurrentClipRgn , xx , yy , xx + ww , yy + hh ) ;
595 // SectRgn( (RgnHandle) m_macCurrentClipRgn , (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
598 m_clipX1
= wxMax( m_clipX1
, xx
);
599 m_clipY1
= wxMax( m_clipY1
, yy
);
600 m_clipX2
= wxMin( m_clipX2
, (xx
+ ww
));
601 m_clipY2
= wxMin( m_clipY2
, (yy
+ hh
));
611 // TODO as soon as we don't reset the context for each operation anymore
612 // we have to update the context as well
615 void wxDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
617 wxCHECK_RET( Ok(), wxT("invalid window dc") ) ;
620 DestroyClippingRegion();
624 region
.GetBox( x
, y
, w
, h
);
625 wxCoord xx
, yy
, ww
, hh
;
630 // if we have a scaling that we cannot map onto native regions
631 // we must use the box
632 if ( ww
!= w
|| hh
!= h
)
634 wxDC::DoSetClippingRegion( x
, y
, w
, h
);
639 CopyRgn( (RgnHandle) region.GetWXHRGN() , (RgnHandle) m_macCurrentClipRgn ) ;
640 if ( xx != x || yy != y )
642 OffsetRgn( (RgnHandle) m_macCurrentClipRgn , xx - x , yy - y ) ;
644 SectRgn( (RgnHandle) m_macCurrentClipRgn , (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
648 m_clipX1
= wxMax( m_clipX1
, xx
);
649 m_clipY1
= wxMax( m_clipY1
, yy
);
650 m_clipX2
= wxMin( m_clipX2
, (xx
+ ww
));
651 m_clipY2
= wxMin( m_clipY2
, (yy
+ hh
));
664 void wxDC::DestroyClippingRegion()
666 // CopyRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
670 void wxDC::DoGetSizeMM( int* width
, int* height
) const
675 *width
= long( double(w
) / (m_scaleX
*m_mm_to_pix_x
) );
676 *height
= long( double(h
) / (m_scaleY
*m_mm_to_pix_y
) );
679 void wxDC::SetTextForeground( const wxColour
&col
)
681 wxCHECK_RET(Ok(), wxT("Invalid DC"));
682 if ( col
!= m_textForegroundColour
)
684 m_textForegroundColour
= col
;
689 void wxDC::SetTextBackground( const wxColour
&col
)
691 wxCHECK_RET(Ok(), wxT("Invalid DC"));
692 m_textBackgroundColour
= col
;
695 void wxDC::SetMapMode( int mode
)
700 SetLogicalScale( twips2mm
*m_mm_to_pix_x
, twips2mm
*m_mm_to_pix_y
);
703 SetLogicalScale( pt2mm
*m_mm_to_pix_x
, pt2mm
*m_mm_to_pix_y
);
706 SetLogicalScale( m_mm_to_pix_x
, m_mm_to_pix_y
);
709 SetLogicalScale( m_mm_to_pix_x
/10.0, m_mm_to_pix_y
/10.0 );
713 SetLogicalScale( 1.0, 1.0 );
716 if (mode
!= wxMM_TEXT
)
718 m_needComputeScaleX
= TRUE
;
719 m_needComputeScaleY
= TRUE
;
723 void wxDC::SetUserScale( double x
, double y
)
725 // allow negative ? -> no
728 ComputeScaleAndOrigin();
731 void wxDC::SetLogicalScale( double x
, double y
)
736 ComputeScaleAndOrigin();
739 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
741 m_logicalOriginX
= x
* m_signX
; // is this still correct ?
742 m_logicalOriginY
= y
* m_signY
;
743 ComputeScaleAndOrigin();
746 void wxDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
748 m_externalDeviceOriginX
= x
;
749 m_externalDeviceOriginY
= y
;
750 ComputeScaleAndOrigin();
753 void wxDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp
)
755 m_signX
= (xLeftRight
? 1 : -1);
756 m_signY
= (yBottomUp
? -1 : 1);
757 ComputeScaleAndOrigin();
760 wxSize
wxDC::GetPPI() const
762 return wxSize(72, 72);
765 int wxDC::GetDepth() const
770 void wxDC::ComputeScaleAndOrigin()
772 // CMB: copy scale to see if it changes
773 double origScaleX
= m_scaleX
;
774 double origScaleY
= m_scaleY
;
775 m_scaleX
= m_logicalScaleX
* m_userScaleX
;
776 m_scaleY
= m_logicalScaleY
* m_userScaleY
;
777 m_deviceOriginX
= m_internalDeviceOriginX
+ m_externalDeviceOriginX
;
778 m_deviceOriginY
= m_internalDeviceOriginY
+ m_externalDeviceOriginY
;
779 // CMB: if scale has changed call SetPen to recalulate the line width
780 if (m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
)
782 // this is a bit artificial, but we need to force wxDC to think
783 // the pen has changed
790 void wxDC::SetPalette( const wxPalette
& palette
)
794 void wxDC::SetBackgroundMode( int mode
)
796 m_backgroundMode
= mode
;
799 void wxDC::SetFont( const wxFont
&font
)
805 void wxDC::SetPen( const wxPen
&pen
)
810 if ( m_graphicContext
)
812 m_graphicContext
->SetPen( m_pen
) ;
816 void wxDC::SetBrush( const wxBrush
&brush
)
818 if (m_brush
== brush
)
821 if ( m_graphicContext
)
823 m_graphicContext
->SetBrush( m_brush
) ;
827 void wxDC::SetBackground( const wxBrush
&brush
)
829 if (m_backgroundBrush
== brush
)
831 m_backgroundBrush
= brush
;
832 if (!m_backgroundBrush
.Ok())
836 void wxDC::SetLogicalFunction( int function
)
838 if (m_logicalFunction
== function
)
840 m_logicalFunction
= function
;
843 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
844 const wxColour
& col
, int style
);
846 bool wxDC::DoFloodFill(wxCoord x
, wxCoord y
,
847 const wxColour
& col
, int style
)
849 return wxDoFloodFill(this, x
, y
, col
, style
);
852 bool wxDC::DoGetPixel( wxCoord x
, wxCoord y
, wxColour
*col
) const
854 wxCHECK_MSG( Ok(), false, wxT("wxDC::DoGetPixel Invalid DC") );
855 wxFAIL_MSG( wxT("GetPixel not implemented on Core Graphics") ) ;
859 void wxDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
861 wxCHECK_RET(Ok(), wxT("Invalid DC"));
863 wxCoord xx1
= XLOG2DEVMAC(x1
) ;
864 wxCoord yy1
= YLOG2DEVMAC(y1
) ;
865 wxCoord xx2
= XLOG2DEVMAC(x2
) ;
866 wxCoord yy2
= YLOG2DEVMAC(y2
) ;
868 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
869 path
->MoveToPoint( xx1
, yy1
) ;
870 path
->AddLineToPoint( xx2
, yy2
) ;
871 path
->CloseSubpath() ;
872 m_graphicContext
->StrokePath( path
) ;
875 CalcBoundingBox(x1
, y1
);
876 CalcBoundingBox(x2
, y2
);
879 void wxDC::DoCrossHair( wxCoord x
, wxCoord y
)
881 wxCHECK_RET( Ok(), wxT("wxDC::DoCrossHair Invalid window dc") );
887 wxCoord xx
= XLOG2DEVMAC(x
);
888 wxCoord yy
= YLOG2DEVMAC(y
);
890 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
891 path
->MoveToPoint( XLOG2DEVMAC(0), yy
) ;
892 path
->AddLineToPoint( XLOG2DEVMAC(w
), yy
) ;
893 path
->CloseSubpath() ;
894 path
->MoveToPoint( xx
, YLOG2DEVMAC(0) ) ;
895 path
->AddLineToPoint( xx
, YLOG2DEVMAC(h
) ) ;
896 path
->CloseSubpath() ;
897 m_graphicContext
->StrokePath( path
) ;
900 CalcBoundingBox(x
, y
);
901 CalcBoundingBox(x
+w
, y
+h
);
905 * To draw arcs properly the angles need to be converted from the WX style:
906 * Angles start on the +ve X axis and go anti-clockwise (As you would draw on
907 * a normal axis on paper).
910 * Angles start on the +ve y axis and go clockwise.
913 static double wxConvertWXangleToMACangle(double angle
)
915 double newAngle
= 90 - angle
;
921 void wxDC::DoDrawArc( wxCoord x1
, wxCoord y1
,
922 wxCoord x2
, wxCoord y2
,
923 wxCoord xc
, wxCoord yc
)
925 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawArc Invalid DC"));
926 wxCoord xx1
= XLOG2DEVMAC(x1
);
927 wxCoord yy1
= YLOG2DEVMAC(y1
);
928 wxCoord xx2
= XLOG2DEVMAC(x2
);
929 wxCoord yy2
= YLOG2DEVMAC(y2
);
930 wxCoord xxc
= XLOG2DEVMAC(xc
);
931 wxCoord yyc
= YLOG2DEVMAC(yc
);
932 double dx
= xx1
- xxc
;
933 double dy
= yy1
- yyc
;
934 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
935 wxCoord rad
= (wxCoord
)radius
;
936 double radius1
, radius2
;
937 if (xx1
== xx2
&& yy1
== yy2
)
942 else if (radius
== 0.0)
944 radius1
= radius2
= 0.0;
948 radius1
= (xx1
- xxc
== 0) ?
949 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
950 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
951 radius2
= (xx2
- xxc
== 0) ?
952 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
953 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
955 wxCoord alpha2
= wxCoord(radius2
- radius1
);
956 wxCoord alpha1
= wxCoord(wxConvertWXangleToMACangle(radius1
));
957 if( (xx1
> xx2
) || (yy1
> yy2
) ) {
960 Rect r
= { yyc
- rad
, xxc
- rad
, yyc
+ rad
, xxc
+ rad
};
961 wxMacCGContext
* mctx
= ((wxMacCGContext
*) m_graphicContext
) ;
962 CGContextRef ctx
= mctx
->GetNativeContext() ;
963 AddEllipticArcToPath( ctx
, CGPointMake( xxc
, yyc
) , rad
, rad
, 0 , 180 ) ;
964 CGContextDrawPath( ctx
, mctx
->GetDrawingMode() ) ;
967 void wxDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
,
968 double sa
, double ea
)
970 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawEllepticArc Invalid DC"));
972 double angle
= sa
- ea
; // Order important Mac in opposite direction to wx
973 // we have to make sure that the filling is always counter-clockwise
976 wxCoord xx
= XLOG2DEVMAC(x
);
977 wxCoord yy
= YLOG2DEVMAC(y
);
978 wxCoord ww
= m_signX
* XLOG2DEVREL(w
);
979 wxCoord hh
= m_signY
* YLOG2DEVREL(h
);
980 // handle -ve width and/or height
981 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
982 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
983 sa
= wxConvertWXangleToMACangle(sa
);
984 wxMacCGContext
* mctx
= ((wxMacCGContext
*) m_graphicContext
) ;
985 CGContextRef ctx
= mctx
->GetNativeContext() ;
986 AddEllipticArcToPath( ctx
, CGPointMake( xx
+ ww
/ 2 , yy
+ hh
/ 2 ) , ww
/ 2 , hh
/ 2 , sa
, angle
) ;
987 CGContextDrawPath( ctx
, mctx
->GetDrawingMode() ) ;
990 void wxDC::DoDrawPoint( wxCoord x
, wxCoord y
)
992 wxCHECK_RET(Ok(), wxT("Invalid DC"));
993 DoDrawLine( x
, y
, x
+ 1 , y
+ 1 ) ;
996 void wxDC::DoDrawLines(int n
, wxPoint points
[],
997 wxCoord xoffset
, wxCoord yoffset
)
999 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1001 wxCoord x1
, x2
, y1
, y2
;
1002 x1
= XLOG2DEVMAC(points
[0].x
+ xoffset
);
1003 y1
= YLOG2DEVMAC(points
[0].y
+ yoffset
);
1004 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
1005 path
->MoveToPoint( x1
, y1
) ;
1006 for (int i
= 1; i
< n
; i
++)
1008 x2
= XLOG2DEVMAC(points
[i
].x
+ xoffset
);
1009 y2
= YLOG2DEVMAC(points
[i
].y
+ yoffset
);
1011 path
->AddLineToPoint( x2
, y2
) ;
1013 m_graphicContext
->StrokePath( path
) ;
1017 void wxDC::DoDrawPolygon(int n
, wxPoint points
[],
1018 wxCoord xoffset
, wxCoord yoffset
,
1021 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1022 wxCoord x1
, x2
, y1
, y2
;
1023 if ( n
== 0 || (m_brush
.GetStyle() == wxTRANSPARENT
&& m_pen
.GetStyle() == wxTRANSPARENT
) )
1026 x2
= x1
= XLOG2DEVMAC(points
[0].x
+ xoffset
);
1027 y2
= y1
= YLOG2DEVMAC(points
[0].y
+ yoffset
);
1029 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
1030 path
->MoveToPoint( x1
, y1
) ;
1031 for (int i
= 1; i
< n
; i
++)
1033 x2
= XLOG2DEVMAC(points
[i
].x
+ xoffset
);
1034 y2
= YLOG2DEVMAC(points
[i
].y
+ yoffset
);
1036 path
->AddLineToPoint( x2
, y2
) ;
1038 if ( x1
!= x2
|| y1
!= y2
)
1040 path
->AddLineToPoint( x1
,y1
) ;
1042 path
->CloseSubpath() ;
1043 m_graphicContext
->DrawPath( path
, fillStyle
) ;
1047 void wxDC::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1049 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1050 wxCoord xx
= XLOG2DEVMAC(x
);
1051 wxCoord yy
= YLOG2DEVMAC(y
);
1052 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
1053 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
1054 // CMB: draw nothing if transformed w or h is 0
1055 if (ww
== 0 || hh
== 0)
1057 // CMB: handle -ve width and/or height
1068 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
1069 path
->AddRectangle(xx
,yy
, ww
, hh
) ;
1070 path
->CloseSubpath() ;
1071 m_graphicContext
->DrawPath( path
) ;
1075 void wxDC::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
,
1076 wxCoord width
, wxCoord height
,
1079 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1081 radius
= - radius
* ((width
< height
) ? width
: height
);
1082 wxCoord xx
= XLOG2DEVMAC(x
);
1083 wxCoord yy
= YLOG2DEVMAC(y
);
1084 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
1085 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
1086 // CMB: draw nothing if transformed w or h is 0
1087 if (ww
== 0 || hh
== 0)
1089 // CMB: handle -ve width and/or height
1100 Rect rect
= { yy
, xx
, yy
+ hh
, xx
+ ww
} ;
1101 wxMacCGContext
* mctx
= ((wxMacCGContext
*) m_graphicContext
) ;
1102 CGContextRef ctx
= mctx
->GetNativeContext() ;
1103 AddRoundedRectToPath( ctx
, CGRectMake( xx
, yy
, ww
, hh
) , 16 ,16 ) ;
1104 CGContextDrawPath( ctx
, mctx
->GetDrawingMode() ) ;
1107 void wxDC::DoDrawEllipse(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1109 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1110 wxCoord xx
= XLOG2DEVMAC(x
);
1111 wxCoord yy
= YLOG2DEVMAC(y
);
1112 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
1113 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
1114 // CMB: draw nothing if transformed w or h is 0
1115 if (ww
== 0 || hh
== 0)
1117 // CMB: handle -ve width and/or height
1129 wxMacCGContext
* mctx
= ((wxMacCGContext
*) m_graphicContext
) ;
1130 CGContextRef ctx
= mctx
->GetNativeContext() ;
1131 if ( width
== height
)
1133 CGContextBeginPath(ctx
);
1134 CGContextAddArc(ctx
,
1141 CGContextClosePath(ctx
);
1143 CGContextDrawPath( ctx
, kCGPathFillStroke
) ;
1147 AddEllipticArcToPath( ctx
, CGPointMake( xx
+ ww
/ 2 , yy
+ hh
/ 2 ) , ww
/ 2 , hh
/ 2 , 0 , 360) ;
1148 CGContextDrawPath( ctx
, mctx
->GetDrawingMode() ) ;
1152 bool wxDC::CanDrawBitmap(void) const
1157 bool wxDC::DoBlit(wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
1158 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int logical_func
, bool useMask
,
1159 wxCoord xsrcMask
, wxCoord ysrcMask
)
1161 wxCHECK_MSG(Ok(), false, wxT("wxDC::DoBlit Illegal dc"));
1162 wxCHECK_MSG(source
->Ok(), false, wxT("wxDC::DoBlit Illegal source DC"));
1163 if ( logical_func
== wxNO_OP
)
1165 if (xsrcMask
== -1 && ysrcMask
== -1)
1167 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
1170 wxMemoryDC
* memdc
= dynamic_cast<wxMemoryDC
*>(source
) ;
1173 wxBitmap blit
= memdc
->GetSelectedObject() ;
1174 wxASSERT_MSG( blit
.Ok() , wxT("Invalid bitmap for blitting") ) ;
1176 wxCoord xxdest
= XLOG2DEVMAC(xdest
);
1177 wxCoord yydest
= YLOG2DEVMAC(ydest
);
1178 wxCoord ww
= XLOG2DEVREL(width
);
1179 wxCoord hh
= YLOG2DEVREL(height
);
1181 wxCoord bmpwidth
= blit
.GetWidth();
1182 wxCoord bmpheight
= blit
.GetHeight();
1184 if ( xsrc
!= 0 || ysrc
!= 0 || bmpwidth
!= width
|| bmpheight
!= height
)
1186 wxRect
subrect( xsrc
, ysrc
, width
, height
) ;
1187 blit
= blit
.GetSubBitmap( subrect
) ;
1190 CGContextRef cg
= dynamic_cast<wxMacCGContext
*>(m_graphicContext
)->GetNativeContext() ;
1191 CGImageRef image
= (CGImageRef
)( blit
.CGImageCreate() ) ;
1192 HIRect r
= CGRectMake( xxdest
, yydest
, ww
, hh
) ;
1193 HIViewDrawCGImage( cg
, &r
, image
) ;
1194 CGImageRelease( image
) ;
1199 wxFAIL_MSG( wxT("Blitting is only supported from bitmap contexts") ) ;
1204 void wxDC::DoDrawRotatedText(const wxString
& str
, wxCoord x
, wxCoord y
,
1207 wxCHECK_RET( Ok(), wxT("wxDC::DoDrawRotatedText Invalid window dc") );
1209 if ( str
.Length() == 0 )
1212 wxCHECK_RET( m_macATSUIStyle
!= NULL
, wxT("No valid font set") ) ;
1214 OSStatus status
= noErr
;
1215 ATSUTextLayout atsuLayout
;
1216 UniCharCount chars
= str
.Length() ;
1217 UniChar
* ubuf
= NULL
;
1218 #if SIZEOF_WCHAR_T == 4
1219 wxMBConvUTF16BE converter
;
1221 size_t unicharlen
= converter
.WC2MB( NULL
, str
.wc_str() , 0 ) ;
1222 ubuf
= (UniChar
*) malloc( unicharlen
+ 2 ) ;
1223 converter
.WC2MB( (char*) ubuf
, str
.wc_str(), unicharlen
+ 2 ) ;
1225 const wxWCharBuffer wchar
= str
.wc_str( wxConvLocal
) ;
1226 size_t unicharlen
= converter
.WC2MB( NULL
, wchar
.data() , 0 ) ;
1227 ubuf
= (UniChar
*) malloc( unicharlen
+ 2 ) ;
1228 converter
.WC2MB( (char*) ubuf
, wchar
.data() , unicharlen
+ 2 ) ;
1230 chars
= unicharlen
/ 2 ;
1233 ubuf
= (UniChar
*) str
.wc_str() ;
1235 wxWCharBuffer wchar
= str
.wc_str( wxConvLocal
) ;
1236 chars
= wxWcslen( wchar
.data() ) ;
1237 ubuf
= (UniChar
*) wchar
.data() ;
1241 int drawX
= XLOG2DEVMAC(x
) ;
1242 int drawY
= YLOG2DEVMAC(y
) ;
1244 status
= ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr
) ubuf
, 0 , chars
, chars
, 1 ,
1245 &chars
, (ATSUStyle
*) &m_macATSUIStyle
, &atsuLayout
) ;
1247 wxASSERT_MSG( status
== noErr
, wxT("couldn't create the layout of the rotated text") );
1248 int iAngle
= int( angle
);
1252 if ( abs(iAngle
) > 0 )
1254 Fixed atsuAngle
= IntToFixed( iAngle
) ;
1255 ATSUAttributeTag atsuTags
[] =
1257 kATSULineRotationTag
,
1259 ByteCount atsuSizes
[sizeof(atsuTags
)/sizeof(ATSUAttributeTag
)] =
1263 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
)/sizeof(ATSUAttributeTag
)] =
1267 status
= ::ATSUSetLayoutControls(atsuLayout
, sizeof(atsuTags
)/sizeof(ATSUAttributeTag
),
1268 atsuTags
, atsuSizes
, atsuValues
) ;
1271 CGContextRef cgContext
= dynamic_cast<wxMacCGContext
*>(m_graphicContext
)->GetNativeContext() ;
1272 ATSUAttributeTag atsuTags
[] =
1276 ByteCount atsuSizes
[sizeof(atsuTags
)/sizeof(ATSUAttributeTag
)] =
1278 sizeof( CGContextRef
) ,
1280 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
)/sizeof(ATSUAttributeTag
)] =
1284 status
= ::ATSUSetLayoutControls(atsuLayout
, sizeof(atsuTags
)/sizeof(ATSUAttributeTag
),
1285 atsuTags
, atsuSizes
, atsuValues
) ;
1288 ATSUTextMeasurement textBefore
;
1289 ATSUTextMeasurement textAfter
;
1290 ATSUTextMeasurement ascent
;
1291 ATSUTextMeasurement descent
;
1293 status
= ::ATSUGetUnjustifiedBounds( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
1294 &textBefore
, &textAfter
, &ascent
, &descent
);
1295 wxASSERT_MSG( status
== noErr
, wxT("couldn't measure the rotated text") );
1299 if ( m_backgroundMode
== wxSOLID
)
1301 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
1305 path
->AddLineToPoint(
1306 drawX
+ sin(angle
/RAD2DEG
) * FixedToInt(ascent
+ descent
) ,
1307 drawY
+ cos(angle
/RAD2DEG
) * FixedToInt(ascent
+ descent
) ) ;
1308 path
->AddLineToPoint(
1309 drawX
+ sin(angle
/RAD2DEG
) * FixedToInt(ascent
+ descent
) + cos(angle
/RAD2DEG
) * FixedToInt(textAfter
) ,
1310 drawY
+ cos(angle
/RAD2DEG
) * FixedToInt(ascent
+ descent
) - sin(angle
/RAD2DEG
) * FixedToInt(textAfter
) ) ;
1311 path
->AddLineToPoint(
1312 drawX
+ cos(angle
/RAD2DEG
) * FixedToInt(textAfter
) ,
1313 drawY
- sin(angle
/RAD2DEG
) * FixedToInt(textAfter
) ) ;
1315 m_graphicContext
->FillPath( path
, m_textBackgroundColour
) ;
1319 drawX
+= (int)(sin(angle
/RAD2DEG
) * FixedToInt(ascent
));
1320 drawY
+= (int)(cos(angle
/RAD2DEG
) * FixedToInt(ascent
));
1322 status
= ::ATSUMeasureTextImage( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
1323 IntToFixed(drawX
) , IntToFixed(drawY
) , &rect
);
1324 wxASSERT_MSG( status
== noErr
, wxT("couldn't measure the rotated text") );
1326 CGContextSaveGState(dynamic_cast<wxMacCGContext
*>(m_graphicContext
)->GetNativeContext());
1327 CGContextTranslateCTM(dynamic_cast<wxMacCGContext
*>(m_graphicContext
)->GetNativeContext(), drawX
, drawY
);
1328 CGContextScaleCTM(dynamic_cast<wxMacCGContext
*>(m_graphicContext
)->GetNativeContext(), 1, -1);
1329 status
= ::ATSUDrawText( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
1330 IntToFixed(0) , IntToFixed(0) );
1331 wxASSERT_MSG( status
== noErr
, wxT("couldn't draw the rotated text") );
1332 CGContextRestoreGState( dynamic_cast<wxMacCGContext
*>(m_graphicContext
)->GetNativeContext() ) ;
1334 CalcBoundingBox(XDEV2LOG(rect
.left
), YDEV2LOG(rect
.top
) );
1335 CalcBoundingBox(XDEV2LOG(rect
.right
), YDEV2LOG(rect
.bottom
) );
1337 ::ATSUDisposeTextLayout(atsuLayout
);
1338 #if SIZEOF_WCHAR_T == 4
1343 void wxDC::DoDrawText(const wxString
& strtext
, wxCoord x
, wxCoord y
)
1345 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawText Invalid DC"));
1346 DoDrawRotatedText( strtext
, x
, y
, 0.0 ) ;
1349 bool wxDC::CanGetTextExtent() const
1351 wxCHECK_MSG(Ok(), false, wxT("Invalid DC"));
1355 void wxDC::DoGetTextExtent( const wxString
&str
, wxCoord
*width
, wxCoord
*height
,
1356 wxCoord
*descent
, wxCoord
*externalLeading
,
1357 wxFont
*theFont
) const
1359 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1360 wxFont formerFont
= m_font
;
1363 // work around the constness
1364 *((wxFont
*)(&m_font
)) = *theFont
;
1368 if ( str
.Length() == 0 )
1371 wxCHECK_RET( m_macATSUIStyle
!= NULL
, wxT("No valid font set") ) ;
1373 OSStatus status
= noErr
;
1374 ATSUTextLayout atsuLayout
;
1375 UniCharCount chars
= str
.Length() ;
1376 UniChar
* ubuf
= NULL
;
1377 #if SIZEOF_WCHAR_T == 4
1378 wxMBConvUTF16BE converter
;
1380 size_t unicharlen
= converter
.WC2MB( NULL
, str
.wc_str() , 0 ) ;
1381 ubuf
= (UniChar
*) malloc( unicharlen
+ 2 ) ;
1382 converter
.WC2MB( (char*) ubuf
, str
.wc_str(), unicharlen
+ 2 ) ;
1384 const wxWCharBuffer wchar
= str
.wc_str( wxConvLocal
) ;
1385 size_t unicharlen
= converter
.WC2MB( NULL
, wchar
.data() , 0 ) ;
1386 ubuf
= (UniChar
*) malloc( unicharlen
+ 2 ) ;
1387 converter
.WC2MB( (char*) ubuf
, wchar
.data() , unicharlen
+ 2 ) ;
1389 chars
= unicharlen
/ 2 ;
1392 ubuf
= (UniChar
*) str
.wc_str() ;
1394 wxWCharBuffer wchar
= str
.wc_str( wxConvLocal
) ;
1395 chars
= wxWcslen( wchar
.data() ) ;
1396 ubuf
= (UniChar
*) wchar
.data() ;
1401 status
= ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr
) ubuf
, 0 , chars
, chars
, 1 ,
1402 &chars
, (ATSUStyle
*) &m_macATSUIStyle
, &atsuLayout
) ;
1404 wxASSERT_MSG( status
== noErr
, wxT("couldn't create the layout of the text") );
1406 ATSUTextMeasurement textBefore
;
1407 ATSUTextMeasurement textAfter
;
1408 ATSUTextMeasurement textAscent
;
1409 ATSUTextMeasurement textDescent
;
1411 status
= ::ATSUGetUnjustifiedBounds( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
1412 &textBefore
, &textAfter
, &textAscent
, &textDescent
);
1415 *height
= YDEV2LOGREL( FixedToInt(textAscent
+ textDescent
) ) ;
1417 *descent
=YDEV2LOGREL( FixedToInt(textDescent
) );
1418 if ( externalLeading
)
1419 *externalLeading
= 0 ;
1421 *width
= XDEV2LOGREL( FixedToInt(textAfter
- textBefore
) ) ;
1423 ::ATSUDisposeTextLayout(atsuLayout
);
1424 #if SIZEOF_WCHAR_T == 4
1429 // work around the constness
1430 *((wxFont
*)(&m_font
)) = formerFont
;
1436 bool wxDC::DoGetPartialTextExtents(const wxString
& text
, wxArrayInt
& widths
) const
1438 wxCHECK_MSG(Ok(), false, wxT("Invalid DC"));
1441 widths
.Add(0, text
.Length());
1443 if (text
.Length() == 0)
1446 wxFAIL_MSG( wxT("Unimplemented for Core Graphics") ) ;
1451 wxCoord
wxDC::GetCharWidth(void) const
1454 DoGetTextExtent(wxT("g") , &width
, NULL
, NULL
, NULL
, NULL
) ;
1458 wxCoord
wxDC::GetCharHeight(void) const
1461 DoGetTextExtent(wxT("g") , NULL
, &height
, NULL
, NULL
, NULL
) ;
1465 void wxDC::Clear(void)
1467 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1469 if ( m_backgroundBrush
.Ok() && m_backgroundBrush
.GetStyle() != wxTRANSPARENT
)
1471 HIRect rect
= CGRectMake( -10000 , -10000 , 20000 , 20000 ) ;
1472 switch( m_backgroundBrush
.MacGetBrushKind() )
1474 case kwxMacBrushTheme
:
1478 case kwxMacBrushThemeBackground
:
1480 HIThemeBackgroundDrawInfo drawInfo
;
1481 drawInfo
.version
= 0 ;
1482 drawInfo
.state
= kThemeStateActive
;
1483 drawInfo
.kind
= m_backgroundBrush
.MacGetThemeBackground(NULL
) ;
1484 HIThemeDrawBackground( &rect
, &drawInfo
, dynamic_cast<wxMacCGContext
*>(m_graphicContext
)->GetNativeContext() ,
1485 kHIThemeOrientationNormal
) ;
1489 case kwxMacBrushColour
:
1491 RGBColor col
= MAC_WXCOLORREF( m_backgroundBrush
.GetColour().GetPixel()) ;
1492 CGContextSetRGBFillColor( dynamic_cast<wxMacCGContext
*>(m_graphicContext
)->GetNativeContext() , col
.red
/ 65536.0 , col
.green
/ 65536.0 , col
.blue
/ 65536.0 , 1.0 ) ;
1493 CGContextFillRect(dynamic_cast<wxMacCGContext
*>(m_graphicContext
)->GetNativeContext(), rect
);
1495 // reset to normal value
1496 col
= MAC_WXCOLORREF( GetBrush().GetColour().GetPixel() ) ;
1497 CGContextSetRGBFillColor( dynamic_cast<wxMacCGContext
*>(m_graphicContext
)->GetNativeContext() , col
.red
/ 65536.0 , col
.green
/ 65536.0 , col
.blue
/ 65536.0 , 1.0 ) ;
1504 void wxDC::MacInstallFont() const
1506 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1508 if( m_macATSUIStyle
)
1510 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUIStyle
);
1511 m_macATSUIStyle
= NULL
;
1514 OSStatus status
= noErr
;
1515 status
= ATSUCreateAndCopyStyle( (ATSUStyle
) m_font
.MacGetATSUStyle() , (ATSUStyle
*) &m_macATSUIStyle
) ;
1516 wxASSERT_MSG( status
== noErr
, wxT("couldn't set create ATSU style") ) ;
1518 Fixed atsuSize
= IntToFixed( int(m_scaleY
* m_font
.MacGetFontSize()) ) ;
1519 RGBColor atsuColor
= MAC_WXCOLORREF( m_textForegroundColour
.GetPixel() ) ;
1520 ATSUAttributeTag atsuTags
[] =
1525 ByteCount atsuSizes
[sizeof(atsuTags
)/sizeof(ATSUAttributeTag
)] =
1528 sizeof( RGBColor
) ,
1530 // Boolean kTrue = true ;
1531 // Boolean kFalse = false ;
1533 // ATSUVerticalCharacterType kHorizontal = kATSUStronglyHorizontal;
1534 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
)/sizeof(ATSUAttributeTag
)] =
1539 status
= ::ATSUSetAttributes((ATSUStyle
)m_macATSUIStyle
, sizeof(atsuTags
)/sizeof(ATSUAttributeTag
) ,
1540 atsuTags
, atsuSizes
, atsuValues
);
1542 wxASSERT_MSG( status
== noErr
, wxT("couldn't Modify ATSU style") ) ;
1545 // ---------------------------------------------------------------------------
1546 // coordinates transformations
1547 // ---------------------------------------------------------------------------
1549 wxCoord
wxDCBase::DeviceToLogicalX(wxCoord x
) const
1551 return ((wxDC
*)this)->XDEV2LOG(x
);
1554 wxCoord
wxDCBase::DeviceToLogicalY(wxCoord y
) const
1556 return ((wxDC
*)this)->YDEV2LOG(y
);
1559 wxCoord
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const
1561 return ((wxDC
*)this)->XDEV2LOGREL(x
);
1564 wxCoord
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const
1566 return ((wxDC
*)this)->YDEV2LOGREL(y
);
1569 wxCoord
wxDCBase::LogicalToDeviceX(wxCoord x
) const
1571 return ((wxDC
*)this)->XLOG2DEV(x
);
1574 wxCoord
wxDCBase::LogicalToDeviceY(wxCoord y
) const
1576 return ((wxDC
*)this)->YLOG2DEV(y
);
1579 wxCoord
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const
1581 return ((wxDC
*)this)->XLOG2DEVREL(x
);
1584 wxCoord
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const
1586 return ((wxDC
*)this)->YLOG2DEVREL(y
);
1589 #endif // wxMAC_USE_CORE_GRAPHICS