]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/graphics.cpp
PCH support.
[wxWidgets.git] / src / mac / carbon / graphics.cpp
index 29c61ab26b5e7d0e399bf01d5b3a03bac7f7ff75..6aec43bfc27f71f15a462d08dbcae4b89b49c2bb 100755 (executable)
@@ -16,6 +16,7 @@
 #include "wx/graphics.h"
 
 #ifndef WX_PRECOMP
+    #include "wx/dcclient.h"
     #include "wx/log.h"
     #include "wx/region.h"
 #endif
 typedef float CGFloat;
 #endif
 
+//-----------------------------------------------------------------------------
+// constants
+//-----------------------------------------------------------------------------
+
+#if !defined( __DARWIN__ ) || defined(__MWERKS__)
+#ifndef M_PI
+const double M_PI = 3.14159265358979;
+#endif
+#endif
+
+static const double RAD2DEG = 180.0 / M_PI;
+
 //
 // Graphics Path
 //
 
 class WXDLLEXPORT wxMacCoreGraphicsPath : public wxGraphicsPath
 {
-    DECLARE_NO_COPY_CLASS(wxMacCoreGraphicsPath)
 public :
     wxMacCoreGraphicsPath();
     ~wxMacCoreGraphicsPath();
@@ -83,11 +95,24 @@ public :
     // draws a an arc to two tangents connecting (current) to (x1,y1) and (x1,y1) to (x2,y2), also a straight line from (current) to (x1,y1)
     virtual void AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r );
     
-    CGPathRef GetPath() const;
+       // returns the native path
+       virtual void * GetNativePath() const { return m_path; }
+       
+       // give the native path returned by GetNativePath() back (there might be some deallocations necessary)
+       virtual void UnGetNativePath(void *p) {}
+
+    DECLARE_DYNAMIC_CLASS(wxMacCoreGraphicsPath)
+    DECLARE_NO_COPY_CLASS(wxMacCoreGraphicsPath)
 private :
     CGMutablePathRef m_path;
 };
 
+//-----------------------------------------------------------------------------
+// wxGraphicsPath implementation
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsPath, wxGraphicsPath)
+
 wxMacCoreGraphicsPath::wxMacCoreGraphicsPath()
 {
     m_path = CGPathCreateMutable();
@@ -148,11 +173,6 @@ void wxMacCoreGraphicsPath::CloseSubpath()
     CGPathCloseSubpath( m_path );
 }
 
-CGPathRef wxMacCoreGraphicsPath::GetPath() const
-{
-    return m_path;
-}
-
 // gets the last point of the current path, (0,0) if not yet set
 void wxMacCoreGraphicsPath::GetCurrentPoint( wxDouble& x, wxDouble&y)
 {
@@ -167,13 +187,13 @@ void wxMacCoreGraphicsPath::GetCurrentPoint( wxDouble& x, wxDouble&y)
 
 class WXDLLEXPORT wxMacCoreGraphicsContext : public wxGraphicsContext
 {
-    DECLARE_NO_COPY_CLASS(wxMacCoreGraphicsContext)
-
 public:
     wxMacCoreGraphicsContext( CGContextRef cgcontext );
     
     wxMacCoreGraphicsContext( WindowRef window );
     
+    wxMacCoreGraphicsContext( wxWindow* window );
+    
     wxMacCoreGraphicsContext();
     
     ~wxMacCoreGraphicsContext();
@@ -271,9 +291,17 @@ public:
     void SetNativeContext( CGContextRef cg );
     CGPathDrawingMode GetDrawingMode() const { return m_mode; }
     
+    DECLARE_NO_COPY_CLASS(wxMacCoreGraphicsContext)
+    DECLARE_DYNAMIC_CLASS(wxMacCoreGraphicsContext)
+
 private:
+       void EnsureIsValid();
+
     CGContextRef m_cgContext;
        WindowRef m_windowRef;
+       int m_originX;
+       int m_originY;
+       wxMacCFRefHolder<HIShapeRef> m_clipRgn;
        bool m_releaseContext;
     CGPathDrawingMode m_mode;
     ATSUStyle m_macATSUIStyle;
@@ -283,18 +311,6 @@ private:
     wxColor m_textForegroundColor;
 };
 
-//-----------------------------------------------------------------------------
-// constants
-//-----------------------------------------------------------------------------
-
-#if !defined( __DARWIN__ ) || defined(__MWERKS__)
-#ifndef M_PI
-const double M_PI = 3.14159265358979;
-#endif
-#endif
-
-static const double RAD2DEG = 180.0 / M_PI;
-
 //-----------------------------------------------------------------------------
 // device context implementation
 //
@@ -307,20 +323,19 @@ static const double RAD2DEG = 180.0 / M_PI;
 // state we were called with, the other one after changing to HI Graphics orientation
 // (this one is used for getting back clippings etc)
 
-//-----------------------------------------------------------------------------
-// wxGraphicsPath implementation
-//-----------------------------------------------------------------------------
-
 //-----------------------------------------------------------------------------
 // wxGraphicsContext implementation
 //-----------------------------------------------------------------------------
 
+IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsContext, wxGraphicsContext)
+
 void wxMacCoreGraphicsContext::Init()
 {
     m_cgContext = NULL;
     m_mode = kCGPathFill;
     m_macATSUIStyle = NULL;
        m_releaseContext = false;
+       m_clipRgn.Set(HIShapeCreateEmpty());
 }
 
 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( CGContextRef cgcontext )
@@ -335,15 +350,14 @@ wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( WindowRef window )
 {
        Init();
        m_windowRef = window;
-       OSStatus status = QDBeginCGContext( GetWindowPort( window ) , &m_cgContext );
-       wxASSERT_MSG( status == noErr , wxT("Cannot nest wxDCs on the same window") );
-       Rect bounds;
-       GetWindowBounds( window, kWindowContentRgn, &bounds );
-       CGContextSaveGState( m_cgContext );
-       CGContextTranslateCTM( m_cgContext , 0 , bounds.bottom - bounds.top );
-       CGContextScaleCTM( m_cgContext , 1 , -1 );
-       CGContextSaveGState( m_cgContext );
-       m_releaseContext = true;
+}
+
+wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxWindow* window )
+{
+       Init();
+       m_windowRef = (WindowRef) window->MacGetTopLevelWindowRef();
+    m_originX = m_originY = 0;
+    window->MacWindowToRootWindow( &m_originX , &m_originY );
 }
 
 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext()
@@ -355,7 +369,7 @@ wxMacCoreGraphicsContext::~wxMacCoreGraphicsContext()
 {
     if ( m_cgContext )
     {
-        CGContextSynchronize( m_cgContext );
+        // TODO : when is this necessary - should we add a Flush() method ? CGContextSynchronize( m_cgContext );
         CGContextRestoreGState( m_cgContext );
         CGContextRestoreGState( m_cgContext );
     }
@@ -364,31 +378,76 @@ wxMacCoreGraphicsContext::~wxMacCoreGraphicsContext()
                QDEndCGContext( GetWindowPort( m_windowRef ) , &m_cgContext);
 }
 
+void wxMacCoreGraphicsContext::EnsureIsValid()
+{
+       if ( !m_cgContext )
+       {
+               OSStatus status = QDBeginCGContext( GetWindowPort( m_windowRef ) , &m_cgContext );
+               wxASSERT_MSG( status == noErr , wxT("Cannot nest wxDCs on the same window") );
+               Rect bounds;
+               GetWindowBounds( m_windowRef, kWindowContentRgn, &bounds );
+               CGContextSaveGState( m_cgContext );
+               CGContextTranslateCTM( m_cgContext , 0 , bounds.bottom - bounds.top );
+               CGContextScaleCTM( m_cgContext , 1 , -1 );
+               CGContextTranslateCTM( m_cgContext, m_originX, m_originY );
+               CGContextSaveGState( m_cgContext );
+               m_releaseContext = true;
+               if ( !HIShapeIsEmpty(m_clipRgn) )
+               {
+                       HIShapeReplacePathInCGContext( m_clipRgn, m_cgContext );
+                       CGContextClip( m_cgContext );
+               }
+       }
+}
+
+
 void wxMacCoreGraphicsContext::Clip( const wxRegion &region )
 {
-       HIShapeRef shape = HIShapeCreateWithQDRgn( (RgnHandle) region.GetWXHRGN() );
-       HIShapeReplacePathInCGContext( shape, m_cgContext );
-       CGContextClip( m_cgContext );
-       CFRelease( shape );
+       if( m_cgContext )
+       {
+               HIShapeRef shape = HIShapeCreateWithQDRgn( (RgnHandle) region.GetWXHRGN() );
+               HIShapeReplacePathInCGContext( shape, m_cgContext );
+               CGContextClip( m_cgContext );
+               CFRelease( shape );
+       }
+       else
+       {
+               m_clipRgn.Set(HIShapeCreateWithQDRgn( (RgnHandle) region.GetWXHRGN() ));
+       }
 }
 
 // clips drawings to the rect
 void wxMacCoreGraphicsContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
 {
-    HIRect r = CGRectMake( x , y , w , h );
-       CGContextClipToRect( m_cgContext, r );
+       HIRect r = CGRectMake( x , y , w , h );
+       if ( m_cgContext )
+       {
+               CGContextClipToRect( m_cgContext, r );
+       }
+       else
+       {
+               m_clipRgn.Set(HIShapeCreateWithRect(&r));
+       }
 }
        
        // resets the clipping to original extent
 void wxMacCoreGraphicsContext::ResetClip()
 {
-    CGContextRestoreGState( m_cgContext );
-    CGContextSaveGState( m_cgContext );
+       if ( m_cgContext )
+       {
+               CGContextRestoreGState( m_cgContext );
+               CGContextSaveGState( m_cgContext );
+       }
+       else
+       {
+               m_clipRgn.Set(HIShapeCreateEmpty());
+       }
 }
 
-void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath *p )
+void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath *path )
 {
-    const wxMacCoreGraphicsPath* path = dynamic_cast< const wxMacCoreGraphicsPath*>( p );
+       EnsureIsValid();
+       
     int width = m_pen.GetWidth();
     if ( width == 0 )
         width = 1 ;
@@ -400,16 +459,17 @@ void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath *p )
     if ( offset )
         CGContextTranslateCTM( m_cgContext, 0.5, 0.5 );
 
-    CGContextAddPath( m_cgContext , path->GetPath() );
+    CGContextAddPath( m_cgContext , (CGPathRef) path->GetNativePath() );
     CGContextStrokePath( m_cgContext );
 
     if ( offset )
         CGContextTranslateCTM( m_cgContext, -0.5, -0.5 );
 }
 
-void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath *p , int fillStyle )
+void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath *path , int fillStyle )
 {
-    const wxMacCoreGraphicsPath* path = dynamic_cast< const wxMacCoreGraphicsPath*>( p );
+       EnsureIsValid();
+       
     CGPathDrawingMode mode = m_mode;
 
     if ( fillStyle == wxODDEVEN_RULE )
@@ -431,18 +491,18 @@ void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath *p , int fillStyle
     if ( offset )
         CGContextTranslateCTM( m_cgContext, 0.5, 0.5 );
 
-    CGContextAddPath( m_cgContext , path->GetPath() );
+    CGContextAddPath( m_cgContext , (CGPathRef) path->GetNativePath() );
     CGContextDrawPath( m_cgContext , mode );
 
     if ( offset )
         CGContextTranslateCTM( m_cgContext, -0.5, -0.5 );
 }
 
-void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath *p , int fillStyle )
+void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath *path , int fillStyle )
 {
-    const wxMacCoreGraphicsPath* path = dynamic_cast< const wxMacCoreGraphicsPath*>( p );
-
-    CGContextAddPath( m_cgContext , path->GetPath() );
+       EnsureIsValid();
+       
+    CGContextAddPath( m_cgContext , (CGPathRef) path->GetNativePath() );
     if ( fillStyle == wxODDEVEN_RULE )
         CGContextEOFillPath( m_cgContext );
     else
@@ -466,21 +526,29 @@ void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg )
 
 void wxMacCoreGraphicsContext::Translate( wxDouble dx , wxDouble dy ) 
 {
+       EnsureIsValid();
+       
     CGContextTranslateCTM( m_cgContext, dx, dy );
 }
 
 void wxMacCoreGraphicsContext::Scale( wxDouble xScale , wxDouble yScale )
 {
+       EnsureIsValid();
+       
     CGContextScaleCTM( m_cgContext , xScale , yScale );
 }
 
 void wxMacCoreGraphicsContext::Rotate( wxDouble angle )
 {
+       EnsureIsValid();
+       
     CGContextRotateCTM( m_cgContext , angle );
 }
 
 void wxMacCoreGraphicsContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h ) 
 {
+       EnsureIsValid();
+       
     CGImageRef image = (CGImageRef)( bmp.CGImageCreate() );
     HIRect r = CGRectMake( x , y , w , h );
     HIViewDrawCGImage( m_cgContext , &r , image );
@@ -489,6 +557,8 @@ void wxMacCoreGraphicsContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDo
 
 void wxMacCoreGraphicsContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h ) 
 {
+       EnsureIsValid();
+       
     CGRect r = CGRectMake( 00 , 00 , w , h );
     CGContextSaveGState( m_cgContext );
     CGContextTranslateCTM( m_cgContext, x , y + h );
@@ -500,11 +570,15 @@ void wxMacCoreGraphicsContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDoubl
 
 void wxMacCoreGraphicsContext::PushState()
 {
+       EnsureIsValid();
+       
     CGContextSaveGState( m_cgContext );
 }
 
 void wxMacCoreGraphicsContext::PopState() 
 {
+       EnsureIsValid();
+       
     CGContextRestoreGState( m_cgContext );
 }
 
@@ -978,6 +1052,8 @@ void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDoub
 
 void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle ) 
 {
+       EnsureIsValid();
+       
     OSStatus status = noErr;
     ATSUTextLayout atsuLayout;
     UniCharCount chars = str.length();
@@ -1275,16 +1351,7 @@ wxGraphicsContext* wxGraphicsContext::Create( const wxWindowDC &dc )
 
 wxGraphicsContext* wxGraphicsContext::Create( wxWindow * window )
 {
-       wxGraphicsContext* ctx = new wxMacCoreGraphicsContext( (WindowRef) window->MacGetTopLevelWindowRef() );
-       CGContextRef cg = (CGContextRef) ctx->GetNativeContext() ;
-       CGContextRestoreGState( cg );
-       int x , y;
-    x = y = 0;
-    window->MacWindowToRootWindow( &x , &y );
-       CGContextTranslateCTM( cg, x, y );
-       CGContextSaveGState( cg );
-       return ctx;
-
+       return new wxMacCoreGraphicsContext( window );
 }
 
 wxGraphicsContext* wxGraphicsContext::CreateFromNative( void * context )
@@ -1292,4 +1359,9 @@ wxGraphicsContext* wxGraphicsContext::CreateFromNative( void * context )
     return new wxMacCoreGraphicsContext((CGContextRef)context);
 }
 
+wxGraphicsContext* wxGraphicsContext::CreateFromNativeWindow( void * window )
+{
+    return new wxMacCoreGraphicsContext((WindowRef)window);
+}
+
 #endif // wxMAC_USE_CORE_GRAPHICS