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.

     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
     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 +}
    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 @@
    61   */
    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"
    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  }
    83  static uint16_t convert_8888_to_0565(uint32_t color)
    84  {
    85      return CONVERT_8888_TO_0565(color);
    86  }
    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);
   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;
   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;
   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;
   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  *
   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  		}
   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;
   177  	    ++buffer;
   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);
   187      return buffer;
   188  }
   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);
   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"
   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);
   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)
   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  	    }
   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 */
   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);
   293  		}
   294  		else
   295  		{
   296  		    *buffer = 0;
   297  		}
   298  	    }
   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];
   306  	}
   307      }
   309      iter->y++;

mercurial