gfx/cairo/libpixman/src/pixman-combine32.c

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

mercurial