gfx/cairo/libpixman/src/pixman-combine.c.template

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 #ifdef HAVE_CONFIG_H
michael@0 2 #include <config.h>
michael@0 3 #endif
michael@0 4
michael@0 5 #include <math.h>
michael@0 6 #include <string.h>
michael@0 7
michael@0 8 #include "pixman-private.h"
michael@0 9
michael@0 10 #include "pixman-combine.h"
michael@0 11
michael@0 12 /*** per channel helper functions ***/
michael@0 13
michael@0 14 static void
michael@0 15 combine_mask_ca (comp4_t *src, comp4_t *mask)
michael@0 16 {
michael@0 17 comp4_t a = *mask;
michael@0 18
michael@0 19 comp4_t x;
michael@0 20 comp2_t xa;
michael@0 21
michael@0 22 if (!a)
michael@0 23 {
michael@0 24 *(src) = 0;
michael@0 25 return;
michael@0 26 }
michael@0 27
michael@0 28 x = *(src);
michael@0 29 if (a == ~0)
michael@0 30 {
michael@0 31 x = x >> A_SHIFT;
michael@0 32 x |= x << G_SHIFT;
michael@0 33 x |= x << R_SHIFT;
michael@0 34 *(mask) = x;
michael@0 35 return;
michael@0 36 }
michael@0 37
michael@0 38 xa = x >> A_SHIFT;
michael@0 39 UNcx4_MUL_UNcx4 (x, a);
michael@0 40 *(src) = x;
michael@0 41
michael@0 42 UNcx4_MUL_UNc (a, xa);
michael@0 43 *(mask) = a;
michael@0 44 }
michael@0 45
michael@0 46 static void
michael@0 47 combine_mask_value_ca (comp4_t *src, const comp4_t *mask)
michael@0 48 {
michael@0 49 comp4_t a = *mask;
michael@0 50 comp4_t x;
michael@0 51
michael@0 52 if (!a)
michael@0 53 {
michael@0 54 *(src) = 0;
michael@0 55 return;
michael@0 56 }
michael@0 57
michael@0 58 if (a == ~0)
michael@0 59 return;
michael@0 60
michael@0 61 x = *(src);
michael@0 62 UNcx4_MUL_UNcx4 (x, a);
michael@0 63 *(src) = x;
michael@0 64 }
michael@0 65
michael@0 66 static void
michael@0 67 combine_mask_alpha_ca (const comp4_t *src, comp4_t *mask)
michael@0 68 {
michael@0 69 comp4_t a = *(mask);
michael@0 70 comp4_t x;
michael@0 71
michael@0 72 if (!a)
michael@0 73 return;
michael@0 74
michael@0 75 x = *(src) >> A_SHIFT;
michael@0 76 if (x == MASK)
michael@0 77 return;
michael@0 78
michael@0 79 if (a == ~0)
michael@0 80 {
michael@0 81 x |= x << G_SHIFT;
michael@0 82 x |= x << R_SHIFT;
michael@0 83 *(mask) = x;
michael@0 84 return;
michael@0 85 }
michael@0 86
michael@0 87 UNcx4_MUL_UNc (a, x);
michael@0 88 *(mask) = a;
michael@0 89 }
michael@0 90
michael@0 91 /*
michael@0 92 * There are two ways of handling alpha -- either as a single unified value or
michael@0 93 * a separate value for each component, hence each macro must have two
michael@0 94 * versions. The unified alpha version has a 'U' at the end of the name,
michael@0 95 * the component version has a 'C'. Similarly, functions which deal with
michael@0 96 * this difference will have two versions using the same convention.
michael@0 97 */
michael@0 98
michael@0 99 /*
michael@0 100 * All of the composing functions
michael@0 101 */
michael@0 102
michael@0 103 static force_inline comp4_t
michael@0 104 combine_mask (const comp4_t *src, const comp4_t *mask, int i)
michael@0 105 {
michael@0 106 comp4_t s, m;
michael@0 107
michael@0 108 if (mask)
michael@0 109 {
michael@0 110 m = *(mask + i) >> A_SHIFT;
michael@0 111
michael@0 112 if (!m)
michael@0 113 return 0;
michael@0 114 }
michael@0 115
michael@0 116 s = *(src + i);
michael@0 117
michael@0 118 if (mask)
michael@0 119 UNcx4_MUL_UNc (s, m);
michael@0 120
michael@0 121 return s;
michael@0 122 }
michael@0 123
michael@0 124 static void
michael@0 125 combine_clear (pixman_implementation_t *imp,
michael@0 126 pixman_op_t op,
michael@0 127 comp4_t * dest,
michael@0 128 const comp4_t * src,
michael@0 129 const comp4_t * mask,
michael@0 130 int width)
michael@0 131 {
michael@0 132 memset (dest, 0, width * sizeof(comp4_t));
michael@0 133 }
michael@0 134
michael@0 135 static void
michael@0 136 combine_dst (pixman_implementation_t *imp,
michael@0 137 pixman_op_t op,
michael@0 138 comp4_t * dest,
michael@0 139 const comp4_t * src,
michael@0 140 const comp4_t * mask,
michael@0 141 int width)
michael@0 142 {
michael@0 143 return;
michael@0 144 }
michael@0 145
michael@0 146 static void
michael@0 147 combine_src_u (pixman_implementation_t *imp,
michael@0 148 pixman_op_t op,
michael@0 149 comp4_t * dest,
michael@0 150 const comp4_t * src,
michael@0 151 const comp4_t * mask,
michael@0 152 int width)
michael@0 153 {
michael@0 154 int i;
michael@0 155
michael@0 156 if (!mask)
michael@0 157 memcpy (dest, src, width * sizeof (comp4_t));
michael@0 158 else
michael@0 159 {
michael@0 160 for (i = 0; i < width; ++i)
michael@0 161 {
michael@0 162 comp4_t s = combine_mask (src, mask, i);
michael@0 163
michael@0 164 *(dest + i) = s;
michael@0 165 }
michael@0 166 }
michael@0 167 }
michael@0 168
michael@0 169 /* if the Src is opaque, call combine_src_u */
michael@0 170 static void
michael@0 171 combine_over_u (pixman_implementation_t *imp,
michael@0 172 pixman_op_t op,
michael@0 173 comp4_t * dest,
michael@0 174 const comp4_t * src,
michael@0 175 const comp4_t * mask,
michael@0 176 int width)
michael@0 177 {
michael@0 178 int i;
michael@0 179
michael@0 180 for (i = 0; i < width; ++i)
michael@0 181 {
michael@0 182 comp4_t s = combine_mask (src, mask, i);
michael@0 183 comp4_t d = *(dest + i);
michael@0 184 comp4_t ia = ALPHA_c (~s);
michael@0 185
michael@0 186 UNcx4_MUL_UNc_ADD_UNcx4 (d, ia, s);
michael@0 187 *(dest + i) = d;
michael@0 188 }
michael@0 189 }
michael@0 190
michael@0 191 /* if the Dst is opaque, this is a noop */
michael@0 192 static void
michael@0 193 combine_over_reverse_u (pixman_implementation_t *imp,
michael@0 194 pixman_op_t op,
michael@0 195 comp4_t * dest,
michael@0 196 const comp4_t * src,
michael@0 197 const comp4_t * mask,
michael@0 198 int width)
michael@0 199 {
michael@0 200 int i;
michael@0 201
michael@0 202 for (i = 0; i < width; ++i)
michael@0 203 {
michael@0 204 comp4_t s = combine_mask (src, mask, i);
michael@0 205 comp4_t d = *(dest + i);
michael@0 206 comp4_t ia = ALPHA_c (~*(dest + i));
michael@0 207 UNcx4_MUL_UNc_ADD_UNcx4 (s, ia, d);
michael@0 208 *(dest + i) = s;
michael@0 209 }
michael@0 210 }
michael@0 211
michael@0 212 /* if the Dst is opaque, call combine_src_u */
michael@0 213 static void
michael@0 214 combine_in_u (pixman_implementation_t *imp,
michael@0 215 pixman_op_t op,
michael@0 216 comp4_t * dest,
michael@0 217 const comp4_t * src,
michael@0 218 const comp4_t * mask,
michael@0 219 int width)
michael@0 220 {
michael@0 221 int i;
michael@0 222
michael@0 223 for (i = 0; i < width; ++i)
michael@0 224 {
michael@0 225 comp4_t s = combine_mask (src, mask, i);
michael@0 226 comp4_t a = ALPHA_c (*(dest + i));
michael@0 227 UNcx4_MUL_UNc (s, a);
michael@0 228 *(dest + i) = s;
michael@0 229 }
michael@0 230 }
michael@0 231
michael@0 232 /* if the Src is opaque, this is a noop */
michael@0 233 static void
michael@0 234 combine_in_reverse_u (pixman_implementation_t *imp,
michael@0 235 pixman_op_t op,
michael@0 236 comp4_t * dest,
michael@0 237 const comp4_t * src,
michael@0 238 const comp4_t * mask,
michael@0 239 int width)
michael@0 240 {
michael@0 241 int i;
michael@0 242
michael@0 243 for (i = 0; i < width; ++i)
michael@0 244 {
michael@0 245 comp4_t s = combine_mask (src, mask, i);
michael@0 246 comp4_t d = *(dest + i);
michael@0 247 comp4_t a = ALPHA_c (s);
michael@0 248 UNcx4_MUL_UNc (d, a);
michael@0 249 *(dest + i) = d;
michael@0 250 }
michael@0 251 }
michael@0 252
michael@0 253 /* if the Dst is opaque, call combine_clear */
michael@0 254 static void
michael@0 255 combine_out_u (pixman_implementation_t *imp,
michael@0 256 pixman_op_t op,
michael@0 257 comp4_t * dest,
michael@0 258 const comp4_t * src,
michael@0 259 const comp4_t * mask,
michael@0 260 int width)
michael@0 261 {
michael@0 262 int i;
michael@0 263
michael@0 264 for (i = 0; i < width; ++i)
michael@0 265 {
michael@0 266 comp4_t s = combine_mask (src, mask, i);
michael@0 267 comp4_t a = ALPHA_c (~*(dest + i));
michael@0 268 UNcx4_MUL_UNc (s, a);
michael@0 269 *(dest + i) = s;
michael@0 270 }
michael@0 271 }
michael@0 272
michael@0 273 /* if the Src is opaque, call combine_clear */
michael@0 274 static void
michael@0 275 combine_out_reverse_u (pixman_implementation_t *imp,
michael@0 276 pixman_op_t op,
michael@0 277 comp4_t * dest,
michael@0 278 const comp4_t * src,
michael@0 279 const comp4_t * mask,
michael@0 280 int width)
michael@0 281 {
michael@0 282 int i;
michael@0 283
michael@0 284 for (i = 0; i < width; ++i)
michael@0 285 {
michael@0 286 comp4_t s = combine_mask (src, mask, i);
michael@0 287 comp4_t d = *(dest + i);
michael@0 288 comp4_t a = ALPHA_c (~s);
michael@0 289 UNcx4_MUL_UNc (d, a);
michael@0 290 *(dest + i) = d;
michael@0 291 }
michael@0 292 }
michael@0 293
michael@0 294 /* if the Src is opaque, call combine_in_u */
michael@0 295 /* if the Dst is opaque, call combine_over_u */
michael@0 296 /* if both the Src and Dst are opaque, call combine_src_u */
michael@0 297 static void
michael@0 298 combine_atop_u (pixman_implementation_t *imp,
michael@0 299 pixman_op_t op,
michael@0 300 comp4_t * dest,
michael@0 301 const comp4_t * src,
michael@0 302 const comp4_t * mask,
michael@0 303 int width)
michael@0 304 {
michael@0 305 int i;
michael@0 306
michael@0 307 for (i = 0; i < width; ++i)
michael@0 308 {
michael@0 309 comp4_t s = combine_mask (src, mask, i);
michael@0 310 comp4_t d = *(dest + i);
michael@0 311 comp4_t dest_a = ALPHA_c (d);
michael@0 312 comp4_t src_ia = ALPHA_c (~s);
michael@0 313
michael@0 314 UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (s, dest_a, d, src_ia);
michael@0 315 *(dest + i) = s;
michael@0 316 }
michael@0 317 }
michael@0 318
michael@0 319 /* if the Src is opaque, call combine_over_reverse_u */
michael@0 320 /* if the Dst is opaque, call combine_in_reverse_u */
michael@0 321 /* if both the Src and Dst are opaque, call combine_dst_u */
michael@0 322 static void
michael@0 323 combine_atop_reverse_u (pixman_implementation_t *imp,
michael@0 324 pixman_op_t op,
michael@0 325 comp4_t * dest,
michael@0 326 const comp4_t * src,
michael@0 327 const comp4_t * mask,
michael@0 328 int width)
michael@0 329 {
michael@0 330 int i;
michael@0 331
michael@0 332 for (i = 0; i < width; ++i)
michael@0 333 {
michael@0 334 comp4_t s = combine_mask (src, mask, i);
michael@0 335 comp4_t d = *(dest + i);
michael@0 336 comp4_t src_a = ALPHA_c (s);
michael@0 337 comp4_t dest_ia = ALPHA_c (~d);
michael@0 338
michael@0 339 UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (s, dest_ia, d, src_a);
michael@0 340 *(dest + i) = s;
michael@0 341 }
michael@0 342 }
michael@0 343
michael@0 344 /* if the Src is opaque, call combine_over_u */
michael@0 345 /* if the Dst is opaque, call combine_over_reverse_u */
michael@0 346 /* if both the Src and Dst are opaque, call combine_clear */
michael@0 347 static void
michael@0 348 combine_xor_u (pixman_implementation_t *imp,
michael@0 349 pixman_op_t op,
michael@0 350 comp4_t * dest,
michael@0 351 const comp4_t * src,
michael@0 352 const comp4_t * mask,
michael@0 353 int width)
michael@0 354 {
michael@0 355 int i;
michael@0 356
michael@0 357 for (i = 0; i < width; ++i)
michael@0 358 {
michael@0 359 comp4_t s = combine_mask (src, mask, i);
michael@0 360 comp4_t d = *(dest + i);
michael@0 361 comp4_t src_ia = ALPHA_c (~s);
michael@0 362 comp4_t dest_ia = ALPHA_c (~d);
michael@0 363
michael@0 364 UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (s, dest_ia, d, src_ia);
michael@0 365 *(dest + i) = s;
michael@0 366 }
michael@0 367 }
michael@0 368
michael@0 369 static void
michael@0 370 combine_add_u (pixman_implementation_t *imp,
michael@0 371 pixman_op_t op,
michael@0 372 comp4_t * dest,
michael@0 373 const comp4_t * src,
michael@0 374 const comp4_t * mask,
michael@0 375 int width)
michael@0 376 {
michael@0 377 int i;
michael@0 378
michael@0 379 for (i = 0; i < width; ++i)
michael@0 380 {
michael@0 381 comp4_t s = combine_mask (src, mask, i);
michael@0 382 comp4_t d = *(dest + i);
michael@0 383 UNcx4_ADD_UNcx4 (d, s);
michael@0 384 *(dest + i) = d;
michael@0 385 }
michael@0 386 }
michael@0 387
michael@0 388 /* if the Src is opaque, call combine_add_u */
michael@0 389 /* if the Dst is opaque, call combine_add_u */
michael@0 390 /* if both the Src and Dst are opaque, call combine_add_u */
michael@0 391 static void
michael@0 392 combine_saturate_u (pixman_implementation_t *imp,
michael@0 393 pixman_op_t op,
michael@0 394 comp4_t * dest,
michael@0 395 const comp4_t * src,
michael@0 396 const comp4_t * mask,
michael@0 397 int width)
michael@0 398 {
michael@0 399 int i;
michael@0 400
michael@0 401 for (i = 0; i < width; ++i)
michael@0 402 {
michael@0 403 comp4_t s = combine_mask (src, mask, i);
michael@0 404 comp4_t d = *(dest + i);
michael@0 405 comp2_t sa, da;
michael@0 406
michael@0 407 sa = s >> A_SHIFT;
michael@0 408 da = ~d >> A_SHIFT;
michael@0 409 if (sa > da)
michael@0 410 {
michael@0 411 sa = DIV_UNc (da, sa);
michael@0 412 UNcx4_MUL_UNc (s, sa);
michael@0 413 }
michael@0 414 ;
michael@0 415 UNcx4_ADD_UNcx4 (d, s);
michael@0 416 *(dest + i) = d;
michael@0 417 }
michael@0 418 }
michael@0 419
michael@0 420 /*
michael@0 421 * PDF blend modes:
michael@0 422 * The following blend modes have been taken from the PDF ISO 32000
michael@0 423 * specification, which at this point in time is available from
michael@0 424 * http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
michael@0 425 * The relevant chapters are 11.3.5 and 11.3.6.
michael@0 426 * The formula for computing the final pixel color given in 11.3.6 is:
michael@0 427 * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
michael@0 428 * with B() being the blend function.
michael@0 429 * Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs
michael@0 430 *
michael@0 431 * These blend modes should match the SVG filter draft specification, as
michael@0 432 * it has been designed to mirror ISO 32000. Note that at the current point
michael@0 433 * no released draft exists that shows this, as the formulas have not been
michael@0 434 * updated yet after the release of ISO 32000.
michael@0 435 *
michael@0 436 * The default implementation here uses the PDF_SEPARABLE_BLEND_MODE and
michael@0 437 * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an
michael@0 438 * argument. Note that this implementation operates on premultiplied colors,
michael@0 439 * while the PDF specification does not. Therefore the code uses the formula
michael@0 440 * Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as)
michael@0 441 */
michael@0 442
michael@0 443 /*
michael@0 444 * Multiply
michael@0 445 * B(Dca, ad, Sca, as) = Dca.Sca
michael@0 446 */
michael@0 447
michael@0 448 static void
michael@0 449 combine_multiply_u (pixman_implementation_t *imp,
michael@0 450 pixman_op_t op,
michael@0 451 comp4_t * dest,
michael@0 452 const comp4_t * src,
michael@0 453 const comp4_t * mask,
michael@0 454 int width)
michael@0 455 {
michael@0 456 int i;
michael@0 457
michael@0 458 for (i = 0; i < width; ++i)
michael@0 459 {
michael@0 460 comp4_t s = combine_mask (src, mask, i);
michael@0 461 comp4_t d = *(dest + i);
michael@0 462 comp4_t ss = s;
michael@0 463 comp4_t src_ia = ALPHA_c (~s);
michael@0 464 comp4_t dest_ia = ALPHA_c (~d);
michael@0 465
michael@0 466 UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (ss, dest_ia, d, src_ia);
michael@0 467 UNcx4_MUL_UNcx4 (d, s);
michael@0 468 UNcx4_ADD_UNcx4 (d, ss);
michael@0 469
michael@0 470 *(dest + i) = d;
michael@0 471 }
michael@0 472 }
michael@0 473
michael@0 474 static void
michael@0 475 combine_multiply_ca (pixman_implementation_t *imp,
michael@0 476 pixman_op_t op,
michael@0 477 comp4_t * dest,
michael@0 478 const comp4_t * src,
michael@0 479 const comp4_t * mask,
michael@0 480 int width)
michael@0 481 {
michael@0 482 int i;
michael@0 483
michael@0 484 for (i = 0; i < width; ++i)
michael@0 485 {
michael@0 486 comp4_t m = *(mask + i);
michael@0 487 comp4_t s = *(src + i);
michael@0 488 comp4_t d = *(dest + i);
michael@0 489 comp4_t r = d;
michael@0 490 comp4_t dest_ia = ALPHA_c (~d);
michael@0 491
michael@0 492 combine_mask_value_ca (&s, &m);
michael@0 493
michael@0 494 UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (r, ~m, s, dest_ia);
michael@0 495 UNcx4_MUL_UNcx4 (d, s);
michael@0 496 UNcx4_ADD_UNcx4 (r, d);
michael@0 497
michael@0 498 *(dest + i) = r;
michael@0 499 }
michael@0 500 }
michael@0 501
michael@0 502 #define PDF_SEPARABLE_BLEND_MODE(name) \
michael@0 503 static void \
michael@0 504 combine_ ## name ## _u (pixman_implementation_t *imp, \
michael@0 505 pixman_op_t op, \
michael@0 506 comp4_t * dest, \
michael@0 507 const comp4_t * src, \
michael@0 508 const comp4_t * mask, \
michael@0 509 int width) \
michael@0 510 { \
michael@0 511 int i; \
michael@0 512 for (i = 0; i < width; ++i) { \
michael@0 513 comp4_t s = combine_mask (src, mask, i); \
michael@0 514 comp4_t d = *(dest + i); \
michael@0 515 comp1_t sa = ALPHA_c (s); \
michael@0 516 comp1_t isa = ~sa; \
michael@0 517 comp1_t da = ALPHA_c (d); \
michael@0 518 comp1_t ida = ~da; \
michael@0 519 comp4_t result; \
michael@0 520 \
michael@0 521 result = d; \
michael@0 522 UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (result, isa, s, ida); \
michael@0 523 \
michael@0 524 *(dest + i) = result + \
michael@0 525 (DIV_ONE_UNc (sa * (comp4_t)da) << A_SHIFT) + \
michael@0 526 (blend_ ## name (RED_c (d), da, RED_c (s), sa) << R_SHIFT) + \
michael@0 527 (blend_ ## name (GREEN_c (d), da, GREEN_c (s), sa) << G_SHIFT) + \
michael@0 528 (blend_ ## name (BLUE_c (d), da, BLUE_c (s), sa)); \
michael@0 529 } \
michael@0 530 } \
michael@0 531 \
michael@0 532 static void \
michael@0 533 combine_ ## name ## _ca (pixman_implementation_t *imp, \
michael@0 534 pixman_op_t op, \
michael@0 535 comp4_t * dest, \
michael@0 536 const comp4_t * src, \
michael@0 537 const comp4_t * mask, \
michael@0 538 int width) \
michael@0 539 { \
michael@0 540 int i; \
michael@0 541 for (i = 0; i < width; ++i) { \
michael@0 542 comp4_t m = *(mask + i); \
michael@0 543 comp4_t s = *(src + i); \
michael@0 544 comp4_t d = *(dest + i); \
michael@0 545 comp1_t da = ALPHA_c (d); \
michael@0 546 comp1_t ida = ~da; \
michael@0 547 comp4_t result; \
michael@0 548 \
michael@0 549 combine_mask_value_ca (&s, &m); \
michael@0 550 \
michael@0 551 result = d; \
michael@0 552 UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (result, ~m, s, ida); \
michael@0 553 \
michael@0 554 result += \
michael@0 555 (DIV_ONE_UNc (ALPHA_c (m) * (comp4_t)da) << A_SHIFT) + \
michael@0 556 (blend_ ## name (RED_c (d), da, RED_c (s), RED_c (m)) << R_SHIFT) + \
michael@0 557 (blend_ ## name (GREEN_c (d), da, GREEN_c (s), GREEN_c (m)) << G_SHIFT) + \
michael@0 558 (blend_ ## name (BLUE_c (d), da, BLUE_c (s), BLUE_c (m))); \
michael@0 559 \
michael@0 560 *(dest + i) = result; \
michael@0 561 } \
michael@0 562 }
michael@0 563
michael@0 564 /*
michael@0 565 * Screen
michael@0 566 * B(Dca, ad, Sca, as) = Dca.sa + Sca.da - Dca.Sca
michael@0 567 */
michael@0 568 static inline comp4_t
michael@0 569 blend_screen (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
michael@0 570 {
michael@0 571 return DIV_ONE_UNc (sca * da + dca * sa - sca * dca);
michael@0 572 }
michael@0 573
michael@0 574 PDF_SEPARABLE_BLEND_MODE (screen)
michael@0 575
michael@0 576 /*
michael@0 577 * Overlay
michael@0 578 * B(Dca, Da, Sca, Sa) =
michael@0 579 * if 2.Dca < Da
michael@0 580 * 2.Sca.Dca
michael@0 581 * otherwise
michael@0 582 * Sa.Da - 2.(Da - Dca).(Sa - Sca)
michael@0 583 */
michael@0 584 static inline comp4_t
michael@0 585 blend_overlay (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
michael@0 586 {
michael@0 587 comp4_t rca;
michael@0 588
michael@0 589 if (2 * dca < da)
michael@0 590 rca = 2 * sca * dca;
michael@0 591 else
michael@0 592 rca = sa * da - 2 * (da - dca) * (sa - sca);
michael@0 593 return DIV_ONE_UNc (rca);
michael@0 594 }
michael@0 595
michael@0 596 PDF_SEPARABLE_BLEND_MODE (overlay)
michael@0 597
michael@0 598 /*
michael@0 599 * Darken
michael@0 600 * B(Dca, Da, Sca, Sa) = min (Sca.Da, Dca.Sa)
michael@0 601 */
michael@0 602 static inline comp4_t
michael@0 603 blend_darken (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
michael@0 604 {
michael@0 605 comp4_t s, d;
michael@0 606
michael@0 607 s = sca * da;
michael@0 608 d = dca * sa;
michael@0 609 return DIV_ONE_UNc (s > d ? d : s);
michael@0 610 }
michael@0 611
michael@0 612 PDF_SEPARABLE_BLEND_MODE (darken)
michael@0 613
michael@0 614 /*
michael@0 615 * Lighten
michael@0 616 * B(Dca, Da, Sca, Sa) = max (Sca.Da, Dca.Sa)
michael@0 617 */
michael@0 618 static inline comp4_t
michael@0 619 blend_lighten (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
michael@0 620 {
michael@0 621 comp4_t s, d;
michael@0 622
michael@0 623 s = sca * da;
michael@0 624 d = dca * sa;
michael@0 625 return DIV_ONE_UNc (s > d ? s : d);
michael@0 626 }
michael@0 627
michael@0 628 PDF_SEPARABLE_BLEND_MODE (lighten)
michael@0 629
michael@0 630 /*
michael@0 631 * Color dodge
michael@0 632 * B(Dca, Da, Sca, Sa) =
michael@0 633 * if Dca == 0
michael@0 634 * 0
michael@0 635 * if Sca == Sa
michael@0 636 * Sa.Da
michael@0 637 * otherwise
michael@0 638 * Sa.Da. min (1, Dca / Da / (1 - Sca/Sa))
michael@0 639 */
michael@0 640 static inline comp4_t
michael@0 641 blend_color_dodge (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
michael@0 642 {
michael@0 643 if (sca >= sa)
michael@0 644 {
michael@0 645 return dca == 0 ? 0 : DIV_ONE_UNc (sa * da);
michael@0 646 }
michael@0 647 else
michael@0 648 {
michael@0 649 comp4_t rca = dca * sa / (sa - sca);
michael@0 650 return DIV_ONE_UNc (sa * MIN (rca, da));
michael@0 651 }
michael@0 652 }
michael@0 653
michael@0 654 PDF_SEPARABLE_BLEND_MODE (color_dodge)
michael@0 655
michael@0 656 /*
michael@0 657 * Color burn
michael@0 658 * B(Dca, Da, Sca, Sa) =
michael@0 659 * if Dca == Da
michael@0 660 * Sa.Da
michael@0 661 * if Sca == 0
michael@0 662 * 0
michael@0 663 * otherwise
michael@0 664 * Sa.Da.(1 - min (1, (1 - Dca/Da).Sa / Sca))
michael@0 665 */
michael@0 666 static inline comp4_t
michael@0 667 blend_color_burn (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
michael@0 668 {
michael@0 669 if (sca == 0)
michael@0 670 {
michael@0 671 return dca < da ? 0 : DIV_ONE_UNc (sa * da);
michael@0 672 }
michael@0 673 else
michael@0 674 {
michael@0 675 comp4_t rca = (da - dca) * sa / sca;
michael@0 676 return DIV_ONE_UNc (sa * (MAX (rca, da) - rca));
michael@0 677 }
michael@0 678 }
michael@0 679
michael@0 680 PDF_SEPARABLE_BLEND_MODE (color_burn)
michael@0 681
michael@0 682 /*
michael@0 683 * Hard light
michael@0 684 * B(Dca, Da, Sca, Sa) =
michael@0 685 * if 2.Sca < Sa
michael@0 686 * 2.Sca.Dca
michael@0 687 * otherwise
michael@0 688 * Sa.Da - 2.(Da - Dca).(Sa - Sca)
michael@0 689 */
michael@0 690 static inline comp4_t
michael@0 691 blend_hard_light (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
michael@0 692 {
michael@0 693 if (2 * sca < sa)
michael@0 694 return DIV_ONE_UNc (2 * sca * dca);
michael@0 695 else
michael@0 696 return DIV_ONE_UNc (sa * da - 2 * (da - dca) * (sa - sca));
michael@0 697 }
michael@0 698
michael@0 699 PDF_SEPARABLE_BLEND_MODE (hard_light)
michael@0 700
michael@0 701 /*
michael@0 702 * Soft light
michael@0 703 * B(Dca, Da, Sca, Sa) =
michael@0 704 * if (2.Sca <= Sa)
michael@0 705 * Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa))
michael@0 706 * otherwise if Dca.4 <= Da
michael@0 707 * Dca.(Sa + (2.Sca - Sa).((16.Dca/Da - 12).Dca/Da + 3)
michael@0 708 * otherwise
michael@0 709 * (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa))
michael@0 710 */
michael@0 711 static inline comp4_t
michael@0 712 blend_soft_light (comp4_t dca_org,
michael@0 713 comp4_t da_org,
michael@0 714 comp4_t sca_org,
michael@0 715 comp4_t sa_org)
michael@0 716 {
michael@0 717 double dca = dca_org * (1.0 / MASK);
michael@0 718 double da = da_org * (1.0 / MASK);
michael@0 719 double sca = sca_org * (1.0 / MASK);
michael@0 720 double sa = sa_org * (1.0 / MASK);
michael@0 721 double rca;
michael@0 722
michael@0 723 if (2 * sca < sa)
michael@0 724 {
michael@0 725 if (da == 0)
michael@0 726 rca = dca * sa;
michael@0 727 else
michael@0 728 rca = dca * sa - dca * (da - dca) * (sa - 2 * sca) / da;
michael@0 729 }
michael@0 730 else if (da == 0)
michael@0 731 {
michael@0 732 rca = 0;
michael@0 733 }
michael@0 734 else if (4 * dca <= da)
michael@0 735 {
michael@0 736 rca = dca * sa +
michael@0 737 (2 * sca - sa) * dca * ((16 * dca / da - 12) * dca / da + 3);
michael@0 738 }
michael@0 739 else
michael@0 740 {
michael@0 741 rca = dca * sa + (sqrt (dca * da) - dca) * (2 * sca - sa);
michael@0 742 }
michael@0 743 return rca * MASK + 0.5;
michael@0 744 }
michael@0 745
michael@0 746 PDF_SEPARABLE_BLEND_MODE (soft_light)
michael@0 747
michael@0 748 /*
michael@0 749 * Difference
michael@0 750 * B(Dca, Da, Sca, Sa) = abs (Dca.Sa - Sca.Da)
michael@0 751 */
michael@0 752 static inline comp4_t
michael@0 753 blend_difference (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
michael@0 754 {
michael@0 755 comp4_t dcasa = dca * sa;
michael@0 756 comp4_t scada = sca * da;
michael@0 757
michael@0 758 if (scada < dcasa)
michael@0 759 return DIV_ONE_UNc (dcasa - scada);
michael@0 760 else
michael@0 761 return DIV_ONE_UNc (scada - dcasa);
michael@0 762 }
michael@0 763
michael@0 764 PDF_SEPARABLE_BLEND_MODE (difference)
michael@0 765
michael@0 766 /*
michael@0 767 * Exclusion
michael@0 768 * B(Dca, Da, Sca, Sa) = (Sca.Da + Dca.Sa - 2.Sca.Dca)
michael@0 769 */
michael@0 770
michael@0 771 /* This can be made faster by writing it directly and not using
michael@0 772 * PDF_SEPARABLE_BLEND_MODE, but that's a performance optimization */
michael@0 773
michael@0 774 static inline comp4_t
michael@0 775 blend_exclusion (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
michael@0 776 {
michael@0 777 return DIV_ONE_UNc (sca * da + dca * sa - 2 * dca * sca);
michael@0 778 }
michael@0 779
michael@0 780 PDF_SEPARABLE_BLEND_MODE (exclusion)
michael@0 781
michael@0 782 #undef PDF_SEPARABLE_BLEND_MODE
michael@0 783
michael@0 784 /*
michael@0 785 * PDF nonseperable blend modes are implemented using the following functions
michael@0 786 * to operate in Hsl space, with Cmax, Cmid, Cmin referring to the max, mid
michael@0 787 * and min value of the red, green and blue components.
michael@0 788 *
michael@0 789 * LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue
michael@0 790 *
michael@0 791 * clip_color (C):
michael@0 792 * l = LUM (C)
michael@0 793 * min = Cmin
michael@0 794 * max = Cmax
michael@0 795 * if n < 0.0
michael@0 796 * C = l + ( ( ( C – l ) × l ) ⁄ ( l – min ) )
michael@0 797 * if x > 1.0
michael@0 798 * C = l + ( ( ( C – l ) × ( 1 – l ) ) ⁄ ( max – l ) )
michael@0 799 * return C
michael@0 800 *
michael@0 801 * set_lum (C, l):
michael@0 802 * d = l – LUM (C)
michael@0 803 * C += d
michael@0 804 * return clip_color (C)
michael@0 805 *
michael@0 806 * SAT (C) = CH_MAX (C) - CH_MIN (C)
michael@0 807 *
michael@0 808 * set_sat (C, s):
michael@0 809 * if Cmax > Cmin
michael@0 810 * Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
michael@0 811 * Cmax = s
michael@0 812 * else
michael@0 813 * Cmid = Cmax = 0.0
michael@0 814 * Cmin = 0.0
michael@0 815 * return C
michael@0 816 */
michael@0 817
michael@0 818 /* For premultiplied colors, we need to know what happens when C is
michael@0 819 * multiplied by a real number. LUM and SAT are linear:
michael@0 820 *
michael@0 821 * LUM (r × C) = r × LUM (C) SAT (r * C) = r * SAT (C)
michael@0 822 *
michael@0 823 * If we extend clip_color with an extra argument a and change
michael@0 824 *
michael@0 825 * if x >= 1.0
michael@0 826 *
michael@0 827 * into
michael@0 828 *
michael@0 829 * if x >= a
michael@0 830 *
michael@0 831 * then clip_color is also linear:
michael@0 832 *
michael@0 833 * r * clip_color (C, a) = clip_color (r_c, ra);
michael@0 834 *
michael@0 835 * for positive r.
michael@0 836 *
michael@0 837 * Similarly, we can extend set_lum with an extra argument that is just passed
michael@0 838 * on to clip_color:
michael@0 839 *
michael@0 840 * r * set_lum ( C, l, a)
michael@0 841 *
michael@0 842 * = r × clip_color ( C + l - LUM (C), a)
michael@0 843 *
michael@0 844 * = clip_color ( r * C + r × l - r * LUM (C), r * a)
michael@0 845 *
michael@0 846 * = set_lum ( r * C, r * l, r * a)
michael@0 847 *
michael@0 848 * Finally, set_sat:
michael@0 849 *
michael@0 850 * r * set_sat (C, s) = set_sat (x * C, r * s)
michael@0 851 *
michael@0 852 * The above holds for all non-zero x, because the x'es in the fraction for
michael@0 853 * C_mid cancel out. Specifically, it holds for x = r:
michael@0 854 *
michael@0 855 * r * set_sat (C, s) = set_sat (r_c, rs)
michael@0 856 *
michael@0 857 */
michael@0 858
michael@0 859 /* So, for the non-separable PDF blend modes, we have (using s, d for
michael@0 860 * non-premultiplied colors, and S, D for premultiplied:
michael@0 861 *
michael@0 862 * Color:
michael@0 863 *
michael@0 864 * a_s * a_d * B(s, d)
michael@0 865 * = a_s * a_d * set_lum (S/a_s, LUM (D/a_d), 1)
michael@0 866 * = set_lum (S * a_d, a_s * LUM (D), a_s * a_d)
michael@0 867 *
michael@0 868 *
michael@0 869 * Luminosity:
michael@0 870 *
michael@0 871 * a_s * a_d * B(s, d)
michael@0 872 * = a_s * a_d * set_lum (D/a_d, LUM(S/a_s), 1)
michael@0 873 * = set_lum (a_s * D, a_d * LUM(S), a_s * a_d)
michael@0 874 *
michael@0 875 *
michael@0 876 * Saturation:
michael@0 877 *
michael@0 878 * a_s * a_d * B(s, d)
michael@0 879 * = a_s * a_d * set_lum (set_sat (D/a_d, SAT (S/a_s)), LUM (D/a_d), 1)
michael@0 880 * = set_lum (a_s * a_d * set_sat (D/a_d, SAT (S/a_s)),
michael@0 881 * a_s * LUM (D), a_s * a_d)
michael@0 882 * = set_lum (set_sat (a_s * D, a_d * SAT (S), a_s * LUM (D), a_s * a_d))
michael@0 883 *
michael@0 884 * Hue:
michael@0 885 *
michael@0 886 * a_s * a_d * B(s, d)
michael@0 887 * = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1)
michael@0 888 * = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d)
michael@0 889 *
michael@0 890 */
michael@0 891
michael@0 892 #define CH_MIN(c) (c[0] < c[1] ? (c[0] < c[2] ? c[0] : c[2]) : (c[1] < c[2] ? c[1] : c[2]))
michael@0 893 #define CH_MAX(c) (c[0] > c[1] ? (c[0] > c[2] ? c[0] : c[2]) : (c[1] > c[2] ? c[1] : c[2]))
michael@0 894 #define LUM(c) ((c[0] * 30 + c[1] * 59 + c[2] * 11) / 100)
michael@0 895 #define SAT(c) (CH_MAX (c) - CH_MIN (c))
michael@0 896
michael@0 897 #define PDF_NON_SEPARABLE_BLEND_MODE(name) \
michael@0 898 static void \
michael@0 899 combine_ ## name ## _u (pixman_implementation_t *imp, \
michael@0 900 pixman_op_t op, \
michael@0 901 comp4_t *dest, \
michael@0 902 const comp4_t *src, \
michael@0 903 const comp4_t *mask, \
michael@0 904 int width) \
michael@0 905 { \
michael@0 906 int i; \
michael@0 907 for (i = 0; i < width; ++i) \
michael@0 908 { \
michael@0 909 comp4_t s = combine_mask (src, mask, i); \
michael@0 910 comp4_t d = *(dest + i); \
michael@0 911 comp1_t sa = ALPHA_c (s); \
michael@0 912 comp1_t isa = ~sa; \
michael@0 913 comp1_t da = ALPHA_c (d); \
michael@0 914 comp1_t ida = ~da; \
michael@0 915 comp4_t result; \
michael@0 916 comp4_t sc[3], dc[3], c[3]; \
michael@0 917 \
michael@0 918 result = d; \
michael@0 919 UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (result, isa, s, ida); \
michael@0 920 dc[0] = RED_c (d); \
michael@0 921 sc[0] = RED_c (s); \
michael@0 922 dc[1] = GREEN_c (d); \
michael@0 923 sc[1] = GREEN_c (s); \
michael@0 924 dc[2] = BLUE_c (d); \
michael@0 925 sc[2] = BLUE_c (s); \
michael@0 926 blend_ ## name (c, dc, da, sc, sa); \
michael@0 927 \
michael@0 928 *(dest + i) = result + \
michael@0 929 (DIV_ONE_UNc (sa * (comp4_t)da) << A_SHIFT) + \
michael@0 930 (DIV_ONE_UNc (c[0]) << R_SHIFT) + \
michael@0 931 (DIV_ONE_UNc (c[1]) << G_SHIFT) + \
michael@0 932 (DIV_ONE_UNc (c[2])); \
michael@0 933 } \
michael@0 934 }
michael@0 935
michael@0 936 static void
michael@0 937 set_lum (comp4_t dest[3], comp4_t src[3], comp4_t sa, comp4_t lum)
michael@0 938 {
michael@0 939 double a, l, min, max;
michael@0 940 double tmp[3];
michael@0 941
michael@0 942 a = sa * (1.0 / MASK);
michael@0 943
michael@0 944 l = lum * (1.0 / MASK);
michael@0 945 tmp[0] = src[0] * (1.0 / MASK);
michael@0 946 tmp[1] = src[1] * (1.0 / MASK);
michael@0 947 tmp[2] = src[2] * (1.0 / MASK);
michael@0 948
michael@0 949 l = l - LUM (tmp);
michael@0 950 tmp[0] += l;
michael@0 951 tmp[1] += l;
michael@0 952 tmp[2] += l;
michael@0 953
michael@0 954 /* clip_color */
michael@0 955 l = LUM (tmp);
michael@0 956 min = CH_MIN (tmp);
michael@0 957 max = CH_MAX (tmp);
michael@0 958
michael@0 959 if (min < 0)
michael@0 960 {
michael@0 961 if (l - min == 0.0)
michael@0 962 {
michael@0 963 tmp[0] = 0;
michael@0 964 tmp[1] = 0;
michael@0 965 tmp[2] = 0;
michael@0 966 }
michael@0 967 else
michael@0 968 {
michael@0 969 tmp[0] = l + (tmp[0] - l) * l / (l - min);
michael@0 970 tmp[1] = l + (tmp[1] - l) * l / (l - min);
michael@0 971 tmp[2] = l + (tmp[2] - l) * l / (l - min);
michael@0 972 }
michael@0 973 }
michael@0 974 if (max > a)
michael@0 975 {
michael@0 976 if (max - l == 0.0)
michael@0 977 {
michael@0 978 tmp[0] = a;
michael@0 979 tmp[1] = a;
michael@0 980 tmp[2] = a;
michael@0 981 }
michael@0 982 else
michael@0 983 {
michael@0 984 tmp[0] = l + (tmp[0] - l) * (a - l) / (max - l);
michael@0 985 tmp[1] = l + (tmp[1] - l) * (a - l) / (max - l);
michael@0 986 tmp[2] = l + (tmp[2] - l) * (a - l) / (max - l);
michael@0 987 }
michael@0 988 }
michael@0 989
michael@0 990 dest[0] = tmp[0] * MASK + 0.5;
michael@0 991 dest[1] = tmp[1] * MASK + 0.5;
michael@0 992 dest[2] = tmp[2] * MASK + 0.5;
michael@0 993 }
michael@0 994
michael@0 995 static void
michael@0 996 set_sat (comp4_t dest[3], comp4_t src[3], comp4_t sat)
michael@0 997 {
michael@0 998 int id[3];
michael@0 999 comp4_t min, max;
michael@0 1000
michael@0 1001 if (src[0] > src[1])
michael@0 1002 {
michael@0 1003 if (src[0] > src[2])
michael@0 1004 {
michael@0 1005 id[0] = 0;
michael@0 1006 if (src[1] > src[2])
michael@0 1007 {
michael@0 1008 id[1] = 1;
michael@0 1009 id[2] = 2;
michael@0 1010 }
michael@0 1011 else
michael@0 1012 {
michael@0 1013 id[1] = 2;
michael@0 1014 id[2] = 1;
michael@0 1015 }
michael@0 1016 }
michael@0 1017 else
michael@0 1018 {
michael@0 1019 id[0] = 2;
michael@0 1020 id[1] = 0;
michael@0 1021 id[2] = 1;
michael@0 1022 }
michael@0 1023 }
michael@0 1024 else
michael@0 1025 {
michael@0 1026 if (src[0] > src[2])
michael@0 1027 {
michael@0 1028 id[0] = 1;
michael@0 1029 id[1] = 0;
michael@0 1030 id[2] = 2;
michael@0 1031 }
michael@0 1032 else
michael@0 1033 {
michael@0 1034 id[2] = 0;
michael@0 1035 if (src[1] > src[2])
michael@0 1036 {
michael@0 1037 id[0] = 1;
michael@0 1038 id[1] = 2;
michael@0 1039 }
michael@0 1040 else
michael@0 1041 {
michael@0 1042 id[0] = 2;
michael@0 1043 id[1] = 1;
michael@0 1044 }
michael@0 1045 }
michael@0 1046 }
michael@0 1047
michael@0 1048 max = dest[id[0]];
michael@0 1049 min = dest[id[2]];
michael@0 1050 if (max > min)
michael@0 1051 {
michael@0 1052 dest[id[1]] = (dest[id[1]] - min) * sat / (max - min);
michael@0 1053 dest[id[0]] = sat;
michael@0 1054 dest[id[2]] = 0;
michael@0 1055 }
michael@0 1056 else
michael@0 1057 {
michael@0 1058 dest[0] = dest[1] = dest[2] = 0;
michael@0 1059 }
michael@0 1060 }
michael@0 1061
michael@0 1062 /*
michael@0 1063 * Hue:
michael@0 1064 * B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb))
michael@0 1065 */
michael@0 1066 static inline void
michael@0 1067 blend_hsl_hue (comp4_t c[3],
michael@0 1068 comp4_t dc[3],
michael@0 1069 comp4_t da,
michael@0 1070 comp4_t sc[3],
michael@0 1071 comp4_t sa)
michael@0 1072 {
michael@0 1073 c[0] = sc[0] * da;
michael@0 1074 c[1] = sc[1] * da;
michael@0 1075 c[2] = sc[2] * da;
michael@0 1076 set_sat (c, c, SAT (dc) * sa);
michael@0 1077 set_lum (c, c, sa * da, LUM (dc) * sa);
michael@0 1078 }
michael@0 1079
michael@0 1080 PDF_NON_SEPARABLE_BLEND_MODE (hsl_hue)
michael@0 1081
michael@0 1082 /*
michael@0 1083 * Saturation:
michael@0 1084 * B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb))
michael@0 1085 */
michael@0 1086 static inline void
michael@0 1087 blend_hsl_saturation (comp4_t c[3],
michael@0 1088 comp4_t dc[3],
michael@0 1089 comp4_t da,
michael@0 1090 comp4_t sc[3],
michael@0 1091 comp4_t sa)
michael@0 1092 {
michael@0 1093 c[0] = dc[0] * sa;
michael@0 1094 c[1] = dc[1] * sa;
michael@0 1095 c[2] = dc[2] * sa;
michael@0 1096 set_sat (c, c, SAT (sc) * da);
michael@0 1097 set_lum (c, c, sa * da, LUM (dc) * sa);
michael@0 1098 }
michael@0 1099
michael@0 1100 PDF_NON_SEPARABLE_BLEND_MODE (hsl_saturation)
michael@0 1101
michael@0 1102 /*
michael@0 1103 * Color:
michael@0 1104 * B(Cb, Cs) = set_lum (Cs, LUM (Cb))
michael@0 1105 */
michael@0 1106 static inline void
michael@0 1107 blend_hsl_color (comp4_t c[3],
michael@0 1108 comp4_t dc[3],
michael@0 1109 comp4_t da,
michael@0 1110 comp4_t sc[3],
michael@0 1111 comp4_t sa)
michael@0 1112 {
michael@0 1113 c[0] = sc[0] * da;
michael@0 1114 c[1] = sc[1] * da;
michael@0 1115 c[2] = sc[2] * da;
michael@0 1116 set_lum (c, c, sa * da, LUM (dc) * sa);
michael@0 1117 }
michael@0 1118
michael@0 1119 PDF_NON_SEPARABLE_BLEND_MODE (hsl_color)
michael@0 1120
michael@0 1121 /*
michael@0 1122 * Luminosity:
michael@0 1123 * B(Cb, Cs) = set_lum (Cb, LUM (Cs))
michael@0 1124 */
michael@0 1125 static inline void
michael@0 1126 blend_hsl_luminosity (comp4_t c[3],
michael@0 1127 comp4_t dc[3],
michael@0 1128 comp4_t da,
michael@0 1129 comp4_t sc[3],
michael@0 1130 comp4_t sa)
michael@0 1131 {
michael@0 1132 c[0] = dc[0] * sa;
michael@0 1133 c[1] = dc[1] * sa;
michael@0 1134 c[2] = dc[2] * sa;
michael@0 1135 set_lum (c, c, sa * da, LUM (sc) * da);
michael@0 1136 }
michael@0 1137
michael@0 1138 PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity)
michael@0 1139
michael@0 1140 #undef SAT
michael@0 1141 #undef LUM
michael@0 1142 #undef CH_MAX
michael@0 1143 #undef CH_MIN
michael@0 1144 #undef PDF_NON_SEPARABLE_BLEND_MODE
michael@0 1145
michael@0 1146 /* All of the disjoint/conjoint composing functions
michael@0 1147 *
michael@0 1148 * The four entries in the first column indicate what source contributions
michael@0 1149 * come from each of the four areas of the picture -- areas covered by neither
michael@0 1150 * A nor B, areas covered only by A, areas covered only by B and finally
michael@0 1151 * areas covered by both A and B.
michael@0 1152 *
michael@0 1153 * Disjoint Conjoint
michael@0 1154 * Fa Fb Fa Fb
michael@0 1155 * (0,0,0,0) 0 0 0 0
michael@0 1156 * (0,A,0,A) 1 0 1 0
michael@0 1157 * (0,0,B,B) 0 1 0 1
michael@0 1158 * (0,A,B,A) 1 min((1-a)/b,1) 1 max(1-a/b,0)
michael@0 1159 * (0,A,B,B) min((1-b)/a,1) 1 max(1-b/a,0) 1
michael@0 1160 * (0,0,0,A) max(1-(1-b)/a,0) 0 min(1,b/a) 0
michael@0 1161 * (0,0,0,B) 0 max(1-(1-a)/b,0) 0 min(a/b,1)
michael@0 1162 * (0,A,0,0) min(1,(1-b)/a) 0 max(1-b/a,0) 0
michael@0 1163 * (0,0,B,0) 0 min(1,(1-a)/b) 0 max(1-a/b,0)
michael@0 1164 * (0,0,B,A) max(1-(1-b)/a,0) min(1,(1-a)/b) min(1,b/a) max(1-a/b,0)
michael@0 1165 * (0,A,0,B) min(1,(1-b)/a) max(1-(1-a)/b,0) max(1-b/a,0) min(1,a/b)
michael@0 1166 * (0,A,B,0) min(1,(1-b)/a) min(1,(1-a)/b) max(1-b/a,0) max(1-a/b,0)
michael@0 1167 *
michael@0 1168 * See http://marc.info/?l=xfree-render&m=99792000027857&w=2 for more
michael@0 1169 * information about these operators.
michael@0 1170 */
michael@0 1171
michael@0 1172 #define COMBINE_A_OUT 1
michael@0 1173 #define COMBINE_A_IN 2
michael@0 1174 #define COMBINE_B_OUT 4
michael@0 1175 #define COMBINE_B_IN 8
michael@0 1176
michael@0 1177 #define COMBINE_CLEAR 0
michael@0 1178 #define COMBINE_A (COMBINE_A_OUT | COMBINE_A_IN)
michael@0 1179 #define COMBINE_B (COMBINE_B_OUT | COMBINE_B_IN)
michael@0 1180 #define COMBINE_A_OVER (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_A_IN)
michael@0 1181 #define COMBINE_B_OVER (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_B_IN)
michael@0 1182 #define COMBINE_A_ATOP (COMBINE_B_OUT | COMBINE_A_IN)
michael@0 1183 #define COMBINE_B_ATOP (COMBINE_A_OUT | COMBINE_B_IN)
michael@0 1184 #define COMBINE_XOR (COMBINE_A_OUT | COMBINE_B_OUT)
michael@0 1185
michael@0 1186 /* portion covered by a but not b */
michael@0 1187 static comp1_t
michael@0 1188 combine_disjoint_out_part (comp1_t a, comp1_t b)
michael@0 1189 {
michael@0 1190 /* min (1, (1-b) / a) */
michael@0 1191
michael@0 1192 b = ~b; /* 1 - b */
michael@0 1193 if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */
michael@0 1194 return MASK; /* 1 */
michael@0 1195 return DIV_UNc (b, a); /* (1-b) / a */
michael@0 1196 }
michael@0 1197
michael@0 1198 /* portion covered by both a and b */
michael@0 1199 static comp1_t
michael@0 1200 combine_disjoint_in_part (comp1_t a, comp1_t b)
michael@0 1201 {
michael@0 1202 /* max (1-(1-b)/a,0) */
michael@0 1203 /* = - min ((1-b)/a - 1, 0) */
michael@0 1204 /* = 1 - min (1, (1-b)/a) */
michael@0 1205
michael@0 1206 b = ~b; /* 1 - b */
michael@0 1207 if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */
michael@0 1208 return 0; /* 1 - 1 */
michael@0 1209 return ~DIV_UNc(b, a); /* 1 - (1-b) / a */
michael@0 1210 }
michael@0 1211
michael@0 1212 /* portion covered by a but not b */
michael@0 1213 static comp1_t
michael@0 1214 combine_conjoint_out_part (comp1_t a, comp1_t b)
michael@0 1215 {
michael@0 1216 /* max (1-b/a,0) */
michael@0 1217 /* = 1-min(b/a,1) */
michael@0 1218
michael@0 1219 /* min (1, (1-b) / a) */
michael@0 1220
michael@0 1221 if (b >= a) /* b >= a -> b/a >= 1 */
michael@0 1222 return 0x00; /* 0 */
michael@0 1223 return ~DIV_UNc(b, a); /* 1 - b/a */
michael@0 1224 }
michael@0 1225
michael@0 1226 /* portion covered by both a and b */
michael@0 1227 static comp1_t
michael@0 1228 combine_conjoint_in_part (comp1_t a, comp1_t b)
michael@0 1229 {
michael@0 1230 /* min (1,b/a) */
michael@0 1231
michael@0 1232 if (b >= a) /* b >= a -> b/a >= 1 */
michael@0 1233 return MASK; /* 1 */
michael@0 1234 return DIV_UNc (b, a); /* b/a */
michael@0 1235 }
michael@0 1236
michael@0 1237 #define GET_COMP(v, i) ((comp2_t) (comp1_t) ((v) >> i))
michael@0 1238
michael@0 1239 #define ADD(x, y, i, t) \
michael@0 1240 ((t) = GET_COMP (x, i) + GET_COMP (y, i), \
michael@0 1241 (comp4_t) ((comp1_t) ((t) | (0 - ((t) >> G_SHIFT)))) << (i))
michael@0 1242
michael@0 1243 #define GENERIC(x, y, i, ax, ay, t, u, v) \
michael@0 1244 ((t) = (MUL_UNc (GET_COMP (y, i), ay, (u)) + \
michael@0 1245 MUL_UNc (GET_COMP (x, i), ax, (v))), \
michael@0 1246 (comp4_t) ((comp1_t) ((t) | \
michael@0 1247 (0 - ((t) >> G_SHIFT)))) << (i))
michael@0 1248
michael@0 1249 static void
michael@0 1250 combine_disjoint_general_u (comp4_t * dest,
michael@0 1251 const comp4_t *src,
michael@0 1252 const comp4_t *mask,
michael@0 1253 int width,
michael@0 1254 comp1_t combine)
michael@0 1255 {
michael@0 1256 int i;
michael@0 1257
michael@0 1258 for (i = 0; i < width; ++i)
michael@0 1259 {
michael@0 1260 comp4_t s = combine_mask (src, mask, i);
michael@0 1261 comp4_t d = *(dest + i);
michael@0 1262 comp4_t m, n, o, p;
michael@0 1263 comp2_t Fa, Fb, t, u, v;
michael@0 1264 comp1_t sa = s >> A_SHIFT;
michael@0 1265 comp1_t da = d >> A_SHIFT;
michael@0 1266
michael@0 1267 switch (combine & COMBINE_A)
michael@0 1268 {
michael@0 1269 default:
michael@0 1270 Fa = 0;
michael@0 1271 break;
michael@0 1272
michael@0 1273 case COMBINE_A_OUT:
michael@0 1274 Fa = combine_disjoint_out_part (sa, da);
michael@0 1275 break;
michael@0 1276
michael@0 1277 case COMBINE_A_IN:
michael@0 1278 Fa = combine_disjoint_in_part (sa, da);
michael@0 1279 break;
michael@0 1280
michael@0 1281 case COMBINE_A:
michael@0 1282 Fa = MASK;
michael@0 1283 break;
michael@0 1284 }
michael@0 1285
michael@0 1286 switch (combine & COMBINE_B)
michael@0 1287 {
michael@0 1288 default:
michael@0 1289 Fb = 0;
michael@0 1290 break;
michael@0 1291
michael@0 1292 case COMBINE_B_OUT:
michael@0 1293 Fb = combine_disjoint_out_part (da, sa);
michael@0 1294 break;
michael@0 1295
michael@0 1296 case COMBINE_B_IN:
michael@0 1297 Fb = combine_disjoint_in_part (da, sa);
michael@0 1298 break;
michael@0 1299
michael@0 1300 case COMBINE_B:
michael@0 1301 Fb = MASK;
michael@0 1302 break;
michael@0 1303 }
michael@0 1304 m = GENERIC (s, d, 0, Fa, Fb, t, u, v);
michael@0 1305 n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v);
michael@0 1306 o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v);
michael@0 1307 p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v);
michael@0 1308 s = m | n | o | p;
michael@0 1309 *(dest + i) = s;
michael@0 1310 }
michael@0 1311 }
michael@0 1312
michael@0 1313 static void
michael@0 1314 combine_disjoint_over_u (pixman_implementation_t *imp,
michael@0 1315 pixman_op_t op,
michael@0 1316 comp4_t * dest,
michael@0 1317 const comp4_t * src,
michael@0 1318 const comp4_t * mask,
michael@0 1319 int width)
michael@0 1320 {
michael@0 1321 int i;
michael@0 1322
michael@0 1323 for (i = 0; i < width; ++i)
michael@0 1324 {
michael@0 1325 comp4_t s = combine_mask (src, mask, i);
michael@0 1326 comp2_t a = s >> A_SHIFT;
michael@0 1327
michael@0 1328 if (s != 0x00)
michael@0 1329 {
michael@0 1330 comp4_t d = *(dest + i);
michael@0 1331 a = combine_disjoint_out_part (d >> A_SHIFT, a);
michael@0 1332 UNcx4_MUL_UNc_ADD_UNcx4 (d, a, s);
michael@0 1333
michael@0 1334 *(dest + i) = d;
michael@0 1335 }
michael@0 1336 }
michael@0 1337 }
michael@0 1338
michael@0 1339 static void
michael@0 1340 combine_disjoint_in_u (pixman_implementation_t *imp,
michael@0 1341 pixman_op_t op,
michael@0 1342 comp4_t * dest,
michael@0 1343 const comp4_t * src,
michael@0 1344 const comp4_t * mask,
michael@0 1345 int width)
michael@0 1346 {
michael@0 1347 combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_IN);
michael@0 1348 }
michael@0 1349
michael@0 1350 static void
michael@0 1351 combine_disjoint_in_reverse_u (pixman_implementation_t *imp,
michael@0 1352 pixman_op_t op,
michael@0 1353 comp4_t * dest,
michael@0 1354 const comp4_t * src,
michael@0 1355 const comp4_t * mask,
michael@0 1356 int width)
michael@0 1357 {
michael@0 1358 combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_IN);
michael@0 1359 }
michael@0 1360
michael@0 1361 static void
michael@0 1362 combine_disjoint_out_u (pixman_implementation_t *imp,
michael@0 1363 pixman_op_t op,
michael@0 1364 comp4_t * dest,
michael@0 1365 const comp4_t * src,
michael@0 1366 const comp4_t * mask,
michael@0 1367 int width)
michael@0 1368 {
michael@0 1369 combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_OUT);
michael@0 1370 }
michael@0 1371
michael@0 1372 static void
michael@0 1373 combine_disjoint_out_reverse_u (pixman_implementation_t *imp,
michael@0 1374 pixman_op_t op,
michael@0 1375 comp4_t * dest,
michael@0 1376 const comp4_t * src,
michael@0 1377 const comp4_t * mask,
michael@0 1378 int width)
michael@0 1379 {
michael@0 1380 combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_OUT);
michael@0 1381 }
michael@0 1382
michael@0 1383 static void
michael@0 1384 combine_disjoint_atop_u (pixman_implementation_t *imp,
michael@0 1385 pixman_op_t op,
michael@0 1386 comp4_t * dest,
michael@0 1387 const comp4_t * src,
michael@0 1388 const comp4_t * mask,
michael@0 1389 int width)
michael@0 1390 {
michael@0 1391 combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP);
michael@0 1392 }
michael@0 1393
michael@0 1394 static void
michael@0 1395 combine_disjoint_atop_reverse_u (pixman_implementation_t *imp,
michael@0 1396 pixman_op_t op,
michael@0 1397 comp4_t * dest,
michael@0 1398 const comp4_t * src,
michael@0 1399 const comp4_t * mask,
michael@0 1400 int width)
michael@0 1401 {
michael@0 1402 combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP);
michael@0 1403 }
michael@0 1404
michael@0 1405 static void
michael@0 1406 combine_disjoint_xor_u (pixman_implementation_t *imp,
michael@0 1407 pixman_op_t op,
michael@0 1408 comp4_t * dest,
michael@0 1409 const comp4_t * src,
michael@0 1410 const comp4_t * mask,
michael@0 1411 int width)
michael@0 1412 {
michael@0 1413 combine_disjoint_general_u (dest, src, mask, width, COMBINE_XOR);
michael@0 1414 }
michael@0 1415
michael@0 1416 static void
michael@0 1417 combine_conjoint_general_u (comp4_t * dest,
michael@0 1418 const comp4_t *src,
michael@0 1419 const comp4_t *mask,
michael@0 1420 int width,
michael@0 1421 comp1_t combine)
michael@0 1422 {
michael@0 1423 int i;
michael@0 1424
michael@0 1425 for (i = 0; i < width; ++i)
michael@0 1426 {
michael@0 1427 comp4_t s = combine_mask (src, mask, i);
michael@0 1428 comp4_t d = *(dest + i);
michael@0 1429 comp4_t m, n, o, p;
michael@0 1430 comp2_t Fa, Fb, t, u, v;
michael@0 1431 comp1_t sa = s >> A_SHIFT;
michael@0 1432 comp1_t da = d >> A_SHIFT;
michael@0 1433
michael@0 1434 switch (combine & COMBINE_A)
michael@0 1435 {
michael@0 1436 default:
michael@0 1437 Fa = 0;
michael@0 1438 break;
michael@0 1439
michael@0 1440 case COMBINE_A_OUT:
michael@0 1441 Fa = combine_conjoint_out_part (sa, da);
michael@0 1442 break;
michael@0 1443
michael@0 1444 case COMBINE_A_IN:
michael@0 1445 Fa = combine_conjoint_in_part (sa, da);
michael@0 1446 break;
michael@0 1447
michael@0 1448 case COMBINE_A:
michael@0 1449 Fa = MASK;
michael@0 1450 break;
michael@0 1451 }
michael@0 1452
michael@0 1453 switch (combine & COMBINE_B)
michael@0 1454 {
michael@0 1455 default:
michael@0 1456 Fb = 0;
michael@0 1457 break;
michael@0 1458
michael@0 1459 case COMBINE_B_OUT:
michael@0 1460 Fb = combine_conjoint_out_part (da, sa);
michael@0 1461 break;
michael@0 1462
michael@0 1463 case COMBINE_B_IN:
michael@0 1464 Fb = combine_conjoint_in_part (da, sa);
michael@0 1465 break;
michael@0 1466
michael@0 1467 case COMBINE_B:
michael@0 1468 Fb = MASK;
michael@0 1469 break;
michael@0 1470 }
michael@0 1471
michael@0 1472 m = GENERIC (s, d, 0, Fa, Fb, t, u, v);
michael@0 1473 n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v);
michael@0 1474 o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v);
michael@0 1475 p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v);
michael@0 1476
michael@0 1477 s = m | n | o | p;
michael@0 1478
michael@0 1479 *(dest + i) = s;
michael@0 1480 }
michael@0 1481 }
michael@0 1482
michael@0 1483 static void
michael@0 1484 combine_conjoint_over_u (pixman_implementation_t *imp,
michael@0 1485 pixman_op_t op,
michael@0 1486 comp4_t * dest,
michael@0 1487 const comp4_t * src,
michael@0 1488 const comp4_t * mask,
michael@0 1489 int width)
michael@0 1490 {
michael@0 1491 combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OVER);
michael@0 1492 }
michael@0 1493
michael@0 1494 static void
michael@0 1495 combine_conjoint_over_reverse_u (pixman_implementation_t *imp,
michael@0 1496 pixman_op_t op,
michael@0 1497 comp4_t * dest,
michael@0 1498 const comp4_t * src,
michael@0 1499 const comp4_t * mask,
michael@0 1500 int width)
michael@0 1501 {
michael@0 1502 combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OVER);
michael@0 1503 }
michael@0 1504
michael@0 1505 static void
michael@0 1506 combine_conjoint_in_u (pixman_implementation_t *imp,
michael@0 1507 pixman_op_t op,
michael@0 1508 comp4_t * dest,
michael@0 1509 const comp4_t * src,
michael@0 1510 const comp4_t * mask,
michael@0 1511 int width)
michael@0 1512 {
michael@0 1513 combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_IN);
michael@0 1514 }
michael@0 1515
michael@0 1516 static void
michael@0 1517 combine_conjoint_in_reverse_u (pixman_implementation_t *imp,
michael@0 1518 pixman_op_t op,
michael@0 1519 comp4_t * dest,
michael@0 1520 const comp4_t * src,
michael@0 1521 const comp4_t * mask,
michael@0 1522 int width)
michael@0 1523 {
michael@0 1524 combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_IN);
michael@0 1525 }
michael@0 1526
michael@0 1527 static void
michael@0 1528 combine_conjoint_out_u (pixman_implementation_t *imp,
michael@0 1529 pixman_op_t op,
michael@0 1530 comp4_t * dest,
michael@0 1531 const comp4_t * src,
michael@0 1532 const comp4_t * mask,
michael@0 1533 int width)
michael@0 1534 {
michael@0 1535 combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OUT);
michael@0 1536 }
michael@0 1537
michael@0 1538 static void
michael@0 1539 combine_conjoint_out_reverse_u (pixman_implementation_t *imp,
michael@0 1540 pixman_op_t op,
michael@0 1541 comp4_t * dest,
michael@0 1542 const comp4_t * src,
michael@0 1543 const comp4_t * mask,
michael@0 1544 int width)
michael@0 1545 {
michael@0 1546 combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OUT);
michael@0 1547 }
michael@0 1548
michael@0 1549 static void
michael@0 1550 combine_conjoint_atop_u (pixman_implementation_t *imp,
michael@0 1551 pixman_op_t op,
michael@0 1552 comp4_t * dest,
michael@0 1553 const comp4_t * src,
michael@0 1554 const comp4_t * mask,
michael@0 1555 int width)
michael@0 1556 {
michael@0 1557 combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP);
michael@0 1558 }
michael@0 1559
michael@0 1560 static void
michael@0 1561 combine_conjoint_atop_reverse_u (pixman_implementation_t *imp,
michael@0 1562 pixman_op_t op,
michael@0 1563 comp4_t * dest,
michael@0 1564 const comp4_t * src,
michael@0 1565 const comp4_t * mask,
michael@0 1566 int width)
michael@0 1567 {
michael@0 1568 combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP);
michael@0 1569 }
michael@0 1570
michael@0 1571 static void
michael@0 1572 combine_conjoint_xor_u (pixman_implementation_t *imp,
michael@0 1573 pixman_op_t op,
michael@0 1574 comp4_t * dest,
michael@0 1575 const comp4_t * src,
michael@0 1576 const comp4_t * mask,
michael@0 1577 int width)
michael@0 1578 {
michael@0 1579 combine_conjoint_general_u (dest, src, mask, width, COMBINE_XOR);
michael@0 1580 }
michael@0 1581
michael@0 1582 /************************************************************************/
michael@0 1583 /*********************** Per Channel functions **************************/
michael@0 1584 /************************************************************************/
michael@0 1585
michael@0 1586 static void
michael@0 1587 combine_clear_ca (pixman_implementation_t *imp,
michael@0 1588 pixman_op_t op,
michael@0 1589 comp4_t * dest,
michael@0 1590 const comp4_t * src,
michael@0 1591 const comp4_t * mask,
michael@0 1592 int width)
michael@0 1593 {
michael@0 1594 memset (dest, 0, width * sizeof(comp4_t));
michael@0 1595 }
michael@0 1596
michael@0 1597 static void
michael@0 1598 combine_src_ca (pixman_implementation_t *imp,
michael@0 1599 pixman_op_t op,
michael@0 1600 comp4_t * dest,
michael@0 1601 const comp4_t * src,
michael@0 1602 const comp4_t * mask,
michael@0 1603 int width)
michael@0 1604 {
michael@0 1605 int i;
michael@0 1606
michael@0 1607 for (i = 0; i < width; ++i)
michael@0 1608 {
michael@0 1609 comp4_t s = *(src + i);
michael@0 1610 comp4_t m = *(mask + i);
michael@0 1611
michael@0 1612 combine_mask_value_ca (&s, &m);
michael@0 1613
michael@0 1614 *(dest + i) = s;
michael@0 1615 }
michael@0 1616 }
michael@0 1617
michael@0 1618 static void
michael@0 1619 combine_over_ca (pixman_implementation_t *imp,
michael@0 1620 pixman_op_t op,
michael@0 1621 comp4_t * dest,
michael@0 1622 const comp4_t * src,
michael@0 1623 const comp4_t * mask,
michael@0 1624 int width)
michael@0 1625 {
michael@0 1626 int i;
michael@0 1627
michael@0 1628 for (i = 0; i < width; ++i)
michael@0 1629 {
michael@0 1630 comp4_t s = *(src + i);
michael@0 1631 comp4_t m = *(mask + i);
michael@0 1632 comp4_t a;
michael@0 1633
michael@0 1634 combine_mask_ca (&s, &m);
michael@0 1635
michael@0 1636 a = ~m;
michael@0 1637 if (a)
michael@0 1638 {
michael@0 1639 comp4_t d = *(dest + i);
michael@0 1640 UNcx4_MUL_UNcx4_ADD_UNcx4 (d, a, s);
michael@0 1641 s = d;
michael@0 1642 }
michael@0 1643
michael@0 1644 *(dest + i) = s;
michael@0 1645 }
michael@0 1646 }
michael@0 1647
michael@0 1648 static void
michael@0 1649 combine_over_reverse_ca (pixman_implementation_t *imp,
michael@0 1650 pixman_op_t op,
michael@0 1651 comp4_t * dest,
michael@0 1652 const comp4_t * src,
michael@0 1653 const comp4_t * mask,
michael@0 1654 int width)
michael@0 1655 {
michael@0 1656 int i;
michael@0 1657
michael@0 1658 for (i = 0; i < width; ++i)
michael@0 1659 {
michael@0 1660 comp4_t d = *(dest + i);
michael@0 1661 comp4_t a = ~d >> A_SHIFT;
michael@0 1662
michael@0 1663 if (a)
michael@0 1664 {
michael@0 1665 comp4_t s = *(src + i);
michael@0 1666 comp4_t m = *(mask + i);
michael@0 1667
michael@0 1668 UNcx4_MUL_UNcx4 (s, m);
michael@0 1669 UNcx4_MUL_UNc_ADD_UNcx4 (s, a, d);
michael@0 1670
michael@0 1671 *(dest + i) = s;
michael@0 1672 }
michael@0 1673 }
michael@0 1674 }
michael@0 1675
michael@0 1676 static void
michael@0 1677 combine_in_ca (pixman_implementation_t *imp,
michael@0 1678 pixman_op_t op,
michael@0 1679 comp4_t * dest,
michael@0 1680 const comp4_t * src,
michael@0 1681 const comp4_t * mask,
michael@0 1682 int width)
michael@0 1683 {
michael@0 1684 int i;
michael@0 1685
michael@0 1686 for (i = 0; i < width; ++i)
michael@0 1687 {
michael@0 1688 comp4_t d = *(dest + i);
michael@0 1689 comp2_t a = d >> A_SHIFT;
michael@0 1690 comp4_t s = 0;
michael@0 1691
michael@0 1692 if (a)
michael@0 1693 {
michael@0 1694 comp4_t m = *(mask + i);
michael@0 1695
michael@0 1696 s = *(src + i);
michael@0 1697 combine_mask_value_ca (&s, &m);
michael@0 1698
michael@0 1699 if (a != MASK)
michael@0 1700 UNcx4_MUL_UNc (s, a);
michael@0 1701 }
michael@0 1702
michael@0 1703 *(dest + i) = s;
michael@0 1704 }
michael@0 1705 }
michael@0 1706
michael@0 1707 static void
michael@0 1708 combine_in_reverse_ca (pixman_implementation_t *imp,
michael@0 1709 pixman_op_t op,
michael@0 1710 comp4_t * dest,
michael@0 1711 const comp4_t * src,
michael@0 1712 const comp4_t * mask,
michael@0 1713 int width)
michael@0 1714 {
michael@0 1715 int i;
michael@0 1716
michael@0 1717 for (i = 0; i < width; ++i)
michael@0 1718 {
michael@0 1719 comp4_t s = *(src + i);
michael@0 1720 comp4_t m = *(mask + i);
michael@0 1721 comp4_t a;
michael@0 1722
michael@0 1723 combine_mask_alpha_ca (&s, &m);
michael@0 1724
michael@0 1725 a = m;
michael@0 1726 if (a != ~0)
michael@0 1727 {
michael@0 1728 comp4_t d = 0;
michael@0 1729
michael@0 1730 if (a)
michael@0 1731 {
michael@0 1732 d = *(dest + i);
michael@0 1733 UNcx4_MUL_UNcx4 (d, a);
michael@0 1734 }
michael@0 1735
michael@0 1736 *(dest + i) = d;
michael@0 1737 }
michael@0 1738 }
michael@0 1739 }
michael@0 1740
michael@0 1741 static void
michael@0 1742 combine_out_ca (pixman_implementation_t *imp,
michael@0 1743 pixman_op_t op,
michael@0 1744 comp4_t * dest,
michael@0 1745 const comp4_t * src,
michael@0 1746 const comp4_t * mask,
michael@0 1747 int width)
michael@0 1748 {
michael@0 1749 int i;
michael@0 1750
michael@0 1751 for (i = 0; i < width; ++i)
michael@0 1752 {
michael@0 1753 comp4_t d = *(dest + i);
michael@0 1754 comp2_t a = ~d >> A_SHIFT;
michael@0 1755 comp4_t s = 0;
michael@0 1756
michael@0 1757 if (a)
michael@0 1758 {
michael@0 1759 comp4_t m = *(mask + i);
michael@0 1760
michael@0 1761 s = *(src + i);
michael@0 1762 combine_mask_value_ca (&s, &m);
michael@0 1763
michael@0 1764 if (a != MASK)
michael@0 1765 UNcx4_MUL_UNc (s, a);
michael@0 1766 }
michael@0 1767
michael@0 1768 *(dest + i) = s;
michael@0 1769 }
michael@0 1770 }
michael@0 1771
michael@0 1772 static void
michael@0 1773 combine_out_reverse_ca (pixman_implementation_t *imp,
michael@0 1774 pixman_op_t op,
michael@0 1775 comp4_t * dest,
michael@0 1776 const comp4_t * src,
michael@0 1777 const comp4_t * mask,
michael@0 1778 int width)
michael@0 1779 {
michael@0 1780 int i;
michael@0 1781
michael@0 1782 for (i = 0; i < width; ++i)
michael@0 1783 {
michael@0 1784 comp4_t s = *(src + i);
michael@0 1785 comp4_t m = *(mask + i);
michael@0 1786 comp4_t a;
michael@0 1787
michael@0 1788 combine_mask_alpha_ca (&s, &m);
michael@0 1789
michael@0 1790 a = ~m;
michael@0 1791 if (a != ~0)
michael@0 1792 {
michael@0 1793 comp4_t d = 0;
michael@0 1794
michael@0 1795 if (a)
michael@0 1796 {
michael@0 1797 d = *(dest + i);
michael@0 1798 UNcx4_MUL_UNcx4 (d, a);
michael@0 1799 }
michael@0 1800
michael@0 1801 *(dest + i) = d;
michael@0 1802 }
michael@0 1803 }
michael@0 1804 }
michael@0 1805
michael@0 1806 static void
michael@0 1807 combine_atop_ca (pixman_implementation_t *imp,
michael@0 1808 pixman_op_t op,
michael@0 1809 comp4_t * dest,
michael@0 1810 const comp4_t * src,
michael@0 1811 const comp4_t * mask,
michael@0 1812 int width)
michael@0 1813 {
michael@0 1814 int i;
michael@0 1815
michael@0 1816 for (i = 0; i < width; ++i)
michael@0 1817 {
michael@0 1818 comp4_t d = *(dest + i);
michael@0 1819 comp4_t s = *(src + i);
michael@0 1820 comp4_t m = *(mask + i);
michael@0 1821 comp4_t ad;
michael@0 1822 comp2_t as = d >> A_SHIFT;
michael@0 1823
michael@0 1824 combine_mask_ca (&s, &m);
michael@0 1825
michael@0 1826 ad = ~m;
michael@0 1827
michael@0 1828 UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (d, ad, s, as);
michael@0 1829
michael@0 1830 *(dest + i) = d;
michael@0 1831 }
michael@0 1832 }
michael@0 1833
michael@0 1834 static void
michael@0 1835 combine_atop_reverse_ca (pixman_implementation_t *imp,
michael@0 1836 pixman_op_t op,
michael@0 1837 comp4_t * dest,
michael@0 1838 const comp4_t * src,
michael@0 1839 const comp4_t * mask,
michael@0 1840 int width)
michael@0 1841 {
michael@0 1842 int i;
michael@0 1843
michael@0 1844 for (i = 0; i < width; ++i)
michael@0 1845 {
michael@0 1846 comp4_t d = *(dest + i);
michael@0 1847 comp4_t s = *(src + i);
michael@0 1848 comp4_t m = *(mask + i);
michael@0 1849 comp4_t ad;
michael@0 1850 comp2_t as = ~d >> A_SHIFT;
michael@0 1851
michael@0 1852 combine_mask_ca (&s, &m);
michael@0 1853
michael@0 1854 ad = m;
michael@0 1855
michael@0 1856 UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (d, ad, s, as);
michael@0 1857
michael@0 1858 *(dest + i) = d;
michael@0 1859 }
michael@0 1860 }
michael@0 1861
michael@0 1862 static void
michael@0 1863 combine_xor_ca (pixman_implementation_t *imp,
michael@0 1864 pixman_op_t op,
michael@0 1865 comp4_t * dest,
michael@0 1866 const comp4_t * src,
michael@0 1867 const comp4_t * mask,
michael@0 1868 int width)
michael@0 1869 {
michael@0 1870 int i;
michael@0 1871
michael@0 1872 for (i = 0; i < width; ++i)
michael@0 1873 {
michael@0 1874 comp4_t d = *(dest + i);
michael@0 1875 comp4_t s = *(src + i);
michael@0 1876 comp4_t m = *(mask + i);
michael@0 1877 comp4_t ad;
michael@0 1878 comp2_t as = ~d >> A_SHIFT;
michael@0 1879
michael@0 1880 combine_mask_ca (&s, &m);
michael@0 1881
michael@0 1882 ad = ~m;
michael@0 1883
michael@0 1884 UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (d, ad, s, as);
michael@0 1885
michael@0 1886 *(dest + i) = d;
michael@0 1887 }
michael@0 1888 }
michael@0 1889
michael@0 1890 static void
michael@0 1891 combine_add_ca (pixman_implementation_t *imp,
michael@0 1892 pixman_op_t op,
michael@0 1893 comp4_t * dest,
michael@0 1894 const comp4_t * src,
michael@0 1895 const comp4_t * mask,
michael@0 1896 int width)
michael@0 1897 {
michael@0 1898 int i;
michael@0 1899
michael@0 1900 for (i = 0; i < width; ++i)
michael@0 1901 {
michael@0 1902 comp4_t s = *(src + i);
michael@0 1903 comp4_t m = *(mask + i);
michael@0 1904 comp4_t d = *(dest + i);
michael@0 1905
michael@0 1906 combine_mask_value_ca (&s, &m);
michael@0 1907
michael@0 1908 UNcx4_ADD_UNcx4 (d, s);
michael@0 1909
michael@0 1910 *(dest + i) = d;
michael@0 1911 }
michael@0 1912 }
michael@0 1913
michael@0 1914 static void
michael@0 1915 combine_saturate_ca (pixman_implementation_t *imp,
michael@0 1916 pixman_op_t op,
michael@0 1917 comp4_t * dest,
michael@0 1918 const comp4_t * src,
michael@0 1919 const comp4_t * mask,
michael@0 1920 int width)
michael@0 1921 {
michael@0 1922 int i;
michael@0 1923
michael@0 1924 for (i = 0; i < width; ++i)
michael@0 1925 {
michael@0 1926 comp4_t s, d;
michael@0 1927 comp2_t sa, sr, sg, sb, da;
michael@0 1928 comp2_t t, u, v;
michael@0 1929 comp4_t m, n, o, p;
michael@0 1930
michael@0 1931 d = *(dest + i);
michael@0 1932 s = *(src + i);
michael@0 1933 m = *(mask + i);
michael@0 1934
michael@0 1935 combine_mask_ca (&s, &m);
michael@0 1936
michael@0 1937 sa = (m >> A_SHIFT);
michael@0 1938 sr = (m >> R_SHIFT) & MASK;
michael@0 1939 sg = (m >> G_SHIFT) & MASK;
michael@0 1940 sb = m & MASK;
michael@0 1941 da = ~d >> A_SHIFT;
michael@0 1942
michael@0 1943 if (sb <= da)
michael@0 1944 m = ADD (s, d, 0, t);
michael@0 1945 else
michael@0 1946 m = GENERIC (s, d, 0, (da << G_SHIFT) / sb, MASK, t, u, v);
michael@0 1947
michael@0 1948 if (sg <= da)
michael@0 1949 n = ADD (s, d, G_SHIFT, t);
michael@0 1950 else
michael@0 1951 n = GENERIC (s, d, G_SHIFT, (da << G_SHIFT) / sg, MASK, t, u, v);
michael@0 1952
michael@0 1953 if (sr <= da)
michael@0 1954 o = ADD (s, d, R_SHIFT, t);
michael@0 1955 else
michael@0 1956 o = GENERIC (s, d, R_SHIFT, (da << G_SHIFT) / sr, MASK, t, u, v);
michael@0 1957
michael@0 1958 if (sa <= da)
michael@0 1959 p = ADD (s, d, A_SHIFT, t);
michael@0 1960 else
michael@0 1961 p = GENERIC (s, d, A_SHIFT, (da << G_SHIFT) / sa, MASK, t, u, v);
michael@0 1962
michael@0 1963 *(dest + i) = m | n | o | p;
michael@0 1964 }
michael@0 1965 }
michael@0 1966
michael@0 1967 static void
michael@0 1968 combine_disjoint_general_ca (comp4_t * dest,
michael@0 1969 const comp4_t *src,
michael@0 1970 const comp4_t *mask,
michael@0 1971 int width,
michael@0 1972 comp1_t combine)
michael@0 1973 {
michael@0 1974 int i;
michael@0 1975
michael@0 1976 for (i = 0; i < width; ++i)
michael@0 1977 {
michael@0 1978 comp4_t s, d;
michael@0 1979 comp4_t m, n, o, p;
michael@0 1980 comp4_t Fa, Fb;
michael@0 1981 comp2_t t, u, v;
michael@0 1982 comp4_t sa;
michael@0 1983 comp1_t da;
michael@0 1984
michael@0 1985 s = *(src + i);
michael@0 1986 m = *(mask + i);
michael@0 1987 d = *(dest + i);
michael@0 1988 da = d >> A_SHIFT;
michael@0 1989
michael@0 1990 combine_mask_ca (&s, &m);
michael@0 1991
michael@0 1992 sa = m;
michael@0 1993
michael@0 1994 switch (combine & COMBINE_A)
michael@0 1995 {
michael@0 1996 default:
michael@0 1997 Fa = 0;
michael@0 1998 break;
michael@0 1999
michael@0 2000 case COMBINE_A_OUT:
michael@0 2001 m = (comp4_t)combine_disjoint_out_part ((comp1_t) (sa >> 0), da);
michael@0 2002 n = (comp4_t)combine_disjoint_out_part ((comp1_t) (sa >> G_SHIFT), da) << G_SHIFT;
michael@0 2003 o = (comp4_t)combine_disjoint_out_part ((comp1_t) (sa >> R_SHIFT), da) << R_SHIFT;
michael@0 2004 p = (comp4_t)combine_disjoint_out_part ((comp1_t) (sa >> A_SHIFT), da) << A_SHIFT;
michael@0 2005 Fa = m | n | o | p;
michael@0 2006 break;
michael@0 2007
michael@0 2008 case COMBINE_A_IN:
michael@0 2009 m = (comp4_t)combine_disjoint_in_part ((comp1_t) (sa >> 0), da);
michael@0 2010 n = (comp4_t)combine_disjoint_in_part ((comp1_t) (sa >> G_SHIFT), da) << G_SHIFT;
michael@0 2011 o = (comp4_t)combine_disjoint_in_part ((comp1_t) (sa >> R_SHIFT), da) << R_SHIFT;
michael@0 2012 p = (comp4_t)combine_disjoint_in_part ((comp1_t) (sa >> A_SHIFT), da) << A_SHIFT;
michael@0 2013 Fa = m | n | o | p;
michael@0 2014 break;
michael@0 2015
michael@0 2016 case COMBINE_A:
michael@0 2017 Fa = ~0;
michael@0 2018 break;
michael@0 2019 }
michael@0 2020
michael@0 2021 switch (combine & COMBINE_B)
michael@0 2022 {
michael@0 2023 default:
michael@0 2024 Fb = 0;
michael@0 2025 break;
michael@0 2026
michael@0 2027 case COMBINE_B_OUT:
michael@0 2028 m = (comp4_t)combine_disjoint_out_part (da, (comp1_t) (sa >> 0));
michael@0 2029 n = (comp4_t)combine_disjoint_out_part (da, (comp1_t) (sa >> G_SHIFT)) << G_SHIFT;
michael@0 2030 o = (comp4_t)combine_disjoint_out_part (da, (comp1_t) (sa >> R_SHIFT)) << R_SHIFT;
michael@0 2031 p = (comp4_t)combine_disjoint_out_part (da, (comp1_t) (sa >> A_SHIFT)) << A_SHIFT;
michael@0 2032 Fb = m | n | o | p;
michael@0 2033 break;
michael@0 2034
michael@0 2035 case COMBINE_B_IN:
michael@0 2036 m = (comp4_t)combine_disjoint_in_part (da, (comp1_t) (sa >> 0));
michael@0 2037 n = (comp4_t)combine_disjoint_in_part (da, (comp1_t) (sa >> G_SHIFT)) << G_SHIFT;
michael@0 2038 o = (comp4_t)combine_disjoint_in_part (da, (comp1_t) (sa >> R_SHIFT)) << R_SHIFT;
michael@0 2039 p = (comp4_t)combine_disjoint_in_part (da, (comp1_t) (sa >> A_SHIFT)) << A_SHIFT;
michael@0 2040 Fb = m | n | o | p;
michael@0 2041 break;
michael@0 2042
michael@0 2043 case COMBINE_B:
michael@0 2044 Fb = ~0;
michael@0 2045 break;
michael@0 2046 }
michael@0 2047 m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v);
michael@0 2048 n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v);
michael@0 2049 o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v);
michael@0 2050 p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v);
michael@0 2051
michael@0 2052 s = m | n | o | p;
michael@0 2053
michael@0 2054 *(dest + i) = s;
michael@0 2055 }
michael@0 2056 }
michael@0 2057
michael@0 2058 static void
michael@0 2059 combine_disjoint_over_ca (pixman_implementation_t *imp,
michael@0 2060 pixman_op_t op,
michael@0 2061 comp4_t * dest,
michael@0 2062 const comp4_t * src,
michael@0 2063 const comp4_t * mask,
michael@0 2064 int width)
michael@0 2065 {
michael@0 2066 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER);
michael@0 2067 }
michael@0 2068
michael@0 2069 static void
michael@0 2070 combine_disjoint_in_ca (pixman_implementation_t *imp,
michael@0 2071 pixman_op_t op,
michael@0 2072 comp4_t * dest,
michael@0 2073 const comp4_t * src,
michael@0 2074 const comp4_t * mask,
michael@0 2075 int width)
michael@0 2076 {
michael@0 2077 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_IN);
michael@0 2078 }
michael@0 2079
michael@0 2080 static void
michael@0 2081 combine_disjoint_in_reverse_ca (pixman_implementation_t *imp,
michael@0 2082 pixman_op_t op,
michael@0 2083 comp4_t * dest,
michael@0 2084 const comp4_t * src,
michael@0 2085 const comp4_t * mask,
michael@0 2086 int width)
michael@0 2087 {
michael@0 2088 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_IN);
michael@0 2089 }
michael@0 2090
michael@0 2091 static void
michael@0 2092 combine_disjoint_out_ca (pixman_implementation_t *imp,
michael@0 2093 pixman_op_t op,
michael@0 2094 comp4_t * dest,
michael@0 2095 const comp4_t * src,
michael@0 2096 const comp4_t * mask,
michael@0 2097 int width)
michael@0 2098 {
michael@0 2099 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT);
michael@0 2100 }
michael@0 2101
michael@0 2102 static void
michael@0 2103 combine_disjoint_out_reverse_ca (pixman_implementation_t *imp,
michael@0 2104 pixman_op_t op,
michael@0 2105 comp4_t * dest,
michael@0 2106 const comp4_t * src,
michael@0 2107 const comp4_t * mask,
michael@0 2108 int width)
michael@0 2109 {
michael@0 2110 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT);
michael@0 2111 }
michael@0 2112
michael@0 2113 static void
michael@0 2114 combine_disjoint_atop_ca (pixman_implementation_t *imp,
michael@0 2115 pixman_op_t op,
michael@0 2116 comp4_t * dest,
michael@0 2117 const comp4_t * src,
michael@0 2118 const comp4_t * mask,
michael@0 2119 int width)
michael@0 2120 {
michael@0 2121 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP);
michael@0 2122 }
michael@0 2123
michael@0 2124 static void
michael@0 2125 combine_disjoint_atop_reverse_ca (pixman_implementation_t *imp,
michael@0 2126 pixman_op_t op,
michael@0 2127 comp4_t * dest,
michael@0 2128 const comp4_t * src,
michael@0 2129 const comp4_t * mask,
michael@0 2130 int width)
michael@0 2131 {
michael@0 2132 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP);
michael@0 2133 }
michael@0 2134
michael@0 2135 static void
michael@0 2136 combine_disjoint_xor_ca (pixman_implementation_t *imp,
michael@0 2137 pixman_op_t op,
michael@0 2138 comp4_t * dest,
michael@0 2139 const comp4_t * src,
michael@0 2140 const comp4_t * mask,
michael@0 2141 int width)
michael@0 2142 {
michael@0 2143 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_XOR);
michael@0 2144 }
michael@0 2145
michael@0 2146 static void
michael@0 2147 combine_conjoint_general_ca (comp4_t * dest,
michael@0 2148 const comp4_t *src,
michael@0 2149 const comp4_t *mask,
michael@0 2150 int width,
michael@0 2151 comp1_t combine)
michael@0 2152 {
michael@0 2153 int i;
michael@0 2154
michael@0 2155 for (i = 0; i < width; ++i)
michael@0 2156 {
michael@0 2157 comp4_t s, d;
michael@0 2158 comp4_t m, n, o, p;
michael@0 2159 comp4_t Fa, Fb;
michael@0 2160 comp2_t t, u, v;
michael@0 2161 comp4_t sa;
michael@0 2162 comp1_t da;
michael@0 2163
michael@0 2164 s = *(src + i);
michael@0 2165 m = *(mask + i);
michael@0 2166 d = *(dest + i);
michael@0 2167 da = d >> A_SHIFT;
michael@0 2168
michael@0 2169 combine_mask_ca (&s, &m);
michael@0 2170
michael@0 2171 sa = m;
michael@0 2172
michael@0 2173 switch (combine & COMBINE_A)
michael@0 2174 {
michael@0 2175 default:
michael@0 2176 Fa = 0;
michael@0 2177 break;
michael@0 2178
michael@0 2179 case COMBINE_A_OUT:
michael@0 2180 m = (comp4_t)combine_conjoint_out_part ((comp1_t) (sa >> 0), da);
michael@0 2181 n = (comp4_t)combine_conjoint_out_part ((comp1_t) (sa >> G_SHIFT), da) << G_SHIFT;
michael@0 2182 o = (comp4_t)combine_conjoint_out_part ((comp1_t) (sa >> R_SHIFT), da) << R_SHIFT;
michael@0 2183 p = (comp4_t)combine_conjoint_out_part ((comp1_t) (sa >> A_SHIFT), da) << A_SHIFT;
michael@0 2184 Fa = m | n | o | p;
michael@0 2185 break;
michael@0 2186
michael@0 2187 case COMBINE_A_IN:
michael@0 2188 m = (comp4_t)combine_conjoint_in_part ((comp1_t) (sa >> 0), da);
michael@0 2189 n = (comp4_t)combine_conjoint_in_part ((comp1_t) (sa >> G_SHIFT), da) << G_SHIFT;
michael@0 2190 o = (comp4_t)combine_conjoint_in_part ((comp1_t) (sa >> R_SHIFT), da) << R_SHIFT;
michael@0 2191 p = (comp4_t)combine_conjoint_in_part ((comp1_t) (sa >> A_SHIFT), da) << A_SHIFT;
michael@0 2192 Fa = m | n | o | p;
michael@0 2193 break;
michael@0 2194
michael@0 2195 case COMBINE_A:
michael@0 2196 Fa = ~0;
michael@0 2197 break;
michael@0 2198 }
michael@0 2199
michael@0 2200 switch (combine & COMBINE_B)
michael@0 2201 {
michael@0 2202 default:
michael@0 2203 Fb = 0;
michael@0 2204 break;
michael@0 2205
michael@0 2206 case COMBINE_B_OUT:
michael@0 2207 m = (comp4_t)combine_conjoint_out_part (da, (comp1_t) (sa >> 0));
michael@0 2208 n = (comp4_t)combine_conjoint_out_part (da, (comp1_t) (sa >> G_SHIFT)) << G_SHIFT;
michael@0 2209 o = (comp4_t)combine_conjoint_out_part (da, (comp1_t) (sa >> R_SHIFT)) << R_SHIFT;
michael@0 2210 p = (comp4_t)combine_conjoint_out_part (da, (comp1_t) (sa >> A_SHIFT)) << A_SHIFT;
michael@0 2211 Fb = m | n | o | p;
michael@0 2212 break;
michael@0 2213
michael@0 2214 case COMBINE_B_IN:
michael@0 2215 m = (comp4_t)combine_conjoint_in_part (da, (comp1_t) (sa >> 0));
michael@0 2216 n = (comp4_t)combine_conjoint_in_part (da, (comp1_t) (sa >> G_SHIFT)) << G_SHIFT;
michael@0 2217 o = (comp4_t)combine_conjoint_in_part (da, (comp1_t) (sa >> R_SHIFT)) << R_SHIFT;
michael@0 2218 p = (comp4_t)combine_conjoint_in_part (da, (comp1_t) (sa >> A_SHIFT)) << A_SHIFT;
michael@0 2219 Fb = m | n | o | p;
michael@0 2220 break;
michael@0 2221
michael@0 2222 case COMBINE_B:
michael@0 2223 Fb = ~0;
michael@0 2224 break;
michael@0 2225 }
michael@0 2226 m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v);
michael@0 2227 n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v);
michael@0 2228 o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v);
michael@0 2229 p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v);
michael@0 2230
michael@0 2231 s = m | n | o | p;
michael@0 2232
michael@0 2233 *(dest + i) = s;
michael@0 2234 }
michael@0 2235 }
michael@0 2236
michael@0 2237 static void
michael@0 2238 combine_conjoint_over_ca (pixman_implementation_t *imp,
michael@0 2239 pixman_op_t op,
michael@0 2240 comp4_t * dest,
michael@0 2241 const comp4_t * src,
michael@0 2242 const comp4_t * mask,
michael@0 2243 int width)
michael@0 2244 {
michael@0 2245 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER);
michael@0 2246 }
michael@0 2247
michael@0 2248 static void
michael@0 2249 combine_conjoint_over_reverse_ca (pixman_implementation_t *imp,
michael@0 2250 pixman_op_t op,
michael@0 2251 comp4_t * dest,
michael@0 2252 const comp4_t * src,
michael@0 2253 const comp4_t * mask,
michael@0 2254 int width)
michael@0 2255 {
michael@0 2256 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OVER);
michael@0 2257 }
michael@0 2258
michael@0 2259 static void
michael@0 2260 combine_conjoint_in_ca (pixman_implementation_t *imp,
michael@0 2261 pixman_op_t op,
michael@0 2262 comp4_t * dest,
michael@0 2263 const comp4_t * src,
michael@0 2264 const comp4_t * mask,
michael@0 2265 int width)
michael@0 2266 {
michael@0 2267 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_IN);
michael@0 2268 }
michael@0 2269
michael@0 2270 static void
michael@0 2271 combine_conjoint_in_reverse_ca (pixman_implementation_t *imp,
michael@0 2272 pixman_op_t op,
michael@0 2273 comp4_t * dest,
michael@0 2274 const comp4_t * src,
michael@0 2275 const comp4_t * mask,
michael@0 2276 int width)
michael@0 2277 {
michael@0 2278 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_IN);
michael@0 2279 }
michael@0 2280
michael@0 2281 static void
michael@0 2282 combine_conjoint_out_ca (pixman_implementation_t *imp,
michael@0 2283 pixman_op_t op,
michael@0 2284 comp4_t * dest,
michael@0 2285 const comp4_t * src,
michael@0 2286 const comp4_t * mask,
michael@0 2287 int width)
michael@0 2288 {
michael@0 2289 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT);
michael@0 2290 }
michael@0 2291
michael@0 2292 static void
michael@0 2293 combine_conjoint_out_reverse_ca (pixman_implementation_t *imp,
michael@0 2294 pixman_op_t op,
michael@0 2295 comp4_t * dest,
michael@0 2296 const comp4_t * src,
michael@0 2297 const comp4_t * mask,
michael@0 2298 int width)
michael@0 2299 {
michael@0 2300 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT);
michael@0 2301 }
michael@0 2302
michael@0 2303 static void
michael@0 2304 combine_conjoint_atop_ca (pixman_implementation_t *imp,
michael@0 2305 pixman_op_t op,
michael@0 2306 comp4_t * dest,
michael@0 2307 const comp4_t * src,
michael@0 2308 const comp4_t * mask,
michael@0 2309 int width)
michael@0 2310 {
michael@0 2311 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP);
michael@0 2312 }
michael@0 2313
michael@0 2314 static void
michael@0 2315 combine_conjoint_atop_reverse_ca (pixman_implementation_t *imp,
michael@0 2316 pixman_op_t op,
michael@0 2317 comp4_t * dest,
michael@0 2318 const comp4_t * src,
michael@0 2319 const comp4_t * mask,
michael@0 2320 int width)
michael@0 2321 {
michael@0 2322 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP);
michael@0 2323 }
michael@0 2324
michael@0 2325 static void
michael@0 2326 combine_conjoint_xor_ca (pixman_implementation_t *imp,
michael@0 2327 pixman_op_t op,
michael@0 2328 comp4_t * dest,
michael@0 2329 const comp4_t * src,
michael@0 2330 const comp4_t * mask,
michael@0 2331 int width)
michael@0 2332 {
michael@0 2333 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_XOR);
michael@0 2334 }
michael@0 2335
michael@0 2336 void
michael@0 2337 _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
michael@0 2338 {
michael@0 2339 /* Unified alpha */
michael@0 2340 imp->combine_width[PIXMAN_OP_CLEAR] = combine_clear;
michael@0 2341 imp->combine_width[PIXMAN_OP_SRC] = combine_src_u;
michael@0 2342 imp->combine_width[PIXMAN_OP_DST] = combine_dst;
michael@0 2343 imp->combine_width[PIXMAN_OP_OVER] = combine_over_u;
michael@0 2344 imp->combine_width[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u;
michael@0 2345 imp->combine_width[PIXMAN_OP_IN] = combine_in_u;
michael@0 2346 imp->combine_width[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_u;
michael@0 2347 imp->combine_width[PIXMAN_OP_OUT] = combine_out_u;
michael@0 2348 imp->combine_width[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_u;
michael@0 2349 imp->combine_width[PIXMAN_OP_ATOP] = combine_atop_u;
michael@0 2350 imp->combine_width[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u;
michael@0 2351 imp->combine_width[PIXMAN_OP_XOR] = combine_xor_u;
michael@0 2352 imp->combine_width[PIXMAN_OP_ADD] = combine_add_u;
michael@0 2353 imp->combine_width[PIXMAN_OP_SATURATE] = combine_saturate_u;
michael@0 2354
michael@0 2355 /* Disjoint, unified */
michael@0 2356 imp->combine_width[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear;
michael@0 2357 imp->combine_width[PIXMAN_OP_DISJOINT_SRC] = combine_src_u;
michael@0 2358 imp->combine_width[PIXMAN_OP_DISJOINT_DST] = combine_dst;
michael@0 2359 imp->combine_width[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_u;
michael@0 2360 imp->combine_width[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_u;
michael@0 2361 imp->combine_width[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_u;
michael@0 2362 imp->combine_width[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_u;
michael@0 2363 imp->combine_width[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_u;
michael@0 2364 imp->combine_width[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_u;
michael@0 2365 imp->combine_width[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_u;
michael@0 2366 imp->combine_width[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_u;
michael@0 2367 imp->combine_width[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_u;
michael@0 2368
michael@0 2369 /* Conjoint, unified */
michael@0 2370 imp->combine_width[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear;
michael@0 2371 imp->combine_width[PIXMAN_OP_CONJOINT_SRC] = combine_src_u;
michael@0 2372 imp->combine_width[PIXMAN_OP_CONJOINT_DST] = combine_dst;
michael@0 2373 imp->combine_width[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_u;
michael@0 2374 imp->combine_width[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_u;
michael@0 2375 imp->combine_width[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_u;
michael@0 2376 imp->combine_width[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_u;
michael@0 2377 imp->combine_width[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_u;
michael@0 2378 imp->combine_width[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_u;
michael@0 2379 imp->combine_width[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_u;
michael@0 2380 imp->combine_width[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_u;
michael@0 2381 imp->combine_width[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_u;
michael@0 2382
michael@0 2383 imp->combine_width[PIXMAN_OP_MULTIPLY] = combine_multiply_u;
michael@0 2384 imp->combine_width[PIXMAN_OP_SCREEN] = combine_screen_u;
michael@0 2385 imp->combine_width[PIXMAN_OP_OVERLAY] = combine_overlay_u;
michael@0 2386 imp->combine_width[PIXMAN_OP_DARKEN] = combine_darken_u;
michael@0 2387 imp->combine_width[PIXMAN_OP_LIGHTEN] = combine_lighten_u;
michael@0 2388 imp->combine_width[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_u;
michael@0 2389 imp->combine_width[PIXMAN_OP_COLOR_BURN] = combine_color_burn_u;
michael@0 2390 imp->combine_width[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u;
michael@0 2391 imp->combine_width[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_u;
michael@0 2392 imp->combine_width[PIXMAN_OP_DIFFERENCE] = combine_difference_u;
michael@0 2393 imp->combine_width[PIXMAN_OP_EXCLUSION] = combine_exclusion_u;
michael@0 2394 imp->combine_width[PIXMAN_OP_HSL_HUE] = combine_hsl_hue_u;
michael@0 2395 imp->combine_width[PIXMAN_OP_HSL_SATURATION] = combine_hsl_saturation_u;
michael@0 2396 imp->combine_width[PIXMAN_OP_HSL_COLOR] = combine_hsl_color_u;
michael@0 2397 imp->combine_width[PIXMAN_OP_HSL_LUMINOSITY] = combine_hsl_luminosity_u;
michael@0 2398
michael@0 2399 /* Component alpha combiners */
michael@0 2400 imp->combine_width_ca[PIXMAN_OP_CLEAR] = combine_clear_ca;
michael@0 2401 imp->combine_width_ca[PIXMAN_OP_SRC] = combine_src_ca;
michael@0 2402 /* dest */
michael@0 2403 imp->combine_width_ca[PIXMAN_OP_OVER] = combine_over_ca;
michael@0 2404 imp->combine_width_ca[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_ca;
michael@0 2405 imp->combine_width_ca[PIXMAN_OP_IN] = combine_in_ca;
michael@0 2406 imp->combine_width_ca[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_ca;
michael@0 2407 imp->combine_width_ca[PIXMAN_OP_OUT] = combine_out_ca;
michael@0 2408 imp->combine_width_ca[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_ca;
michael@0 2409 imp->combine_width_ca[PIXMAN_OP_ATOP] = combine_atop_ca;
michael@0 2410 imp->combine_width_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca;
michael@0 2411 imp->combine_width_ca[PIXMAN_OP_XOR] = combine_xor_ca;
michael@0 2412 imp->combine_width_ca[PIXMAN_OP_ADD] = combine_add_ca;
michael@0 2413 imp->combine_width_ca[PIXMAN_OP_SATURATE] = combine_saturate_ca;
michael@0 2414
michael@0 2415 /* Disjoint CA */
michael@0 2416 imp->combine_width_ca[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear_ca;
michael@0 2417 imp->combine_width_ca[PIXMAN_OP_DISJOINT_SRC] = combine_src_ca;
michael@0 2418 imp->combine_width_ca[PIXMAN_OP_DISJOINT_DST] = combine_dst;
michael@0 2419 imp->combine_width_ca[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_ca;
michael@0 2420 imp->combine_width_ca[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_ca;
michael@0 2421 imp->combine_width_ca[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_ca;
michael@0 2422 imp->combine_width_ca[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_ca;
michael@0 2423 imp->combine_width_ca[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_ca;
michael@0 2424 imp->combine_width_ca[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_ca;
michael@0 2425 imp->combine_width_ca[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_ca;
michael@0 2426 imp->combine_width_ca[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_ca;
michael@0 2427 imp->combine_width_ca[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_ca;
michael@0 2428
michael@0 2429 /* Conjoint CA */
michael@0 2430 imp->combine_width_ca[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear_ca;
michael@0 2431 imp->combine_width_ca[PIXMAN_OP_CONJOINT_SRC] = combine_src_ca;
michael@0 2432 imp->combine_width_ca[PIXMAN_OP_CONJOINT_DST] = combine_dst;
michael@0 2433 imp->combine_width_ca[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_ca;
michael@0 2434 imp->combine_width_ca[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_ca;
michael@0 2435 imp->combine_width_ca[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_ca;
michael@0 2436 imp->combine_width_ca[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_ca;
michael@0 2437 imp->combine_width_ca[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_ca;
michael@0 2438 imp->combine_width_ca[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_ca;
michael@0 2439 imp->combine_width_ca[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_ca;
michael@0 2440 imp->combine_width_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_ca;
michael@0 2441 imp->combine_width_ca[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_ca;
michael@0 2442
michael@0 2443 imp->combine_width_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca;
michael@0 2444 imp->combine_width_ca[PIXMAN_OP_SCREEN] = combine_screen_ca;
michael@0 2445 imp->combine_width_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca;
michael@0 2446 imp->combine_width_ca[PIXMAN_OP_DARKEN] = combine_darken_ca;
michael@0 2447 imp->combine_width_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca;
michael@0 2448 imp->combine_width_ca[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_ca;
michael@0 2449 imp->combine_width_ca[PIXMAN_OP_COLOR_BURN] = combine_color_burn_ca;
michael@0 2450 imp->combine_width_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca;
michael@0 2451 imp->combine_width_ca[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_ca;
michael@0 2452 imp->combine_width_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca;
michael@0 2453 imp->combine_width_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca;
michael@0 2454
michael@0 2455 /* It is not clear that these make sense, so make them noops for now */
michael@0 2456 imp->combine_width_ca[PIXMAN_OP_HSL_HUE] = combine_dst;
michael@0 2457 imp->combine_width_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst;
michael@0 2458 imp->combine_width_ca[PIXMAN_OP_HSL_COLOR] = combine_dst;
michael@0 2459 imp->combine_width_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst;
michael@0 2460 }
michael@0 2461

mercurial