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