[cairo-commit] 11 commits - src/cairo.c src/cairo-color.c src/cairo-directfb-surface.c src/cairo-gl-gradient.c src/cairo-gl-gradient-private.h src/cairo-gl-surface.c src/cairo-gstate.c src/cairoint.h src/cairo-pattern.c src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-script-surface.c src/cairo-surface.c src/cairo-types-private.h src/cairo-win32-surface.c src/cairo-xlib-surface.c test/linear-gradient-one-stop.argb32.ref.png test/linear-gradient-one-stop.c test/linear-gradient-one-stop.ref.png test/linear-gradient-one-stop.rgb24.ref.png test/radial-gradient-one-stop.argb32.ref.png test/radial-gradient-one-stop.c test/radial-gradient-one-stop.ref.png test/radial-gradient-one-stop.rgb24.ref.png

Andrea Canciani ranma42 at kemper.freedesktop.org
Thu Jun 10 08:20:57 PDT 2010


 dev/null                                     |binary
 src/cairo-color.c                            |   16 +
 src/cairo-directfb-surface.c                 |    2 
 src/cairo-gl-gradient-private.h              |    2 
 src/cairo-gl-gradient.c                      |    3 
 src/cairo-gl-surface.c                       |    2 
 src/cairo-gstate.c                           |   93 ++--------
 src/cairo-pattern.c                          |  231 ++++++++++++++++++++++-----
 src/cairo-pdf-surface.c                      |    6 
 src/cairo-ps-surface.c                       |    9 -
 src/cairo-script-surface.c                   |    9 -
 src/cairo-surface.c                          |    9 -
 src/cairo-types-private.h                    |    1 
 src/cairo-win32-surface.c                    |    3 
 src/cairo-xlib-surface.c                     |   36 ----
 src/cairo.c                                  |    4 
 src/cairoint.h                               |   24 +-
 test/linear-gradient-one-stop.argb32.ref.png |binary
 test/linear-gradient-one-stop.c              |    2 
 test/linear-gradient-one-stop.rgb24.ref.png  |binary
 test/radial-gradient-one-stop.argb32.ref.png |binary
 test/radial-gradient-one-stop.c              |    2 
 test/radial-gradient-one-stop.rgb24.ref.png  |binary
 23 files changed, 271 insertions(+), 183 deletions(-)

New commits:
commit 836f6166597eaa687b10e5f26fe71e099c434aa1
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Wed Jun 9 19:09:22 2010 +0200

    gl: support single stop gradients

diff --git a/src/cairo-gl-gradient-private.h b/src/cairo-gl-gradient-private.h
index 60e0525..383a118 100644
--- a/src/cairo-gl-gradient-private.h
+++ b/src/cairo-gl-gradient-private.h
@@ -66,7 +66,7 @@ typedef struct _cairo_gl_gradient {
     GLuint                        tex;
     unsigned int	          n_stops;
     const cairo_gradient_stop_t  *stops;
-    cairo_gradient_stop_t         stops_embedded[2];
+    cairo_gradient_stop_t         stops_embedded[1];
 } cairo_gl_gradient_t;
 
 cairo_private cairo_int_status_t
diff --git a/src/cairo-gl-gradient.c b/src/cairo-gl-gradient.c
index cad38d4..aea352c 100644
--- a/src/cairo-gl-gradient.c
+++ b/src/cairo-gl-gradient.c
@@ -196,7 +196,6 @@ _cairo_gl_gradient_create (cairo_gl_context_t           *ctx,
     int tex_width;
     void *data;
 
-    assert (n_stops >= 2);
     if ((unsigned int) ctx->max_texture_size / 2 <= n_stops)
         return CAIRO_INT_STATUS_UNSUPPORTED;
 
@@ -208,7 +207,7 @@ _cairo_gl_gradient_create (cairo_gl_context_t           *ctx,
         return CAIRO_STATUS_SUCCESS;
     }
 
-    gradient = malloc (sizeof (cairo_gl_gradient_t) + sizeof (cairo_gradient_stop_t) * (n_stops - 2));
+    gradient = malloc (sizeof (cairo_gl_gradient_t) + sizeof (cairo_gradient_stop_t) * (n_stops - 1));
     if (gradient == NULL)
         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
commit d17e2c5e23eac302b7463a08205088147da1172a
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Thu Jun 10 10:52:16 2010 +0200

    ps: support single stop gradients

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 71d10b8..15a6752 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -3114,7 +3114,10 @@ _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t       *surface,
 
     _cairo_output_stream_printf (surface->stream,
 				 "/CairoFunction\n");
-    if (n_stops == 2) {
+    if (n_stops == 1) {
+	/* work around single stop gradients */
+	_cairo_ps_surface_emit_linear_colorgradient (surface, &stops[0], &stops[0]);
+    } else if (n_stops == 2) {
 	/* no need for stitched function */
 	_cairo_ps_surface_emit_linear_colorgradient (surface, &stops[0], &stops[1]);
     } else {
@@ -3176,8 +3179,6 @@ _cairo_ps_surface_emit_linear_pattern (cairo_ps_surface_t     *surface,
     double first_stop, last_stop;
     int repeat_begin = 0, repeat_end = 1;
 
-    assert (pattern->base.n_stops >= 2);
-
     extend = cairo_pattern_get_extend (&pattern->base.base);
 
     pat_to_ps = pattern->base.base.matrix;
@@ -3302,8 +3303,6 @@ _cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t     *surface,
     cairo_extend_t extend;
     cairo_status_t status;
 
-    assert (pattern->base.n_stops >= 2);
-
     extend = cairo_pattern_get_extend (&pattern->base.base);
 
     pat_to_ps = pattern->base.base.matrix;
commit eb7fc351156bd66921ac3b3ffbd1fba6ba743ffb
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Thu Jun 10 10:51:50 2010 +0200

    pdf: support single stop gradients

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 2fc0150..350f7d0 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -2781,11 +2781,11 @@ _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t      *surface,
 	stops[n_stops-1].offset = 1.0;
     }
 
-    if (n_stops == 2) {
+    if (n_stops <= 2) {
         /* no need for stitched function */
         status = cairo_pdf_surface_emit_rgb_linear_function (surface,
                                                              &stops[0],
-                                                             &stops[1],
+                                                             &stops[n_stops - 1],
                                                              color_function);
         if (unlikely (status))
             goto BAIL;
@@ -2793,7 +2793,7 @@ _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t      *surface,
         if (emit_alpha) {
             status = cairo_pdf_surface_emit_alpha_linear_function (surface,
                                                                    &stops[0],
-                                                                   &stops[1],
+                                                                   &stops[n_stops - 1],
                                                                    alpha_function);
             if (unlikely (status))
                 goto BAIL;
commit e2660a0eac5f6081bf052db16b8bd85c814d19d8
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Wed Jun 9 16:59:29 2010 +0200

    pattern: improve single stop gradients handling
    
    None-extended single stop gradients are now explicitly made clear.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 7041258..d91e5d5 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1767,6 +1767,11 @@ _gradient_is_clear (const cairo_gradient_pattern_t *gradient,
     assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
 	    gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
 
+    if (gradient->n_stops == 0 ||
+	(gradient->base.extend == CAIRO_EXTEND_NONE &&
+	 gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
+	return TRUE;
+
     /* Check if the extents intersect the drawn part of the pattern. */
     if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
 	if (gradient->base.extend == CAIRO_EXTEND_NONE) {
@@ -1928,7 +1933,9 @@ _gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
     assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
 	    gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
 
-    if (gradient->n_stops == 0)
+    if (gradient->n_stops == 0 ||
+	(gradient->base.extend == CAIRO_EXTEND_NONE &&
+	 gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
 	return FALSE;
 
     if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
commit 7a024bc206aae790c7357be83474126037335ab1
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Wed Jun 9 17:59:47 2010 +0200

    test: exercise ps crash with single stop gradients
    
    PS crashes only when using the source operator, as it will otherwise
    fallback to rasterization of the gradients.

diff --git a/test/linear-gradient-one-stop.argb32.ref.png b/test/linear-gradient-one-stop.argb32.ref.png
new file mode 100644
index 0000000..da02fda
Binary files /dev/null and b/test/linear-gradient-one-stop.argb32.ref.png differ
diff --git a/test/linear-gradient-one-stop.c b/test/linear-gradient-one-stop.c
index b1a608f..09c4b9d 100644
--- a/test/linear-gradient-one-stop.c
+++ b/test/linear-gradient-one-stop.c
@@ -45,7 +45,7 @@ draw (cairo_t *cr, int width, int height)
 	CAIRO_EXTEND_PAD
     };
 
-    cairo_test_paint_checkered (cr);
+    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 
     cairo_translate (cr, PAD, PAD);
 
diff --git a/test/linear-gradient-one-stop.ref.png b/test/linear-gradient-one-stop.ref.png
deleted file mode 100644
index 9831006..0000000
Binary files a/test/linear-gradient-one-stop.ref.png and /dev/null differ
diff --git a/test/linear-gradient-one-stop.rgb24.ref.png b/test/linear-gradient-one-stop.rgb24.ref.png
new file mode 100644
index 0000000..efc12ee
Binary files /dev/null and b/test/linear-gradient-one-stop.rgb24.ref.png differ
diff --git a/test/radial-gradient-one-stop.argb32.ref.png b/test/radial-gradient-one-stop.argb32.ref.png
new file mode 100644
index 0000000..bdc64dc
Binary files /dev/null and b/test/radial-gradient-one-stop.argb32.ref.png differ
diff --git a/test/radial-gradient-one-stop.c b/test/radial-gradient-one-stop.c
index 69f7fe6..552de23 100644
--- a/test/radial-gradient-one-stop.c
+++ b/test/radial-gradient-one-stop.c
@@ -78,7 +78,7 @@ draw (cairo_t *cr, int width, int height)
 	CAIRO_EXTEND_PAD
     };
 
-    cairo_test_paint_checkered (cr);
+    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 
     for (j = 0; j < NUM_EXTEND; j++) {
 	for (i = 0; i < NUM_GRADIENTS; i++) {
diff --git a/test/radial-gradient-one-stop.ref.png b/test/radial-gradient-one-stop.ref.png
deleted file mode 100644
index 2c09cfb..0000000
Binary files a/test/radial-gradient-one-stop.ref.png and /dev/null differ
diff --git a/test/radial-gradient-one-stop.rgb24.ref.png b/test/radial-gradient-one-stop.rgb24.ref.png
new file mode 100644
index 0000000..d9f471b
Binary files /dev/null and b/test/radial-gradient-one-stop.rgb24.ref.png differ
commit a0f8cfe64660c0043db15f9b9cbf1298bf1838d1
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Tue Jun 8 17:04:00 2010 +0200

    pattern: improve degenerate gradients handling
    
    Degenerate radial gradients are now considered clear.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 319101f..7041258 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1764,12 +1764,14 @@ _gradient_is_clear (const cairo_gradient_pattern_t *gradient,
 {
     unsigned int i;
 
-    /* Check if the extents intersect the drawn part of the pattern.
-     * TODO: radial gradients, other linear extend modes.
-     */
+    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
+	    gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
+
+    /* Check if the extents intersect the drawn part of the pattern. */
     if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
 	if (gradient->base.extend == CAIRO_EXTEND_NONE) {
 	    cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
+	    /* EXTEND_NONE degenerate linear gradients are clear */
 	    if (linear->p1.x == linear->p2.x && linear->p1.y == linear->p2.y)
 		return TRUE;
 
@@ -1780,6 +1782,13 @@ _gradient_is_clear (const cairo_gradient_pattern_t *gradient,
 		    return TRUE;
 	    }
 	}
+    } else {
+	cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
+	/* degenerate radial gradients are clear */
+	if (((radial->c1.x == radial->c2.x && radial->c1.y == radial->c2.y) ||
+	     radial->r1 == 0) && radial->r1 == radial->r2)
+	    return TRUE;
+	/* TODO: check actual intersection */
     }
 
     for (i = 0; i < gradient->n_stops; i++)
@@ -1808,7 +1817,10 @@ _cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient,
 {
     unsigned int i;
 
-     /* TODO: radial, degenerate linear */
+    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
+	    gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
+
+    /* TODO: radial, degenerate linear */
     if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
 	if (gradient->base.extend == CAIRO_EXTEND_NONE) {
 	    cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
@@ -1913,17 +1925,20 @@ _gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
 {
     unsigned int i;
 
+    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
+	    gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
+
     if (gradient->n_stops == 0)
 	return FALSE;
 
-    /* TODO: radial gradients, degenerate linear gradients */
     if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
-	cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
-	if (linear->p1.x == linear->p2.x && linear->p1.y == linear->p2.y)
-	    return FALSE;
-
 	if (gradient->base.extend == CAIRO_EXTEND_NONE) {
 	    double t[2];
+	    cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
+
+	    /* EXTEND_NONE degenerate radial gradients are clear */
+	    if (linear->p1.x == linear->p2.x && linear->p1.y == linear->p2.y)
+		return FALSE;
 
 	    if (extents == NULL)
 		return FALSE;
@@ -1933,7 +1948,7 @@ _gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
 		return FALSE;
 	}
     } else
-	return FALSE;
+	return FALSE; /* TODO: check actual intersection */
 
     for (i = 0; i < gradient->n_stops; i++)
 	if (! CAIRO_COLOR_IS_OPAQUE (&gradient->stops[i].color))
commit bccd89b4177b5f5bd05def9bee5f0927a9f25e4a
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Tue Jun 8 15:45:09 2010 +0200

    gstate: correct optimizations
    
    Gradient were previously hand-optimized (without properly checking
    for extend modes). By properly using _cairo_pattern functions we
    avoid code duplication and bugs.
    
    Fixes linear-gradient-extend, radial-gradient-extend.

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 4738449..28266dd 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -849,21 +849,6 @@ _cairo_gstate_path_extents (cairo_gstate_t     *gstate,
 }
 
 static void
-_init_solid_for_color_stop (cairo_solid_pattern_t *solid,
-			    const cairo_color_stop_t *color)
-{
-    cairo_color_t premult;
-
-    /* Color stops aren't premultiplied, so fix that here */
-    _cairo_color_init_rgba (&premult,
-			    color->red,
-			    color->green,
-			    color->blue,
-			    color->alpha);
-    _cairo_pattern_init_solid (solid, &premult);
-}
-
-static void
 _cairo_gstate_copy_pattern (cairo_pattern_t *pattern,
 			    const cairo_pattern_t *original)
 {
@@ -871,60 +856,24 @@ _cairo_gstate_copy_pattern (cairo_pattern_t *pattern,
      * pattern. For example, gradients that are uniform or just have a single
      * stop can be replace with a solid.
      */
-    switch (original->type) {
-    case CAIRO_PATTERN_TYPE_SOLID:
-	break;
-
-    case CAIRO_PATTERN_TYPE_SURFACE:
-        {
-            cairo_surface_pattern_t *surface = (cairo_surface_pattern_t *) original;
-            cairo_rectangle_int_t extents;
-
-            if (_cairo_surface_get_extents (surface->surface, &extents) &&
-                (extents.width == 0 || extents.height == 0)) {
-                _cairo_pattern_init_solid ((cairo_solid_pattern_t *) pattern,
-                                           CAIRO_COLOR_TRANSPARENT);
-
-                return;
-            }
-        }
-	break;
-
-    case CAIRO_PATTERN_TYPE_LINEAR:
-    case CAIRO_PATTERN_TYPE_RADIAL:
-	{
-	    cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) original;
-
-	    /* fast path for gradients with less than 2 color stops */
-	    if (src->n_stops < 2) {
-		if (src->n_stops) {
-		    _init_solid_for_color_stop ((cairo_solid_pattern_t *) pattern,
-						&src->stops->color);
-		} else {
-		    _cairo_pattern_init_solid ((cairo_solid_pattern_t *) pattern,
-					       CAIRO_COLOR_TRANSPARENT);
-		}
 
-		return;
-	    } else {
-		unsigned int i;
-
-		/* Is the gradient a uniform colour?
-		 * Happens more often than you would believe.
-		 */
-		for (i = 1; i < src->n_stops; i++) {
-		    if (! _cairo_color_stop_equal (&src->stops[0].color,
-						   &src->stops[i].color))
-		    {
-			break;
-		    }
-		}
-		if (i == src->n_stops) {
-		    _init_solid_for_color_stop ((cairo_solid_pattern_t *) pattern,
-						&src->stops->color);
-		    return;
-		}
-	    }
+    if (_cairo_pattern_is_clear (original)) {
+        _cairo_pattern_init_solid ((cairo_solid_pattern_t *) pattern,
+				   CAIRO_COLOR_TRANSPARENT);
+	return;
+    }
+
+    if (original->type == CAIRO_PATTERN_TYPE_LINEAR ||
+	original->type == CAIRO_PATTERN_TYPE_RADIAL)
+    {
+        cairo_color_t color;
+	if (_cairo_gradient_pattern_is_solid ((cairo_gradient_pattern_t *) original,
+					      NULL,
+					      &color))
+	{
+	    _cairo_pattern_init_solid ((cairo_solid_pattern_t *) pattern,
+				       &color);
+	    return;
 	}
     }
 
commit 06c6207ad4205f211be70e324c6d32ea7d28dca8
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Tue Jun 1 19:40:14 2010 +0200

    pattern: add gradient_is_solid function
    
    It contains in a single place the logic needed to check if a gradient
    pattern is solid (within a specified region).

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 2aa80d5..319101f 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1790,6 +1790,59 @@ _gradient_is_clear (const cairo_gradient_pattern_t *gradient,
 }
 
 /**
+ * _cairo_gradient_pattern_is_solid
+ *
+ * Convenience function to determine whether a gradient pattern is
+ * a solid color within the given extents. In this case the color
+ * argument is initialized to the color the pattern represents.
+ * This functions doesn't handle completely transparent gradients,
+ * thus it should be called only after _cairo_pattern_is_clear has
+ * returned FALSE.
+ *
+ * Return value: %TRUE if the pattern is a solid color.
+ **/
+cairo_bool_t
+_cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient,
+				  const cairo_rectangle_int_t *extents,
+				  cairo_color_t *color)
+{
+    unsigned int i;
+
+     /* TODO: radial, degenerate linear */
+    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
+	if (gradient->base.extend == CAIRO_EXTEND_NONE) {
+	    cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
+	    double t[2];
+
+	    /* We already know that the pattern is not clear, thus if some
+	     * part of it is clear, the whole is not solid.
+	     */
+
+	    if (extents == NULL)
+		return FALSE;
+
+	    _extents_to_linear_parameter (linear, extents, t);
+	    if (t[0] < 0.0 || t[1] > 1.0)
+		return FALSE;
+	}
+    } else
+	return FALSE;
+
+    for (i = 1; i < gradient->n_stops; i++)
+	if (! _cairo_color_stop_equal (&gradient->stops[0].color,
+				       &gradient->stops[i].color))
+	    return FALSE;
+
+    _cairo_color_init_rgba (color,
+			    gradient->stops[0].color.red,
+			    gradient->stops[0].color.green,
+			    gradient->stops[0].color.blue,
+			    gradient->stops[0].color.alpha);
+
+    return TRUE;
+}
+
+/**
  * _cairo_pattern_is_opaque_solid
  *
  * Convenience function to determine whether a pattern is an opaque
diff --git a/src/cairoint.h b/src/cairoint.h
index 59af684..b7c072d 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2216,6 +2216,11 @@ _cairo_pattern_transform (cairo_pattern_t      *pattern,
 			  const cairo_matrix_t *ctm_inverse);
 
 cairo_private cairo_bool_t
+_cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient,
+				  const cairo_rectangle_int_t *extents,
+				  cairo_color_t *color);
+
+cairo_private cairo_bool_t
 _cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern);
 
 cairo_private cairo_bool_t
commit 561625ee3bd2732457eaaf28937edf557ee7661d
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Tue Jun 1 19:39:02 2010 +0200

    pattern: improve clear/opaque check functions
    
    _cairo_pattern_is_opaque was missing some checks about the extend type.
    Conversely _cairo_pattern_is_clear was being too strict about gradients.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 27a7a80..2aa80d5 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1726,6 +1726,69 @@ _cairo_pattern_reset_solid_surface_cache (void)
     CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
 }
 
+static void
+_extents_to_linear_parameter (const cairo_linear_pattern_t *linear,
+			      const cairo_rectangle_int_t *extents,
+			      double t[2])
+{
+    double t0, tdx, tdy;
+    double p1x, p1y, pdx, pdy, invsqnorm;
+
+    p1x = _cairo_fixed_to_double (linear->p1.x);
+    p1y = _cairo_fixed_to_double (linear->p1.y);
+    pdx = _cairo_fixed_to_double (linear->p2.x) - p1x;
+    pdy = _cairo_fixed_to_double (linear->p2.y) - p1y;
+    invsqnorm = 1.0 / (pdx * pdx + pdy * pdy);
+    pdx *= invsqnorm;
+    pdy *= invsqnorm;
+
+    t0 = (extents->x - p1x) * pdx + (extents->y - p1y) * pdy;
+    tdx = extents->width * pdx;
+    tdy = extents->height * pdy;
+
+    t[0] = t[1] = t0;
+    if (tdx < 0)
+	t[0] += tdx;
+    else
+	t[1] += tdx;
+
+    if (tdy < 0)
+	t[0] += tdy;
+    else
+	t[1] += tdy;
+}
+
+static cairo_bool_t
+_gradient_is_clear (const cairo_gradient_pattern_t *gradient,
+		    const cairo_rectangle_int_t *extents)
+{
+    unsigned int i;
+
+    /* Check if the extents intersect the drawn part of the pattern.
+     * TODO: radial gradients, other linear extend modes.
+     */
+    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
+	if (gradient->base.extend == CAIRO_EXTEND_NONE) {
+	    cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
+	    if (linear->p1.x == linear->p2.x && linear->p1.y == linear->p2.y)
+		return TRUE;
+
+	    if (extents != NULL) {
+		double t[2];
+		_extents_to_linear_parameter (linear, extents, t);
+		if ((t[0] <= 0.0 && t[1] <= 0.0) || (t[0] >= 1.0 && t[1] >= 1.0))
+		    return TRUE;
+	    }
+	}
+    }
+
+    for (i = 0; i < gradient->n_stops; i++)
+	if (! CAIRO_COLOR_IS_CLEAR (&gradient->stops[i].color))
+	    return FALSE;
+
+    return TRUE;
+}
+
 /**
  * _cairo_pattern_is_opaque_solid
  *
@@ -1779,13 +1842,46 @@ _surface_is_opaque (const cairo_surface_pattern_t *pattern,
 }
 
 static cairo_bool_t
-_gradient_is_opaque (const cairo_gradient_pattern_t *gradient)
+_surface_is_clear (const cairo_surface_pattern_t *pattern)
+{
+    cairo_rectangle_int_t extents;
+
+    if (_cairo_surface_get_extents (pattern->surface, &extents) &&
+	(extents.width == 0 || extents.height == 0))
+	return TRUE;
+
+    return pattern->surface->is_clear &&
+	pattern->surface->content & CAIRO_CONTENT_ALPHA;
+}
+
+static cairo_bool_t
+_gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
+		     const cairo_rectangle_int_t *extents)
 {
     unsigned int i;
 
     if (gradient->n_stops == 0)
 	return FALSE;
 
+    /* TODO: radial gradients, degenerate linear gradients */
+    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
+	cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
+	if (linear->p1.x == linear->p2.x && linear->p1.y == linear->p2.y)
+	    return FALSE;
+
+	if (gradient->base.extend == CAIRO_EXTEND_NONE) {
+	    double t[2];
+
+	    if (extents == NULL)
+		return FALSE;
+
+	    _extents_to_linear_parameter (linear, extents, t);
+	    if (t[0] < 0.0 || t[1] > 1.0)
+		return FALSE;
+	}
+    } else
+	return FALSE;
+
     for (i = 0; i < gradient->n_stops; i++)
 	if (! CAIRO_COLOR_IS_OPAQUE (&gradient->stops[i].color))
 	    return FALSE;
@@ -1819,7 +1915,7 @@ _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern,
 	return _surface_is_opaque (&pattern->surface, extents);
     case CAIRO_PATTERN_TYPE_LINEAR:
     case CAIRO_PATTERN_TYPE_RADIAL:
-	return _gradient_is_opaque (&pattern->gradient.base);
+	return _gradient_is_opaque (&pattern->gradient.base, extents);
     }
 
     ASSERT_NOT_REACHED;
@@ -1837,16 +1933,16 @@ _cairo_pattern_is_clear (const cairo_pattern_t *abstract_pattern)
     pattern = (cairo_pattern_union_t *) abstract_pattern;
     switch (pattern->type) {
     case CAIRO_PATTERN_TYPE_SOLID:
-	return pattern->solid.color.alpha_short == 0x0000;
+	return CAIRO_COLOR_IS_CLEAR (&pattern->solid.color);
     case CAIRO_PATTERN_TYPE_SURFACE:
-	return pattern->surface.surface->is_clear &&
-	       pattern->surface.surface->content & CAIRO_CONTENT_ALPHA;
-    default:
-	ASSERT_NOT_REACHED;
+	return _surface_is_clear (&pattern->surface);
     case CAIRO_PATTERN_TYPE_LINEAR:
     case CAIRO_PATTERN_TYPE_RADIAL:
-	return pattern->gradient.base.n_stops == 0;
+	return _gradient_is_clear (&pattern->gradient.base, NULL);
     }
+
+    ASSERT_NOT_REACHED;
+    return FALSE;
 }
 
 /**
diff --git a/src/cairoint.h b/src/cairoint.h
index 22ff16d..59af684 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -145,10 +145,14 @@ do {					\
 #define COMPILE_TIME_ASSERT0(condition, line)	COMPILE_TIME_ASSERT1(condition, line)
 #define COMPILE_TIME_ASSERT(condition)		COMPILE_TIME_ASSERT0(condition, __LINE__)
 
+#define CAIRO_ALPHA_IS_CLEAR(alpha) ((alpha) <= ((double)0x00ff / (double)0xffff))
+#define CAIRO_ALPHA_SHORT_IS_CLEAR(alpha) ((alpha) <= 0x00ff)
+
 #define CAIRO_ALPHA_IS_OPAQUE(alpha) ((alpha) >= ((double)0xff00 / (double)0xffff))
 #define CAIRO_ALPHA_SHORT_IS_OPAQUE(alpha) ((alpha) >= 0xff00)
 #define CAIRO_ALPHA_IS_ZERO(alpha) ((alpha) <= 0.0)
 
+#define CAIRO_COLOR_IS_CLEAR(color) CAIRO_ALPHA_SHORT_IS_CLEAR ((color)->alpha_short)
 #define CAIRO_COLOR_IS_OPAQUE(color) CAIRO_ALPHA_SHORT_IS_OPAQUE ((color)->alpha_short)
 
 /* Reverse the bits in a byte with 7 operations (no 64-bit):
commit baaf312e047a9bea6f54e63cd6534c2ed7448523
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Mon Apr 19 09:53:00 2010 +0200

    pattern: remove content field from solid patterns
    
    The content field in solid patterns had ill-defined semantic (or no
    semantic at all), thus it can be removed.

diff --git a/src/cairo-color.c b/src/cairo-color.c
index 9483c8b..6bc1705 100644
--- a/src/cairo-color.c
+++ b/src/cairo-color.c
@@ -210,3 +210,19 @@ _cairo_color_stop_equal (const cairo_color_stop_t *color_a,
 
     return TRUE;
 }
+
+cairo_content_t
+_cairo_color_get_content (const cairo_color_t *color)
+{
+    if (CAIRO_COLOR_IS_OPAQUE (color))
+        return CAIRO_CONTENT_COLOR;
+
+    if (color->red_short == 0 &&
+	color->green_short == 0 &&
+	color->blue_short == 0)
+    {
+        return CAIRO_CONTENT_ALPHA;
+    }
+
+    return CAIRO_CONTENT_COLOR_ALPHA;
+}
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index b896e0b..e79f46c 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1022,7 +1022,7 @@ _cairo_gl_surface_fill_rectangles (void			   *abstract_dst,
     if (unlikely (status))
         goto CLEANUP;
 
-    _cairo_pattern_init_solid (&solid, color, CAIRO_CONTENT_COLOR_ALPHA);
+    _cairo_pattern_init_solid (&solid, color);
     status = _cairo_gl_composite_set_source (&setup, &solid.base,
                                              0, 0,
                                              0, 0,
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index f7a32ae..4738449 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -415,8 +415,7 @@ _cairo_gstate_get_source (cairo_gstate_t *gstate)
 {
     if (gstate->source == &_cairo_pattern_black.base) {
 	/* do not expose the static object to the user */
-	gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK,
-						      CAIRO_CONTENT_COLOR);
+        gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
     }
 
     return gstate->source;
@@ -861,7 +860,7 @@ _init_solid_for_color_stop (cairo_solid_pattern_t *solid,
 			    color->green,
 			    color->blue,
 			    color->alpha);
-    _cairo_pattern_init_solid (solid, &premult, CAIRO_CONTENT_COLOR_ALPHA);
+    _cairo_pattern_init_solid (solid, &premult);
 }
 
 static void
@@ -884,8 +883,7 @@ _cairo_gstate_copy_pattern (cairo_pattern_t *pattern,
             if (_cairo_surface_get_extents (surface->surface, &extents) &&
                 (extents.width == 0 || extents.height == 0)) {
                 _cairo_pattern_init_solid ((cairo_solid_pattern_t *) pattern,
-                                           CAIRO_COLOR_TRANSPARENT,
-                                           surface->surface->content);
+                                           CAIRO_COLOR_TRANSPARENT);
 
                 return;
             }
@@ -904,8 +902,7 @@ _cairo_gstate_copy_pattern (cairo_pattern_t *pattern,
 						&src->stops->color);
 		} else {
 		    _cairo_pattern_init_solid ((cairo_solid_pattern_t *) pattern,
-					       CAIRO_COLOR_TRANSPARENT,
-					       CAIRO_CONTENT_ALPHA);
+					       CAIRO_COLOR_TRANSPARENT);
 		}
 
 		return;
@@ -1147,8 +1144,7 @@ _cairo_gstate_mask (cairo_gstate_t  *gstate,
 	    _cairo_color_multiply_alpha (&combined, mask_pattern.solid.color.alpha);
 	}
 
-	_cairo_pattern_init_solid (&source_pattern.solid, &combined,
-				   solid->content | mask_pattern.solid.content);
+	_cairo_pattern_init_solid (&source_pattern.solid, &combined);
 
 	status = _cairo_surface_paint (gstate->target, op,
 				       &source_pattern.base,
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index e9743e2..27a7a80 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -65,7 +65,6 @@ const cairo_solid_pattern_t _cairo_pattern_black = {
       CAIRO_FILTER_DEFAULT,		/* filter */
       CAIRO_EXTEND_GRADIENT_DEFAULT},	/* extend */
     { 0., 0., 0., 1., 0, 0, 0, 0xffff },/* color (double rgba, short rgba) */
-    CAIRO_CONTENT_COLOR,                /* content */
 };
 
 const cairo_solid_pattern_t _cairo_pattern_clear = {
@@ -77,7 +76,6 @@ const cairo_solid_pattern_t _cairo_pattern_clear = {
       CAIRO_FILTER_DEFAULT,		/* filter */
       CAIRO_EXTEND_GRADIENT_DEFAULT},	/* extend */
     { 0., 0., 0., 0., 0, 0, 0, 0 },/* color (double rgba, short rgba) */
-    CAIRO_CONTENT_ALPHA,                /* content */
 };
 
 const cairo_solid_pattern_t _cairo_pattern_white = {
@@ -89,7 +87,6 @@ const cairo_solid_pattern_t _cairo_pattern_white = {
       CAIRO_FILTER_DEFAULT,		/* filter */
       CAIRO_EXTEND_GRADIENT_DEFAULT},	/* extend */
     { 1., 1., 1., 1., 0xffff, 0xffff, 0xffff, 0xffff },/* color (double rgba, short rgba) */
-    CAIRO_CONTENT_COLOR_ALPHA,                /* content */
 };
 
 /**
@@ -420,15 +417,10 @@ _cairo_pattern_create_copy (cairo_pattern_t	  **pattern_out,
 
 void
 _cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
-			   const cairo_color_t	 *color,
-			   cairo_content_t	  content)
+			   const cairo_color_t	 *color)
 {
-    if (content == CAIRO_CONTENT_COLOR_ALPHA && CAIRO_COLOR_IS_OPAQUE (color))
-	content = CAIRO_CONTENT_COLOR;
-
     _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
     pattern->color = *color;
-    pattern->content = content;
 }
 
 void
@@ -486,8 +478,7 @@ _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
 }
 
 cairo_pattern_t *
-_cairo_pattern_create_solid (const cairo_color_t *color,
-			     cairo_content_t	  content)
+_cairo_pattern_create_solid (const cairo_color_t *color)
 {
     cairo_solid_pattern_t *pattern;
 
@@ -502,7 +493,7 @@ _cairo_pattern_create_solid (const cairo_color_t *color,
 	}
     }
 
-    _cairo_pattern_init_solid (pattern, color, content);
+    _cairo_pattern_init_solid (pattern, color);
     CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
 
     return &pattern->base;
@@ -518,7 +509,7 @@ _cairo_pattern_create_in_error (cairo_status_t status)
 
     CAIRO_MUTEX_INITIALIZE ();
 
-    pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK, CAIRO_CONTENT_COLOR);
+    pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
     if (pattern->status == CAIRO_STATUS_SUCCESS)
 	status = _cairo_pattern_set_error (pattern, status);
 
@@ -558,7 +549,7 @@ cairo_pattern_create_rgb (double red, double green, double blue)
 
     CAIRO_MUTEX_INITIALIZE ();
 
-    return _cairo_pattern_create_solid (&color, CAIRO_CONTENT_COLOR);
+    return _cairo_pattern_create_solid (&color);
 }
 slim_hidden_def (cairo_pattern_create_rgb);
 
@@ -598,7 +589,7 @@ cairo_pattern_create_rgba (double red, double green, double blue,
 
     CAIRO_MUTEX_INITIALIZE ();
 
-    return _cairo_pattern_create_solid (&color, CAIRO_CONTENT_COLOR_ALPHA);
+    return _cairo_pattern_create_solid (&color);
 }
 slim_hidden_def (cairo_pattern_create_rgba);
 
@@ -1566,7 +1557,6 @@ _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pat
 #define MAX_SURFACE_CACHE_SIZE 16
 static struct {
     struct _cairo_pattern_solid_surface_cache{
-	cairo_content_t  content;
 	cairo_color_t    color;
 	cairo_surface_t *surface;
     } cache[MAX_SURFACE_CACHE_SIZE];
@@ -1579,7 +1569,7 @@ _cairo_pattern_solid_surface_matches (
 	const cairo_solid_pattern_t			    *pattern,
 	cairo_surface_t					    *dst)
 {
-    if (cache->content != pattern->content)
+    if (cairo_surface_get_content (cache->surface) != _cairo_color_get_content (&pattern->color))
 	return FALSE;
 
     if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1)
@@ -1690,7 +1680,6 @@ _cairo_pattern_acquire_surface_for_solid (const cairo_solid_pattern_t	     *patt
     to_destroy = solid_surface_cache.cache[i].surface;
     solid_surface_cache.cache[i].surface = surface;
     solid_surface_cache.cache[i].color   = pattern->color;
-    solid_surface_cache.cache[i].content = pattern->content;
 
 DONE:
     *out = cairo_surface_reference (solid_surface_cache.cache[i].surface);
@@ -2210,7 +2199,7 @@ _init_solid_for_color_stop (cairo_solid_pattern_t *solid,
 			    color->green,
 			    color->blue,
 			    color->alpha);
-    _cairo_pattern_init_solid (solid, &premult, CAIRO_CONTENT_COLOR_ALPHA);
+    _cairo_pattern_init_solid (solid, &premult);
 }
 
 /**
@@ -2275,8 +2264,7 @@ _cairo_pattern_acquire_surface (const cairo_pattern_t	   *pattern,
 		_init_solid_for_color_stop (&solid, &src->stops->color);
 	    } else {
 		_cairo_pattern_init_solid (&solid,
-					   CAIRO_COLOR_TRANSPARENT,
-					   CAIRO_CONTENT_ALPHA);
+					   CAIRO_COLOR_TRANSPARENT);
 	    }
 
 	    status = _cairo_pattern_acquire_surface_for_solid (&solid, dst,
@@ -2393,8 +2381,7 @@ _cairo_pattern_acquire_surfaces (const cairo_pattern_t	    *src,
 	combined = src_solid->color;
 	_cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
 
-	_cairo_pattern_init_solid (&src_tmp.solid, &combined,
-				   src_solid->content | mask_solid->content);
+	_cairo_pattern_init_solid (&src_tmp.solid, &combined);
 
 	src = &src_tmp.base;
 	mask = NULL;
@@ -2608,7 +2595,6 @@ _cairo_solid_pattern_hash (unsigned long hash,
 {
     const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
 
-    hash = _cairo_hash_bytes (hash, &solid->content, sizeof (solid->content));
     hash = _cairo_hash_bytes (hash, &solid->color, sizeof (solid->color));
 
     return hash;
@@ -2748,9 +2734,6 @@ _cairo_solid_pattern_equal (const cairo_pattern_t *A,
     const cairo_solid_pattern_t *a = (cairo_solid_pattern_t *) A;
     const cairo_solid_pattern_t *b = (cairo_solid_pattern_t *) B;
 
-    if (a->content != b->content)
-	return FALSE;
-
     return _cairo_color_equal (&a->color, &b->color);
 }
 
diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c
index b925081..d1c2816 100644
--- a/src/cairo-script-surface.c
+++ b/src/cairo-script-surface.c
@@ -855,11 +855,9 @@ _emit_solid_pattern (cairo_script_surface_t *surface,
     cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
     cairo_script_context_t *ctx = to_context (surface);
 
-    if (solid->content & CAIRO_CONTENT_ALPHA &&
-	! CAIRO_COLOR_IS_OPAQUE (&solid->color))
+    if (! CAIRO_COLOR_IS_OPAQUE (&solid->color))
     {
-	if (! (solid->content & CAIRO_CONTENT_COLOR) ||
-	    ! (surface->base.content & CAIRO_CONTENT_COLOR) ||
+	if (! (surface->base.content & CAIRO_CONTENT_COLOR) ||
 	    ((solid->color.red_short   == 0 || solid->color.red_short   == 0xffff) &&
 	     (solid->color.green_short == 0 || solid->color.green_short == 0xffff) &&
 	     (solid->color.blue_short  == 0 || solid->color.blue_short  == 0xffff) ))
@@ -3379,8 +3377,7 @@ _cairo_script_implicit_context_init (cairo_script_implicit_context_t *cr)
     cr->current_antialias = CAIRO_ANTIALIAS_DEFAULT;
     _cairo_stroke_style_init (&cr->current_style);
     _cairo_pattern_init_solid (&cr->current_source.solid,
-			       CAIRO_COLOR_BLACK,
-			       CAIRO_CONTENT_COLOR);
+			       CAIRO_COLOR_BLACK);
     _cairo_path_fixed_init (&cr->current_path);
     cairo_matrix_init_identity (&cr->current_ctm);
     cairo_matrix_init_identity (&cr->current_stroke_matrix);
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 624ba35..9d5f7b8 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -480,7 +480,7 @@ _cairo_surface_create_similar_solid (cairo_surface_t	 *other,
     if (surface == NULL || surface->status)
 	return surface;
 
-    _cairo_pattern_init_solid (&pattern, color, content);
+    _cairo_pattern_init_solid (&pattern, color);
     status = _cairo_surface_paint (surface,
 				   color == CAIRO_COLOR_TRANSPARENT ?
 				   CAIRO_OPERATOR_CLEAR : CAIRO_OPERATOR_SOURCE,
@@ -507,7 +507,7 @@ _cairo_surface_create_solid_pattern_surface (cairo_surface_t	   *other,
     }
 
     return _cairo_surface_create_similar_solid (other,
-						solid_pattern->content,
+						_cairo_color_get_content (&solid_pattern->color),
 						1, 1,
 						&solid_pattern->color,
 						FALSE);
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index fa65677..dbfdd79 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -356,7 +356,6 @@ struct _cairo_pattern {
 struct _cairo_solid_pattern {
     cairo_pattern_t base;
     cairo_color_t color;
-    cairo_content_t content;
 };
 
 typedef struct _cairo_surface_pattern {
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 0706296..93467ff 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1432,8 +1432,8 @@ _cairo_xlib_surface_create_solid_pattern_surface (void                  *abstrac
 	return NULL;
 
     image = (cairo_image_surface_t *)
-	    _cairo_image_surface_create_with_content (solid_pattern->content,
-						      width, height);
+	_cairo_image_surface_create_with_content (_cairo_color_get_content (&solid_pattern->color),
+						  width, height);
     status = image->base.status;
     if (unlikely (status))
 	goto BAIL;
@@ -2427,7 +2427,7 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t    *surface,
     GC gc;
     int i;
 
-    _cairo_pattern_init_solid (&solid, color, CAIRO_CONTENT_COLOR);
+    _cairo_pattern_init_solid (&solid, color);
 
     status = _cairo_xlib_display_acquire (surface->base.device, &display);
     if (unlikely (status))
diff --git a/src/cairo.c b/src/cairo.c
index 7ddfd84..b2a3a7b 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -2144,8 +2144,8 @@ cairo_paint_with_alpha (cairo_t *cr,
 	return;
     }
 
-    _cairo_color_init_rgba (&color, 1., 1., 1., alpha);
-    _cairo_pattern_init_solid (&pattern, &color, CAIRO_CONTENT_ALPHA);
+    _cairo_color_init_rgba (&color, 0., 0., 0., alpha);
+    _cairo_pattern_init_solid (&pattern, &color);
 
     status = _cairo_gstate_mask (cr->gstate, &pattern.base);
     if (unlikely (status))
diff --git a/src/cairoint.h b/src/cairoint.h
index 9fbb772..22ff16d 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1017,6 +1017,9 @@ cairo_private cairo_bool_t
 _cairo_color_stop_equal (const cairo_color_stop_t *color_a,
 			 const cairo_color_stop_t *color_b) cairo_pure;
 
+cairo_content_t
+_cairo_color_get_content (const cairo_color_t *color) cairo_pure;
+
 /* cairo-font-face.c */
 
 extern const cairo_private cairo_font_face_t _cairo_font_face_nil;
@@ -2180,8 +2183,7 @@ _cairo_pattern_init_snapshot (cairo_pattern_t       *pattern,
 
 cairo_private void
 _cairo_pattern_init_solid (cairo_solid_pattern_t	*pattern,
-			   const cairo_color_t		*color,
-			   cairo_content_t		 content);
+			   const cairo_color_t		*color);
 
 cairo_private void
 _cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
@@ -2203,8 +2205,7 @@ cairo_private void
 _cairo_pattern_fini_snapshot (cairo_pattern_t *pattern);
 
 cairo_private cairo_pattern_t *
-_cairo_pattern_create_solid (const cairo_color_t	*color,
-			     cairo_content_t		 content);
+_cairo_pattern_create_solid (const cairo_color_t	*color);
 
 cairo_private void
 _cairo_pattern_transform (cairo_pattern_t      *pattern,
commit 7461947eb1a5f002a5931303843a5a2deca0e383
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Mon Apr 19 09:51:26 2010 +0200

    surface: remove content argument from is_similar
    
    The content argument was basically unuses.
    
    Xlib change extracted from ickle's wip/compositor branch.

diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index c6481d3..fc7509c 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -1816,7 +1816,7 @@ _cairo_directfb_surface_show_glyphs (void		    *abstract_dst,
 
 
 static cairo_bool_t
-_cairo_directfb_surface_is_similar (void *surface_a, void *surface_b, cairo_content_t content)
+_cairo_directfb_surface_is_similar (void *surface_a, void *surface_b)
 {
     cairo_directfb_surface_t *a = (cairo_directfb_surface_t *) surface_a;
     cairo_directfb_surface_t *b = (cairo_directfb_surface_t *) surface_b;
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index d3dca9d..e9743e2 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1585,7 +1585,7 @@ _cairo_pattern_solid_surface_matches (
     if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1)
 	return FALSE;
 
-    if (! _cairo_surface_is_similar (cache->surface, dst, pattern->content))
+    if (! _cairo_surface_is_similar (cache->surface, dst))
 	return FALSE;
 
     return TRUE;
@@ -1674,8 +1674,7 @@ _cairo_pattern_acquire_surface_for_solid (const cairo_solid_pattern_t	     *patt
 	    goto UNLOCK;
 	}
 
-	if (unlikely (! _cairo_surface_is_similar (surface,
-						   dst, pattern->content)))
+	if (unlikely (! _cairo_surface_is_similar (surface, dst)))
 	{
 	    /* In the rare event of a substitute surface being returned,
 	     * don't cache the fallback.
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 8a41883..624ba35 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1663,14 +1663,13 @@ _cairo_surface_clone_similar (cairo_surface_t  *surface,
  **/
 cairo_bool_t
 _cairo_surface_is_similar (cairo_surface_t *surface_a,
-	                   cairo_surface_t *surface_b,
-			   cairo_content_t content)
+	                   cairo_surface_t *surface_b)
 {
     if (surface_a->backend != surface_b->backend)
 	return FALSE;
 
     if (surface_a->backend->is_similar != NULL)
-	return surface_a->backend->is_similar (surface_a, surface_b, content);
+	return surface_a->backend->is_similar (surface_a, surface_b);
 
     return TRUE;
 }
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 9d83bbd..ba4d24e 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1865,8 +1865,7 @@ cairo_win32_surface_get_image (cairo_surface_t *surface)
 
 static cairo_bool_t
 _cairo_win32_surface_is_similar (void *surface_a,
-	                         void *surface_b,
-				 cairo_content_t content)
+	                         void *surface_b)
 {
     cairo_win32_surface_t *a = surface_a;
     cairo_win32_surface_t *b = surface_b;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index ebc45b2..0706296 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2821,35 +2821,9 @@ _cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
 
 static cairo_bool_t
 _cairo_xlib_surface_is_similar (void		*surface_a,
-	                        void		*surface_b,
-				cairo_content_t	 content)
+	                        void		*surface_b)
 {
-    cairo_xlib_surface_t *a = surface_a;
-    cairo_xlib_surface_t *b = surface_b;
-    XRenderPictFormat *xrender_format = b->xrender_format;
-    cairo_xlib_display_t *display;
-
-    if (! _cairo_xlib_surface_same_screen (a, b))
-	return FALSE;
-
-    if (_cairo_xlib_display_acquire (b->base.device, &display))
-        return FALSE;
-
-    /* now inspect the content to check that a is similar to b */
-    if (xrender_format == NULL && b->visual != NULL)
-        xrender_format = XRenderFindVisualFormat (display->display, b->visual);
-
-    if (xrender_format == NULL ||
-	_xrender_format_to_content (xrender_format) != content)
-    {
-	xrender_format = _cairo_xlib_display_get_xrender_format (
-					  display,
-					  _cairo_format_from_content (content));
-    }
-
-    cairo_device_release (&display->base);
-
-    return a->xrender_format == xrender_format;
+    return _cairo_xlib_surface_same_screen (surface_a, surface_b);
 }
 
 static const cairo_surface_backend_t cairo_xlib_surface_backend = {
diff --git a/src/cairoint.h b/src/cairoint.h
index 522dd12..9fbb772 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -769,8 +769,7 @@ struct _cairo_surface_backend {
 
     cairo_bool_t
     (*is_similar)		(void			*surface_a,
-	                         void			*surface_b,
-				 cairo_content_t         content);
+	                         void			*surface_b);
 
     cairo_warn cairo_int_status_t
     (*fill_stroke)		(void			*surface,
@@ -1744,8 +1743,7 @@ _cairo_surface_detach_snapshot (cairo_surface_t *snapshot);
 
 cairo_private cairo_bool_t
 _cairo_surface_is_similar (cairo_surface_t *surface_a,
-	                   cairo_surface_t *surface_b,
-			   cairo_content_t  content);
+	                   cairo_surface_t *surface_b);
 
 cairo_private cairo_bool_t
 _cairo_surface_get_extents (cairo_surface_t         *surface,


More information about the cairo-commit mailing list