]> git.saurik.com Git - wxWidgets.git/blobdiff - src/osx/carbon/graphics.cpp
Ensure there is valid context for DrawRectangle
[wxWidgets.git] / src / osx / carbon / graphics.cpp
index 3a5306d1bb23de6cb550df9d5cba1c8a06705703..c42ffba7f76ec97ca77bdd9294b55fafbe8baddd 100644 (file)
@@ -113,11 +113,9 @@ extern "C"
 // 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;
 
@@ -149,26 +147,13 @@ OSStatus wxMacDrawCGImage(
 
 CGColorRef wxMacCreateCGColor( const wxColour& col )
 {
-    CGColorRef retval = 0;
-#ifdef __WXMAC__
-    retval = col.CreateCGColor();
-#else
-// TODO add conversion NSColor - CGColorRef (obj-c)
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
-    if ( CGColorCreateGenericRGB )
-        retval = CGColorCreateGenericRGB( col.Red() / 255.0 , col.Green() / 255.0, col.Blue() / 255.0, col.Alpha() / 255.0 );
-    else
-#endif
-    {
-        CGFloat components[4] = { col.Red() / 255.0, col.Green() / 255.0, col.Blue()  / 255.0, col.Alpha() / 255.0 } ;
-        retval = CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ;
-    }
+    CGColorRef retval = col.CreateCGColor();
 
-#endif
+    wxASSERT(retval != NULL);
     return retval;
 }
 
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && wxOSX_USE_CORE_TEXT
+#if wxOSX_USE_CORE_TEXT
 
 CTFontRef wxMacCreateCTFont( const wxFont& font )
 {
@@ -970,13 +955,14 @@ wxMacCoreGraphicsFontData::~wxMacCoreGraphicsFontData()
 #endif
 }
 
-class wxMacCoreGraphicsBitmapData : public wxGraphicsObjectRefData
+class wxMacCoreGraphicsBitmapData : public wxGraphicsBitmapData
 {
 public:
     wxMacCoreGraphicsBitmapData( wxGraphicsRenderer* renderer, CGImageRef bitmap, bool monochrome );
     ~wxMacCoreGraphicsBitmapData();
 
     virtual CGImageRef GetBitmap() { return m_bitmap; }
+    virtual void* GetNativeBitmap() const { return m_bitmap; }
     bool IsMonochrome() { return m_monochrome; }
 
 #if wxUSE_IMAGE
@@ -991,7 +977,7 @@ private :
     bool m_monochrome;
 };
 
-wxMacCoreGraphicsBitmapData::wxMacCoreGraphicsBitmapData( wxGraphicsRenderer* renderer, CGImageRef bitmap, bool monochrome ) : wxGraphicsObjectRefData( renderer ),
+wxMacCoreGraphicsBitmapData::wxMacCoreGraphicsBitmapData( wxGraphicsRenderer* renderer, CGImageRef bitmap, bool monochrome ) : wxGraphicsBitmapData( renderer ),
     m_bitmap(bitmap), m_monochrome(monochrome)
 {
 }
@@ -1500,7 +1486,7 @@ public:
     // fast convenience methods
     
     
-    virtual void DrawRectangleX( wxDouble x, wxDouble y, wxDouble w, wxDouble h ); 
+    virtual void DrawRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h ); 
 
     void SetNativeContext( CGContextRef cg );
 
@@ -1508,6 +1494,7 @@ public:
 
 private:
     bool EnsureIsValid();
+    void CheckInvariants() const;
 
     virtual void DoDrawText( const wxString &str, wxDouble x, wxDouble y );
     virtual void DoDrawRotatedText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle );
@@ -1653,6 +1640,13 @@ wxMacCoreGraphicsContext::~wxMacCoreGraphicsContext()
 }
 
 
+void wxMacCoreGraphicsContext::CheckInvariants() const
+{
+    // check invariants here for debugging ...
+}
+
+
+
 void wxMacCoreGraphicsContext::StartPage( wxDouble width, wxDouble height )
 {
     CGRect r;
@@ -1678,6 +1672,8 @@ void wxMacCoreGraphicsContext::Flush()
 
 bool wxMacCoreGraphicsContext::EnsureIsValid()
 {
+    CheckInvariants();
+    
     if ( !m_cgContext )
     {
         if (m_invisible)
@@ -1751,6 +1747,8 @@ bool wxMacCoreGraphicsContext::EnsureIsValid()
 #endif
         }
     }
+    CheckInvariants();
+
     return m_cgContext != NULL;
 }
 
@@ -1777,6 +1775,7 @@ bool wxMacCoreGraphicsContext::SetAntialiasMode(wxAntialiasMode antialias)
             return false;
     }
     CGContextSetShouldAntialias(m_cgContext, antialiasMode);
+    CheckInvariants();
     return true;
 }
 
@@ -1816,6 +1815,7 @@ bool wxMacCoreGraphicsContext::SetInterpolationQuality(wxInterpolationQuality in
             return false;
     }
     CGContextSetInterpolationQuality(m_cgContext, quality);
+    CheckInvariants();
     return true;
 }
 
@@ -1832,8 +1832,8 @@ bool wxMacCoreGraphicsContext::SetCompositionMode(wxCompositionMode op)
     if (m_composition == wxCOMPOSITION_DEST)
         return true;
 
-#if wxOSX_USE_COCOA_OR_CARBON
-    if ( UMAGetSystemVersion() < 0x1060 )
+    // TODO REMOVE if we don't need it because of bugs in 10.5
+#if 0
     {
         CGCompositeOperation cop = kCGCompositeOperationSourceOver;
         CGBlendMode mode = kCGBlendModeNormal;
@@ -1872,11 +1872,9 @@ bool wxMacCoreGraphicsContext::SetCompositionMode(wxCompositionMode op)
         case wxCOMPOSITION_XOR:
             cop = kCGCompositeOperationXOR;
             break;
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
         case wxCOMPOSITION_ADD:
             mode = kCGBlendModePlusLighter ;
             break;
-#endif
         default:
             return false;
         }
@@ -1886,8 +1884,6 @@ bool wxMacCoreGraphicsContext::SetCompositionMode(wxCompositionMode op)
             CGContextSetBlendMode(m_cgContext, mode);
     }
 #endif
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
-    else
     {
         CGBlendMode mode = kCGBlendModeNormal;
         switch( op )
@@ -1923,7 +1919,7 @@ bool wxMacCoreGraphicsContext::SetCompositionMode(wxCompositionMode op)
            mode = kCGBlendModeDestinationAtop;
             break;
         case wxCOMPOSITION_XOR:
-            mode = kCGBlendModeXOR;
+            mode = kCGBlendModeExclusion; // Not kCGBlendModeXOR!
             break;
 
         case wxCOMPOSITION_ADD:
@@ -1934,25 +1930,31 @@ bool wxMacCoreGraphicsContext::SetCompositionMode(wxCompositionMode op)
         }
         CGContextSetBlendMode(m_cgContext, mode);
     }
-#endif
+
+    CheckInvariants();
     return true;
 }
 
 void wxMacCoreGraphicsContext::BeginLayer(wxDouble opacity)
 {
+    CheckInvariants();
     CGContextSaveGState(m_cgContext);
     CGContextSetAlpha(m_cgContext, (CGFloat) opacity);
     CGContextBeginTransparencyLayer(m_cgContext, 0);
+    CheckInvariants();
 }
 
 void wxMacCoreGraphicsContext::EndLayer()
 {
+    CheckInvariants();
     CGContextEndTransparencyLayer(m_cgContext);
     CGContextRestoreGState(m_cgContext);
+    CheckInvariants();
 }
 
 void wxMacCoreGraphicsContext::Clip( const wxRegion &region )
 {
+    CheckInvariants();
 #if wxOSX_USE_COCOA_OR_CARBON
     if( m_cgContext )
     {
@@ -1983,11 +1985,13 @@ void wxMacCoreGraphicsContext::Clip( const wxRegion &region )
     // allow usage as measuring context
     // wxASSERT_MSG( m_cgContext != NULL, "Needs a valid context for clipping" );
 #endif
+    CheckInvariants();    
 }
 
 // clips drawings to the rect
 void wxMacCoreGraphicsContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
 {
+    CheckInvariants();
     CGRect r = CGRectMake( (CGFloat) x , (CGFloat) y , (CGFloat) w , (CGFloat) h );
     if ( m_cgContext )
     {
@@ -2006,6 +2010,7 @@ void wxMacCoreGraphicsContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDoubl
     // wxFAIL_MSG( "Needs a valid context for clipping" );
 #endif
     }
+    CheckInvariants();    
 }
 
     // resets the clipping to original extent
@@ -2032,6 +2037,7 @@ void wxMacCoreGraphicsContext::ResetClip()
     // wxFAIL_MSG( "Needs a valid context for clipping" );
 #endif
     }
+    CheckInvariants();    
 }
 
 void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath &path )
@@ -2050,6 +2056,8 @@ void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath &path )
     ((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->Apply(this);
     CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
     CGContextStrokePath( m_cgContext );
+    
+    CheckInvariants();
 }
 
 void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , wxPolygonFillMode fillStyle )
@@ -2103,6 +2111,8 @@ void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , wxPolygonF
 
     CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
     CGContextDrawPath( m_cgContext , mode );
+    
+    CheckInvariants();
 }
 
 void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath &path , wxPolygonFillMode fillStyle )
@@ -2133,6 +2143,8 @@ void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath &path , wxPolygonF
         else
             CGContextFillPath( m_cgContext );
     }
+    
+    CheckInvariants();
 }
 
 void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg )
@@ -2142,6 +2154,7 @@ void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg )
 
     if ( m_cgContext )
     {
+        CheckInvariants();
         CGContextRestoreGState( m_cgContext );
         CGContextRestoreGState( m_cgContext );
         if ( m_contextSynthesized )
@@ -2215,7 +2228,7 @@ void wxMacCoreGraphicsContext::DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble
         return;
 
 #ifdef __WXMAC__
-    wxMacCoreGraphicsBitmapData* refdata  =static_cast<wxMacCoreGraphicsBitmapData*>(bmp.GetRefData());
+    wxMacCoreGraphicsBitmapData* refdata static_cast<wxMacCoreGraphicsBitmapData*>(bmp.GetRefData());
     CGImageRef image = refdata->GetBitmap();
     CGRect r = CGRectMake( (CGFloat) x , (CGFloat) y , (CGFloat) w , (CGFloat) h );
     if ( refdata->IsMonochrome() == 1 )
@@ -2246,6 +2259,8 @@ void wxMacCoreGraphicsContext::DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble
         wxMacDrawCGImage( m_cgContext , &r , image );
     }
 #endif
+    
+    CheckInvariants();
 }
 
 void wxMacCoreGraphicsContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
@@ -2256,15 +2271,17 @@ void wxMacCoreGraphicsContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDoubl
     if (m_composition == wxCOMPOSITION_DEST)
         return;
 
-    CGRect r = CGRectMake( (CGFloat) 0.0 , (CGFloat) 0.0 , (CGFloat) w , (CGFloat) h );
     CGContextSaveGState( m_cgContext );
     CGContextTranslateCTM( m_cgContext,(CGFloat) x ,(CGFloat) (y + h) );
     CGContextScaleCTM( m_cgContext, 1, -1 );
 #if wxOSX_USE_COCOA_OR_CARBON
+    CGRect r = CGRectMake( (CGFloat) 0.0 , (CGFloat) 0.0 , (CGFloat) w , (CGFloat) h );
     PlotIconRefInContext( m_cgContext , &r , kAlignNone , kTransformNone ,
         NULL , kPlotIconRefNormalFlags , icon.GetHICON() );
 #endif
     CGContextRestoreGState( m_cgContext );
+    
+    CheckInvariants();
 }
 
 void wxMacCoreGraphicsContext::PushState()
@@ -2294,7 +2311,6 @@ void wxMacCoreGraphicsContext::DoDrawText( const wxString &str, wxDouble x, wxDo
         return;
 
 #if wxOSX_USE_CORE_TEXT
-    if ( UMAGetSystemVersion() >= 0x1050 )
     {
         wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
         wxCFStringRef text(str, wxLocale::GetSystemEncoding() );
@@ -2318,9 +2334,12 @@ void wxMacCoreGraphicsContext::DoDrawText( const wxString &str, wxDouble x, wxDo
         y += CTFontGetAscent(font);
 
         CGContextSaveGState(m_cgContext);
+        CGAffineTransform textMatrix = CGContextGetTextMatrix(m_cgContext);
+        
         CGContextTranslateCTM(m_cgContext, (CGFloat) x, (CGFloat) y);
         CGContextScaleCTM(m_cgContext, 1, -1);
-        CGContextSetTextPosition(m_cgContext, 0, 0);
+        CGContextSetTextMatrix(m_cgContext, CGAffineTransformIdentity);
+        
         CTLineDraw( line, m_cgContext );
         
         if ( fref->GetUnderlined() ) {
@@ -2336,7 +2355,9 @@ void wxMacCoreGraphicsContext::DoDrawText( const wxString &str, wxDouble x, wxDo
         }
         
         CGContextRestoreGState(m_cgContext);
-        CFRelease( col );
+        CGContextSetTextMatrix(m_cgContext, textMatrix);
+        CGColorRelease( col );
+        CheckInvariants();
         return;
     }
 #endif
@@ -2361,6 +2382,8 @@ void wxMacCoreGraphicsContext::DoDrawText( const wxString &str, wxDouble x, wxDo
     CGContextRestoreGState(m_cgContext);
     CFRelease( col );
 #endif
+    
+    CheckInvariants();
 }
 
 void wxMacCoreGraphicsContext::DoDrawRotatedText(const wxString &str,
@@ -2376,7 +2399,6 @@ void wxMacCoreGraphicsContext::DoDrawRotatedText(const wxString &str,
         return;
 
 #if wxOSX_USE_CORE_TEXT
-    if ( UMAGetSystemVersion() >= 0x1050 )
     {
         // default implementation takes care of rotation and calls non rotated DrawText afterwards
         wxGraphicsContext::DoDrawRotatedText( str, x, y, angle );
@@ -2463,6 +2485,7 @@ void wxMacCoreGraphicsContext::DoDrawRotatedText(const wxString &str,
         CGContextRestoreGState(m_cgContext);
 
         ::ATSUDisposeTextLayout(atsuLayout);
+        CheckInvariants();
 
         return;
     }
@@ -2471,6 +2494,8 @@ void wxMacCoreGraphicsContext::DoDrawRotatedText(const wxString &str,
     // default implementation takes care of rotation and calls non rotated DrawText afterwards
     wxGraphicsContext::DoDrawRotatedText( str, x, y, angle );
 #endif
+    
+    CheckInvariants();
 }
 
 void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
@@ -2491,7 +2516,6 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid
         return;
 
 #if wxOSX_USE_CORE_TEXT
-    if ( UMAGetSystemVersion() >= 0x1050 )
     {
         wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
         CTFontRef font = fref->OSXGetCTFont();
@@ -2572,6 +2596,8 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid
     if ( width )
         *width = sz.width;
 #endif
+    
+    CheckInvariants();    
 }
 
 void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const
@@ -2670,6 +2696,8 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr
 #if wxOSX_USE_IPHONE
     // TODO core graphics text implementation here
 #endif
+    
+    CheckInvariants();
 }
 
 void * wxMacCoreGraphicsContext::GetNativeContext()
@@ -2678,11 +2706,21 @@ void * wxMacCoreGraphicsContext::GetNativeContext()
 }
 
 
-void wxMacCoreGraphicsContext::DrawRectangleX( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
+void wxMacCoreGraphicsContext::DrawRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
 {
+    if (!EnsureIsValid())
+        return;
+
     if (m_composition == wxCOMPOSITION_DEST) 
         return; 
 
+    // when using shading, we have to go back to drawing paths 
+    if ( !m_brush.IsNull() && ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
+    {
+        wxGraphicsContext::DrawRectangle( x,y,w,h );
+        return;
+    }
+
     CGRect rect = CGRectMake( (CGFloat) x , (CGFloat) y , (CGFloat) w , (CGFloat) h );
     if ( !m_brush.IsNull() )
     {
@@ -2710,6 +2748,7 @@ void wxMacCoreGraphicsContext::ConcatTransform( const wxGraphicsMatrix& matrix )
 // sets the transform of this context
 void wxMacCoreGraphicsContext::SetTransform( const wxGraphicsMatrix& matrix )
 {
+    CheckInvariants();
     if ( m_cgContext )
     {
         CGAffineTransform transform = CGContextGetCTM( m_cgContext );
@@ -2721,6 +2760,7 @@ void wxMacCoreGraphicsContext::SetTransform( const wxGraphicsMatrix& matrix )
     {
         m_windowTransform = *(CGAffineTransform*) matrix.GetNativeMatrix();
     }
+    CheckInvariants();
 }
 
 // gets the matrix of this context