[cairo-commit] src/cairoint.h src/cairo-pattern.c

Carl Worth cworth at kemper.freedesktop.org
Wed Oct 25 10:40:49 PDT 2006


 src/cairo-pattern.c |   54 ++++++++++++++++++++++++++++++++--------------------
 src/cairoint.h      |   10 +++++++++
 2 files changed, 44 insertions(+), 20 deletions(-)

New commits:
diff-tree 7e9aad228971a81783e09edfef58c5165a3c932e (from 804e5b58cd3a4032bfa1d0c8cccac92a70c3c635)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 25 10:32:37 2006 -0700

    Fix repeating source surface patterns with xlib backend.
    
    This broke with the clone_similar optimization in
    8d7a02ed58e06584eb09575e6ca11d0a81094ab6 The optimization added an
    interest rectangle to clone_similar, but with a repeating source
    pattern, the interest rectangle might not intersect the extents of the
    surface at all.
    
    The test suite caught this with the trap-clip case.
    
    The fix here is to clone the entire surface if the pattern has an
    extend mode of REPEAT.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 08f2321..9589b34 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1159,29 +1159,43 @@ _cairo_pattern_acquire_surface_for_surfa
     }
     else
     {
-	/* Before we can clone, we must transform the rectangle to the
-	 * coordinate space of the source surface. */
-	if (! _cairo_matrix_is_identity (&attr->matrix)) {
-	    double src_x = x;
-	    double src_y = y;
-	    double src_width = width;
-	    double src_height = height;
-	    double x2, y2;
-	    cairo_bool_t is_tight;
-
-	    _cairo_matrix_transform_bounding_box  (&attr->matrix, &src_x, &src_y,
-						   &src_width, &src_height,
-						   &is_tight);
-	    x2 = src_x + src_width;
-	    y2 = src_y + src_height;
-	    x = floor (src_x);
-	    y = floor (src_y);
-	    width = ceil (x2) - x;
-	    height = ceil (y2) - y;
+	/* If we're repeating, we just play it safe and clone the entire surface. */
+	if (attr->extend == CAIRO_EXTEND_REPEAT) {
+	    cairo_rectangle_int16_t extents;
+	    status = _cairo_surface_get_extents (pattern->surface, &extents);
+	    x = extents.x;
+	    y = extents.y;
+	    width = extents.width;
+	    height = extents.height;
+	} else {
+	    /* Otherwise, we first transform the rectangle to the
+	     * coordinate space of the source surface so that we can
+	     * clone only that portion of the surface that will be
+	     * read. */
+	    if (! _cairo_matrix_is_identity (&attr->matrix)) {
+		double src_x = x;
+		double src_y = y;
+		double src_width = width;
+		double src_height = height;
+		double x2, y2;
+		cairo_bool_t is_tight;
+
+		_cairo_matrix_transform_bounding_box  (&attr->matrix, &src_x, &src_y,
+						       &src_width, &src_height,
+						       &is_tight);
+		x2 = src_x + src_width;
+		y2 = src_y + src_height;
+		x = floor (src_x);
+		y = floor (src_y);
+		width = ceil (x2) - x;
+		height = ceil (y2) - y;
+	    }
+	    x += tx;
+	    y += ty;
 	}
 
 	status = _cairo_surface_clone_similar (dst, pattern->surface,
-					       x+tx, y+ty, width, height, out);
+					       x, y, width, height, out);
     }
 
     return status;
diff --git a/src/cairoint.h b/src/cairoint.h
index 2c5856d..06fc8d4 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -720,6 +720,16 @@ struct _cairo_surface_backend {
 				 cairo_rectangle_int16_t *image_rect,
 				 void                    *image_extra);
 
+    /* Create a new surface (@clone_out) with the following
+     * characteristics:
+     *
+     * 1. It is as compatible as possible with @surface (in terms of
+     *    efficiency)
+     *
+     * 2. It has the same size as @src
+     *
+     * 3. It has the same contents as @src within the given rectangle.
+     */
     cairo_status_t
     (*clone_similar)            (void                   *surface,
 				 cairo_surface_t        *src,


More information about the cairo-commit mailing list