[cairo-commit] 3 commits - src/cairo-pdf-surface.c src/cairo-ps-surface.c test/.gitignore test/Makefile.am test/surface-pattern.c test/surface-pattern-scale-down.c test/surface-pattern-scale-down-pdf-argb32-ref.png test/surface-pattern-scale-down-ps-argb32-ref.png test/surface-pattern-scale-down-ref.png test/surface-pattern-scale-up.c test/surface-pattern-scale-up-pdf-argb32-ref.png test/surface-pattern-scale-up-ps-argb32-ref.png test/surface-pattern-scale-up-ref.png

Behdad Esfahbod behdad at kemper.freedesktop.org
Tue Feb 27 16:31:44 PST 2007


 src/cairo-pdf-surface.c                            |   36 ++++-------
 src/cairo-ps-surface.c                             |   43 ++++++++-----
 test/.gitignore                                    |    2 
 test/Makefile.am                                   |    2 
 test/surface-pattern-scale-down-pdf-argb32-ref.png |binary
 test/surface-pattern-scale-down-ps-argb32-ref.png  |binary
 test/surface-pattern-scale-down-ref.png            |binary
 test/surface-pattern-scale-down.c                  |   68 +++++++++++++++++++++
 test/surface-pattern-scale-up-pdf-argb32-ref.png   |binary
 test/surface-pattern-scale-up-ps-argb32-ref.png    |binary
 test/surface-pattern-scale-up-ref.png              |binary
 test/surface-pattern-scale-up.c                    |   68 +++++++++++++++++++++
 test/surface-pattern.c                             |    3 
 13 files changed, 184 insertions(+), 38 deletions(-)

New commits:
diff-tree 153465bfe5346b9e1ebdbd4f794bd11868ee7458 (from e2ce27db302a185e6e80ead699c01e43921939ca)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Feb 27 19:28:37 2007 -0500

    [test] Add ref images for new tests

diff --git a/test/surface-pattern-scale-down-pdf-argb32-ref.png b/test/surface-pattern-scale-down-pdf-argb32-ref.png
new file mode 100644
index 0000000..9f27687
Binary files /dev/null and b/test/surface-pattern-scale-down-pdf-argb32-ref.png differ
diff --git a/test/surface-pattern-scale-down-ps-argb32-ref.png b/test/surface-pattern-scale-down-ps-argb32-ref.png
new file mode 100644
index 0000000..1f0b3e0
Binary files /dev/null and b/test/surface-pattern-scale-down-ps-argb32-ref.png differ
diff --git a/test/surface-pattern-scale-down-ref.png b/test/surface-pattern-scale-down-ref.png
new file mode 100644
index 0000000..b7255ef
Binary files /dev/null and b/test/surface-pattern-scale-down-ref.png differ
diff --git a/test/surface-pattern-scale-down.c b/test/surface-pattern-scale-down.c
index db5b861..314f852 100644
--- a/test/surface-pattern-scale-down.c
+++ b/test/surface-pattern-scale-down.c
@@ -21,8 +21,7 @@ draw (cairo_t *cr, int width, int height
     int surface_size = 300;
 
     cairo_set_source_rgb (cr, 0, 0, 0);
-    cairo_rectangle (cr, 0, 0, SIZE, SIZE);
-    cairo_fill (cr);
+    cairo_paint (cr);
 
     /* Create an image surface with my favorite four colors in each
      * quadrant. */
diff --git a/test/surface-pattern-scale-up-pdf-argb32-ref.png b/test/surface-pattern-scale-up-pdf-argb32-ref.png
new file mode 100644
index 0000000..c277a0f
Binary files /dev/null and b/test/surface-pattern-scale-up-pdf-argb32-ref.png differ
diff --git a/test/surface-pattern-scale-up-ps-argb32-ref.png b/test/surface-pattern-scale-up-ps-argb32-ref.png
new file mode 100644
index 0000000..dc9f8d2
Binary files /dev/null and b/test/surface-pattern-scale-up-ps-argb32-ref.png differ
diff --git a/test/surface-pattern-scale-up-ref.png b/test/surface-pattern-scale-up-ref.png
new file mode 100644
index 0000000..32d7bdf
Binary files /dev/null and b/test/surface-pattern-scale-up-ref.png differ
diff --git a/test/surface-pattern-scale-up.c b/test/surface-pattern-scale-up.c
index 921e1a3..d1f0e41 100644
--- a/test/surface-pattern-scale-up.c
+++ b/test/surface-pattern-scale-up.c
@@ -21,8 +21,7 @@ draw (cairo_t *cr, int width, int height
     int surface_size = 6;
 
     cairo_set_source_rgb (cr, 0, 0, 0);
-    cairo_rectangle (cr, 0, 0, SIZE, SIZE);
-    cairo_fill (cr);
+    cairo_paint (cr);
 
     /* Create an image surface with my favorite four colors in each
      * quadrant. */
diff --git a/test/surface-pattern.c b/test/surface-pattern.c
index 42aca27..51b638d 100644
--- a/test/surface-pattern.c
+++ b/test/surface-pattern.c
@@ -21,8 +21,7 @@ draw (cairo_t *cr, int width, int height
     int surface_size = 6;
 
     cairo_set_source_rgb (cr, 0, 0, 0);
-    cairo_rectangle (cr, 0, 0, SIZE, SIZE);
-    cairo_fill (cr);
+    cairo_paint (cr);
 
     /* Create an image surface with my favorite four colors in each
      * quadrant. */
diff-tree e2ce27db302a185e6e80ead699c01e43921939ca (from de0a6522b00822305fa5a0e32c4821628425ebdc)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Feb 27 18:47:47 2007 -0500

    [PS/PDF] Fix xstep/ystep values for CAIRO_EXTEND_NONE
    
    This fixes the fallback-resolution test, as well as the two of
    surface-pattern-scale-up and surface-pattern-scale-down.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 3b8830d..938a4f0 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -878,7 +878,7 @@ emit_surface_pattern (cairo_pdf_surface_
     cairo_pdf_resource_t alpha, image_resource = {0}; /* squelch bogus compiler warning */
     cairo_matrix_t cairo_p2d, pdf_p2d;
     cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
-    int xstep, ystep;
+    double xstep, ystep;
     cairo_rectangle_int16_t surface_extents;
 
     /* XXX: Should do something clever here for PDF source surfaces ? */
@@ -905,36 +905,30 @@ emit_surface_pattern (cairo_pdf_surface_
     switch (extend) {
     case CAIRO_EXTEND_NONE:
         {
-	    /* In PDF, (as far as I can tell), all patterns are
+	    /* In PS/PDF, (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 a size large enough
 	     * to guarantee that no more than a single occurrence will
 	     * be visible.
 	     *
-	     * First, map the pattern's extents through the inverse
-	     * pattern matrix to compute the device-space bounds of
-	     * the desired single occurrence. Then consider the bounds
-	     * of (the union of this rectangle with the target surface
-	     * extents). If the repeat size is larger than the
-	     * diagonal of the bounds of the union, then it is
-	     * guaranteed to never repeat visibly.
+	     * First, map the surface extents into pattern space (since
+	     * xstep and ystep are in pattern space).  Then use an upper
+	     * bound on the length of the diagonal of the pattern image
+	     * and the surface as repeat size.  This guarantees to never
+	     * repeat visibly.
 	     */
 	    double x1 = 0.0, y1 = 0.0;
-	    double x2 = image->width, y2 = image->height;
-	    cairo_matrix_t surface_to_device = pattern->base.matrix;
-	    cairo_matrix_invert (&surface_to_device);
-	    _cairo_matrix_transform_bounding_box (&surface_to_device,
+	    double x2 = surface->width, y2 = surface->height;
+	    _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
 						  &x1, &y1, &x2, &y2,
 						  NULL);
+
 	    /* Rather than computing precise bounds of the union, just
 	     * add the surface extents unconditionally. We only
 	     * required an answer that's large enough, we don't really
-	     * care if it's not as tight as possible. */
-	    x1 = MAX (fabs(x1), fabs(x2)) + surface_extents.width;
-	    y1 = MAX (fabs(y1), fabs(y2)) + surface_extents.height;
-	    /* Similarly, don't bother computing the square root to
-	     * determine the length of the final diagonal. */
-	    xstep = ystep = _cairo_lround (ceil (x1 + y1));
+	     * care if it's not as tight as possible.*/
+	    xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
+				  image->width + image->height);
 	}
 	break;
     case CAIRO_EXTEND_REPEAT:
@@ -991,8 +985,8 @@ emit_surface_pattern (cairo_pdf_surface_
     stream = _cairo_pdf_surface_open_stream (surface,
                                              FALSE,
 					     "   /BBox [0 0 %d %d]\r\n"
-					     "   /XStep %d\r\n"
-					     "   /YStep %d\r\n"
+					     "   /XStep %f\r\n"
+					     "   /YStep %f\r\n"
 					     "   /PatternType 1\r\n"
 					     "   /TilingType 1\r\n"
 					     "   /PaintType 1\r\n"
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index b55900c..ac07395 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1704,7 +1704,7 @@ emit_surface_pattern (cairo_ps_surface_t
 		      cairo_surface_pattern_t *pattern)
 {
     double bbox_width, bbox_height;
-    int xstep, ystep;
+    double xstep, ystep;
     cairo_matrix_t inverse = pattern->base.matrix;
 
     cairo_matrix_invert (&inverse);
@@ -1732,22 +1732,35 @@ emit_surface_pattern (cairo_ps_surface_t
 	bbox_width = image->width;
 	bbox_height = image->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:
-	    /* XXX We may need to update this to something like the code
-	     * that is in PDF.  The point is, xstep/ystep are in pattern
-	     * space, not device space, so surface->width/height do not
-	     * make much sense.  But most of the time patterns scale up,
-	     * not down, so this is less of a problem. */
-	    xstep = MAX (image->width, surface->width);
-	    ystep = MAX (image->height, surface->height);
+	{
+	    /* In PS/PDF, (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 a size large enough
+	     * to guarantee that no more than a single occurrence will
+	     * be visible.
+	     *
+	     * First, map the surface extents into pattern space (since
+	     * xstep and ystep are in pattern space).  Then use an upper
+	     * bound on the length of the diagonal of the pattern image
+	     * and the surface as repeat size.  This guarantees to never
+	     * repeat visibly.
+	     */
+	    double x1 = 0.0, y1 = 0.0;
+	    double x2 = surface->width, y2 = surface->height;
+	    _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
+						  &x1, &y1, &x2, &y2,
+						  NULL);
+
+	    /* Rather than computing precise bounds of the union, just
+	     * add the surface extents unconditionally. We only
+	     * required an answer that's large enough, we don't really
+	     * care if it's not as tight as possible.*/
+	    xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
+				  image->width + image->height);
 	    break;
+	}
 	case CAIRO_EXTEND_REPEAT:
 	case CAIRO_EXTEND_REFLECT:
 	    xstep = image->width;
@@ -1773,7 +1786,7 @@ emit_surface_pattern (cairo_ps_surface_t
 				 "   /BBox [0 0 %f %f]\n",
 				 bbox_width, bbox_height);
     _cairo_output_stream_printf (surface->stream,
-				 "   /XStep %d /YStep %d\n",
+				 "   /XStep %f /YStep %f\n",
 				 xstep, ystep);
     _cairo_output_stream_printf (surface->stream,
 				 "   /PaintProc { MyPattern } bind\n"
diff-tree de0a6522b00822305fa5a0e32c4821628425ebdc (from 4c1d788219ae62bb9e8a7723d5a73d70eb42e69a)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Feb 27 17:33:17 2007 -0500

    [test] Add tests that show xstep/ystep failures in PS/PDF backends
    with surface patterns.  One test scaled the pattern up, another scales
    down.  We observe that both PS and PDF are broken when scaling down.
    This is the reason that PDF is failing in the fallback-resolution test
    too.

diff --git a/test/.gitignore b/test/.gitignore
index 6918015..7cbb8bc 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -123,6 +123,8 @@ source-clip-scale
 source-surface-scale-paint
 surface-finish-twice
 surface-pattern
+surface-pattern-scale-down
+surface-pattern-scale-up
 text-antialias-gray
 text-antialias-none
 text-antialias-subpixel
diff --git a/test/Makefile.am b/test/Makefile.am
index 162f607..1d1a796 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -89,6 +89,8 @@ source-clip-scale		\
 source-surface-scale-paint	\
 surface-finish-twice		\
 surface-pattern			\
+surface-pattern-scale-down	\
+surface-pattern-scale-up	\
 text-antialias-gray		\
 text-antialias-none		\
 text-antialias-subpixel		\
diff --git a/test/surface-pattern-scale-down.c b/test/surface-pattern-scale-down.c
new file mode 100644
index 0000000..db5b861
--- /dev/null
+++ b/test/surface-pattern-scale-down.c
@@ -0,0 +1,69 @@
+#include <math.h>
+#include "cairo-test.h"
+#include <stdio.h>
+
+#define SIZE 200
+
+static cairo_test_draw_function_t draw;
+
+cairo_test_t test = {
+    "surface-pattern-scale-down",
+    "Test scaled-down transformed not-repeated surface patterns",
+    SIZE, SIZE,
+    draw
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    cairo_surface_t *surface;
+    cairo_t * cr_surface;
+    int surface_size = 300;
+
+    cairo_set_source_rgb (cr, 0, 0, 0);
+    cairo_rectangle (cr, 0, 0, SIZE, SIZE);
+    cairo_fill (cr);
+
+    /* Create an image surface with my favorite four colors in each
+     * quadrant. */
+    surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+					  surface_size, surface_size);
+    cr_surface = cairo_create (surface);
+    cairo_set_source_rgb (cr_surface, 1, 1, 1);
+    cairo_rectangle (cr_surface,
+		     0, 0,
+		     surface_size / 2, surface_size / 2);
+    cairo_fill (cr_surface);
+    cairo_set_source_rgb (cr_surface, 1, 0, 0);
+    cairo_rectangle (cr_surface,
+		     surface_size / 2, 0,
+		     surface_size / 2, surface_size / 2);
+    cairo_fill (cr_surface);
+    cairo_set_source_rgb (cr_surface, 0, 1, 0);
+    cairo_rectangle (cr_surface,
+		     0, surface_size / 2,
+		     surface_size / 2, surface_size / 2);
+    cairo_fill (cr_surface);
+    cairo_set_source_rgb (cr_surface, 0, 0, 1);
+    cairo_rectangle (cr_surface,
+		     surface_size / 2, surface_size / 2,
+		     surface_size / 2, surface_size / 2);
+    cairo_fill (cr_surface);
+    cairo_destroy (cr_surface);
+
+    cairo_scale (cr, 0.2, 0.2);
+    cairo_rotate (cr, 1.);
+    cairo_set_source_surface (cr, surface, 225, -225);
+    cairo_surface_destroy (surface);
+
+    cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_NONE);
+    cairo_paint (cr);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+    return cairo_test (&test);
+}
diff --git a/test/surface-pattern-scale-up.c b/test/surface-pattern-scale-up.c
new file mode 100644
index 0000000..921e1a3
--- /dev/null
+++ b/test/surface-pattern-scale-up.c
@@ -0,0 +1,69 @@
+#include <math.h>
+#include "cairo-test.h"
+#include <stdio.h>
+
+#define SIZE 100
+
+static cairo_test_draw_function_t draw;
+
+cairo_test_t test = {
+    "surface-pattern-scale-up",
+    "Test scaled-up transformed not-repeated surface patterns",
+    SIZE, SIZE,
+    draw
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    cairo_surface_t *surface;
+    cairo_t * cr_surface;
+    int surface_size = 6;
+
+    cairo_set_source_rgb (cr, 0, 0, 0);
+    cairo_rectangle (cr, 0, 0, SIZE, SIZE);
+    cairo_fill (cr);
+
+    /* Create an image surface with my favorite four colors in each
+     * quadrant. */
+    surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+					  surface_size, surface_size);
+    cr_surface = cairo_create (surface);
+    cairo_set_source_rgb (cr_surface, 1, 1, 1);
+    cairo_rectangle (cr_surface,
+		     0, 0,
+		     surface_size / 2, surface_size / 2);
+    cairo_fill (cr_surface);
+    cairo_set_source_rgb (cr_surface, 1, 0, 0);
+    cairo_rectangle (cr_surface,
+		     surface_size / 2, 0,
+		     surface_size / 2, surface_size / 2);
+    cairo_fill (cr_surface);
+    cairo_set_source_rgb (cr_surface, 0, 1, 0);
+    cairo_rectangle (cr_surface,
+		     0, surface_size / 2,
+		     surface_size / 2, surface_size / 2);
+    cairo_fill (cr_surface);
+    cairo_set_source_rgb (cr_surface, 0, 0, 1);
+    cairo_rectangle (cr_surface,
+		     surface_size / 2, surface_size / 2,
+		     surface_size / 2, surface_size / 2);
+    cairo_fill (cr_surface);
+    cairo_destroy (cr_surface);
+
+    cairo_scale (cr, 10, 10);
+    cairo_rotate (cr, 1.);
+    cairo_set_source_surface (cr, surface, 4, -4.5);
+    cairo_surface_destroy (surface);
+
+    cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_NONE);
+    cairo_paint (cr);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+    return cairo_test (&test);
+}


More information about the cairo-commit mailing list