]> git.saurik.com Git - wxWidgets.git/blobdiff - src/osx/carbon/graphics.cpp
Various typos fixes and minor build system changes. After a rebake wxMSW should now...
[wxWidgets.git] / src / osx / carbon / graphics.cpp
index 75f74d7de83b0ba18f39326451209b7511b904ba..2a3bf12a40c3579397c610049c83888577f72db9 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        src/osx/carbon/dccg.cpp
+// Name:        src/osx/carbon/graphics.cpp
 // Purpose:     wxDC class
 // Author:      Stefan Csomor
 // Modified by:
@@ -686,7 +686,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 )
@@ -731,15 +766,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;
 }
 
@@ -759,35 +791,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)
+    {
+        // 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
     {
-        out[i] = colors[i] + ( colors[4+i] - colors[i] ) * f;
+        // 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 wxGraphicsGradientStops& stops)
 {
-    // TODO: implement support for intermediate gradient stops
-    const wxColour c1 = stops.GetStartColour();
-    const wxColour c2 = stops.GetEndColour();
 
     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,
@@ -1015,7 +1082,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
@@ -1173,7 +1240,7 @@ 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, wxPolygonFillMode fillStyle = wxODDEVEN_RULE) const;
 private :
@@ -1323,9 +1390,6 @@ public:
 
     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();
@@ -1393,6 +1457,9 @@ public:
 
     virtual bool ShouldOffset() const
     {
+        if ( !m_enableOffset )
+            return false;
+        
         int penwidth = 0 ;
         if ( !m_pen.IsNull() )
         {
@@ -1439,8 +1506,6 @@ private:
 #endif
     bool m_contextSynthesized;
     CGAffineTransform m_windowTransform;
-    wxDouble m_width;
-    wxDouble m_height;
     bool m_invisible;
 
 #if wxOSX_USE_COCOA_OR_CARBON
@@ -1478,6 +1543,11 @@ public :
             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( )
     {
@@ -1518,6 +1588,7 @@ wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer
 {
     Init();
     m_windowRef = window;
+    m_enableOffset = true;
 }
 #endif
 
@@ -1525,6 +1596,7 @@ wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer
 {
     Init();
 
+    m_enableOffset = true;
     wxSize sz = window->GetSize();
     m_width = sz.x;
     m_height = sz.y;
@@ -1572,12 +1644,6 @@ wxMacCoreGraphicsContext::~wxMacCoreGraphicsContext()
     SetNativeContext(NULL);
 }
 
-void wxMacCoreGraphicsContext::GetSize( wxDouble* width, wxDouble* height)
-{
-    *width = m_width;
-    *height = m_height;
-}
-
 
 void wxMacCoreGraphicsContext::StartPage( wxDouble width, wxDouble height )
 {
@@ -2109,7 +2175,7 @@ void wxMacCoreGraphicsContext::DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble
     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() )
@@ -2315,8 +2381,8 @@ void wxMacCoreGraphicsContext::DoDrawRotatedText(const wxString &str,
         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 );
@@ -2374,13 +2440,8 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid
         wxCFRef<CFAttributedStringRef> attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, attributes) );
         wxCFRef<CTLineRef> line( CTLineCreateWithAttributedString(attrtext) );
 
-        // round the returned extent: this is probably more correct anyhow but
-        // we also need to do it to be consistent with GetPartialTextExtents()
-        // below and avoid strange situation when the last partial extent
-        // returned by it could have been greater than the full extent returned
-        // by us
-        CGFloat a, d, l;
-        int w = CTLineGetTypographicBounds(line, &a, &d, &l) + 0.5;
+        CGFloat a, d, l, w;
+        w = CTLineGetTypographicBounds(line, &a, &d, &l);
 
         if ( height )
             *height = a+d+l;
@@ -2417,13 +2478,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);
 
@@ -2440,7 +2501,7 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid
         *height = sz.height;
         /*
     if ( descent )
-        *descent = FixedToInt(textDescent);
+        *descent = FixedToFloat(textDescent);
     if ( externalLeading )
         *externalLeading = 0;
         */
@@ -2511,7 +2572,7 @@ 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
@@ -2531,7 +2592,7 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr
         {
             for ( int pos = 1; pos < (int)glyphCount ; pos ++ )
             {
-                widths[pos-1] = FixedToInt( layoutRecords[pos].realPos );
+                widths[pos-1] = FixedToFloat( layoutRecords[pos].realPos );
             }
         }
 
@@ -2558,7 +2619,7 @@ 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
@@ -2684,8 +2745,12 @@ wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxWindowDC&
         if (win_impl->GetWindow())
             cgctx =  (CGContextRef)(win_impl->GetWindow()->MacGetCGContextRef());
 
-        if (cgctx != 0)
-            return new wxMacCoreGraphicsContext( this, cgctx, (wxDouble) w, (wxDouble) h );
+        // 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;
 }
@@ -2699,8 +2764,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;
@@ -2732,7 +2799,9 @@ 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;