1diff --git a/gfx/cairo/libpixman/src/pixman-access.c b/gfx/cairo/libpixman/src/pixman-access.c
2--- a/gfx/cairo/libpixman/src/pixman-access.c
3+++ b/gfx/cairo/libpixman/src/pixman-access.c
4@@ -933,16 +933,54 @@ store_scanline_x2b10g10r10 (bits_image_t
5     {
6 	WRITE (image, pixel++,
7 	       ((values[i] >> 38) & 0x3ff) |
8 	       ((values[i] >> 12) & 0xffc00) |
9 	       ((values[i] << 14) & 0x3ff00000));
10     }
11 }
12
13+static void
14+store_scanline_16 (bits_image_t *  image,
15+		   int             x,
16+		   int             y,
17+		   int             width,
18+		   const uint32_t *v)
19+{
20+    uint16_t *bits = (uint16_t*)(image->bits + image->rowstride * y);
21+    uint16_t *values = (uint16_t *)v;
22+    uint16_t *pixel = bits + x;
23+    int i;
24+
25+    for (i = 0; i < width; ++i)
26+    {
27+	WRITE (image, pixel++, values[i]);
28+    }
29+}
30+
31+static void
32+fetch_scanline_16 (pixman_image_t *image,
33+                            int             x,
34+                            int             y,
35+                            int             width,
36+                            uint32_t *      b,
37+                            const uint32_t *mask)
38+{
39+    const uint16_t *bits = (uint16_t*)(image->bits.bits + y * image->bits.rowstride);
40+    const uint16_t *pixel = bits + x;
41+    int i;
42+    uint16_t *buffer = (uint16_t *)b;
43+
44+    for (i = 0; i < width; ++i)
45+    {
46+	*buffer++ = READ (image, pixel++);
47+    }
48+}
49+
50+
51 /*
52  * Contracts a 64bpp image to 32bpp and then stores it using a regular 32-bit
53  * store proc. Despite the type, this function expects a uint64_t buffer.
54  */
55 static void
56 store_scanline_generic_64 (bits_image_t *  image,
57                            int             x,
58                            int             y,
59@@ -1044,32 +1082,47 @@ fetch_pixel_generic_lossy_32 (bits_image
60     pixman_contract (&result, &pixel64, 1);
61
62     return result;
63 }
64
65 typedef struct
66 {
67     pixman_format_code_t	format;
68+    fetch_scanline_t		fetch_scanline_16;
69     fetch_scanline_t		fetch_scanline_32;
70     fetch_scanline_t		fetch_scanline_64;
71     fetch_pixel_32_t		fetch_pixel_32;
72     fetch_pixel_64_t		fetch_pixel_64;
73+    store_scanline_t		store_scanline_16;
74     store_scanline_t		store_scanline_32;
75     store_scanline_t		store_scanline_64;
76 } format_info_t;
77
78 #define FORMAT_INFO(format) 						\
79     {									\
80 	PIXMAN_ ## format,						\
81+	    NULL,							\
82 	    fetch_scanline_ ## format,					\
83 	    fetch_scanline_generic_64,					\
84 	    fetch_pixel_ ## format, fetch_pixel_generic_64,		\
85+	    NULL,							\
86 	    store_scanline_ ## format, store_scanline_generic_64	\
87     }
88+#define FORMAT_INFO16(format) 						\
89+    {									\
90+	PIXMAN_ ## format,						\
91+	    fetch_scanline_16,						\
92+	    fetch_scanline_ ## format,					\
93+	    fetch_scanline_generic_64,					\
94+	    fetch_pixel_ ## format, fetch_pixel_generic_64,		\
95+	    store_scanline_16,						\
96+	    store_scanline_ ## format, store_scanline_generic_64	\
97+    }
98+
99
100 static const format_info_t accessors[] =
101 {
102 /* 32 bpp formats */
103     FORMAT_INFO (a8r8g8b8),
104     FORMAT_INFO (x8r8g8b8),
105     FORMAT_INFO (a8b8g8r8),
106     FORMAT_INFO (x8b8g8r8),
107@@ -1079,18 +1132,18 @@ static const format_info_t accessors[] =
108     FORMAT_INFO (r8g8b8x8),
109     FORMAT_INFO (x14r6g6b6),
110
111 /* 24bpp formats */
112     FORMAT_INFO (r8g8b8),
113     FORMAT_INFO (b8g8r8),
114
115 /* 16bpp formats */
116-    FORMAT_INFO (r5g6b5),
117-    FORMAT_INFO (b5g6r5),
118+    FORMAT_INFO16 (r5g6b5),
119+    FORMAT_INFO16 (b5g6r5),
120
121     FORMAT_INFO (a1r5g5b5),
122     FORMAT_INFO (x1r5g5b5),
123     FORMAT_INFO (a1b5g5r5),
124     FORMAT_INFO (x1b5g5r5),
125     FORMAT_INFO (a4r4g4b4),
126     FORMAT_INFO (x4r4g4b4),
127     FORMAT_INFO (a4b4g4r4),
128@@ -1132,62 +1185,64 @@ static const format_info_t accessors[] =
129
130 /* 1bpp formats */
131     FORMAT_INFO (a1),
132     FORMAT_INFO (g1),
133
134 /* Wide formats */
135
136     { PIXMAN_a2r10g10b10,
137-      NULL, fetch_scanline_a2r10g10b10,
138+      NULL, NULL, fetch_scanline_a2r10g10b10,
139       fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10,
140       NULL, store_scanline_a2r10g10b10 },
141
142     { PIXMAN_x2r10g10b10,
143-      NULL, fetch_scanline_x2r10g10b10,
144+      NULL, NULL, fetch_scanline_x2r10g10b10,
145       fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10,
146       NULL, store_scanline_x2r10g10b10 },
147
148     { PIXMAN_a2b10g10r10,
149-      NULL, fetch_scanline_a2b10g10r10,
150+      NULL, NULL, fetch_scanline_a2b10g10r10,
151       fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10,
152       NULL, store_scanline_a2b10g10r10 },
153
154     { PIXMAN_x2b10g10r10,
155-      NULL, fetch_scanline_x2b10g10r10,
156+      NULL, NULL, fetch_scanline_x2b10g10r10,
157       fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10,
158       NULL, store_scanline_x2b10g10r10 },
159
160 /* YUV formats */
161     { PIXMAN_yuy2,
162-      fetch_scanline_yuy2, fetch_scanline_generic_64,
163+      NULL, fetch_scanline_yuy2, fetch_scanline_generic_64,
164       fetch_pixel_yuy2, fetch_pixel_generic_64,
165       NULL, NULL },
166
167     { PIXMAN_yv12,
168-      fetch_scanline_yv12, fetch_scanline_generic_64,
169+      NULL, fetch_scanline_yv12, fetch_scanline_generic_64,
170       fetch_pixel_yv12, fetch_pixel_generic_64,
171       NULL, NULL },
172
173     { PIXMAN_null },
174 };
175
176 static void
177 setup_accessors (bits_image_t *image)
178 {
179     const format_info_t *info = accessors;
180
181     while (info->format != PIXMAN_null)
182     {
183 	if (info->format == image->format)
184 	{
185+	    image->fetch_scanline_16 = info->fetch_scanline_16;
186 	    image->fetch_scanline_32 = info->fetch_scanline_32;
187 	    image->fetch_scanline_64 = info->fetch_scanline_64;
188 	    image->fetch_pixel_32 = info->fetch_pixel_32;
189 	    image->fetch_pixel_64 = info->fetch_pixel_64;
190+	    image->store_scanline_16 = info->store_scanline_16;
191 	    image->store_scanline_32 = info->store_scanline_32;
192 	    image->store_scanline_64 = info->store_scanline_64;
193
194 	    return;
195 	}
196
197 	info++;
198     }
199diff --git a/gfx/cairo/libpixman/src/pixman-bits-image.c b/gfx/cairo/libpixman/src/pixman-bits-image.c
200--- a/gfx/cairo/libpixman/src/pixman-bits-image.c
201+++ b/gfx/cairo/libpixman/src/pixman-bits-image.c
202@@ -1247,16 +1247,31 @@ src_get_scanline_wide (pixman_iter_t *it
203
204 void
205 _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter)
206 {
207     if (iter->flags & ITER_NARROW)
208 	iter->get_scanline = src_get_scanline_narrow;
209     else
210 	iter->get_scanline = src_get_scanline_wide;
211+
212+}
213+
214+static uint32_t *
215+dest_get_scanline_16 (pixman_iter_t *iter, const uint32_t *mask)
216+{
217+    pixman_image_t *image  = iter->image;
218+    int             x      = iter->x;
219+    int             y      = iter->y;
220+    int             width  = iter->width;
221+    uint32_t *	    buffer = iter->buffer;
222+
223+    image->bits.fetch_scanline_16 (image, x, y, width, buffer, mask);
224+
225+    return iter->buffer;
226 }
227
228 static uint32_t *
229 dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
230 {
231     pixman_image_t *image  = iter->image;
232     int             x      = iter->x;
233     int             y      = iter->y;
234@@ -1327,16 +1342,30 @@ dest_get_scanline_wide (pixman_iter_t *i
235 	    free (alpha);
236 	}
237     }
238
239     return iter->buffer;
240 }
241
242 static void
243+dest_write_back_16 (pixman_iter_t *iter)
244+{
245+    bits_image_t *  image  = &iter->image->bits;
246+    int             x      = iter->x;
247+    int             y      = iter->y;
248+    int             width  = iter->width;
249+    const uint32_t *buffer = iter->buffer;
250+
251+    image->store_scanline_16 (image, x, y, width, buffer);
252+
253+    iter->y++;
254+}
255+
256+static void
257 dest_write_back_narrow (pixman_iter_t *iter)
258 {
259     bits_image_t *  image  = &iter->image->bits;
260     int             x      = iter->x;
261     int             y      = iter->y;
262     int             width  = iter->width;
263     const uint32_t *buffer = iter->buffer;
264
265@@ -1375,28 +1404,41 @@ dest_write_back_wide (pixman_iter_t *ite
266     }
267
268     iter->y++;
269 }
270
271 void
272 _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter)
273 {
274-    if (iter->flags & ITER_NARROW)
275+    if (iter->flags & ITER_16)
276+    {
277+        if ((iter->flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
278+	    (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
279+	{
280+            iter->get_scanline = _pixman_iter_get_scanline_noop;
281+        }
282+        else
283+        {
284+	    iter->get_scanline = dest_get_scanline_16;
285+        }
286+	iter->write_back = dest_write_back_16;
287+    }
288+    else if (iter->flags & ITER_NARROW)
289     {
290 	if ((iter->flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
291 	    (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
292 	{
293 	    iter->get_scanline = _pixman_iter_get_scanline_noop;
294 	}
295 	else
296 	{
297 	    iter->get_scanline = dest_get_scanline_narrow;
298 	}
299-
300+
301 	iter->write_back = dest_write_back_narrow;
302     }
303     else
304     {
305 	iter->get_scanline = dest_get_scanline_wide;
306 	iter->write_back = dest_write_back_wide;
307     }
308 }
309diff --git a/gfx/cairo/libpixman/src/pixman-combine16.c b/gfx/cairo/libpixman/src/pixman-combine16.c
310new file mode 100644
311--- /dev/null
312+++ b/gfx/cairo/libpixman/src/pixman-combine16.c
313@@ -0,0 +1,124 @@
314+#ifdef HAVE_CONFIG_H
315+#include <config.h>
316+#endif
317+
318+#include <math.h>
319+#include <string.h>
320+
321+#include "pixman-private.h"
322+
323+#include "pixman-combine32.h"
324+
325+static force_inline uint32_t
326+combine_mask (const uint32_t src, const uint32_t mask)
327+{
328+    uint32_t s, m;
329+
330+    m = mask >> A_SHIFT;
331+
332+    if (!m)
333+	return 0;
334+    s = src;
335+
336+    UN8x4_MUL_UN8 (s, m);
337+
338+    return s;
339+}
340+
341+static inline uint32_t convert_0565_to_8888(uint16_t color)
342+{
343+    return CONVERT_0565_TO_8888(color);
344+}
345+
346+static inline uint16_t convert_8888_to_0565(uint32_t color)
347+{
348+    return CONVERT_8888_TO_0565(color);
349+}
350+
351+static void
352+combine_src_u (pixman_implementation_t *imp,
353+               pixman_op_t              op,
354+               uint32_t *               dest,
355+               const uint32_t *         src,
356+               const uint32_t *         mask,
357+               int                      width)
358+{
359+    int i;
360+
361+    if (!mask)
362+	memcpy (dest, src, width * sizeof (uint16_t));
363+    else
364+    {
365+	uint16_t *d = (uint16_t*)dest;
366+	uint16_t *src16 = (uint16_t*)src;
367+	for (i = 0; i < width; ++i)
368+	{
369+	    if ((*mask & 0xff000000) == 0xff000000) {
370+		// it's likely worth special casing
371+		// fully opaque because it avoids
372+		// the cost of conversion as well the multiplication
373+		*(d + i) = *src16;
374+	    } else {
375+		// the mask is still 32bits
376+		uint32_t s = combine_mask (convert_0565_to_8888(*src16), *mask);
377+		*(d + i) = convert_8888_to_0565(s);
378+	    }
379+	    mask++;
380+	    src16++;
381+	}
382+    }
383+
384+}
385+
386+static void
387+combine_over_u (pixman_implementation_t *imp,
388+               pixman_op_t              op,
389+               uint32_t *                dest,
390+               const uint32_t *          src,
391+               const uint32_t *          mask,
392+               int                      width)
393+{
394+    int i;
395+
396+    if (!mask)
397+	memcpy (dest, src, width * sizeof (uint16_t));
398+    else
399+    {
400+	uint16_t *d = (uint16_t*)dest;
401+	uint16_t *src16 = (uint16_t*)src;
402+	for (i = 0; i < width; ++i)
403+	{
404+	    if ((*mask & 0xff000000) == 0xff000000) {
405+		// it's likely worth special casing
406+		// fully opaque because it avoids
407+		// the cost of conversion as well the multiplication
408+		*(d + i) = *src16;
409+	    } else if ((*mask & 0xff000000) == 0x00000000) {
410+		// keep the dest the same
411+	    } else {
412+		// the mask is still 32bits
413+		uint32_t s = combine_mask (convert_0565_to_8888(*src16), *mask);
414+		uint32_t ia = ALPHA_8 (~s);
415+		uint32_t d32 = convert_0565_to_8888(*(d + i));
416+		UN8x4_MUL_UN8_ADD_UN8x4 (d32, ia, s);
417+		*(d + i) = convert_8888_to_0565(d32);
418+	    }
419+	    mask++;
420+	    src16++;
421+	}
422+    }
423+
424+}
425+
426+
427+void
428+_pixman_setup_combiner_functions_16 (pixman_implementation_t *imp)
429+{
430+    int i;
431+    for (i = 0; i < PIXMAN_N_OPERATORS; i++) {
432+	imp->combine_16[i] = NULL;
433+    }
434+    imp->combine_16[PIXMAN_OP_SRC] = combine_src_u;
435+    imp->combine_16[PIXMAN_OP_OVER] = combine_over_u;
436+}
437+
438diff --git a/gfx/cairo/libpixman/src/pixman-general.c b/gfx/cairo/libpixman/src/pixman-general.c
439--- a/gfx/cairo/libpixman/src/pixman-general.c
440+++ b/gfx/cairo/libpixman/src/pixman-general.c
441@@ -106,46 +106,61 @@ general_composite_rect  (pixman_implemen
442     PIXMAN_COMPOSITE_ARGS (info);
443     uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8];
444     uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer;
445     uint8_t *src_buffer, *mask_buffer, *dest_buffer;
446     pixman_iter_t src_iter, mask_iter, dest_iter;
447     pixman_combine_32_func_t compose;
448     pixman_bool_t component_alpha;
449     iter_flags_t narrow, src_flags;
450+    iter_flags_t rgb16;
451     int Bpp;
452     int i;
453
454     if ((src_image->common.flags & FAST_PATH_NARROW_FORMAT)		    &&
455 	(!mask_image || mask_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
456 	(dest_image->common.flags & FAST_PATH_NARROW_FORMAT))
457     {
458 	narrow = ITER_NARROW;
459 	Bpp = 4;
460     }
461     else
462     {
463 	narrow = 0;
464 	Bpp = 8;
465     }
466
467+    // XXX: This special casing is bad. Ideally, we'd keep the general code general perhaps
468+    // by having it deal more specifically with different intermediate formats
469+    if (
470+	(dest_image->common.flags & FAST_PATH_16_FORMAT && (src_image->type == LINEAR || src_image->type == RADIAL)) &&
471+	( op == PIXMAN_OP_SRC ||
472+         (op == PIXMAN_OP_OVER && (src_image->common.flags & FAST_PATH_IS_OPAQUE))
473+	)
474+	) {
475+	rgb16 = ITER_16;
476+    } else {
477+	rgb16 = 0;
478+    }
479+
480+
481     if (width * Bpp > SCANLINE_BUFFER_LENGTH)
482     {
483 	scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
484
485 	if (!scanline_buffer)
486 	    return;
487     }
488
489     src_buffer = scanline_buffer;
490     mask_buffer = src_buffer + width * Bpp;
491     dest_buffer = mask_buffer + width * Bpp;
492
493     /* src iter */
494-    src_flags = narrow | op_flags[op].src;
495+    src_flags = narrow | op_flags[op].src | rgb16;
496
497     _pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src_image,
498 					  src_x, src_y, width, height,
499 					  src_buffer, src_flags);
500
501     /* mask iter */
502     if ((src_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
503 	(ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
504@@ -164,20 +179,20 @@ general_composite_rect  (pixman_implemen
505
506     _pixman_implementation_src_iter_init (
507 	imp->toplevel, &mask_iter, mask_image, mask_x, mask_y, width, height,
508 	mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB));
509
510     /* dest iter */
511     _pixman_implementation_dest_iter_init (
512 	imp->toplevel, &dest_iter, dest_image, dest_x, dest_y, width, height,
513-	dest_buffer, narrow | op_flags[op].dst);
514+	dest_buffer, narrow | op_flags[op].dst | rgb16);
515
516     compose = _pixman_implementation_lookup_combiner (
517-	imp->toplevel, op, component_alpha, narrow);
518+	imp->toplevel, op, component_alpha, narrow, !!rgb16);
519
520     if (!compose)
521 	return;
522
523     for (i = 0; i < height; ++i)
524     {
525 	uint32_t *s, *m, *d;
526
527@@ -234,16 +249,17 @@ general_fill (pixman_implementation_t *i
528     return FALSE;
529 }
530
531 pixman_implementation_t *
532 _pixman_implementation_create_general (void)
533 {
534     pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
535
536+    _pixman_setup_combiner_functions_16 (imp);
537     _pixman_setup_combiner_functions_32 (imp);
538     _pixman_setup_combiner_functions_64 (imp);
539
540     imp->blt = general_blt;
541     imp->fill = general_fill;
542     imp->src_iter_init = general_src_iter_init;
543     imp->dest_iter_init = general_dest_iter_init;
544
545diff --git a/gfx/cairo/libpixman/src/pixman-image.c b/gfx/cairo/libpixman/src/pixman-image.c
546--- a/gfx/cairo/libpixman/src/pixman-image.c
547+++ b/gfx/cairo/libpixman/src/pixman-image.c
548@@ -451,16 +451,20 @@ compute_image_info (pixman_image_t *imag
549 		flags |= FAST_PATH_IS_OPAQUE;
550 	}
551
552 	if (image->bits.read_func || image->bits.write_func)
553 	    flags &= ~FAST_PATH_NO_ACCESSORS;
554
555 	if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
556 	    flags &= ~FAST_PATH_NARROW_FORMAT;
557+
558+	if (image->bits.format == PIXMAN_r5g6b5)
559+	    flags |= FAST_PATH_16_FORMAT;
560+
561 	break;
562
563     case RADIAL:
564 	code = PIXMAN_unknown;
565
566 	/*
567 	 * As explained in pixman-radial-gradient.c, every point of
568 	 * the plane has a valid associated radius (and thus will be
569diff --git a/gfx/cairo/libpixman/src/pixman-implementation.c b/gfx/cairo/libpixman/src/pixman-implementation.c
570--- a/gfx/cairo/libpixman/src/pixman-implementation.c
571+++ b/gfx/cairo/libpixman/src/pixman-implementation.c
572@@ -101,45 +101,51 @@ pixman_implementation_t *
573     imp->fill = delegate_fill;
574     imp->src_iter_init = delegate_src_iter_init;
575     imp->dest_iter_init = delegate_dest_iter_init;
576
577     imp->fast_paths = fast_paths;
578
579     for (i = 0; i < PIXMAN_N_OPERATORS; ++i)
580     {
581+	imp->combine_16[i] = NULL;
582 	imp->combine_32[i] = NULL;
583 	imp->combine_64[i] = NULL;
584 	imp->combine_32_ca[i] = NULL;
585 	imp->combine_64_ca[i] = NULL;
586     }
587
588     return imp;
589 }
590
591 pixman_combine_32_func_t
592 _pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
593 					pixman_op_t		 op,
594 					pixman_bool_t		 component_alpha,
595-					pixman_bool_t		 narrow)
596+					pixman_bool_t		 narrow,
597+					pixman_bool_t		 rgb16)
598 {
599     pixman_combine_32_func_t f;
600
601     do
602     {
603 	pixman_combine_32_func_t (*combiners[]) =
604 	{
605 	    (pixman_combine_32_func_t *)imp->combine_64,
606 	    (pixman_combine_32_func_t *)imp->combine_64_ca,
607 	    imp->combine_32,
608 	    imp->combine_32_ca,
609+	    (pixman_combine_32_func_t *)imp->combine_16,
610+	    NULL,
611 	};
612-
613-	f = combiners[component_alpha | (narrow << 1)][op];
614-
615+        if (rgb16) {
616+            f = combiners[4][op];
617+        } else {
618+            f = combiners[component_alpha + (narrow << 1)][op];
619+        }
620 	imp = imp->delegate;
621     }
622     while (!f);
623
624     return f;
625 }
626
627 pixman_bool_t
628diff --git a/gfx/cairo/libpixman/src/pixman-linear-gradient.c b/gfx/cairo/libpixman/src/pixman-linear-gradient.c
629--- a/gfx/cairo/libpixman/src/pixman-linear-gradient.c
630+++ b/gfx/cairo/libpixman/src/pixman-linear-gradient.c
631@@ -217,42 +217,185 @@ linear_get_scanline_narrow (pixman_iter_
632 	}
633     }
634
635     iter->y++;
636
637     return iter->buffer;
638 }
639
640+static uint16_t convert_8888_to_0565(uint32_t color)
641+{
642+    return CONVERT_8888_TO_0565(color);
643+}
644+
645+static uint32_t *
646+linear_get_scanline_16 (pixman_iter_t  *iter,
647+			const uint32_t *mask)
648+{
649+    pixman_image_t *image  = iter->image;
650+    int             x      = iter->x;
651+    int             y      = iter->y;
652+    int             width  = iter->width;
653+    uint16_t *      buffer = (uint16_t*)iter->buffer;
654+
655+    pixman_vector_t v, unit;
656+    pixman_fixed_32_32_t l;
657+    pixman_fixed_48_16_t dx, dy;
658+    gradient_t *gradient = (gradient_t *)image;
659+    linear_gradient_t *linear = (linear_gradient_t *)image;
660+    uint16_t *end = buffer + width;
661+    pixman_gradient_walker_t walker;
662+
663+    _pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
664+
665+    /* reference point is the center of the pixel */
666+    v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
667+    v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
668+    v.vector[2] = pixman_fixed_1;
669+
670+    if (image->common.transform)
671+    {
672+	if (!pixman_transform_point_3d (image->common.transform, &v))
673+	    return iter->buffer;
674+
675+	unit.vector[0] = image->common.transform->matrix[0][0];
676+	unit.vector[1] = image->common.transform->matrix[1][0];
677+	unit.vector[2] = image->common.transform->matrix[2][0];
678+    }
679+    else
680+    {
681+	unit.vector[0] = pixman_fixed_1;
682+	unit.vector[1] = 0;
683+	unit.vector[2] = 0;
684+    }
685+
686+    dx = linear->p2.x - linear->p1.x;
687+    dy = linear->p2.y - linear->p1.y;
688+
689+    l = dx * dx + dy * dy;
690+
691+    if (l == 0 || unit.vector[2] == 0)
692+    {
693+	/* affine transformation only */
694+        pixman_fixed_32_32_t t, next_inc;
695+	double inc;
696+
697+	if (l == 0 || v.vector[2] == 0)
698+	{
699+	    t = 0;
700+	    inc = 0;
701+	}
702+	else
703+	{
704+	    double invden, v2;
705+
706+	    invden = pixman_fixed_1 * (double) pixman_fixed_1 /
707+		(l * (double) v.vector[2]);
708+	    v2 = v.vector[2] * (1. / pixman_fixed_1);
709+	    t = ((dx * v.vector[0] + dy * v.vector[1]) -
710+		 (dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
711+	    inc = (dx * unit.vector[0] + dy * unit.vector[1]) * invden;
712+	}
713+	next_inc = 0;
714+
715+	if (((pixman_fixed_32_32_t )(inc * width)) == 0)
716+	{
717+	    register uint16_t color;
718+
719+	    color = convert_8888_to_0565(_pixman_gradient_walker_pixel (&walker, t));
720+	    while (buffer < end)
721+		*buffer++ = color;
722+	}
723+	else
724+	{
725+	    int i;
726+
727+	    i = 0;
728+	    while (buffer < end)
729+	    {
730+		if (!mask || *mask++)
731+		{
732+		    *buffer = convert_8888_to_0565(_pixman_gradient_walker_pixel (&walker,
733+										  t + next_inc));
734+		}
735+		i++;
736+		next_inc = inc * i;
737+		buffer++;
738+	    }
739+	}
740+    }
741+    else
742+    {
743+	/* projective transformation */
744+        double t;
745+
746+	t = 0;
747+
748+	while (buffer < end)
749+	{
750+	    if (!mask || *mask++)
751+	    {
752+	        if (v.vector[2] != 0)
753+		{
754+		    double invden, v2;
755+
756+		    invden = pixman_fixed_1 * (double) pixman_fixed_1 /
757+			(l * (double) v.vector[2]);
758+		    v2 = v.vector[2] * (1. / pixman_fixed_1);
759+		    t = ((dx * v.vector[0] + dy * v.vector[1]) -
760+			 (dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
761+		}
762+
763+		*buffer = convert_8888_to_0565(_pixman_gradient_walker_pixel (&walker, t));
764+	    }
765+
766+	    ++buffer;
767+
768+	    v.vector[0] += unit.vector[0];
769+	    v.vector[1] += unit.vector[1];
770+	    v.vector[2] += unit.vector[2];
771+	}
772+    }
773+
774+    iter->y++;
775+
776+    return iter->buffer;
777+}
778+
779 static uint32_t *
780 linear_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
781 {
782     uint32_t *buffer = linear_get_scanline_narrow (iter, NULL);
783
784     pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
785
786     return buffer;
787 }
788
789 void
790 _pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t  *iter)
791 {
792     if (linear_gradient_is_horizontal (
793 	    iter->image, iter->x, iter->y, iter->width, iter->height))
794     {
795-	if (iter->flags & ITER_NARROW)
796+	if (iter->flags & ITER_16)
797+	    linear_get_scanline_16 (iter, NULL);
798+	else if (iter->flags & ITER_NARROW)
799 	    linear_get_scanline_narrow (iter, NULL);
800 	else
801 	    linear_get_scanline_wide (iter, NULL);
802
803 	iter->get_scanline = _pixman_iter_get_scanline_noop;
804     }
805     else
806     {
807-	if (iter->flags & ITER_NARROW)
808+	if (iter->flags & ITER_16)
809+	    iter->get_scanline = linear_get_scanline_16;
810+	else if (iter->flags & ITER_NARROW)
811 	    iter->get_scanline = linear_get_scanline_narrow;
812 	else
813 	    iter->get_scanline = linear_get_scanline_wide;
814     }
815 }
816
817 PIXMAN_EXPORT pixman_image_t *
818 pixman_image_create_linear_gradient (pixman_point_fixed_t *        p1,
819diff --git a/gfx/cairo/libpixman/src/pixman-private.h b/gfx/cairo/libpixman/src/pixman-private.h
820--- a/gfx/cairo/libpixman/src/pixman-private.h
821+++ b/gfx/cairo/libpixman/src/pixman-private.h
822@@ -152,24 +152,28 @@ struct bits_image
823     int                        height;
824     uint32_t *                 bits;
825     uint32_t *                 free_me;
826     int                        rowstride;  /* in number of uint32_t's */
827
828     fetch_scanline_t           get_scanline_32;
829     fetch_scanline_t           get_scanline_64;
830
831+    fetch_scanline_t           fetch_scanline_16;
832+
833     fetch_scanline_t           fetch_scanline_32;
834     fetch_pixel_32_t	       fetch_pixel_32;
835     store_scanline_t           store_scanline_32;
836
837     fetch_scanline_t           fetch_scanline_64;
838     fetch_pixel_64_t	       fetch_pixel_64;
839     store_scanline_t           store_scanline_64;
840
841+    store_scanline_t           store_scanline_16;
842+
843     /* Used for indirect access to the bits */
844     pixman_read_memory_func_t  read_func;
845     pixman_write_memory_func_t write_func;
846 };
847
848 union pixman_image
849 {
850     image_type_t       type;
851@@ -202,17 +206,24 @@ typedef enum
852      * destination.
853      *
854      * When he destination is xRGB, this is useful knowledge, because then
855      * we can treat it as if it were ARGB, which means in some cases we can
856      * avoid copying it to a temporary buffer.
857      */
858     ITER_LOCALIZED_ALPHA =	(1 << 1),
859     ITER_IGNORE_ALPHA =		(1 << 2),
860-    ITER_IGNORE_RGB =		(1 << 3)
861+    ITER_IGNORE_RGB =		(1 << 3),
862+
863+    /* With the addition of ITER_16 we now have two flags that to represent
864+     * 3 pipelines. This means that there can be an invalid state when
865+     * both ITER_NARROW and ITER_16 are set. In this case
866+     * ITER_16 overrides NARROW and we should use the 16 bit pipeline.
867+     * Note: ITER_16 still has a 32 bit mask, which is a bit weird. */
868+    ITER_16 =			(1 << 4)
869 } iter_flags_t;
870
871 struct pixman_iter_t
872 {
873     /* These are initialized by _pixman_implementation_{src,dest}_init */
874     pixman_image_t *		image;
875     uint32_t *			buffer;
876     int				x, y;
877@@ -429,16 +440,17 @@ typedef pixman_bool_t (*pixman_fill_func
878 					     int                      x,
879 					     int                      y,
880 					     int                      width,
881 					     int                      height,
882 					     uint32_t                 xor);
883 typedef void (*pixman_iter_init_func_t) (pixman_implementation_t *imp,
884                                          pixman_iter_t           *iter);
885
886+void _pixman_setup_combiner_functions_16 (pixman_implementation_t *imp);
887 void _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp);
888 void _pixman_setup_combiner_functions_64 (pixman_implementation_t *imp);
889
890 typedef struct
891 {
892     pixman_op_t             op;
893     pixman_format_code_t    src_format;
894     uint32_t		    src_flags;
895@@ -459,32 +471,34 @@ struct pixman_implementation_t
896     pixman_fill_func_t		fill;
897     pixman_iter_init_func_t     src_iter_init;
898     pixman_iter_init_func_t     dest_iter_init;
899
900     pixman_combine_32_func_t	combine_32[PIXMAN_N_OPERATORS];
901     pixman_combine_32_func_t	combine_32_ca[PIXMAN_N_OPERATORS];
902     pixman_combine_64_func_t	combine_64[PIXMAN_N_OPERATORS];
903     pixman_combine_64_func_t	combine_64_ca[PIXMAN_N_OPERATORS];
904+    pixman_combine_64_func_t	combine_16[PIXMAN_N_OPERATORS];
905 };
906
907 uint32_t
908 _pixman_image_get_solid (pixman_implementation_t *imp,
909 			 pixman_image_t *         image,
910                          pixman_format_code_t     format);
911
912 pixman_implementation_t *
913 _pixman_implementation_create (pixman_implementation_t *delegate,
914 			       const pixman_fast_path_t *fast_paths);
915
916 pixman_combine_32_func_t
917 _pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
918 					pixman_op_t		 op,
919 					pixman_bool_t		 component_alpha,
920-					pixman_bool_t		 wide);
921+					pixman_bool_t		 wide,
922+					pixman_bool_t		 rgb16);
923
924 pixman_bool_t
925 _pixman_implementation_blt (pixman_implementation_t *imp,
926                             uint32_t *               src_bits,
927                             uint32_t *               dst_bits,
928                             int                      src_stride,
929                             int                      dst_stride,
930                             int                      src_bpp,
931@@ -613,16 +627,17 @@ uint32_t *
932 #define FAST_PATH_Y_UNIT_ZERO			(1 << 18)
933 #define FAST_PATH_BILINEAR_FILTER		(1 << 19)
934 #define FAST_PATH_ROTATE_90_TRANSFORM		(1 << 20)
935 #define FAST_PATH_ROTATE_180_TRANSFORM		(1 << 21)
936 #define FAST_PATH_ROTATE_270_TRANSFORM		(1 << 22)
937 #define FAST_PATH_SAMPLES_COVER_CLIP_NEAREST	(1 << 23)
938 #define FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR	(1 << 24)
939 #define FAST_PATH_BITS_IMAGE			(1 << 25)
940+#define FAST_PATH_16_FORMAT			(1 << 26)
941
942 #define FAST_PATH_PAD_REPEAT						\
943     (FAST_PATH_NO_NONE_REPEAT		|				\
944      FAST_PATH_NO_NORMAL_REPEAT		|				\
945      FAST_PATH_NO_REFLECT_REPEAT)
946
947 #define FAST_PATH_NORMAL_REPEAT						\
948     (FAST_PATH_NO_NONE_REPEAT		|				\
949diff --git a/gfx/cairo/libpixman/src/pixman-radial-gradient.c b/gfx/cairo/libpixman/src/pixman-radial-gradient.c
950--- a/gfx/cairo/libpixman/src/pixman-radial-gradient.c
951+++ b/gfx/cairo/libpixman/src/pixman-radial-gradient.c
952@@ -395,35 +395,289 @@ radial_get_scanline_narrow (pixman_iter_
953 	    v.vector[2] += unit.vector[2];
954 	}
955     }
956
957     iter->y++;
958     return iter->buffer;
959 }
960
961+static uint16_t convert_8888_to_0565(uint32_t color)
962+{
963+    return CONVERT_8888_TO_0565(color);
964+}
965+
966+static uint32_t *
967+radial_get_scanline_16 (pixman_iter_t *iter, const uint32_t *mask)
968+{
969+    /*
970+     * Implementation of radial gradients following the PDF specification.
971+     * See section 8.7.4.5.4 Type 3 (Radial) Shadings of the PDF Reference
972+     * Manual (PDF 32000-1:2008 at the time of this writing).
973+     *
974+     * In the radial gradient problem we are given two circles (c₁,r₁) and
975+     * (c₂,r₂) that define the gradient itself.
976+     *
977+     * Mathematically the gradient can be defined as the family of circles
978+     *
979+     *     ((1-t)·c₁ + t·(c₂), (1-t)·r₁ + t·r₂)
980+     *
981+     * excluding those circles whose radius would be < 0. When a point
982+     * belongs to more than one circle, the one with a bigger t is the only
983+     * one that contributes to its color. When a point does not belong
984+     * to any of the circles, it is transparent black, i.e. RGBA (0, 0, 0, 0).
985+     * Further limitations on the range of values for t are imposed when
986+     * the gradient is not repeated, namely t must belong to [0,1].
987+     *
988+     * The graphical result is the same as drawing the valid (radius > 0)
989+     * circles with increasing t in [-inf, +inf] (or in [0,1] if the gradient
990+     * is not repeated) using SOURCE operator composition.
991+     *
992+     * It looks like a cone pointing towards the viewer if the ending circle
993+     * is smaller than the starting one, a cone pointing inside the page if
994+     * the starting circle is the smaller one and like a cylinder if they
995+     * have the same radius.
996+     *
997+     * What we actually do is, given the point whose color we are interested
998+     * in, compute the t values for that point, solving for t in:
999+     *
1000+     *     length((1-t)·c₁ + t·(c₂) - p) = (1-t)·r₁ + t·r₂
1001+     *
1002+     * Let's rewrite it in a simpler way, by defining some auxiliary
1003+     * variables:
1004+     *
1005+     *     cd = c₂ - c₁
1006+     *     pd = p - c₁
1007+     *     dr = r₂ - r₁
1008+     *     length(t·cd - pd) = r₁ + t·dr
1009+     *
1010+     * which actually means
1011+     *
1012+     *     hypot(t·cdx - pdx, t·cdy - pdy) = r₁ + t·dr
1013+     *
1014+     * or
1015+     *
1016+     *     ⎷((t·cdx - pdx)² + (t·cdy - pdy)²) = r₁ + t·dr.
1017+     *
1018+     * If we impose (as stated earlier) that r₁ + t·dr >= 0, it becomes:
1019+     *
1020+     *     (t·cdx - pdx)² + (t·cdy - pdy)² = (r₁ + t·dr)²
1021+     *
1022+     * where we can actually expand the squares and solve for t:
1023+     *
1024+     *     t²cdx² - 2t·cdx·pdx + pdx² + t²cdy² - 2t·cdy·pdy + pdy² =
1025+     *       = r₁² + 2·r₁·t·dr + t²·dr²
1026+     *
1027+     *     (cdx² + cdy² - dr²)t² - 2(cdx·pdx + cdy·pdy + r₁·dr)t +
1028+     *         (pdx² + pdy² - r₁²) = 0
1029+     *
1030+     *     A = cdx² + cdy² - dr²
1031+     *     B = pdx·cdx + pdy·cdy + r₁·dr
1032+     *     C = pdx² + pdy² - r₁²
1033+     *     At² - 2Bt + C = 0
1034+     *
1035+     * The solutions (unless the equation degenerates because of A = 0) are:
1036+     *
1037+     *     t = (B ± ⎷(B² - A·C)) / A
1038+     *
1039+     * The solution we are going to prefer is the bigger one, unless the
1040+     * radius associated to it is negative (or it falls outside the valid t
1041+     * range).
1042+     *
1043+     * Additional observations (useful for optimizations):
1044+     * A does not depend on p
1045+     *
1046+     * A < 0 <=> one of the two circles completely contains the other one
1047+     *   <=> for every p, the radiuses associated with the two t solutions
1048+     *       have opposite sign
1049+     */
1050+    pixman_image_t *image = iter->image;
1051+    int x = iter->x;
1052+    int y = iter->y;
1053+    int width = iter->width;
1054+    uint16_t *buffer = iter->buffer;
1055+
1056+    gradient_t *gradient = (gradient_t *)image;
1057+    radial_gradient_t *radial = (radial_gradient_t *)image;
1058+    uint16_t *end = buffer + width;
1059+    pixman_gradient_walker_t walker;
1060+    pixman_vector_t v, unit;
1061+
1062+    /* reference point is the center of the pixel */
1063+    v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
1064+    v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
1065+    v.vector[2] = pixman_fixed_1;
1066+
1067+    _pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
1068+
1069+    if (image->common.transform)
1070+    {
1071+	if (!pixman_transform_point_3d (image->common.transform, &v))
1072+	    return iter->buffer;
1073+
1074+	unit.vector[0] = image->common.transform->matrix[0][0];
1075+	unit.vector[1] = image->common.transform->matrix[1][0];
1076+	unit.vector[2] = image->common.transform->matrix[2][0];
1077+    }
1078+    else
1079+    {
1080+	unit.vector[0] = pixman_fixed_1;
1081+	unit.vector[1] = 0;
1082+	unit.vector[2] = 0;
1083+    }
1084+
1085+    if (unit.vector[2] == 0 && v.vector[2] == pixman_fixed_1)
1086+    {
1087+	/*
1088+	 * Given:
1089+	 *
1090+	 * t = (B ± ⎷(B² - A·C)) / A
1091+	 *
1092+	 * where
1093+	 *
1094+	 * A = cdx² + cdy² - dr²
1095+	 * B = pdx·cdx + pdy·cdy + r₁·dr
1096+	 * C = pdx² + pdy² - r₁²
1097+	 * det = B² - A·C
1098+	 *
1099+	 * Since we have an affine transformation, we know that (pdx, pdy)
1100+	 * increase linearly with each pixel,
1101+	 *
1102+	 * pdx = pdx₀ + n·ux,
1103+	 * pdy = pdy₀ + n·uy,
1104+	 *
1105+	 * we can then express B, C and det through multiple differentiation.
1106+	 */
1107+	pixman_fixed_32_32_t b, db, c, dc, ddc;
1108+
1109+	/* warning: this computation may overflow */
1110+	v.vector[0] -= radial->c1.x;
1111+	v.vector[1] -= radial->c1.y;
1112+
1113+	/*
1114+	 * B and C are computed and updated exactly.
1115+	 * If fdot was used instead of dot, in the worst case it would
1116+	 * lose 11 bits of precision in each of the multiplication and
1117+	 * summing up would zero out all the bit that were preserved,
1118+	 * thus making the result 0 instead of the correct one.
1119+	 * This would mean a worst case of unbound relative error or
1120+	 * about 2^10 absolute error
1121+	 */
1122+	b = dot (v.vector[0], v.vector[1], radial->c1.radius,
1123+		 radial->delta.x, radial->delta.y, radial->delta.radius);
1124+	db = dot (unit.vector[0], unit.vector[1], 0,
1125+		  radial->delta.x, radial->delta.y, 0);
1126+
1127+	c = dot (v.vector[0], v.vector[1],
1128+		 -((pixman_fixed_48_16_t) radial->c1.radius),
1129+		 v.vector[0], v.vector[1], radial->c1.radius);
1130+	dc = dot (2 * (pixman_fixed_48_16_t) v.vector[0] + unit.vector[0],
1131+		  2 * (pixman_fixed_48_16_t) v.vector[1] + unit.vector[1],
1132+		  0,
1133+		  unit.vector[0], unit.vector[1], 0);
1134+	ddc = 2 * dot (unit.vector[0], unit.vector[1], 0,
1135+		       unit.vector[0], unit.vector[1], 0);
1136+
1137+	while (buffer < end)
1138+	{
1139+	    if (!mask || *mask++)
1140+	    {
1141+		*buffer = convert_8888_to_0565(
1142+			  radial_compute_color (radial->a, b, c,
1143+						radial->inva,
1144+						radial->delta.radius,
1145+						radial->mindr,
1146+						&walker,
1147+						image->common.repeat));
1148+	    }
1149+
1150+	    b += db;
1151+	    c += dc;
1152+	    dc += ddc;
1153+	    ++buffer;
1154+	}
1155+    }
1156+    else
1157+    {
1158+	/* projective */
1159+	/* Warning:
1160+	 * error propagation guarantees are much looser than in the affine case
1161+	 */
1162+	while (buffer < end)
1163+	{
1164+	    if (!mask || *mask++)
1165+	    {
1166+		if (v.vector[2] != 0)
1167+		{
1168+		    double pdx, pdy, invv2, b, c;
1169+
1170+		    invv2 = 1. * pixman_fixed_1 / v.vector[2];
1171+
1172+		    pdx = v.vector[0] * invv2 - radial->c1.x;
1173+		    /*    / pixman_fixed_1 */
1174+
1175+		    pdy = v.vector[1] * invv2 - radial->c1.y;
1176+		    /*    / pixman_fixed_1 */
1177+
1178+		    b = fdot (pdx, pdy, radial->c1.radius,
1179+			      radial->delta.x, radial->delta.y,
1180+			      radial->delta.radius);
1181+		    /*  / pixman_fixed_1 / pixman_fixed_1 */
1182+
1183+		    c = fdot (pdx, pdy, -radial->c1.radius,
1184+			      pdx, pdy, radial->c1.radius);
1185+		    /*  / pixman_fixed_1 / pixman_fixed_1 */
1186+
1187+		    *buffer = convert_8888_to_0565 (
1188+			      radial_compute_color (radial->a, b, c,
1189+						    radial->inva,
1190+						    radial->delta.radius,
1191+						    radial->mindr,
1192+						    &walker,
1193+						    image->common.repeat));
1194+		}
1195+		else
1196+		{
1197+		    *buffer = 0;
1198+		}
1199+	    }
1200+
1201+	    ++buffer;
1202+
1203+	    v.vector[0] += unit.vector[0];
1204+	    v.vector[1] += unit.vector[1];
1205+	    v.vector[2] += unit.vector[2];
1206+	}
1207+    }
1208+
1209+    iter->y++;
1210+    return iter->buffer;
1211+}
1212 static uint32_t *
1213 radial_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
1214 {
1215     uint32_t *buffer = radial_get_scanline_narrow (iter, NULL);
1216
1217     pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
1218
1219     return buffer;
1220 }
1221
1222 void
1223 _pixman_radial_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
1224 {
1225-    if (iter->flags & ITER_NARROW)
1226+    if (iter->flags & ITER_16)
1227+	iter->get_scanline = radial_get_scanline_16;
1228+    else if (iter->flags & ITER_NARROW)
1229 	iter->get_scanline = radial_get_scanline_narrow;
1230     else
1231 	iter->get_scanline = radial_get_scanline_wide;
1232 }
1233
1234+
1235 PIXMAN_EXPORT pixman_image_t *
1236 pixman_image_create_radial_gradient (pixman_point_fixed_t *        inner,
1237                                      pixman_point_fixed_t *        outer,
1238                                      pixman_fixed_t                inner_radius,
1239                                      pixman_fixed_t                outer_radius,
1240                                      const pixman_gradient_stop_t *stops,
1241                                      int                           n_stops)
1242 {
1243