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