[cairo-commit] 2 commits - src/cairoint.h src/cairo-pattern.c test/huge-pattern-pdf-ref.png test/huge-pattern-pdf-rgb24-ref.png test/huge-pattern-ps3-ref.png test/Makefile.am

Chris Wilson ickle at kemper.freedesktop.org
Sun Oct 12 04:26:25 PDT 2008


 src/cairo-pattern.c                 |   48 +++++++++++++++++++++++++++++++-----
 src/cairoint.h                      |    5 +++
 test/Makefile.am                    |    5 ++-
 test/huge-pattern-pdf-ref.png       |binary
 test/huge-pattern-pdf-rgb24-ref.png |binary
 test/huge-pattern-ps3-ref.png       |binary
 6 files changed, 49 insertions(+), 9 deletions(-)

New commits:
commit ceab32e2c3d51c0dd29b105a5a390cdd8aa58f8f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Oct 12 12:11:12 2008 +0100

    [win32] win32 also uses font subsets.
    
    Include win32 in the list of font subset users, fixes build when
    cross-compiling.

diff --git a/src/cairoint.h b/src/cairoint.h
index 8b2bd49..afdcd4d 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -72,7 +72,10 @@
 
 #include "cairo-compiler-private.h"
 
-#if CAIRO_HAS_PS_SURFACE || CAIRO_HAS_PDF_SURFACE || CAIRO_HAS_SVG_SURFACE
+#if CAIRO_HAS_PS_SURFACE  || \
+    CAIRO_HAS_PDF_SURFACE || \
+    CAIRO_HAS_SVG_SURFACE || \
+    CAIRO_HAS_WIN32_SURFACE
 #define CAIRO_HAS_FONT_SUBSET 1
 #endif
 
commit 1d3453eee50e4343995c5d3f225d18289fbcebec
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Oct 12 11:21:14 2008 +0100

    [pattern] Rescale the linear pattern matrix to avoid overflow.
    
    As proof-of-principle, compute a scale factor to avoid overflow when
    converting a linear pattern to pixman_fixed_t. Fixes test/huge-pattern,
    but the principle should be extended to handle more cases of overflow.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index b2b1c60..c60b1f6 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1248,6 +1248,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
     pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
     unsigned int i;
     int clone_offset_x, clone_offset_y;
+    cairo_matrix_t matrix = pattern->base.matrix;
 
     if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
 	pixman_stops = _cairo_malloc_ab (pattern->n_stops, sizeof(pixman_gradient_stop_t));
@@ -1267,11 +1268,46 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
     {
 	cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;
 	pixman_point_fixed_t p1, p2;
+	cairo_fixed_t xdim, ydim;
+
+	xdim = linear->p2.x - linear->p1.x;
+	ydim = linear->p2.y - linear->p1.y;
+
+	/*
+	 * Transform the matrix to avoid overflow when converting between
+	 * cairo_fixed_t and pixman_fixed_t (without incurring performance
+	 * loss when the transformation is unnecessary).
+	 *
+	 * XXX: Consider converting out-of-range co-ordinates and transforms.
+	 * Having a function to compute the required transformation to
+	 * "normalize" a given bounding box would be generally useful -
+	 * cf linear patterns, gradient patterns, surface patterns...
+	 */
+#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
+	if (_cairo_fixed_integer_ceil (xdim) > PIXMAN_MAX_INT ||
+	    _cairo_fixed_integer_ceil (ydim) > PIXMAN_MAX_INT)
+	{
+	    double sf;
+
+	    if (xdim > ydim)
+		sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (xdim);
+	    else
+		sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (ydim);
+
+	    p1.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.x) * sf);
+	    p1.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.y) * sf);
+	    p2.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.x) * sf);
+	    p2.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.y) * sf);
 
-	p1.x = _cairo_fixed_to_16_16 (linear->p1.x);
-	p1.y = _cairo_fixed_to_16_16 (linear->p1.y);
-	p2.x = _cairo_fixed_to_16_16 (linear->p2.x);
-	p2.y = _cairo_fixed_to_16_16 (linear->p2.y);
+	    cairo_matrix_scale (&matrix, sf, sf);
+	}
+	else
+	{
+	    p1.x = _cairo_fixed_to_16_16 (linear->p1.x);
+	    p1.y = _cairo_fixed_to_16_16 (linear->p1.y);
+	    p2.x = _cairo_fixed_to_16_16 (linear->p2.x);
+	    p2.y = _cairo_fixed_to_16_16 (linear->p2.y);
+	}
 
 	pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
 							    pixman_stops,
@@ -1315,7 +1351,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
 	}
 
 	attr->x_offset = attr->y_offset = 0;
-	attr->matrix = pattern->base.matrix;
+	attr->matrix = matrix;
 	attr->extend = pattern->base.extend;
 	attr->filter = CAIRO_FILTER_NEAREST;
 	attr->acquired = FALSE;
@@ -1363,7 +1399,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
 	return image->base.status;
     }
 
-    _cairo_matrix_to_pixman_matrix (&pattern->base.matrix, &pixman_transform);
+    _cairo_matrix_to_pixman_matrix (&matrix, &pixman_transform);
     if (!pixman_image_set_transform (pixman_image, &pixman_transform)) {
 	cairo_surface_destroy (&image->base);
 	pixman_image_unref (pixman_image);
diff --git a/test/Makefile.am b/test/Makefile.am
index 6a98cf6..bd7272e 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -541,6 +541,9 @@ REFERENCE_IMAGES = \
 	gradient-zero-stops-rgb24-ref.png	\
 	group-paint-ref.png	\
 	huge-pattern-ref.png	\
+	huge-pattern-ps3-ref.png	\
+	huge-pattern-pdf-ref.png	\
+	huge-pattern-pdf-rgb24-ref.png	\
 	image-surface-source-ref.png \
 	infinite-join-ref.png	\
 	infinite-join-ps2-ref.png	\
@@ -947,7 +950,6 @@ $(REFERENCE_IMAGES)
 #                         room, with Carl as a moderator and not let them out
 #                         until they have come up with an interface and
 #                         semantics that actually work. :-)
-# huge-pattern          - range overflow of fixed-point
 # 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
@@ -971,7 +973,6 @@ degenerate-path$(EXEEXT)			\
 device-offset-scale$(EXEEXT)			\
 extend-pad$(EXEEXT)				\
 fallback-resolution$(EXEEXT)			\
-huge-pattern$(EXEEXT)				\
 long-lines$(EXEEXT)				\
 self-copy-overlap$(EXEEXT)			\
 self-intersecting$(EXEEXT)			\
diff --git a/test/huge-pattern-pdf-ref.png b/test/huge-pattern-pdf-ref.png
new file mode 100644
index 0000000..dfa8c5b
Binary files /dev/null and b/test/huge-pattern-pdf-ref.png differ
diff --git a/test/huge-pattern-pdf-rgb24-ref.png b/test/huge-pattern-pdf-rgb24-ref.png
new file mode 100644
index 0000000..a950f8b
Binary files /dev/null and b/test/huge-pattern-pdf-rgb24-ref.png differ
diff --git a/test/huge-pattern-ps3-ref.png b/test/huge-pattern-ps3-ref.png
new file mode 100644
index 0000000..d55239b
Binary files /dev/null and b/test/huge-pattern-ps3-ref.png differ


More information about the cairo-commit mailing list