michael@0: diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c michael@0: --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c michael@0: +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c michael@0: @@ -690,31 +690,51 @@ ComputeGradientValue (void *info, const michael@0: } michael@0: michael@0: static const float gradient_output_value_ranges[8] = { michael@0: 0.f, 1.f, 0.f, 1.f, 0.f, 1.f, 0.f, 1.f michael@0: }; michael@0: static const CGFunctionCallbacks gradient_callbacks = { michael@0: 0, ComputeGradientValue, (CGFunctionReleaseInfoCallback) cairo_pattern_destroy michael@0: }; michael@0: +/* Quartz will clamp input values to the input range. michael@0: + michael@0: + Our stops are all in the range 0.0 to 1.0. However, the color before the michael@0: + beginning of the gradient line is obtained by Quartz computing a negative michael@0: + position on the gradient line, clamping it to the input range we specified michael@0: + for our color function, and then calling our color function (actually it michael@0: + pre-samples the color function into an array, but that doesn't matter just michael@0: + here). Therefore if we set the lower bound to 0.0, a negative position michael@0: + on the gradient line will pass 0.0 to ComputeGradientValue, which will michael@0: + select the last color stop with position 0, although it should select michael@0: + the first color stop (this matters when there are multiple color stops with michael@0: + position 0). michael@0: + michael@0: + Therefore we pass a small negative number as the lower bound of the input michael@0: + range, so this value gets passed into ComputeGradientValue, which will michael@0: + return the color of the first stop. The number should be small because michael@0: + as far as I can tell, Quartz pre-samples the entire input range of the color michael@0: + function into an array of fixed size, so if the input range is larger michael@0: + than needed, the resolution of the gradient will be unnecessarily low. michael@0: +*/ michael@0: +static const float nonrepeating_gradient_input_value_range[2] = { -0.001f, 1.f }; michael@0: michael@0: static CGFunctionRef michael@0: CreateGradientFunction (const cairo_gradient_pattern_t *gpat) michael@0: { michael@0: cairo_pattern_t *pat; michael@0: - float input_value_range[2] = { 0.f, 1.f }; michael@0: michael@0: if (_cairo_pattern_create_copy (&pat, &gpat->base)) michael@0: /* quartz doesn't deal very well with malloc failing, so there's michael@0: * not much point in us trying either */ michael@0: return NULL; michael@0: michael@0: return CGFunctionCreate (pat, michael@0: 1, michael@0: - input_value_range, michael@0: + nonrepeating_gradient_input_value_range, michael@0: 4, michael@0: gradient_output_value_ranges, michael@0: &gradient_callbacks); michael@0: } michael@0: michael@0: static void michael@0: UpdateLinearParametersToIncludePoint(double *min_t, double *max_t, CGPoint *start, michael@0: double dx, double dy,