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

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

mercurial