]> git.saurik.com Git - wxWidgets.git/blobdiff - src/osx/carbon/graphics.cpp
use correct scale when drawing
[wxWidgets.git] / src / osx / carbon / graphics.cpp
index 07446d9a17fdc577ef78bbdf8aecd5ee17ebf213..c42ffba7f76ec97ca77bdd9294b55fafbe8baddd 100644 (file)
@@ -1,11 +1,11 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        src/mac/carbon/dccg.cpp
+// Name:        src/osx/carbon/graphics.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
 /////////////////////////////////////////////////////////////////////////////
 
     #include "wx/osx/dcprint.h"
     #include "wx/osx/dcclient.h"
     #include "wx/osx/dcmemory.h"
-#if wxOSX_USE_CARBON
-#include "wx/osx/uma.h"
-#else
-#include "wx/osx/private.h"
-#endif
-
+    #include "wx/osx/private.h"
 #else
     #include "CoreServices/CoreServices.h"
     #include "ApplicationServices/ApplicationServices.h"
@@ -76,15 +71,51 @@ int UMAGetSystemVersion()
 
 #endif
 
+#if wxOSX_USE_COCOA_OR_IPHONE
+extern CGContextRef wxOSXGetContextFromCurrentContext() ;
+#if wxOSX_USE_COCOA
+extern bool wxOSXLockFocus( WXWidget view) ;
+extern void wxOSXUnlockFocus( WXWidget view) ;
+#endif
+#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
+
 //-----------------------------------------------------------------------------
 // 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;
 
@@ -103,39 +134,31 @@ OSStatus wxMacDrawCGImage(
 #if wxOSX_USE_CARBON
     return HIViewDrawCGImage( inContext, inBounds, inImage );
 #else
-    // todo flip
-    CGContextDrawImage(inContext, *inBounds, inImage );
+    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
 }
 
 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 )
 {
 #ifdef __WXMAC__
-    return wxCFRetain((CTFontRef) font.MacGetCTFont());
+    return wxCFRetain((CTFontRef) font.OSXGetCTFont());
 #else
     return CTFontCreateWithName( wxCFStringRef( font.GetFaceName(), wxLocale::GetSystemEncoding() ) , font.GetPointSize() , NULL );
 #endif
@@ -187,7 +210,7 @@ class ImagePattern : public wxMacCoreGraphicsPattern
 public :
     ImagePattern( const wxBitmap* bmp , const CGAffineTransform& transform )
     {
-        wxASSERT( bmp && bmp->Ok() );
+        wxASSERT( bmp && bmp->IsOk() );
 #ifdef __WXMAC__
         Init( (CGImageRef) bmp->CreateCGImage() , transform );
 #endif
@@ -415,32 +438,32 @@ wxMacCoreGraphicsPenData::wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer
 
     switch ( pen.GetStyle() )
     {
-        case wxSOLID :
+        case wxPENSTYLE_SOLID:
             break;
 
-        case wxDOT :
+        case wxPENSTYLE_DOT:
             m_count = WXSIZEOF(dotted);
             m_userLengths = new CGFloat[ m_count ] ;
             memcpy( m_userLengths, dotted, sizeof(dotted) );
             m_lengths = m_userLengths;
             break;
 
-        case wxLONG_DASH :
+        case wxPENSTYLE_LONG_DASH:
             m_count = WXSIZEOF(dashed);
             m_lengths = dashed;
             break;
 
-        case wxSHORT_DASH :
+        case wxPENSTYLE_SHORT_DASH:
             m_count = WXSIZEOF(short_dashed);
             m_lengths = short_dashed;
             break;
 
-        case wxDOT_DASH :
+        case wxPENSTYLE_DOT_DASH:
             m_count = WXSIZEOF(dotted_dashed);
             m_lengths = dotted_dashed;
             break;
 
-        case wxUSER_DASH :
+        case wxPENSTYLE_USER_DASH:
             wxDash *dashes;
             m_count = pen.GetDashes( &dashes );
             if ((dashes != NULL) && (m_count > 0))
@@ -459,10 +482,10 @@ wxMacCoreGraphicsPenData::wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer
             m_lengths = m_userLengths;
             break;
 
-        case wxSTIPPLE :
+        case wxPENSTYLE_STIPPLE:
             {
                 wxBitmap* bmp = pen.GetStipple();
-                if ( bmp && bmp->Ok() )
+                if ( bmp && bmp->IsOk() )
                 {
                     m_colorSpace.reset( CGColorSpaceCreatePattern( NULL ) );
                     m_pattern.reset( (CGPatternRef) *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) );
@@ -527,12 +550,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 );
     }
 }
 
@@ -540,20 +558,6 @@ void wxMacCoreGraphicsPenData::Apply( wxGraphicsContext* context )
 // Brush
 //
 
-static const char *gs_stripedback_xpm[] = {
-/* columns rows colors chars-per-pixel */
-"4 4 2 1",
-". c #F0F0F0",
-"X c #ECECEC",
-/* pixels */
-"....",
-"....",
-"XXXX",
-"XXXX"
-};
-
-wxBitmap gs_stripedback_bmp( wxImage( (const char* const* ) gs_stripedback_xpm  ), -1 ) ;
-
 // make sure we all use one class for all conversions from wx to native colour
 
 class wxMacCoreGraphicsColour
@@ -628,7 +632,7 @@ wxMacCoreGraphicsColour::wxMacCoreGraphicsColour( const wxBrush &brush )
     {
         // now brush is a bitmap
         wxBitmap* bmp = brush.GetStipple();
-        if ( bmp && bmp->Ok() )
+        if ( bmp && bmp->IsOk() )
         {
             m_isPattern = true;
             m_patternColorComponents = new CGFloat[1] ;
@@ -647,15 +651,18 @@ public:
     ~wxMacCoreGraphicsBrushData ();
 
     virtual void Apply( wxGraphicsContext* context );
-    void CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
-        const wxColour&c1, const wxColour&c2 );
-    void CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
-    const wxColour &oColor, const wxColour &cColor );
+    void CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
+                                   wxDouble x2, wxDouble y2,
+                                   const wxGraphicsGradientStops& stops);
+    void CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
+                                   wxDouble xc, wxDouble yc, wxDouble radius,
+                                   const wxGraphicsGradientStops& stops);
 
     virtual bool IsShading() { return m_isShading; }
     CGShadingRef GetShading() { return m_shading; }
 protected:
-    CGFunctionRef CreateGradientFunction( const wxColour& c1, const wxColour& c2 );
+    CGFunctionRef CreateGradientFunction(const wxGraphicsGradientStops& stops);
+
     static void CalculateShadingValues (void *info, const CGFloat *in, CGFloat *out);
     virtual void Init();
 
@@ -664,7 +671,42 @@ protected:
     bool m_isShading;
     CGFunctionRef m_gradientFunction;
     CGShadingRef m_shading;
-    CGFloat *m_gradientComponents;
+
+    // information about a single gradient component
+    struct GradientComponent
+    {
+        CGFloat pos;
+        CGFloat red;
+        CGFloat green;
+        CGFloat blue;
+        CGFloat alpha;
+    };
+
+    // and information about all of them
+    struct GradientComponents
+    {
+        GradientComponents()
+        {
+            count = 0;
+            comps = NULL;
+        }
+
+        void Init(unsigned count_)
+        {
+            count = count_;
+            comps = new GradientComponent[count];
+        }
+
+        ~GradientComponents()
+        {
+            delete [] comps;
+        }
+
+        unsigned count;
+        GradientComponent *comps;
+    };
+
+    GradientComponents m_gradientComponents;
 };
 
 wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData( wxGraphicsRenderer* renderer) : wxGraphicsObjectRefData( renderer )
@@ -672,20 +714,25 @@ wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData( wxGraphicsRenderer* rend
     Init();
 }
 
-void wxMacCoreGraphicsBrushData::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
-        const wxColour&c1, const wxColour&c2 )
+void
+wxMacCoreGraphicsBrushData::CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
+                                                      wxDouble x2, wxDouble y2,
+                                                      const wxGraphicsGradientStops& stops)
 {
-    m_gradientFunction = CreateGradientFunction( c1, c2 );
+    m_gradientFunction = CreateGradientFunction(stops);
     m_shading = CGShadingCreateAxial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat) x1, (CGFloat) y1),
                                         CGPointMake((CGFloat) x2,(CGFloat) y2), m_gradientFunction, true, true ) ;
     m_isShading = true ;
 }
 
-void wxMacCoreGraphicsBrushData::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
-    const wxColour &oColor, const wxColour &cColor )
+void
+wxMacCoreGraphicsBrushData::CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
+                                                      wxDouble xc, wxDouble yc,
+                                                      wxDouble radius,
+                                                      const wxGraphicsGradientStops& stops)
 {
-    m_gradientFunction = CreateGradientFunction( oColor, cColor );
-    m_shading = CGShadingCreateRadial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat) xo,(CGFloat) yo), 0, 
+    m_gradientFunction = CreateGradientFunction(stops);
+    m_shading = CGShadingCreateRadial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat) xo,(CGFloat) yo), 0,
                                         CGPointMake((CGFloat) xc,(CGFloat) yc), (CGFloat) radius, m_gradientFunction, true, true ) ;
     m_isShading = true ;
 }
@@ -704,15 +751,12 @@ wxMacCoreGraphicsBrushData::~wxMacCoreGraphicsBrushData()
 
     if( m_gradientFunction )
         CGFunctionRelease(m_gradientFunction);
-
-    delete[] m_gradientComponents;
 }
 
 void wxMacCoreGraphicsBrushData::Init()
 {
     m_gradientFunction = NULL;
     m_shading = NULL;
-    m_gradientComponents = NULL;
     m_isShading = false;
 }
 
@@ -732,30 +776,70 @@ void wxMacCoreGraphicsBrushData::Apply( wxGraphicsContext* context )
 
 void wxMacCoreGraphicsBrushData::CalculateShadingValues (void *info, const CGFloat *in, CGFloat *out)
 {
-    CGFloat* colors = (CGFloat*) info ;
+    const GradientComponents& stops = *(GradientComponents*) info ;
+
     CGFloat f = *in;
-    for( int i = 0 ; i < 4 ; ++i )
+    if (f <= 0.0)
     {
-        out[i] = colors[i] + ( colors[4+i] - colors[i] ) * f;
+        // Start
+        out[0] = stops.comps[0].red;
+        out[1] = stops.comps[0].green;
+        out[2] = stops.comps[0].blue;
+        out[3] = stops.comps[0].alpha;
+    }
+    else if (f >= 1.0)
+    {
+        // end
+        out[0] = stops.comps[stops.count - 1].red;
+        out[1] = stops.comps[stops.count - 1].green;
+        out[2] = stops.comps[stops.count - 1].blue;
+        out[3] = stops.comps[stops.count - 1].alpha;
+    }
+    else
+    {
+        // Find first component with position greater than f
+        unsigned i;
+        for ( i = 0; i < stops.count; i++ )
+        {
+            if (stops.comps[i].pos > f)
+                break;
+        }
+
+        // Interpolated between stops
+        CGFloat diff = (f - stops.comps[i-1].pos);
+        CGFloat range = (stops.comps[i].pos - stops.comps[i-1].pos);
+        CGFloat fact = diff / range;
+
+        out[0] = stops.comps[i - 1].red + (stops.comps[i].red - stops.comps[i - 1].red) * fact;
+        out[1] = stops.comps[i - 1].green + (stops.comps[i].green - stops.comps[i - 1].green) * fact;
+        out[2] = stops.comps[i - 1].blue + (stops.comps[i].blue - stops.comps[i - 1].blue) * fact;
+        out[3] = stops.comps[i - 1].alpha + (stops.comps[i].alpha - stops.comps[i - 1].alpha) * fact;
     }
 }
 
-CGFunctionRef wxMacCoreGraphicsBrushData::CreateGradientFunction( const wxColour& c1, const wxColour& c2 )
+CGFunctionRef
+wxMacCoreGraphicsBrushData::CreateGradientFunction(const wxGraphicsGradientStops& stops)
 {
+
     static const CGFunctionCallbacks callbacks = { 0, &CalculateShadingValues, NULL };
     static const CGFloat input_value_range [2] = { 0, 1 };
     static const CGFloat output_value_ranges [8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
-    m_gradientComponents = new CGFloat[8] ;
-    m_gradientComponents[0] = (CGFloat) (c1.Red() / 255.0);
-    m_gradientComponents[1] = (CGFloat) (c1.Green() / 255.0);
-    m_gradientComponents[2] = (CGFloat) (c1.Blue() / 255.0);
-    m_gradientComponents[3] = (CGFloat) (c1.Alpha() / 255.0);
-    m_gradientComponents[4] = (CGFloat) (c2.Red() / 255.0);
-    m_gradientComponents[5] = (CGFloat) (c2.Green() / 255.0);
-    m_gradientComponents[6] = (CGFloat) (c2.Blue() / 255.0);
-    m_gradientComponents[7] = (CGFloat) (c2.Alpha() / 255.0);
-
-    return CGFunctionCreate ( m_gradientComponents,  1,
+
+    m_gradientComponents.Init(stops.GetCount());
+    for ( unsigned i = 0; i < m_gradientComponents.count; i++ )
+    {
+        const wxGraphicsGradientStop stop = stops.Item(i);
+
+        m_gradientComponents.comps[i].pos = stop.GetPosition();
+
+        const wxColour col = stop.GetColour();
+        m_gradientComponents.comps[i].red = (CGFloat) (col.Red() / 255.0);
+        m_gradientComponents.comps[i].green = (CGFloat) (col.Green() / 255.0);
+        m_gradientComponents.comps[i].blue = (CGFloat) (col.Blue() / 255.0);
+        m_gradientComponents.comps[i].alpha = (CGFloat) (col.Alpha() / 255.0);
+    }
+
+    return CGFunctionCreate ( &m_gradientComponents,  1,
                             input_value_range,
                             4,
                             output_value_ranges,
@@ -784,7 +868,7 @@ public:
     virtual ATSUStyle GetATSUStyle() { return m_macATSUIStyle; }
 #endif
 #if wxOSX_USE_CORE_TEXT
-    CTFontRef GetCTFont() const { return m_ctFont ; }
+    CTFontRef OSXGetCTFont() const { return m_ctFont ; }
 #endif
     wxColour GetColour() const { return m_colour ; }
 
@@ -828,7 +912,7 @@ wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* rendere
 
     // we need the scale here ...
 
-    Fixed atsuSize = IntToFixed( int( 1 * font.MacGetFontSize()) );
+    Fixed atsuSize = IntToFixed( int( 1 * font.GetPointSize()) );
     RGBColor atsuColor ;
     col.GetRGBColor( &atsuColor );
     ATSUAttributeTag atsuTags[] =
@@ -836,19 +920,19 @@ wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* rendere
             kATSUSizeTag ,
             kATSUColorTag ,
     };
-    ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
+    ByteCount atsuSizes[WXSIZEOF(atsuTags)] =
     {
             sizeof( Fixed ) ,
             sizeof( RGBColor ) ,
     };
-    ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
+    ATSUAttributeValuePtr atsuValues[WXSIZEOF(atsuTags)] =
     {
             &atsuSize ,
             &atsuColor ,
     };
 
     status = ::ATSUSetAttributes(
-        m_macATSUIStyle, sizeof(atsuTags) / sizeof(ATSUAttributeTag) ,
+        m_macATSUIStyle, WXSIZEOF(atsuTags),
         atsuTags, atsuSizes, atsuValues);
 
     wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") );
@@ -871,20 +955,29 @@ 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
+    wxImage ConvertToImage() const
+    {
+        return wxBitmap(m_bitmap).ConvertToImage();
+    }
+#endif // wxUSE_IMAGE
+
 private :
     CGImageRef m_bitmap;
     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)
 {
 }
@@ -894,6 +987,7 @@ wxMacCoreGraphicsBitmapData::~wxMacCoreGraphicsBitmapData()
     CGImageRelease( m_bitmap );
 }
 
+
 //
 // Graphics Matrix
 //
@@ -983,7 +1077,7 @@ wxGraphicsObjectRefData *wxMacCoreGraphicsMatrixData::Clone() const
 // concatenates the matrix
 void wxMacCoreGraphicsMatrixData::Concat( const wxGraphicsMatrixData *t )
 {
-    m_matrix = CGAffineTransformConcat(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix()) );
+    m_matrix = CGAffineTransformConcat(*((CGAffineTransform*) t->GetNativeMatrix()), m_matrix );
 }
 
 // sets the matrix to the respective values
@@ -1119,9 +1213,12 @@ public :
     // appends a rectangle as a new closed subpath
     virtual void AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
 
-    // appends an ellipsis as a new closed subpath fitting the passed rectangle
+    // appends a circle as a new closed subpath
     virtual void AddCircle( wxDouble x, wxDouble y, wxDouble r );
 
+    // appends an ellipsis as a new closed subpath fitting the passed rectangle
+    virtual void AddEllipse( wxDouble x, wxDouble y, wxDouble w, wxDouble h);
+
     // 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 );
 
@@ -1138,9 +1235,9 @@ public :
     virtual void Transform( const wxGraphicsMatrixData* matrix );
 
     // gets the bounding box enclosing all points (possibly including control points)
-    virtual void GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *y) const;
+    virtual void GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) 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;
 };
@@ -1198,7 +1295,12 @@ void wxMacCoreGraphicsPathData::AddRectangle( wxDouble x, wxDouble y, wxDouble w
 
 void wxMacCoreGraphicsPathData::AddCircle( wxDouble x, wxDouble y , wxDouble r )
 {
-    CGPathAddArc( m_path , NULL , (CGFloat) x , (CGFloat) y , (CGFloat) r , (CGFloat) 0.0 , (CGFloat) (2 * M_PI) , true );
+    CGPathAddEllipseInRect( m_path, NULL, CGRectMake(x-r,y-r,2*r,2*r));
+}
+
+void wxMacCoreGraphicsPathData::AddEllipse( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
+{
+    CGPathAddEllipseInRect( m_path, NULL, CGRectMake(x,y,w,h));
 }
 
 // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
@@ -1251,7 +1353,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 );
 }
@@ -1277,15 +1379,10 @@ public:
 
     wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer);
 
-    wxMacCoreGraphicsContext();
-
     ~wxMacCoreGraphicsContext();
 
     void Init();
 
-    // returns the size of the graphics context in device coordinates
-    virtual void GetSize( wxDouble* width, wxDouble* height);
-
     virtual void StartPage( wxDouble width, wxDouble height );
 
     virtual void EndPage();
@@ -1309,7 +1406,16 @@ public:
 
     virtual void * GetNativeContext();
 
-    bool SetLogicalFunction( int function );
+    virtual bool SetAntialiasMode(wxAntialiasMode antialias);
+
+    virtual bool SetInterpolationQuality(wxInterpolationQuality interpolation);
+    
+    virtual bool SetCompositionMode(wxCompositionMode op);
+
+    virtual void BeginLayer(wxDouble opacity);
+
+    virtual void EndLayer();
+
     //
     // transformation
     //
@@ -1339,13 +1445,16 @@ 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
     {
+        if ( !m_enableOffset )
+            return false;
+        
         int penwidth = 0 ;
         if ( !m_pen.IsNull() )
         {
@@ -1359,10 +1468,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;
 
@@ -1377,24 +1482,34 @@ public:
     virtual void DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
 
     virtual void DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
+    
+    // fast convenience methods
+    
+    
+    virtual void DrawRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h ); 
 
     void SetNativeContext( CGContextRef cg );
 
-    DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacCoreGraphicsContext)
+    wxDECLARE_NO_COPY_CLASS(wxMacCoreGraphicsContext);
 
 private:
-    void EnsureIsValid();
+    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 );
 
     CGContextRef m_cgContext;
 #if wxOSX_USE_CARBON
     WindowRef m_windowRef;
+#else
+    WXWidget m_view;
 #endif
-    bool m_releaseContext;
+    bool m_contextSynthesized;
     CGAffineTransform m_windowTransform;
-    wxDouble m_width;
-    wxDouble m_height;
+    bool m_invisible;
 
-#if wxOSX_USE_CARBON
+#if wxOSX_USE_COCOA_OR_CARBON
     wxCFRef<HIShapeRef> m_clipRgn;
 #endif
 };
@@ -1415,8 +1530,6 @@ private:
 // wxMacCoreGraphicsContext implementation
 //-----------------------------------------------------------------------------
 
-IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsContext, wxGraphicsContext)
-
 class wxQuartzOffsetHelper
 {
 public :
@@ -1425,14 +1538,23 @@ public :
         m_cg = cg;
         m_offset = offset;
         if ( m_offset )
-            CGContextTranslateCTM( m_cg, (CGFloat) 0.5, (CGFloat) 0.5 );
+        {
+            m_userOffset = CGContextConvertSizeToUserSpace( m_cg, CGSizeMake( 0.5 , 0.5 ) );
+            CGContextTranslateCTM( m_cg, m_userOffset.width , m_userOffset.height );
+        }
+        else
+        {
+            m_userOffset = CGSizeMake(0.0, 0.0);
+        }
+
     }
     ~wxQuartzOffsetHelper( )
     {
         if ( m_offset )
-            CGContextTranslateCTM( m_cg, (CGFloat) -0.5, (CGFloat) -0.5 );
+            CGContextTranslateCTM( m_cg, -m_userOffset.width , -m_userOffset.height );
     }
 public :
+    CGSize m_userOffset;
     CGContextRef m_cg;
     bool m_offset;
 } ;
@@ -1440,12 +1562,18 @@ public :
 void wxMacCoreGraphicsContext::Init()
 {
     m_cgContext = NULL;
-    m_releaseContext = false;
+    m_contextSynthesized = false;
+    m_width = 0;
+    m_height = 0;
 #if wxOSX_USE_CARBON
     m_windowRef = NULL;
 #endif
-    m_width = 0;
-    m_height = 0;
+#if wxOSX_USE_COCOA_OR_IPHONE
+    m_view = NULL;
+#endif
+    m_invisible = false;
+    m_antialias = wxANTIALIAS_DEFAULT;
+    m_interpolation = wxINTERPOLATION_DEFAULT;
 }
 
 wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext, wxDouble width, wxDouble height ) : wxGraphicsContext(renderer)
@@ -1461,6 +1589,7 @@ wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer
 {
     Init();
     m_windowRef = window;
+    m_enableOffset = true;
 }
 #endif
 
@@ -1468,19 +1597,36 @@ wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer
 {
     Init();
 
+    m_enableOffset = true;
+    wxSize sz = window->GetSize();
+    m_width = sz.x;
+    m_height = sz.y;
+
+#if wxOSX_USE_COCOA_OR_IPHONE
+    m_view = window->GetHandle();
+
+#if wxOSX_USE_COCOA
+    if ( ! window->GetPeer()->IsFlipped() )
+    {
+        m_windowTransform = CGAffineTransformMakeTranslation( 0 , m_height );
+        m_windowTransform = CGAffineTransformScale( m_windowTransform , 1 , -1 );
+    }
+    else
+#endif
+    {
+        m_windowTransform = CGAffineTransformIdentity;
+    }
+#else
     int originX , originY;
     originX = originY = 0;
-
     Rect bounds = { 0,0,0,0 };
-#if defined(__WXCOCOA__) || !wxOSX_USE_CARBON
-#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)
@@ -1488,24 +1634,19 @@ wxMacCoreGraphicsContext::wxMacCoreGraphicsContext(wxGraphicsRenderer* renderer)
     Init();
 }
 
-wxMacCoreGraphicsContext::wxMacCoreGraphicsContext() : wxGraphicsContext(NULL)
-{
-    Init();
-    wxLogDebug(wxT("Illegal Constructor called"));
-}
-
 wxMacCoreGraphicsContext::~wxMacCoreGraphicsContext()
 {
     SetNativeContext(NULL);
 }
 
-void wxMacCoreGraphicsContext::GetSize( wxDouble* width, wxDouble* height)
+
+void wxMacCoreGraphicsContext::CheckInvariants() const
 {
-    *width = m_width;
-    *height = m_height;
+    // check invariants here for debugging ...
 }
 
 
+
 void wxMacCoreGraphicsContext::StartPage( wxDouble width, wxDouble height )
 {
     CGRect r;
@@ -1529,112 +1670,292 @@ void wxMacCoreGraphicsContext::Flush()
     CGContextFlush(m_cgContext);
 }
 
-void wxMacCoreGraphicsContext::EnsureIsValid()
+bool wxMacCoreGraphicsContext::EnsureIsValid()
 {
+    CheckInvariants();
+    
     if ( !m_cgContext )
     {
-#if defined(__WXCOCOA__) || ! wxOSX_USE_CARBON
-        wxFAIL_MSG("Cannot create wxDCs lazily");
-#else
+        if (m_invisible)
+            return false;
+
+#if wxOSX_USE_COCOA
+        if ( wxOSXLockFocus(m_view) )
+        {
+            m_cgContext = wxOSXGetContextFromCurrentContext();
+            wxASSERT_MSG( m_cgContext != NULL, wxT("Unable to retrieve drawing context from View"));
+        }
+        else
+        {
+            m_invisible = true;
+        }
+#endif
+#if wxOSX_USE_IPHONE
+        m_cgContext = wxOSXGetContextFromCurrentContext();
+        if ( m_cgContext == NULL )
+        {
+            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))
+            CGContextSaveGState( m_cgContext );
+#if wxOSX_USE_COCOA_OR_CARBON
+            if ( m_clipRgn.get() )
             {
-                CGRect empty = CGRectMake( 0,0,0,0 );
-                CGContextClipToRect( m_cgContext, empty );
+                wxCFRef<HIMutableShapeRef> hishape( HIShapeCreateMutableCopy( m_clipRgn ) );
+                // 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
+#endif
+            CGContextConcatCTM( m_cgContext, m_windowTransform );
+            CGContextSetTextMatrix( m_cgContext, CGAffineTransformIdentity );
+            m_contextSynthesized = true;
+            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 ;
             }
-        }
-        CGContextSaveGState( m_cgContext );
 #endif
+        }
     }
-}
+    CheckInvariants();
 
-// TODO test whether the private CGContextSetCompositeOperation works under 10.3 (using NSCompositingModes)
+    return m_cgContext != NULL;
+}
 
-bool wxMacCoreGraphicsContext::SetLogicalFunction( int function )
+bool wxMacCoreGraphicsContext::SetAntialiasMode(wxAntialiasMode antialias)
 {
-    if (m_logicalFunction == function)
+    if (!EnsureIsValid())
         return true;
 
-    EnsureIsValid();
+    if (m_antialias == antialias)
+        return true;
 
-    bool retval = false;
-    bool shouldAntiAlias = true;
-    CGBlendMode mode = kCGBlendModeNormal;
+    m_antialias = antialias;
 
-#if defined(__WXMAC__) && ( wxOSX_USE_IPHONE || ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 ) )
-#if wxOSX_USE_IPHONE
-    if ( 1 )
+    bool antialiasMode;
+    switch (antialias)
+    {
+        case wxANTIALIAS_DEFAULT:
+            antialiasMode = true;
+            break;
+        case wxANTIALIAS_NONE:
+            antialiasMode = false;
+            break;
+        default:
+            return false;
+    }
+    CGContextSetShouldAntialias(m_cgContext, antialiasMode);
+    CheckInvariants();
+    return true;
+}
+
+bool wxMacCoreGraphicsContext::SetInterpolationQuality(wxInterpolationQuality interpolation)
+{
+    if (!EnsureIsValid())
+        return true;
+    
+    if (m_interpolation == interpolation)
+        return true;
+
+    m_interpolation = interpolation;
+    CGInterpolationQuality quality;
+    
+    switch (interpolation) 
+    {
+        case wxINTERPOLATION_DEFAULT:
+            quality = kCGInterpolationDefault;
+            break;
+        case wxINTERPOLATION_NONE:
+            quality = kCGInterpolationNone;
+            break;
+        case wxINTERPOLATION_FAST:
+            quality = kCGInterpolationLow;
+            break;
+        case wxINTERPOLATION_GOOD:
+#if wxOSX_USE_COCOA_OR_CARBON
+            quality = UMAGetSystemVersion() < 0x1060 ? kCGInterpolationHigh : (CGInterpolationQuality) 4 /*kCGInterpolationMedium only on 10.6*/;
 #else
-    if ( UMAGetSystemVersion() >= 0x1050 )
+            quality = kCGInterpolationMedium;
 #endif
+            break;
+        case wxINTERPOLATION_BEST:
+            quality = kCGInterpolationHigh;
+            break;
+        default:
+            return false;
+    }
+    CGContextSetInterpolationQuality(m_cgContext, quality);
+    CheckInvariants();
+    return true;
+}
+
+bool wxMacCoreGraphicsContext::SetCompositionMode(wxCompositionMode op)
+{
+    if (!EnsureIsValid())
+        return true;
+
+    if ( m_composition == op )
+        return true;
+
+    m_composition = op;
+
+    if (m_composition == wxCOMPOSITION_DEST)
+        return true;
+
+    // TODO REMOVE if we don't need it because of bugs in 10.5
+#if 0
     {
-        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;
+        case wxCOMPOSITION_ADD:
+            mode = kCGBlendModePlusLighter ;
+            break;
+        default:
+            return false;
         }
+        if ( cop != kCGCompositeOperationSourceOver )
+            CGContextSetCompositeOperation(m_cgContext, cop);
+        else
+            CGContextSetBlendMode(m_cgContext, mode);
     }
-    else
 #endif
     {
-        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 = kCGBlendModeExclusion; // Not kCGBlendModeXOR!
+            break;
+
+        case wxCOMPOSITION_ADD:
+            mode = kCGBlendModePlusLighter ;
+            break;
+        default:
+            return false;
         }
+        CGContextSetBlendMode(m_cgContext, mode);
     }
 
-    if (retval)
-    {
-        m_logicalFunction = function;
-        CGContextSetBlendMode( m_cgContext, mode );
-        CGContextSetShouldAntialias(m_cgContext, shouldAntiAlias);
-    }
-    return retval ;
+    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 )
 {
-#if wxOSX_USE_CARBON
+    CheckInvariants();
+#if wxOSX_USE_COCOA_OR_CARBON
     if( m_cgContext )
     {
         wxCFRef<HIShapeRef> shape = wxCFRefFromGet(region.GetWXHRGN());
@@ -1664,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 )
     {
@@ -1676,16 +1999,18 @@ void wxMacCoreGraphicsContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDoubl
     }
     else
     {
-#if wxOSX_USE_CARBON
+#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 );
+        r.size= CGSizeApplyAffineTransform(r.size, m_windowTransform);
         m_clipRgn.reset(HIShapeCreateWithRect(&r));
 #else
     // allow usage as measuring context
     // wxFAIL_MSG( "Needs a valid context for clipping" );
 #endif
     }
+    CheckInvariants();    
 }
 
     // resets the clipping to original extent
@@ -1705,13 +2030,14 @@ void wxMacCoreGraphicsContext::ResetClip()
     }
     else
     {
-#if wxOSX_USE_CARBON
+#if wxOSX_USE_COCOA_OR_CARBON
         m_clipRgn.reset();
 #else
     // allow usage as measuring context
     // wxFAIL_MSG( "Needs a valid context for clipping" );
 #endif
     }
+    CheckInvariants();    
 }
 
 void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath &path )
@@ -1719,17 +2045,29 @@ void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath &path )
     if ( m_pen.IsNull() )
         return ;
 
-    EnsureIsValid();
+    if (!EnsureIsValid())
+        return;
+
+    if (m_composition == wxCOMPOSITION_DEST)
+        return;
 
     wxQuartzOffsetHelper helper( m_cgContext , ShouldOffset() );
 
     ((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->Apply(this);
     CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
     CGContextStrokePath( m_cgContext );
+    
+    CheckInvariants();
 }
 
-void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , int fillStyle )
+void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , wxPolygonFillMode fillStyle )
 {
+    if (!EnsureIsValid())
+        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
@@ -1764,8 +2102,6 @@ void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , int fillSt
         }
     }
 
-    EnsureIsValid();
-
     if ( !m_brush.IsNull() )
         ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->Apply(this);
     if ( !m_pen.IsNull() )
@@ -1775,14 +2111,20 @@ void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , int fillSt
 
     CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
     CGContextDrawPath( m_cgContext , mode );
+    
+    CheckInvariants();
 }
 
-void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath &path , int fillStyle )
+void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath &path , wxPolygonFillMode fillStyle )
 {
     if ( m_brush.IsNull() )
         return;
 
-    EnsureIsValid();
+    if (!EnsureIsValid())
+        return;
+
+    if (m_composition == wxCOMPOSITION_DEST)
+        return;
 
     if ( ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
     {
@@ -1801,6 +2143,8 @@ void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath &path , int fillSt
         else
             CGContextFillPath( m_cgContext );
     }
+    
+    CheckInvariants();
 }
 
 void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg )
@@ -1810,20 +2154,22 @@ void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg )
 
     if ( m_cgContext )
     {
-        // TODO : when is this necessary - should we add a Flush() method ? CGContextSynchronize( m_cgContext );
+        CheckInvariants();
         CGContextRestoreGState( m_cgContext );
         CGContextRestoreGState( m_cgContext );
-        if ( m_releaseContext )
+        if ( m_contextSynthesized )
         {
 #if wxOSX_USE_CARBON
             QDEndCGContext( GetWindowPort( m_windowRef ) , &m_cgContext);
+#endif
+#if wxOSX_USE_COCOA
+            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
@@ -1839,7 +2185,7 @@ void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg )
         CGContextSaveGState( m_cgContext );
         CGContextSetTextMatrix( m_cgContext, CGAffineTransformIdentity );
         CGContextSaveGState( m_cgContext );
-        m_releaseContext = false;
+        m_contextSynthesized = false;
     }
 }
 
@@ -1875,14 +2221,19 @@ 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())
+        return;
+
+    if (m_composition == wxCOMPOSITION_DEST)
+        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 )
     {
-        // is is a mask, the '1' in the mask tell where to draw the current brush
+        // is a mask, the '1' in the mask tell where to draw the current brush
         if (  !m_brush.IsNull() )
         {
             if ( ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
@@ -1908,54 +2259,73 @@ 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 )
 {
-    EnsureIsValid();
+    if (!EnsureIsValid())
+        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 );
-#if wxOSX_USE_CARBON
+#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 , MAC_WXHICON( icon.GetHICON() ) );
+        NULL , kPlotIconRefNormalFlags , icon.GetHICON() );
 #endif
     CGContextRestoreGState( m_cgContext );
+    
+    CheckInvariants();
 }
 
 void wxMacCoreGraphicsContext::PushState()
 {
-    EnsureIsValid();
+    if (!EnsureIsValid())
+        return;
 
     CGContextSaveGState( m_cgContext );
 }
 
 void wxMacCoreGraphicsContext::PopState()
 {
-    EnsureIsValid();
+    if (!EnsureIsValid())
+        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())
+        return;
+
+    if (m_composition == wxCOMPOSITION_DEST)
         return;
 
-    EnsureIsValid();
 #if wxOSX_USE_CORE_TEXT
-    if ( UMAGetSystemVersion() >= 0x1050 )
     {
         wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
         wxCFStringRef text(str, wxLocale::GetSystemEncoding() );
-        CTFontRef font = fref->GetCTFont();
+        CTFontRef font = fref->OSXGetCTFont();
         CGColorRef col = wxMacCreateCGColor( fref->GetColour() );
+#if 0
+        // right now there's no way to get continuous underlines, only words, so we emulate it
         CTUnderlineStyle ustyle = fref->GetUnderlined() ? kCTUnderlineStyleSingle : kCTUnderlineStyleNone ;
         wxCFRef<CFNumberRef> underlined( CFNumberCreate(NULL, kCFNumberSInt32Type, &ustyle) );
          CFStringRef keys[] = { kCTFontAttributeName , kCTForegroundColorAttributeName, kCTUnderlineStyleAttributeName };
         CFTypeRef values[] = { font, col, underlined };
+#else
+        CFStringRef keys[] = { kCTFontAttributeName , kCTForegroundColorAttributeName };
+        CFTypeRef values[] = { font, col };
+#endif
         wxCFRef<CFDictionaryRef> attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**) &keys, (const void**) &values,
                                                         WXSIZEOF( keys ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) );
         wxCFRef<CFAttributedStringRef> attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, attributes) );
@@ -1964,12 +2334,30 @@ void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDoub
         y += CTFontGetAscent(font);
 
         CGContextSaveGState(m_cgContext);
-        CGContextTranslateCTM(m_cgContext, x, y);
+        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() ) {
+            //AKT: draw horizontal line 1 pixel thick and with 1 pixel gap under baseline
+            CGFloat width = CTLineGetTypographicBounds(line, NULL, NULL, NULL);
+
+            CGPoint points[] = { {0.0, -2.0},  {width, -2.0} };
+            
+            CGContextSetStrokeColorWithColor(m_cgContext, col);
+            CGContextSetShouldAntialias(m_cgContext, false);
+            CGContextSetLineWidth(m_cgContext, 1.0);
+            CGContextStrokeLineSegments(m_cgContext, points, 2);
+        }
+        
         CGContextRestoreGState(m_cgContext);
-        CFRelease( col );
+        CGContextSetTextMatrix(m_cgContext, textMatrix);
+        CGColorRelease( col );
+        CheckInvariants();
         return;
     }
 #endif
@@ -1985,7 +2373,7 @@ void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDoub
     CGContextSaveGState(m_cgContext);
 
     CGColorRef col = wxMacCreateCGColor( fref->GetColour() );
-    CGContextSetTextDrawingMode (m_cgContext, kCGTextFill); 
+    CGContextSetTextDrawingMode (m_cgContext, kCGTextFill);
     CGContextSetFillColorWithColor( m_cgContext, col );
 
     wxCFStringRef text(str, wxLocale::GetSystemEncoding() );
@@ -1994,19 +2382,26 @@ void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDoub
     CGContextRestoreGState(m_cgContext);
     CFRelease( col );
 #endif
+    
+    CheckInvariants();
 }
 
-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())
+        return;
+
+    if (m_composition == wxCOMPOSITION_DEST)
         return;
 
-    EnsureIsValid();
 #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
@@ -2034,15 +2429,15 @@ void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDoub
             {
                 kATSULineRotationTag ,
             };
-            ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
+            ByteCount atsuSizes[WXSIZEOF(atsuTags)] =
             {
                 sizeof( Fixed ) ,
             };
-            ATSUAttributeValuePtr    atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
+            ATSUAttributeValuePtr    atsuValues[WXSIZEOF(atsuTags)] =
             {
                 &atsuAngle ,
             };
-            status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag),
+            status = ::ATSUSetLayoutControls(atsuLayout , WXSIZEOF(atsuTags),
                                              atsuTags, atsuSizes, atsuValues );
         }
 
@@ -2051,15 +2446,15 @@ void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDoub
             {
                 kATSUCGContextTag ,
             };
-            ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
+            ByteCount atsuSizes[WXSIZEOF(atsuTags)] =
             {
                 sizeof( CGContextRef ) ,
             };
-            ATSUAttributeValuePtr    atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
+            ATSUAttributeValuePtr    atsuValues[WXSIZEOF(atsuTags)] =
             {
                 &m_cgContext ,
             };
-            status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag),
+            status = ::ATSUSetLayoutControls(atsuLayout , WXSIZEOF(atsuTags),
                                              atsuTags, atsuSizes, atsuValues );
         }
 
@@ -2072,8 +2467,8 @@ void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDoub
         wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
 
         Rect rect;
-        x += (int)(sin(angle) * FixedToInt(ascent));
-        y += (int)(cos(angle) * FixedToInt(ascent));
+        x += (int)(sin(angle) * FixedToFloat(ascent));
+        y += (int)(cos(angle) * FixedToFloat(ascent));
 
         status = ::ATSUMeasureTextImage( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
                                         IntToFixed(x) , IntToFixed(y) , &rect );
@@ -2090,20 +2485,23 @@ void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDoub
         CGContextRestoreGState(m_cgContext);
 
         ::ATSUDisposeTextLayout(atsuLayout);
+        CheckInvariants();
 
         return;
     }
 #endif
 #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
+    
+    CheckInvariants();
 }
 
 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;
@@ -2118,10 +2516,9 @@ 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->GetCTFont();
+        CTFontRef font = fref->OSXGetCTFont();
 
         wxCFStringRef text(str, wxLocale::GetSystemEncoding() );
         CFStringRef keys[] = { kCTFontAttributeName  };
@@ -2131,9 +2528,8 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid
         wxCFRef<CFAttributedStringRef> attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, attributes) );
         wxCFRef<CTLineRef> line( CTLineCreateWithAttributedString(attrtext) );
 
-        CGFloat w, a, d, l;
-
-        w = CTLineGetTypographicBounds(line, &a, &d, &l) ;
+        CGFloat a, d, l, w;
+        w = CTLineGetTypographicBounds(line, &a, &d, &l);
 
         if ( height )
             *height = a+d+l;
@@ -2170,13 +2566,13 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid
                                             &textBefore , &textAfter, &textAscent , &textDescent );
 
         if ( height )
-            *height = FixedToInt(textAscent + textDescent);
+            *height = FixedToFloat(textAscent + textDescent);
         if ( descent )
-            *descent = FixedToInt(textDescent);
+            *descent = FixedToFloat(textDescent);
         if ( externalLeading )
             *externalLeading = 0;
         if ( width )
-            *width = FixedToInt(textAfter - textBefore);
+            *width = FixedToFloat(textAfter - textBefore);
 
         ::ATSUDisposeTextLayout(atsuLayout);
 
@@ -2188,18 +2584,20 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid
 
     wxCFStringRef text(str, wxLocale::GetSystemEncoding() );
     CGSize sz = MeasureTextInContext( fref->GetUIFont() , text.AsNSString() );
-    
+
     if ( height )
         *height = sz.height;
         /*
     if ( descent )
-        *descent = FixedToInt(textDescent);
+        *descent = FixedToFloat(textDescent);
     if ( externalLeading )
         *externalLeading = 0;
         */
     if ( width )
         *width = sz.width;
 #endif
+    
+    CheckInvariants();    
 }
 
 void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const
@@ -2207,13 +2605,15 @@ 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 wxOSX_USE_CORE_TEXT
     {
         wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData();
-        CTFontRef font = fref->GetCTFont();
+        CTFontRef font = fref->OSXGetCTFont();
 
         wxCFStringRef t(text, wxLocale::GetSystemEncoding() );
         CFStringRef keys[] = { kCTFontAttributeName  };
@@ -2226,7 +2626,7 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr
         int chars = text.length();
         for ( int pos = 0; pos < (int)chars; pos ++ )
         {
-            widths[pos] = CTLineGetOffsetForStringIndex( line, pos+1 , NULL )+0.5;
+            widths[pos] = CTLineGetOffsetForStringIndex( line, pos+1 , NULL );
         }
 
         return;
@@ -2262,13 +2662,13 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr
             if (result != noErr || actualNumberOfBounds != 1 )
                 return;
 
-            widths[pos] = FixedToInt( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
+            widths[pos] = FixedToFloat( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
             //unsigned char uch = s[i];
         }
 #else
         ATSLayoutRecord *layoutRecords = NULL;
         ItemCount glyphCount = 0;
-        
+
         // Get the glyph extents
         OSStatus err = ::ATSUDirectGetLayoutDataArrayPtrFromTextLayout(atsuLayout,
                                                                        0,
@@ -2277,15 +2677,15 @@ 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 ++ )
             {
-                widths[pos-1] = FixedToInt( layoutRecords[pos].realPos );
+                widths[pos-1] = FixedToFloat( layoutRecords[pos].realPos );
             }
         }
-        
+
         ::ATSUDirectReleaseLayoutDataArrayPtr(NULL,
                                               kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
                                               (void **) &layoutRecords);
@@ -2296,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()
@@ -2303,18 +2705,50 @@ void * wxMacCoreGraphicsContext::GetNativeContext()
     return m_cgContext;
 }
 
+
+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() )
+    {
+        ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->Apply(this);
+        CGContextFillRect(m_cgContext, rect);
+    }
+    
+    wxQuartzOffsetHelper helper( m_cgContext , ShouldOffset() );
+    if ( !m_pen.IsNull() )
+    {
+        ((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->Apply(this);
+        CGContextStrokeRect(m_cgContext, rect);
+    }
+}
+
 // concatenates this transform with the current transform of this context
 void wxMacCoreGraphicsContext::ConcatTransform( const wxGraphicsMatrix& matrix )
 {
     if ( m_cgContext )
         CGContextConcatCTM( m_cgContext, *(CGAffineTransform*) matrix.GetNativeMatrix());
     else
-        m_windowTransform = CGAffineTransformConcat(m_windowTransform, *(CGAffineTransform*) matrix.GetNativeMatrix());
+        m_windowTransform = CGAffineTransformConcat(*(CGAffineTransform*) matrix.GetNativeMatrix(), m_windowTransform);
 }
 
 // sets the transform of this context
 void wxMacCoreGraphicsContext::SetTransform( const wxGraphicsMatrix& matrix )
 {
+    CheckInvariants();
     if ( m_cgContext )
     {
         CGAffineTransform transform = CGContextGetCTM( m_cgContext );
@@ -2326,6 +2760,7 @@ void wxMacCoreGraphicsContext::SetTransform( const wxGraphicsMatrix& matrix )
     {
         m_windowTransform = *(CGAffineTransform*) matrix.GetNativeMatrix();
     }
+    CheckInvariants();
 }
 
 // gets the matrix of this context
@@ -2337,6 +2772,49 @@ wxGraphicsMatrix wxMacCoreGraphicsContext::GetTransform() const
     return m;
 }
 
+
+#if wxUSE_IMAGE
+
+// ----------------------------------------------------------------------------
+// wxMacCoreGraphicsImageContext
+// ----------------------------------------------------------------------------
+
+// This is a GC that can be used to draw on wxImage. In this implementation we
+// simply draw on a wxBitmap using wxMemoryDC and then convert it to wxImage in
+// the end so it's not especially interesting and exists mainly for
+// compatibility with the other platforms.
+class wxMacCoreGraphicsImageContext : public wxMacCoreGraphicsContext
+{
+public:
+    wxMacCoreGraphicsImageContext(wxGraphicsRenderer* renderer,
+                                  wxImage& image) :
+        wxMacCoreGraphicsContext(renderer),
+        m_image(image),
+        m_bitmap(image),
+        m_memDC(m_bitmap)
+    {
+        SetNativeContext
+        (
+            (CGContextRef)(m_memDC.GetGraphicsContext()->GetNativeContext())
+        );
+        m_width = image.GetWidth();
+        m_height = image.GetHeight();
+    }
+
+    virtual ~wxMacCoreGraphicsImageContext()
+    {
+        m_memDC.SelectObject(wxNullBitmap);
+        m_image = m_bitmap.ConvertToImage();
+    }
+
+private:
+    wxImage& m_image;
+    wxBitmap m_bitmap;
+    wxMemoryDC m_memDC;
+};
+
+#endif // wxUSE_IMAGE
+
 //
 // Renderer
 //
@@ -2366,6 +2844,10 @@ public :
 
     virtual wxGraphicsContext * CreateContext( wxWindow* window );
 
+#if wxUSE_IMAGE
+    virtual wxGraphicsContext * CreateContextFromImage(wxImage& image);
+#endif // wxUSE_IMAGE
+
     virtual wxGraphicsContext * CreateMeasuringContext();
 
     // Path
@@ -2382,21 +2864,35 @@ public :
 
     virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) ;
 
-    // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
-    virtual wxGraphicsBrush CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
-        const wxColour&c1, const wxColour&c2) ;
+    virtual wxGraphicsBrush
+    CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
+                              wxDouble x2, wxDouble y2,
+                              const wxGraphicsGradientStops& stops);
 
-    // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
-    // with radius r and color cColor
-    virtual wxGraphicsBrush CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
-        const wxColour &oColor, const wxColour &cColor) ;
+    virtual wxGraphicsBrush
+    CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
+                              wxDouble xc, wxDouble yc,
+                              wxDouble radius,
+                              const wxGraphicsGradientStops& stops);
 
    // sets the font
     virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ;
+    virtual wxGraphicsFont CreateFont(double sizeInPixels,
+                                      const wxString& facename,
+                                      int flags = wxFONTFLAG_DEFAULT,
+                                      const wxColour& col = *wxBLACK);
 
     // create a native bitmap representation
     virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) ;
 
+#if wxUSE_IMAGE
+    virtual wxGraphicsBitmap CreateBitmapFromImage(const wxImage& image);
+    virtual wxImage CreateImageFromBitmap(const wxGraphicsBitmap& bmp);
+#endif // wxUSE_IMAGE
+
+    // create a graphics bitmap from a native bitmap
+    virtual wxGraphicsBitmap CreateBitmapFromNativeBitmap( void* bitmap );
+
     // create a native bitmap representation
     virtual wxGraphicsBitmap CreateSubBitmap( const wxGraphicsBitmap &bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h  ) ;
 private :
@@ -2416,10 +2912,6 @@ wxGraphicsRenderer* wxGraphicsRenderer::GetDefaultRenderer()
     return &gs_MacCoreGraphicsRenderer;
 }
 
-#if defined( __WXCOCOA__ ) || wxOSX_USE_COCOA
-extern CGContextRef wxMacGetContextFromCurrentNSContext() ;
-#endif
-
 wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxWindowDC& dc )
 {
     const wxDCImpl* impl = dc.GetImpl();
@@ -2429,12 +2921,17 @@ 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());
+
+        // having a cgctx being NULL is fine (will be created on demand)
+        // this is the case for all wxWindowDCs except wxPaintDC
+        wxMacCoreGraphicsContext *context = 
+            new wxMacCoreGraphicsContext( this, cgctx, (wxDouble) w, (wxDouble) h );
+        context->EnableOffset(true);
+        return context;
     }
     return NULL;
 }
@@ -2448,8 +2945,10 @@ wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxMemoryDC&
     {
         int w, h;
         mem_impl->GetSize( &w, &h );
-        return new wxMacCoreGraphicsContext( this,
+        wxMacCoreGraphicsContext* context = new wxMacCoreGraphicsContext( this,
             (CGContextRef)(mem_impl->GetGraphicsContext()->GetNativeContext()), (wxDouble) w, (wxDouble) h );
+        context->EnableOffset(true);
+        return context;
     }
 #endif
     return NULL;
@@ -2481,8 +2980,11 @@ wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeContext( v
 wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeWindow( void * window )
 {
 #if wxOSX_USE_CARBON
-    return new wxMacCoreGraphicsContext(this,(WindowRef)window);
+    wxMacCoreGraphicsContext* context = new wxMacCoreGraphicsContext(this,(WindowRef)window);
+    context->EnableOffset(true);
+    return context;
 #else
+    wxUnusedVar(window);
     return NULL;
 #endif
 }
@@ -2497,6 +2999,16 @@ wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateMeasuringContext()
     return new wxMacCoreGraphicsContext(this);
 }
 
+#if wxUSE_IMAGE
+
+wxGraphicsContext*
+wxMacCoreGraphicsRenderer::CreateContextFromImage(wxImage& image)
+{
+    return new wxMacCoreGraphicsImageContext(this, image);
+}
+
+#endif // wxUSE_IMAGE
+
 // Path
 
 wxGraphicsPath wxMacCoreGraphicsRenderer::CreatePath()
@@ -2521,7 +3033,7 @@ wxGraphicsMatrix wxMacCoreGraphicsRenderer::CreateMatrix( wxDouble a, wxDouble b
 
 wxGraphicsPen wxMacCoreGraphicsRenderer::CreatePen(const wxPen& pen)
 {
-    if ( !pen.Ok() || pen.GetStyle() == wxTRANSPARENT )
+    if ( !pen.IsOk() || pen.GetStyle() == wxTRANSPARENT )
         return wxNullGraphicsPen;
     else
     {
@@ -2533,7 +3045,7 @@ wxGraphicsPen wxMacCoreGraphicsRenderer::CreatePen(const wxPen& pen)
 
 wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateBrush(const wxBrush& brush )
 {
-    if ( !brush.Ok() || brush.GetStyle() == wxTRANSPARENT )
+    if ( !brush.IsOk() || brush.GetStyle() == wxTRANSPARENT )
         return wxNullGraphicsBrush;
     else
     {
@@ -2545,12 +3057,44 @@ wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateBrush(const wxBrush& brush )
 
 wxGraphicsBitmap wxMacCoreGraphicsRenderer::CreateBitmap( const wxBitmap& bmp )
 {
-    if ( bmp.Ok() )
+    if ( bmp.IsOk() )
     {
         wxGraphicsBitmap p;
-#ifdef __WXMAC__
         p.SetRefData(new wxMacCoreGraphicsBitmapData( this , bmp.CreateCGImage(), bmp.GetDepth() == 1 ) );
-#endif
+        return p;
+    }
+    else
+        return wxNullGraphicsBitmap;
+}
+
+#if wxUSE_IMAGE
+
+wxGraphicsBitmap
+wxMacCoreGraphicsRenderer::CreateBitmapFromImage(const wxImage& image)
+{
+    // We don't have any direct way to convert wxImage to CGImage so pass by
+    // wxBitmap. This makes this function pretty useless in this implementation
+    // but it allows to have the same API as with Cairo backend where we can
+    // convert wxImage to a Cairo surface directly, bypassing wxBitmap.
+    return CreateBitmap(wxBitmap(image));
+}
+
+wxImage wxMacCoreGraphicsRenderer::CreateImageFromBitmap(const wxGraphicsBitmap& bmp)
+{
+    wxMacCoreGraphicsBitmapData* const
+        data = static_cast<wxMacCoreGraphicsBitmapData*>(bmp.GetRefData());
+
+    return data ? data->ConvertToImage() : wxNullImage;
+}
+
+#endif // wxUSE_IMAGE
+
+wxGraphicsBitmap wxMacCoreGraphicsRenderer::CreateBitmapFromNativeBitmap( void* bitmap )
+{
+    if ( bitmap != NULL )
+    {
+        wxGraphicsBitmap p;
+        p.SetRefData(new wxMacCoreGraphicsBitmapData( this , (CGImageRef) bitmap, false ));
         return p;
     }
     else
@@ -2572,33 +3116,34 @@ wxGraphicsBitmap wxMacCoreGraphicsRenderer::CreateSubBitmap( const wxGraphicsBit
         return wxNullGraphicsBitmap;
 }
 
-// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
-wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
-    const wxColour&c1, const wxColour&c2)
+wxGraphicsBrush
+wxMacCoreGraphicsRenderer::CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
+                                                     wxDouble x2, wxDouble y2,
+                                                     const wxGraphicsGradientStops& stops)
 {
     wxGraphicsBrush p;
     wxMacCoreGraphicsBrushData* d = new wxMacCoreGraphicsBrushData( this );
-    d->CreateLinearGradientBrush(x1, y1, x2, y2, c1, c2);
+    d->CreateLinearGradientBrush(x1, y1, x2, y2, stops);
     p.SetRefData(d);
     return p;
 }
 
-// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
-// with radius r and color cColor
-wxGraphicsBrush wxMacCoreGraphicsRenderer::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
-    const wxColour &oColor, const wxColour &cColor)
+wxGraphicsBrush
+wxMacCoreGraphicsRenderer::CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
+                                                     wxDouble xc, wxDouble yc,
+                                                     wxDouble radius,
+                                                     const wxGraphicsGradientStops& stops)
 {
     wxGraphicsBrush p;
     wxMacCoreGraphicsBrushData* d = new wxMacCoreGraphicsBrushData( this );
-    d->CreateRadialGradientBrush(xo,yo,xc,yc,radius,oColor,cColor);
+    d->CreateRadialGradientBrush(xo, yo, xc, yc, radius, stops);
     p.SetRefData(d);
     return p;
 }
 
-// sets the font
 wxGraphicsFont wxMacCoreGraphicsRenderer::CreateFont( const wxFont &font , const wxColour &col )
 {
-    if ( font.Ok() )
+    if ( font.IsOk() )
     {
         wxGraphicsFont p;
         p.SetRefData(new wxMacCoreGraphicsFontData( this , font, col ));
@@ -2608,6 +3153,32 @@ wxGraphicsFont wxMacCoreGraphicsRenderer::CreateFont( const wxFont &font , const
         return wxNullGraphicsFont;
 }
 
+wxGraphicsFont
+wxMacCoreGraphicsRenderer::CreateFont(double sizeInPixels,
+                                      const wxString& facename,
+                                      int flags,
+                                      const wxColour& col)
+{
+    // This implementation is not ideal as we don't support fractional font
+    // sizes right now, but it's the simplest one.
+    //
+    // Notice that under Mac we always use 72 DPI so the font size in pixels is
+    // the same as the font size in points and we can pass it directly to wxFont
+    // ctor.
+    wxFont font(wxRound(sizeInPixels),
+                wxFONTFAMILY_DEFAULT,
+                flags & wxFONTFLAG_ITALIC ? wxFONTSTYLE_ITALIC
+                                          : wxFONTSTYLE_NORMAL,
+                flags & wxFONTFLAG_BOLD ? wxFONTWEIGHT_BOLD
+                                        : wxFONTWEIGHT_NORMAL,
+                (flags & wxFONTFLAG_UNDERLINED) != 0,
+                facename);
+
+    wxGraphicsFont f;
+    f.SetRefData(new wxMacCoreGraphicsFontData(this, font, col));
+    return f;
+}
+
 //
 // CoreGraphics Helper Methods
 //