]> git.saurik.com Git - wxWidgets.git/commitdiff
Implement support for gradient stops for OS X.
authorVadim Zeitlin <vadim@wxwidgets.org>
Tue, 6 Apr 2010 18:46:18 +0000 (18:46 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Tue, 6 Apr 2010 18:46:18 +0000 (18:46 +0000)
Currently the code still doesn't work but OTOH it's not any worse than what it
was before.

See #11904.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@63879 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/osx/carbon/graphics.cpp

index 75f74d7de83b0ba18f39326451209b7511b904ba..8f4e0cde52a9871600fd2aedc1d4c6f6471c2949 100644 (file)
@@ -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[1].green;
+        out[2] = stops.comps[2].blue;
+        out[3] = stops.comps[3].alpha;
+    }
+    else if (f >= 1.0)
     {
-        out[i] = colors[i] + ( colors[4+i] - colors[i] ) * f;
+        // 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[0] = stops.comps[i - 1].green + (stops.comps[i].green - stops.comps[i - 1].green) * fact;
+        out[0] = stops.comps[i - 1].blue + (stops.comps[i].blue - stops.comps[i - 1].blue) * fact;
+        out[0] = 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,