tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pixman-combine-float.c (32665B)


      1 /* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
      2 /*
      3 * Copyright © 2010, 2012 Soren Sandmann Pedersen
      4 * Copyright © 2010, 2012 Red Hat, Inc.
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a
      7 * copy of this software and associated documentation files (the "Software"),
      8 * to deal in the Software without restriction, including without limitation
      9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10 * and/or sell copies of the Software, and to permit persons to whom the
     11 * Software is furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice (including the next
     14 * paragraph) shall be included in all copies or substantial portions of the
     15 * Software.
     16 *
     17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     23 * DEALINGS IN THE SOFTWARE.
     24 *
     25 * Author: Soren Sandmann Pedersen (sandmann@cs.au.dk)
     26 */
     27 
     28 #ifdef HAVE_CONFIG_H
     29 #include <pixman-config.h>
     30 #endif
     31 
     32 #include <math.h>
     33 #include <string.h>
     34 #include <float.h>
     35 
     36 #include "pixman-private.h"
     37 #include "pixman-combine-float.h"
     38 
     39 /* Workaround for http://gcc.gnu.org/PR54965 */
     40 /* GCC 4.6 has problems with force_inline, so just use normal inline instead */
     41 #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 6)
     42 #undef force_inline
     43 #define force_inline __inline__
     44 #endif
     45 
     46 typedef float (* combine_channel_t) (float sa, float s, float da, float d);
     47 
     48 static force_inline void
     49 combine_inner (pixman_bool_t component,
     50        float *dest, const float *src, const float *mask, int n_pixels,
     51        combine_channel_t combine_a, combine_channel_t combine_c)
     52 {
     53    int i;
     54 
     55    if (!mask)
     56    {
     57 for (i = 0; i < 4 * n_pixels; i += 4)
     58 {
     59     float sa = src[i + 0];
     60     float sr = src[i + 1];
     61     float sg = src[i + 2];
     62     float sb = src[i + 3];
     63     
     64     float da = dest[i + 0];
     65     float dr = dest[i + 1];
     66     float dg = dest[i + 2];
     67     float db = dest[i + 3];					
     68     
     69     dest[i + 0] = combine_a (sa, sa, da, da);
     70     dest[i + 1] = combine_c (sa, sr, da, dr);
     71     dest[i + 2] = combine_c (sa, sg, da, dg);
     72     dest[i + 3] = combine_c (sa, sb, da, db);
     73 }
     74    }
     75    else
     76    {
     77 for (i = 0; i < 4 * n_pixels; i += 4)
     78 {
     79     float sa, sr, sg, sb;
     80     float ma, mr, mg, mb;
     81     float da, dr, dg, db;
     82     
     83     sa = src[i + 0];
     84     sr = src[i + 1];
     85     sg = src[i + 2];
     86     sb = src[i + 3];
     87     
     88     if (component)
     89     {
     90 	ma = mask[i + 0];
     91 	mr = mask[i + 1];
     92 	mg = mask[i + 2];
     93 	mb = mask[i + 3];
     94 
     95 	sr *= mr;
     96 	sg *= mg;
     97 	sb *= mb;
     98 
     99 	ma *= sa;
    100 	mr *= sa;
    101 	mg *= sa;
    102 	mb *= sa;
    103 	
    104 	sa = ma;
    105     }
    106     else
    107     {
    108 	ma = mask[i + 0];
    109 
    110 	sa *= ma;
    111 	sr *= ma;
    112 	sg *= ma;
    113 	sb *= ma;
    114 
    115 	ma = mr = mg = mb = sa;
    116     }
    117     
    118     da = dest[i + 0];
    119     dr = dest[i + 1];
    120     dg = dest[i + 2];
    121     db = dest[i + 3];
    122     
    123     dest[i + 0] = combine_a (ma, sa, da, da);
    124     dest[i + 1] = combine_c (mr, sr, da, dr);
    125     dest[i + 2] = combine_c (mg, sg, da, dg);
    126     dest[i + 3] = combine_c (mb, sb, da, db);
    127 }
    128    }
    129 }
    130 
    131 #define MAKE_COMBINER(name, component, combine_a, combine_c)		\
    132    static void								\
    133    combine_ ## name ## _float (pixman_implementation_t *imp,		\
    134 			pixman_op_t              op,		\
    135 			float                   *dest,		\
    136 			const float             *src,		\
    137 			const float             *mask,		\
    138 			int		         n_pixels)	\
    139    {									\
    140 combine_inner (component, dest, src, mask, n_pixels,		\
    141 	       combine_a, combine_c);				\
    142    }
    143 
    144 #define MAKE_COMBINERS(name, combine_a, combine_c)			\
    145    MAKE_COMBINER(name ## _ca, TRUE, combine_a, combine_c)		\
    146    MAKE_COMBINER(name ## _u, FALSE, combine_a, combine_c)
    147 
    148 
    149 /*
    150 * Porter/Duff operators
    151 */
    152 
    153 #define CLAMP(f)					\
    154    (((f) < 0)? 0 : (((f) > 1.0) ? 1.0 : (f)))
    155 
    156 static force_inline float
    157 get_factor (combine_factor_t factor, float sa, float da)
    158 {
    159    float f = -1;
    160 
    161    switch (factor)
    162    {
    163    case ZERO:
    164 f = 0.0f;
    165 break;
    166 
    167    case ONE:
    168 f = 1.0f;
    169 break;
    170 
    171    case SRC_ALPHA:
    172 f = sa;
    173 break;
    174 
    175    case DEST_ALPHA:
    176 f = da;
    177 break;
    178 
    179    case INV_SA:
    180 f = 1 - sa;
    181 break;
    182 
    183    case INV_DA:
    184 f = 1 - da;
    185 break;
    186 
    187    case SA_OVER_DA:
    188 if (FLOAT_IS_ZERO (da))
    189     f = 1.0f;
    190 else
    191     f = CLAMP (sa / da);
    192 break;
    193 
    194    case DA_OVER_SA:
    195 if (FLOAT_IS_ZERO (sa))
    196     f = 1.0f;
    197 else
    198     f = CLAMP (da / sa);
    199 break;
    200 
    201    case INV_SA_OVER_DA:
    202 if (FLOAT_IS_ZERO (da))
    203     f = 1.0f;
    204 else
    205     f = CLAMP ((1.0f - sa) / da);
    206 break;
    207 
    208    case INV_DA_OVER_SA:
    209 if (FLOAT_IS_ZERO (sa))
    210     f = 1.0f;
    211 else
    212     f = CLAMP ((1.0f - da) / sa);
    213 break;
    214 
    215    case ONE_MINUS_SA_OVER_DA:
    216 if (FLOAT_IS_ZERO (da))
    217     f = 0.0f;
    218 else
    219     f = CLAMP (1.0f - sa / da);
    220 break;
    221 
    222    case ONE_MINUS_DA_OVER_SA:
    223 if (FLOAT_IS_ZERO (sa))
    224     f = 0.0f;
    225 else
    226     f = CLAMP (1.0f - da / sa);
    227 break;
    228 
    229    case ONE_MINUS_INV_DA_OVER_SA:
    230 if (FLOAT_IS_ZERO (sa))
    231     f = 0.0f;
    232 else
    233     f = CLAMP (1.0f - (1.0f - da) / sa);
    234 break;
    235 
    236    case ONE_MINUS_INV_SA_OVER_DA:
    237 if (FLOAT_IS_ZERO (da))
    238     f = 0.0f;
    239 else
    240     f = CLAMP (1.0f - (1.0f - sa) / da);
    241 break;
    242    }
    243 
    244    return f;
    245 }
    246 
    247 #define MAKE_PD_COMBINERS(name, a, b)					\
    248    static float							\
    249    pd_combine_ ## name (float sa, float s, float da, float d)		\
    250    {									\
    251 const float fa = get_factor (a, sa, da);			\
    252 const float fb = get_factor (b, sa, da);			\
    253 								\
    254 return MIN (1.0f, s * fa + d * fb);				\
    255    }									\
    256    									\
    257    MAKE_COMBINERS(name, pd_combine_ ## name, pd_combine_ ## name)
    258 
    259 MAKE_PD_COMBINERS (clear,			ZERO,				ZERO)
    260 MAKE_PD_COMBINERS (src,				ONE,				ZERO)
    261 MAKE_PD_COMBINERS (dst,				ZERO,				ONE)
    262 MAKE_PD_COMBINERS (over,			ONE,				INV_SA)
    263 MAKE_PD_COMBINERS (over_reverse,		INV_DA,				ONE)
    264 MAKE_PD_COMBINERS (in,				DEST_ALPHA,			ZERO)
    265 MAKE_PD_COMBINERS (in_reverse,			ZERO,				SRC_ALPHA)
    266 MAKE_PD_COMBINERS (out,				INV_DA,				ZERO)
    267 MAKE_PD_COMBINERS (out_reverse,			ZERO,				INV_SA)
    268 MAKE_PD_COMBINERS (atop,			DEST_ALPHA,			INV_SA)
    269 MAKE_PD_COMBINERS (atop_reverse,		INV_DA,				SRC_ALPHA)
    270 MAKE_PD_COMBINERS (xor,				INV_DA,				INV_SA)
    271 MAKE_PD_COMBINERS (add,				ONE,				ONE)
    272 
    273 MAKE_PD_COMBINERS (saturate,			INV_DA_OVER_SA,			ONE)
    274 
    275 MAKE_PD_COMBINERS (disjoint_clear,		ZERO,				ZERO)
    276 MAKE_PD_COMBINERS (disjoint_src,		ONE,				ZERO)
    277 MAKE_PD_COMBINERS (disjoint_dst,		ZERO,				ONE)
    278 MAKE_PD_COMBINERS (disjoint_over,		ONE,				INV_SA_OVER_DA)
    279 MAKE_PD_COMBINERS (disjoint_over_reverse,	INV_DA_OVER_SA,			ONE)
    280 MAKE_PD_COMBINERS (disjoint_in,			ONE_MINUS_INV_DA_OVER_SA,	ZERO)
    281 MAKE_PD_COMBINERS (disjoint_in_reverse,		ZERO,				ONE_MINUS_INV_SA_OVER_DA)
    282 MAKE_PD_COMBINERS (disjoint_out,		INV_DA_OVER_SA,			ZERO)
    283 MAKE_PD_COMBINERS (disjoint_out_reverse,	ZERO,				INV_SA_OVER_DA)
    284 MAKE_PD_COMBINERS (disjoint_atop,		ONE_MINUS_INV_DA_OVER_SA,	INV_SA_OVER_DA)
    285 MAKE_PD_COMBINERS (disjoint_atop_reverse,	INV_DA_OVER_SA,			ONE_MINUS_INV_SA_OVER_DA)
    286 MAKE_PD_COMBINERS (disjoint_xor,		INV_DA_OVER_SA,			INV_SA_OVER_DA)
    287 
    288 MAKE_PD_COMBINERS (conjoint_clear,		ZERO,				ZERO)
    289 MAKE_PD_COMBINERS (conjoint_src,		ONE,				ZERO)
    290 MAKE_PD_COMBINERS (conjoint_dst,		ZERO,				ONE)
    291 MAKE_PD_COMBINERS (conjoint_over,		ONE,				ONE_MINUS_SA_OVER_DA)
    292 MAKE_PD_COMBINERS (conjoint_over_reverse,	ONE_MINUS_DA_OVER_SA,		ONE)
    293 MAKE_PD_COMBINERS (conjoint_in,			DA_OVER_SA,			ZERO)
    294 MAKE_PD_COMBINERS (conjoint_in_reverse,		ZERO,				SA_OVER_DA)
    295 MAKE_PD_COMBINERS (conjoint_out,		ONE_MINUS_DA_OVER_SA,		ZERO)
    296 MAKE_PD_COMBINERS (conjoint_out_reverse,	ZERO,				ONE_MINUS_SA_OVER_DA)
    297 MAKE_PD_COMBINERS (conjoint_atop,		DA_OVER_SA,			ONE_MINUS_SA_OVER_DA)
    298 MAKE_PD_COMBINERS (conjoint_atop_reverse,	ONE_MINUS_DA_OVER_SA,		SA_OVER_DA)
    299 MAKE_PD_COMBINERS (conjoint_xor,		ONE_MINUS_DA_OVER_SA,		ONE_MINUS_SA_OVER_DA)
    300 
    301 /*
    302 * PDF blend modes:
    303 *
    304 * The following blend modes have been taken from the PDF ISO 32000
    305 * specification, which at this point in time is available from
    306 *
    307 *     http://www.adobe.com/devnet/pdf/pdf_reference.html
    308 *
    309 * The specific documents of interest are the PDF spec itself:
    310 *
    311 *     http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf
    312 *
    313 * chapters 11.3.5 and 11.3.6 and a later supplement for Adobe Acrobat
    314 * 9.1 and Reader 9.1:
    315 *
    316 *     http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/adobe_supplement_iso32000_1.pdf
    317 *
    318 * that clarifies the specifications for blend modes ColorDodge and
    319 * ColorBurn.
    320 *
    321 * The formula for computing the final pixel color given in 11.3.6 is:
    322 *
    323 *     αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
    324 *
    325 * with B() is the blend function. When B(Cb, Cs) = Cs, this formula
    326 * reduces to the regular OVER operator.
    327 *
    328 * Cs and Cb are not premultiplied, so in our implementation we instead
    329 * use:
    330 *
    331 *     cr = (1 – αs) × cb  +  (1 – αb) × cs  +  αb × αs × B (cb/αb, cs/αs)
    332 *
    333 * where cr, cs, and cb are premultiplied colors, and where the
    334 *
    335 *     αb × αs × B(cb/αb, cs/αs)
    336 *
    337 * part is first arithmetically simplified under the assumption that αb
    338 * and αs are not 0, and then updated to produce a meaningful result when
    339 * they are.
    340 *
    341 * For all the blend mode operators, the alpha channel is given by
    342 *
    343 *     αr = αs + αb + αb × αs
    344 */
    345 
    346 #define MAKE_SEPARABLE_PDF_COMBINERS(name)				\
    347    static float							\
    348    combine_ ## name ## _a (float sa, float s, float da, float d)	\
    349    {									\
    350 return da + sa - da * sa;					\
    351    }									\
    352    									\
    353    static float							\
    354    combine_ ## name ## _c (float sa, float s, float da, float d)	\
    355    {									\
    356 float f = (1 - sa) * d + (1 - da) * s;				\
    357 								\
    358 return f + blend_ ## name (sa, s, da, d);			\
    359    }									\
    360    									\
    361    MAKE_COMBINERS (name, combine_ ## name ## _a, combine_ ## name ## _c)
    362 
    363 /*
    364 * Multiply
    365 *
    366 *      ad * as * B(d / ad, s / as)
    367 *    = ad * as * d/ad * s/as
    368 *    = d * s
    369 *
    370 */
    371 static force_inline float
    372 blend_multiply (float sa, float s, float da, float d)
    373 {
    374    return d * s;
    375 }
    376 
    377 /*
    378 * Screen
    379 *
    380 *      ad * as * B(d/ad, s/as)
    381 *    = ad * as * (d/ad + s/as - s/as * d/ad)
    382 *    = ad * s + as * d - s * d
    383 */
    384 static force_inline float
    385 blend_screen (float sa, float s, float da, float d)
    386 {
    387    return d * sa + s * da - s * d;
    388 }
    389 
    390 /*
    391 * Overlay
    392 *
    393 *     ad * as * B(d/ad, s/as)
    394 *   = ad * as * Hardlight (s, d)
    395 *   = if (d / ad < 0.5)
    396 *         as * ad * Multiply (s/as, 2 * d/ad)
    397 *     else
    398 *         as * ad * Screen (s/as, 2 * d / ad - 1)
    399 *   = if (d < 0.5 * ad)
    400 *         as * ad * s/as * 2 * d /ad
    401 *     else
    402 *         as * ad * (s/as + 2 * d / ad - 1 - s / as * (2 * d / ad - 1))
    403 *   = if (2 * d < ad)
    404 *         2 * s * d
    405 *     else
    406 *         ad * s + 2 * as * d - as * ad - ad * s * (2 * d / ad - 1)
    407 *   = if (2 * d < ad)
    408 *         2 * s * d
    409 *     else
    410 *         as * ad - 2 * (ad - d) * (as - s)
    411 */
    412 static force_inline float
    413 blend_overlay (float sa, float s, float da, float d)
    414 {
    415    if (2 * d < da)
    416 return 2 * s * d;
    417    else
    418 return sa * da - 2 * (da - d) * (sa - s);
    419 }
    420 
    421 /*
    422 * Darken
    423 *
    424 *     ad * as * B(d/ad, s/as)
    425 *   = ad * as * MIN(d/ad, s/as)
    426 *   = MIN (as * d, ad * s)
    427 */
    428 static force_inline float
    429 blend_darken (float sa, float s, float da, float d)
    430 {
    431    s = s * da;
    432    d = d * sa;
    433 
    434    if (s > d)
    435 return d;
    436    else
    437 return s;
    438 }
    439 
    440 /*
    441 * Lighten
    442 *
    443 *     ad * as * B(d/ad, s/as)
    444 *   = ad * as * MAX(d/ad, s/as)
    445 *   = MAX (as * d, ad * s)
    446 */
    447 static force_inline float
    448 blend_lighten (float sa, float s, float da, float d)
    449 {
    450    s = s * da;
    451    d = d * sa;
    452 
    453    if (s > d)
    454 return s;
    455    else
    456 return d;
    457 }
    458 
    459 /*
    460 * Color dodge
    461 *
    462 *     ad * as * B(d/ad, s/as)
    463 *   = if d/ad = 0
    464 *         ad * as * 0
    465 *     else if (d/ad >= (1 - s/as)
    466 *         ad * as * 1
    467 *     else
    468 *         ad * as * ((d/ad) / (1 - s/as))
    469 *   = if d = 0
    470 *         0
    471 *     elif as * d >= ad * (as - s)
    472 *         ad * as
    473 *     else
    474 *         as * (as * d / (as - s))
    475 *
    476 */
    477 static force_inline float
    478 blend_color_dodge (float sa, float s, float da, float d)
    479 {
    480    if (FLOAT_IS_ZERO (d))
    481 return 0.0f;
    482    else if (d * sa >= sa * da - s * da)
    483 return sa * da;
    484    else if (FLOAT_IS_ZERO (sa - s))
    485 return sa * da;
    486    else
    487 return sa * sa * d / (sa - s);
    488 }
    489 
    490 /*
    491 * Color burn
    492 *
    493 * We modify the first clause "if d = 1" to "if d >= 1" since with
    494 * premultiplied colors d > 1 can actually happen.
    495 *
    496 *     ad * as * B(d/ad, s/as)
    497 *   = if d/ad >= 1
    498 *         ad * as * 1
    499 *     elif (1 - d/ad) >= s/as
    500 *         ad * as * 0
    501 *     else
    502 *         ad * as * (1 - ((1 - d/ad) / (s/as)))
    503 *   = if d >= ad
    504 *         ad * as
    505 *     elif as * ad - as * d >= ad * s
    506 *         0
    507 *     else
    508 *         ad * as  - as * as * (ad - d) / s
    509 */
    510 static force_inline float
    511 blend_color_burn (float sa, float s, float da, float d)
    512 {
    513    if (d >= da)
    514 return sa * da;
    515    else if (sa * (da - d) >= s * da)
    516 return 0.0f;
    517    else if (FLOAT_IS_ZERO (s))
    518 return 0.0f;
    519    else
    520 return sa * (da - sa * (da - d) / s);
    521 }
    522 
    523 /*
    524 * Hard light
    525 *
    526 *     ad * as * B(d/ad, s/as)
    527 *   = if (s/as <= 0.5)
    528 *         ad * as * Multiply (d/ad, 2 * s/as)
    529 *     else
    530 *         ad * as * Screen (d/ad, 2 * s/as - 1)
    531 *   = if 2 * s <= as
    532 *         ad * as * d/ad * 2 * s / as
    533 *     else
    534 *         ad * as * (d/ad + (2 * s/as - 1) + d/ad * (2 * s/as - 1))
    535 *   = if 2 * s <= as
    536 *         2 * s * d
    537 *     else
    538 *         as * ad - 2 * (ad - d) * (as - s)
    539 */
    540 static force_inline float
    541 blend_hard_light (float sa, float s, float da, float d)
    542 {
    543    if (2 * s < sa)
    544 return 2 * s * d;
    545    else
    546 return sa * da - 2 * (da - d) * (sa - s);
    547 }
    548 
    549 /*
    550 * Soft light
    551 *
    552 *     ad * as * B(d/ad, s/as)
    553 *   = if (s/as <= 0.5)
    554 *         ad * as * (d/ad - (1 - 2 * s/as) * d/ad * (1 - d/ad))
    555 *     else if (d/ad <= 0.25)
    556 *         ad * as * (d/ad + (2 * s/as - 1) * ((((16 * d/ad - 12) * d/ad + 4) * d/ad) - d/ad))
    557 *     else
    558 *         ad * as * (d/ad + (2 * s/as - 1) * sqrt (d/ad))
    559 *   = if (2 * s <= as)
    560 *         d * as - d * (ad - d) * (as - 2 * s) / ad;
    561 *     else if (4 * d <= ad)
    562 *         (2 * s - as) * d * ((16 * d / ad - 12) * d / ad + 3);
    563 *     else
    564 *         d * as + (sqrt (d * ad) - d) * (2 * s - as);
    565 */
    566 static force_inline float
    567 blend_soft_light (float sa, float s, float da, float d)
    568 {
    569    if (2 * s <= sa)
    570    {
    571 if (FLOAT_IS_ZERO (da))
    572     return d * sa;
    573 else
    574     return d * sa - d * (da - d) * (sa - 2 * s) / da;
    575    }
    576    else
    577    {
    578 if (FLOAT_IS_ZERO (da))
    579 {
    580     return d * sa;
    581 }
    582 else
    583 {
    584     if (4 * d <= da)
    585 	return d * sa + (2 * s - sa) * d * ((16 * d / da - 12) * d / da + 3);
    586     else
    587 	return d * sa + (sqrtf (d * da) - d) * (2 * s - sa);
    588 }
    589    }
    590 }
    591 
    592 /*
    593 * Difference
    594 *
    595 *     ad * as * B(s/as, d/ad)
    596 *   = ad * as * abs (s/as - d/ad)
    597 *   = if (s/as <= d/ad)
    598 *         ad * as * (d/ad - s/as)
    599 *     else
    600 *         ad * as * (s/as - d/ad)
    601 *   = if (ad * s <= as * d)
    602 *        as * d - ad * s
    603 *     else
    604 *        ad * s - as * d
    605 */
    606 static force_inline float
    607 blend_difference (float sa, float s, float da, float d)
    608 {
    609    float dsa = d * sa;
    610    float sda = s * da;
    611 
    612    if (sda < dsa)
    613 return dsa - sda;
    614    else
    615 return sda - dsa;
    616 }
    617 
    618 /*
    619 * Exclusion
    620 *
    621 *     ad * as * B(s/as, d/ad)
    622 *   = ad * as * (d/ad + s/as - 2 * d/ad * s/as)
    623 *   = as * d + ad * s - 2 * s * d
    624 */
    625 static force_inline float
    626 blend_exclusion (float sa, float s, float da, float d)
    627 {
    628    return s * da + d * sa - 2 * d * s;
    629 }
    630 
    631 MAKE_SEPARABLE_PDF_COMBINERS (multiply)
    632 MAKE_SEPARABLE_PDF_COMBINERS (screen)
    633 MAKE_SEPARABLE_PDF_COMBINERS (overlay)
    634 MAKE_SEPARABLE_PDF_COMBINERS (darken)
    635 MAKE_SEPARABLE_PDF_COMBINERS (lighten)
    636 MAKE_SEPARABLE_PDF_COMBINERS (color_dodge)
    637 MAKE_SEPARABLE_PDF_COMBINERS (color_burn)
    638 MAKE_SEPARABLE_PDF_COMBINERS (hard_light)
    639 MAKE_SEPARABLE_PDF_COMBINERS (soft_light)
    640 MAKE_SEPARABLE_PDF_COMBINERS (difference)
    641 MAKE_SEPARABLE_PDF_COMBINERS (exclusion)
    642 
    643 /*
    644 * PDF nonseperable blend modes are implemented using the following functions
    645 * to operate in Hsl space, with Cmax, Cmid, Cmin referring to the max, mid
    646 * and min value of the red, green and blue components.
    647 *
    648 * LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue
    649 *
    650 * clip_color (C):
    651 *     l = LUM (C)
    652 *     min = Cmin
    653 *     max = Cmax
    654 *     if n < 0.0
    655 *         C = l + (((C – l) × l) ⁄ (l – min))
    656 *     if x > 1.0
    657 *         C = l + (((C – l) × (1 – l) ) ⁄ (max – l))
    658 *     return C
    659 *
    660 * set_lum (C, l):
    661 *     d = l – LUM (C)
    662 *     C += d
    663 *     return clip_color (C)
    664 *
    665 * SAT (C) = CH_MAX (C) - CH_MIN (C)
    666 *
    667 * set_sat (C, s):
    668 *     if Cmax > Cmin
    669 *         Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
    670 *         Cmax = s
    671 *     else
    672 *         Cmid = Cmax = 0.0
    673 *         Cmin = 0.0
    674 *     return C
    675 */
    676 
    677 /* For premultiplied colors, we need to know what happens when C is
    678 * multiplied by a real number. LUM and SAT are linear:
    679 *
    680 *     LUM (r × C) = r × LUM (C)	SAT (r * C) = r * SAT (C)
    681 *
    682 * If we extend clip_color with an extra argument a and change
    683 *
    684 *     if x >= 1.0
    685 *
    686 * into
    687 *
    688 *     if x >= a
    689 *
    690 * then clip_color is also linear:
    691 *
    692 *     r * clip_color (C, a) = clip_color (r * C, r * a);
    693 *
    694 * for positive r.
    695 *
    696 * Similarly, we can extend set_lum with an extra argument that is just passed
    697 * on to clip_color:
    698 *
    699 *       r * set_lum (C, l, a)
    700 *
    701 *     = r × clip_color (C + l - LUM (C), a)
    702 *
    703 *     = clip_color (r * C + r × l - r * LUM (C), r * a)
    704 *
    705 *     = set_lum (r * C, r * l, r * a)
    706 *
    707 * Finally, set_sat:
    708 *
    709 *       r * set_sat (C, s) = set_sat (x * C, r * s)
    710 *
    711 * The above holds for all non-zero x, because the x'es in the fraction for
    712 * C_mid cancel out. Specifically, it holds for x = r:
    713 *
    714 *       r * set_sat (C, s) = set_sat (r * C, r * s)
    715 *
    716 */
    717 typedef struct
    718 {
    719    float	r;
    720    float	g;
    721    float	b;
    722 } rgb_t;
    723 
    724 static force_inline float
    725 minf (float a, float b)
    726 {
    727    return a < b? a : b;
    728 }
    729 
    730 static force_inline float
    731 maxf (float a, float b)
    732 {
    733    return a > b? a : b;
    734 }
    735 
    736 static force_inline float
    737 channel_min (const rgb_t *c)
    738 {
    739    return minf (minf (c->r, c->g), c->b);
    740 }
    741 
    742 static force_inline float
    743 channel_max (const rgb_t *c)
    744 {
    745    return maxf (maxf (c->r, c->g), c->b);
    746 }
    747 
    748 static force_inline float
    749 get_lum (const rgb_t *c)
    750 {
    751    return c->r * 0.3f + c->g * 0.59f + c->b * 0.11f;
    752 }
    753 
    754 static force_inline float
    755 get_sat (const rgb_t *c)
    756 {
    757    return channel_max (c) - channel_min (c);
    758 }
    759 
    760 static void
    761 clip_color (rgb_t *color, float a)
    762 {
    763    float l = get_lum (color);
    764    float n = channel_min (color);
    765    float x = channel_max (color);
    766    float t;
    767 
    768    if (n < 0.0f)
    769    {
    770 t = l - n;
    771 if (FLOAT_IS_ZERO (t))
    772 {
    773     color->r = 0.0f;
    774     color->g = 0.0f;
    775     color->b = 0.0f;
    776 }
    777 else
    778 {
    779     color->r = l + (((color->r - l) * l) / t);
    780     color->g = l + (((color->g - l) * l) / t);
    781     color->b = l + (((color->b - l) * l) / t);
    782 }
    783    }
    784    if (x > a)
    785    {
    786 t = x - l;
    787 if (FLOAT_IS_ZERO (t))
    788 {
    789     color->r = a;
    790     color->g = a;
    791     color->b = a;
    792 }
    793 else
    794 {
    795     color->r = l + (((color->r - l) * (a - l) / t));
    796     color->g = l + (((color->g - l) * (a - l) / t));
    797     color->b = l + (((color->b - l) * (a - l) / t));
    798 }
    799    }
    800 }
    801 
    802 static void
    803 set_lum (rgb_t *color, float sa, float l)
    804 {
    805    float d = l - get_lum (color);
    806 
    807    color->r = color->r + d;
    808    color->g = color->g + d;
    809    color->b = color->b + d;
    810 
    811    clip_color (color, sa);
    812 }
    813 
    814 static void
    815 set_sat (rgb_t *src, float sat)
    816 {
    817    float *max, *mid, *min;
    818    float t;
    819 
    820    if (src->r > src->g)
    821    {
    822 if (src->r > src->b)
    823 {
    824     max = &(src->r);
    825 
    826     if (src->g > src->b)
    827     {
    828 	mid = &(src->g);
    829 	min = &(src->b);
    830     }
    831     else
    832     {
    833 	mid = &(src->b);
    834 	min = &(src->g);
    835     }
    836 }
    837 else
    838 {
    839     max = &(src->b);
    840     mid = &(src->r);
    841     min = &(src->g);
    842 }
    843    }
    844    else
    845    {
    846 if (src->r > src->b)
    847 {
    848     max = &(src->g);
    849     mid = &(src->r);
    850     min = &(src->b);
    851 }
    852 else
    853 {
    854     min = &(src->r);
    855 
    856     if (src->g > src->b)
    857     {
    858 	max = &(src->g);
    859 	mid = &(src->b);
    860     }
    861     else
    862     {
    863 	max = &(src->b);
    864 	mid = &(src->g);
    865     }
    866 }
    867    }
    868 
    869    t = *max - *min;
    870 
    871    if (FLOAT_IS_ZERO (t))
    872    {
    873 *mid = *max = 0.0f;
    874    }
    875    else
    876    {
    877 *mid = ((*mid - *min) * sat) / t;
    878 *max = sat;
    879    }
    880 
    881    *min = 0.0f;
    882 }
    883 
    884 /* Hue:
    885 *
    886 *       as * ad * B(s/as, d/as)
    887 *     = as * ad * set_lum (set_sat (s/as, SAT (d/ad)), LUM (d/ad), 1)
    888 *     = set_lum (set_sat (ad * s, as * SAT (d)), as * LUM (d), as * ad)
    889 *
    890 */
    891 static force_inline void
    892 blend_hsl_hue (rgb_t *res,
    893        const rgb_t *dest, float da,
    894        const rgb_t *src, float sa)
    895 {
    896    res->r = src->r * da;
    897    res->g = src->g * da;
    898    res->b = src->b * da;
    899 
    900    set_sat (res, get_sat (dest) * sa);
    901    set_lum (res, sa * da, get_lum (dest) * sa);
    902 }
    903 
    904 /* 
    905 * Saturation
    906 *
    907 *     as * ad * B(s/as, d/ad)
    908 *   = as * ad * set_lum (set_sat (d/ad, SAT (s/as)), LUM (d/ad), 1)
    909 *   = set_lum (as * ad * set_sat (d/ad, SAT (s/as)),
    910 *                                       as * LUM (d), as * ad)
    911 *   = set_lum (set_sat (as * d, ad * SAT (s), as * LUM (d), as * ad))
    912 */
    913 static force_inline void
    914 blend_hsl_saturation (rgb_t *res,
    915 	      const rgb_t *dest, float da,
    916 	      const rgb_t *src, float sa)
    917 {
    918    res->r = dest->r * sa;
    919    res->g = dest->g * sa;
    920    res->b = dest->b * sa;
    921 
    922    set_sat (res, get_sat (src) * da);
    923    set_lum (res, sa * da, get_lum (dest) * sa);
    924 }
    925 
    926 /* 
    927 * Color
    928 *
    929 *     as * ad * B(s/as, d/as)
    930 *   = as * ad * set_lum (s/as, LUM (d/ad), 1)
    931 *   = set_lum (s * ad, as * LUM (d), as * ad)
    932 */
    933 static force_inline void
    934 blend_hsl_color (rgb_t *res,
    935 	 const rgb_t *dest, float da,
    936 	 const rgb_t *src, float sa)
    937 {
    938    res->r = src->r * da;
    939    res->g = src->g * da;
    940    res->b = src->b * da;
    941 
    942    set_lum (res, sa * da, get_lum (dest) * sa);
    943 }
    944 
    945 /*
    946 * Luminosity
    947 *
    948 *     as * ad * B(s/as, d/ad)
    949 *   = as * ad * set_lum (d/ad, LUM (s/as), 1)
    950 *   = set_lum (as * d, ad * LUM (s), as * ad)
    951 */
    952 static force_inline void
    953 blend_hsl_luminosity (rgb_t *res,
    954 	      const rgb_t *dest, float da,
    955 	      const rgb_t *src, float sa)
    956 {
    957    res->r = dest->r * sa;
    958    res->g = dest->g * sa;
    959    res->b = dest->b * sa;
    960 
    961    set_lum (res, sa * da, get_lum (src) * da);
    962 }
    963 
    964 #define MAKE_NON_SEPARABLE_PDF_COMBINERS(name)				\
    965    static void								\
    966    combine_ ## name ## _u_float (pixman_implementation_t *imp,		\
    967 			  pixman_op_t              op,		\
    968 			  float                   *dest,	\
    969 			  const float             *src,		\
    970 			  const float             *mask,	\
    971 			  int		           n_pixels)	\
    972    {									\
    973    	int i;								\
    974 								\
    975 for (i = 0; i < 4 * n_pixels; i += 4)				\
    976 {								\
    977     float sa, da;						\
    978     rgb_t sc, dc, rc;						\
    979 								\
    980     sa = src[i + 0];						\
    981     sc.r = src[i + 1];						\
    982     sc.g = src[i + 2];						\
    983     sc.b = src[i + 3];						\
    984 								\
    985     da = dest[i + 0];						\
    986     dc.r = dest[i + 1];						\
    987     dc.g = dest[i + 2];						\
    988     dc.b = dest[i + 3];						\
    989 								\
    990     if (mask)							\
    991     {								\
    992 	float ma = mask[i + 0];					\
    993 								\
    994 	/* Component alpha is not supported for HSL modes */	\
    995 	sa *= ma;						\
    996 	sc.r *= ma;						\
    997 	sc.g *= ma;						\
    998 	sc.b *= ma;						\
    999     }								\
   1000 								\
   1001     blend_ ## name (&rc, &dc, da, &sc, sa);			\
   1002 								\
   1003     dest[i + 0] = sa + da - sa * da;				\
   1004     dest[i + 1] = (1 - sa) * dc.r + (1 - da) * sc.r + rc.r;	\
   1005     dest[i + 2] = (1 - sa) * dc.g + (1 - da) * sc.g + rc.g;	\
   1006     dest[i + 3] = (1 - sa) * dc.b + (1 - da) * sc.b + rc.b;	\
   1007 }								\
   1008    }
   1009 
   1010 MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_hue)
   1011 MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_saturation)
   1012 MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_color)
   1013 MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_luminosity)
   1014 
   1015 void
   1016 _pixman_setup_combiner_functions_float (pixman_implementation_t *imp)
   1017 {
   1018    /* Unified alpha */
   1019    imp->combine_float[PIXMAN_OP_CLEAR] = combine_clear_u_float;
   1020    imp->combine_float[PIXMAN_OP_SRC] = combine_src_u_float;
   1021    imp->combine_float[PIXMAN_OP_DST] = combine_dst_u_float;
   1022    imp->combine_float[PIXMAN_OP_OVER] = combine_over_u_float;
   1023    imp->combine_float[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u_float;
   1024    imp->combine_float[PIXMAN_OP_IN] = combine_in_u_float;
   1025    imp->combine_float[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_u_float;
   1026    imp->combine_float[PIXMAN_OP_OUT] = combine_out_u_float;
   1027    imp->combine_float[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_u_float;
   1028    imp->combine_float[PIXMAN_OP_ATOP] = combine_atop_u_float;
   1029    imp->combine_float[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u_float;
   1030    imp->combine_float[PIXMAN_OP_XOR] = combine_xor_u_float;
   1031    imp->combine_float[PIXMAN_OP_ADD] = combine_add_u_float;
   1032    imp->combine_float[PIXMAN_OP_SATURATE] = combine_saturate_u_float;
   1033 
   1034    /* Disjoint, unified */
   1035    imp->combine_float[PIXMAN_OP_DISJOINT_CLEAR] = combine_disjoint_clear_u_float;
   1036    imp->combine_float[PIXMAN_OP_DISJOINT_SRC] = combine_disjoint_src_u_float;
   1037    imp->combine_float[PIXMAN_OP_DISJOINT_DST] = combine_disjoint_dst_u_float;
   1038    imp->combine_float[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_u_float;
   1039    imp->combine_float[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_disjoint_over_reverse_u_float;
   1040    imp->combine_float[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_u_float;
   1041    imp->combine_float[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_u_float;
   1042    imp->combine_float[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_u_float;
   1043    imp->combine_float[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_u_float;
   1044    imp->combine_float[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_u_float;
   1045    imp->combine_float[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_u_float;
   1046    imp->combine_float[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_u_float;
   1047 
   1048    /* Conjoint, unified */
   1049    imp->combine_float[PIXMAN_OP_CONJOINT_CLEAR] = combine_conjoint_clear_u_float;
   1050    imp->combine_float[PIXMAN_OP_CONJOINT_SRC] = combine_conjoint_src_u_float;
   1051    imp->combine_float[PIXMAN_OP_CONJOINT_DST] = combine_conjoint_dst_u_float;
   1052    imp->combine_float[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_u_float;
   1053    imp->combine_float[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_u_float;
   1054    imp->combine_float[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_u_float;
   1055    imp->combine_float[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_u_float;
   1056    imp->combine_float[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_u_float;
   1057    imp->combine_float[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_u_float;
   1058    imp->combine_float[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_u_float;
   1059    imp->combine_float[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_u_float;
   1060    imp->combine_float[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_u_float;
   1061 
   1062    /* PDF operators, unified */
   1063    imp->combine_float[PIXMAN_OP_MULTIPLY] = combine_multiply_u_float;
   1064    imp->combine_float[PIXMAN_OP_SCREEN] = combine_screen_u_float;
   1065    imp->combine_float[PIXMAN_OP_OVERLAY] = combine_overlay_u_float;
   1066    imp->combine_float[PIXMAN_OP_DARKEN] = combine_darken_u_float;
   1067    imp->combine_float[PIXMAN_OP_LIGHTEN] = combine_lighten_u_float;
   1068    imp->combine_float[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_u_float;
   1069    imp->combine_float[PIXMAN_OP_COLOR_BURN] = combine_color_burn_u_float;
   1070    imp->combine_float[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u_float;
   1071    imp->combine_float[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_u_float;
   1072    imp->combine_float[PIXMAN_OP_DIFFERENCE] = combine_difference_u_float;
   1073    imp->combine_float[PIXMAN_OP_EXCLUSION] = combine_exclusion_u_float;
   1074 
   1075    imp->combine_float[PIXMAN_OP_HSL_HUE] = combine_hsl_hue_u_float;
   1076    imp->combine_float[PIXMAN_OP_HSL_SATURATION] = combine_hsl_saturation_u_float;
   1077    imp->combine_float[PIXMAN_OP_HSL_COLOR] = combine_hsl_color_u_float;
   1078    imp->combine_float[PIXMAN_OP_HSL_LUMINOSITY] = combine_hsl_luminosity_u_float;
   1079 
   1080    /* Component alpha combiners */
   1081    imp->combine_float_ca[PIXMAN_OP_CLEAR] = combine_clear_ca_float;
   1082    imp->combine_float_ca[PIXMAN_OP_SRC] = combine_src_ca_float;
   1083    imp->combine_float_ca[PIXMAN_OP_DST] = combine_dst_ca_float;
   1084    imp->combine_float_ca[PIXMAN_OP_OVER] = combine_over_ca_float;
   1085    imp->combine_float_ca[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_ca_float;
   1086    imp->combine_float_ca[PIXMAN_OP_IN] = combine_in_ca_float;
   1087    imp->combine_float_ca[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_ca_float;
   1088    imp->combine_float_ca[PIXMAN_OP_OUT] = combine_out_ca_float;
   1089    imp->combine_float_ca[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_ca_float;
   1090    imp->combine_float_ca[PIXMAN_OP_ATOP] = combine_atop_ca_float;
   1091    imp->combine_float_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca_float;
   1092    imp->combine_float_ca[PIXMAN_OP_XOR] = combine_xor_ca_float;
   1093    imp->combine_float_ca[PIXMAN_OP_ADD] = combine_add_ca_float;
   1094    imp->combine_float_ca[PIXMAN_OP_SATURATE] = combine_saturate_ca_float;
   1095 
   1096    /* Disjoint CA */
   1097    imp->combine_float_ca[PIXMAN_OP_DISJOINT_CLEAR] = combine_disjoint_clear_ca_float;
   1098    imp->combine_float_ca[PIXMAN_OP_DISJOINT_SRC] = combine_disjoint_src_ca_float;
   1099    imp->combine_float_ca[PIXMAN_OP_DISJOINT_DST] = combine_disjoint_dst_ca_float;
   1100    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_ca_float;
   1101    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_disjoint_over_reverse_ca_float;
   1102    imp->combine_float_ca[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_ca_float;
   1103    imp->combine_float_ca[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_ca_float;
   1104    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_ca_float;
   1105    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_ca_float;
   1106    imp->combine_float_ca[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_ca_float;
   1107    imp->combine_float_ca[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_ca_float;
   1108    imp->combine_float_ca[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_ca_float;
   1109 
   1110    /* Conjoint CA */
   1111    imp->combine_float_ca[PIXMAN_OP_CONJOINT_CLEAR] = combine_conjoint_clear_ca_float;
   1112    imp->combine_float_ca[PIXMAN_OP_CONJOINT_SRC] = combine_conjoint_src_ca_float;
   1113    imp->combine_float_ca[PIXMAN_OP_CONJOINT_DST] = combine_conjoint_dst_ca_float;
   1114    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_ca_float;
   1115    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_ca_float;
   1116    imp->combine_float_ca[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_ca_float;
   1117    imp->combine_float_ca[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_ca_float;
   1118    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_ca_float;
   1119    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_ca_float;
   1120    imp->combine_float_ca[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_ca_float;
   1121    imp->combine_float_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_ca_float;
   1122    imp->combine_float_ca[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_ca_float;
   1123 
   1124    /* PDF operators CA */
   1125    imp->combine_float_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca_float;
   1126    imp->combine_float_ca[PIXMAN_OP_SCREEN] = combine_screen_ca_float;
   1127    imp->combine_float_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca_float;
   1128    imp->combine_float_ca[PIXMAN_OP_DARKEN] = combine_darken_ca_float;
   1129    imp->combine_float_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca_float;
   1130    imp->combine_float_ca[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_ca_float;
   1131    imp->combine_float_ca[PIXMAN_OP_COLOR_BURN] = combine_color_burn_ca_float;
   1132    imp->combine_float_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca_float;
   1133    imp->combine_float_ca[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_ca_float;
   1134    imp->combine_float_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca_float;
   1135    imp->combine_float_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca_float;
   1136 
   1137    /* It is not clear that these make sense, so make them noops for now */
   1138    imp->combine_float_ca[PIXMAN_OP_HSL_HUE] = combine_dst_u_float;
   1139    imp->combine_float_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst_u_float;
   1140    imp->combine_float_ca[PIXMAN_OP_HSL_COLOR] = combine_dst_u_float;
   1141    imp->combine_float_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst_u_float;
   1142 }