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