[cairo-commit] 4 commits - src/cairo-pdf-surface.c src/cairo-ps-surface.c test/.gitignore test/Makefile.am test/paint-repeat.c test/paint-repeat-ref.png

Carl Worth cworth at kemper.freedesktop.org
Wed Oct 25 12:52:05 PDT 2006


 src/cairo-pdf-surface.c   |    2 -
 src/cairo-ps-surface.c    |   84 +++++++++++++++++++++++++++++++---------------
 test/.gitignore           |    1 
 test/Makefile.am          |    2 +
 test/paint-repeat-ref.png |binary
 test/paint-repeat.c       |   68 +++++++++++++++++++++++++++++++++++++
 6 files changed, 129 insertions(+), 28 deletions(-)

New commits:
diff-tree 02096f66f365c109ddf41432b9a818726d45cbae (from 7955fe63cc6bdb3a525535c7f052ea354cc7497c)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 25 12:51:35 2006 -0700

    Fix typo

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 447ebdd..6db28ec 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -880,7 +880,7 @@ emit_surface_pattern (cairo_pdf_surface_
 	xstep = image->width;
 	ystep = image->height;
 	break;
-    /* All the reset should have been analyzed away, so this case
+    /* All the rest should have been analyzed away, so this case
      * should be unreachable. */
     case CAIRO_EXTEND_REFLECT:
     case CAIRO_EXTEND_PAD:
diff-tree 7955fe63cc6bdb3a525535c7f052ea354cc7497c (from 76f816c765a19a4fcda0500b5495bb969d014958)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 25 12:51:17 2006 -0700

    Fix offset/extent bug in ps output for repeating source surface patterns
    
    The bug was exposed by the recent addition of the paint-repeat test.
    The ps output was crashing various interpreters by using infinite
    extents for repeating patterns. Fixing that was easy enough, but
    the offset of the repeating pattern was still being lost. The fix
    for both involved imitating the style of emit_surface_pattern as
    it exists in cairo-pdf-surface.c, (though the details are quite
    different due to differences in the models of PS and PDF).

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index cc95f2e..25b9f6b 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1667,55 +1667,84 @@ emit_solid_pattern (cairo_ps_surface_t *
 
 static void
 emit_surface_pattern (cairo_ps_surface_t *surface,
-		      cairo_surface_pattern_t *pattern,
-		      double x, double y)
+		      cairo_surface_pattern_t *pattern)
 {
-    cairo_rectangle_int16_t extents;
+    double bbox_width, bbox_height;
+    int xstep, ystep;
+    cairo_matrix_t inverse = pattern->base.matrix;
+    cairo_matrix_invert (&inverse);
 
     if (_cairo_surface_is_meta (pattern->surface)) {
 	_cairo_output_stream_printf (surface->stream, "/MyPattern {\n");
 	_cairo_meta_surface_replay (pattern->surface, &surface->base);
-	extents.width = surface->width;
-	extents.height = surface->height;
+	bbox_width = surface->width;
+	bbox_height = surface->height;
+	xstep = surface->width;
+	ystep = surface->height;
 	_cairo_output_stream_printf (surface->stream, "} bind def\n");
     } else {
 	cairo_image_surface_t	*image;
 	void			*image_extra;
 	cairo_status_t		status;
-	cairo_matrix_t		inverse = pattern->base.matrix;
-
-	cairo_matrix_invert (&inverse);
 
 	status = _cairo_surface_acquire_source_image (pattern->surface,
 						      &image,
 						      &image_extra);
 	assert (status == CAIRO_STATUS_SUCCESS);
 
-	_cairo_pattern_get_extents (&pattern->base, &extents);
-
 	emit_image (surface, image, &pattern->base.matrix, "MyPattern");
+
+	bbox_width = image->width;
+	bbox_height = image->height;
+	cairo_matrix_transform_distance (&inverse,
+					 &bbox_width, &bbox_height);
+
+	/* In PostScript, (as far as I can tell), all patterns are
+	 * repeating. So we support cairo's EXTEND_NONE semantics by
+	 * setting the repeat step size to the larger of the image size
+	 * and the extents of the destination surface. That way we
+	 * guarantee the pattern will not repeat.
+	 */
+	switch (pattern->base.extend) {
+	case CAIRO_EXTEND_NONE:
+	    xstep = MAX (image->width, surface->width);
+	    ystep = MAX (image->height, surface->height);
+	    break;
+	case CAIRO_EXTEND_REPEAT:
+	    xstep = image->width;
+	    ystep = image->height;
+	    break;
+	/* All the rest should have been analyzed away, so these cases
+	 * should be unreachable. */
+	case CAIRO_EXTEND_REFLECT:
+	case CAIRO_EXTEND_PAD:
+	default:
+	    ASSERT_NOT_REACHED;
+	    xstep = 0;
+	    ystep = 0;
+	}
+
 	_cairo_surface_release_source_image (pattern->surface, image,
 					     image_extra);
     }
     _cairo_output_stream_printf (surface->stream,
-				 "%f %f translate\n",
-				 x, y);
-    _cairo_output_stream_printf (surface->stream,
 				 "<< /PatternType 1\n"
 				 "   /PaintType 1\n"
 				 "   /TilingType 1\n");
     _cairo_output_stream_printf (surface->stream,
 				 "   /BBox [0 0 %d %d]\n",
-				 extents.width, extents.height);
+				 (int) bbox_width, (int) bbox_height);
     _cairo_output_stream_printf (surface->stream,
 				 "   /XStep %d /YStep %d\n",
-				 extents.width, extents.height);
+				 xstep, ystep);
     _cairo_output_stream_printf (surface->stream,
 				 "   /PaintProc { MyPattern } bind\n"
-				 ">> matrix makepattern setpattern\n");
+				 ">>\n");
+    _cairo_output_stream_printf (surface->stream,
+				 "[ 1 0 0 1 %f %f ]\n",
+				 inverse.x0, inverse.y0);
     _cairo_output_stream_printf (surface->stream,
-				 "-%f -%f translate\n",
-				 x, y);
+				 "makepattern setpattern\n");
 }
 
 static void
@@ -1733,8 +1762,7 @@ emit_radial_pattern (cairo_ps_surface_t 
 }
 
 static void
-emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern,
-	      double x, double y)
+emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern)
 {
     /* FIXME: We should keep track of what pattern is currently set in
      * the postscript file and only emit code if we're setting a
@@ -1746,7 +1774,7 @@ emit_pattern (cairo_ps_surface_t *surfac
 	break;
 
     case CAIRO_PATTERN_TYPE_SURFACE:
-	emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, x, y);
+	emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
 	break;
 
     case CAIRO_PATTERN_TYPE_LINEAR:
@@ -1841,7 +1869,7 @@ _cairo_ps_surface_paint (void			*abstrac
 {
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_output_stream_t *stream = surface->stream;
-    cairo_rectangle_int16_t extents;
+    cairo_rectangle_int16_t extents, pattern_extents;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return _analyze_operation (surface, op, source);
@@ -1859,9 +1887,11 @@ _cairo_ps_surface_paint (void			*abstrac
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_paint\n");
 
-    _cairo_pattern_get_extents (source, &extents);
+    _cairo_surface_get_extents (&surface->base, &extents);
+    _cairo_pattern_get_extents (source, &pattern_extents);
+    _cairo_rectangle_intersect (&extents, &pattern_extents);
 
-    emit_pattern (surface, source, extents.x, extents.y);
+    emit_pattern (surface, source);
 
     _cairo_output_stream_printf (stream, "%d %d M\n",
 				 extents.x, extents.y);
@@ -2000,7 +2030,7 @@ _cairo_ps_surface_stroke (void			*abstra
 	}
     }
 
-    emit_pattern (surface, source, 0, 0);
+    emit_pattern (surface, source);
 
     _cairo_output_stream_printf (stream,
 				 "gsave\n");
@@ -2067,7 +2097,7 @@ _cairo_ps_surface_fill (void		*abstract_
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_fill\n");
 
-    emit_pattern (surface, source, 0, 0);
+    emit_pattern (surface, source);
 
     /* We're filling not stroking, so we pass CAIRO_LINE_CAP_ROUND. */
     status = _cairo_ps_surface_emit_path (surface, stream, path,
@@ -2114,7 +2144,7 @@ _cairo_ps_surface_show_glyphs (void		   
 				 "%% _cairo_ps_surface_show_glyphs\n");
 
     if (num_glyphs)
-	emit_pattern (surface, source, 0, 0);
+	emit_pattern (surface, source);
 
     for (i = 0; i < num_glyphs; i++) {
 	status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
diff-tree 76f816c765a19a4fcda0500b5495bb969d014958 (from 06d3786b2c76e05939bff1065a57db3059ccbc95)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 25 10:44:53 2006 -0700

    test/paint-repeat: Use offset larger than source surface for better stress testing

diff --git a/test/paint-repeat.c b/test/paint-repeat.c
index 2879dcf..892cbf8 100644
--- a/test/paint-repeat.c
+++ b/test/paint-repeat.c
@@ -49,7 +49,9 @@ draw (cairo_t *cr, int width, int height
     surface = cairo_image_surface_create_for_data ((unsigned char *) data,
 						   CAIRO_FORMAT_RGB24, 4, 4, 16);
 
-    cairo_set_source_surface (cr, surface, 2, 2);
+    /* We use a non-zero offset larger than the source surface size to
+     * stress cairo out a bit more. */
+    cairo_set_source_surface (cr, surface, 10, 10);
     cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
     cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
     cairo_paint (cr);
diff-tree 06d3786b2c76e05939bff1065a57db3059ccbc95 (from 7421e8af0ca3b5c80dd3c7b145c639196f6036a5)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 25 10:43:19 2006 -0700

    Add new paint-repeat test
    
    I added this test originally to make it easier to debug
    some recent bugs, (the test suite did have some repeating
    in the checkered backgrounds, but with an offset of 0,
    and then also in trap clip with an offset larger than the
    surface itself). This test exercises repeating more directly.
    
    It also triggers a bug in the PostScript backend that I've
    not yet investigated. So the test does fail currently.

diff --git a/test/.gitignore b/test/.gitignore
index f6a293e..62c04a0 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -77,6 +77,7 @@ nil-surface
 operator-clear
 operator-source
 paint
+paint-repeat
 paint-source-alpha
 paint-with-alpha
 path-data
diff --git a/test/Makefile.am b/test/Makefile.am
index 846b606..69b70f4 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -57,6 +57,7 @@ nil-surface			\
 operator-clear			\
 operator-source			\
 paint				\
+paint-repeat			\
 paint-source-alpha		\
 paint-with-alpha		\
 pattern-get-type		\
@@ -273,6 +274,7 @@ operator-clear-rgb24-ref.png				\
 operator-source-ref.png					\
 operator-source-rgb24-ref.png				\
 paint-ref.png						\
+paint-repeat-ref.png					\
 paint-source-alpha-ref.png				\
 paint-source-alpha-pdf-argb32-ref.png			\
 paint-source-alpha-svg-ref.png				\
diff --git a/test/paint-repeat-ref.png b/test/paint-repeat-ref.png
new file mode 100644
index 0000000..2cc48f3
Binary files /dev/null and b/test/paint-repeat-ref.png differ
diff --git a/test/paint-repeat.c b/test/paint-repeat.c
new file mode 100644
index 0000000..2879dcf
--- /dev/null
+++ b/test/paint-repeat.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth at cworth.org>
+ */
+
+#include "cairo-test.h"
+
+static cairo_test_draw_function_t draw;
+
+cairo_test_t test = {
+    "paint-repeat",
+    "Test calls to cairo_paint with a repeating source surface pattern",
+    8, 8,
+    draw
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    cairo_surface_t *surface;
+    static uint32_t data[16] = {
+	0xffffffff, 0xffffffff,		0xffff0000, 0xffff0000,
+	0xffffffff, 0xffffffff,		0xffff0000, 0xffff0000,
+
+	0xff00ff00, 0xff00ff00,		0xff0000ff, 0xff0000ff,
+	0xff00ff00, 0xff00ff00,		0xff0000ff, 0xff0000ff
+    };
+
+    surface = cairo_image_surface_create_for_data ((unsigned char *) data,
+						   CAIRO_FORMAT_RGB24, 4, 4, 16);
+
+    cairo_set_source_surface (cr, surface, 2, 2);
+    cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
+    cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
+    cairo_paint (cr);
+
+    cairo_surface_destroy (surface);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+    return cairo_test (&test);
+}


More information about the cairo-commit mailing list