summaryrefslogtreecommitdiff
path: root/gfx/cairo/quartz-first-stop.patch
blob: 5ea4b916cd1f519c03599f384f3534d03ed3e57e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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,