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