diff options
author | Andrea Canciani <ranma42@gmail.com> | 2010-11-23 19:31:40 +0100 |
---|---|---|
committer | Andrea Canciani <ranma42@gmail.com> | 2010-12-13 09:46:09 +0100 |
commit | 08cb6db5206203fda919e3d258ce7fdbb3e3c9d8 (patch) | |
tree | d6af948f3d2a1a3360bc7783bac19962288acee3 | |
parent | 790837ac68e51bdd55f13b70d54ba32917cebb45 (diff) |
pattern: Use pattern parameter range when analysing all gradients.
This patch adds support for analysing the transparency of a
radial gradient within some area of interest. Before the code
would ignore the extents for radial gradients. Linear gradients
now use _cairo_linear_pattern_box_to_parameter() allowing us
to remove the superfluous _extents_to_linear_parameter().
Reviewed-by: M Joonas Pihlaja <jpihlaja@cc.helsinki.fi>
-rw-r--r-- | src/cairo-pattern.c | 95 |
1 files changed, 44 insertions, 51 deletions
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index 1ac50b6cb..e783207e5 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -1728,38 +1728,6 @@ _cairo_pattern_reset_solid_surface_cache (void) CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock); } -static void -_extents_to_linear_parameter (const cairo_linear_pattern_t *linear, - const cairo_rectangle_int_t *extents, - double t[2]) -{ - double t0, tdx, tdy; - double p1x, p1y, pdx, pdy, invsqnorm; - - p1x = _cairo_fixed_to_double (linear->p1.x); - p1y = _cairo_fixed_to_double (linear->p1.y); - pdx = _cairo_fixed_to_double (linear->p2.x) - p1x; - pdy = _cairo_fixed_to_double (linear->p2.y) - p1y; - invsqnorm = 1.0 / (pdx * pdx + pdy * pdy); - pdx *= invsqnorm; - pdy *= invsqnorm; - - t0 = (extents->x - p1x) * pdx + (extents->y - p1y) * pdy; - tdx = extents->width * pdx; - tdy = extents->height * pdy; - - t[0] = t[1] = t0; - if (tdx < 0) - t[0] += tdx; - else - t[1] += tdx; - - if (tdy < 0) - t[0] += tdy; - else - t[1] += tdy; -} - static cairo_bool_t _linear_pattern_is_degenerate (const cairo_linear_pattern_t *linear) { @@ -2249,27 +2217,40 @@ _gradient_is_clear (const cairo_gradient_pattern_t *gradient, gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset)) return TRUE; + if (gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL) { + /* degenerate radial gradients are clear */ + if (_radial_pattern_is_degenerate ((cairo_radial_pattern_t *) gradient)) + return TRUE; + } else if (gradient->base.extend == CAIRO_EXTEND_NONE) { + /* EXTEND_NONE degenerate linear gradients are clear */ + if (_linear_pattern_is_degenerate ((cairo_linear_pattern_t *) gradient)) + return TRUE; + } + /* Check if the extents intersect the drawn part of the pattern. */ - if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) { - if (gradient->base.extend == CAIRO_EXTEND_NONE) { - cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient; - /* EXTEND_NONE degenerate linear gradients are clear */ - if (_linear_pattern_is_degenerate (linear)) + if (extents != NULL && + (gradient->base.extend == CAIRO_EXTEND_NONE || + gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL)) + { + double t[2]; + + _cairo_gradient_pattern_box_to_parameter (gradient, + extents->x, + extents->y, + extents->x + extents->width, + extents->y + extents->height, + DBL_EPSILON, + t); + + if (gradient->base.extend == CAIRO_EXTEND_NONE && + (t[0] >= gradient->stops[gradient->n_stops - 1].offset || + t[1] <= gradient->stops[0].offset)) + { return TRUE; - - if (extents != NULL) { - double t[2]; - _extents_to_linear_parameter (linear, extents, t); - if ((t[0] <= 0.0 && t[1] <= 0.0) || (t[0] >= 1.0 && t[1] >= 1.0)) - return TRUE; - } } - } else { - cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient; - /* degenerate radial gradients are clear */ - if (_radial_pattern_is_degenerate (radial)) + + if (t[0] == t[1]) return TRUE; - /* TODO: check actual intersection */ } for (i = 0; i < gradient->n_stops; i++) @@ -2487,7 +2468,13 @@ _cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient, if (extents == NULL) return FALSE; - _extents_to_linear_parameter (linear, extents, t); + _cairo_linear_pattern_box_to_parameter (linear, + extents->x, + extents->y, + extents->x + extents->width, + extents->y + extents->height, + t); + if (t[0] < 0.0 || t[1] > 1.0) return FALSE; } @@ -2599,7 +2586,13 @@ _gradient_is_opaque (const cairo_gradient_pattern_t *gradient, if (extents == NULL) return FALSE; - _extents_to_linear_parameter (linear, extents, t); + _cairo_linear_pattern_box_to_parameter (linear, + extents->x, + extents->y, + extents->x + extents->width, + extents->y + extents->height, + t); + if (t[0] < 0.0 || t[1] > 1.0) return FALSE; } |