diff options
author | Andrea Canciani <ranma42@gmail.com> | 2011-01-05 12:15:06 +0100 |
---|---|---|
committer | Andrea Canciani <ranma42@gmail.com> | 2011-01-19 11:53:52 +0100 |
commit | 7d89d69c494bb438ca1caddf1a2226a48297e4b6 (patch) | |
tree | 7121c100b25b11d152c44078dd1e1befcec740ec /src/cairo-quartz-surface.c | |
parent | 4874dab984fe73ae687b354aff45b879e1de9db2 (diff) |
quartz: Make huge domain handling more stable
Quartz cannot correctly handle arbitrary domains. Falling back is
needed to get correct results on very large (in parameter space)
gradients.
For PAD extended gradients, limiting the domain to (at most) [-0.5,
1.5] is sufficient to guarantee that it will correctly sample the
extreme stops and improves the accuracy (over having a much bigger
domain).
Fixes radial-gradient, radial-gradient-mask, radial-gradient-source,
radial-gradient-mask-source, radial-gradient-one-stop.
Improves the quality of the linear gradients in linear-gradient,
linear-gradient-subset, mask, operator-source, trap-clip.
Diffstat (limited to 'src/cairo-quartz-surface.c')
-rw-r--r-- | src/cairo-quartz-surface.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c index cacfeefb..e8ac7f6b 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -831,6 +831,11 @@ static const CGFunctionCallbacks gradient_callbacks = { 0, ComputeGradientValue, (CGFunctionReleaseInfoCallback) cairo_pattern_destroy }; +/* Quartz computes a small number of samples of the gradient color + * function. On MacOS X 10.5 it apparently computes only 1024 + * samples. */ +#define MAX_GRADIENT_RANGE 1024 + static CGFunctionRef _cairo_quartz_create_gradient_function (const cairo_gradient_pattern_t *gradient, const cairo_rectangle_int_t *extents, @@ -862,6 +867,12 @@ _cairo_quartz_create_gradient_function (const cairo_gradient_pattern_t *gradient tolerance, t); + if (gradient->base.extend == CAIRO_EXTEND_PAD) { + t[0] = MAX (t[0], -0.5); + t[1] = MIN (t[1], 1.5); + } else if (t[1] - t[0] > MAX_GRADIENT_RANGE) + return NULL; + /* set the input range for the function -- the function knows how to map values outside of 0.0 .. 1.0 to the correct color */ input_value_range[0] = t[0]; @@ -875,8 +886,6 @@ _cairo_quartz_create_gradient_function (const cairo_gradient_pattern_t *gradient _cairo_gradient_pattern_interpolate (gradient, input_value_range[1], end); if (_cairo_pattern_create_copy (&pat, &gradient->base)) - /* quartz doesn't deal very well with malloc failing, so there's - * not much point in us trying either */ return NULL; return CGFunctionCreate (pat, @@ -1156,13 +1165,16 @@ _cairo_quartz_setup_gradient_source (cairo_quartz_drawing_state_t *state, cairo_matrix_invert (&mat); _cairo_quartz_cairo_matrix_to_quartz (&mat, &state->transform); - rgb = CGColorSpaceCreateDeviceRGB (); - gradFunc = _cairo_quartz_create_gradient_function (gradient, extents, &start, &end); + if (unlikely (gradFunc == NULL)) + return CAIRO_INT_STATUS_UNSUPPORTED; + + rgb = CGColorSpaceCreateDeviceRGB (); + if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) { state->shading = CGShadingCreateAxial (rgb, CGPointMake (start.center.x, |