]> git.saurik.com Git - wxWidgets.git/blobdiff - src/osx/carbon/graphics.cpp
move wxGridCellRenderer::Draw before other derived classes implementations (no real...
[wxWidgets.git] / src / osx / carbon / graphics.cpp
index 3c65a99a8cfc452f6a71a488f536b53b3eea928d..98ce41f0d8d54a139acb225bb1298f63a9bda85f 100644 (file)
@@ -1,11 +1,11 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        src/mac/carbon/dccg.cpp
+// Name:        src/osx/carbon/dccg.cpp
 // Purpose:     wxDC class
 // Author:      Stefan Csomor
 // Modified by:
 // Created:     01/02/97
 // RCS-ID:      $Id$
-// Copyright:   (c) Stefan Csomor
+// copyright:   (c) Stefan Csomor
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 #endif
 
 #ifdef __WXMAC__
-    #include "wx/mac/uma.h"
-    #include "wx/mac/dcprint.h"
+    #include "wx/osx/private.h"
+    #include "wx/osx/dcprint.h"
+    #include "wx/osx/dcclient.h"
+    #include "wx/osx/dcmemory.h"
+    #include "wx/osx/private.h"
 #else
     #include "CoreServices/CoreServices.h"
     #include "ApplicationServices/ApplicationServices.h"
-    #include "wx/mac/corefoundation/cfstring.h"
+    #include "wx/osx/core/cfstring.h"
     #include "wx/cocoa/dcclient.h"
 #endif
 
@@ -64,7 +67,43 @@ int UMAGetSystemVersion()
 }
 
 
-#define wxMAC_USE_CORE_TEXT 1
+#define wxOSX_USE_CORE_TEXT 1
+
+#endif
+
+#if wxOSX_USE_COCOA_OR_IPHONE
+extern CGContextRef wxOSXGetContextFromCurrentNSContext() ;
+extern bool wxOSXLockFocus( WXWidget view) ;
+extern void wxOSXUnlockFocus( WXWidget view) ;
+#endif
+
+#if 1 // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
+
+// TODO test whether this private API also works under 10.3
+
+// copying values from NSCompositingModes (see also webkit and cairo sources)
+
+typedef enum CGCompositeOperation {
+   kCGCompositeOperationClear           = 0,
+   kCGCompositeOperationCopy            = 1,
+   kCGCompositeOperationSourceOver      = 2,
+   kCGCompositeOperationSourceIn        = 3,
+   kCGCompositeOperationSourceOut       = 4,
+   kCGCompositeOperationSourceAtop      = 5,
+   kCGCompositeOperationDestinationOver = 6,
+   kCGCompositeOperationDestinationIn   = 7,
+   kCGCompositeOperationDestinationOut  = 8,
+   kCGCompositeOperationDestinationAtop = 9,
+   kCGCompositeOperationXOR             = 10,
+   kCGCompositeOperationPlusDarker      = 11,
+// NS only, unsupported by CG : Highlight 
+   kCGCompositeOperationPlusLighter     = 12
+} CGCompositeOperation ;
+
+extern "C"
+{
+   CG_EXTERN void CGContextSetCompositeOperation (CGContextRef context, int operation);
+} ;
 
 #endif
 
@@ -92,12 +131,17 @@ OSStatus wxMacDrawCGImage(
                   const CGRect *  inBounds,
                   CGImageRef      inImage)
 {
-#if defined( __LP64__ ) || defined(__WXCOCOA__)
-    // todo flip
-    CGContextDrawImage(inContext, *inBounds, inImage );
-    return noErr;
-#else
+#if wxOSX_USE_CARBON
     return HIViewDrawCGImage( inContext, inBounds, inImage );
+#else
+    CGContextSaveGState(inContext);
+    CGContextTranslateCTM(inContext, inBounds->origin.x, inBounds->origin.y + inBounds->size.height);
+    CGRect r = *inBounds;
+    r.origin.x = r.origin.y = 0;
+    CGContextScaleCTM(inContext, 1, -1);
+    CGContextDrawImage(inContext, r, inImage );
+    CGContextRestoreGState(inContext);
+    return noErr;
 #endif
 }
 
@@ -122,7 +166,7 @@ CGColorRef wxMacCreateCGColor( const wxColour& col )
     return retval;
 }
 
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && defined(wxMAC_USE_CORE_TEXT)
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && wxOSX_USE_CORE_TEXT
 
 CTFontRef wxMacCreateCTFont( const wxFont& font )
 {
@@ -519,12 +563,7 @@ void wxMacCoreGraphicsPenData::Apply( wxGraphicsContext* context )
     }
     else
     {
-        if ( context->GetLogicalFunction() == wxINVERT || context->GetLogicalFunction() == wxXOR )
-        {
-            CGContextSetRGBStrokeColor( cg , (CGFloat) 1.0,(CGFloat)  1.0 , (CGFloat) 1.0, (CGFloat) 1.0 );
-        }
-        else
-            CGContextSetStrokeColorWithColor( cg , m_color );
+        CGContextSetStrokeColorWithColor( cg , m_color );
     }
 }
 
@@ -677,7 +716,7 @@ void wxMacCoreGraphicsBrushData::CreateRadialGradientBrush( wxDouble xo, wxDoubl
     const wxColour &oColor, const wxColour &cColor )
 {
     m_gradientFunction = CreateGradientFunction( oColor, cColor );
-    m_shading = CGShadingCreateRadial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat) xo,(CGFloat) yo), 0, 
+    m_shading = CGShadingCreateRadial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat) xo,(CGFloat) yo), 0,
                                         CGPointMake((CGFloat) xc,(CGFloat) yc), (CGFloat) radius, m_gradientFunction, true, true ) ;
     m_isShading = true ;
 }
@@ -758,30 +797,44 @@ CGFunctionRef wxMacCoreGraphicsBrushData::CreateGradientFunction( const wxColour
 // Font
 //
 
+#if wxOSX_USE_IPHONE
+
+extern UIFont* CreateUIFont( const wxFont& font );
+extern void DrawTextInContext( CGContextRef context, CGPoint where, UIFont *font, NSString* text );
+extern CGSize MeasureTextInContext( UIFont *font, NSString* text );
+
+#endif
+
 class wxMacCoreGraphicsFontData : public wxGraphicsObjectRefData
 {
 public:
     wxMacCoreGraphicsFontData( wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col );
     ~wxMacCoreGraphicsFontData();
 
-#if wxMAC_USE_ATSU_TEXT
+#if wxOSX_USE_ATSU_TEXT
     virtual ATSUStyle GetATSUStyle() { return m_macATSUIStyle; }
 #endif
-#if wxMAC_USE_CORE_TEXT
+#if wxOSX_USE_CORE_TEXT
     CTFontRef GetCTFont() const { return m_ctFont ; }
 #endif
     wxColour GetColour() const { return m_colour ; }
 
     bool GetUnderlined() const { return m_underlined ; }
+#if wxOSX_USE_IPHONE
+    UIFont* GetUIFont() const { return m_uiFont; }
+#endif
 private :
     wxColour m_colour;
     bool m_underlined;
-#if wxMAC_USE_ATSU_TEXT
+#if wxOSX_USE_ATSU_TEXT
     ATSUStyle m_macATSUIStyle;
 #endif
-#if wxMAC_USE_CORE_TEXT
+#if wxOSX_USE_CORE_TEXT
     wxCFRef< CTFontRef > m_ctFont;
 #endif
+#if wxOSX_USE_IPHONE
+    UIFont*  m_uiFont;
+#endif
 };
 
 wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col) : wxGraphicsObjectRefData( renderer )
@@ -789,10 +842,14 @@ wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* rendere
     m_colour = col;
     m_underlined = font.GetUnderlined();
 
-#if wxMAC_USE_CORE_TEXT
+#if wxOSX_USE_CORE_TEXT
     m_ctFont.reset( wxMacCreateCTFont( font ) );
 #endif
-#if wxMAC_USE_ATSU_TEXT
+#if wxOSX_USE_IPHONE
+    m_uiFont = CreateUIFont(font);
+    wxMacCocoaRetain( m_uiFont );
+#endif
+#if wxOSX_USE_ATSU_TEXT
     OSStatus status = noErr;
     m_macATSUIStyle = NULL;
 
@@ -827,22 +884,21 @@ wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* rendere
 
     wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") );
 #endif
-#if wxMAC_USE_CG_TEXT
-#endif
 }
 
 wxMacCoreGraphicsFontData::~wxMacCoreGraphicsFontData()
 {
-#if wxMAC_USE_CORE_TEXT
+#if wxOSX_USE_CORE_TEXT
 #endif
-#if wxMAC_USE_ATSU_TEXT
+#if wxOSX_USE_ATSU_TEXT
     if ( m_macATSUIStyle )
     {
         ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
         m_macATSUIStyle = NULL;
     }
 #endif
-#if wxMAC_USE_CG_TEXT
+#if wxOSX_USE_IPHONE
+    wxMacCocoaRelease( m_uiFont );
 #endif
 }
 
@@ -1115,7 +1171,7 @@ public :
     // gets the bounding box enclosing all points (possibly including control points)
     virtual void GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *y) const;
 
-    virtual bool Contains( wxDouble x, wxDouble y, int fillStyle = wxODDEVEN_RULE) const;
+    virtual bool Contains( wxDouble x, wxDouble y, wxPolygonFillMode fillStyle = wxODDEVEN_RULE) const;
 private :
     CGMutablePathRef m_path;
 };
@@ -1226,7 +1282,7 @@ void wxMacCoreGraphicsPathData::GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wx
     *h = bounds.size.height;
 }
 
-bool wxMacCoreGraphicsPathData::Contains( wxDouble x, wxDouble y, int fillStyle) const
+bool wxMacCoreGraphicsPathData::Contains( wxDouble x, wxDouble y, wxPolygonFillMode fillStyle) const
 {
     return CGPathContainsPoint( m_path, NULL, CGPointMake((CGFloat) x,(CGFloat) y), fillStyle == wxODDEVEN_RULE );
 }
@@ -1244,7 +1300,9 @@ class WXDLLEXPORT wxMacCoreGraphicsContext : public wxGraphicsContext
 public:
     wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext, wxDouble width = 0, wxDouble height = 0 );
 
+#if wxOSX_USE_CARBON
     wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, WindowRef window );
+#endif
 
     wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, wxWindow* window );
 
@@ -1282,7 +1340,14 @@ public:
 
     virtual void * GetNativeContext();
 
-    bool SetLogicalFunction( int function );
+    virtual bool SetAntialiasMode(wxAntialiasMode antialias);
+
+    virtual bool SetCompositionMode(wxCompositionMode op);
+
+    virtual void BeginLayer(wxDouble opacity);
+
+    virtual void EndLayer();
+    
     //
     // transformation
     //
@@ -1312,10 +1377,10 @@ public:
     virtual void StrokePath( const wxGraphicsPath &path );
 
     // fills a path with the current brush
-    virtual void FillPath( const wxGraphicsPath &path, int fillStyle = wxODDEVEN_RULE );
+    virtual void FillPath( const wxGraphicsPath &path, wxPolygonFillMode fillStyle = wxODDEVEN_RULE );
 
     // draws a path by first filling and then stroking
-    virtual void DrawPath( const wxGraphicsPath &path, int fillStyle = wxODDEVEN_RULE );
+    virtual void DrawPath( const wxGraphicsPath &path, wxPolygonFillMode fillStyle = wxODDEVEN_RULE );
 
     virtual bool ShouldOffset() const
     {
@@ -1332,10 +1397,6 @@ public:
     // text
     //
 
-    virtual void DrawText( const wxString &str, wxDouble x, wxDouble y );
-
-    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;
 
@@ -1353,20 +1414,29 @@ public:
 
     void SetNativeContext( CGContextRef cg );
 
-    DECLARE_NO_COPY_CLASS(wxMacCoreGraphicsContext)
-    DECLARE_DYNAMIC_CLASS(wxMacCoreGraphicsContext)
+    DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacCoreGraphicsContext)
 
 private:
-    void EnsureIsValid();
+    bool EnsureIsValid();
+
+    virtual void DoDrawText( const wxString &str, wxDouble x, wxDouble y );
+    virtual void DoDrawRotatedText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle );
 
     CGContextRef m_cgContext;
+#if wxOSX_USE_CARBON
     WindowRef m_windowRef;
-    bool m_releaseContext;
+#else
+    WXWidget m_view;
+#endif
+    bool m_contextSynthesized;
     CGAffineTransform m_windowTransform;
     wxDouble m_width;
     wxDouble m_height;
+    bool m_invisible;
 
+#if wxOSX_USE_COCOA_OR_CARBON
     wxCFRef<HIShapeRef> m_clipRgn;
+#endif
 };
 
 //-----------------------------------------------------------------------------
@@ -1410,10 +1480,16 @@ public :
 void wxMacCoreGraphicsContext::Init()
 {
     m_cgContext = NULL;
-    m_releaseContext = false;
-    m_windowRef = NULL;
+    m_contextSynthesized = false;
     m_width = 0;
     m_height = 0;
+#if wxOSX_USE_CARBON
+    m_windowRef = NULL;
+#endif
+#if wxOSX_USE_COCOA_OR_IPHONE
+    m_view = NULL;
+#endif
+    m_invisible = false;
 }
 
 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext, wxDouble width, wxDouble height ) : wxGraphicsContext(renderer)
@@ -1424,29 +1500,45 @@ wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer
     m_height = height;
 }
 
+#if wxOSX_USE_CARBON
 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, WindowRef window ): wxGraphicsContext(renderer)
 {
     Init();
     m_windowRef = window;
 }
+#endif
 
 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, wxWindow* window ): wxGraphicsContext(renderer)
 {
     Init();
 
+    wxSize sz = window->GetSize();
+    m_width = sz.x;
+    m_height = sz.y;
+
+#if wxOSX_USE_COCOA_OR_IPHONE
+    m_view = window->GetHandle();
+
+    if ( !((wxWidgetCocoaImpl*) window->GetPeer())->IsFlipped() )
+    {
+        m_windowTransform = CGAffineTransformMakeTranslation( 0 , m_height );
+        m_windowTransform = CGAffineTransformScale( m_windowTransform , 1 , -1 );
+    }
+    else
+    {
+        m_windowTransform = CGAffineTransformIdentity;
+    }
+#else
     int originX , originY;
     originX = originY = 0;
-
     Rect bounds = { 0,0,0,0 };
-#if defined( __LP64__ ) || defined(__WXCOCOA__)
-#else
     m_windowRef = (WindowRef) window->MacGetTopLevelWindowRef();
     window->MacWindowToRootWindow( &originX , &originY );
     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 ) ;
+#endif
 }
 
 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext(wxGraphicsRenderer* renderer) : wxGraphicsContext(renderer)
@@ -1495,109 +1587,238 @@ void wxMacCoreGraphicsContext::Flush()
     CGContextFlush(m_cgContext);
 }
 
-void wxMacCoreGraphicsContext::EnsureIsValid()
+bool wxMacCoreGraphicsContext::EnsureIsValid()
 {
     if ( !m_cgContext )
     {
-        OSStatus status =
-#if ! ( defined( __LP64__ ) || defined(__WXCOCOA__) )
-            QDBeginCGContext( GetWindowPort( m_windowRef ) , &m_cgContext );
-#else
-            paramErr;
+        if (m_invisible)
+            return false;
+            
+#if wxOSX_USE_COCOA_OR_IPHONE
+        if ( wxOSXLockFocus(m_view) )
+        {
+            m_cgContext = wxOSXGetContextFromCurrentNSContext();
+            wxASSERT_MSG( m_cgContext != NULL, _T("Unable to retrieve drawing context from View"));
+        }
+        else
+        {
+            m_invisible = true;
+        }
 #endif
+#if wxOSX_USE_CARBON
+        OSStatus status = QDBeginCGContext( GetWindowPort( m_windowRef ) , &m_cgContext );
         if ( status != noErr )
         {
             wxFAIL_MSG("Cannot nest wxDCs on the same window");
         }
-
-        CGContextConcatCTM( m_cgContext, m_windowTransform );
-        CGContextSaveGState( m_cgContext );
-        m_releaseContext = true;
-        if ( m_clipRgn.get() )
+#endif
+        if ( m_cgContext )
         {
-            // the clip region is in device coordinates, so we convert this again to user coordinates
-            wxCFRef<HIMutableShapeRef> hishape( HIShapeCreateMutableCopy( m_clipRgn ) );
-            CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero,m_windowTransform);
-            HIShapeOffset( hishape, -transformedOrigin.x, -transformedOrigin.y );
-            // if the shape is empty, HIShapeReplacePathInCGContext doesn't work
-            if ( HIShapeIsEmpty(hishape))
+            CGContextConcatCTM( m_cgContext, m_windowTransform );
+            CGContextSaveGState( m_cgContext );
+            m_contextSynthesized = true;
+            if ( m_clipRgn.get() )
             {
-                CGRect empty = CGRectMake( 0,0,0,0 );
-                CGContextClipToRect( m_cgContext, empty );
+                // the clip region is in device coordinates, so we convert this again to user coordinates
+                wxCFRef<HIMutableShapeRef> hishape( HIShapeCreateMutableCopy( m_clipRgn ) );
+                CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero,m_windowTransform);
+                HIShapeOffset( hishape, -transformedOrigin.x, -transformedOrigin.y );
+                // if the shape is empty, HIShapeReplacePathInCGContext doesn't work
+                if ( HIShapeIsEmpty(hishape))
+                {
+                    CGRect empty = CGRectMake( 0,0,0,0 );
+                    CGContextClipToRect( m_cgContext, empty );
+                }
+                else
+                {
+                    HIShapeReplacePathInCGContext( hishape, m_cgContext );
+                    CGContextClip( m_cgContext );
+                }
             }
-            else
+            CGContextSaveGState( m_cgContext );
+            
+#if 0 // turn on for debugging of clientdc
+            static float color = 0.5 ;
+            static int channel = 0 ;
+            CGRect bounds = CGRectMake(-1000,-1000,2000,2000);
+            CGContextSetRGBFillColor( m_cgContext, channel == 0 ? color : 0.5 ,
+                channel == 1 ? color : 0.5 , channel == 2 ? color : 0.5 , 1 );
+            CGContextFillRect( m_cgContext, bounds );
+            color += 0.1 ;
+            if ( color > 0.9 )
             {
-                HIShapeReplacePathInCGContext( hishape, m_cgContext );
-                CGContextClip( m_cgContext );
+                color = 0.5 ;
+                channel++ ;
+                if ( channel == 3 )
+                    channel = 0 ;
             }
+#endif
         }
-        CGContextSaveGState( m_cgContext );
     }
+    return m_cgContext != NULL;
 }
 
-// TODO test whether the private CGContextSetCompositeOperation works under 10.3 (using NSCompositingModes)
-
-bool wxMacCoreGraphicsContext::SetLogicalFunction( int function )
+bool wxMacCoreGraphicsContext::SetAntialiasMode(wxAntialiasMode antialias)
 {
-    if (m_logicalFunction == function)
+    if (EnsureIsValid()==false)
         return true;
 
-    EnsureIsValid();
+    if (m_antialias == antialias)
+        return true;
+    
+    m_antialias = antialias;
+    
+    bool antialiasMode;
+    switch (antialias)
+    {
+        case wxANTIALIAS_DEFAULT:
+            antialiasMode = true;
+            break;
+        case wxANTIALIAS_NONE:
+            antialiasMode = false;
+            break;
+        default:
+            return false;
+    }
+    CGContextSetShouldAntialias(m_cgContext, antialiasMode);
+    return true;
+}
 
-    bool retval = false;
-    bool shouldAntiAlias = true;
-    CGBlendMode mode = kCGBlendModeNormal;
+bool wxMacCoreGraphicsContext::SetCompositionMode(wxCompositionMode op)
+{
+    if (EnsureIsValid()==false)
+        return true;
 
-#if defined(__WXMAC__) && ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 )
-    if ( UMAGetSystemVersion() >= 0x1050 )
+    if ( m_composition == op )
+        return true;
+        
+    m_composition = op;
+    
+    if (m_composition == wxCOMPOSITION_DEST)
+        return true;
+        
+#if wxOSX_USE_COCOA_OR_CARBON
+    if ( UMAGetSystemVersion() < 0x1060 )
     {
-        retval = true;
-        switch ( function )
+        CGCompositeOperation cop = kCGCompositeOperationSourceOver;
+        CGBlendMode mode = kCGBlendModeNormal;
+        switch( op )
         {
-            // TODO find best corresponding porter duff modes
-            case wxCOPY :
-                mode = kCGBlendModeCopy;
-                break;
-            case wxCLEAR :
-                mode = kCGBlendModeClear;
-                break;
-            case wxXOR :
-                mode = kCGBlendModeXOR;
-                shouldAntiAlias = false;
-                break;
-            default :
-                retval = false;
-                break;
+        case wxCOMPOSITION_CLEAR:
+            cop = kCGCompositeOperationClear; 
+            break;
+        case wxCOMPOSITION_SOURCE:
+            cop = kCGCompositeOperationCopy; 
+            break;
+        case wxCOMPOSITION_OVER:
+            mode = kCGBlendModeNormal; 
+            break;
+        case wxCOMPOSITION_IN:
+            cop = kCGCompositeOperationSourceIn; 
+            break;
+        case wxCOMPOSITION_OUT:
+            cop = kCGCompositeOperationSourceOut; 
+            break;
+        case wxCOMPOSITION_ATOP:
+            cop = kCGCompositeOperationSourceAtop; 
+            break;
+        case wxCOMPOSITION_DEST_OVER:
+            cop = kCGCompositeOperationDestinationOver; 
+            break;
+        case wxCOMPOSITION_DEST_IN:
+            cop = kCGCompositeOperationDestinationIn; 
+            break;
+        case wxCOMPOSITION_DEST_OUT:
+            cop = kCGCompositeOperationDestinationOut; 
+            break;
+        case wxCOMPOSITION_DEST_ATOP:
+           cop = kCGCompositeOperationDestinationAtop; 
+            break;
+        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;
         }
+        if ( cop != kCGCompositeOperationSourceOver )
+            CGContextSetCompositeOperation(m_cgContext, cop);
+        else
+            CGContextSetBlendMode(m_cgContext, mode);
     }
-    else
 #endif
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
+    else
     {
-        if ( function == wxCOPY )
+        CGBlendMode mode = kCGBlendModeNormal;
+        switch( op )
         {
-            retval = true;
-        }
-        else if ( function == wxINVERT || function == wxXOR )
-        {
-            // change color to white
-            mode = kCGBlendModeExclusion;
-            shouldAntiAlias = false;
-            retval = true;
+        case wxCOMPOSITION_CLEAR:
+            mode = kCGBlendModeClear; 
+            break;
+        case wxCOMPOSITION_SOURCE:
+            mode = kCGBlendModeCopy; 
+            break;
+        case wxCOMPOSITION_OVER:
+            mode = kCGBlendModeNormal; 
+            break;
+        case wxCOMPOSITION_IN:
+            mode = kCGBlendModeSourceIn; 
+            break;
+        case wxCOMPOSITION_OUT:
+            mode = kCGBlendModeSourceOut; 
+            break;
+        case wxCOMPOSITION_ATOP:
+            mode = kCGBlendModeSourceAtop; 
+            break;
+        case wxCOMPOSITION_DEST_OVER:
+            mode = kCGBlendModeDestinationOver; 
+            break;
+        case wxCOMPOSITION_DEST_IN:
+            mode = kCGBlendModeDestinationIn; 
+            break;
+        case wxCOMPOSITION_DEST_OUT:
+            mode = kCGBlendModeDestinationOut; 
+            break;
+        case wxCOMPOSITION_DEST_ATOP:
+           mode = kCGBlendModeDestinationAtop; 
+            break;
+        case wxCOMPOSITION_XOR:
+            mode = kCGBlendModeXOR; 
+            break;
+            
+        case wxCOMPOSITION_ADD:
+            mode = kCGBlendModePlusLighter ;
+            break;
+        default:
+            return false;
         }
+        CGContextSetBlendMode(m_cgContext, mode);
     }
+#endif
+    return true;
+}
 
-    if (retval)
-    {
-        m_logicalFunction = function;
-        CGContextSetBlendMode( m_cgContext, mode );
-        CGContextSetShouldAntialias(m_cgContext, shouldAntiAlias);
-    }
-    return retval ;
+void wxMacCoreGraphicsContext::BeginLayer(wxDouble opacity)
+{
+    CGContextSaveGState(m_cgContext);
+    CGContextSetAlpha(m_cgContext, opacity);
+    CGContextBeginTransparencyLayer(m_cgContext, 0);
+}
+
+void wxMacCoreGraphicsContext::EndLayer()
+{
+    CGContextEndTransparencyLayer(m_cgContext);
+    CGContextRestoreGState(m_cgContext);
 }
 
 void wxMacCoreGraphicsContext::Clip( const wxRegion &region )
 {
-#ifdef __WXMAC__
+#if wxOSX_USE_COCOA_OR_CARBON
     if( m_cgContext )
     {
         wxCFRef<HIShapeRef> shape = wxCFRefFromGet(region.GetWXHRGN());
@@ -1623,6 +1844,9 @@ void wxMacCoreGraphicsContext::Clip( const wxRegion &region )
         HIShapeOffset( mutableShape, transformedOrigin.x, transformedOrigin.y );
         m_clipRgn.reset(mutableShape);
     }
+#else
+    // allow usage as measuring context
+    // wxASSERT_MSG( m_cgContext != NULL, "Needs a valid context for clipping" );
 #endif
 }
 
@@ -1636,10 +1860,15 @@ void wxMacCoreGraphicsContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDoubl
     }
     else
     {
+#if wxOSX_USE_COCOA_OR_CARBON
         // 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.reset(HIShapeCreateWithRect(&r));
+#else
+    // allow usage as measuring context
+    // wxFAIL_MSG( "Needs a valid context for clipping" );
+#endif
     }
 }
 
@@ -1660,7 +1889,12 @@ void wxMacCoreGraphicsContext::ResetClip()
     }
     else
     {
+#if wxOSX_USE_COCOA_OR_CARBON
         m_clipRgn.reset();
+#else
+    // allow usage as measuring context
+    // wxFAIL_MSG( "Needs a valid context for clipping" );
+#endif
     }
 }
 
@@ -1669,7 +1903,11 @@ void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath &path )
     if ( m_pen.IsNull() )
         return ;
 
-    EnsureIsValid();
+    if (EnsureIsValid()==false)
+        return;
+        
+    if (m_composition == wxCOMPOSITION_DEST)
+        return;
 
     wxQuartzOffsetHelper helper( m_cgContext , ShouldOffset() );
 
@@ -1678,8 +1916,14 @@ void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath &path )
     CGContextStrokePath( m_cgContext );
 }
 
-void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , int fillStyle )
+void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , wxPolygonFillMode fillStyle )
 {
+    if (EnsureIsValid()==false)
+        return;
+        
+    if (m_composition == wxCOMPOSITION_DEST)
+        return;
+
     if ( !m_brush.IsNull() && ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
     {
         // when using shading, we cannot draw pen and brush at the same time
@@ -1714,8 +1958,6 @@ void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , int fillSt
         }
     }
 
-    EnsureIsValid();
-
     if ( !m_brush.IsNull() )
         ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->Apply(this);
     if ( !m_pen.IsNull() )
@@ -1727,12 +1969,16 @@ void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , int fillSt
     CGContextDrawPath( m_cgContext , mode );
 }
 
-void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath &path , int fillStyle )
+void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath &path , wxPolygonFillMode fillStyle )
 {
     if ( m_brush.IsNull() )
         return;
 
-    EnsureIsValid();
+    if (EnsureIsValid()==false)
+        return;
+        
+    if (m_composition == wxCOMPOSITION_DEST)
+        return;
 
     if ( ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
     {
@@ -1760,20 +2006,24 @@ void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg )
 
     if ( m_cgContext )
     {
-        // TODO : when is this necessary - should we add a Flush() method ? CGContextSynchronize( m_cgContext );
         CGContextRestoreGState( m_cgContext );
         CGContextRestoreGState( m_cgContext );
-        if ( m_releaseContext )
+        if ( m_contextSynthesized )
         {
-#if ! ( defined( __LP64__ ) || defined(__WXCOCOA__) )
+            // TODO: in case of performance problems, try issuing this not too 
+            // frequently (half of refresh rate)
+            CGContextFlush(m_cgContext);
+#if wxOSX_USE_CARBON
             QDEndCGContext( GetWindowPort( m_windowRef ) , &m_cgContext);
+#endif
+#if wxOSX_USE_COCOA_OR_IPHONE
+            wxOSXUnlockFocus(m_view);
 #endif
         }
         else
             CGContextRelease(m_cgContext);
     }
 
-
     m_cgContext = cg;
 
     // FIXME: This check is needed because currently we need to use a DC/GraphicsContext
@@ -1789,7 +2039,7 @@ void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg )
         CGContextSaveGState( m_cgContext );
         CGContextSetTextMatrix( m_cgContext, CGAffineTransformIdentity );
         CGContextSaveGState( m_cgContext );
-        m_releaseContext = false;
+        m_contextSynthesized = false;
     }
 }
 
@@ -1825,7 +2075,12 @@ void wxMacCoreGraphicsContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDo
 
 void wxMacCoreGraphicsContext::DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
 {
-    EnsureIsValid();
+    if (EnsureIsValid()==false)
+        return;
+
+    if (m_composition == wxCOMPOSITION_DEST)
+        return;
+        
 #ifdef __WXMAC__
     wxMacCoreGraphicsBitmapData* refdata  =static_cast<wxMacCoreGraphicsBitmapData*>(bmp.GetRefData());
     CGImageRef image = refdata->GetBitmap();
@@ -1862,40 +2117,50 @@ void wxMacCoreGraphicsContext::DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble
 
 void wxMacCoreGraphicsContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
 {
-    EnsureIsValid();
+    if (EnsureIsValid()==false)
+        return;
+        
+    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 );
-#ifdef __WXMAC__
+#if wxOSX_USE_COCOA_OR_CARBON
     PlotIconRefInContext( m_cgContext , &r , kAlignNone , kTransformNone ,
-        NULL , kPlotIconRefNormalFlags , MAC_WXHICON( icon.GetHICON() ) );
+        NULL , kPlotIconRefNormalFlags , icon.GetHICON() );
 #endif
     CGContextRestoreGState( m_cgContext );
 }
 
 void wxMacCoreGraphicsContext::PushState()
 {
-    EnsureIsValid();
-
+    if (EnsureIsValid()==false)
+        return;
+        
     CGContextSaveGState( m_cgContext );
 }
 
 void wxMacCoreGraphicsContext::PopState()
 {
-    EnsureIsValid();
-
+    if (EnsureIsValid()==false)
+        return;
+        
     CGContextRestoreGState( m_cgContext );
 }
 
-void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y )
+void wxMacCoreGraphicsContext::DoDrawText( const wxString &str, wxDouble x, wxDouble y )
 {
-    if ( m_font.IsNull() )
+    wxCHECK_RET( !m_font.IsNull(), wxT("wxMacCoreGraphicsContext::DrawText - no valid font set") );
+
+    if (EnsureIsValid()==false)
+        return;
+        
+    if (m_composition == wxCOMPOSITION_DEST)
         return;
 
-    EnsureIsValid();
-#if wxMAC_USE_CORE_TEXT
+#if wxOSX_USE_CORE_TEXT
     if ( UMAGetSystemVersion() >= 0x1050 )
     {
         wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
@@ -1923,32 +2188,50 @@ void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDoub
         return;
     }
 #endif
-#if wxMAC_USE_ATSU_TEXT
+#if wxOSX_USE_ATSU_TEXT
     {
         DrawText(str, x, y, 0.0);
         return;
     }
 #endif
-#if wxMAC_USE_CG_TEXT
-    // TODO core graphics text implementation here
+#if wxOSX_USE_IPHONE
+    wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
+
+    CGContextSaveGState(m_cgContext);
+
+    CGColorRef col = wxMacCreateCGColor( fref->GetColour() );
+    CGContextSetTextDrawingMode (m_cgContext, kCGTextFill);
+    CGContextSetFillColorWithColor( m_cgContext, col );
+
+    wxCFStringRef text(str, wxLocale::GetSystemEncoding() );
+    DrawTextInContext( m_cgContext, CGPointMake( x, y ), fref->GetUIFont() , text.AsNSString() );
+
+    CGContextRestoreGState(m_cgContext);
+    CFRelease( col );
 #endif
 }
 
-void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle )
+void wxMacCoreGraphicsContext::DoDrawRotatedText(const wxString &str,
+                                                 wxDouble x, wxDouble y,
+                                                 wxDouble angle)
 {
-    if ( m_font.IsNull() )
+    wxCHECK_RET( !m_font.IsNull(), wxT("wxMacCoreGraphicsContext::DrawText - no valid font set") );
+
+    if (EnsureIsValid()==false)
+        return;
+        
+    if (m_composition == wxCOMPOSITION_DEST)
         return;
 
-    EnsureIsValid();
-#if wxMAC_USE_CORE_TEXT
+#if wxOSX_USE_CORE_TEXT
     if ( UMAGetSystemVersion() >= 0x1050 )
     {
         // default implementation takes care of rotation and calls non rotated DrawText afterwards
-        wxGraphicsContext::DrawText( str, x, y, angle );
+        wxGraphicsContext::DoDrawRotatedText( str, x, y, angle );
         return;
     }
 #endif
-#if wxMAC_USE_ATSU_TEXT
+#if wxOSX_USE_ATSU_TEXT
     {
         OSStatus status = noErr;
         ATSUTextLayout atsuLayout;
@@ -2032,16 +2315,16 @@ void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDoub
         return;
     }
 #endif
-#if wxMAC_USE_CG_TEXT
+#if wxOSX_USE_IPHONE
     // default implementation takes care of rotation and calls non rotated DrawText afterwards
-    wxGraphicsContext::DrawText( str, x, y, angle );
+    wxGraphicsContext::DoDrawRotatedText( str, x, y, angle );
 #endif
 }
 
 void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
                             wxDouble *descent, wxDouble *externalLeading ) const
 {
-    wxCHECK_RET( !m_font.IsNull(), wxT("wxDC(cg)::DoGetTextExtent - no valid font set") );
+    wxCHECK_RET( !m_font.IsNull(), wxT("wxMacCoreGraphicsContext::GetTextExtent - no valid font set") );
 
     if ( width )
         *width = 0;
@@ -2055,7 +2338,7 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid
     if (str.empty())
         return;
 
-#if wxMAC_USE_CORE_TEXT
+#if wxOSX_USE_CORE_TEXT
     if ( UMAGetSystemVersion() >= 0x1050 )
     {
         wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
@@ -2084,7 +2367,7 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid
         return;
     }
 #endif
-#if wxMAC_USE_ATSU_TEXT
+#if wxOSX_USE_ATSU_TEXT
     {
         OSStatus status = noErr;
 
@@ -2121,8 +2404,22 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid
         return;
     }
 #endif
-#if wxMAC_USE_CG_TEXT
-    // TODO core graphics text implementation here
+#if wxOSX_USE_IPHONE
+    wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
+
+    wxCFStringRef text(str, wxLocale::GetSystemEncoding() );
+    CGSize sz = MeasureTextInContext( fref->GetUIFont() , text.AsNSString() );
+
+    if ( height )
+        *height = sz.height;
+        /*
+    if ( descent )
+        *descent = FixedToInt(textDescent);
+    if ( externalLeading )
+        *externalLeading = 0;
+        */
+    if ( width )
+        *width = sz.width;
 #endif
 }
 
@@ -2131,10 +2428,12 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr
     widths.Empty();
     widths.Add(0, text.length());
 
+    wxCHECK_RET( !m_font.IsNull(), wxT("wxMacCoreGraphicsContext::DrawText - no valid font set") );
+
     if (text.empty())
         return;
 
-#if wxMAC_USE_CORE_TEXT
+#if wxOSX_USE_CORE_TEXT
     {
         wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
         CTFontRef font = fref->GetCTFont();
@@ -2156,7 +2455,7 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr
         return;
     }
 #endif
-#if wxMAC_USE_ATSU_TEXT
+#if wxOSX_USE_ATSU_TEXT
     {
         OSStatus status = noErr;
         ATSUTextLayout atsuLayout;
@@ -2192,7 +2491,7 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr
 #else
         ATSLayoutRecord *layoutRecords = NULL;
         ItemCount glyphCount = 0;
-        
+
         // Get the glyph extents
         OSStatus err = ::ATSUDirectGetLayoutDataArrayPtrFromTextLayout(atsuLayout,
                                                                        0,
@@ -2201,7 +2500,7 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr
                                                                        &layoutRecords,
                                                                        &glyphCount);
         wxASSERT(glyphCount == (text.length()+1));
-        
+
         if ( err == noErr && glyphCount == (text.length()+1))
         {
             for ( int pos = 1; pos < (int)glyphCount ; pos ++ )
@@ -2209,7 +2508,7 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr
                 widths[pos-1] = FixedToInt( layoutRecords[pos].realPos );
             }
         }
-        
+
         ::ATSUDirectReleaseLayoutDataArrayPtr(NULL,
                                               kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
                                               (void **) &layoutRecords);
@@ -2217,7 +2516,7 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr
         ::ATSUDisposeTextLayout(atsuLayout);
     }
 #endif
-#if wxMAC_USE_CG_TEXT
+#if wxOSX_USE_IPHONE
     // TODO core graphics text implementation here
 #endif
 }
@@ -2280,7 +2579,9 @@ public :
 
     virtual wxGraphicsContext * CreateContext( const wxWindowDC& dc);
     virtual wxGraphicsContext * CreateContext( const wxMemoryDC& dc);
+#if wxUSE_PRINTING_ARCHITECTURE
     virtual wxGraphicsContext * CreateContext( const wxPrinterDC& dc);
+#endif
 
     virtual wxGraphicsContext * CreateContextFromNativeContext( void * context );
 
@@ -2338,10 +2639,6 @@ wxGraphicsRenderer* wxGraphicsRenderer::GetDefaultRenderer()
     return &gs_MacCoreGraphicsRenderer;
 }
 
-#ifdef __WXCOCOA__
-extern CGContextRef wxMacGetContextFromCurrentNSContext() ;
-#endif
-
 wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxWindowDC& dc )
 {
     const wxDCImpl* impl = dc.GetImpl();
@@ -2351,12 +2648,13 @@ wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxWindowDC&
         int w, h;
         win_impl->GetSize( &w, &h );
         CGContextRef cgctx = 0;
-#ifdef __WXMAC__
-        cgctx =  (CGContextRef)(win_impl->GetWindow()->MacGetCGContextRef());
-#else
-        cgctx = wxMacGetContextFromCurrentNSContext() ;
-#endif
-        return new wxMacCoreGraphicsContext( this, cgctx, (wxDouble) w, (wxDouble) h );
+
+        wxASSERT_MSG(win_impl->GetWindow(), "Invalid wxWindow in wxMacCoreGraphicsRenderer::CreateContext");
+        if (win_impl->GetWindow())
+            cgctx =  (CGContextRef)(win_impl->GetWindow()->MacGetCGContextRef());
+
+        if (cgctx != 0)
+            return new wxMacCoreGraphicsContext( this, cgctx, (wxDouble) w, (wxDouble) h );
     }
     return NULL;
 }
@@ -2377,6 +2675,7 @@ wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxMemoryDC&
     return NULL;
 }
 
+#if wxUSE_PRINTING_ARCHITECTURE
 wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxPrinterDC& dc )
 {
 #ifdef __WXMAC__
@@ -2392,16 +2691,20 @@ wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxPrinterDC&
 #endif
     return NULL;
 }
+#endif
 
 wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeContext( void * context )
 {
     return new wxMacCoreGraphicsContext(this,(CGContextRef)context);
 }
 
-
 wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeWindow( void * window )
 {
+#if wxOSX_USE_CARBON
     return new wxMacCoreGraphicsContext(this,(WindowRef)window);
+#else
+    return NULL;
+#endif
 }
 
 wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( wxWindow* window )