[cairo] [patch] gl: fix gradient color texture generation
Henry (Yu) Song - SISA
hsong at sisa.samsung.com
Wed Jul 25 15:41:34 PDT 2012
commit 143dcad36f057ed2bb4fc2970781a4efc9386602
Author: Henry Song <henry.song at samsung.com>
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,
More information about the cairo
mailing list