gfx/cairo/quartz-first-stop.patch
author ffxbld
Wed, 04 Aug 2010 18:10:29 -0700
branchGECKO20b3_20100804_RELBRANCH
changeset 48887 58e6149956439d59b8281c4bc1986a4b2c83964d
parent 34472 4e88b5896a2c1be3c6365c0efb7397fc62e06054
permissions -rw-r--r--
Added tag FIREFOX_4_0b3_RELEASE for changeset 69f2d0457750. CLOSED TREE

diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c
--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
@@ -690,31 +690,51 @@ ComputeGradientValue (void *info, const 
 }
 
 static const float gradient_output_value_ranges[8] = {
     0.f, 1.f, 0.f, 1.f, 0.f, 1.f, 0.f, 1.f
 };
 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 float nonrepeating_gradient_input_value_range[2] = { -0.001f, 1.f };
 
 static CGFunctionRef
 CreateGradientFunction (const cairo_gradient_pattern_t *gpat)
 {
     cairo_pattern_t *pat;
-    float 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
 	 * not much point in us trying either */
 	return NULL;
 
     return CGFunctionCreate (pat,
 			     1,
-			     input_value_range,
+			     nonrepeating_gradient_input_value_range,
 			     4,
 			     gradient_output_value_ranges,
 			     &gradient_callbacks);
 }
 
 static void
 UpdateLinearParametersToIncludePoint(double *min_t, double *max_t, CGPoint *start,
                                      double dx, double dy,