[PATCH 4/5] pattern: factor out gradient rescaling code

Thomas Jaeger ThJaeger at gmail.com
Sat Feb 28 16:13:26 PST 2009


This code will be needed for both the client-side fallback and if
gradients are drawn using Render, so factor it out.
---
 src/cairo-pattern.c |   88 ++++++++++++++++++++++++++++----------------------
 src/cairoint.h      |    6 +++
 2 files changed, 55 insertions(+), 39 deletions(-)

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 499a25d..0ce57ac 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1241,6 +1241,54 @@ _cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern,
     *is_horizontal = factors[2] == factors[0];
 }
 
+/*
+ * 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...
+ */
+void
+_cairo_pattern_scale_linear (const cairo_linear_pattern_t *linear,
+			     cairo_matrix_t               *matrix,
+			     pixman_point_fixed_t         *p1,
+			     pixman_point_fixed_t         *p2)
+{
+    cairo_fixed_t xdim, ydim;
+
+    xdim = linear->p2.x - linear->p1.x;
+    ydim = linear->p2.y - linear->p1.y;
+
+#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);
+
+	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);
+    }
+}
+
 static cairo_int_status_t
 _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pattern,
 					     cairo_surface_t	        *dst,
@@ -1285,46 +1333,8 @@ _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pat
     {
 	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);
-
-	    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);
-	}
+	_cairo_pattern_scale_linear(linear, &matrix, &p1, &p2);
 
 	pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
 							    pixman_stops,
diff --git a/src/cairoint.h b/src/cairoint.h
index 29b8ea6..0c94aa7 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2458,6 +2458,12 @@ _cairo_pattern_init_linear (cairo_linear_pattern_t *pattern,
 			    double x0, double y0, double x1, double y1);
 
 cairo_private void
+_cairo_pattern_scale_linear (const cairo_linear_pattern_t *linear,
+			     cairo_matrix_t               *matrix,
+			     pixman_point_fixed_t         *p1,
+			     pixman_point_fixed_t         *p2);
+
+cairo_private void
 _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
 			    double cx0, double cy0, double radius0,
 			    double cx1, double cy1, double radius1);
-- 
1.6.3


--------------000209070203020007040404
Content-Type: text/x-patch;
 name="0005-xlib-fix-server-gradients.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="0005-xlib-fix-server-gradients.patch"



More information about the cairo mailing list