1diff --git a/gfx/cairo/libpixman/src/pixman-dither.h b/gfx/cairo/libpixman/src/pixman-dither.h
2new file mode 100644
3--- /dev/null
4+++ b/gfx/cairo/libpixman/src/pixman-dither.h
5@@ -0,0 +1,51 @@
6+#define R16_BITS     5
7+#define G16_BITS     6
8+#define B16_BITS     5
9+
10+#define R16_SHIFT    (B16_BITS + G16_BITS)
11+#define G16_SHIFT    (B16_BITS)
12+#define B16_SHIFT    0
13+
14+#define MASK 0xff
15+#define ONE_HALF 0x80
16+
17+#define A_SHIFT 8 * 3
18+#define R_SHIFT 8 * 2
19+#define G_SHIFT 8
20+#define A_MASK 0xff000000
21+#define R_MASK 0xff0000
22+#define G_MASK 0xff00
23+
24+#define RB_MASK 0xff00ff
25+#define AG_MASK 0xff00ff00
26+#define RB_ONE_HALF 0x800080
27+#define RB_MASK_PLUS_ONE 0x10000100
28+
29+#define ALPHA_8(x) ((x) >> A_SHIFT)
30+#define RED_8(x) (((x) >> R_SHIFT) & MASK)
31+#define GREEN_8(x) (((x) >> G_SHIFT) & MASK)
32+#define BLUE_8(x) ((x) & MASK)
33+
34+// This uses the same dithering technique that Skia does.
35+// It is essentially preturbing the lower bit based on the
36+// high bit
37+static inline uint16_t dither_32_to_16(uint32_t c)
38+{
39+    uint8_t b = BLUE_8(c);
40+    uint8_t g = GREEN_8(c);
41+    uint8_t r = RED_8(c);
42+    r = ((r << 1) - ((r >> (8 - R16_BITS) << (8 - R16_BITS)) | (r >> R16_BITS))) >> (8 - R16_BITS);
43+    g = ((g << 1) - ((g >> (8 - G16_BITS) << (8 - G16_BITS)) | (g >> G16_BITS))) >> (8 - G16_BITS);
44+    b = ((b << 1) - ((b >> (8 - B16_BITS) << (8 - B16_BITS)) | (b >> B16_BITS))) >> (8 - B16_BITS);
45+    return ((r << R16_SHIFT) | (g << G16_SHIFT) | (b << B16_SHIFT));
46+}
47+
48+static inline uint16_t dither_8888_to_0565(uint32_t color, pixman_bool_t toggle)
49+{
50+    // alternate between a preturbed truncation and a regular truncation
51+    if (toggle) {
52+	return dither_32_to_16(color);
53+    } else {
54+	return CONVERT_8888_TO_0565(color);
55+    }
56+}
57diff --git a/gfx/cairo/libpixman/src/pixman-linear-gradient.c b/gfx/cairo/libpixman/src/pixman-linear-gradient.c
58--- a/gfx/cairo/libpixman/src/pixman-linear-gradient.c
59+++ b/gfx/cairo/libpixman/src/pixman-linear-gradient.c
60@@ -26,16 +26,18 @@
61  */
62
63 #ifdef HAVE_CONFIG_H
64 #include <config.h>
65 #endif
66 #include <stdlib.h>
67 #include "pixman-private.h"
68
69+#include "pixman-dither.h"
70+
71 static pixman_bool_t
72 linear_gradient_is_horizontal (pixman_image_t *image,
73 			       int             x,
74 			       int             y,
75 			       int             width,
76 			       int             height)
77 {
78     linear_gradient_t *linear = (linear_gradient_t *)image;
79@@ -222,25 +224,28 @@ linear_get_scanline_narrow (pixman_iter_
80     return iter->buffer;
81 }
82
83 static uint16_t convert_8888_to_0565(uint32_t color)
84 {
85     return CONVERT_8888_TO_0565(color);
86 }
87
88+
89+
90 static uint32_t *
91 linear_get_scanline_16 (pixman_iter_t  *iter,
92 			const uint32_t *mask)
93 {
94     pixman_image_t *image  = iter->image;
95     int             x      = iter->x;
96     int             y      = iter->y;
97     int             width  = iter->width;
98     uint16_t *      buffer = (uint16_t*)iter->buffer;
99+    pixman_bool_t   toggle = ((x ^ y) & 1);
100
101     pixman_vector_t v, unit;
102     pixman_fixed_32_32_t l;
103     pixman_fixed_48_16_t dx, dy;
104     gradient_t *gradient = (gradient_t *)image;
105     linear_gradient_t *linear = (linear_gradient_t *)image;
106     uint16_t *end = buffer + width;
107     pixman_gradient_walker_t walker;
108@@ -294,34 +299,47 @@ linear_get_scanline_16 (pixman_iter_t  *
109 	    t = ((dx * v.vector[0] + dy * v.vector[1]) -
110 		 (dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
111 	    inc = (dx * unit.vector[0] + dy * unit.vector[1]) * invden;
112 	}
113 	next_inc = 0;
114
115 	if (((pixman_fixed_32_32_t )(inc * width)) == 0)
116 	{
117-	    register uint16_t color;
118+	    register uint32_t color;
119+	    uint16_t dither_diff;
120+	    uint16_t color16;
121+	    uint16_t color16b;
122
123-	    color = convert_8888_to_0565(_pixman_gradient_walker_pixel (&walker, t));
124-	    while (buffer < end)
125-		*buffer++ = color;
126+	    color = _pixman_gradient_walker_pixel (&walker, t);
127+	    color16 = dither_8888_to_0565(color, toggle);
128+	    color16b = dither_8888_to_0565(color, toggle^1);
129+	    // compute the difference
130+	    dither_diff =  color16 ^ color16b;
131+	    while (buffer < end) {
132+		*buffer++ = color16;
133+		// use dither_diff to toggle between color16 and color16b
134+		color16 ^= dither_diff;
135+		toggle ^= 1;
136+	    }
137 	}
138 	else
139 	{
140 	    int i;
141
142 	    i = 0;
143 	    while (buffer < end)
144 	    {
145 		if (!mask || *mask++)
146 		{
147-		    *buffer = convert_8888_to_0565(_pixman_gradient_walker_pixel (&walker,
148-										  t + next_inc));
149+		    *buffer = dither_8888_to_0565(_pixman_gradient_walker_pixel (&walker,
150+										 t + next_inc),
151+						  toggle);
152 		}
153+		toggle ^= 1;
154 		i++;
155 		next_inc = inc * i;
156 		buffer++;
157 	    }
158 	}
159     }
160     else
161     {
162@@ -340,18 +358,20 @@ linear_get_scanline_16 (pixman_iter_t  *
163
164 		    invden = pixman_fixed_1 * (double) pixman_fixed_1 /
165 			(l * (double) v.vector[2]);
166 		    v2 = v.vector[2] * (1. / pixman_fixed_1);
167 		    t = ((dx * v.vector[0] + dy * v.vector[1]) -
168 			 (dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
169 		}
170
171-		*buffer = convert_8888_to_0565(_pixman_gradient_walker_pixel (&walker, t));
172+		*buffer = dither_8888_to_0565(_pixman_gradient_walker_pixel (&walker, t),
173+					      toggle);
174 	    }
175+	    toggle ^= 1;
176
177 	    ++buffer;
178
179 	    v.vector[0] += unit.vector[0];
180 	    v.vector[1] += unit.vector[1];
181 	    v.vector[2] += unit.vector[2];
182 	}
183     }
184@@ -369,17 +389,18 @@ linear_get_scanline_wide (pixman_iter_t
185     pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
186
187     return buffer;
188 }
189
190 void
191 _pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t  *iter)
192 {
193-    if (linear_gradient_is_horizontal (
194+    // XXX: we can't use this optimization when dithering
195+    if (0 && linear_gradient_is_horizontal (
196 	    iter->image, iter->x, iter->y, iter->width, iter->height))
197     {
198 	if (iter->flags & ITER_16)
199 	    linear_get_scanline_16 (iter, NULL);
200 	else if (iter->flags & ITER_NARROW)
201 	    linear_get_scanline_narrow (iter, NULL);
202 	else
203 	    linear_get_scanline_wide (iter, NULL);
204diff --git a/gfx/cairo/libpixman/src/pixman-radial-gradient.c b/gfx/cairo/libpixman/src/pixman-radial-gradient.c
205--- a/gfx/cairo/libpixman/src/pixman-radial-gradient.c
206+++ b/gfx/cairo/libpixman/src/pixman-radial-gradient.c
207@@ -29,16 +29,18 @@
208
209 #ifdef HAVE_CONFIG_H
210 #include <config.h>
211 #endif
212 #include <stdlib.h>
213 #include <math.h>
214 #include "pixman-private.h"
215
216+#include "pixman-dither.h"
217+
218 static inline pixman_fixed_32_32_t
219 dot (pixman_fixed_48_16_t x1,
220      pixman_fixed_48_16_t y1,
221      pixman_fixed_48_16_t z1,
222      pixman_fixed_48_16_t x2,
223      pixman_fixed_48_16_t y2,
224      pixman_fixed_48_16_t z2)
225 {
226@@ -489,16 +491,17 @@ radial_get_scanline_16 (pixman_iter_t *i
227      *   <=> for every p, the radiuses associated with the two t solutions
228      *       have opposite sign
229      */
230     pixman_image_t *image = iter->image;
231     int x = iter->x;
232     int y = iter->y;
233     int width = iter->width;
234     uint16_t *buffer = iter->buffer;
235+    pixman_bool_t toggle = ((x ^ y) & 1);
236
237     gradient_t *gradient = (gradient_t *)image;
238     radial_gradient_t *radial = (radial_gradient_t *)image;
239     uint16_t *end = buffer + width;
240     pixman_gradient_walker_t walker;
241     pixman_vector_t v, unit;
242
243     /* reference point is the center of the pixel */
244@@ -575,25 +578,27 @@ radial_get_scanline_16 (pixman_iter_t *i
245 		  unit.vector[0], unit.vector[1], 0);
246 	ddc = 2 * dot (unit.vector[0], unit.vector[1], 0,
247 		       unit.vector[0], unit.vector[1], 0);
248
249 	while (buffer < end)
250 	{
251 	    if (!mask || *mask++)
252 	    {
253-		*buffer = convert_8888_to_0565(
254+		*buffer = dither_8888_to_0565(
255 			  radial_compute_color (radial->a, b, c,
256 						radial->inva,
257 						radial->delta.radius,
258 						radial->mindr,
259 						&walker,
260-						image->common.repeat));
261+						image->common.repeat),
262+			  toggle);
263 	    }
264
265+	    toggle ^= 1;
266 	    b += db;
267 	    c += dc;
268 	    dc += ddc;
269 	    ++buffer;
270 	}
271     }
272     else
273     {
274@@ -621,31 +626,33 @@ radial_get_scanline_16 (pixman_iter_t *i
275 			      radial->delta.x, radial->delta.y,
276 			      radial->delta.radius);
277 		    /*  / pixman_fixed_1 / pixman_fixed_1 */
278
279 		    c = fdot (pdx, pdy, -radial->c1.radius,
280 			      pdx, pdy, radial->c1.radius);
281 		    /*  / pixman_fixed_1 / pixman_fixed_1 */
282
283-		    *buffer = convert_8888_to_0565 (
284+		    *buffer = dither_8888_to_0565 (
285 			      radial_compute_color (radial->a, b, c,
286 						    radial->inva,
287 						    radial->delta.radius,
288 						    radial->mindr,
289 						    &walker,
290-						    image->common.repeat));
291+						    image->common.repeat),
292+			      toggle);
293 		}
294 		else
295 		{
296 		    *buffer = 0;
297 		}
298 	    }
299
300 	    ++buffer;
301+	    toggle ^= 1;
302
303 	    v.vector[0] += unit.vector[0];
304 	    v.vector[1] += unit.vector[1];
305 	    v.vector[2] += unit.vector[2];
306 	}
307     }
308
309     iter->y++;
310
311