]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/graphics.cpp
Test to avoid crashes in some circumstances
[wxWidgets.git] / src / mac / carbon / graphics.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 5d3ec9a..b2bcb07
@@ -17,6 +17,7 @@
 
 #ifndef WX_PRECOMP
     #include "wx/dcclient.h"
+    #include "wx/dcmemory.h"
     #include "wx/log.h"
     #include "wx/region.h"
 #endif
 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
 typedef float CGFloat;
 #endif
+#ifndef wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+    #define wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 1
+#else
+    #define wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 0
+#endif
+#endif
 
 //-----------------------------------------------------------------------------
 // constants
@@ -161,7 +169,7 @@ public :
     void StrokeLineSegments( CGContextRef ctxRef , const CGPoint pts[] , size_t count )
     {
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
-        if ( UMAGetSystemVersion() >= 0x1040 )
+        if ( CGContextStrokeLineSegments!=NULL  )
         {
             CGContextStrokeLineSegments( ctxRef , pts , count );
         }
@@ -457,7 +465,12 @@ void wxMacCoreGraphicsPenData::Apply( wxGraphicsContext* context )
     }
     else
     {
-        CGContextSetStrokeColorWithColor( cg , m_color );
+        if ( context->GetLogicalFunction() == wxINVERT || context->GetLogicalFunction() == wxXOR )
+        {
+            CGContextSetRGBStrokeColor( cg , 1.0, 1.0 , 1.0, 1.0 );
+        }
+        else
+            CGContextSetStrokeColorWithColor( cg , m_color );
     }
 }
 
@@ -525,9 +538,32 @@ wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData(wxGraphicsRenderer* rende
 
     if ( brush.GetStyle() == wxSOLID )
     {
-        float components[4] = { brush.GetColour().Red() / 255.0 , brush.GetColour().Green() / 255.0 ,
+        if ( brush.MacGetBrushKind() == kwxMacBrushTheme )
+        {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+            if ( HIThemeBrushCreateCGColor != 0 )
+            {
+                CGColorRef color ;
+                HIThemeBrushCreateCGColor( brush.MacGetTheme(), &color );
+                m_color.Set( color ) ;
+            }
+            else
+#endif
+            {
+                // as close as we can get, unfortunately < 10.4 things get difficult
+                RGBColor color;
+                GetThemeBrushAsColor( brush.MacGetTheme(), 32, true, &color );
+                float components[4] = {  (CGFloat) color.red / 65536,
+                    (CGFloat) color.green / 65536, (CGFloat) color.blue / 65536, 1 } ;
+                m_color.Set( CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ) ;
+            }
+        }
+        else
+        {
+            float components[4] = { brush.GetColour().Red() / 255.0 , brush.GetColour().Green() / 255.0 ,
                 brush.GetColour().Blue() / 255.0 , brush.GetColour().Alpha() / 255.0 } ;
-        m_color.Set( CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ) ;
+            m_color.Set( CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ) ;
+        }
     }
     else if ( brush.IsHatch() )
     {
@@ -719,6 +755,10 @@ public :
     virtual void Set(wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
         wxDouble tx=0.0, wxDouble ty=0.0);
 
+    // gets the component valuess of the matrix
+    virtual void Get(wxDouble* a=NULL, wxDouble* b=NULL,  wxDouble* c=NULL,
+                     wxDouble* d=NULL, wxDouble* tx=NULL, wxDouble* ty=NULL) const;
+       
     // makes this the inverse matrix
     virtual void Invert();
 
@@ -790,6 +830,18 @@ void wxMacCoreGraphicsMatrixData::Set(wxDouble a, wxDouble b, wxDouble c, wxDoub
     m_matrix = CGAffineTransformMake(a,b,c,d,tx,ty);
 }
 
+// gets the component valuess of the matrix
+void wxMacCoreGraphicsMatrixData::Get(wxDouble* a, wxDouble* b,  wxDouble* c,
+                                      wxDouble* d, wxDouble* tx, wxDouble* ty) const
+{
+    if (a)  *a = m_matrix.a;
+    if (b)  *b = m_matrix.b;
+    if (c)  *c = m_matrix.c;
+    if (d)  *d = m_matrix.d;
+    if (tx) *tx= m_matrix.tx;
+    if (ty) *ty= m_matrix.ty;
+}
+
 // makes this the inverse matrix
 void wxMacCoreGraphicsMatrixData::Invert()
 {
@@ -1110,6 +1162,7 @@ public:
 
     virtual void * GetNativeContext();
 
+    bool SetLogicalFunction( int function );
     //
     // transformation
     //
@@ -1145,7 +1198,7 @@ public:
     virtual void DrawPath( const wxGraphicsPath &path, int fillStyle = wxODDEVEN_RULE );
 
     virtual bool ShouldOffset() const
-    {
+    {     
         int penwidth = 0 ;
         if ( !m_pen.IsNull() )
         {
@@ -1275,13 +1328,55 @@ void wxMacCoreGraphicsContext::EnsureIsValid()
                m_releaseContext = true;
                if ( !HIShapeIsEmpty(m_clipRgn) )
                {
-                       HIShapeReplacePathInCGContext( m_clipRgn, m_cgContext );
+            // 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 );
        }
 }
 
+bool wxMacCoreGraphicsContext::SetLogicalFunction( int function )
+{
+    if (m_logicalFunction == function)
+        return true;
+
+    EnsureIsValid();
+    
+    bool retval = false;
+
+    if ( function == wxCOPY )
+    {
+        retval = true;
+#if wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
+        if ( CGContextSetBlendMode != NULL )
+        {
+            CGContextSetBlendMode( m_cgContext, kCGBlendModeNormal );
+            CGContextSetShouldAntialias( m_cgContext, true );
+        }
+#endif
+    }
+    else if ( function == wxINVERT || function == wxXOR )
+    {
+#if wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
+        if ( CGContextSetBlendMode != NULL )
+        {
+            // change color to white
+            CGContextSetBlendMode( m_cgContext, kCGBlendModeExclusion );
+            CGContextSetShouldAntialias( m_cgContext, false );
+            retval = true;
+        }
+#endif
+    }
+    
+    if (retval)
+        m_logicalFunction = function;
+    return retval ;
+}
 
 void wxMacCoreGraphicsContext::Clip( const wxRegion &region )
 {
@@ -1294,7 +1389,15 @@ void wxMacCoreGraphicsContext::Clip( const wxRegion &region )
     }
     else
     {
-        m_clipRgn.Set(HIShapeCreateWithQDRgn( (RgnHandle) region.GetWXHRGN() ));
+        // 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
+        wxMacCFRefHolder<HIShapeRef> hishape ;
+        hishape.Set( HIShapeCreateWithQDRgn( (RgnHandle) region.GetWXHRGN() ));
+        HIMutableShapeRef mutableShape = HIShapeCreateMutableCopy( hishape );
+        
+        CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero, m_windowTransform );
+        HIShapeOffset( mutableShape, transformedOrigin.x, transformedOrigin.y );
+        m_clipRgn.Set(mutableShape);
     }
 }
 
@@ -1308,6 +1411,9 @@ void wxMacCoreGraphicsContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDoubl
     }
     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));
     }
 }
@@ -1731,6 +1837,9 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid
         *width = FixedToInt(textAfter - textBefore);
 
     ::ATSUDisposeTextLayout(atsuLayout);
+#if SIZEOF_WCHAR_T == 4
+    free( ubuf ) ;
+#endif
 }
 
 void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const
@@ -1789,6 +1898,9 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr
     }
 
     ::ATSUDisposeTextLayout(atsuLayout);
+#if SIZEOF_WCHAR_T == 4
+    free( ubuf ) ;
+#endif
 }
 
 void * wxMacCoreGraphicsContext::GetNativeContext()
@@ -1902,7 +2014,16 @@ wxGraphicsRenderer* wxGraphicsRenderer::GetDefaultRenderer()
 
 wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxWindowDC& dc)
 {
-   return new wxMacCoreGraphicsContext(this,(CGContextRef)dc.GetWindow()->MacGetCGContextRef() );
+    wxMemoryDC* mdc = wxDynamicCast(&dc, wxMemoryDC);
+    if ( mdc )
+    {
+        return new wxMacCoreGraphicsContext(this, 
+            (CGContextRef)mdc->GetGraphicsContext()->GetNativeContext());
+    }
+    else
+    {
+        return new wxMacCoreGraphicsContext(this,(CGContextRef)dc.GetWindow()->MacGetCGContextRef() );
+    }
 }
 
 wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeContext( void * context )