[patch] gl: fix gradient color texture generation

"Henry (Yu) Song - SISA" <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <3955FA337689574EB32F94B12A7E6E9E163641B9@sisaex01sj>
commit 143dcad36f057ed2bb4fc2970781a4efc9386602
Author: Henry Song <[email protected]>
Date:   Wed Jul 25 15:34:52 2012 -0700

    gl: (1) increase minimal gradient texture width from  to 256.
    (2) set gradient color strip center to be a little offset from pixel
    center
    
    (1) gradient texture width of 8 is too small that results in lost of
    color precision when gradient end/start points are far apart.
    
    (2) due to a "bug" in pixman, we should not set p1.x and p2.x to be
    exact of pixel center - this results in a out-of-bound when pixman
    loops of over stops.
    
    fix test cases: huge-radial, huge-linear.
    bring test case: linear-gradient-large closer to reference image

diff --git a/src/cairo-gl-gradient.c b/src/cairo-gl-gradient.c
index ffb5468..c060ca1 100644
--- a/src/cairo-gl-gradient.c
+++ b/src/cairo-gl-gradient.c
@@ -52,7 +52,12 @@ _cairo_gl_gradient_sample_width (unsigned int                 n_stops,
     unsigned int n;
     int width;
 
-    width = 8;
+    /*  minimal 8 sample width is too small for situation where 
+     * gradient start/end points are far apart.  In GL backend, the 
+     * gl shader picks gradient color by interpolation.  If the texture
+     * width is too small, it results in lose of color precision
+     */
+    width = 256;
     for (n = 1; n < n_stops; n++) {
 	double dx = stops[n].offset - stops[n-1].offset;
 	double delta, max;
@@ -80,6 +85,7 @@ _cairo_gl_gradient_sample_width (unsigned int                 n_stops,
 	    width = ramp;
     }
 
+    /* increment by 8 is OK */
     width = (width + 7) & -8;
     return MIN (width, 1024);
 }
@@ -124,9 +130,17 @@ _cairo_gl_gradient_render (const cairo_gl_context_t    *ctx,
 	pixman_stops[i].color.alpha = stops[i].color.alpha_short;
     }
 
-    p1.x = _cairo_fixed_16_16_from_double (0.5);
+    /* due to a "bug" in pixman, we should not use exact center of pixel
+     * as the p1.x and p2.x.  This is beause pixman generates gradient
+     * color by interpolate two adjacent stops.  And the step of 
+     * interpolation is computed from p2.x - p1.x.  If we have set
+     * at the center of pixel, it results pixman picking stop colors from
+     * out-of-bound stops array.  see _gradient_walker_reset () in
+     * pixman-gradient-walker.c
+     */
+    p1.x = _cairo_fixed_16_16_from_double (0.6);
     p1.y = 0;
-    p2.x = _cairo_fixed_16_16_from_double (width - 0.5);
+    p2.x = _cairo_fixed_16_16_from_double (width - 0.6);
     p2.y = 0;
 
     gradient = pixman_image_create_linear_gradient (&p1, &p2,
-- 
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.