[cairo-commit] src/cairo-pdf-surface.c

Carl Worth cworth at kemper.freedesktop.org
Fri Jan 19 23:11:24 PST 2007


 src/cairo-pdf-surface.c |   41 +++++++++++++++++++++++++++++++++--------
 1 files changed, 33 insertions(+), 8 deletions(-)

New commits:
diff-tree 5f9d70a56158e468683dba953d6eaceea4dfd644 (from 2f6d184e6659e91909ed933d36bef441f1b5df4d)
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Jan 19 23:11:09 2007 -0800

    PDF: Fix CAIRO_EXTEND_NONE for source surface patterns
    
    The former workaround for the lack of non-repeating patterns in PDF
    (as far as we can tell) was broken for a source pattern matrix that
    resulted in scaling the source surface pattern down. This was
    demonstrated by the failure of the scale-down-source-surface-paint
    test which now passes.
    
    The old code would have also allowed for bogus repeated pattern
    instances to appear if the source surface pattern was translated
    sufficiently far off the destination surface in just the right
    direction. This bug is also fixed.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index ec98345..9debdb6 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -890,16 +890,41 @@ emit_surface_pattern (cairo_pdf_surface_
 
     _cairo_surface_get_extents (&surface->base, &surface_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, surface_extents.width);
-	ystep = MAX(image->height, surface_extents.height);
+        {
+	    /* 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 a size large enough
+	     * to guarantee that no more than a single occurence 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.
+	     */
+	    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,
+						  &x1, &y1, &x2, &y2,
+						  NULL);
+	    /* Rather than computing precise bounds of the union, just
+	     * add the surface extents unconditonally. 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 = _cairo_lround (ceil (x1 * y1));
+	    ystep = _cairo_lround (ceil (x1 * y1));
+	}
 	break;
     case CAIRO_EXTEND_REPEAT:
 	xstep = image->width;


More information about the cairo-commit mailing list