Ensure the quartz backend returns the first stop for negative positions on the gradient line of a nonrepeating linear gradient.

I discovered a small bug in cairo-quartz gradients. If you have multiple stops
at position 0, then cairo-quartz pads with the *last* stop at position 0,
instead of the first stop at position 0. This patch fixes that.

From https://bugzilla.mozilla.org/show_bug.cgi?id=513395
This commit is contained in:
Robert O'Callahan 2010-05-11 13:59:58 -04:00 committed by Jeff Muizelaar
parent ce27db9a55
commit d65e8064c0

View file

@ -800,12 +800,32 @@ static const cairo_quartz_float_t gradient_output_value_ranges[8] = {
static const CGFunctionCallbacks gradient_callbacks = {
0, ComputeGradientValue, (CGFunctionReleaseInfoCallback) cairo_pattern_destroy
};
/* Quartz will clamp input values to the input range.
Our stops are all in the range 0.0 to 1.0. However, the color before the
beginning of the gradient line is obtained by Quartz computing a negative
position on the gradient line, clamping it to the input range we specified
for our color function, and then calling our color function (actually it
pre-samples the color function into an array, but that doesn't matter just
here). Therefore if we set the lower bound to 0.0, a negative position
on the gradient line will pass 0.0 to ComputeGradientValue, which will
select the last color stop with position 0, although it should select
the first color stop (this matters when there are multiple color stops with
position 0).
Therefore we pass a small negative number as the lower bound of the input
range, so this value gets passed into ComputeGradientValue, which will
return the color of the first stop. The number should be small because
as far as I can tell, Quartz pre-samples the entire input range of the color
function into an array of fixed size, so if the input range is larger
than needed, the resolution of the gradient will be unnecessarily low.
*/
static const cairo_quartz_float_t nonrepeating_gradient_input_value_range[2] = { -0.001f, 1.f };
static CGFunctionRef
CreateGradientFunction (const cairo_gradient_pattern_t *gpat)
{
cairo_pattern_t *pat;
cairo_quartz_float_t input_value_range[2] = { 0.f, 1.f };
if (_cairo_pattern_create_copy (&pat, &gpat->base))
/* quartz doesn't deal very well with malloc failing, so there's
@ -814,7 +834,7 @@ CreateGradientFunction (const cairo_gradient_pattern_t *gpat)
return CGFunctionCreate (pat,
1,
input_value_range,
nonrepeating_gradient_input_value_range,
4,
gradient_output_value_ranges,
&gradient_callbacks);