[cairo-commit] 8 commits - boilerplate/cairo-boilerplate.c src/cairo-glitz-surface.c src/cairoint.h src/cairo-matrix.c src/cairo-pattern.c src/cairo-svg-surface.c src/cairo-win32-printing-surface.c test/filter-bilinear-extents.c test/filter-bilinear-extents-pdf-ref.png test/filter-bilinear-extents-ps2-ref.png test/filter-bilinear-extents-ps3-ref.png test/Makefile.am test/paint-source-alpha-svg11-ref.png test/scale-source-surface-paint-svg11-argb32-ref.png test/scale-source-surface-paint-svg11-rgb24-ref.png test/scale-source-surface-paint-svg12-argb32-ref.png test/scale-source-surface-paint-svg12-rgb24-ref.png

Chris Wilson ickle at kemper.freedesktop.org
Mon Sep 29 02:13:19 PDT 2008


 boilerplate/cairo-boilerplate.c                      |    8 -
 src/cairo-glitz-surface.c                            |    6 
 src/cairo-matrix.c                                   |   29 +++
 src/cairo-pattern.c                                  |  149 +++++++++++++------
 src/cairo-svg-surface.c                              |   16 --
 src/cairo-win32-printing-surface.c                   |   41 ++---
 src/cairoint.h                                       |    3 
 test/Makefile.am                                     |   35 ++++
 test/filter-bilinear-extents-pdf-ref.png             |binary
 test/filter-bilinear-extents-ps2-ref.png             |binary
 test/filter-bilinear-extents-ps3-ref.png             |binary
 test/filter-bilinear-extents.c                       |   45 +++--
 test/paint-source-alpha-svg11-ref.png                |binary
 test/scale-source-surface-paint-svg11-argb32-ref.png |binary
 test/scale-source-surface-paint-svg11-rgb24-ref.png  |binary
 test/scale-source-surface-paint-svg12-argb32-ref.png |binary
 test/scale-source-surface-paint-svg12-rgb24-ref.png  |binary
 17 files changed, 231 insertions(+), 101 deletions(-)

New commits:
commit 3b33d49d37a5751e7848516c468b323e19c34bea
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Sep 29 08:14:24 2008 +0100

    [test/filter-bilinear-extents] Remove XFAIL.
    
    With the reintroduction of Carl Worth's and Owen Taylor's work to expand
    pattern extents as necessary to include extra samples due to the filter
    radius, we expect filter-bilinear-extents to PASS. This patch series is
    important as it factors out our assumptions about filter radius into a
    single function and cleans up the code in its wake.
    
    However, since the external PS/PDF renderers do not necessarily use the same
    filter as cairo (and currently they only use NEAREST due to lack of
    /Interpolate emission in those backends) we can expect differences in test
    output. So add the respective reference images to capture current
    expectations and to highlight future changes.
    
    Fixes bugs:
      Bug 15349 - bad clipping with EXTEND_NONE
      [https://bugs.freedesktop.org/show_bug.cgi?id=15349],
      Bug 15367 -Improve filtering handling in cairo-pattern.c
      [https://bugs.freedesktop.org/show_bug.cgi?id=15367]

diff --git a/test/Makefile.am b/test/Makefile.am
index 4ad2a4e..34c3a05 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -477,6 +477,9 @@ REFERENCE_IMAGES = \
 	fill-rule-ref.png	\
 	fill-rule-rgb24-ref.png	\
 	filter-bilinear-extents-ref.png \
+	filter-bilinear-extents-pdf-ref.png \
+	filter-bilinear-extents-ps2-ref.png \
+	filter-bilinear-extents-ps3-ref.png \
 	filter-nearest-offset-ref.png	\
 	finer-grained-fallbacks-ref.png			\
 	finer-grained-fallbacks-rgb24-ref.png		\
@@ -916,6 +919,37 @@ $(REFERENCE_IMAGES)
 # Of course, before any "release" of cairo we should eliminate
 # everything from this list by fixing the bugs. (We don't necessarily
 # have to be that strict for "snapshots" though.)
+#
+# Analysis of XFAIL errors:
+# alpha-similar         - discrepancy between backends in applying color
+#                         components of a pure alpha surface
+# big-line              - range overflow of fixed-point
+# big-trap              - range overflow of fixed-point
+# degenerate-path       - undefined behaviour in PS, needs path editing to
+#                         convert degenerate segments into circles/rectangles
+#                         as expected by cairo
+# device-offset-scale   - complication of pre-multiplying device_offset
+#                         into the pattern_matrix and then requiring futher
+#                         manipulation for SVG
+# extend-pad            - lacks implementation in pixman and consequently used
+#                         as an excuse for lack of support in other backends
+# filter-nearest-offset - banker's rounding vs arthimetic rounding in
+#                         double to fixed-point conversion
+# long-lines            - range overflow of fixed-point
+# self-copy-overlap     - vector surfaces take snapshot of patterns in contrast
+#                         to the raster backends which don't. One solution
+#                         would be to clone overlapping areas of dst/source, so
+#                         patterns were effectively snapshotted across all
+#                         backends.
+# self-intersecting     - incremental trapezoidation of strokes can generate
+#                         overlapping traps. Needs self-intersection analysis
+#                         on cairo_traps_t after strokes.
+#                         Test case should also be expanded to hit special-case
+#                         tessellators as well.
+# surface-pattern*      - old bugs in pixman, but fails PS/PDF due to lack of
+#                         /Interpolate support - which causes a half-pixel
+#                         shift in GS (and consequently virtually every
+#                         image/fallback-image using test to FAIL).
 XFAIL_TESTS =					\
 alpha-similar$(EXEEXT)				\
 big-line$(EXEEXT)				\
@@ -924,7 +958,6 @@ degenerate-path$(EXEEXT)			\
 device-offset-scale$(EXEEXT)			\
 extend-pad$(EXEEXT)				\
 filter-nearest-offset$(EXEEXT)			\
-filter-bilinear-extents$(EXEEXT)		\
 long-lines$(EXEEXT)				\
 self-copy-overlap$(EXEEXT)			\
 self-intersecting$(EXEEXT)			\
diff --git a/test/filter-bilinear-extents-pdf-ref.png b/test/filter-bilinear-extents-pdf-ref.png
new file mode 100644
index 0000000..014b715
Binary files /dev/null and b/test/filter-bilinear-extents-pdf-ref.png differ
diff --git a/test/filter-bilinear-extents-ps2-ref.png b/test/filter-bilinear-extents-ps2-ref.png
new file mode 100644
index 0000000..da58907
Binary files /dev/null and b/test/filter-bilinear-extents-ps2-ref.png differ
diff --git a/test/filter-bilinear-extents-ps3-ref.png b/test/filter-bilinear-extents-ps3-ref.png
new file mode 100644
index 0000000..da58907
Binary files /dev/null and b/test/filter-bilinear-extents-ps3-ref.png differ
commit 5eec3e378afd6ff9991cea8e42b8478eb3e79773
Author: Owen W. Taylor <otaylor at fishsoup.net>
Date:   Mon Sep 29 00:53:59 2008 +0100

    [pattern] Improve handling of filter radius and optimize when possible.
    
    Factor out common filter analysis code from _cairo_pattern_get_extents()
    so that we can share it with _cairo_pattern_acquire_surface_for_surface()
    as well. During the analysis of the filter determine whether the pattern
    matrix maps source pixels exactly onto destination pixels and if so convert
    the filter to NEAREST - generalising the existing conversion to NEAREST.
    
    (Patch ported to master by Chris Wilson, all bugs are his.)

diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index 9277e7c..ca18323 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -624,6 +624,35 @@ _cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix,
     return FALSE;
 }
 
+/* By pixel exact here, we mean a matrix that is composed only of
+ * 90 degree rotations, flips, and integer translations and produces a 1:1
+ * mapping between source and destination pixels. If we transform an image
+ * with a pixel-exact matrix, filtering is not useful.
+ */
+cairo_private cairo_bool_t
+_cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix)
+{
+    cairo_fixed_t x0_fixed, y0_fixed;
+
+    if (matrix->xy == 0.0 && matrix->yx == 0.0) {
+	if (! (matrix->xx == 1.0 || matrix->xx == -1.0))
+	    return FALSE;
+	if (! (matrix->yy == 1.0 || matrix->yy == -1.0))
+	    return FALSE;
+    } else if (matrix->xx == 0.0 && matrix->yy == 0.0) {
+	if (! (matrix->xy == 1.0 || matrix->xy == -1.0))
+	    return FALSE;
+	if (! (matrix->yx == 1.0 || matrix->yx == -1.0))
+	    return FALSE;
+    } else
+	return FALSE;
+
+    x0_fixed = _cairo_fixed_from_double (matrix->x0);
+    y0_fixed = _cairo_fixed_from_double (matrix->y0);
+
+    return _cairo_fixed_is_integer (x0_fixed) && _cairo_fixed_is_integer (y0_fixed);
+}
+
 /*
   A circle in user space is transformed into an ellipse in device space.
 
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 60cd4a3..5bfeb5b 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1662,6 +1662,65 @@ _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern)
     return FALSE;
 }
 
+/**
+ * _cairo_pattern_analyze_filter
+ * @pattern: surface pattern
+ * @pad_out: location to store necessary padding in the source image, or %NULL
+ *
+ * Returns the optimized #cairo_filter_t to use with @pattern.
+ *
+ * Analyze the filter to determine how much extra needs to be sampled
+ * from the source image to account for the filter radius and whether
+ * we can optimize the filter to a simpler value.
+ *
+ * XXX: We don't actually have any way of querying the backend for
+ *      the filter radius, so we just guess base on what we know that
+ *      backends do currently (see bug #10508)
+ */
+static cairo_filter_t
+_cairo_pattern_analyze_filter (cairo_surface_pattern_t *pattern,
+			       double                  *pad_out)
+{
+    double pad;
+    cairo_filter_t optimized_filter;
+
+    switch (pattern->base.filter) {
+    case CAIRO_FILTER_GOOD:
+    case CAIRO_FILTER_BEST:
+    case CAIRO_FILTER_BILINEAR:
+	/* If source pixels map 1:1 onto destination pixels, we do
+	 * not need to filter (and do not want to filter, since it
+	 * will cause blurriness)
+	 */
+	if (_cairo_matrix_is_pixel_exact (&pattern->base.matrix)) {
+	    pad = 0.;
+	    optimized_filter = CAIRO_FILTER_NEAREST;
+	} else {
+	    /* 0.5 is enough for a bilinear filter. It's possible we
+	     * should defensively use more for CAIRO_FILTER_BEST, but
+	     * without a single example, it's hard to know how much
+	     * more would be defensive...
+	     */
+	    pad = 0.5;
+	    optimized_filter = pattern->base.filter;
+	}
+	break;
+
+    case CAIRO_FILTER_FAST:
+    case CAIRO_FILTER_NEAREST:
+    case CAIRO_FILTER_GAUSSIAN:
+    default:
+	pad = 0.;
+	optimized_filter = pattern->base.filter;
+	break;
+    }
+
+    if (pad_out)
+	*pad_out = pad;
+
+    return optimized_filter;
+}
+
 static cairo_int_status_t
 _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
 					    cairo_surface_t	       *dst,
@@ -1674,18 +1733,20 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
 {
     cairo_int_status_t status;
     int tx, ty;
+    double pad;
 
     attr->acquired = FALSE;
 
     attr->extend = pattern->base.extend;
-    attr->filter = pattern->base.filter;
+    attr->filter = _cairo_pattern_analyze_filter (pattern, &pad);
+
     if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
 					      &tx, &ty))
     {
 	cairo_matrix_init_identity (&attr->matrix);
 	attr->x_offset = tx;
 	attr->y_offset = ty;
-	attr->filter = CAIRO_FILTER_NEAREST;
+	assert (attr->filter == CAIRO_FILTER_NEAREST);
     }
     else
     {
@@ -1812,14 +1873,10 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
 						       &x1, &y1, &x2, &y2,
 						       NULL);
 
-		/* XXX: The one padding here is to account for filter
-		 * radius.  It's a workaround right now, until we get a
-		 * proper fix. (see bug #10508)
-		 */
-		sampled_area.x = floor (x1) - 1;
-		sampled_area.y = floor (y1) - 1;
-		sampled_area.width  = ceil (x2) + 1 - sampled_area.x;
-		sampled_area.height = ceil (y2) + 1 - sampled_area.y;
+		sampled_area.x = floor (x1) - pad;
+		sampled_area.y = floor (y1) - pad;
+		sampled_area.width  = ceil (x2) + pad - sampled_area.x;
+		sampled_area.height = ceil (y2) + pad - sampled_area.y;
 	    }
 
 	    sampled_area.x += tx;
@@ -1859,6 +1916,9 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
  * A convenience function to obtain a surface to use as the source for
  * drawing on @dst.
  *
+ * Note that this function is only suitable for use when the destination
+ * surface is pixel based and 1 device unit maps to one pixel.
+ *
  * Return value: %CAIRO_STATUS_SUCCESS if a surface was stored in @surface_out.
  **/
 cairo_int_status_t
@@ -2088,37 +2148,20 @@ _cairo_pattern_get_extents (cairo_pattern_t         *pattern,
 	cairo_surface_t *surface = surface_pattern->surface;
 	cairo_matrix_t imatrix;
 	double x1, y1, x2, y2;
+	double pad;
 
 	status = _cairo_surface_get_extents (surface, &surface_extents);
 	if (status)
 	    return status;
 
-	x1 = surface_extents.x;
-	y1 = surface_extents.y;
-	x2 = x1 + surface_extents.width;
-	y2 = y1 + surface_extents.height;
-
 	/* The filter can effectively enlarge the extents of the
-	 * pattern, so extend as necessary. Note: We aren't doing any
-	 * backend-specific querying of filter box sizes at this time,
-	 * (since currently no specific backends that could do custom
-	 * filters are calling _cairo_pattern_get_extents). */
-	switch (pattern->filter) {
-	case CAIRO_FILTER_GOOD:
-	case CAIRO_FILTER_BEST:
-	case CAIRO_FILTER_BILINEAR:
-	    x1 -= 0.5;
-	    y1 -= 0.5;
-	    x2 += 0.5;
-	    y2 += 0.5;
-	    break;
-	case CAIRO_FILTER_FAST:
-	case CAIRO_FILTER_NEAREST:
-	case CAIRO_FILTER_GAUSSIAN:
-	default:
-	    /* Nothing to do */
-	    break;
-	}
+	 * pattern, so extend as necessary.
+	 */
+	_cairo_pattern_analyze_filter (surface_pattern, &pad);
+	x1 = surface_extents.x - pad;
+	y1 = surface_extents.y - pad;
+	x2 = surface_extents.x + surface_extents.width + pad;
+	y2 = surface_extents.y + surface_extents.height + pad;
 
 	imatrix = pattern->matrix;
 	status = cairo_matrix_invert (&imatrix);
diff --git a/src/cairoint.h b/src/cairoint.h
index 323004c..8b2bd49 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2164,6 +2164,9 @@ cairo_private cairo_bool_t
 _cairo_matrix_is_integer_translation(const cairo_matrix_t *matrix,
 				     int *itx, int *ity);
 
+cairo_private cairo_bool_t
+_cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix);
+
 cairo_private double
 _cairo_matrix_transformed_circle_major_axis(cairo_matrix_t *matrix, double radius);
 
commit 7d7057cf8896a3558fadc35d160d3bc667972800
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Apr 4 19:00:28 2008 -0700

    _cairo_pattern_get_extents: Fix to allow for expansion based on filter
    
    This fixes the filter-bilinear-extents test case and the
    related bug entry:
    
    	bad clipping with EXTEND_NONE
    	http://bugs.freedesktop.org/show_bug.cgi?id=15349
    
    Though there are still differences in the PDF and PostScript
    backends, (primarily because we can't capture cairo's filter
    modes in those file formats).

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 5c1a02d..60cd4a3 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -2098,6 +2098,28 @@ _cairo_pattern_get_extents (cairo_pattern_t         *pattern,
 	x2 = x1 + surface_extents.width;
 	y2 = y1 + surface_extents.height;
 
+	/* The filter can effectively enlarge the extents of the
+	 * pattern, so extend as necessary. Note: We aren't doing any
+	 * backend-specific querying of filter box sizes at this time,
+	 * (since currently no specific backends that could do custom
+	 * filters are calling _cairo_pattern_get_extents). */
+	switch (pattern->filter) {
+	case CAIRO_FILTER_GOOD:
+	case CAIRO_FILTER_BEST:
+	case CAIRO_FILTER_BILINEAR:
+	    x1 -= 0.5;
+	    y1 -= 0.5;
+	    x2 += 0.5;
+	    y2 += 0.5;
+	    break;
+	case CAIRO_FILTER_FAST:
+	case CAIRO_FILTER_NEAREST:
+	case CAIRO_FILTER_GAUSSIAN:
+	default:
+	    /* Nothing to do */
+	    break;
+	}
+
 	imatrix = pattern->matrix;
 	status = cairo_matrix_invert (&imatrix);
 	/* cairo_pattern_set_matrix ensures the matrix is invertible */
diff --git a/test/paint-source-alpha-svg11-ref.png b/test/paint-source-alpha-svg11-ref.png
index 3b3a990..8736d44 100644
Binary files a/test/paint-source-alpha-svg11-ref.png and b/test/paint-source-alpha-svg11-ref.png differ
diff --git a/test/scale-source-surface-paint-svg11-argb32-ref.png b/test/scale-source-surface-paint-svg11-argb32-ref.png
index de274f9..ed946d4 100644
Binary files a/test/scale-source-surface-paint-svg11-argb32-ref.png and b/test/scale-source-surface-paint-svg11-argb32-ref.png differ
diff --git a/test/scale-source-surface-paint-svg11-rgb24-ref.png b/test/scale-source-surface-paint-svg11-rgb24-ref.png
index 099b8a0..d424dce 100644
Binary files a/test/scale-source-surface-paint-svg11-rgb24-ref.png and b/test/scale-source-surface-paint-svg11-rgb24-ref.png differ
diff --git a/test/scale-source-surface-paint-svg12-argb32-ref.png b/test/scale-source-surface-paint-svg12-argb32-ref.png
index de274f9..ed946d4 100644
Binary files a/test/scale-source-surface-paint-svg12-argb32-ref.png and b/test/scale-source-surface-paint-svg12-argb32-ref.png differ
diff --git a/test/scale-source-surface-paint-svg12-rgb24-ref.png b/test/scale-source-surface-paint-svg12-rgb24-ref.png
index 099b8a0..d424dce 100644
Binary files a/test/scale-source-surface-paint-svg12-rgb24-ref.png and b/test/scale-source-surface-paint-svg12-rgb24-ref.png differ
commit 6ef4bd4ecfa30f00ad0fe6e5e5f1d1a0a5dfe8e3
Author: Owen W. Taylor <otaylor at fishsoup.net>
Date:   Sun Sep 28 23:30:22 2008 +0100

    [pattern] Fix acquiring outside of source bounds
    
    Restrict the area we acquire from the source image to the bounds of
    the source image, even when we have an identity matrix. This handles
    circumstances where the pattern extents may be enlarged due to
    filtering, for example when applying a bilinear filter.
    
    This patch replaces the open-coded rectangle intersection which has
    already proven itself to be a source of bugs.
    
    (Patch ported to master by Chris Wilson, all bugs are his.)

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 07e8cc1..5c1a02d 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1768,8 +1768,7 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
 	return status;
     }
 
-    if (_cairo_surface_is_image (dst))
-    {
+    if (_cairo_surface_is_image (dst)) {
 	cairo_image_surface_t *image;
 
 	status = _cairo_surface_acquire_source_image (pattern->surface,
@@ -1780,57 +1779,59 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
 
 	*out = &image->base;
 	attr->acquired = TRUE;
-    }
-    else
-    {
+    } else {
 	cairo_rectangle_int_t extents;
+
 	status = _cairo_surface_get_extents (pattern->surface, &extents);
 	if (status)
 	    return status;
 
-	/* If we're repeating, we just play it safe and clone the entire surface. */
-	if (attr->extend == CAIRO_EXTEND_REPEAT) {
-	    x = extents.x;
-	    y = extents.y;
-	    width = extents.width;
-	    height = extents.height;
-	} else {
+	/* If we're repeating, we just play it safe and clone the
+	 * entire surface - i.e. we use the existing extents.
+	 */
+	if (attr->extend != CAIRO_EXTEND_REPEAT) {
+	    cairo_rectangle_int_t sampled_area;
+
 	    /* 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)) {
+	     * read.
+	     */
+	    if (_cairo_matrix_is_identity (&attr->matrix)) {
+		sampled_area.x = x;
+		sampled_area.y = y;
+		sampled_area.width  = width;
+		sampled_area.height = height;
+	    } else {
 		double x1 = x;
 		double y1 = y;
 		double x2 = x + width;
 		double y2 = y + height;
-		cairo_bool_t is_tight;
 
 		_cairo_matrix_transform_bounding_box  (&attr->matrix,
 						       &x1, &y1, &x2, &y2,
-						       &is_tight);
-
-		/* The transform_bounding_box call may have resulted
-		 * in a region larger than the surface, but we never
-		 * want to clone more than the surface itself, (we
-		 * know we're not repeating at this point due to the
-		 * above.
-		 *
-		 * XXX: The one padding here is to account for filter
+						       NULL);
+
+		/* XXX: The one padding here is to account for filter
 		 * radius.  It's a workaround right now, until we get a
 		 * proper fix. (see bug #10508)
 		 */
-		x = MAX (0, floor (x1) - 1);
-		y = MAX (0, floor (y1) - 1);
-		width = MAX (MIN (extents.width, ceil (x2) + 1) - x, 0);
-		height = MAX (MIN (extents.height, ceil (y2) + 1) - y, 0);
+		sampled_area.x = floor (x1) - 1;
+		sampled_area.y = floor (y1) - 1;
+		sampled_area.width  = ceil (x2) + 1 - sampled_area.x;
+		sampled_area.height = ceil (y2) + 1 - sampled_area.y;
 	    }
-	    x += tx;
-	    y += ty;
+
+	    sampled_area.x += tx;
+	    sampled_area.y += ty;
+
+	    /* Never acquire a larger area than the source itself */
+	    _cairo_rectangle_intersect (&extents, &sampled_area);
 	}
 
 	status = _cairo_surface_clone_similar (dst, pattern->surface,
-					       x, y, width, height,
+					       extents.x, extents.y,
+					       extents.width, extents.height,
 					       &x, &y, out);
 	if (status == CAIRO_STATUS_SUCCESS && (x != 0 || y != 0)) {
 	    cairo_matrix_t m;
commit 6d0f2c4421e34a078469a81646a52dfa47b4dcf1
Author: Owen W. Taylor <otaylor at fishsoup.net>
Date:   Mon Sep 29 00:02:18 2008 +0100

    [pattern] Remove the hack to support cloning surface patterns.
    
    Remove instances (abuses) of calling _cairo_pattern_acquire_surface() on
    a known-surface-pattern with a hack to say "give me the entire surface".
    If you know you just want the entire surface as an image surface, that
    can be done more simply.
    
    (Split from original patch on
    https://bugs.freedesktop.org/attachment.cgi?id=15703, by Chris Wilson -
    as usual all bugs are his.)

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index fce9b6b..07e8cc1 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1789,10 +1789,7 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
 	    return status;
 
 	/* If we're repeating, we just play it safe and clone the entire surface. */
-	/* If requested width and height are -1, clone the entire surface.
-	 * This is relied on in the svg backend. */
-	if (attr->extend == CAIRO_EXTEND_REPEAT ||
-	    (width == (unsigned int) -1 && height == (unsigned int) -1)) {
+	if (attr->extend == CAIRO_EXTEND_REPEAT) {
 	    x = extents.x;
 	    y = extents.y;
 	    width = extents.width;
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index ec744b0..ecb7163 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -1033,23 +1033,15 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t   *output
 						 const cairo_matrix_t	 *parent_matrix,
 						 const char		 *extra_attributes)
 {
-    cairo_surface_t *surface;
     cairo_surface_attributes_t surface_attr;
     cairo_rectangle_int_t extents;
     cairo_status_t status;
     cairo_matrix_t p2u;
 
-    status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern,
-					     (cairo_surface_t *)svg_surface,
-					     0, 0, (unsigned int)-1, (unsigned int)-1,
-					     &surface, &surface_attr);
+    status = _cairo_surface_get_extents (pattern->surface, &extents);
     if (status)
 	return status;
 
-    status = _cairo_surface_get_extents (surface, &extents);
-    if (status)
-	goto FAIL;
-
     p2u = pattern->base.matrix;
     status = cairo_matrix_invert (&p2u);
     /* cairo_pattern_set_matrix ensures the matrix is invertible */
@@ -1080,17 +1072,13 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t   *output
 
     _cairo_output_stream_printf (output, " xlink:href=\"");
 
-    status = _cairo_surface_base64_encode (surface, output);
+    status = _cairo_surface_base64_encode (pattern->surface, output);
 
     _cairo_output_stream_printf (output, "\"/>\n");
 
     if (pattern_id != invalid_pattern_id)
 	_cairo_output_stream_printf (output, "</pattern>\n");
 
-  FAIL:
-    _cairo_pattern_release_surface ((cairo_pattern_t *)pattern,
-				    surface, &surface_attr);
-
     return status;
 }
 
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 55d5b19..1ffedad 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -490,7 +490,6 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
 {
     cairo_status_t status;
     cairo_extend_t extend;
-    cairo_surface_t *pat_surface;
     cairo_surface_attributes_t pat_attr;
     cairo_image_surface_t *image;
     void *image_extra;
@@ -516,25 +515,20 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
 	background_color = CAIRO_COLOR_BLACK;
 
     extend = cairo_pattern_get_extend (&pattern->base);
-    status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern,
-					     (cairo_surface_t *)surface,
-					     0, 0, -1, -1,
-					     &pat_surface, &pat_attr);
-    if (status)
-	return status;
 
-    status = _cairo_surface_acquire_source_image (pat_surface, &image, &image_extra);
+    status = _cairo_surface_acquire_source_image (pattern->surface,
+						  &image, &image_extra);
     if (status)
-	goto FINISH;
+	return status;
 
     if (image->base.status) {
 	status = image->base.status;
-	goto FINISH2;
+	goto CLEANUP_IMAGE;
     }
 
     if (image->width == 0 || image->height == 0) {
 	status = CAIRO_STATUS_SUCCESS;
-	goto FINISH2;
+	goto CLEANUP_IMAGE;
     }
 
     if (image->format != CAIRO_FORMAT_RGB24) {
@@ -545,7 +539,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
 						     image->height);
 	if (opaque_surface->status) {
 	    status = opaque_surface->status;
-	    goto FINISH3;
+	    goto CLEANUP_OPAQUE_IMAGE;
 	}
 
 	_cairo_pattern_init_for_surface (&opaque_pattern, &image->base);
@@ -557,7 +551,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
 						image->width, image->height);
 	if (status) {
 	    _cairo_pattern_fini (&opaque_pattern.base);
-	    goto FINISH3;
+	    goto CLEANUP_OPAQUE_IMAGE;
 	}
 
 	status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
@@ -571,7 +565,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
 					   image->height);
 	if (status) {
 	    _cairo_pattern_fini (&opaque_pattern.base);
-	    goto FINISH3;
+	    goto CLEANUP_OPAQUE_IMAGE;
 	}
 
 	_cairo_pattern_fini (&opaque_pattern.base);
@@ -602,8 +596,10 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
     SaveDC (surface->dc);
     _cairo_matrix_to_win32_xform (&m, &xform);
 
-    if (!SetWorldTransform (surface->dc, &xform))
-	return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform");
+    if (! SetWorldTransform (surface->dc, &xform)) {
+	status = _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform");
+	goto CLEANUP_OPAQUE_IMAGE;
+    }
 
     oldmode = SetStretchBltMode(surface->dc, HALFTONE);
 
@@ -635,19 +631,20 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
 				&bi,
 				DIB_RGB_COLORS,
 				SRCCOPY))
-		return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)");
+	    {
+		status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)");
+		goto CLEANUP_OPAQUE_IMAGE;
+	    }
 	}
     }
     SetStretchBltMode(surface->dc, oldmode);
     RestoreDC (surface->dc, -1);
 
-FINISH3:
+CLEANUP_OPAQUE_IMAGE:
     if (opaque_image != image)
 	cairo_surface_destroy (opaque_surface);
-FINISH2:
-    _cairo_surface_release_source_image (pat_surface, image, image_extra);
-FINISH:
-    _cairo_pattern_release_surface ((cairo_pattern_t *)pattern, pat_surface, &pat_attr);
+CLEANUP_IMAGE:
+    _cairo_surface_release_source_image (pattern->surface, image, image_extra);
 
     return status;
 }
commit 117f643e49615295eb37af24efffd8327429cbf9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Sep 28 22:42:30 2008 +0100

    [test/filter-bilinear-extents] Extend testing.
    
    First, explicitly set the filter mode to BILINEAR in case the default should
    ever change. And then draw a second pattern with extents that in theory
    are larger than the source surface in order to test handling of acquiring
    out-of-bounds extents.

diff --git a/test/filter-bilinear-extents.c b/test/filter-bilinear-extents.c
index 666b7b3..53789ab 100644
--- a/test/filter-bilinear-extents.c
+++ b/test/filter-bilinear-extents.c
@@ -54,34 +54,51 @@ static const cairo_test_t test = {
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
-    cairo_surface_t *checker;
+    cairo_surface_t *image;
     cairo_t *cr2;
 
-    /* Create a 2x2 blue+red checker */
-    checker = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 2, 2);
-    cr2 = cairo_create (checker);
+    image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 2, 2);
 
-    cairo_set_source_rgb (cr2, 1, 0 ,0); /* red */
+    /* Fill with an opaque background to avoid a separate rgb24 ref image */
+    cairo_set_source_rgb (cr, 0, 0, 0);
+    cairo_paint (cr);
+
+    /* First check handling of pattern extents > surface extents */
+    cairo_save (cr);
+    cairo_scale (cr, width/2., height/2.);
+
+    /* Create a solid black source to merge with the background */
+    cr2 = cairo_create (image);
+    cairo_set_source_rgb (cr2, 0, 0 ,0);
     cairo_paint (cr2);
-    cairo_set_source_rgb (cr2, 0, 0, 1); /* blue */
-    cairo_rectangle (cr2, 0, 1, 1, 1);
-    cairo_rectangle (cr2, 1, 0, 1, 1);
-    cairo_fill (cr2);
+    cairo_set_source_surface (cr, cairo_get_target (cr2), 0, 0);
     cairo_destroy (cr2);
-
-    /* Draw our surface scaled with EXTEND_NONE */
-    cairo_set_source_rgb (cr, 0, 0, 0);
+    cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_BILINEAR);
     cairo_paint (cr);
+    cairo_restore (cr);
 
+    /* Then scale to smaller so we can see the full bilinear extents */
     cairo_save (cr);
     cairo_translate (cr, PAD, PAD);
     cairo_scale (cr, SCALE, SCALE);
     cairo_translate (cr, 0.5, 0.5);
-    cairo_set_source_surface (cr, checker, 0, 0);
+
+    /* Create a 2x2 blue+red checkerboard source */
+    cr2 = cairo_create (image);
+    cairo_set_source_rgb (cr2, 1, 0 ,0); /* red */
+    cairo_paint (cr2);
+    cairo_set_source_rgb (cr2, 0, 0, 1); /* blue */
+    cairo_rectangle (cr2, 0, 1, 1, 1);
+    cairo_rectangle (cr2, 1, 0, 1, 1);
+    cairo_fill (cr2);
+    cairo_set_source_surface (cr, cairo_get_target (cr2), 0, 0);
+    cairo_destroy (cr2);
+
+    cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_BILINEAR);
     cairo_paint (cr);
     cairo_restore (cr);
 
-    cairo_surface_destroy (checker);
+    cairo_surface_destroy (image);
 
     return CAIRO_TEST_SUCCESS;
 }
commit 3ff86a4510b718a3154b56b052be786f9495a3b0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Sep 29 08:38:31 2008 +0100

    [test] Disable caching of SVG fail/pass surfaces.
    
    As we use cairo to convert SVG files back to an image, that process is
    dependent upon changes within our library and so we cannot skip the
    conversion if the SVG file happens to match a previous run. Fortunately,
    librsvg is quick enough that this is not a major issue.

diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index cc64490..34b9133 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -509,7 +509,7 @@ static cairo_boilerplate_target_t targets[] =
      * systems get an error of 1 for some pixels on some of the text
      * tests. XXX: I'd still like to chase these down at some point.
      * For now just set the svg error tolerance to 1. */
-    { "svg11", ".svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA, 1,
+    { "svg11", NULL, CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA, 1,
       _cairo_boilerplate_svg11_create_surface,
       _cairo_boilerplate_svg_force_fallbacks,
       _cairo_boilerplate_svg_finish_surface,
@@ -517,7 +517,7 @@ static cairo_boilerplate_target_t targets[] =
       _cairo_boilerplate_svg_surface_write_to_png,
       _cairo_boilerplate_svg_cleanup,
       NULL, TRUE },
-    { "svg11", ".svg", CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
+    { "svg11", NULL, CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
       _cairo_boilerplate_svg11_create_surface,
       _cairo_boilerplate_svg_force_fallbacks,
       _cairo_boilerplate_svg_finish_surface,
@@ -525,7 +525,7 @@ static cairo_boilerplate_target_t targets[] =
       _cairo_boilerplate_svg_surface_write_to_png,
       _cairo_boilerplate_svg_cleanup,
       NULL, TRUE },
-    { "svg12", ".svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA, 1,
+    { "svg12", NULL, CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA, 1,
       _cairo_boilerplate_svg12_create_surface,
       _cairo_boilerplate_svg_force_fallbacks,
       _cairo_boilerplate_svg_finish_surface,
@@ -533,7 +533,7 @@ static cairo_boilerplate_target_t targets[] =
       _cairo_boilerplate_svg_surface_write_to_png,
       _cairo_boilerplate_svg_cleanup,
       NULL, TRUE },
-    { "svg12", ".svg", CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
+    { "svg12", NULL, CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
       _cairo_boilerplate_svg12_create_surface,
       _cairo_boilerplate_svg_force_fallbacks,
       _cairo_boilerplate_svg_finish_surface,
commit 24b22f0d2161f7a4ce75ceb2a86a77737027ee56
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Sep 29 07:52:09 2008 +0100

    [glitz] Compile fix for typo.
    
    I wonder whether merely fixing a compile error in glitz will do anything
    towards its utility... Anyway fix the missing comma as reported by
    Shunichi Fuji and correct the asserts.

diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index b2046fb..71a5b9d 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -2261,14 +2261,14 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
 							glyph_width,
 							glyph_height,
 							&clone_offset_x,
-							&clone_offset_y
+							&clone_offset_y,
 							(cairo_surface_t **)
 							&clone);
 		if (status)
 		    goto UNLOCK;
 
-		assert (clone_offset_x = 0);
-		assert (clone_offset_y = 0);
+		assert (clone_offset_x == 0);
+		assert (clone_offset_y == 0);
 
 		x_offset = scaled_glyphs[i]->surface->base.device_transform.x0;
 		y_offset = scaled_glyphs[i]->surface->base.device_transform.y0;


More information about the cairo-commit mailing list