+ virtual void DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle );
+
+ virtual void GetTextExtent( const wxString &text, wxDouble *width, wxDouble *height,
+ wxDouble *descent, wxDouble *externalLeading ) const;
+
+ virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const;
+
+ //
+ // image support
+ //
+
+ virtual void DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
+
+ virtual void DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
+
+ void SetNativeContext( CGContextRef cg );
+
+ DECLARE_NO_COPY_CLASS(wxMacCoreGraphicsContext)
+ DECLARE_DYNAMIC_CLASS(wxMacCoreGraphicsContext)
+
+private:
+ void EnsureIsValid();
+
+ CGContextRef m_cgContext;
+ WindowRef m_windowRef;
+ bool m_releaseContext;
+ CGAffineTransform m_windowTransform;
+ wxDouble m_width;
+ wxDouble m_height;
+
+ wxMacCFRefHolder<HIShapeRef> m_clipRgn;
+};
+
+//-----------------------------------------------------------------------------
+// device context implementation
+//
+// more and more of the dc functionality should be implemented by calling
+// the appropricate wxMacCoreGraphicsContext, but we will have to do that step by step
+// also coordinate conversions should be moved to native matrix ops
+//-----------------------------------------------------------------------------
+
+// we always stock two context states, one at entry, to be able to preserve the
+// state we were called with, the other one after changing to HI Graphics orientation
+// (this one is used for getting back clippings etc)
+
+//-----------------------------------------------------------------------------
+// wxMacCoreGraphicsContext implementation
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsContext, wxGraphicsContext)
+
+class wxQuartzOffsetHelper
+{
+public :
+ wxQuartzOffsetHelper( CGContextRef cg , bool offset )
+ {
+ m_cg = cg;
+ m_offset = offset;
+ if ( m_offset )
+ CGContextTranslateCTM( m_cg, 0.5, 0.5 );
+ }
+ ~wxQuartzOffsetHelper( )
+ {
+ if ( m_offset )
+ CGContextTranslateCTM( m_cg, -0.5, -0.5 );
+ }
+public :
+ CGContextRef m_cg;
+ bool m_offset;
+} ;
+
+void wxMacCoreGraphicsContext::Init()
+{
+ m_cgContext = NULL;
+ m_releaseContext = false;
+ m_windowRef = NULL;
+ m_width = 0;
+ m_height = 0;
+
+ HIRect r = CGRectMake(0,0,0,0);
+ m_clipRgn.Set(HIShapeCreateWithRect(&r));
+}
+
+wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext, wxDouble width, wxDouble height ) : wxGraphicsContext(renderer)
+{
+ Init();
+ SetNativeContext(cgcontext);
+ m_width = width;
+ m_height = height;
+}
+
+wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, WindowRef window ): wxGraphicsContext(renderer)
+{
+ Init();
+ m_windowRef = window;
+}
+
+wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, wxWindow* window ): wxGraphicsContext(renderer)
+{
+ Init();
+ m_windowRef = (WindowRef) window->MacGetTopLevelWindowRef();
+ int originX , originY;
+ originX = originY = 0;
+ window->MacWindowToRootWindow( &originX , &originY );
+
+ Rect bounds = { 0,0,0,0 };
+#ifdef __LP64__
+#else
+ GetWindowBounds( m_windowRef, kWindowContentRgn, &bounds );
+#endif
+ m_windowTransform = CGAffineTransformMakeTranslation( 0 , bounds.bottom - bounds.top );
+ m_windowTransform = CGAffineTransformScale( m_windowTransform , 1 , -1 );
+ m_windowTransform = CGAffineTransformTranslate( m_windowTransform, originX, originY ) ;
+}
+
+wxMacCoreGraphicsContext::wxMacCoreGraphicsContext(wxGraphicsRenderer* renderer) : wxGraphicsContext(renderer)
+{
+ Init();
+}
+
+wxMacCoreGraphicsContext::wxMacCoreGraphicsContext() : wxGraphicsContext(NULL)
+{
+ Init();
+ wxLogDebug(wxT("Illegal Constructor called"));
+}
+
+wxMacCoreGraphicsContext::~wxMacCoreGraphicsContext()
+{
+ SetNativeContext(NULL);
+}
+
+void wxMacCoreGraphicsContext::GetSize( wxDouble* width, wxDouble* height)
+{
+ *width = m_width;
+ *height = m_height;
+}
+
+
+void wxMacCoreGraphicsContext::StartPage( wxDouble width, wxDouble height )
+{
+ CGRect r;
+ if ( width != 0 && height != 0)
+ r = CGRectMake( 0 , 0 , width , height );
+ else
+ r = CGRectMake( 0 , 0 , m_width , m_height );
+
+ CGContextBeginPage(m_cgContext, &r );
+// CGContextTranslateCTM( m_cgContext , 0 , height == 0 ? m_height : height );
+// CGContextScaleCTM( m_cgContext , 1 , -1 );
+}
+
+void wxMacCoreGraphicsContext::EndPage()
+{
+ CGContextEndPage(m_cgContext);
+}
+
+void wxMacCoreGraphicsContext::Flush()
+{
+ CGContextFlush(m_cgContext);
+}
+
+void wxMacCoreGraphicsContext::EnsureIsValid()
+{
+ if ( !m_cgContext )
+ {
+ OSStatus status =
+#ifndef __LP64__
+ QDBeginCGContext( GetWindowPort( m_windowRef ) , &m_cgContext );
+#else
+ paramErr;
+#endif
+ wxASSERT_MSG( status == noErr , wxT("Cannot nest wxDCs on the same window") );
+
+ CGContextConcatCTM( m_cgContext, m_windowTransform );
+ CGContextSaveGState( m_cgContext );
+ m_releaseContext = true;
+ if ( !HIShapeIsEmpty(m_clipRgn) )
+ {
+ // the clip region is in device coordinates, so we convert this again to user coordinates
+ wxMacCFRefHolder<HIMutableShapeRef> hishape ;
+ hishape.Set( HIShapeCreateMutableCopy( m_clipRgn ) );
+ CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero,m_windowTransform);
+ HIShapeOffset( hishape, -transformedOrigin.x, -transformedOrigin.y );
+ HIShapeReplacePathInCGContext( hishape, m_cgContext );
+ CGContextClip( m_cgContext );
+ }
+ CGContextSaveGState( m_cgContext );
+ }
+}
+
+// TODO test whether the private CGContextSetCompositeOperation works under 10.3 (using NSCompositingModes)
+
+bool wxMacCoreGraphicsContext::SetLogicalFunction( int function )
+{
+ if (m_logicalFunction == function)
+ return true;
+
+ EnsureIsValid();
+
+ bool retval = false;
+
+ if ( function == wxCOPY )
+ {
+ retval = true;
+ CGContextSetBlendMode( m_cgContext, kCGBlendModeNormal );
+ }
+ else if ( function == wxINVERT || function == wxXOR )
+ {
+ // change color to white
+ CGContextSetBlendMode( m_cgContext, kCGBlendModeExclusion );
+ CGContextSetShouldAntialias( m_cgContext, false );
+ retval = true;
+ }
+
+ if (retval)
+ m_logicalFunction = function;
+ return retval ;
+}
+
+void wxMacCoreGraphicsContext::Clip( const wxRegion ®ion )
+{
+ if( m_cgContext )
+ {
+ HIShapeReplacePathInCGContext( region.GetWXHRGN() , m_cgContext );
+ CGContextClip( m_cgContext );
+ }
+ else
+ {
+ // this offsetting to device coords is not really correct, but since we cannot apply affine transforms
+ // to regions we try at least to have correct translations
+ HIMutableShapeRef mutableShape = HIShapeCreateMutableCopy( region.GetWXHRGN() );
+
+ CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero, m_windowTransform );
+ HIShapeOffset( mutableShape, transformedOrigin.x, transformedOrigin.y );
+ m_clipRgn.Set(mutableShape);
+ }
+}
+
+// clips drawings to the rect
+void wxMacCoreGraphicsContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
+{
+ HIRect r = CGRectMake( x , y , w , h );
+ if ( m_cgContext )
+ {
+ CGContextClipToRect( m_cgContext, r );
+ }
+ else
+ {
+ // the clipping itself must be stored as device coordinates, otherwise
+ // we cannot apply it back correctly
+ r.origin= CGPointApplyAffineTransform( r.origin, m_windowTransform );
+ m_clipRgn.Set(HIShapeCreateWithRect(&r));
+ }
+}
+
+ // resets the clipping to original extent
+void wxMacCoreGraphicsContext::ResetClip()
+{
+ if ( m_cgContext )
+ {
+ // there is no way for clearing the clip, we can only revert to the stored
+ // state, but then we have to make sure everything else is NOT restored
+ CGAffineTransform transform = CGContextGetCTM( m_cgContext );
+ CGContextRestoreGState( m_cgContext );
+ CGContextSaveGState( m_cgContext );
+ CGAffineTransform transformNew = CGContextGetCTM( m_cgContext );
+ transformNew = CGAffineTransformInvert( transformNew ) ;
+ CGContextConcatCTM( m_cgContext, transformNew);
+ CGContextConcatCTM( m_cgContext, transform);
+ }
+ else
+ {
+ HIRect r = CGRectMake(0,0,0,0);
+ m_clipRgn.Set(HIShapeCreateWithRect(&r));
+ }
+}
+
+void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath &path )
+{
+ if ( m_pen.IsNull() )
+ return ;