[cairo-commit] 4 commits - src/cairo-pdf-surface.c test/filter-nearest-offset.c test/mask-ctm.c test/move-to-show-surface.c test/paint-with-alpha.c test/scale-source-surface-paint.c test/scale-source-surface-paint-pdf-argb32-ref.png test/source-surface-scale-paint.c test/translate-show-surface.c

Carl Worth cworth at kemper.freedesktop.org
Mon Apr 24 16:19:28 PDT 2006


 src/cairo-pdf-surface.c                            |   85 +++++++++++++++++----
 test/filter-nearest-offset.c                       |    2 
 test/mask-ctm.c                                    |    2 
 test/move-to-show-surface.c                        |    2 
 test/paint-with-alpha.c                            |    2 
 test/scale-source-surface-paint-pdf-argb32-ref.png |binary
 test/scale-source-surface-paint.c                  |    2 
 test/source-surface-scale-paint.c                  |    2 
 test/translate-show-surface.c                      |    2 
 9 files changed, 79 insertions(+), 20 deletions(-)

New commits:
diff-tree a5afc59d0ad90125c0593ab60c8e1e01f51bdc3c (from 32a7edc42dae507678e4eed98fcb41802b8ee69c)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Apr 24 16:16:19 2006 -0700

    Add PDF-specific reference image for scale-source-surface-paint
    
    It only fails because the PDF ouput doesn't preserve the NEAREST filter attribute.
    There might be a way to get something like this in the PDF, but it's not the point
    of the test.

diff --git a/test/scale-source-surface-paint-pdf-argb32-ref.png b/test/scale-source-surface-paint-pdf-argb32-ref.png
new file mode 100644
index 0000000..bb940f8
Binary files /dev/null and b/test/scale-source-surface-paint-pdf-argb32-ref.png differ
diff-tree 32a7edc42dae507678e4eed98fcb41802b8ee69c (from a1bba71eb9442a1c3a5f9fb227353971d58cecba)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Apr 24 16:11:21 2006 -0700

    PDF: Fix surface pattern transformation and support for EXTEND_NONE.
    
    There's a bunch of careful matrix transformation here needed to
    resolve the differences between cairo and PDF pattern matrices,
    (primarily due to the different location for the origin).
    
    This fixes the several PDF test suite failures that recently appeared
    when we switched from ARGB32 to RGB24 source surface patterns.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 046a4d1..a2e7c95 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -931,7 +931,10 @@ emit_surface_pattern (cairo_pdf_surface_
     void *image_extra;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     unsigned int id, alpha;
-    cairo_matrix_t i2u;
+    cairo_matrix_t cairo_p2d, pdf_p2d;
+    cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
+    int xstep, ystep;
+    cairo_rectangle_t dst_extents;
 
     /* XXX: This is broken. We need new code here to actually emit the
      * PDF surface. */
@@ -948,29 +951,85 @@ emit_surface_pattern (cairo_pdf_surface_
     if (status)
 	goto BAIL;
 
-    /* BBox must be smaller than XStep by YStep or acroread wont
-     * display the pattern. */
+    _cairo_surface_get_extents (&dst->base, &dst_extents);
+
+    /* In 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 the larger of the image size and the extents of
+     * the destination surface. That way we guarantee the pattern will
+     * not repeat.
+     */
+    switch (extend) {
+    case CAIRO_EXTEND_NONE:
+	xstep = MAX(image->width, dst_extents.width);
+	ystep = MAX(image->height, dst_extents.height);
+	break;
+    case CAIRO_EXTEND_REPEAT:
+	xstep = image->width;
+	ystep = image->height;
+	break;
+    default:
+	ASSERT_NOT_REACHED; /* all others should be analyzed away */
+	xstep = 0;
+	ystep = 0;
+    }
+
+    /* At this point, (that is, within the surface backend interface),
+     * the pattern's matrix maps from cairo's device space to cairo's
+     * pattern space, (both with their origin at the upper-left, and
+     * cairo's pattern space of size width,height).
+     *
+     * Then, we must emit a PDF pattern object that maps from its own
+     * pattern space, (which has a size that we establish in the BBox
+     * dictionary entry), to the PDF page's *initial* space, (which
+     * does not benefit from the Y-axis flipping matrix that we emit
+     * on each page). So the PDF patterns patrix maps from a
+     * (width,height) pattern space to a device space with the origin
+     * in the lower-left corner.
+     *
+     * So to handle all of that, we start with an identity matrix for
+     * the PDF pattern to device matrix. We translate it up by the
+     * image height then flip it in the Y direction, (moving us from
+     * the PDF origin to cairo's origin). We then multiply in the
+     * inverse of the cairo pattern matrix, (since it maps from device
+     * to pattern, while we're setting up pattern to device). Finally,
+     * we translate back down by the image height and flip again to
+     * end up at the lower-left origin that PDF expects.
+     *
+     * Additionally, within the stream that paints the pattern itself,
+     * we are using a PDF image object that has a size of (1,1) so we
+     * have to scale it up by the image width and height to fill our
+     * pattern cell.
+     */
+    cairo_p2d = pattern->base.matrix;
+    cairo_matrix_invert (&cairo_p2d);
+
+    cairo_matrix_init_identity (&pdf_p2d);
+    cairo_matrix_translate (&pdf_p2d, 0.0, dst_extents.height);
+    cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
+    cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
+    cairo_matrix_translate (&pdf_p2d, 0.0, image->height);
+    cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
+
     stream = _cairo_pdf_document_open_stream (document,
-					      "   /BBox [ 0 0 %d %d ]\r\n"
+					      "   /BBox [0 0 %d %d]\r\n"
 					      "   /XStep %d\r\n"
 					      "   /YStep %d\r\n"
 					      "   /PatternType 1\r\n"
 					      "   /TilingType 1\r\n"
 					      "   /PaintType 1\r\n"
+					      "   /Matrix [ %f %f %f %f %f %f ]\r\n"
 					      "   /Resources << /XObject << /res%d %d 0 R >> >>\r\n",
 					      image->width, image->height,
-					      image->width, image->height,
+					      xstep, ystep,
+					      pdf_p2d.xx, pdf_p2d.yx,
+					      pdf_p2d.xy, pdf_p2d.yy,
+					      pdf_p2d.x0, pdf_p2d.y0,
 					      id, id);
 
-    i2u = pattern->base.matrix;
-    cairo_matrix_invert (&i2u);
-    cairo_matrix_scale (&i2u, image->width, image->height);
-
     _cairo_output_stream_printf (output,
-				 "q %f %f %f %f %f %f cm /res%d Do Q\r\n",
-				 i2u.xx, i2u.yx,
-				 i2u.xy, i2u.yy,
-				 i2u.x0, i2u.y0,
+				 "q %d 0 0 %d 0 0 cm /res%d Do Q\r\n",
+				 image->width, image->height,
 				 id);
 
     _cairo_pdf_surface_add_pattern (dst, stream->id);
diff-tree a1bba71eb9442a1c3a5f9fb227353971d58cecba (from 893239248a9a6ef1a7b9f770aec334f20c5c0861)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Apr 24 14:51:31 2006 -0700

    Trivial indentation fix

diff --git a/test/mask-ctm.c b/test/mask-ctm.c
index 99c67ed..1196e4d 100644
--- a/test/mask-ctm.c
+++ b/test/mask-ctm.c
@@ -43,7 +43,7 @@ draw (cairo_t *cr, int width, int height
     cairo_matrix_t matrix;
 
     mask_surface = cairo_image_surface_create_for_data ((unsigned char *) data,
-						CAIRO_FORMAT_ARGB32, 2, 2, 8);
+							CAIRO_FORMAT_ARGB32, 2, 2, 8);
     mask = cairo_pattern_create_for_surface (mask_surface);
     cairo_surface_destroy (mask_surface);
 
diff-tree 893239248a9a6ef1a7b9f770aec334f20c5c0861 (from 28e25e1cce0a4e4c612743effb8927c5cb6b3c5b)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Apr 24 14:50:52 2006 -0700

    Prefer RGB24 over ARGB32 for source surfaces in tests.
    
    Some tests were using source surfaces created as ARGB32 even though all
    alpha values are entirely opaque. This meant these tests were triggering
    more fallbacks than strictly necessary for what the tests are ttrying to
    do.

diff --git a/test/filter-nearest-offset.c b/test/filter-nearest-offset.c
index d7373c7..f664fbf 100644
--- a/test/filter-nearest-offset.c
+++ b/test/filter-nearest-offset.c
@@ -62,7 +62,7 @@ draw (cairo_t *cr, int width, int height
     cairo_stroke (cr);
 
     surface = cairo_image_surface_create_for_data ((unsigned char *) data,
-						   CAIRO_FORMAT_ARGB32,
+						   CAIRO_FORMAT_RGB24,
 						   STAMP_WIDTH,
 						   STAMP_HEIGHT,
 						   STAMP_WIDTH * 4);
diff --git a/test/move-to-show-surface.c b/test/move-to-show-surface.c
index 74bf51b..74cf3a0 100644
--- a/test/move-to-show-surface.c
+++ b/test/move-to-show-surface.c
@@ -63,7 +63,7 @@ draw (cairo_t *cr, int width, int height
 
     for (i=0; i < 4; i++) {
 	surface = cairo_image_surface_create_for_data ((unsigned char *) &colors[i],
-						       CAIRO_FORMAT_ARGB32,
+						       CAIRO_FORMAT_RGB24,
 						       1, 1, 4);
 	cairo_set_source_surface (cr, surface,
 				  i % 2, i / 2);
diff --git a/test/paint-with-alpha.c b/test/paint-with-alpha.c
index c35f679..3292d5f 100644
--- a/test/paint-with-alpha.c
+++ b/test/paint-with-alpha.c
@@ -44,7 +44,7 @@ draw (cairo_t *cr, int width, int height
     };
 
     surface = cairo_image_surface_create_for_data ((unsigned char *) data,
-					      CAIRO_FORMAT_ARGB32, 4, 4, 16);
+						   CAIRO_FORMAT_RGB24, 4, 4, 16);
 
     cairo_scale (cr, 2, 2);
 
diff --git a/test/scale-source-surface-paint.c b/test/scale-source-surface-paint.c
index 9553b9f..c2b76d3 100644
--- a/test/scale-source-surface-paint.c
+++ b/test/scale-source-surface-paint.c
@@ -44,7 +44,7 @@ draw (cairo_t *cr, int width, int height
     };
 
     surface = cairo_image_surface_create_for_data ((unsigned char *) data,
-					      CAIRO_FORMAT_ARGB32, 4, 4, 16);
+						   CAIRO_FORMAT_RGB24, 4, 4, 16);
 
     cairo_scale (cr, 2, 2);
 
diff --git a/test/source-surface-scale-paint.c b/test/source-surface-scale-paint.c
index e5676c9..472630c 100644
--- a/test/source-surface-scale-paint.c
+++ b/test/source-surface-scale-paint.c
@@ -44,7 +44,7 @@ draw (cairo_t *cr, int width, int height
     };
 
     surface = cairo_image_surface_create_for_data ((unsigned char *) data,
-					      CAIRO_FORMAT_ARGB32, 4, 4, 16);
+						   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);
diff --git a/test/translate-show-surface.c b/test/translate-show-surface.c
index d81ed1a..cc0cb07 100644
--- a/test/translate-show-surface.c
+++ b/test/translate-show-surface.c
@@ -61,7 +61,7 @@ draw (cairo_t *cr, int width, int height
 
     for (i=0; i < 4; i++) {
 	surface = cairo_image_surface_create_for_data ((unsigned char *) &colors[i],
-						       CAIRO_FORMAT_ARGB32,
+						       CAIRO_FORMAT_RGB24,
 						       1, 1, 4);
 	cairo_save (cr);
 	{


More information about the cairo-commit mailing list