[PATCH 4/5] pattern: factor out gradient rescaling code
Thomas Jaeger
ThJaeger at gmail.com
Sat Feb 28 16:13:26 PST 2009
---
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
--------------010101010805020406070805
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