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
21 #include "wx/dcmemory.h"
22 #include "wx/dcprint.h"
23 #include "wx/region.h"
27 #include "wx/mac/uma.h"
33 // in case our functions were defined outside std, we make it known all the same
39 #include "wx/mac/private.h"
41 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
)
43 #ifndef wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
44 #define wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 0
47 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
48 typedef float CGFloat
;
51 //-----------------------------------------------------------------------------
53 //-----------------------------------------------------------------------------
55 #if !defined( __DARWIN__ ) || defined(__MWERKS__)
57 const double M_PI
= 3.14159265358979 ;
61 const double RAD2DEG
= 180.0 / M_PI
;
62 const short kEmulatedMode
= -1 ;
63 const short kUnsupportedMode
= -2 ;
65 extern TECObjectRef s_TECNativeCToUnicode
;
69 // The textctrl implementation still needs that (needs what?) for the non-HIView implementation
71 wxMacWindowClipper::wxMacWindowClipper( const wxWindow
* win
) :
72 wxMacPortSaver( (GrafPtr
) GetWindowPort( (WindowRef
) win
->MacGetTopLevelWindowRef() ) )
74 m_newPort
= (GrafPtr
) GetWindowPort( (WindowRef
) win
->MacGetTopLevelWindowRef() ) ;
75 m_formerClip
= NewRgn() ;
76 m_newClip
= NewRgn() ;
77 GetClip( m_formerClip
) ;
81 // guard against half constructed objects, this just leads to a empty clip
85 win
->MacWindowToRootWindow( &x
, &y
) ;
87 // get area including focus rect
88 CopyRgn( (RgnHandle
) ((wxWindow
*)win
)->MacGetVisibleRegion(true).GetWXHRGN() , m_newClip
) ;
89 if ( !EmptyRgn( m_newClip
) )
90 OffsetRgn( m_newClip
, x
, y
) ;
93 SetClip( m_newClip
) ;
97 wxMacWindowClipper::~wxMacWindowClipper()
99 SetPort( m_newPort
) ;
100 SetClip( m_formerClip
) ;
101 DisposeRgn( m_newClip
) ;
102 DisposeRgn( m_formerClip
) ;
105 wxMacWindowStateSaver::wxMacWindowStateSaver( const wxWindow
* win
) :
106 wxMacWindowClipper( win
)
108 // the port is already set at this point
109 m_newPort
= (GrafPtr
) GetWindowPort( (WindowRef
) win
->MacGetTopLevelWindowRef() ) ;
110 GetThemeDrawingState( &m_themeDrawingState
) ;
113 wxMacWindowStateSaver::~wxMacWindowStateSaver()
115 SetPort( m_newPort
) ;
116 SetThemeDrawingState( m_themeDrawingState
, true ) ;
119 // minimal implementation only used for appearance drawing < 10.3
121 wxMacPortSetter::wxMacPortSetter( const wxDC
* dc
) :
122 m_ph( (GrafPtr
) dc
->m_macPort
)
124 wxASSERT( dc
->Ok() ) ;
127 // dc->MacSetupPort(&m_ph) ;
130 wxMacPortSetter::~wxMacPortSetter()
132 // m_dc->MacCleanupPort(&m_ph) ;
135 //-----------------------------------------------------------------------------
137 //-----------------------------------------------------------------------------
139 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
140 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
141 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
143 //-----------------------------------------------------------------------------
144 // device context implementation
146 // more and more of the dc functionality should be implemented by calling
147 // the appropricate wxMacCGContext, but we will have to do that step by step
148 // also coordinate conversions should be moved to native matrix ops
149 //-----------------------------------------------------------------------------
151 // we always stock two context states, one at entry, to be able to preserve the
152 // state we were called with, the other one after changing to HI Graphics orientation
153 // (this one is used for getting back clippings etc)
155 //-----------------------------------------------------------------------------
156 // wxGraphicPath implementation
157 //-----------------------------------------------------------------------------
159 wxMacCGPath::wxMacCGPath()
161 m_path
= CGPathCreateMutable() ;
164 wxMacCGPath::~wxMacCGPath()
166 CGPathRelease( m_path
) ;
169 // opens (starts) a new subpath
170 void wxMacCGPath::MoveToPoint( wxCoord x1
, wxCoord y1
)
172 CGPathMoveToPoint( m_path
, NULL
, x1
, y1
) ;
175 void wxMacCGPath::AddLineToPoint( wxCoord x1
, wxCoord y1
)
177 CGPathAddLineToPoint( m_path
, NULL
, x1
, y1
) ;
180 void wxMacCGPath::AddQuadCurveToPoint( wxCoord cx1
, wxCoord cy1
, wxCoord x1
, wxCoord y1
)
182 CGPathAddQuadCurveToPoint( m_path
, NULL
, cx1
, cy1
, x1
, y1
);
185 void wxMacCGPath::AddRectangle( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
187 CGRect cgRect
= { { x
, y
} , { w
, h
} } ;
188 CGPathAddRect( m_path
, NULL
, cgRect
) ;
191 void wxMacCGPath::AddCircle( wxCoord x
, wxCoord y
, wxCoord r
)
193 CGPathAddArc( m_path
, NULL
, x
, y
, r
, 0.0 , 2 * M_PI
, true ) ;
196 // closes the current subpath
197 void wxMacCGPath::CloseSubpath()
199 CGPathCloseSubpath( m_path
) ;
202 CGPathRef
wxMacCGPath::GetPath() const
207 void wxMacCGPath::AddArcToPoint( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord r
)
209 CGPathAddArcToPoint( m_path
, NULL
, x1
, y1
, x2
, y2
, r
);
212 void wxMacCGPath::AddArc( wxCoord x
, wxCoord y
, wxCoord r
, double startAngle
, double endAngle
, bool clockwise
)
214 CGPathAddArc( m_path
, NULL
, x
, y
, r
, startAngle
, endAngle
, clockwise
);
217 //-----------------------------------------------------------------------------
218 // wxGraphicContext implementation
219 //-----------------------------------------------------------------------------
221 wxMacCGContext::wxMacCGContext( CGrafPtr port
)
225 m_mode
= kCGPathFill
;
226 m_macATSUIStyle
= NULL
;
229 wxMacCGContext::wxMacCGContext( CGContextRef cgcontext
)
232 m_cgContext
= cgcontext
;
233 m_mode
= kCGPathFill
;
234 m_macATSUIStyle
= NULL
;
235 CGContextSaveGState( m_cgContext
) ;
236 CGContextSaveGState( m_cgContext
) ;
239 wxMacCGContext::wxMacCGContext()
243 m_mode
= kCGPathFill
;
244 m_macATSUIStyle
= NULL
;
247 wxMacCGContext::~wxMacCGContext()
251 CGContextSynchronize( m_cgContext
) ;
252 CGContextRestoreGState( m_cgContext
) ;
253 CGContextRestoreGState( m_cgContext
) ;
257 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 GetPortBounds( (CGrafPtr
) m_qdPort
, &bounds
) ;
357 OSStatus status
= QDBeginCGContext((CGrafPtr
) m_qdPort
, &m_cgContext
) ;
358 CGContextSaveGState( m_cgContext
) ;
360 wxASSERT_MSG( status
== noErr
, wxT("Cannot nest wxDCs on the same window") ) ;
362 CGContextTranslateCTM( m_cgContext
, 0 , bounds
.bottom
- bounds
.top
) ;
363 CGContextScaleCTM( m_cgContext
, 1 , -1 ) ;
365 CGContextSaveGState( m_cgContext
) ;
367 SetBrush( m_brush
) ;
373 void wxMacCGContext::SetNativeContext( CGContextRef cg
)
375 // we allow either setting or clearing but not replacing
376 wxASSERT( m_cgContext
== NULL
|| cg
== NULL
) ;
379 CGContextSaveGState( cg
) ;
383 void wxMacCGContext::Translate( wxCoord dx
, wxCoord dy
)
385 CGContextTranslateCTM( m_cgContext
, dx
, dy
);
388 void wxMacCGContext::Scale( wxCoord xScale
, wxCoord yScale
)
390 CGContextScaleCTM( m_cgContext
, xScale
, yScale
) ;
393 void wxMacCGContext::DrawBitmap( const wxBitmap
&bmp
, wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
395 CGImageRef image
= (CGImageRef
)( bmp
.CGImageCreate() ) ;
396 HIRect r
= CGRectMake( 0 , 0 , w
, h
);
398 CGContextSaveGState( m_cgContext
);
399 CGContextTranslateCTM( m_cgContext
, x
, y
+ h
);
400 CGContextScaleCTM( m_cgContext
, 1, -1 );
402 // in case image is a mask, set the foreground color
403 CGContextSetRGBFillColor( m_cgContext
, m_textForegroundColor
.Red() / 255.0 , m_textForegroundColor
.Green() / 255.0 ,
404 m_textForegroundColor
.Blue() / 255.0 , m_textForegroundColor
.Alpha() / 255.0 ) ;
405 CGContextDrawImage( m_cgContext
, r
, image
);
406 CGContextRestoreGState( m_cgContext
);
408 CGImageRelease( image
) ;
411 void wxMacCGContext::DrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
413 CGRect r
= CGRectMake( 0 , 0 , w
, h
) ;
414 CGContextSaveGState( m_cgContext
);
415 CGContextTranslateCTM( m_cgContext
, x
, y
+ h
);
416 CGContextScaleCTM( m_cgContext
, 1, -1 );
417 PlotIconRefInContext( m_cgContext
, &r
, kAlignNone
, kTransformNone
,
418 NULL
, kPlotIconRefNormalFlags
, MAC_WXHICON( icon
.GetHICON() ) ) ;
419 CGContextRestoreGState( m_cgContext
) ;
422 void wxMacCGContext::PushState()
424 CGContextSaveGState( m_cgContext
);
427 void wxMacCGContext::PopState()
429 CGContextRestoreGState( m_cgContext
);
432 void wxMacCGContext::SetTextColor( const wxColour
&col
)
434 m_textForegroundColor
= col
;
438 #pragma mark wxMacCGPattern, ImagePattern, HatchPattern classes
440 // CGPattern wrapper class: always allocate on heap, never call destructor
447 // is guaranteed to be called only with a non-Null CGContextRef
448 virtual void Render( CGContextRef ctxRef
) = 0 ;
450 operator CGPatternRef() const { return m_patternRef
; }
453 virtual ~wxMacCGPattern()
455 // as this is called only when the m_patternRef is been released;
456 // don't release it again
459 static void _Render( void *info
, CGContextRef ctxRef
)
461 wxMacCGPattern
* self
= (wxMacCGPattern
*) info
;
462 if ( self
&& ctxRef
)
463 self
->Render( ctxRef
) ;
466 static void _Dispose( void *info
)
468 wxMacCGPattern
* self
= (wxMacCGPattern
*) info
;
472 CGPatternRef m_patternRef
;
474 static const CGPatternCallbacks ms_Callbacks
;
477 const CGPatternCallbacks
wxMacCGPattern::ms_Callbacks
= { 0, &wxMacCGPattern::_Render
, &wxMacCGPattern::_Dispose
};
479 class ImagePattern
: public wxMacCGPattern
482 ImagePattern( const wxBitmap
* bmp
, CGAffineTransform transform
)
484 wxASSERT( bmp
&& bmp
->Ok() ) ;
486 Init( (CGImageRef
) bmp
->CGImageCreate() , transform
) ;
489 // ImagePattern takes ownership of CGImageRef passed in
490 ImagePattern( CGImageRef image
, CGAffineTransform transform
)
495 Init( image
, transform
) ;
498 virtual void Render( CGContextRef ctxRef
)
501 HIViewDrawCGImage( ctxRef
, &m_imageBounds
, m_image
);
505 void Init( CGImageRef image
, CGAffineTransform transform
)
510 m_imageBounds
= CGRectMake( 0.0, 0.0, (CGFloat
)CGImageGetWidth( m_image
), (CGFloat
)CGImageGetHeight( m_image
) ) ;
511 m_patternRef
= CGPatternCreate(
512 this , m_imageBounds
, transform
,
513 m_imageBounds
.size
.width
, m_imageBounds
.size
.height
,
514 kCGPatternTilingNoDistortion
, true , &wxMacCGPattern::ms_Callbacks
) ;
518 virtual ~ImagePattern()
521 CGImageRelease( m_image
) ;
525 CGRect m_imageBounds
;
528 class HatchPattern
: public wxMacCGPattern
531 HatchPattern( int hatchstyle
, CGAffineTransform transform
)
533 m_hatch
= hatchstyle
;
534 m_imageBounds
= CGRectMake( 0.0, 0.0, 8.0 , 8.0 ) ;
535 m_patternRef
= CGPatternCreate(
536 this , m_imageBounds
, transform
,
537 m_imageBounds
.size
.width
, m_imageBounds
.size
.height
,
538 kCGPatternTilingNoDistortion
, false , &wxMacCGPattern::ms_Callbacks
) ;
541 void StrokeLineSegments( CGContextRef ctxRef
, const CGPoint pts
[] , size_t count
)
543 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
544 if ( UMAGetSystemVersion() >= 0x1040 )
546 CGContextStrokeLineSegments( ctxRef
, pts
, count
) ;
551 CGContextBeginPath( ctxRef
);
552 for (size_t i
= 0; i
< count
; i
+= 2)
554 CGContextMoveToPoint(ctxRef
, pts
[i
].x
, pts
[i
].y
);
555 CGContextAddLineToPoint(ctxRef
, pts
[i
+1].x
, pts
[i
+1].y
);
557 CGContextStrokePath(ctxRef
);
561 virtual void Render( CGContextRef ctxRef
)
565 case wxBDIAGONAL_HATCH
:
569 { 8.0 , 0.0 } , { 0.0 , 8.0 }
571 StrokeLineSegments( ctxRef
, pts
, 2 ) ;
575 case wxCROSSDIAG_HATCH
:
579 { 0.0 , 0.0 } , { 8.0 , 8.0 } ,
580 { 8.0 , 0.0 } , { 0.0 , 8.0 }
582 StrokeLineSegments( ctxRef
, pts
, 4 ) ;
586 case wxFDIAGONAL_HATCH
:
590 { 0.0 , 0.0 } , { 8.0 , 8.0 }
592 StrokeLineSegments( ctxRef
, pts
, 2 ) ;
600 { 0.0 , 4.0 } , { 8.0 , 4.0 } ,
601 { 4.0 , 0.0 } , { 4.0 , 8.0 } ,
603 StrokeLineSegments( ctxRef
, pts
, 4 ) ;
607 case wxHORIZONTAL_HATCH
:
611 { 0.0 , 4.0 } , { 8.0 , 4.0 } ,
613 StrokeLineSegments( ctxRef
, pts
, 2 ) ;
617 case wxVERTICAL_HATCH
:
621 { 4.0 , 0.0 } , { 4.0 , 8.0 } ,
623 StrokeLineSegments( ctxRef
, pts
, 2 ) ;
633 virtual ~HatchPattern() {}
635 CGRect m_imageBounds
;
641 void wxMacCGContext::SetPen( const wxPen
&pen
)
644 if ( m_cgContext
== NULL
)
647 bool fill
= m_brush
.GetStyle() != wxTRANSPARENT
;
648 bool stroke
= pen
.GetStyle() != wxTRANSPARENT
;
651 // we can benchmark performance; should go into a setting eventually
652 CGContextSetShouldAntialias( m_cgContext
, false ) ;
658 m_mode
= kCGPathFill
; // just a default
662 CGContextSetRGBStrokeColor( m_cgContext
, pen
.GetColour().Red() / 255.0 , pen
.GetColour().Green() / 255.0 ,
663 pen
.GetColour().Blue() / 255.0 , pen
.GetColour().Alpha() / 255.0 ) ;
665 // TODO: * m_dc->m_scaleX
666 CGFloat penWidth
= pen
.GetWidth();
669 CGContextSetLineWidth( m_cgContext
, penWidth
) ;
672 switch ( pen
.GetCap() )
675 cap
= kCGLineCapRound
;
678 case wxCAP_PROJECTING
:
679 cap
= kCGLineCapSquare
;
683 cap
= kCGLineCapButt
;
687 cap
= kCGLineCapButt
;
692 switch ( pen
.GetJoin() )
695 join
= kCGLineJoinBevel
;
699 join
= kCGLineJoinMiter
;
703 join
= kCGLineJoinRound
;
707 join
= kCGLineJoinMiter
;
711 m_mode
= kCGPathStroke
;
714 const CGFloat
*lengths
= NULL
;
715 CGFloat
*userLengths
= NULL
;
717 const CGFloat dashUnit
= penWidth
< 1.0 ? 1.0 : penWidth
;
719 const CGFloat dotted
[] = { dashUnit
, dashUnit
+ 2.0 };
720 const CGFloat short_dashed
[] = { 9.0 , 6.0 };
721 const CGFloat dashed
[] = { 19.0 , 9.0 };
722 const CGFloat dotted_dashed
[] = { 9.0 , 6.0 , 3.0 , 3.0 };
724 switch ( pen
.GetStyle() )
731 count
= WXSIZEOF(dotted
);
736 count
= WXSIZEOF(dashed
) ;
740 lengths
= short_dashed
;
741 count
= WXSIZEOF(short_dashed
) ;
745 lengths
= dotted_dashed
;
746 count
= WXSIZEOF(dotted_dashed
);
751 count
= pen
.GetDashes( &dashes
) ;
752 if ((dashes
!= NULL
) && (count
> 0))
754 userLengths
= new CGFloat
[count
] ;
755 for ( int i
= 0 ; i
< count
; ++i
)
757 userLengths
[i
] = dashes
[i
] * dashUnit
;
759 if ( i
% 2 == 1 && userLengths
[i
] < dashUnit
+ 2.0 )
760 userLengths
[i
] = dashUnit
+ 2.0 ;
761 else if ( i
% 2 == 0 && userLengths
[i
] < dashUnit
)
762 userLengths
[i
] = dashUnit
;
765 lengths
= userLengths
;
770 CGFloat alphaArray
[1] = { 1.0 } ;
771 wxBitmap
* bmp
= pen
.GetStipple() ;
772 if ( bmp
&& bmp
->Ok() )
774 wxMacCFRefHolder
<CGColorSpaceRef
> patternSpace( CGColorSpaceCreatePattern( NULL
) ) ;
775 CGContextSetStrokeColorSpace( m_cgContext
, patternSpace
) ;
776 wxMacCFRefHolder
<CGPatternRef
> pattern( *( new ImagePattern( bmp
, CGContextGetCTM( m_cgContext
) ) ) );
777 CGContextSetStrokePattern( m_cgContext
, pattern
, alphaArray
) ;
784 wxMacCFRefHolder
<CGColorSpaceRef
> patternSpace( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ) ;
785 CGContextSetStrokeColorSpace( m_cgContext
, patternSpace
) ;
786 wxMacCFRefHolder
<CGPatternRef
> pattern( *( new HatchPattern( pen
.GetStyle() , CGContextGetCTM( m_cgContext
) ) ) );
788 CGFloat colorArray
[4] = { pen
.GetColour().Red() / 255.0 , pen
.GetColour().Green() / 255.0 ,
789 pen
.GetColour().Blue() / 255.0 , pen
.GetColour().Alpha() / 255.0 } ;
791 CGContextSetStrokePattern( m_cgContext
, pattern
, colorArray
) ;
796 if ((lengths
!= NULL
) && (count
> 0))
798 CGContextSetLineDash( m_cgContext
, 0 , lengths
, count
) ;
799 // force the line cap, otherwise we get artifacts (overlaps) and just solid lines
800 cap
= kCGLineCapButt
;
804 CGContextSetLineDash( m_cgContext
, 0 , NULL
, 0 ) ;
807 CGContextSetLineCap( m_cgContext
, cap
) ;
808 CGContextSetLineJoin( m_cgContext
, join
) ;
810 delete[] userLengths
;
813 if ( fill
&& stroke
)
814 m_mode
= kCGPathFillStroke
;
818 void wxMacCGContext::SetBrush( const wxBrush
&brush
)
821 if ( m_cgContext
== NULL
)
824 bool fill
= brush
.GetStyle() != wxTRANSPARENT
;
825 bool stroke
= m_pen
.GetStyle() != wxTRANSPARENT
;
828 // we can benchmark performance, should go into a setting later
829 CGContextSetShouldAntialias( m_cgContext
, false ) ;
835 m_mode
= kCGPathFill
; // just a default
839 if ( brush
.GetStyle() == wxSOLID
)
841 CGContextSetRGBFillColor( m_cgContext
, brush
.GetColour().Red() / 255.0 , brush
.GetColour().Green() / 255.0 ,
842 brush
.GetColour().Blue() / 255.0 , brush
.GetColour().Alpha() / 255.0 ) ;
844 else if ( brush
.IsHatch() )
846 wxMacCFRefHolder
<CGColorSpaceRef
> patternSpace( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ) ;
847 CGContextSetFillColorSpace( m_cgContext
, patternSpace
) ;
848 wxMacCFRefHolder
<CGPatternRef
> pattern( *( new HatchPattern( brush
.GetStyle() , CGContextGetCTM( m_cgContext
) ) ) );
850 CGFloat colorArray
[4] = { brush
.GetColour().Red() / 255.0 , brush
.GetColour().Green() / 255.0 ,
851 brush
.GetColour().Blue() / 255.0 , brush
.GetColour().Alpha() / 255.0 } ;
853 CGContextSetFillPattern( m_cgContext
, pattern
, colorArray
) ;
857 // now brush is a bitmap
858 CGFloat alphaArray
[1] = { 1.0 } ;
859 wxBitmap
* bmp
= brush
.GetStipple() ;
860 if ( bmp
&& bmp
->Ok() )
862 wxMacCFRefHolder
<CGColorSpaceRef
> patternSpace( CGColorSpaceCreatePattern( NULL
) ) ;
863 CGContextSetFillColorSpace( m_cgContext
, patternSpace
) ;
864 wxMacCFRefHolder
<CGPatternRef
> pattern( *( new ImagePattern( bmp
, CGContextGetCTM( m_cgContext
) ) ) );
865 CGContextSetFillPattern( m_cgContext
, pattern
, alphaArray
) ;
869 m_mode
= kCGPathFill
;
872 if ( fill
&& stroke
)
873 m_mode
= kCGPathFillStroke
;
875 m_mode
= kCGPathStroke
;
879 void wxMacCGContext::DrawText( const wxString
&str
, wxCoord x
, wxCoord y
, double angle
)
881 OSStatus status
= noErr
;
882 ATSUTextLayout atsuLayout
;
883 UniCharCount chars
= str
.length() ;
884 UniChar
* ubuf
= NULL
;
886 #if SIZEOF_WCHAR_T == 4
887 wxMBConvUTF16 converter
;
889 size_t unicharlen
= converter
.WC2MB( NULL
, str
.wc_str() , 0 ) ;
890 ubuf
= (UniChar
*) malloc( unicharlen
+ 2 ) ;
891 converter
.WC2MB( (char*) ubuf
, str
.wc_str(), unicharlen
+ 2 ) ;
893 const wxWCharBuffer wchar
= str
.wc_str( wxConvLocal
) ;
894 size_t unicharlen
= converter
.WC2MB( NULL
, wchar
.data() , 0 ) ;
895 ubuf
= (UniChar
*) malloc( unicharlen
+ 2 ) ;
896 converter
.WC2MB( (char*) ubuf
, wchar
.data() , unicharlen
+ 2 ) ;
898 chars
= unicharlen
/ 2 ;
901 ubuf
= (UniChar
*) str
.wc_str() ;
903 wxWCharBuffer wchar
= str
.wc_str( wxConvLocal
) ;
904 chars
= wxWcslen( wchar
.data() ) ;
905 ubuf
= (UniChar
*) wchar
.data() ;
909 status
= ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr
) ubuf
, 0 , chars
, chars
, 1 ,
910 &chars
, (ATSUStyle
*) &m_macATSUIStyle
, &atsuLayout
) ;
912 wxASSERT_MSG( status
== noErr
, wxT("couldn't create the layout of the rotated text") );
914 status
= ::ATSUSetTransientFontMatching( atsuLayout
, true ) ;
915 wxASSERT_MSG( status
== noErr
, wxT("couldn't setup transient font matching") );
917 int iAngle
= int( angle
);
918 if ( abs(iAngle
) > 0 )
920 Fixed atsuAngle
= IntToFixed( iAngle
) ;
921 ATSUAttributeTag atsuTags
[] =
923 kATSULineRotationTag
,
925 ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
929 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
933 status
= ::ATSUSetLayoutControls(atsuLayout
, sizeof(atsuTags
) / sizeof(ATSUAttributeTag
),
934 atsuTags
, atsuSizes
, atsuValues
) ;
938 ATSUAttributeTag atsuTags
[] =
942 ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
944 sizeof( CGContextRef
) ,
946 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
950 status
= ::ATSUSetLayoutControls(atsuLayout
, sizeof(atsuTags
) / sizeof(ATSUAttributeTag
),
951 atsuTags
, atsuSizes
, atsuValues
) ;
954 ATSUTextMeasurement textBefore
, textAfter
;
955 ATSUTextMeasurement ascent
, descent
;
957 status
= ::ATSUGetUnjustifiedBounds( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
958 &textBefore
, &textAfter
, &ascent
, &descent
);
960 wxASSERT_MSG( status
== noErr
, wxT("couldn't measure the rotated text") );
965 if ( m_backgroundMode == wxSOLID )
967 wxGraphicPath* path = m_graphicContext->CreatePath() ;
968 path->MoveToPoint( drawX , drawY ) ;
969 path->AddLineToPoint(
970 (int) (drawX + sin(angle / RAD2DEG) * FixedToInt(ascent + descent)) ,
971 (int) (drawY + cos(angle / RAD2DEG) * FixedToInt(ascent + descent)) ) ;
972 path->AddLineToPoint(
973 (int) (drawX + sin(angle / RAD2DEG) * FixedToInt(ascent + descent ) + cos(angle / RAD2DEG) * FixedToInt(textAfter)) ,
974 (int) (drawY + cos(angle / RAD2DEG) * FixedToInt(ascent + descent) - sin(angle / RAD2DEG) * FixedToInt(textAfter)) ) ;
975 path->AddLineToPoint(
976 (int) (drawX + cos(angle / RAD2DEG) * FixedToInt(textAfter)) ,
977 (int) (drawY - sin(angle / RAD2DEG) * FixedToInt(textAfter)) ) ;
979 m_graphicContext->FillPath( path , m_textBackgroundColour ) ;
983 x
+= (int)(sin(angle
/ RAD2DEG
) * FixedToInt(ascent
));
984 y
+= (int)(cos(angle
/ RAD2DEG
) * FixedToInt(ascent
));
986 status
= ::ATSUMeasureTextImage( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
987 IntToFixed(x
) , IntToFixed(y
) , &rect
);
988 wxASSERT_MSG( status
== noErr
, wxT("couldn't measure the rotated text") );
990 CGContextSaveGState(m_cgContext
);
991 CGContextTranslateCTM(m_cgContext
, x
, y
);
992 CGContextScaleCTM(m_cgContext
, 1, -1);
993 status
= ::ATSUDrawText( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
994 IntToFixed(0) , IntToFixed(0) );
996 wxASSERT_MSG( status
== noErr
, wxT("couldn't draw the rotated text") );
998 CGContextRestoreGState(m_cgContext
) ;
1000 ::ATSUDisposeTextLayout(atsuLayout
);
1002 #if SIZEOF_WCHAR_T == 4
1007 void wxMacCGContext::GetTextExtent( const wxString
&str
, wxCoord
*width
, wxCoord
*height
,
1008 wxCoord
*descent
, wxCoord
*externalLeading
) const
1010 wxCHECK_RET( m_macATSUIStyle
!= NULL
, wxT("wxDC(cg)::DoGetTextExtent - no valid font set") ) ;
1012 OSStatus status
= noErr
;
1014 ATSUTextLayout atsuLayout
;
1015 UniCharCount chars
= str
.length() ;
1016 UniChar
* ubuf
= NULL
;
1018 #if SIZEOF_WCHAR_T == 4
1019 wxMBConvUTF16 converter
;
1021 size_t unicharlen
= converter
.WC2MB( NULL
, str
.wc_str() , 0 ) ;
1022 ubuf
= (UniChar
*) malloc( unicharlen
+ 2 ) ;
1023 converter
.WC2MB( (char*) ubuf
, str
.wc_str(), unicharlen
+ 2 ) ;
1025 const wxWCharBuffer wchar
= str
.wc_str( wxConvLocal
) ;
1026 size_t unicharlen
= converter
.WC2MB( NULL
, wchar
.data() , 0 ) ;
1027 ubuf
= (UniChar
*) malloc( unicharlen
+ 2 ) ;
1028 converter
.WC2MB( (char*) ubuf
, wchar
.data() , unicharlen
+ 2 ) ;
1030 chars
= unicharlen
/ 2 ;
1033 ubuf
= (UniChar
*) str
.wc_str() ;
1035 wxWCharBuffer wchar
= str
.wc_str( wxConvLocal
) ;
1036 chars
= wxWcslen( wchar
.data() ) ;
1037 ubuf
= (UniChar
*) wchar
.data() ;
1041 status
= ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr
) ubuf
, 0 , chars
, chars
, 1 ,
1042 &chars
, (ATSUStyle
*) &m_macATSUIStyle
, &atsuLayout
) ;
1044 wxASSERT_MSG( status
== noErr
, wxT("couldn't create the layout of the text") );
1046 ATSUTextMeasurement textBefore
, textAfter
;
1047 ATSUTextMeasurement textAscent
, textDescent
;
1049 status
= ::ATSUGetUnjustifiedBounds( atsuLayout
, kATSUFromTextBeginning
, kATSUToTextEnd
,
1050 &textBefore
, &textAfter
, &textAscent
, &textDescent
);
1053 *height
= FixedToInt(textAscent
+ textDescent
) ;
1055 *descent
= FixedToInt(textDescent
) ;
1056 if ( externalLeading
)
1057 *externalLeading
= 0 ;
1059 *width
= FixedToInt(textAfter
- textBefore
) ;
1061 ::ATSUDisposeTextLayout(atsuLayout
);
1064 void wxMacCGContext::GetPartialTextExtents(const wxString
& text
, wxArrayInt
& widths
) const
1067 widths
.Add(0, text
.length());
1072 ATSUTextLayout atsuLayout
;
1073 UniCharCount chars
= text
.length() ;
1074 UniChar
* ubuf
= NULL
;
1076 #if SIZEOF_WCHAR_T == 4
1077 wxMBConvUTF16 converter
;
1079 size_t unicharlen
= converter
.WC2MB( NULL
, text
.wc_str() , 0 ) ;
1080 ubuf
= (UniChar
*) malloc( unicharlen
+ 2 ) ;
1081 converter
.WC2MB( (char*) ubuf
, text
.wc_str(), unicharlen
+ 2 ) ;
1083 const wxWCharBuffer wchar
= text
.wc_str( wxConvLocal
) ;
1084 size_t unicharlen
= converter
.WC2MB( NULL
, wchar
.data() , 0 ) ;
1085 ubuf
= (UniChar
*) malloc( unicharlen
+ 2 ) ;
1086 converter
.WC2MB( (char*) ubuf
, wchar
.data() , unicharlen
+ 2 ) ;
1088 chars
= unicharlen
/ 2 ;
1091 ubuf
= (UniChar
*) text
.wc_str() ;
1093 wxWCharBuffer wchar
= text
.wc_str( wxConvLocal
) ;
1094 chars
= wxWcslen( wchar
.data() ) ;
1095 ubuf
= (UniChar
*) wchar
.data() ;
1100 status
= ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr
) ubuf
, 0 , chars
, chars
, 1 ,
1101 &chars
, (ATSUStyle
*) &m_macATSUIStyle
, &atsuLayout
) ;
1103 for ( int pos
= 0; pos
< (int)chars
; pos
++ )
1105 unsigned long actualNumberOfBounds
= 0;
1106 ATSTrapezoid glyphBounds
;
1108 // We get a single bound, since the text should only require one. If it requires more, there is an issue
1110 result
= ATSUGetGlyphBounds( atsuLayout
, 0, 0, kATSUFromTextBeginning
, pos
+ 1,
1111 kATSUseDeviceOrigins
, 1, &glyphBounds
, &actualNumberOfBounds
);
1112 if (result
!= noErr
|| actualNumberOfBounds
!= 1 )
1115 widths
[pos
] = FixedToInt( glyphBounds
.upperRight
.x
- glyphBounds
.upperLeft
.x
);
1116 //unsigned char uch = s[i];
1119 ::ATSUDisposeTextLayout(atsuLayout
);
1122 void wxMacCGContext::SetFont( const wxFont
&font
)
1124 if ( m_macATSUIStyle
)
1126 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUIStyle
);
1127 m_macATSUIStyle
= NULL
;
1134 status
= ATSUCreateAndCopyStyle( (ATSUStyle
) font
.MacGetATSUStyle() , (ATSUStyle
*) &m_macATSUIStyle
) ;
1136 wxASSERT_MSG( status
== noErr
, wxT("couldn't create ATSU style") ) ;
1138 // we need the scale here ...
1140 Fixed atsuSize
= IntToFixed( int( /*m_scaleY*/ 1 * font
.MacGetFontSize()) ) ;
1141 RGBColor atsuColor
= MAC_WXCOLORREF( m_textForegroundColor
.GetPixel() ) ;
1142 ATSUAttributeTag atsuTags
[] =
1147 ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
1150 sizeof( RGBColor
) ,
1152 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
1158 status
= ::ATSUSetAttributes(
1159 (ATSUStyle
)m_macATSUIStyle
, sizeof(atsuTags
) / sizeof(ATSUAttributeTag
) ,
1160 atsuTags
, atsuSizes
, atsuValues
);
1162 wxASSERT_MSG( status
== noErr
, wxT("couldn't modify ATSU style") ) ;
1173 m_mm_to_pix_x
= mm2pt
;
1174 m_mm_to_pix_y
= mm2pt
;
1176 m_externalDeviceOriginX
= 0;
1177 m_externalDeviceOriginY
= 0;
1178 m_logicalScaleX
= 1.0;
1179 m_logicalScaleY
= 1.0;
1184 m_needComputeScaleX
=
1185 m_needComputeScaleY
= false;
1188 m_macLocalOrigin
.x
=
1189 m_macLocalOrigin
.y
= 0 ;
1191 m_pen
= *wxBLACK_PEN
;
1192 m_font
= *wxNORMAL_FONT
;
1193 m_brush
= *wxWHITE_BRUSH
;
1195 m_macATSUIStyle
= NULL
;
1196 m_graphicContext
= NULL
;
1201 if ( m_macATSUIStyle
)
1203 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUIStyle
);
1204 m_macATSUIStyle
= NULL
;
1207 delete m_graphicContext
;
1210 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
, wxCoord x
, wxCoord y
, bool useMask
)
1212 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawBitmap - invalid DC") );
1213 wxCHECK_RET( bmp
.Ok(), wxT("wxDC(cg)::DoDrawBitmap - invalid bitmap") );
1215 wxCoord xx
= XLOG2DEVMAC(x
);
1216 wxCoord yy
= YLOG2DEVMAC(y
);
1217 wxCoord w
= bmp
.GetWidth();
1218 wxCoord h
= bmp
.GetHeight();
1219 wxCoord ww
= XLOG2DEVREL(w
);
1220 wxCoord hh
= YLOG2DEVREL(h
);
1222 if ( bmp
.GetDepth()==1 )
1224 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
1225 path
->AddRectangle( xx
, yy
, ww
, hh
) ;
1226 m_graphicContext
->FillPath( path
, m_textBackgroundColour
, wxODDEVEN_RULE
) ;
1228 m_graphicContext
->DrawBitmap( bmp
, xx
, yy
, ww
, hh
) ;
1232 m_graphicContext
->DrawBitmap( bmp
, xx
, yy
, ww
, hh
) ;
1236 void wxDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
1238 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawIcon - invalid DC") );
1239 wxCHECK_RET( icon
.Ok(), wxT("wxDC(cg)::DoDrawIcon - invalid icon") );
1241 wxCoord xx
= XLOG2DEVMAC(x
);
1242 wxCoord yy
= YLOG2DEVMAC(y
);
1243 wxCoord w
= icon
.GetWidth();
1244 wxCoord h
= icon
.GetHeight();
1245 wxCoord ww
= XLOG2DEVREL(w
);
1246 wxCoord hh
= YLOG2DEVREL(h
);
1248 m_graphicContext
->DrawIcon( icon
, xx
, yy
, ww
, hh
) ;
1251 void wxDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1253 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoSetClippingRegion - invalid DC") );
1255 wxCoord xx
, yy
, ww
, hh
;
1256 xx
= XLOG2DEVMAC(x
);
1257 yy
= YLOG2DEVMAC(y
);
1258 ww
= XLOG2DEVREL(width
);
1259 hh
= YLOG2DEVREL(height
);
1261 CGContextRef cgContext
= ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ;
1262 CGRect clipRect
= CGRectMake( xx
, yy
, ww
, hh
) ;
1263 CGContextClipToRect( cgContext
, clipRect
) ;
1265 // SetRectRgn( (RgnHandle) m_macCurrentClipRgn , xx , yy , xx + ww , yy + hh ) ;
1266 // SectRgn( (RgnHandle) m_macCurrentClipRgn , (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
1270 m_clipX1
= wxMax( m_clipX1
, xx
);
1271 m_clipY1
= wxMax( m_clipY1
, yy
);
1272 m_clipX2
= wxMin( m_clipX2
, (xx
+ ww
) );
1273 m_clipY2
= wxMin( m_clipY2
, (yy
+ hh
) );
1285 // TODO: as soon as we don't reset the context for each operation anymore
1286 // we have to update the context as well
1289 void wxDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
1291 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoSetClippingRegionAsRegion - invalid DC") );
1295 DestroyClippingRegion();
1300 region
.GetBox( x
, y
, w
, h
);
1301 wxCoord xx
, yy
, ww
, hh
;
1302 xx
= XLOG2DEVMAC(x
);
1303 yy
= YLOG2DEVMAC(y
);
1304 ww
= XLOG2DEVREL(w
);
1305 hh
= YLOG2DEVREL(h
);
1307 // if we have a scaling that we cannot map onto native regions
1308 // we must use the box
1309 if ( ww
!= w
|| hh
!= h
)
1311 wxDC::DoSetClippingRegion( x
, y
, w
, h
);
1316 CopyRgn( (RgnHandle
) region
.GetWXHRGN() , (RgnHandle
) m_macCurrentClipRgn
) ;
1317 if ( xx
!= x
|| yy
!= y
)
1318 OffsetRgn( (RgnHandle
) m_macCurrentClipRgn
, xx
- x
, yy
- y
) ;
1319 SectRgn( (RgnHandle
)m_macCurrentClipRgn
, (RgnHandle
)m_macBoundaryClipRgn
, (RgnHandle
)m_macCurrentClipRgn
) ;
1324 m_clipX1
= wxMax( m_clipX1
, xx
);
1325 m_clipY1
= wxMax( m_clipY1
, yy
);
1326 m_clipX2
= wxMin( m_clipX2
, (xx
+ ww
) );
1327 m_clipY2
= wxMin( m_clipY2
, (yy
+ hh
) );
1341 void wxDC::DestroyClippingRegion()
1343 // CopyRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
1345 CGContextRef cgContext
= ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ;
1346 CGContextRestoreGState( cgContext
);
1347 CGContextSaveGState( cgContext
);
1349 m_graphicContext
->SetPen( m_pen
) ;
1350 m_graphicContext
->SetBrush( m_brush
) ;
1355 void wxDC::DoGetSizeMM( int* width
, int* height
) const
1361 *width
= long( double(w
) / (m_scaleX
* m_mm_to_pix_x
) );
1363 *height
= long( double(h
) / (m_scaleY
* m_mm_to_pix_y
) );
1366 void wxDC::SetTextForeground( const wxColour
&col
)
1368 wxCHECK_RET( Ok(), wxT("wxDC(cg)::SetTextForeground - invalid DC") );
1370 if ( col
!= m_textForegroundColour
)
1372 m_textForegroundColour
= col
;
1373 m_graphicContext
->SetTextColor( col
);
1374 // in the current implementation the font contains the text color
1375 m_graphicContext
->SetFont(m_font
);
1379 void wxDC::SetTextBackground( const wxColour
&col
)
1381 wxCHECK_RET( Ok(), wxT("wxDC(cg)::SetTextBackground - invalid DC") );
1383 m_textBackgroundColour
= col
;
1386 void wxDC::SetMapMode( int mode
)
1391 SetLogicalScale( twips2mm
* m_mm_to_pix_x
, twips2mm
* m_mm_to_pix_y
);
1395 SetLogicalScale( pt2mm
* m_mm_to_pix_x
, pt2mm
* m_mm_to_pix_y
);
1399 SetLogicalScale( m_mm_to_pix_x
, m_mm_to_pix_y
);
1403 SetLogicalScale( m_mm_to_pix_x
/ 10.0, m_mm_to_pix_y
/ 10.0 );
1408 SetLogicalScale( 1.0, 1.0 );
1412 if (mode
!= wxMM_TEXT
)
1414 m_needComputeScaleX
=
1415 m_needComputeScaleY
= true;
1419 void wxDC::SetUserScale( double x
, double y
)
1421 // allow negative ? -> no
1424 ComputeScaleAndOrigin();
1427 void wxDC::SetLogicalScale( double x
, double y
)
1430 m_logicalScaleX
= x
;
1431 m_logicalScaleY
= y
;
1432 ComputeScaleAndOrigin();
1435 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
1437 m_logicalOriginX
= x
* m_signX
; // is this still correct ?
1438 m_logicalOriginY
= y
* m_signY
;
1439 ComputeScaleAndOrigin();
1442 void wxDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
1444 m_externalDeviceOriginX
= x
;
1445 m_externalDeviceOriginY
= y
;
1446 ComputeScaleAndOrigin();
1449 void wxDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp
)
1451 m_signX
= (xLeftRight
? 1 : -1);
1452 m_signY
= (yBottomUp
? -1 : 1);
1453 ComputeScaleAndOrigin();
1456 wxSize
wxDC::GetPPI() const
1458 return wxSize(72, 72);
1461 int wxDC::GetDepth() const
1466 void wxDC::ComputeScaleAndOrigin()
1468 // CMB: copy scale to see if it changes
1469 double origScaleX
= m_scaleX
;
1470 double origScaleY
= m_scaleY
;
1471 m_scaleX
= m_logicalScaleX
* m_userScaleX
;
1472 m_scaleY
= m_logicalScaleY
* m_userScaleY
;
1473 m_deviceOriginX
= m_externalDeviceOriginX
;
1474 m_deviceOriginY
= m_externalDeviceOriginY
;
1476 // CMB: if scale has changed call SetPen to recalulate the line width
1477 if (m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
)
1479 // this is a bit artificial, but we need to force wxDC to think
1480 // the pen has changed
1481 wxPen
pen( GetPen() );
1488 void wxDC::SetPalette( const wxPalette
& palette
)
1492 void wxDC::SetBackgroundMode( int mode
)
1494 m_backgroundMode
= mode
;
1497 void wxDC::SetFont( const wxFont
&font
)
1500 if ( m_graphicContext
)
1501 m_graphicContext
->SetFont( font
) ;
1504 void wxDC::SetPen( const wxPen
&pen
)
1510 if ( m_graphicContext
)
1512 if ( m_pen
.GetStyle() == wxSOLID
|| m_pen
.GetStyle() == wxTRANSPARENT
)
1514 m_graphicContext
->SetPen( m_pen
) ;
1518 // we have to compensate for moved device origins etc. otherwise patterned pens are standing still
1519 // eg when using a wxScrollWindow and scrolling around
1520 int origX
= XLOG2DEVMAC( 0 ) ;
1521 int origY
= YLOG2DEVMAC( 0 ) ;
1522 m_graphicContext
->Translate( origX
, origY
) ;
1523 m_graphicContext
->SetPen( m_pen
) ;
1524 m_graphicContext
->Translate( -origX
, -origY
) ;
1529 void wxDC::SetBrush( const wxBrush
&brush
)
1531 if (m_brush
== brush
)
1535 if ( m_graphicContext
)
1537 if ( brush
.GetStyle() == wxSOLID
|| brush
.GetStyle() == wxTRANSPARENT
)
1539 m_graphicContext
->SetBrush( m_brush
) ;
1543 // we have to compensate for moved device origins etc. otherwise patterned brushes are standing still
1544 // eg when using a wxScrollWindow and scrolling around
1545 int origX
= XLOG2DEVMAC(0) ;
1546 int origY
= YLOG2DEVMAC(0) ;
1547 m_graphicContext
->Translate( origX
, origY
) ;
1548 m_graphicContext
->SetBrush( m_brush
) ;
1549 m_graphicContext
->Translate( -origX
, -origY
) ;
1554 void wxDC::SetBackground( const wxBrush
&brush
)
1556 if (m_backgroundBrush
== brush
)
1559 m_backgroundBrush
= brush
;
1560 if (!m_backgroundBrush
.Ok())
1564 void wxDC::SetLogicalFunction( int function
)
1566 if (m_logicalFunction
== function
)
1569 m_logicalFunction
= function
;
1570 #if wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
1571 CGContextRef cgContext
= ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ;
1572 if ( m_logicalFunction
== wxCOPY
)
1573 CGContextSetBlendMode( cgContext
, kCGBlendModeNormal
) ;
1574 else if ( m_logicalFunction
== wxINVERT
)
1575 CGContextSetBlendMode( cgContext
, kCGBlendModeExclusion
) ;
1577 CGContextSetBlendMode( cgContext
, kCGBlendModeNormal
) ;
1581 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
1582 const wxColour
& col
, int style
);
1584 bool wxDC::DoFloodFill(wxCoord x
, wxCoord y
,
1585 const wxColour
& col
, int style
)
1587 return wxDoFloodFill(this, x
, y
, col
, style
);
1590 bool wxDC::DoGetPixel( wxCoord x
, wxCoord y
, wxColour
*col
) const
1592 wxCHECK_MSG( Ok(), false, wxT("wxDC(cg)::DoGetPixel - invalid DC") );
1594 wxMacPortSaver
helper((CGrafPtr
)m_macPort
) ;
1597 // NB: GetCPixel is a deprecated QD call, and a slow one at that
1599 XLOG2DEVMAC(x
) + m_macLocalOriginInPort
.x
- m_macLocalOrigin
.x
,
1600 YLOG2DEVMAC(y
) + m_macLocalOriginInPort
.y
- m_macLocalOrigin
.y
, &colour
);
1602 // convert from Mac colour to wx
1603 col
->Set( colour
.red
>> 8, colour
.green
>> 8, colour
.blue
>> 8 );
1608 void wxDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
1610 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawLine - invalid DC") );
1612 #if !wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
1613 if ( m_logicalFunction
!= wxCOPY
)
1617 wxCoord xx1
= XLOG2DEVMAC(x1
) ;
1618 wxCoord yy1
= YLOG2DEVMAC(y1
) ;
1619 wxCoord xx2
= XLOG2DEVMAC(x2
) ;
1620 wxCoord yy2
= YLOG2DEVMAC(y2
) ;
1622 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
1623 path
->MoveToPoint( xx1
, yy1
) ;
1624 path
->AddLineToPoint( xx2
, yy2
) ;
1625 path
->CloseSubpath() ;
1626 m_graphicContext
->StrokePath( path
) ;
1629 CalcBoundingBox(x1
, y1
);
1630 CalcBoundingBox(x2
, y2
);
1633 void wxDC::DoCrossHair( wxCoord x
, wxCoord y
)
1635 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoCrossHair - invalid DC") );
1637 if ( m_logicalFunction
!= wxCOPY
)
1643 wxCoord xx
= XLOG2DEVMAC(x
);
1644 wxCoord yy
= YLOG2DEVMAC(y
);
1646 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
1647 path
->MoveToPoint( XLOG2DEVMAC(0), yy
) ;
1648 path
->AddLineToPoint( XLOG2DEVMAC(w
), yy
) ;
1649 path
->CloseSubpath() ;
1650 path
->MoveToPoint( xx
, YLOG2DEVMAC(0) ) ;
1651 path
->AddLineToPoint( xx
, YLOG2DEVMAC(h
) ) ;
1652 path
->CloseSubpath() ;
1653 m_graphicContext
->StrokePath( path
) ;
1656 CalcBoundingBox(x
, y
);
1657 CalcBoundingBox(x
+ w
, y
+ h
);
1660 void wxDC::DoDrawArc( wxCoord x1
, wxCoord y1
,
1661 wxCoord x2
, wxCoord y2
,
1662 wxCoord xc
, wxCoord yc
)
1664 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawArc - invalid DC") );
1666 if ( m_logicalFunction
!= wxCOPY
)
1669 wxCoord xx1
= XLOG2DEVMAC(x1
);
1670 wxCoord yy1
= YLOG2DEVMAC(y1
);
1671 wxCoord xx2
= XLOG2DEVMAC(x2
);
1672 wxCoord yy2
= YLOG2DEVMAC(y2
);
1673 wxCoord xxc
= XLOG2DEVMAC(xc
);
1674 wxCoord yyc
= YLOG2DEVMAC(yc
);
1676 double dx
= xx1
- xxc
;
1677 double dy
= yy1
- yyc
;
1678 double radius
= sqrt((double)(dx
* dx
+ dy
* dy
));
1679 wxCoord rad
= (wxCoord
)radius
;
1681 if (xx1
== xx2
&& yy1
== yy2
)
1686 else if (radius
== 0.0)
1692 sa
= (xx1
- xxc
== 0) ?
1693 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
1694 -atan2(double(yy1
- yyc
), double(xx1
- xxc
)) * RAD2DEG
;
1695 ea
= (xx2
- xxc
== 0) ?
1696 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
1697 -atan2(double(yy2
- yyc
), double(xx2
- xxc
)) * RAD2DEG
;
1700 bool fill
= m_brush
.GetStyle() != wxTRANSPARENT
;
1702 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
1703 m_graphicContext
->PushState() ;
1704 m_graphicContext
->Translate( xxc
, yyc
) ;
1705 m_graphicContext
->Scale( 1, -1 ) ;
1707 path
->MoveToPoint( 0, 0 ) ;
1708 path
->AddArc( 0, 0, rad
, DegToRad(sa
) , DegToRad(ea
), false ) ;
1710 path
->AddLineToPoint( 0, 0 ) ;
1711 m_graphicContext
->DrawPath( path
) ;
1712 m_graphicContext
->PopState() ;
1716 void wxDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
,
1717 double sa
, double ea
)
1719 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawEllipticArc - invalid DC") );
1721 if ( m_logicalFunction
!= wxCOPY
)
1724 wxCoord xx
= XLOG2DEVMAC(x
);
1725 wxCoord yy
= YLOG2DEVMAC(y
);
1726 wxCoord ww
= m_signX
* XLOG2DEVREL(w
);
1727 wxCoord hh
= m_signY
* YLOG2DEVREL(h
);
1729 // handle -ve width and/or height
1741 bool fill
= m_brush
.GetStyle() != wxTRANSPARENT
;
1743 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
1744 m_graphicContext
->PushState() ;
1745 m_graphicContext
->Translate( xx
+ ww
/ 2, yy
+ hh
/ 2 ) ;
1746 m_graphicContext
->Scale( 1 * ww
/ 2 , -1 * hh
/ 2 ) ;
1748 path
->MoveToPoint( 0, 0 ) ;
1749 path
->AddArc( 0, 0, 1 , DegToRad(sa
) , DegToRad(ea
), false ) ;
1751 path
->AddLineToPoint( 0, 0 ) ;
1752 m_graphicContext
->DrawPath( path
) ;
1753 m_graphicContext
->PopState() ;
1757 void wxDC::DoDrawPoint( wxCoord x
, wxCoord y
)
1759 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawPoint - invalid DC") );
1761 DoDrawLine( x
, y
, x
+ 1 , y
+ 1 ) ;
1764 void wxDC::DoDrawLines(int n
, wxPoint points
[],
1765 wxCoord xoffset
, wxCoord yoffset
)
1767 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawLines - invalid DC") );
1769 #if !wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
1770 if ( m_logicalFunction
!= wxCOPY
)
1774 wxCoord x1
, x2
, y1
, y2
;
1775 x1
= XLOG2DEVMAC(points
[0].x
+ xoffset
);
1776 y1
= YLOG2DEVMAC(points
[0].y
+ yoffset
);
1777 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
1778 path
->MoveToPoint( x1
, y1
) ;
1779 for (int i
= 1; i
< n
; i
++)
1781 x2
= XLOG2DEVMAC(points
[i
].x
+ xoffset
);
1782 y2
= YLOG2DEVMAC(points
[i
].y
+ yoffset
);
1784 path
->AddLineToPoint( x2
, y2
) ;
1787 m_graphicContext
->StrokePath( path
) ;
1792 void wxDC::DoDrawSpline(wxList
*points
)
1794 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawSpline - invalid DC") );
1796 if ( m_logicalFunction
!= wxCOPY
)
1799 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
1801 wxList::compatibility_iterator node
= points
->GetFirst();
1802 if (node
== wxList::compatibility_iterator())
1806 wxPoint
*p
= (wxPoint
*)node
->GetData();
1811 node
= node
->GetNext();
1812 p
= (wxPoint
*)node
->GetData();
1816 wxCoord cx1
= ( x1
+ x2
) / 2;
1817 wxCoord cy1
= ( y1
+ y2
) / 2;
1819 path
->MoveToPoint( XLOG2DEVMAC( x1
) , YLOG2DEVMAC( y1
) ) ;
1820 path
->AddLineToPoint( XLOG2DEVMAC( cx1
) , YLOG2DEVMAC( cy1
) ) ;
1823 while ((node
= node
->GetNext()) != NULL
)
1825 while ((node
= node
->GetNext()))
1826 #endif // !wxUSE_STL
1828 p
= (wxPoint
*)node
->GetData();
1833 wxCoord cx4
= (x1
+ x2
) / 2;
1834 wxCoord cy4
= (y1
+ y2
) / 2;
1836 path
->AddQuadCurveToPoint(
1837 XLOG2DEVMAC( x1
) , YLOG2DEVMAC( y1
) ,
1838 XLOG2DEVMAC( cx4
) , YLOG2DEVMAC( cy4
) ) ;
1844 path
->AddLineToPoint( XLOG2DEVMAC( x2
) , YLOG2DEVMAC( y2
) ) ;
1846 m_graphicContext
->StrokePath( path
) ;
1851 void wxDC::DoDrawPolygon( int n
, wxPoint points
[],
1852 wxCoord xoffset
, wxCoord yoffset
,
1855 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawPolygon - invalid DC") );
1857 if ( n
<= 0 || (m_brush
.GetStyle() == wxTRANSPARENT
&& m_pen
.GetStyle() == wxTRANSPARENT
) )
1859 if ( m_logicalFunction
!= wxCOPY
)
1862 wxCoord x1
, x2
, y1
, y2
;
1863 x2
= x1
= XLOG2DEVMAC(points
[0].x
+ xoffset
);
1864 y2
= y1
= YLOG2DEVMAC(points
[0].y
+ yoffset
);
1866 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
1867 path
->MoveToPoint( x1
, y1
) ;
1868 for (int i
= 1; i
< n
; i
++)
1870 x2
= XLOG2DEVMAC(points
[i
].x
+ xoffset
);
1871 y2
= YLOG2DEVMAC(points
[i
].y
+ yoffset
);
1873 path
->AddLineToPoint( x2
, y2
) ;
1876 if ( x1
!= x2
|| y1
!= y2
)
1877 path
->AddLineToPoint( x1
, y1
) ;
1879 path
->CloseSubpath() ;
1880 m_graphicContext
->DrawPath( path
, fillStyle
) ;
1885 void wxDC::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1887 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawRectangle - invalid DC") );
1889 if ( m_logicalFunction
!= wxCOPY
)
1892 wxCoord xx
= XLOG2DEVMAC(x
);
1893 wxCoord yy
= YLOG2DEVMAC(y
);
1894 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
1895 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
1897 // CMB: draw nothing if transformed w or h is 0
1898 if (ww
== 0 || hh
== 0)
1901 // CMB: handle -ve width and/or height
1913 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
1914 path
->AddRectangle( xx
, yy
, ww
, hh
) ;
1915 m_graphicContext
->DrawPath( path
) ;
1919 void wxDC::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
,
1920 wxCoord width
, wxCoord height
,
1923 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawRoundedRectangle - invalid DC") );
1925 if ( m_logicalFunction
!= wxCOPY
)
1929 radius
= - radius
* ((width
< height
) ? width
: height
);
1930 wxCoord xx
= XLOG2DEVMAC(x
);
1931 wxCoord yy
= YLOG2DEVMAC(y
);
1932 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
1933 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
1935 // CMB: draw nothing if transformed w or h is 0
1936 if (ww
== 0 || hh
== 0)
1939 // CMB: handle -ve width and/or height
1951 wxGraphicPath
* path
= m_graphicContext
->CreatePath() ;
1954 path
->AddRectangle( xx
, yy
, ww
, hh
) ;
1955 m_graphicContext
->DrawPath( path
) ;
1959 m_graphicContext
->PushState() ;
1960 m_graphicContext
->Translate( xx
, yy
) ;
1961 m_graphicContext
->Scale( radius
, radius
) ;
1962 double fw
= ww
/ radius
;
1963 double fh
= hh
/ radius
;
1964 path
->MoveToPoint(fw
, fh
/ 2);
1965 path
->AddArcToPoint(fw
, fh
, fw
/ 2, fh
, 1);
1966 path
->AddArcToPoint(0, fh
, 0, fh
/ 2, 1);
1967 path
->AddArcToPoint(0, 0, fw
/ 2, 0, 1);
1968 path
->AddArcToPoint(fw
, 0, fw
, fh
/ 2, 1);
1969 path
->CloseSubpath();
1970 m_graphicContext
->DrawPath( path
) ;
1971 m_graphicContext
->PopState() ;
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 wxCHECK_MSG( Ok(), false, wxT("wxDC(cg)::DoBlit - invalid DC") );
2025 wxCHECK_MSG( source
->Ok(), false, wxT("wxDC(cg)::DoBlit - invalid source DC") );
2027 if ( logical_func
== wxNO_OP
)
2030 if (xsrcMask
== -1 && ysrcMask
== -1)
2036 wxCoord yysrc
= source
->YLOG2DEVMAC(ysrc
) ;
2037 wxCoord xxsrc
= source
->XLOG2DEVMAC(xsrc
) ;
2038 wxCoord wwsrc
= source
->XLOG2DEVREL(width
) ;
2039 wxCoord hhsrc
= source
->YLOG2DEVREL(height
) ;
2041 wxCoord yydest
= YLOG2DEVMAC(ydest
) ;
2042 wxCoord xxdest
= XLOG2DEVMAC(xdest
) ;
2043 wxCoord wwdest
= XLOG2DEVREL(width
) ;
2044 wxCoord hhdest
= YLOG2DEVREL(height
) ;
2046 wxMemoryDC
* memdc
= dynamic_cast<wxMemoryDC
*>(source
) ;
2047 if ( memdc
&& logical_func
== wxCOPY
)
2049 wxBitmap blit
= memdc
->GetSelectedObject() ;
2051 wxASSERT_MSG( blit
.Ok() , wxT("Invalid bitmap for blitting") ) ;
2053 wxCoord bmpwidth
= blit
.GetWidth();
2054 wxCoord bmpheight
= blit
.GetHeight();
2056 if ( xxsrc
!= 0 || yysrc
!= 0 || bmpwidth
!= wwsrc
|| bmpheight
!= hhsrc
)
2058 wwsrc
= wxMin( wwsrc
, bmpwidth
- xxsrc
) ;
2059 hhsrc
= wxMin( hhsrc
, bmpheight
- yysrc
) ;
2060 if ( wwsrc
> 0 && hhsrc
> 0 )
2062 if ( xxsrc
>= 0 && yysrc
>= 0 )
2064 wxRect
subrect( xxsrc
, yysrc
, wwsrc
, hhsrc
) ;
2065 // TODO we perhaps could add a DrawSubBitmap call to dc for performance reasons
2066 blit
= blit
.GetSubBitmap( subrect
) ;
2070 // in this case we'd probably have to adjust the different coordinates, but
2071 // we have to find out proper contract first
2072 blit
= wxNullBitmap
;
2077 blit
= wxNullBitmap
;
2083 m_graphicContext
->DrawBitmap( blit
, xxdest
, yydest
, wwdest
, hhdest
) ;
2088 wxFAIL_MSG( wxT("Blitting is only supported from bitmap contexts, and only with wxCOPY logical operation.") ) ;
2095 void wxDC::DoDrawRotatedText(const wxString
& str
, wxCoord x
, wxCoord y
,
2098 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawRotatedText - invalid DC") );
2099 // wxCHECK_RET( m_macATSUIStyle != NULL, wxT("wxDC(cg)::DoDrawRotatedText - no valid font set") );
2101 if ( str
.length() == 0 )
2103 if ( m_logicalFunction
!= wxCOPY
)
2106 int drawX
= XLOG2DEVMAC(x
) ;
2107 int drawY
= YLOG2DEVMAC(y
) ;
2109 m_graphicContext
->DrawText( str
, drawX
,drawY
, angle
) ;
2112 void wxDC::DoDrawText(const wxString
& strtext
, wxCoord x
, wxCoord y
)
2114 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawText - invalid DC") );
2116 DoDrawRotatedText( strtext
, x
, y
, 0.0 ) ;
2119 bool wxDC::CanGetTextExtent() const
2121 wxCHECK_MSG( Ok(), false, wxT("wxDC(cg)::CanGetTextExtent - invalid DC") );
2126 void wxDC::DoGetTextExtent( const wxString
&str
, wxCoord
*width
, wxCoord
*height
,
2127 wxCoord
*descent
, wxCoord
*externalLeading
,
2128 wxFont
*theFont
) const
2130 wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoGetTextExtent - invalid DC") );
2132 wxFont formerFont
= m_font
;
2135 m_graphicContext
->SetFont( *theFont
) ;
2138 wxCoord h
, d
, e
, w
;
2140 m_graphicContext
->GetTextExtent( str
, &w
, &h
, &d
, &e
) ;
2143 *height
= YDEV2LOGREL( h
) ;
2145 *descent
=YDEV2LOGREL( d
);
2146 if ( externalLeading
)
2147 *externalLeading
= YDEV2LOGREL( e
);
2149 *width
= XDEV2LOGREL( w
) ;
2153 m_graphicContext
->SetFont( m_font
) ;
2157 bool wxDC::DoGetPartialTextExtents(const wxString
& text
, wxArrayInt
& widths
) const
2159 wxCHECK_MSG( Ok(), false, wxT("wxDC(cg)::DoGetPartialTextExtents - invalid DC") );
2161 m_graphicContext
->GetPartialTextExtents( text
, widths
) ;
2162 for ( size_t i
= 0 ; i
< widths
.GetCount() ; ++i
)
2163 widths
[i
] = XDEV2LOGREL( widths
[i
] );
2168 wxCoord
wxDC::GetCharWidth(void) const
2171 DoGetTextExtent( wxT("g") , &width
, NULL
, NULL
, NULL
, NULL
) ;
2176 wxCoord
wxDC::GetCharHeight(void) const
2179 DoGetTextExtent( wxT("g") , NULL
, &height
, NULL
, NULL
, NULL
) ;
2184 void wxDC::Clear(void)
2186 wxCHECK_RET( Ok(), wxT("wxDC(cg)::Clear - invalid DC") );
2188 if (m_backgroundBrush
.Ok() && m_backgroundBrush
.GetStyle() != wxTRANSPARENT
)
2190 HIRect rect
= CGRectMake( -10000 , -10000 , 20000 , 20000 ) ;
2191 CGContextRef cg
= ((wxMacCGContext
*)(m_graphicContext
))->GetNativeContext() ;
2192 switch ( m_backgroundBrush
.MacGetBrushKind() )
2194 case kwxMacBrushTheme
:
2196 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
2197 if ( HIThemeSetFill
!= 0 )
2199 HIThemeSetFill( m_backgroundBrush
.MacGetTheme(), NULL
, cg
, kHIThemeOrientationNormal
);
2200 CGContextFillRect(cg
, rect
);
2207 GetThemeBrushAsColor( m_backgroundBrush
.MacGetTheme(), 32, true, &color
);
2208 CGContextSetRGBFillColor( cg
, (CGFloat
) color
.red
/ 65536,
2209 (CGFloat
) color
.green
/ 65536, (CGFloat
) color
.blue
/ 65536, 1 );
2210 CGContextFillRect( cg
, rect
);
2213 // reset to normal value
2214 RGBColor col
= MAC_WXCOLORREF( GetBrush().GetColour().GetPixel() ) ;
2215 CGContextSetRGBFillColor( cg
, col
.red
/ 65536.0, col
.green
/ 65536.0, col
.blue
/ 65536.0, 1.0 );
2219 case kwxMacBrushThemeBackground
:
2221 wxFAIL_MSG( wxT("There shouldn't be theme backgrounds under Quartz") ) ;
2223 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
2224 if ( UMAGetSystemVersion() >= 0x1030 )
2226 HIThemeBackgroundDrawInfo drawInfo
;
2227 drawInfo
.version
= 0 ;
2228 drawInfo
.state
= kThemeStateActive
;
2229 drawInfo
.kind
= m_backgroundBrush
.MacGetThemeBackground( NULL
) ;
2230 if ( drawInfo
.kind
== kThemeBackgroundMetal
)
2232 HIThemeDrawBackground( &rect
, &drawInfo
, cg
, kHIThemeOrientationNormal
) ;
2233 HIThemeApplyBackground( &rect
, &drawInfo
, cg
, kHIThemeOrientationNormal
) ;
2240 case kwxMacBrushColour
:
2242 // FIXME: doesn't correctly render stippled brushes !!
2243 // FIXME: should this be replaced by ::SetBrush() ??
2245 RGBColor col
= MAC_WXCOLORREF( m_backgroundBrush
.GetColour().GetPixel()) ;
2246 CGContextSetRGBFillColor( cg
, col
.red
/ 65536.0 , col
.green
/ 65536.0 , col
.blue
/ 65536.0 , 1.0 ) ;
2247 CGContextFillRect(cg
, rect
);
2249 // reset to normal value
2250 col
= MAC_WXCOLORREF( GetBrush().GetColour().GetPixel() ) ;
2251 CGContextSetRGBFillColor( cg
, col
.red
/ 65536.0 , col
.green
/ 65536.0 , col
.blue
/ 65536.0 , 1.0 ) ;
2256 wxFAIL_MSG( wxT("unknown brush kind") ) ;
2264 // ---------------------------------------------------------------------------
2265 // coordinates transformations
2266 // ---------------------------------------------------------------------------
2268 wxCoord
wxDCBase::DeviceToLogicalX(wxCoord x
) const
2270 return ((wxDC
*)this)->XDEV2LOG(x
);
2273 wxCoord
wxDCBase::DeviceToLogicalY(wxCoord y
) const
2275 return ((wxDC
*)this)->YDEV2LOG(y
);
2278 wxCoord
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const
2280 return ((wxDC
*)this)->XDEV2LOGREL(x
);
2283 wxCoord
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const
2285 return ((wxDC
*)this)->YDEV2LOGREL(y
);
2288 wxCoord
wxDCBase::LogicalToDeviceX(wxCoord x
) const
2290 return ((wxDC
*)this)->XLOG2DEV(x
);
2293 wxCoord
wxDCBase::LogicalToDeviceY(wxCoord y
) const
2295 return ((wxDC
*)this)->YLOG2DEV(y
);
2298 wxCoord
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const
2300 return ((wxDC
*)this)->XLOG2DEVREL(x
);
2303 wxCoord
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const
2305 return ((wxDC
*)this)->YLOG2DEVREL(y
);
2308 #endif // wxMAC_USE_CORE_GRAPHICS