[cairo-commit] 2 commits - src/cairo-gl-gradient.c

Chris Wilson ickle at kemper.freedesktop.org
Sat Aug 11 10:26:33 PDT 2012


 src/cairo-gl-gradient.c |   36 +++++++++++++++++++++++++++++++++---
 1 file changed, 33 insertions(+), 3 deletions(-)

New commits:
commit adfe9b7eb67f642cda93f80cf9c97f1eaded0317
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Aug 11 17:55:49 2012 +0100

    gl: Fudge gradient color generation to handle multiple stops at 0
    
    In order to generate the correct left-hand border color, we need to
    fudge the offsets of the color stops if multiple stops are defined at 0.
    The reason is that pixman will generate our color ramp by using the
    right-most color stop for the pixel centre, but in order to provide the
    sample colour outside of the gradient we need pixel 0 to be have the
    left-most color.
    
    Reported by Henry Song.

diff --git a/src/cairo-gl-gradient.c b/src/cairo-gl-gradient.c
index 1a6f290..1c1f972 100644
--- a/src/cairo-gl-gradient.c
+++ b/src/cairo-gl-gradient.c
@@ -83,6 +83,27 @@ _cairo_gl_gradient_sample_width (unsigned int                 n_stops,
     return (width + 7) & -8;
 }
 
+static uint8_t premultiply(double c, double a)
+{
+    int v = c * a * 256;
+    return v - (v >> 8);
+}
+
+static uint32_t color_stop_to_pixel(const cairo_gradient_stop_t *stop)
+{
+    uint8_t a, r, g, b;
+
+    a = stop->color.alpha_short >> 8;
+    r = premultiply(stop->color.red,   stop->color.alpha);
+    g = premultiply(stop->color.green, stop->color.alpha);
+    b = premultiply(stop->color.blue,  stop->color.alpha);
+
+    if (_cairo_is_little_endian ())
+	return a << 24 | r << 16 | g << 8 | b << 0;
+    else
+	return a << 0 | r << 8 | g << 16 | b << 24;
+}
+
 static cairo_status_t
 _cairo_gl_gradient_render (const cairo_gl_context_t    *ctx,
                            unsigned int                 n_stops,
@@ -156,6 +177,14 @@ _cairo_gl_gradient_render (const cairo_gl_context_t    *ctx,
 
     pixman_image_unref (gradient);
     pixman_image_unref (image);
+
+    /* We need to fudge pixel 0 to hold the left-most color stop and not
+     * the neareset stop to the zeroth pixel centre in order to correctly
+     * populate the border color. For completeness, do both edges.
+     */
+    ((uint32_t*)bytes)[0] = color_stop_to_pixel(&stops[0]);
+    ((uint32_t*)bytes)[width-1] = color_stop_to_pixel(&stops[n_stops-1]);
+
     return CAIRO_STATUS_SUCCESS;
 }
 
commit b0336e9aadbbface0a059887ac62b1398bc81e7b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Aug 11 18:23:51 2012 +0100

    gl: Use a wide texture ramp to emulate a linear step function
    
    If the gradient contains a step function, we need an infinitely sharp
    texture to emulate the correct output. Failing that, lets just use as
    large a texture as can be reasonably handled by the hardware

diff --git a/src/cairo-gl-gradient.c b/src/cairo-gl-gradient.c
index 76920da..1a6f290 100644
--- a/src/cairo-gl-gradient.c
+++ b/src/cairo-gl-gradient.c
@@ -59,7 +59,7 @@ _cairo_gl_gradient_sample_width (unsigned int                 n_stops,
 	int ramp;
 
 	if (dx == 0)
-	    continue;
+	    return 1024; /* we need to emulate an infinitely sharp step */
 
 	max = fabs (stops[n].color.red - stops[n-1].color.red);
 
@@ -80,8 +80,7 @@ _cairo_gl_gradient_sample_width (unsigned int                 n_stops,
 	    width = ramp;
     }
 
-    width = (width + 7) & -8;
-    return MIN (width, 1024);
+    return (width + 7) & -8;
 }
 
 static cairo_status_t
@@ -225,6 +224,8 @@ _cairo_gl_gradient_create (cairo_gl_context_t           *ctx,
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     tex_width = _cairo_gl_gradient_sample_width (n_stops, stops);
+    if (tex_width > ctx->max_texture_size)
+	tex_width = ctx->max_texture_size;
 
     CAIRO_REFERENCE_COUNT_INIT (&gradient->ref_count, 2);
     gradient->cache_entry.hash = hash;


More information about the cairo-commit mailing list