]> git.saurik.com Git - wxWidgets.git/commitdiff
finished implementation for stencil and colored patterns
authorStefan Csomor <csomor@advancedconcepts.ch>
Sat, 5 Nov 2005 16:53:42 +0000 (16:53 +0000)
committerStefan Csomor <csomor@advancedconcepts.ch>
Sat, 5 Nov 2005 16:53:42 +0000 (16:53 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@36092 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/mac/carbon/dccg.cpp

index eaaa2f179cfdb301401f576d28e515cefff7d064..67375d25db458ab5968c4108ee6b539f2398e4e8 100755 (executable)
@@ -304,208 +304,189 @@ void wxMacCGContext::SetNativeContext( CGContextRef cg )
 
 #pragma mark -
 
-// Experimental support for dashes and patterned brushes
-// uncomment the following lines to enable it
+// wrapper class for a CGPattern, always allocate on heap, never call destructor
 
-// #define _NEW_GC_DASHES_
-// #define _NEW_GC_SUPPORT_
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
-#define kCGColorSpaceGenericRGB   CFSTR("kCGColorSpaceGenericRGB")
-#endif
-
-void EstablishPatternColorSpace(
-       CGContextRef            ctxRef,
-       bool                            useMultibit,
-       bool                            useFill )
-{
-       CGColorSpaceRef baseSpace, patternSpace;
-
-       if (ctxRef == NULL)
-               return;
-
-       baseSpace = NULL;
-       patternSpace = NULL;
-
-       if (useMultibit)
-       {
-               patternSpace = CGColorSpaceCreatePattern( NULL );
-
-               if (useFill)
-                       CGContextSetFillColorSpace( ctxRef, patternSpace );
-               else
-                       CGContextSetStrokeColorSpace( ctxRef, patternSpace );
-       }
-       else
-       {
-               baseSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericRGB );
-               patternSpace = CGColorSpaceCreatePattern( baseSpace );
-
-               if (useFill)
-                       CGContextSetFillColorSpace( ctxRef, patternSpace );
-               else
-                       CGContextSetStrokeColorSpace( ctxRef, patternSpace );
-       }
-
-       // NB: the context owns these now, and this code is finished with them
-       if (patternSpace != NULL)
-               CGColorSpaceRelease( patternSpace );
-       if (baseSpace != NULL)
-               CGColorSpaceRelease( baseSpace );
-}
-
-void ImagePatternRender(
-       void                    *info,
-       CGContextRef    ctxRef )
-{
-       if (ctxRef == NULL)
-               return;
-
-       CGImageRef      imageRef = (CGImageRef)info;
-       if (imageRef != NULL)
-       {
-               CGRect  boundsR = CGRectMake( 0.0, 0.0, (float)CGImageGetWidth( imageRef ), (float)CGImageGetHeight( imageRef ) );
-               CGContextDrawImage( ctxRef, boundsR, imageRef );
-       }
-}
-
-void ImagePatternDispose(
-       void            *info )
-{
-       CGImageRef      imageRef = (CGImageRef)info;
-       if (imageRef != NULL)
-               CGImageRelease( imageRef );
-}
-
-// specifies the struct version value and the callback functions for draw and release
-static const CGPatternCallbacks sImagePatternCallback = { 0, &ImagePatternRender, &ImagePatternDispose };
-
-long CreatePatternFromBitmap(
-       CGPatternRef            *patternRef,
-       const wxBitmap  *rasterInfo,
-       bool                            useMultibit )
-{
-       CGRect          boundsR;
-       CGImageRef      imageRef;
-       long                    errorStatus, widthV, heightV, depthV;
-
-       if (patternRef == NULL)
-               return (-1);
-
-       *patternRef = NULL;
-       imageRef = NULL;
-       errorStatus = 0;
-
-       if ((rasterInfo == NULL) || !rasterInfo->Ok())
-               errorStatus = (-2);
-
-       if (errorStatus == 0)
-       {
-               // build a usable bounding CGRect from the wxBitmap's bounds wxRect
-               widthV = rasterInfo->GetWidth();
-               heightV = rasterInfo->GetHeight();
-               if ((widthV <= 0) || (heightV <= 0))
-                       errorStatus = (-3);
-       }
-
-       if (errorStatus == 0)
-       {
-               depthV = rasterInfo->GetDepth();
-//             isColored = (depthV > 1);
-
-               // FIXME: this is often <= 0 - why???
-//             if (depthV <= 1)
-//                     errorStatus = (-4);
-       }
-
-       if (errorStatus == 0)
-       {
-               imageRef = (CGImageRef)(rasterInfo->CGImageCreate());
-               if (imageRef == NULL)
-                       errorStatus = (-5);
-       }
-
-       if (errorStatus == 0)
-       {
-               // FIXME: switch when this routine belongs to a DC class...
-               boundsR = CGRectMake( 0.0, 0.0, (float)widthV, (float)heightV );
-//             boundsR = CGRectMake( 0.0, 0.0, (float)XLOG2DEVREL( widthV ), (float)XLOG2DEVREL( heightV ) );
-
-               *patternRef = CGPatternCreate(
-                       (void*)imageRef,
-                       boundsR,
-                       CGAffineTransformIdentity,
-                       boundsR.size.width,
-                       boundsR.size.height,
-                       kCGPatternTilingNoDistortion,
-                       (int)useMultibit,
-                       &sImagePatternCallback );
-
-               if (*patternRef == (CGPatternRef)NULL)
-                       errorStatus = (-6);
-       }
-
-       return errorStatus;
-}
-
-long CreatePatternFromDashes(
-       CGPatternRef    *patternRef,
-       const wxDash    *sourceDash,
-       int                     count,
-       bool                    useMultibit )
+class wxMacCGPattern
 {
-       long            errorStatus;
-
-       if (patternRef == NULL)
-               return (-1);
+public :
+    wxMacCGPattern()
+    {
+    }
+    
+    // is guaranteed to be called only with a non-Null CGContextRef
+    virtual void Render( CGContextRef  ctxRef ) = 0 ;
 
-       *patternRef = NULL;
-       if ((sourceDash == NULL) || (count <= 0))
-               return (-2);
+    operator CGPatternRef() const { return m_patternRef ; }
+protected :
+    virtual ~wxMacCGPattern()
+    {
+        // as this is called only when our m_patternRef is been released, don't release
+        // it again
+    }
+    
+    static void _Render( void *info, CGContextRef ctxRef )
+    {
+        wxMacCGPattern* self = (wxMacCGPattern*) info ;
+        if ( self && ctxRef )
+            self->Render( ctxRef ) ;
+    }
+    
+    static void _Dispose( void *info )
+    {
+        wxMacCGPattern* self = (wxMacCGPattern*) info ;
+        delete self ;
+    }
+    
+    CGPatternRef m_patternRef ;
 
-       wxBitmap                dashBits( (char*)sourceDash, 8, count, 1 );
-       errorStatus = CreatePatternFromBitmap( patternRef, &dashBits, useMultibit );
+    static const CGPatternCallbacks ms_Callbacks ;
+;
 
-       return errorStatus;
-}
+const CGPatternCallbacks wxMacCGPattern::ms_Callbacks = { 0, &wxMacCGPattern::_Render, &wxMacCGPattern::_Dispose };
 
-long CreatePatternFromBrush(
-       CGPatternRef    *patternRef,
-       const wxBrush   &sourceBrush,
-       bool                    useMultibit )
+class ImagePattern : public wxMacCGPattern
 {
-       long            errorStatus;
-
-       if (patternRef == NULL)
-               return (-1);
-
-       *patternRef = NULL;
-       errorStatus = CreatePatternFromBitmap( patternRef, sourceBrush.GetStipple(), useMultibit );
+public :
+    ImagePattern( const wxBitmap* bmp  , CGAffineTransform transform )
+    {
+        wxASSERT( bmp && bmp->Ok() ) ;
+        Init( (CGImageRef) bmp->CGImageCreate() , transform ) ;
+    }
+    
+    // ImagePattern takes ownership of CGImageRef passed in
+    ImagePattern( CGImageRef image , CGAffineTransform transform )
+    {
+        if ( image )
+        {
+            CFRetain( image ) ;
+        }
+        Init( image , transform ) ;
+    }
+    
+    virtual void Render( CGContextRef  ctxRef )
+    {
+        if (m_image != NULL)
+            HIViewDrawCGImage( ctxRef, &m_imageBounds, m_image );
+    }
 
-       return errorStatus;
-}
+protected :
+    void Init( CGImageRef image , CGAffineTransform transform )
+    {
+        m_image = image ;
+        if ( m_image )
+        {
+            m_imageBounds = CGRectMake( 0.0, 0.0, (float)CGImageGetWidth( m_image  ), (float)CGImageGetHeight( m_image ) ) ;
+            m_patternRef = CGPatternCreate( this , m_imageBounds, transform ,
+                                            m_imageBounds.size.width, m_imageBounds.size.height,
+                                            kCGPatternTilingNoDistortion, true , &wxMacCGPattern::ms_Callbacks ) ;
+        }
+    }
+    
+    ~ImagePattern()
+    {
+        if ( m_image )
+            CGImageRelease( m_image ) ;
+    }
+    CGImageRef  m_image ;
+    CGRect      m_imageBounds ;
+} ;
 
-long CreatePatternFromPen(
-       CGPatternRef    *patternRef,
-       const wxPen     &sourcePen,
-       bool                    useMultibit )
+class HatchPattern : public wxMacCGPattern
 {
-       long            errorStatus;
-
-       if (patternRef == NULL)
-               return (-1);
-
-       *patternRef = NULL;
-       errorStatus = CreatePatternFromBitmap( patternRef, sourcePen.GetStipple(), useMultibit );
-
-       return errorStatus;
-}
-
-// ------------
-#pragma mark -
+public :
+    HatchPattern( int hatchstyle  , CGAffineTransform transform )
+    {
+        m_hatch = hatchstyle ;
+        m_imageBounds = CGRectMake( 0.0, 0.0, 8.0 , 8.0 ) ;
+        m_patternRef = CGPatternCreate( this , m_imageBounds, transform ,
+                                            m_imageBounds.size.width, m_imageBounds.size.height,
+                                            kCGPatternTilingNoDistortion, false , &wxMacCGPattern::ms_Callbacks ) ;
+    }
+        
+    void StrokeLineSegments( CGContextRef ctxRef , const CGPoint pts[] , size_t count )
+    {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+        if ( UMAGetSystemVersion() >= 0x1040 )
+        {
+            CGContextStrokeLineSegments( ctxRef , pts , count ) ;
+        }
+        else
+#endif
+        {
+            CGContextBeginPath (ctxRef);
+            for (size_t i = 0; i < count; i += 2) {
+                CGContextMoveToPoint(ctxRef, pts[i].x, pts[i].y);
+                CGContextAddLineToPoint(ctxRef, pts[i+1].x, pts[i+1].y);
+            }
+            CGContextStrokePath(ctxRef);
+        }
+    }
+    
+    virtual void Render( CGContextRef  ctxRef )
+    {
+        switch( m_hatch )
+        {
+            case wxBDIAGONAL_HATCH :
+                {
+                    CGPoint pts[] = { 
+                    { 8.0 , 0.0 } , { 0.0 , 8.0 } 
+                    };
+                    StrokeLineSegments( ctxRef , pts , 2 ) ;
+                }
+                break ;
+            case wxCROSSDIAG_HATCH :
+                {
+                    CGPoint pts[] = { 
+                        { 0.0 , 0.0 } , { 8.0 , 8.0 } , 
+                        { 8.0 , 0.0 } , { 0.0 , 8.0 } 
+                    };
+                    StrokeLineSegments( ctxRef , pts , 4 ) ;
+                }
+                break ;
+            case wxFDIAGONAL_HATCH :
+                {
+                    CGPoint pts[] = { 
+                    { 0.0 , 0.0 } , { 8.0 , 8.0 } 
+                    };
+                    StrokeLineSegments( ctxRef , pts , 2 ) ;
+                }
+                break ;
+            case wxCROSS_HATCH :
+                {
+                    CGPoint pts[] = { 
+                    { 0.0 , 4.0 } , { 8.0 , 4.0 } , 
+                    { 4.0 , 0.0 } , { 4.0 , 8.0 } , 
+                    };
+                    StrokeLineSegments( ctxRef , pts , 4 ) ;
+                }
+                break ;
+            case wxHORIZONTAL_HATCH :
+                {
+                    CGPoint pts[] = { 
+                    { 0.0 , 4.0 } , { 8.0 , 4.0 } , 
+                    };
+                    StrokeLineSegments( ctxRef , pts , 2 ) ;
+                }
+                break ;
+            case wxVERTICAL_HATCH :
+                {
+                    CGPoint pts[] = { 
+                    { 4.0 , 0.0 } , { 4.0 , 8.0 } , 
+                    };
+                    StrokeLineSegments( ctxRef , pts , 2 ) ;
+                }
+                break ;
+        }
+    }
+    
+protected :
+    ~HatchPattern()
+    {
+    }
+    int         m_hatch ;
+    CGRect      m_imageBounds ;
+} ;
 
-// FIXME: the NEW_GC_SUPPORT part this routine is unfinished and needs lots of work !!
-//
 void wxMacCGContext::SetPen( const wxPen &pen )
 {
     m_pen = pen ;
@@ -529,55 +510,14 @@ void wxMacCGContext::SetPen( const wxPen &pen )
         }
         if ( stroke )
         {
-#if defined(_NEW_GC_SUPPORT_)
-            // new candidate
-            {
-                CGPatternRef  patternRef;
-                float  alphaArray[1];
-                long  result;
-                bool  hasSetPattern, useMultibit;
-
-                hasSetPattern = false;
-                useMultibit = true;
-                result = CreatePatternFromPen( &patternRef, pen, useMultibit );
-                if (result == 0)
-                {
-                    EstablishPatternColorSpace( m_cgContext, useMultibit, false );
-
-                    alphaArray[0] = 1.0;
-                    CGContextSetStrokePattern( m_cgContext, patternRef, alphaArray );
-                    CGPatternRelease( patternRef );
-
-                    hasSetPattern = true;
-
-//wxLogDebug( wxT("CreatePatternFromPen succeeded!") );
-                }
-
-                // NB: the (-2) result is from wxPen instances that don't have a stipple wxBitmap
-                if (result < (-2))
-                    wxLogDebug( wxT("CreatePatternFromPen failed: result [%ld]"), result );
-
-                if (!hasSetPattern)
-                {
-                    RGBColor col;
-
-#if 1
-                    col = MAC_WXCOLORREF( pen.GetColour().GetPixel() );
-#else
-                    GetThemeBrushAsColor( pen.MacGetTheme(), 32, true, &col );
-#endif
-
-                    CGContextSetRGBStrokeColor(
-                        m_cgContext, (float) col.red / 65536.0,
-                        (float) col.green / 65536.0, (float) col.blue / 65536.0, 1.0 );
-                }
-            }
-
-#else
-            // original implementation
             RGBColor col = MAC_WXCOLORREF( pen.GetColour().GetPixel() ) ;
             CGContextSetRGBStrokeColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
-#endif
+
+            /* TODO * m_dc->m_scaleX */
+            float penWidth = pen.GetWidth();
+            if (penWidth <= 0.0)
+                penWidth = 0.1;
+            CGContextSetLineWidth( m_cgContext , penWidth ) ;
             
             CGLineCap cap ;
             switch( pen.GetCap() )
@@ -595,7 +535,6 @@ void wxMacCGContext::SetPen( const wxPen &pen )
                     cap = kCGLineCapButt ;
                     break ;
             }
-            CGContextSetLineCap( m_cgContext , cap ) ;
 
             CGLineJoin join ;
             switch( pen.GetJoin() )
@@ -615,91 +554,20 @@ void wxMacCGContext::SetPen( const wxPen &pen )
             }
             CGContextSetLineJoin( m_cgContext , join ) ;
 
-            /* TODO * m_dc->m_scaleX */
-            float penWidth = pen.GetWidth();
-            if (penWidth <= 0.0)
-                penWidth = 0.1;
-            CGContextSetLineWidth( m_cgContext , penWidth ) ; 
-
             m_mode = kCGPathStroke ;
             int count = 0 ;
+            
+            const float *lengths = NULL ;
+            float *userLengths = NULL ;
 
-#if defined(_NEW_GC_DASHES_)
-            const char *dashData = NULL ;
-            char *userDashData = NULL ;
-            float  alphaArray[1];
-
-            const char dotted[] = { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 };
-            const char dashed[] = { 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00 };
-            const char short_dashed[] = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 };
-            const char dotted_dashed[] = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00 };
-
-            switch (pen.GetStyle())
-            {
-                case wxSOLID:
-                    // default, undashed pen
-                    break;
-
-                case wxDOT:
-                    dashData = dotted;
-                    count = WXSIZEOF(dotted);
-                    break;
-                case wxLONG_DASH:
-                    dashData = dashed;
-                    count = WXSIZEOF(dashed);
-                    break;
-                case wxSHORT_DASH:
-                    dashData = short_dashed;
-                    count = WXSIZEOF(short_dashed);
-                    break;
-                case wxDOT_DASH:
-                    dashData = dotted_dashed;
-                    count = WXSIZEOF(dotted_dashed);
-                    break;
-                case wxUSER_DASH:
-                    count = pen.GetDashes( (wxDash**)&userDashData );
-                    dashData = userDashData;
-                    break;
-
-                default :
-                    break; 
-            }
-
-            if ((dashData != NULL) && (count > 0))
-            {
-                CGPatternRef  patternRef;
-                RGBColor col;
-                long  result;
-                bool  useMultibit;
-
-                    useMultibit = true;
-                    result = CreatePatternFromDashes( &patternRef, (const wxDash*)dashData, count, useMultibit );
-                    if (result == 0)
-                    {
-                        col = MAC_WXCOLORREF( pen.GetColour().GetPixel() );
-                        CGContextSetRGBStrokeColor(
-                            m_cgContext, (float) col.red / 65536.0,
-                            (float) col.green / 65536.0, (float) col.blue / 65536.0, 1.0 );
+            int dashUnit = ( penWidth < 1.0 ) ? 1.0 : penWidth;
+  
+            const float dotted[] = { dashUnit  , dashUnit + 2.0 };
+            const float short_dashed[] = { 9.0 , 6.0 };
+            const float dashed[] = { 19.0 , 9.0 };
+            const float dotted_dashed[] = { 9.0 , 6.0 , 3.0 , 3.0 };
 
-                        EstablishPatternColorSpace( m_cgContext, useMultibit, false );
 
-                        alphaArray[0] = 1.0;
-                        CGContextSetStrokePattern( m_cgContext, patternRef, alphaArray );
-                        CGPatternRelease( patternRef );
-                    }
-                if (result != 0)
-                    wxLogDebug( wxT("CreatePatternFromDashes failed: result [%ld]"), result );
-           }
-#else
-            const float *lengths = NULL ;
-            float *userLengths = NULL ;
-            
-            const float dotted[] = { 3 , 3 };
-            const float dashed[] = { 19 , 9 };
-            const float short_dashed[] = { 9 , 6 };
-            const float dotted_dashed[] = { 9 , 6 , 3 , 3 };
-            
             switch( pen.GetStyle() )
             {
                 case wxSOLID :
@@ -728,34 +596,56 @@ void wxMacCGContext::SetPen( const wxPen &pen )
                         userLengths = new float[count] ;
                         for( int i = 0 ; i < count ; ++i )
                         {
-                            userLengths[i] = (float)dashes[i] ;
-                            if (userLengths[i] <= 0.0)
-                            {
-                                userLengths[i] = 1.0;
-//                                wxLogDebug( wxT("wxMacCGContext::SetPen - bad dash length[%d] [%.2f]"), i, (float)dashes[i] );
-                            }
+                            userLengths[i] = (float)dashes[i] * dashUnit ;
+
+                            if ( i % 2 == 1 && userLengths[i] < dashUnit + 2.0 )
+                                userLengths[i] = dashUnit + 2.0 ;
+                            else if ( i % 2 == 0 && userLengths[i] < dashUnit )
+                                userLengths[i] = dashUnit ;
                         }
                     }
                     lengths = userLengths ;
                     break ;
+                case wxSTIPPLE :
+                    {
+                        float  alphaArray[1] = { 1.0 } ;
+                        wxBitmap* bmp = pen.GetStipple() ;
+                        if ( bmp && bmp->Ok() ) 
+                        {
+                            wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( NULL ) ) ;
+                            CGContextSetStrokeColorSpace( m_cgContext , patternSpace ) ;
+                            wxMacCFRefHolder<CGPatternRef> pattern( *( new ImagePattern( bmp , CGContextGetCTM( m_cgContext ) ) ) );
+                            CGContextSetStrokePattern( m_cgContext, pattern , alphaArray ) ;
+                        }
+                    }
+                    break ;
                 default :
+                    {
+                        wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ) ;
+                        CGContextSetStrokeColorSpace( m_cgContext , patternSpace ) ;
+                        wxMacCFRefHolder<CGPatternRef> pattern( *( new HatchPattern( pen.GetStyle() , CGContextGetCTM( m_cgContext ) ) ) );
+                        
+                        RGBColor col = MAC_WXCOLORREF( pen.GetColour().GetPixel() ) ;
+                        float  colorArray[4] = { col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 } ;
+                        
+                        CGContextSetStrokePattern( m_cgContext, pattern , colorArray ) ;
+                    }
                     break ; 
             }
 
             if ((lengths != NULL) && (count > 0))
             {
-                // we need to change the cap, otherwise everything overlaps
-                // and we get solid lines
                 CGContextSetLineDash( m_cgContext , 0 , lengths , count ) ;
-                CGContextSetLineCap( m_cgContext , kCGLineCapButt ) ;
+                // force the line cap, otherwise we get artifacts (overlaps) and just solid lines
+                cap = kCGLineCapButt ;
             }
             else 
             {
                CGContextSetLineDash( m_cgContext , 0 , NULL , 0 ) ;
             }
+            CGContextSetLineCap( m_cgContext , cap ) ;
 
             delete[] userLengths ;
-#endif
         }
         if ( fill && stroke )
         {
@@ -785,56 +675,35 @@ void wxMacCGContext::SetBrush( const wxBrush &brush )
 
         if ( fill )
         {
-#if defined(_NEW_GC_SUPPORT_)
-            // new candidate
+            if ( brush.GetStyle() == wxSOLID )
             {
-                CGPatternRef  patternRef;
-                float  alphaArray[1];
-                long  result;
-                bool  hasSetPattern, useMultibit;
-
-                hasSetPattern = false;
-                useMultibit = true;
-                result = CreatePatternFromBrush( &patternRef, brush, useMultibit );
-                if (result == 0)
-                {
-                    EstablishPatternColorSpace( m_cgContext, useMultibit, true );
-
-                    alphaArray[0] = 1.0;
-                    CGContextSetFillPattern( m_cgContext, patternRef, alphaArray );
-                    CGPatternRelease( patternRef );
-
-                    hasSetPattern = true;
-
-//wxLogDebug( wxT("CreatePatternFromBrush succeeded!") );
-                }
-
-                // NB: the (-2) result is from wxBrush instances that don't have a stipple wxBitmap
-                if (result < (-2))
-                    wxLogDebug( wxT("CreatePatternFromBrush failed: result [%ld]"), result );
-
-                if (!hasSetPattern)
+                RGBColor col = MAC_WXCOLORREF( brush.GetColour().GetPixel() ) ;
+                CGContextSetRGBFillColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
+            }
+            else if ( brush.IsHatch() )
+            {
+                wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ) ;
+                CGContextSetFillColorSpace( m_cgContext , patternSpace ) ;
+                wxMacCFRefHolder<CGPatternRef> pattern( *( new HatchPattern( brush.GetStyle() , CGContextGetCTM( m_cgContext ) ) ) );
+
+                RGBColor col = MAC_WXCOLORREF( brush.GetColour().GetPixel() ) ;
+                float  colorArray[4] = { col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 } ;
+                
+                CGContextSetFillPattern( m_cgContext, pattern , colorArray ) ;
+            }
+            else
+            {
+                // now brush is a bitmap
+                float  alphaArray[1] = { 1.0 } ;
+                wxBitmap* bmp = brush.GetStipple() ;
+                if ( bmp && bmp->Ok() ) 
                 {
-                    RGBColor col;
-
-#if 1
-                    col = MAC_WXCOLORREF( brush.GetColour().GetPixel() );
-#else
-                    GetThemeBrushAsColor( brush.MacGetTheme(), 32, true, &col );
-#endif
-
-                    CGContextSetRGBFillColor(
-                        m_cgContext, (float) col.red / 65536.0,
-                        (float) col.green / 65536.0, (float) col.blue / 65536.0, 1.0 );
+                    wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( NULL ) ) ;
+                    CGContextSetFillColorSpace( m_cgContext , patternSpace ) ;
+                    wxMacCFRefHolder<CGPatternRef> pattern( *( new ImagePattern( bmp , CGContextGetCTM( m_cgContext ) ) ) );
+                    CGContextSetFillPattern( m_cgContext, pattern , alphaArray ) ;
                 }
             }
-
-#else
-            // original implementation
-            RGBColor col = MAC_WXCOLORREF( brush.GetColour().GetPixel() ) ;
-            CGContextSetRGBFillColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
-#endif
-
             m_mode = kCGPathFill ;
         }
         if ( stroke )
@@ -888,8 +757,7 @@ wxDC::wxDC()
     m_colour = TRUE;
     m_mm_to_pix_x = mm2pt;
     m_mm_to_pix_y = mm2pt;
-    m_internalDeviceOriginX = 0;
-    m_internalDeviceOriginY = 0;
+
     m_externalDeviceOriginX = 0;
     m_externalDeviceOriginY = 0;
     m_logicalScaleX = 1.0;
@@ -1166,8 +1034,8 @@ void wxDC::ComputeScaleAndOrigin()
     double origScaleY = m_scaleY;
     m_scaleX = m_logicalScaleX * m_userScaleX;
     m_scaleY = m_logicalScaleY * m_userScaleY;
-    m_deviceOriginX = m_internalDeviceOriginX + m_externalDeviceOriginX;
-    m_deviceOriginY = m_internalDeviceOriginY + m_externalDeviceOriginY;
+    m_deviceOriginX = m_externalDeviceOriginX;
+    m_deviceOriginY = m_externalDeviceOriginY;
     // CMB: if scale has changed call SetPen to recalulate the line width
     if (m_scaleX != origScaleX || m_scaleY != origScaleY)
     {
@@ -1201,7 +1069,21 @@ void  wxDC::SetPen( const wxPen &pen )
     m_pen = pen;
     if ( m_graphicContext )
     {
-        m_graphicContext->SetPen( m_pen ) ;
+        if ( m_pen.GetStyle() == wxSOLID || m_pen.GetStyle() == wxTRANSPARENT )
+        {
+            m_graphicContext->SetPen( m_pen ) ;
+        }
+        else
+        {
+            // we have to compensate for moved device origins etc. otherwise patterned pens are standing still
+            // eg when using a wxScrollWindow and scrolling around
+            CGContextRef cgContext = ((wxMacCGContext*)(m_graphicContext))->GetNativeContext() ;
+            int origX = XLOG2DEVMAC(0) ;
+            int origY = YLOG2DEVMAC(0) ;
+            CGContextTranslateCTM (cgContext,origX,origY);
+            m_graphicContext->SetPen( m_pen ) ;
+            CGContextTranslateCTM (cgContext,-origX,-origY);
+        }
     }
 }
 
@@ -1212,7 +1094,21 @@ void  wxDC::SetBrush( const wxBrush &brush )
     m_brush = brush;
     if ( m_graphicContext )
     {
-        m_graphicContext->SetBrush( m_brush ) ;
+        if ( brush.GetStyle() == wxSOLID || brush.GetStyle() == wxTRANSPARENT )
+        {
+            m_graphicContext->SetBrush( m_brush ) ;
+        }
+        else
+        {
+            // we have to compensate for moved device origins etc. otherwise patterned brushes are standing still
+            // eg when using a wxScrollWindow and scrolling around
+            CGContextRef cgContext = ((wxMacCGContext*)(m_graphicContext))->GetNativeContext() ;
+            int origX = XLOG2DEVMAC(0) ;
+            int origY = YLOG2DEVMAC(0) ;
+            CGContextTranslateCTM (cgContext,origX,origY);
+            m_graphicContext->SetBrush( m_brush ) ;
+            CGContextTranslateCTM (cgContext,-origX,-origY);
+        }
     }
 }
 
@@ -1542,7 +1438,7 @@ void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
         yy = yy - hh;
     }
     wxGraphicPath* path = m_graphicContext->CreatePath() ;
-    path->AddRectangle(xx ,yy , ww , hh ) ;
+    path->AddRectangle( xx , yy , ww , hh ) ;
     m_graphicContext->DrawPath( path ) ;
     delete path ;
 }