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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 #ifdef HAVE_CONFIG_H
     2 #include <config.h>
     3 #endif
     5 #include <math.h>
     6 #include <string.h>
     8 #include "pixman-private.h"
    10 #include "pixman-combine.h"
    12 /*** per channel helper functions ***/
    14 static void
    15 combine_mask_ca (comp4_t *src, comp4_t *mask)
    16 {
    17     comp4_t a = *mask;
    19     comp4_t x;
    20     comp2_t xa;
    22     if (!a)
    23     {
    24 	*(src) = 0;
    25 	return;
    26     }
    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     }
    38     xa = x >> A_SHIFT;
    39     UNcx4_MUL_UNcx4 (x, a);
    40     *(src) = x;
    42     UNcx4_MUL_UNc (a, xa);
    43     *(mask) = a;
    44 }
    46 static void
    47 combine_mask_value_ca (comp4_t *src, const comp4_t *mask)
    48 {
    49     comp4_t a = *mask;
    50     comp4_t x;
    52     if (!a)
    53     {
    54 	*(src) = 0;
    55 	return;
    56     }
    58     if (a == ~0)
    59 	return;
    61     x = *(src);
    62     UNcx4_MUL_UNcx4 (x, a);
    63     *(src) = x;
    64 }
    66 static void
    67 combine_mask_alpha_ca (const comp4_t *src, comp4_t *mask)
    68 {
    69     comp4_t a = *(mask);
    70     comp4_t x;
    72     if (!a)
    73 	return;
    75     x = *(src) >> A_SHIFT;
    76     if (x == MASK)
    77 	return;
    79     if (a == ~0)
    80     {
    81 	x |= x << G_SHIFT;
    82 	x |= x << R_SHIFT;
    83 	*(mask) = x;
    84 	return;
    85     }
    87     UNcx4_MUL_UNc (a, x);
    88     *(mask) = a;
    89 }
    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  */
    99 /*
   100  * All of the composing functions
   101  */
   103 static force_inline comp4_t
   104 combine_mask (const comp4_t *src, const comp4_t *mask, int i)
   105 {
   106     comp4_t s, m;
   108     if (mask)
   109     {
   110 	m = *(mask + i) >> A_SHIFT;
   112 	if (!m)
   113 	    return 0;
   114     }
   116     s = *(src + i);
   118     if (mask)
   119 	UNcx4_MUL_UNc (s, m);
   121     return s;
   122 }
   124 static void
   125 combine_clear (pixman_implementation_t *imp,
   126                pixman_op_t              op,
   127                comp4_t *                dest,
   128                const comp4_t *          src,
   129                const comp4_t *          mask,
   130                int                      width)
   131 {
   132     memset (dest, 0, width * sizeof(comp4_t));
   133 }
   135 static void
   136 combine_dst (pixman_implementation_t *imp,
   137 	     pixman_op_t	      op,
   138 	     comp4_t *		      dest,
   139 	     const comp4_t *	      src,
   140 	     const comp4_t *          mask,
   141 	     int		      width)
   142 {
   143     return;
   144 }
   146 static void
   147 combine_src_u (pixman_implementation_t *imp,
   148                pixman_op_t              op,
   149                comp4_t *                dest,
   150                const comp4_t *          src,
   151                const comp4_t *          mask,
   152                int                      width)
   153 {
   154     int i;
   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);
   164 	    *(dest + i) = s;
   165 	}
   166     }
   167 }
   169 /* if the Src is opaque, call combine_src_u */
   170 static void
   171 combine_over_u (pixman_implementation_t *imp,
   172                 pixman_op_t              op,
   173                 comp4_t *                dest,
   174                 const comp4_t *          src,
   175                 const comp4_t *          mask,
   176                 int                      width)
   177 {
   178     int i;
   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);
   186 	UNcx4_MUL_UNc_ADD_UNcx4 (d, ia, s);
   187 	*(dest + i) = d;
   188     }
   189 }
   191 /* if the Dst is opaque, this is a noop */
   192 static void
   193 combine_over_reverse_u (pixman_implementation_t *imp,
   194                         pixman_op_t              op,
   195                         comp4_t *                dest,
   196                         const comp4_t *          src,
   197                         const comp4_t *          mask,
   198                         int                      width)
   199 {
   200     int i;
   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 }
   212 /* if the Dst is opaque, call combine_src_u */
   213 static void
   214 combine_in_u (pixman_implementation_t *imp,
   215               pixman_op_t              op,
   216               comp4_t *                dest,
   217               const comp4_t *          src,
   218               const comp4_t *          mask,
   219               int                      width)
   220 {
   221     int i;
   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 }
   232 /* if the Src is opaque, this is a noop */
   233 static void
   234 combine_in_reverse_u (pixman_implementation_t *imp,
   235                       pixman_op_t              op,
   236                       comp4_t *                dest,
   237                       const comp4_t *          src,
   238                       const comp4_t *          mask,
   239                       int                      width)
   240 {
   241     int i;
   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 }
   253 /* if the Dst is opaque, call combine_clear */
   254 static void
   255 combine_out_u (pixman_implementation_t *imp,
   256                pixman_op_t              op,
   257                comp4_t *                dest,
   258                const comp4_t *          src,
   259                const comp4_t *          mask,
   260                int                      width)
   261 {
   262     int i;
   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 }
   273 /* if the Src is opaque, call combine_clear */
   274 static void
   275 combine_out_reverse_u (pixman_implementation_t *imp,
   276                        pixman_op_t              op,
   277                        comp4_t *                dest,
   278                        const comp4_t *          src,
   279                        const comp4_t *          mask,
   280                        int                      width)
   281 {
   282     int i;
   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 }
   294 /* if the Src is opaque, call combine_in_u */
   295 /* if the Dst is opaque, call combine_over_u */
   296 /* if both the Src and Dst are opaque, call combine_src_u */
   297 static void
   298 combine_atop_u (pixman_implementation_t *imp,
   299                 pixman_op_t              op,
   300                 comp4_t *                dest,
   301                 const comp4_t *          src,
   302                 const comp4_t *          mask,
   303                 int                      width)
   304 {
   305     int i;
   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);
   314 	UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (s, dest_a, d, src_ia);
   315 	*(dest + i) = s;
   316     }
   317 }
   319 /* if the Src is opaque, call combine_over_reverse_u */
   320 /* if the Dst is opaque, call combine_in_reverse_u */
   321 /* if both the Src and Dst are opaque, call combine_dst_u */
   322 static void
   323 combine_atop_reverse_u (pixman_implementation_t *imp,
   324                         pixman_op_t              op,
   325                         comp4_t *                dest,
   326                         const comp4_t *          src,
   327                         const comp4_t *          mask,
   328                         int                      width)
   329 {
   330     int i;
   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);
   339 	UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (s, dest_ia, d, src_a);
   340 	*(dest + i) = s;
   341     }
   342 }
   344 /* if the Src is opaque, call combine_over_u */
   345 /* if the Dst is opaque, call combine_over_reverse_u */
   346 /* if both the Src and Dst are opaque, call combine_clear */
   347 static void
   348 combine_xor_u (pixman_implementation_t *imp,
   349                pixman_op_t              op,
   350                comp4_t *                dest,
   351                const comp4_t *          src,
   352                const comp4_t *          mask,
   353                int                      width)
   354 {
   355     int i;
   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);
   364 	UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (s, dest_ia, d, src_ia);
   365 	*(dest + i) = s;
   366     }
   367 }
   369 static void
   370 combine_add_u (pixman_implementation_t *imp,
   371                pixman_op_t              op,
   372                comp4_t *                dest,
   373                const comp4_t *          src,
   374                const comp4_t *          mask,
   375                int                      width)
   376 {
   377     int i;
   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 }
   388 /* if the Src is opaque, call combine_add_u */
   389 /* if the Dst is opaque, call combine_add_u */
   390 /* if both the Src and Dst are opaque, call combine_add_u */
   391 static void
   392 combine_saturate_u (pixman_implementation_t *imp,
   393                     pixman_op_t              op,
   394                     comp4_t *                dest,
   395                     const comp4_t *          src,
   396                     const comp4_t *          mask,
   397                     int                      width)
   398 {
   399     int i;
   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;
   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 }
   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  */
   443 /*
   444  * Multiply
   445  * B(Dca, ad, Sca, as) = Dca.Sca
   446  */
   448 static void
   449 combine_multiply_u (pixman_implementation_t *imp,
   450                     pixman_op_t              op,
   451                     comp4_t *                dest,
   452                     const comp4_t *          src,
   453                     const comp4_t *          mask,
   454                     int                      width)
   455 {
   456     int i;
   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);
   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);
   470 	*(dest + i) = d;
   471     }
   472 }
   474 static void
   475 combine_multiply_ca (pixman_implementation_t *imp,
   476                      pixman_op_t              op,
   477                      comp4_t *                dest,
   478                      const comp4_t *          src,
   479                      const comp4_t *          mask,
   480                      int                      width)
   481 {
   482     int i;
   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);
   492 	combine_mask_value_ca (&s, &m);
   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);
   498 	*(dest + i) = r;
   499     }
   500 }
   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     }
   564 /*
   565  * Screen
   566  * B(Dca, ad, Sca, as) = Dca.sa + Sca.da - Dca.Sca
   567  */
   568 static inline comp4_t
   569 blend_screen (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
   570 {
   571     return DIV_ONE_UNc (sca * da + dca * sa - sca * dca);
   572 }
   574 PDF_SEPARABLE_BLEND_MODE (screen)
   576 /*
   577  * Overlay
   578  * B(Dca, Da, Sca, Sa) =
   579  *   if 2.Dca < Da
   580  *     2.Sca.Dca
   581  *   otherwise
   582  *     Sa.Da - 2.(Da - Dca).(Sa - Sca)
   583  */
   584 static inline comp4_t
   585 blend_overlay (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
   586 {
   587     comp4_t rca;
   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 }
   596 PDF_SEPARABLE_BLEND_MODE (overlay)
   598 /*
   599  * Darken
   600  * B(Dca, Da, Sca, Sa) = min (Sca.Da, Dca.Sa)
   601  */
   602 static inline comp4_t
   603 blend_darken (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
   604 {
   605     comp4_t s, d;
   607     s = sca * da;
   608     d = dca * sa;
   609     return DIV_ONE_UNc (s > d ? d : s);
   610 }
   612 PDF_SEPARABLE_BLEND_MODE (darken)
   614 /*
   615  * Lighten
   616  * B(Dca, Da, Sca, Sa) = max (Sca.Da, Dca.Sa)
   617  */
   618 static inline comp4_t
   619 blend_lighten (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
   620 {
   621     comp4_t s, d;
   623     s = sca * da;
   624     d = dca * sa;
   625     return DIV_ONE_UNc (s > d ? s : d);
   626 }
   628 PDF_SEPARABLE_BLEND_MODE (lighten)
   630 /*
   631  * Color dodge
   632  * B(Dca, Da, Sca, Sa) =
   633  *   if Dca == 0
   634  *     0
   635  *   if Sca == Sa
   636  *     Sa.Da
   637  *   otherwise
   638  *     Sa.Da. min (1, Dca / Da / (1 - Sca/Sa))
   639  */
   640 static inline comp4_t
   641 blend_color_dodge (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
   642 {
   643     if (sca >= sa)
   644     {
   645 	return dca == 0 ? 0 : DIV_ONE_UNc (sa * da);
   646     }
   647     else
   648     {
   649 	comp4_t rca = dca * sa / (sa - sca);
   650 	return DIV_ONE_UNc (sa * MIN (rca, da));
   651     }
   652 }
   654 PDF_SEPARABLE_BLEND_MODE (color_dodge)
   656 /*
   657  * Color burn
   658  * B(Dca, Da, Sca, Sa) =
   659  *   if Dca == Da
   660  *     Sa.Da
   661  *   if Sca == 0
   662  *     0
   663  *   otherwise
   664  *     Sa.Da.(1 - min (1, (1 - Dca/Da).Sa / Sca))
   665  */
   666 static inline comp4_t
   667 blend_color_burn (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
   668 {
   669     if (sca == 0)
   670     {
   671 	return dca < da ? 0 : DIV_ONE_UNc (sa * da);
   672     }
   673     else
   674     {
   675 	comp4_t rca = (da - dca) * sa / sca;
   676 	return DIV_ONE_UNc (sa * (MAX (rca, da) - rca));
   677     }
   678 }
   680 PDF_SEPARABLE_BLEND_MODE (color_burn)
   682 /*
   683  * Hard light
   684  * B(Dca, Da, Sca, Sa) =
   685  *   if 2.Sca < Sa
   686  *     2.Sca.Dca
   687  *   otherwise
   688  *     Sa.Da - 2.(Da - Dca).(Sa - Sca)
   689  */
   690 static inline comp4_t
   691 blend_hard_light (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
   692 {
   693     if (2 * sca < sa)
   694 	return DIV_ONE_UNc (2 * sca * dca);
   695     else
   696 	return DIV_ONE_UNc (sa * da - 2 * (da - dca) * (sa - sca));
   697 }
   699 PDF_SEPARABLE_BLEND_MODE (hard_light)
   701 /*
   702  * Soft light
   703  * B(Dca, Da, Sca, Sa) =
   704  *   if (2.Sca <= Sa)
   705  *     Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa))
   706  *   otherwise if Dca.4 <= Da
   707  *     Dca.(Sa + (2.Sca - Sa).((16.Dca/Da - 12).Dca/Da + 3)
   708  *   otherwise
   709  *     (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa))
   710  */
   711 static inline comp4_t
   712 blend_soft_light (comp4_t dca_org,
   713 		  comp4_t da_org,
   714 		  comp4_t sca_org,
   715 		  comp4_t sa_org)
   716 {
   717     double dca = dca_org * (1.0 / MASK);
   718     double da = da_org * (1.0 / MASK);
   719     double sca = sca_org * (1.0 / MASK);
   720     double sa = sa_org * (1.0 / MASK);
   721     double rca;
   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 }
   746 PDF_SEPARABLE_BLEND_MODE (soft_light)
   748 /*
   749  * Difference
   750  * B(Dca, Da, Sca, Sa) = abs (Dca.Sa - Sca.Da)
   751  */
   752 static inline comp4_t
   753 blend_difference (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
   754 {
   755     comp4_t dcasa = dca * sa;
   756     comp4_t scada = sca * da;
   758     if (scada < dcasa)
   759 	return DIV_ONE_UNc (dcasa - scada);
   760     else
   761 	return DIV_ONE_UNc (scada - dcasa);
   762 }
   764 PDF_SEPARABLE_BLEND_MODE (difference)
   766 /*
   767  * Exclusion
   768  * B(Dca, Da, Sca, Sa) = (Sca.Da + Dca.Sa - 2.Sca.Dca)
   769  */
   771 /* This can be made faster by writing it directly and not using
   772  * PDF_SEPARABLE_BLEND_MODE, but that's a performance optimization */
   774 static inline comp4_t
   775 blend_exclusion (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
   776 {
   777     return DIV_ONE_UNc (sca * da + dca * sa - 2 * dca * sca);
   778 }
   780 PDF_SEPARABLE_BLEND_MODE (exclusion)
   782 #undef PDF_SEPARABLE_BLEND_MODE
   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  */
   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  */
   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  */
   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))
   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     }
   936 static void
   937 set_lum (comp4_t dest[3], comp4_t src[3], comp4_t sa, comp4_t lum)
   938 {
   939     double a, l, min, max;
   940     double tmp[3];
   942     a = sa * (1.0 / MASK);
   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);
   949     l = l - LUM (tmp);
   950     tmp[0] += l;
   951     tmp[1] += l;
   952     tmp[2] += l;
   954     /* clip_color */
   955     l = LUM (tmp);
   956     min = CH_MIN (tmp);
   957     max = CH_MAX (tmp);
   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     }
   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 }
   995 static void
   996 set_sat (comp4_t dest[3], comp4_t src[3], comp4_t sat)
   997 {
   998     int id[3];
   999     comp4_t min, max;
  1001     if (src[0] > src[1])
  1003 	if (src[0] > src[2])
  1005 	    id[0] = 0;
  1006 	    if (src[1] > src[2])
  1008 		id[1] = 1;
  1009 		id[2] = 2;
  1011 	    else
  1013 		id[1] = 2;
  1014 		id[2] = 1;
  1017 	else
  1019 	    id[0] = 2;
  1020 	    id[1] = 0;
  1021 	    id[2] = 1;
  1024     else
  1026 	if (src[0] > src[2])
  1028 	    id[0] = 1;
  1029 	    id[1] = 0;
  1030 	    id[2] = 2;
  1032 	else
  1034 	    id[2] = 0;
  1035 	    if (src[1] > src[2])
  1037 		id[0] = 1;
  1038 		id[1] = 2;
  1040 	    else
  1042 		id[0] = 2;
  1043 		id[1] = 1;
  1048     max = dest[id[0]];
  1049     min = dest[id[2]];
  1050     if (max > min)
  1052 	dest[id[1]] = (dest[id[1]] - min) * sat / (max - min);
  1053 	dest[id[0]] = sat;
  1054 	dest[id[2]] = 0;
  1056     else
  1058 	dest[0] = dest[1] = dest[2] = 0;
  1062 /*
  1063  * Hue:
  1064  * B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb))
  1065  */
  1066 static inline void
  1067 blend_hsl_hue (comp4_t c[3],
  1068                comp4_t dc[3],
  1069                comp4_t da,
  1070                comp4_t sc[3],
  1071                comp4_t sa)
  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);
  1080 PDF_NON_SEPARABLE_BLEND_MODE (hsl_hue)
  1082 /*
  1083  * Saturation:
  1084  * B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb))
  1085  */
  1086 static inline void
  1087 blend_hsl_saturation (comp4_t c[3],
  1088                       comp4_t dc[3],
  1089                       comp4_t da,
  1090                       comp4_t sc[3],
  1091                       comp4_t sa)
  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);
  1100 PDF_NON_SEPARABLE_BLEND_MODE (hsl_saturation)
  1102 /*
  1103  * Color:
  1104  * B(Cb, Cs) = set_lum (Cs, LUM (Cb))
  1105  */
  1106 static inline void
  1107 blend_hsl_color (comp4_t c[3],
  1108                  comp4_t dc[3],
  1109                  comp4_t da,
  1110                  comp4_t sc[3],
  1111                  comp4_t sa)
  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);
  1119 PDF_NON_SEPARABLE_BLEND_MODE (hsl_color)
  1121 /*
  1122  * Luminosity:
  1123  * B(Cb, Cs) = set_lum (Cb, LUM (Cs))
  1124  */
  1125 static inline void
  1126 blend_hsl_luminosity (comp4_t c[3],
  1127                       comp4_t dc[3],
  1128                       comp4_t da,
  1129                       comp4_t sc[3],
  1130                       comp4_t sa)
  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);
  1138 PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity)
  1140 #undef SAT
  1141 #undef LUM
  1142 #undef CH_MAX
  1143 #undef CH_MIN
  1144 #undef PDF_NON_SEPARABLE_BLEND_MODE
  1146 /* All of the disjoint/conjoint composing functions
  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.
  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)
  1168  * See  http://marc.info/?l=xfree-render&m=99792000027857&w=2  for more
  1169  * information about these operators.
  1170  */
  1172 #define COMBINE_A_OUT 1
  1173 #define COMBINE_A_IN  2
  1174 #define COMBINE_B_OUT 4
  1175 #define COMBINE_B_IN  8
  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)
  1186 /* portion covered by a but not b */
  1187 static comp1_t
  1188 combine_disjoint_out_part (comp1_t a, comp1_t b)
  1190     /* min (1, (1-b) / a) */
  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 */
  1198 /* portion covered by both a and b */
  1199 static comp1_t
  1200 combine_disjoint_in_part (comp1_t a, comp1_t b)
  1202     /* max (1-(1-b)/a,0) */
  1203     /*  = - min ((1-b)/a - 1, 0) */
  1204     /*  = 1 - min (1, (1-b)/a) */
  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 */
  1212 /* portion covered by a but not b */
  1213 static comp1_t
  1214 combine_conjoint_out_part (comp1_t a, comp1_t b)
  1216     /* max (1-b/a,0) */
  1217     /* = 1-min(b/a,1) */
  1219     /* min (1, (1-b) / a) */
  1221     if (b >= a)             /* b >= a -> b/a >= 1 */
  1222 	return 0x00;        /* 0 */
  1223     return ~DIV_UNc(b, a);    /* 1 - b/a */
  1226 /* portion covered by both a and b */
  1227 static comp1_t
  1228 combine_conjoint_in_part (comp1_t a, comp1_t b)
  1230     /* min (1,b/a) */
  1232     if (b >= a)             /* b >= a -> b/a >= 1 */
  1233 	return MASK;        /* 1 */
  1234     return DIV_UNc (b, a);     /* b/a */
  1237 #define GET_COMP(v, i)   ((comp2_t) (comp1_t) ((v) >> i))
  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))
  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))
  1249 static void
  1250 combine_disjoint_general_u (comp4_t *      dest,
  1251                             const comp4_t *src,
  1252                             const comp4_t *mask,
  1253                             int            width,
  1254                             comp1_t        combine)
  1256     int i;
  1258     for (i = 0; i < width; ++i)
  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;
  1267 	switch (combine & COMBINE_A)
  1269 	default:
  1270 	    Fa = 0;
  1271 	    break;
  1273 	case COMBINE_A_OUT:
  1274 	    Fa = combine_disjoint_out_part (sa, da);
  1275 	    break;
  1277 	case COMBINE_A_IN:
  1278 	    Fa = combine_disjoint_in_part (sa, da);
  1279 	    break;
  1281 	case COMBINE_A:
  1282 	    Fa = MASK;
  1283 	    break;
  1286 	switch (combine & COMBINE_B)
  1288 	default:
  1289 	    Fb = 0;
  1290 	    break;
  1292 	case COMBINE_B_OUT:
  1293 	    Fb = combine_disjoint_out_part (da, sa);
  1294 	    break;
  1296 	case COMBINE_B_IN:
  1297 	    Fb = combine_disjoint_in_part (da, sa);
  1298 	    break;
  1300 	case COMBINE_B:
  1301 	    Fb = MASK;
  1302 	    break;
  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;
  1313 static void
  1314 combine_disjoint_over_u (pixman_implementation_t *imp,
  1315                          pixman_op_t              op,
  1316                          comp4_t *                dest,
  1317                          const comp4_t *          src,
  1318                          const comp4_t *          mask,
  1319                          int                      width)
  1321     int i;
  1323     for (i = 0; i < width; ++i)
  1325 	comp4_t s = combine_mask (src, mask, i);
  1326 	comp2_t a = s >> A_SHIFT;
  1328 	if (s != 0x00)
  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);
  1334 	    *(dest + i) = d;
  1339 static void
  1340 combine_disjoint_in_u (pixman_implementation_t *imp,
  1341                        pixman_op_t              op,
  1342                        comp4_t *                dest,
  1343                        const comp4_t *          src,
  1344                        const comp4_t *          mask,
  1345                        int                      width)
  1347     combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_IN);
  1350 static void
  1351 combine_disjoint_in_reverse_u (pixman_implementation_t *imp,
  1352                                pixman_op_t              op,
  1353                                comp4_t *                dest,
  1354                                const comp4_t *          src,
  1355                                const comp4_t *          mask,
  1356                                int                      width)
  1358     combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_IN);
  1361 static void
  1362 combine_disjoint_out_u (pixman_implementation_t *imp,
  1363                         pixman_op_t              op,
  1364                         comp4_t *                dest,
  1365                         const comp4_t *          src,
  1366                         const comp4_t *          mask,
  1367                         int                      width)
  1369     combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_OUT);
  1372 static void
  1373 combine_disjoint_out_reverse_u (pixman_implementation_t *imp,
  1374                                 pixman_op_t              op,
  1375                                 comp4_t *                dest,
  1376                                 const comp4_t *          src,
  1377                                 const comp4_t *          mask,
  1378                                 int                      width)
  1380     combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_OUT);
  1383 static void
  1384 combine_disjoint_atop_u (pixman_implementation_t *imp,
  1385                          pixman_op_t              op,
  1386                          comp4_t *                dest,
  1387                          const comp4_t *          src,
  1388                          const comp4_t *          mask,
  1389                          int                      width)
  1391     combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP);
  1394 static void
  1395 combine_disjoint_atop_reverse_u (pixman_implementation_t *imp,
  1396                                  pixman_op_t              op,
  1397                                  comp4_t *                dest,
  1398                                  const comp4_t *          src,
  1399                                  const comp4_t *          mask,
  1400                                  int                      width)
  1402     combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP);
  1405 static void
  1406 combine_disjoint_xor_u (pixman_implementation_t *imp,
  1407                         pixman_op_t              op,
  1408                         comp4_t *                dest,
  1409                         const comp4_t *          src,
  1410                         const comp4_t *          mask,
  1411                         int                      width)
  1413     combine_disjoint_general_u (dest, src, mask, width, COMBINE_XOR);
  1416 static void
  1417 combine_conjoint_general_u (comp4_t *      dest,
  1418                             const comp4_t *src,
  1419                             const comp4_t *mask,
  1420                             int            width,
  1421                             comp1_t        combine)
  1423     int i;
  1425     for (i = 0; i < width; ++i)
  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;
  1434 	switch (combine & COMBINE_A)
  1436 	default:
  1437 	    Fa = 0;
  1438 	    break;
  1440 	case COMBINE_A_OUT:
  1441 	    Fa = combine_conjoint_out_part (sa, da);
  1442 	    break;
  1444 	case COMBINE_A_IN:
  1445 	    Fa = combine_conjoint_in_part (sa, da);
  1446 	    break;
  1448 	case COMBINE_A:
  1449 	    Fa = MASK;
  1450 	    break;
  1453 	switch (combine & COMBINE_B)
  1455 	default:
  1456 	    Fb = 0;
  1457 	    break;
  1459 	case COMBINE_B_OUT:
  1460 	    Fb = combine_conjoint_out_part (da, sa);
  1461 	    break;
  1463 	case COMBINE_B_IN:
  1464 	    Fb = combine_conjoint_in_part (da, sa);
  1465 	    break;
  1467 	case COMBINE_B:
  1468 	    Fb = MASK;
  1469 	    break;
  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);
  1477 	s = m | n | o | p;
  1479 	*(dest + i) = s;
  1483 static void
  1484 combine_conjoint_over_u (pixman_implementation_t *imp,
  1485                          pixman_op_t              op,
  1486                          comp4_t *                dest,
  1487                          const comp4_t *          src,
  1488                          const comp4_t *          mask,
  1489                          int                      width)
  1491     combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OVER);
  1494 static void
  1495 combine_conjoint_over_reverse_u (pixman_implementation_t *imp,
  1496                                  pixman_op_t              op,
  1497                                  comp4_t *                dest,
  1498                                  const comp4_t *          src,
  1499                                  const comp4_t *          mask,
  1500                                  int                      width)
  1502     combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OVER);
  1505 static void
  1506 combine_conjoint_in_u (pixman_implementation_t *imp,
  1507                        pixman_op_t              op,
  1508                        comp4_t *                dest,
  1509                        const comp4_t *          src,
  1510                        const comp4_t *          mask,
  1511                        int                      width)
  1513     combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_IN);
  1516 static void
  1517 combine_conjoint_in_reverse_u (pixman_implementation_t *imp,
  1518                                pixman_op_t              op,
  1519                                comp4_t *                dest,
  1520                                const comp4_t *          src,
  1521                                const comp4_t *          mask,
  1522                                int                      width)
  1524     combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_IN);
  1527 static void
  1528 combine_conjoint_out_u (pixman_implementation_t *imp,
  1529                         pixman_op_t              op,
  1530                         comp4_t *                dest,
  1531                         const comp4_t *          src,
  1532                         const comp4_t *          mask,
  1533                         int                      width)
  1535     combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OUT);
  1538 static void
  1539 combine_conjoint_out_reverse_u (pixman_implementation_t *imp,
  1540                                 pixman_op_t              op,
  1541                                 comp4_t *                dest,
  1542                                 const comp4_t *          src,
  1543                                 const comp4_t *          mask,
  1544                                 int                      width)
  1546     combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OUT);
  1549 static void
  1550 combine_conjoint_atop_u (pixman_implementation_t *imp,
  1551                          pixman_op_t              op,
  1552                          comp4_t *                dest,
  1553                          const comp4_t *          src,
  1554                          const comp4_t *          mask,
  1555                          int                      width)
  1557     combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP);
  1560 static void
  1561 combine_conjoint_atop_reverse_u (pixman_implementation_t *imp,
  1562                                  pixman_op_t              op,
  1563                                  comp4_t *                dest,
  1564                                  const comp4_t *          src,
  1565                                  const comp4_t *          mask,
  1566                                  int                      width)
  1568     combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP);
  1571 static void
  1572 combine_conjoint_xor_u (pixman_implementation_t *imp,
  1573                         pixman_op_t              op,
  1574                         comp4_t *                dest,
  1575                         const comp4_t *          src,
  1576                         const comp4_t *          mask,
  1577                         int                      width)
  1579     combine_conjoint_general_u (dest, src, mask, width, COMBINE_XOR);
  1582 /************************************************************************/
  1583 /*********************** Per Channel functions **************************/
  1584 /************************************************************************/
  1586 static void
  1587 combine_clear_ca (pixman_implementation_t *imp,
  1588                   pixman_op_t              op,
  1589                   comp4_t *                dest,
  1590                   const comp4_t *          src,
  1591                   const comp4_t *          mask,
  1592                   int                      width)
  1594     memset (dest, 0, width * sizeof(comp4_t));
  1597 static void
  1598 combine_src_ca (pixman_implementation_t *imp,
  1599                 pixman_op_t              op,
  1600                 comp4_t *                dest,
  1601                 const comp4_t *          src,
  1602                 const comp4_t *          mask,
  1603                 int                      width)
  1605     int i;
  1607     for (i = 0; i < width; ++i)
  1609 	comp4_t s = *(src + i);
  1610 	comp4_t m = *(mask + i);
  1612 	combine_mask_value_ca (&s, &m);
  1614 	*(dest + i) = s;
  1618 static void
  1619 combine_over_ca (pixman_implementation_t *imp,
  1620                  pixman_op_t              op,
  1621                  comp4_t *                dest,
  1622                  const comp4_t *          src,
  1623                  const comp4_t *          mask,
  1624                  int                      width)
  1626     int i;
  1628     for (i = 0; i < width; ++i)
  1630 	comp4_t s = *(src + i);
  1631 	comp4_t m = *(mask + i);
  1632 	comp4_t a;
  1634 	combine_mask_ca (&s, &m);
  1636 	a = ~m;
  1637 	if (a)
  1639 	    comp4_t d = *(dest + i);
  1640 	    UNcx4_MUL_UNcx4_ADD_UNcx4 (d, a, s);
  1641 	    s = d;
  1644 	*(dest + i) = s;
  1648 static void
  1649 combine_over_reverse_ca (pixman_implementation_t *imp,
  1650                          pixman_op_t              op,
  1651                          comp4_t *                dest,
  1652                          const comp4_t *          src,
  1653                          const comp4_t *          mask,
  1654                          int                      width)
  1656     int i;
  1658     for (i = 0; i < width; ++i)
  1660 	comp4_t d = *(dest + i);
  1661 	comp4_t a = ~d >> A_SHIFT;
  1663 	if (a)
  1665 	    comp4_t s = *(src + i);
  1666 	    comp4_t m = *(mask + i);
  1668 	    UNcx4_MUL_UNcx4 (s, m);
  1669 	    UNcx4_MUL_UNc_ADD_UNcx4 (s, a, d);
  1671 	    *(dest + i) = s;
  1676 static void
  1677 combine_in_ca (pixman_implementation_t *imp,
  1678                pixman_op_t              op,
  1679                comp4_t *                dest,
  1680                const comp4_t *          src,
  1681                const comp4_t *          mask,
  1682                int                      width)
  1684     int i;
  1686     for (i = 0; i < width; ++i)
  1688 	comp4_t d = *(dest + i);
  1689 	comp2_t a = d >> A_SHIFT;
  1690 	comp4_t s = 0;
  1692 	if (a)
  1694 	    comp4_t m = *(mask + i);
  1696 	    s = *(src + i);
  1697 	    combine_mask_value_ca (&s, &m);
  1699 	    if (a != MASK)
  1700 		UNcx4_MUL_UNc (s, a);
  1703 	*(dest + i) = s;
  1707 static void
  1708 combine_in_reverse_ca (pixman_implementation_t *imp,
  1709                        pixman_op_t              op,
  1710                        comp4_t *                dest,
  1711                        const comp4_t *          src,
  1712                        const comp4_t *          mask,
  1713                        int                      width)
  1715     int i;
  1717     for (i = 0; i < width; ++i)
  1719 	comp4_t s = *(src + i);
  1720 	comp4_t m = *(mask + i);
  1721 	comp4_t a;
  1723 	combine_mask_alpha_ca (&s, &m);
  1725 	a = m;
  1726 	if (a != ~0)
  1728 	    comp4_t d = 0;
  1730 	    if (a)
  1732 		d = *(dest + i);
  1733 		UNcx4_MUL_UNcx4 (d, a);
  1736 	    *(dest + i) = d;
  1741 static void
  1742 combine_out_ca (pixman_implementation_t *imp,
  1743                 pixman_op_t              op,
  1744                 comp4_t *                dest,
  1745                 const comp4_t *          src,
  1746                 const comp4_t *          mask,
  1747                 int                      width)
  1749     int i;
  1751     for (i = 0; i < width; ++i)
  1753 	comp4_t d = *(dest + i);
  1754 	comp2_t a = ~d >> A_SHIFT;
  1755 	comp4_t s = 0;
  1757 	if (a)
  1759 	    comp4_t m = *(mask + i);
  1761 	    s = *(src + i);
  1762 	    combine_mask_value_ca (&s, &m);
  1764 	    if (a != MASK)
  1765 		UNcx4_MUL_UNc (s, a);
  1768 	*(dest + i) = s;
  1772 static void
  1773 combine_out_reverse_ca (pixman_implementation_t *imp,
  1774                         pixman_op_t              op,
  1775                         comp4_t *                dest,
  1776                         const comp4_t *          src,
  1777                         const comp4_t *          mask,
  1778                         int                      width)
  1780     int i;
  1782     for (i = 0; i < width; ++i)
  1784 	comp4_t s = *(src + i);
  1785 	comp4_t m = *(mask + i);
  1786 	comp4_t a;
  1788 	combine_mask_alpha_ca (&s, &m);
  1790 	a = ~m;
  1791 	if (a != ~0)
  1793 	    comp4_t d = 0;
  1795 	    if (a)
  1797 		d = *(dest + i);
  1798 		UNcx4_MUL_UNcx4 (d, a);
  1801 	    *(dest + i) = d;
  1806 static void
  1807 combine_atop_ca (pixman_implementation_t *imp,
  1808                  pixman_op_t              op,
  1809                  comp4_t *                dest,
  1810                  const comp4_t *          src,
  1811                  const comp4_t *          mask,
  1812                  int                      width)
  1814     int i;
  1816     for (i = 0; i < width; ++i)
  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;
  1824 	combine_mask_ca (&s, &m);
  1826 	ad = ~m;
  1828 	UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (d, ad, s, as);
  1830 	*(dest + i) = d;
  1834 static void
  1835 combine_atop_reverse_ca (pixman_implementation_t *imp,
  1836                          pixman_op_t              op,
  1837                          comp4_t *                dest,
  1838                          const comp4_t *          src,
  1839                          const comp4_t *          mask,
  1840                          int                      width)
  1842     int i;
  1844     for (i = 0; i < width; ++i)
  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;
  1852 	combine_mask_ca (&s, &m);
  1854 	ad = m;
  1856 	UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (d, ad, s, as);
  1858 	*(dest + i) = d;
  1862 static void
  1863 combine_xor_ca (pixman_implementation_t *imp,
  1864                 pixman_op_t              op,
  1865                 comp4_t *                dest,
  1866                 const comp4_t *          src,
  1867                 const comp4_t *          mask,
  1868                 int                      width)
  1870     int i;
  1872     for (i = 0; i < width; ++i)
  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;
  1880 	combine_mask_ca (&s, &m);
  1882 	ad = ~m;
  1884 	UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (d, ad, s, as);
  1886 	*(dest + i) = d;
  1890 static void
  1891 combine_add_ca (pixman_implementation_t *imp,
  1892                 pixman_op_t              op,
  1893                 comp4_t *                dest,
  1894                 const comp4_t *          src,
  1895                 const comp4_t *          mask,
  1896                 int                      width)
  1898     int i;
  1900     for (i = 0; i < width; ++i)
  1902 	comp4_t s = *(src + i);
  1903 	comp4_t m = *(mask + i);
  1904 	comp4_t d = *(dest + i);
  1906 	combine_mask_value_ca (&s, &m);
  1908 	UNcx4_ADD_UNcx4 (d, s);
  1910 	*(dest + i) = d;
  1914 static void
  1915 combine_saturate_ca (pixman_implementation_t *imp,
  1916                      pixman_op_t              op,
  1917                      comp4_t *                dest,
  1918                      const comp4_t *          src,
  1919                      const comp4_t *          mask,
  1920                      int                      width)
  1922     int i;
  1924     for (i = 0; i < width; ++i)
  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;
  1931 	d = *(dest + i);
  1932 	s = *(src + i);
  1933 	m = *(mask + i);
  1935 	combine_mask_ca (&s, &m);
  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;
  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);
  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);
  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);
  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);
  1963 	*(dest + i) = m | n | o | p;
  1967 static void
  1968 combine_disjoint_general_ca (comp4_t *      dest,
  1969                              const comp4_t *src,
  1970                              const comp4_t *mask,
  1971                              int            width,
  1972                              comp1_t        combine)
  1974     int i;
  1976     for (i = 0; i < width; ++i)
  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;
  1985 	s = *(src + i);
  1986 	m = *(mask + i);
  1987 	d = *(dest + i);
  1988 	da = d >> A_SHIFT;
  1990 	combine_mask_ca (&s, &m);
  1992 	sa = m;
  1994 	switch (combine & COMBINE_A)
  1996 	default:
  1997 	    Fa = 0;
  1998 	    break;
  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;
  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;
  2016 	case COMBINE_A:
  2017 	    Fa = ~0;
  2018 	    break;
  2021 	switch (combine & COMBINE_B)
  2023 	default:
  2024 	    Fb = 0;
  2025 	    break;
  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;
  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;
  2043 	case COMBINE_B:
  2044 	    Fb = ~0;
  2045 	    break;
  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);
  2052 	s = m | n | o | p;
  2054 	*(dest + i) = s;
  2058 static void
  2059 combine_disjoint_over_ca (pixman_implementation_t *imp,
  2060                           pixman_op_t              op,
  2061                           comp4_t *                dest,
  2062                           const comp4_t *          src,
  2063                           const comp4_t *          mask,
  2064                           int                      width)
  2066     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER);
  2069 static void
  2070 combine_disjoint_in_ca (pixman_implementation_t *imp,
  2071                         pixman_op_t              op,
  2072                         comp4_t *                dest,
  2073                         const comp4_t *          src,
  2074                         const comp4_t *          mask,
  2075                         int                      width)
  2077     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_IN);
  2080 static void
  2081 combine_disjoint_in_reverse_ca (pixman_implementation_t *imp,
  2082                                 pixman_op_t              op,
  2083                                 comp4_t *                dest,
  2084                                 const comp4_t *          src,
  2085                                 const comp4_t *          mask,
  2086                                 int                      width)
  2088     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_IN);
  2091 static void
  2092 combine_disjoint_out_ca (pixman_implementation_t *imp,
  2093                          pixman_op_t              op,
  2094                          comp4_t *                dest,
  2095                          const comp4_t *          src,
  2096                          const comp4_t *          mask,
  2097                          int                      width)
  2099     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT);
  2102 static void
  2103 combine_disjoint_out_reverse_ca (pixman_implementation_t *imp,
  2104                                  pixman_op_t              op,
  2105                                  comp4_t *                dest,
  2106                                  const comp4_t *          src,
  2107                                  const comp4_t *          mask,
  2108                                  int                      width)
  2110     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT);
  2113 static void
  2114 combine_disjoint_atop_ca (pixman_implementation_t *imp,
  2115                           pixman_op_t              op,
  2116                           comp4_t *                dest,
  2117                           const comp4_t *          src,
  2118                           const comp4_t *          mask,
  2119                           int                      width)
  2121     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP);
  2124 static void
  2125 combine_disjoint_atop_reverse_ca (pixman_implementation_t *imp,
  2126                                   pixman_op_t              op,
  2127                                   comp4_t *                dest,
  2128                                   const comp4_t *          src,
  2129                                   const comp4_t *          mask,
  2130                                   int                      width)
  2132     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP);
  2135 static void
  2136 combine_disjoint_xor_ca (pixman_implementation_t *imp,
  2137                          pixman_op_t              op,
  2138                          comp4_t *                dest,
  2139                          const comp4_t *          src,
  2140                          const comp4_t *          mask,
  2141                          int                      width)
  2143     combine_disjoint_general_ca (dest, src, mask, width, COMBINE_XOR);
  2146 static void
  2147 combine_conjoint_general_ca (comp4_t *      dest,
  2148                              const comp4_t *src,
  2149                              const comp4_t *mask,
  2150                              int            width,
  2151                              comp1_t        combine)
  2153     int i;
  2155     for (i = 0; i < width; ++i)
  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;
  2164 	s = *(src + i);
  2165 	m = *(mask + i);
  2166 	d = *(dest + i);
  2167 	da = d >> A_SHIFT;
  2169 	combine_mask_ca (&s, &m);
  2171 	sa = m;
  2173 	switch (combine & COMBINE_A)
  2175 	default:
  2176 	    Fa = 0;
  2177 	    break;
  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;
  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;
  2195 	case COMBINE_A:
  2196 	    Fa = ~0;
  2197 	    break;
  2200 	switch (combine & COMBINE_B)
  2202 	default:
  2203 	    Fb = 0;
  2204 	    break;
  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;
  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;
  2222 	case COMBINE_B:
  2223 	    Fb = ~0;
  2224 	    break;
  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);
  2231 	s = m | n | o | p;
  2233 	*(dest + i) = s;
  2237 static void
  2238 combine_conjoint_over_ca (pixman_implementation_t *imp,
  2239                           pixman_op_t              op,
  2240                           comp4_t *                dest,
  2241                           const comp4_t *          src,
  2242                           const comp4_t *          mask,
  2243                           int                      width)
  2245     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER);
  2248 static void
  2249 combine_conjoint_over_reverse_ca (pixman_implementation_t *imp,
  2250                                   pixman_op_t              op,
  2251                                   comp4_t *                dest,
  2252                                   const comp4_t *          src,
  2253                                   const comp4_t *          mask,
  2254                                   int                      width)
  2256     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OVER);
  2259 static void
  2260 combine_conjoint_in_ca (pixman_implementation_t *imp,
  2261                         pixman_op_t              op,
  2262                         comp4_t *                dest,
  2263                         const comp4_t *          src,
  2264                         const comp4_t *          mask,
  2265                         int                      width)
  2267     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_IN);
  2270 static void
  2271 combine_conjoint_in_reverse_ca (pixman_implementation_t *imp,
  2272                                 pixman_op_t              op,
  2273                                 comp4_t *                dest,
  2274                                 const comp4_t *          src,
  2275                                 const comp4_t *          mask,
  2276                                 int                      width)
  2278     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_IN);
  2281 static void
  2282 combine_conjoint_out_ca (pixman_implementation_t *imp,
  2283                          pixman_op_t              op,
  2284                          comp4_t *                dest,
  2285                          const comp4_t *          src,
  2286                          const comp4_t *          mask,
  2287                          int                      width)
  2289     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT);
  2292 static void
  2293 combine_conjoint_out_reverse_ca (pixman_implementation_t *imp,
  2294                                  pixman_op_t              op,
  2295                                  comp4_t *                dest,
  2296                                  const comp4_t *          src,
  2297                                  const comp4_t *          mask,
  2298                                  int                      width)
  2300     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT);
  2303 static void
  2304 combine_conjoint_atop_ca (pixman_implementation_t *imp,
  2305                           pixman_op_t              op,
  2306                           comp4_t *                dest,
  2307                           const comp4_t *          src,
  2308                           const comp4_t *          mask,
  2309                           int                      width)
  2311     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP);
  2314 static void
  2315 combine_conjoint_atop_reverse_ca (pixman_implementation_t *imp,
  2316                                   pixman_op_t              op,
  2317                                   comp4_t *                dest,
  2318                                   const comp4_t *          src,
  2319                                   const comp4_t *          mask,
  2320                                   int                      width)
  2322     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP);
  2325 static void
  2326 combine_conjoint_xor_ca (pixman_implementation_t *imp,
  2327                          pixman_op_t              op,
  2328                          comp4_t *                dest,
  2329                          const comp4_t *          src,
  2330                          const comp4_t *          mask,
  2331                          int                      width)
  2333     combine_conjoint_general_ca (dest, src, mask, width, COMBINE_XOR);
  2336 void
  2337 _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
  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;
  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;
  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;
  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;
  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;
  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;
  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;
  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;
  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;

mercurial