Bug 1687807 [wpt PR 27261] - Remove leftover debugging line from dom/historical.html...
[gecko.git] / gfx / cairo / pixman-dither.patch
blob633a8d7282d5ea8216352fe1569d2037e658b01f
1 diff --git a/gfx/cairo/libpixman/src/pixman-dither.h b/gfx/cairo/libpixman/src/pixman-dither.h
2 new 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
10 +#define R16_SHIFT (B16_BITS + G16_BITS)
11 +#define G16_SHIFT (B16_BITS)
12 +#define B16_SHIFT 0
14 +#define MASK 0xff
15 +#define ONE_HALF 0x80
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
24 +#define RB_MASK 0xff00ff
25 +#define AG_MASK 0xff00ff00
26 +#define RB_ONE_HALF 0x800080
27 +#define RB_MASK_PLUS_ONE 0x10000100
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)
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)
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));
48 +static inline uint16_t dither_8888_to_0565(uint32_t color, pixman_bool_t toggle)
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 + }
57 diff --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 @@
63 #ifdef HAVE_CONFIG_H
64 #include <config.h>
65 #endif
66 #include <stdlib.h>
67 #include "pixman-private.h"
69 +#include "pixman-dither.h"
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)
78 linear_gradient_t *linear = (linear_gradient_t *)image;
79 @@ -222,25 +224,28 @@ linear_get_scanline_narrow (pixman_iter_
80 return iter->buffer;
83 static uint16_t convert_8888_to_0565(uint32_t color)
85 return CONVERT_8888_TO_0565(color);
90 static uint32_t *
91 linear_get_scanline_16 (pixman_iter_t *iter,
92 const uint32_t *mask)
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);
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;
113 next_inc = 0;
115 if (((pixman_fixed_32_32_t )(inc * width)) == 0)
117 - register uint16_t color;
118 + register uint32_t color;
119 + uint16_t dither_diff;
120 + uint16_t color16;
121 + uint16_t color16b;
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;
138 else
140 int i;
142 i = 0;
143 while (buffer < end)
145 if (!mask || *mask++)
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);
153 + toggle ^= 1;
154 i++;
155 next_inc = inc * i;
156 buffer++;
160 else
162 @@ -340,18 +358,20 @@ linear_get_scanline_16 (pixman_iter_t *
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;
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);
175 + toggle ^= 1;
177 ++buffer;
179 v.vector[0] += unit.vector[0];
180 v.vector[1] += unit.vector[1];
181 v.vector[2] += unit.vector[2];
184 @@ -369,17 +389,18 @@ linear_get_scanline_wide (pixman_iter_t
185 pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
187 return buffer;
190 void
191 _pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
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))
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);
204 diff --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 @@
209 #ifdef HAVE_CONFIG_H
210 #include <config.h>
211 #endif
212 #include <stdlib.h>
213 #include <math.h>
214 #include "pixman-private.h"
216 +#include "pixman-dither.h"
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)
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
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);
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;
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);
249 while (buffer < end)
251 if (!mask || *mask++)
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);
265 + toggle ^= 1;
266 b += db;
267 c += dc;
268 dc += ddc;
269 ++buffer;
272 else
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 */
279 c = fdot (pdx, pdy, -radial->c1.radius,
280 pdx, pdy, radial->c1.radius);
281 /* / pixman_fixed_1 / pixman_fixed_1 */
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);
294 else
296 *buffer = 0;
300 ++buffer;
301 + toggle ^= 1;
303 v.vector[0] += unit.vector[0];
304 v.vector[1] += unit.vector[1];
305 v.vector[2] += unit.vector[2];
309 iter->y++;