gfx/cairo/pixman-dither.patch

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial