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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/cairo/libpixman/src/pixman-combine-float.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1018 @@
     1.4 +/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
     1.5 +/*
     1.6 + * Copyright © 2010, 2012 Soren Sandmann Pedersen
     1.7 + * Copyright © 2010, 2012 Red Hat, Inc.
     1.8 + *
     1.9 + * Permission is hereby granted, free of charge, to any person obtaining a
    1.10 + * copy of this software and associated documentation files (the "Software"),
    1.11 + * to deal in the Software without restriction, including without limitation
    1.12 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    1.13 + * and/or sell copies of the Software, and to permit persons to whom the
    1.14 + * Software is furnished to do so, subject to the following conditions:
    1.15 + *
    1.16 + * The above copyright notice and this permission notice (including the next
    1.17 + * paragraph) shall be included in all copies or substantial portions of the
    1.18 + * Software.
    1.19 + *
    1.20 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    1.21 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    1.22 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
    1.23 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    1.24 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    1.25 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    1.26 + * DEALINGS IN THE SOFTWARE.
    1.27 + *
    1.28 + * Author: Soren Sandmann Pedersen (sandmann@cs.au.dk)
    1.29 + */
    1.30 +
    1.31 +#ifdef HAVE_CONFIG_H
    1.32 +#include <config.h>
    1.33 +#endif
    1.34 +
    1.35 +#include <math.h>
    1.36 +#include <string.h>
    1.37 +#include <float.h>
    1.38 +
    1.39 +#include "pixman-private.h"
    1.40 +
    1.41 +/* Workaround for http://gcc.gnu.org/PR54965 */
    1.42 +/* GCC 4.6 has problems with force_inline, so just use normal inline instead */
    1.43 +#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 6)
    1.44 +#undef force_inline
    1.45 +#define force_inline __inline__
    1.46 +#endif
    1.47 +
    1.48 +#define IS_ZERO(f)     (-FLT_MIN < (f) && (f) < FLT_MIN)
    1.49 +
    1.50 +typedef float (* combine_channel_t) (float sa, float s, float da, float d);
    1.51 +
    1.52 +static force_inline void
    1.53 +combine_inner (pixman_bool_t component,
    1.54 +	       float *dest, const float *src, const float *mask, int n_pixels,
    1.55 +	       combine_channel_t combine_a, combine_channel_t combine_c)
    1.56 +{
    1.57 +    int i;
    1.58 +
    1.59 +    if (!mask)
    1.60 +    {
    1.61 +	for (i = 0; i < 4 * n_pixels; i += 4)
    1.62 +	{
    1.63 +	    float sa = src[i + 0];
    1.64 +	    float sr = src[i + 1];
    1.65 +	    float sg = src[i + 2];
    1.66 +	    float sb = src[i + 3];
    1.67 +	    
    1.68 +	    float da = dest[i + 0];
    1.69 +	    float dr = dest[i + 1];
    1.70 +	    float dg = dest[i + 2];
    1.71 +	    float db = dest[i + 3];					
    1.72 +	    
    1.73 +	    dest[i + 0] = combine_a (sa, sa, da, da);
    1.74 +	    dest[i + 1] = combine_c (sa, sr, da, dr);
    1.75 +	    dest[i + 2] = combine_c (sa, sg, da, dg);
    1.76 +	    dest[i + 3] = combine_c (sa, sb, da, db);
    1.77 +	}
    1.78 +    }
    1.79 +    else
    1.80 +    {
    1.81 +	for (i = 0; i < 4 * n_pixels; i += 4)
    1.82 +	{
    1.83 +	    float sa, sr, sg, sb;
    1.84 +	    float ma, mr, mg, mb;
    1.85 +	    float da, dr, dg, db;
    1.86 +	    
    1.87 +	    sa = src[i + 0];
    1.88 +	    sr = src[i + 1];
    1.89 +	    sg = src[i + 2];
    1.90 +	    sb = src[i + 3];
    1.91 +	    
    1.92 +	    if (component)
    1.93 +	    {
    1.94 +		ma = mask[i + 0];
    1.95 +		mr = mask[i + 1];
    1.96 +		mg = mask[i + 2];
    1.97 +		mb = mask[i + 3];
    1.98 +
    1.99 +		sr *= mr;
   1.100 +		sg *= mg;
   1.101 +		sb *= mb;
   1.102 +
   1.103 +		ma *= sa;
   1.104 +		mr *= sa;
   1.105 +		mg *= sa;
   1.106 +		mb *= sa;
   1.107 +		
   1.108 +		sa = ma;
   1.109 +	    }
   1.110 +	    else
   1.111 +	    {
   1.112 +		ma = mask[i + 0];
   1.113 +
   1.114 +		sa *= ma;
   1.115 +		sr *= ma;
   1.116 +		sg *= ma;
   1.117 +		sb *= ma;
   1.118 +
   1.119 +		ma = mr = mg = mb = sa;
   1.120 +	    }
   1.121 +	    
   1.122 +	    da = dest[i + 0];
   1.123 +	    dr = dest[i + 1];
   1.124 +	    dg = dest[i + 2];
   1.125 +	    db = dest[i + 3];
   1.126 +	    
   1.127 +	    dest[i + 0] = combine_a (ma, sa, da, da);
   1.128 +	    dest[i + 1] = combine_c (mr, sr, da, dr);
   1.129 +	    dest[i + 2] = combine_c (mg, sg, da, dg);
   1.130 +	    dest[i + 3] = combine_c (mb, sb, da, db);
   1.131 +	}
   1.132 +    }
   1.133 +}
   1.134 +
   1.135 +#define MAKE_COMBINER(name, component, combine_a, combine_c)		\
   1.136 +    static void								\
   1.137 +    combine_ ## name ## _float (pixman_implementation_t *imp,		\
   1.138 +				pixman_op_t              op,		\
   1.139 +				float                   *dest,		\
   1.140 +				const float             *src,		\
   1.141 +				const float             *mask,		\
   1.142 +				int		         n_pixels)	\
   1.143 +    {									\
   1.144 +	combine_inner (component, dest, src, mask, n_pixels,		\
   1.145 +		       combine_a, combine_c);				\
   1.146 +    }
   1.147 +
   1.148 +#define MAKE_COMBINERS(name, combine_a, combine_c)			\
   1.149 +    MAKE_COMBINER(name ## _ca, TRUE, combine_a, combine_c)		\
   1.150 +    MAKE_COMBINER(name ## _u, FALSE, combine_a, combine_c)
   1.151 +
   1.152 +
   1.153 +/*
   1.154 + * Porter/Duff operators
   1.155 + */
   1.156 +typedef enum
   1.157 +{
   1.158 +    ZERO,
   1.159 +    ONE,
   1.160 +    SRC_ALPHA,
   1.161 +    DEST_ALPHA,
   1.162 +    INV_SA,
   1.163 +    INV_DA,
   1.164 +    SA_OVER_DA,
   1.165 +    DA_OVER_SA,
   1.166 +    INV_SA_OVER_DA,
   1.167 +    INV_DA_OVER_SA,
   1.168 +    ONE_MINUS_SA_OVER_DA,
   1.169 +    ONE_MINUS_DA_OVER_SA,
   1.170 +    ONE_MINUS_INV_DA_OVER_SA,
   1.171 +    ONE_MINUS_INV_SA_OVER_DA
   1.172 +} combine_factor_t;
   1.173 +
   1.174 +#define CLAMP(f)					\
   1.175 +    (((f) < 0)? 0 : (((f) > 1.0) ? 1.0 : (f)))
   1.176 +
   1.177 +static force_inline float
   1.178 +get_factor (combine_factor_t factor, float sa, float da)
   1.179 +{
   1.180 +    float f = -1;
   1.181 +
   1.182 +    switch (factor)
   1.183 +    {
   1.184 +    case ZERO:
   1.185 +	f = 0.0f;
   1.186 +	break;
   1.187 +
   1.188 +    case ONE:
   1.189 +	f = 1.0f;
   1.190 +	break;
   1.191 +
   1.192 +    case SRC_ALPHA:
   1.193 +	f = sa;
   1.194 +	break;
   1.195 +
   1.196 +    case DEST_ALPHA:
   1.197 +	f = da;
   1.198 +	break;
   1.199 +
   1.200 +    case INV_SA:
   1.201 +	f = 1 - sa;
   1.202 +	break;
   1.203 +
   1.204 +    case INV_DA:
   1.205 +	f = 1 - da;
   1.206 +	break;
   1.207 +
   1.208 +    case SA_OVER_DA:
   1.209 +	if (IS_ZERO (da))
   1.210 +	    f = 1.0f;
   1.211 +	else
   1.212 +	    f = CLAMP (sa / da);
   1.213 +	break;
   1.214 +
   1.215 +    case DA_OVER_SA:
   1.216 +	if (IS_ZERO (sa))
   1.217 +	    f = 1.0f;
   1.218 +	else
   1.219 +	    f = CLAMP (da / sa);
   1.220 +	break;
   1.221 +
   1.222 +    case INV_SA_OVER_DA:
   1.223 +	if (IS_ZERO (da))
   1.224 +	    f = 1.0f;
   1.225 +	else
   1.226 +	    f = CLAMP ((1.0f - sa) / da);
   1.227 +	break;
   1.228 +
   1.229 +    case INV_DA_OVER_SA:
   1.230 +	if (IS_ZERO (sa))
   1.231 +	    f = 1.0f;
   1.232 +	else
   1.233 +	    f = CLAMP ((1.0f - da) / sa);
   1.234 +	break;
   1.235 +
   1.236 +    case ONE_MINUS_SA_OVER_DA:
   1.237 +	if (IS_ZERO (da))
   1.238 +	    f = 0.0f;
   1.239 +	else
   1.240 +	    f = CLAMP (1.0f - sa / da);
   1.241 +	break;
   1.242 +
   1.243 +    case ONE_MINUS_DA_OVER_SA:
   1.244 +	if (IS_ZERO (sa))
   1.245 +	    f = 0.0f;
   1.246 +	else
   1.247 +	    f = CLAMP (1.0f - da / sa);
   1.248 +	break;
   1.249 +
   1.250 +    case ONE_MINUS_INV_DA_OVER_SA:
   1.251 +	if (IS_ZERO (sa))
   1.252 +	    f = 0.0f;
   1.253 +	else
   1.254 +	    f = CLAMP (1.0f - (1.0f - da) / sa);
   1.255 +	break;
   1.256 +
   1.257 +    case ONE_MINUS_INV_SA_OVER_DA:
   1.258 +	if (IS_ZERO (da))
   1.259 +	    f = 0.0f;
   1.260 +	else
   1.261 +	    f = CLAMP (1.0f - (1.0f - sa) / da);
   1.262 +	break;
   1.263 +    }
   1.264 +
   1.265 +    return f;
   1.266 +}
   1.267 +
   1.268 +#define MAKE_PD_COMBINERS(name, a, b)					\
   1.269 +    static float force_inline						\
   1.270 +    pd_combine_ ## name (float sa, float s, float da, float d)		\
   1.271 +    {									\
   1.272 +	const float fa = get_factor (a, sa, da);			\
   1.273 +	const float fb = get_factor (b, sa, da);			\
   1.274 +									\
   1.275 +	return MIN (1.0f, s * fa + d * fb);				\
   1.276 +    }									\
   1.277 +    									\
   1.278 +    MAKE_COMBINERS(name, pd_combine_ ## name, pd_combine_ ## name)
   1.279 +
   1.280 +MAKE_PD_COMBINERS (clear,			ZERO,				ZERO)
   1.281 +MAKE_PD_COMBINERS (src,				ONE,				ZERO)
   1.282 +MAKE_PD_COMBINERS (dst,				ZERO,				ONE)
   1.283 +MAKE_PD_COMBINERS (over,			ONE,				INV_SA)
   1.284 +MAKE_PD_COMBINERS (over_reverse,		INV_DA,				ONE)
   1.285 +MAKE_PD_COMBINERS (in,				DEST_ALPHA,			ZERO)
   1.286 +MAKE_PD_COMBINERS (in_reverse,			ZERO,				SRC_ALPHA)
   1.287 +MAKE_PD_COMBINERS (out,				INV_DA,				ZERO)
   1.288 +MAKE_PD_COMBINERS (out_reverse,			ZERO,				INV_SA)
   1.289 +MAKE_PD_COMBINERS (atop,			DEST_ALPHA,			INV_SA)
   1.290 +MAKE_PD_COMBINERS (atop_reverse,		INV_DA,				SRC_ALPHA)
   1.291 +MAKE_PD_COMBINERS (xor,				INV_DA,				INV_SA)
   1.292 +MAKE_PD_COMBINERS (add,				ONE,				ONE)
   1.293 +
   1.294 +MAKE_PD_COMBINERS (saturate,			INV_DA_OVER_SA,			ONE)
   1.295 +
   1.296 +MAKE_PD_COMBINERS (disjoint_clear,		ZERO,				ZERO)
   1.297 +MAKE_PD_COMBINERS (disjoint_src,		ONE,				ZERO)
   1.298 +MAKE_PD_COMBINERS (disjoint_dst,		ZERO,				ONE)
   1.299 +MAKE_PD_COMBINERS (disjoint_over,		ONE,				INV_SA_OVER_DA)
   1.300 +MAKE_PD_COMBINERS (disjoint_over_reverse,	INV_DA_OVER_SA,			ONE)
   1.301 +MAKE_PD_COMBINERS (disjoint_in,			ONE_MINUS_INV_DA_OVER_SA,	ZERO)
   1.302 +MAKE_PD_COMBINERS (disjoint_in_reverse,		ZERO,				ONE_MINUS_INV_SA_OVER_DA)
   1.303 +MAKE_PD_COMBINERS (disjoint_out,		INV_DA_OVER_SA,			ZERO)
   1.304 +MAKE_PD_COMBINERS (disjoint_out_reverse,	ZERO,				INV_SA_OVER_DA)
   1.305 +MAKE_PD_COMBINERS (disjoint_atop,		ONE_MINUS_INV_DA_OVER_SA,	INV_SA_OVER_DA)
   1.306 +MAKE_PD_COMBINERS (disjoint_atop_reverse,	INV_DA_OVER_SA,			ONE_MINUS_INV_SA_OVER_DA)
   1.307 +MAKE_PD_COMBINERS (disjoint_xor,		INV_DA_OVER_SA,			INV_SA_OVER_DA)
   1.308 +
   1.309 +MAKE_PD_COMBINERS (conjoint_clear,		ZERO,				ZERO)
   1.310 +MAKE_PD_COMBINERS (conjoint_src,		ONE,				ZERO)
   1.311 +MAKE_PD_COMBINERS (conjoint_dst,		ZERO,				ONE)
   1.312 +MAKE_PD_COMBINERS (conjoint_over,		ONE,				ONE_MINUS_SA_OVER_DA)
   1.313 +MAKE_PD_COMBINERS (conjoint_over_reverse,	ONE_MINUS_DA_OVER_SA,		ONE)
   1.314 +MAKE_PD_COMBINERS (conjoint_in,			DA_OVER_SA,			ZERO)
   1.315 +MAKE_PD_COMBINERS (conjoint_in_reverse,		ZERO,				SA_OVER_DA)
   1.316 +MAKE_PD_COMBINERS (conjoint_out,		ONE_MINUS_DA_OVER_SA,		ZERO)
   1.317 +MAKE_PD_COMBINERS (conjoint_out_reverse,	ZERO,				ONE_MINUS_SA_OVER_DA)
   1.318 +MAKE_PD_COMBINERS (conjoint_atop,		DA_OVER_SA,			ONE_MINUS_SA_OVER_DA)
   1.319 +MAKE_PD_COMBINERS (conjoint_atop_reverse,	ONE_MINUS_DA_OVER_SA,		SA_OVER_DA)
   1.320 +MAKE_PD_COMBINERS (conjoint_xor,		ONE_MINUS_DA_OVER_SA,		ONE_MINUS_SA_OVER_DA)
   1.321 +
   1.322 +/*
   1.323 + * PDF blend modes:
   1.324 + *
   1.325 + * The following blend modes have been taken from the PDF ISO 32000
   1.326 + * specification, which at this point in time is available from
   1.327 + * http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
   1.328 + * The relevant chapters are 11.3.5 and 11.3.6.
   1.329 + * The formula for computing the final pixel color given in 11.3.6 is:
   1.330 + * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
   1.331 + * with B() being the blend function.
   1.332 + * Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs
   1.333 + *
   1.334 + * These blend modes should match the SVG filter draft specification, as
   1.335 + * it has been designed to mirror ISO 32000. Note that at the current point
   1.336 + * no released draft exists that shows this, as the formulas have not been
   1.337 + * updated yet after the release of ISO 32000.
   1.338 + *
   1.339 + * The default implementation here uses the PDF_SEPARABLE_BLEND_MODE and
   1.340 + * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an
   1.341 + * argument. Note that this implementation operates on premultiplied colors,
   1.342 + * while the PDF specification does not. Therefore the code uses the formula
   1.343 + * ar.Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as)
   1.344 + */
   1.345 +
   1.346 +#define MAKE_SEPARABLE_PDF_COMBINERS(name)				\
   1.347 +    static force_inline float						\
   1.348 +    combine_ ## name ## _a (float sa, float s, float da, float d)	\
   1.349 +    {									\
   1.350 +	return da + sa - da * sa;					\
   1.351 +    }									\
   1.352 +    									\
   1.353 +    static force_inline float						\
   1.354 +    combine_ ## name ## _c (float sa, float s, float da, float d)	\
   1.355 +    {									\
   1.356 +	float f = (1 - sa) * d + (1 - da) * s;				\
   1.357 +									\
   1.358 +	return f + blend_ ## name (sa, s, da, d);			\
   1.359 +    }									\
   1.360 +    									\
   1.361 +    MAKE_COMBINERS (name, combine_ ## name ## _a, combine_ ## name ## _c)
   1.362 +
   1.363 +static force_inline float
   1.364 +blend_multiply (float sa, float s, float da, float d)
   1.365 +{
   1.366 +    return d * s;
   1.367 +}
   1.368 +
   1.369 +static force_inline float
   1.370 +blend_screen (float sa, float s, float da, float d)
   1.371 +{
   1.372 +    return d * sa + s * da - s * d;
   1.373 +}
   1.374 +
   1.375 +static force_inline float
   1.376 +blend_overlay (float sa, float s, float da, float d)
   1.377 +{
   1.378 +    if (2 * d < da)
   1.379 +	return 2 * s * d;
   1.380 +    else
   1.381 +	return sa * da - 2 * (da - d) * (sa - s);
   1.382 +}
   1.383 +
   1.384 +static force_inline float
   1.385 +blend_darken (float sa, float s, float da, float d)
   1.386 +{
   1.387 +    s = s * da;
   1.388 +    d = d * sa;
   1.389 +
   1.390 +    if (s > d)
   1.391 +	return d;
   1.392 +    else
   1.393 +	return s;
   1.394 +}
   1.395 +
   1.396 +static force_inline float
   1.397 +blend_lighten (float sa, float s, float da, float d)
   1.398 +{
   1.399 +    s = s * da;
   1.400 +    d = d * sa;
   1.401 +
   1.402 +    if (s > d)
   1.403 +	return s;
   1.404 +    else
   1.405 +	return d;
   1.406 +}
   1.407 +
   1.408 +static force_inline float
   1.409 +blend_color_dodge (float sa, float s, float da, float d)
   1.410 +{
   1.411 +    if (IS_ZERO (d))
   1.412 +	return 0.0f;
   1.413 +    else if (d * sa >= sa * da - s * da)
   1.414 +	return sa * da;
   1.415 +    else if (IS_ZERO (sa - s))
   1.416 +	return sa * da;
   1.417 +    else
   1.418 +	return sa * sa * d / (sa - s);
   1.419 +}
   1.420 +
   1.421 +static force_inline float
   1.422 +blend_color_burn (float sa, float s, float da, float d)
   1.423 +{
   1.424 +    if (d >= da)
   1.425 +	return sa * da;
   1.426 +    else if (sa * (da - d) >= s * da)
   1.427 +	return 0.0f;
   1.428 +    else if (IS_ZERO (s))
   1.429 +	return 0.0f;
   1.430 +    else
   1.431 +	return sa * (da - sa * (da - d) / s);
   1.432 +}
   1.433 +
   1.434 +static force_inline float
   1.435 +blend_hard_light (float sa, float s, float da, float d)
   1.436 +{
   1.437 +    if (2 * s < sa)
   1.438 +	return 2 * s * d;
   1.439 +    else
   1.440 +	return sa * da - 2 * (da - d) * (sa - s);
   1.441 +}
   1.442 +
   1.443 +static force_inline float
   1.444 +blend_soft_light (float sa, float s, float da, float d)
   1.445 +{
   1.446 +    if (2 * s < sa)
   1.447 +    {
   1.448 +	if (IS_ZERO (da))
   1.449 +	    return d * sa;
   1.450 +	else
   1.451 +	    return d * sa - d * (da - d) * (sa - 2 * s) / da;
   1.452 +    }
   1.453 +    else
   1.454 +    {
   1.455 +	if (IS_ZERO (da))
   1.456 +	{
   1.457 +	    return 0.0f;
   1.458 +	}
   1.459 +	else
   1.460 +	{
   1.461 +	    if (4 * d <= da)
   1.462 +		return d * sa + (2 * s - sa) * d * ((16 * d / da - 12) * d / da + 3);
   1.463 +	    else
   1.464 +		return d * sa + (sqrtf (d * da) - d) * (2 * s - sa);
   1.465 +	}
   1.466 +    }
   1.467 +}
   1.468 +
   1.469 +static force_inline float
   1.470 +blend_difference (float sa, float s, float da, float d)
   1.471 +{
   1.472 +    float dsa = d * sa;
   1.473 +    float sda = s * da;
   1.474 +
   1.475 +    if (sda < dsa)
   1.476 +	return dsa - sda;
   1.477 +    else
   1.478 +	return sda - dsa;
   1.479 +}
   1.480 +
   1.481 +static force_inline float
   1.482 +blend_exclusion (float sa, float s, float da, float d)
   1.483 +{
   1.484 +    return s * da + d * sa - 2 * d * s;
   1.485 +}
   1.486 +
   1.487 +MAKE_SEPARABLE_PDF_COMBINERS (multiply)
   1.488 +MAKE_SEPARABLE_PDF_COMBINERS (screen)
   1.489 +MAKE_SEPARABLE_PDF_COMBINERS (overlay)
   1.490 +MAKE_SEPARABLE_PDF_COMBINERS (darken)
   1.491 +MAKE_SEPARABLE_PDF_COMBINERS (lighten)
   1.492 +MAKE_SEPARABLE_PDF_COMBINERS (color_dodge)
   1.493 +MAKE_SEPARABLE_PDF_COMBINERS (color_burn)
   1.494 +MAKE_SEPARABLE_PDF_COMBINERS (hard_light)
   1.495 +MAKE_SEPARABLE_PDF_COMBINERS (soft_light)
   1.496 +MAKE_SEPARABLE_PDF_COMBINERS (difference)
   1.497 +MAKE_SEPARABLE_PDF_COMBINERS (exclusion)
   1.498 +
   1.499 +/*
   1.500 + * PDF nonseperable blend modes.
   1.501 + *
   1.502 + * These are implemented using the following functions to operate in Hsl
   1.503 + * space, with Cmax, Cmid, Cmin referring to the max, mid and min value
   1.504 + * of the red, green and blue components.
   1.505 + *
   1.506 + * LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue
   1.507 + *
   1.508 + * clip_color (C):
   1.509 + *   l = LUM (C)
   1.510 + *   min = Cmin
   1.511 + *   max = Cmax
   1.512 + *   if n < 0.0
   1.513 + *     C = l + (((C – l) × l) ⁄     (l – min))
   1.514 + *   if x > 1.0
   1.515 + *     C = l + (((C – l) × (1 – l)) (max – l))
   1.516 + *   return C
   1.517 + *
   1.518 + * set_lum (C, l):
   1.519 + *   d = l – LUM (C)
   1.520 + *   C += d
   1.521 + *   return clip_color (C)
   1.522 + *
   1.523 + * SAT (C) = CH_MAX (C) - CH_MIN (C)
   1.524 + *
   1.525 + * set_sat (C, s):
   1.526 + *  if Cmax > Cmin
   1.527 + *    Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
   1.528 + *    Cmax = s
   1.529 + *  else
   1.530 + *    Cmid = Cmax = 0.0
   1.531 + *  Cmin = 0.0
   1.532 + *  return C
   1.533 + */
   1.534 +
   1.535 +/* For premultiplied colors, we need to know what happens when C is
   1.536 + * multiplied by a real number. LUM and SAT are linear:
   1.537 + *
   1.538 + *    LUM (r × C) = r × LUM (C)		SAT (r × C) = r × SAT (C)
   1.539 + *
   1.540 + * If we extend clip_color with an extra argument a and change
   1.541 + *
   1.542 + *        if x >= 1.0
   1.543 + *
   1.544 + * into
   1.545 + *
   1.546 + *        if x >= a
   1.547 + *
   1.548 + * then clip_color is also linear:
   1.549 + *
   1.550 + *     r * clip_color (C, a) = clip_color (r_c, ra);
   1.551 + *
   1.552 + * for positive r.
   1.553 + *
   1.554 + * Similarly, we can extend set_lum with an extra argument that is just passed
   1.555 + * on to clip_color:
   1.556 + *
   1.557 + *     r × set_lum ( C, l, a)
   1.558 + *
   1.559 + *   = r × clip_color ( C + l - LUM (C), a)
   1.560 + *
   1.561 + *   = clip_color ( r * C + r × l - LUM (r × C), r * a)
   1.562 + *
   1.563 + *   = set_lum ( r * C, r * l, r * a)
   1.564 + *
   1.565 + * Finally, set_sat:
   1.566 + *
   1.567 + *     r * set_sat (C, s) = set_sat (x * C, r * s)
   1.568 + *
   1.569 + * The above holds for all non-zero x because they x'es in the fraction for
   1.570 + * C_mid cancel out. Specifically, it holds for x = r:
   1.571 + *
   1.572 + *     r * set_sat (C, s) = set_sat (r_c, rs)
   1.573 + *
   1.574 + *
   1.575 + *
   1.576 + *
   1.577 + * So, for the non-separable PDF blend modes, we have (using s, d for
   1.578 + * non-premultiplied colors, and S, D for premultiplied:
   1.579 + *
   1.580 + *   Color:
   1.581 + *
   1.582 + *     a_s * a_d * B(s, d)
   1.583 + *   = a_s * a_d * set_lum (S/a_s, LUM (D/a_d), 1)
   1.584 + *   = set_lum (S * a_d, a_s * LUM (D), a_s * a_d)
   1.585 + *
   1.586 + *
   1.587 + *   Luminosity:
   1.588 + *
   1.589 + *     a_s * a_d * B(s, d)
   1.590 + *   = a_s * a_d * set_lum (D/a_d, LUM(S/a_s), 1)
   1.591 + *   = set_lum (a_s * D, a_d * LUM(S), a_s * a_d)
   1.592 + *
   1.593 + *
   1.594 + *   Saturation:
   1.595 + *
   1.596 + *     a_s * a_d * B(s, d)
   1.597 + *   = a_s * a_d * set_lum (set_sat (D/a_d, SAT (S/a_s)), LUM (D/a_d), 1)
   1.598 + *   = set_lum (a_s * a_d * set_sat (D/a_d, SAT (S/a_s)),
   1.599 + *                                        a_s * LUM (D), a_s * a_d)
   1.600 + *   = set_lum (set_sat (a_s * D, a_d * SAT (S), a_s * LUM (D), a_s * a_d))
   1.601 + *
   1.602 + *   Hue:
   1.603 + *
   1.604 + *     a_s * a_d * B(s, d)
   1.605 + *   = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1)
   1.606 + *   = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d)
   1.607 + *
   1.608 + */
   1.609 +
   1.610 +typedef struct
   1.611 +{
   1.612 +    float	r;
   1.613 +    float	g;
   1.614 +    float	b;
   1.615 +} rgb_t;
   1.616 +
   1.617 +static force_inline float
   1.618 +minf (float a, float b)
   1.619 +{
   1.620 +    return a < b? a : b;
   1.621 +}
   1.622 +
   1.623 +static force_inline float
   1.624 +maxf (float a, float b)
   1.625 +{
   1.626 +    return a > b? a : b;
   1.627 +}
   1.628 +
   1.629 +static force_inline float
   1.630 +channel_min (const rgb_t *c)
   1.631 +{
   1.632 +    return minf (minf (c->r, c->g), c->b);
   1.633 +}
   1.634 +
   1.635 +static force_inline float
   1.636 +channel_max (const rgb_t *c)
   1.637 +{
   1.638 +    return maxf (maxf (c->r, c->g), c->b);
   1.639 +}
   1.640 +
   1.641 +static force_inline float
   1.642 +get_lum (const rgb_t *c)
   1.643 +{
   1.644 +    return c->r * 0.3f + c->g * 0.59f + c->b * 0.11f;
   1.645 +}
   1.646 +
   1.647 +static force_inline float
   1.648 +get_sat (const rgb_t *c)
   1.649 +{
   1.650 +    return channel_max (c) - channel_min (c);
   1.651 +}
   1.652 +
   1.653 +static void
   1.654 +clip_color (rgb_t *color, float a)
   1.655 +{
   1.656 +    float l = get_lum (color);
   1.657 +    float n = channel_min (color);
   1.658 +    float x = channel_max (color);
   1.659 +    float t;
   1.660 +
   1.661 +    if (n < 0.0f)
   1.662 +    {
   1.663 +	t = l - n;
   1.664 +	if (IS_ZERO (t))
   1.665 +	{
   1.666 +	    color->r = 0.0f;
   1.667 +	    color->g = 0.0f;
   1.668 +	    color->b = 0.0f;
   1.669 +	}
   1.670 +	else
   1.671 +	{
   1.672 +	    color->r = l + (((color->r - l) * l) / t);
   1.673 +	    color->g = l + (((color->g - l) * l) / t);
   1.674 +	    color->b = l + (((color->b - l) * l) / t);
   1.675 +	}
   1.676 +    }
   1.677 +    if (x > a)
   1.678 +    {
   1.679 +	t = x - l;
   1.680 +	if (IS_ZERO (t))
   1.681 +	{
   1.682 +	    color->r = a;
   1.683 +	    color->g = a;
   1.684 +	    color->b = a;
   1.685 +	}
   1.686 +	else
   1.687 +	{
   1.688 +	    color->r = l + (((color->r - l) * (a - l) / t));
   1.689 +	    color->g = l + (((color->g - l) * (a - l) / t));
   1.690 +	    color->b = l + (((color->b - l) * (a - l) / t));
   1.691 +	}
   1.692 +    }
   1.693 +}
   1.694 +
   1.695 +static void
   1.696 +set_lum (rgb_t *color, float sa, float l)
   1.697 +{
   1.698 +    float d = l - get_lum (color);
   1.699 +
   1.700 +    color->r = color->r + d;
   1.701 +    color->g = color->g + d;
   1.702 +    color->b = color->b + d;
   1.703 +
   1.704 +    clip_color (color, sa);
   1.705 +}
   1.706 +
   1.707 +static void
   1.708 +set_sat (rgb_t *src, float sat)
   1.709 +{
   1.710 +    float *max, *mid, *min;
   1.711 +    float t;
   1.712 +
   1.713 +    if (src->r > src->g)
   1.714 +    {
   1.715 +	if (src->r > src->b)
   1.716 +	{
   1.717 +	    max = &(src->r);
   1.718 +
   1.719 +	    if (src->g > src->b)
   1.720 +	    {
   1.721 +		mid = &(src->g);
   1.722 +		min = &(src->b);
   1.723 +	    }
   1.724 +	    else
   1.725 +	    {
   1.726 +		mid = &(src->b);
   1.727 +		min = &(src->g);
   1.728 +	    }
   1.729 +	}
   1.730 +	else
   1.731 +	{
   1.732 +	    max = &(src->b);
   1.733 +	    mid = &(src->r);
   1.734 +	    min = &(src->g);
   1.735 +	}
   1.736 +    }
   1.737 +    else
   1.738 +    {
   1.739 +	if (src->r > src->b)
   1.740 +	{
   1.741 +	    max = &(src->g);
   1.742 +	    mid = &(src->r);
   1.743 +	    min = &(src->b);
   1.744 +	}
   1.745 +	else
   1.746 +	{
   1.747 +	    min = &(src->r);
   1.748 +
   1.749 +	    if (src->g > src->b)
   1.750 +	    {
   1.751 +		max = &(src->g);
   1.752 +		mid = &(src->b);
   1.753 +	    }
   1.754 +	    else
   1.755 +	    {
   1.756 +		max = &(src->b);
   1.757 +		mid = &(src->g);
   1.758 +	    }
   1.759 +	}
   1.760 +    }
   1.761 +
   1.762 +    t = *max - *min;
   1.763 +
   1.764 +    if (IS_ZERO (t))
   1.765 +    {
   1.766 +	*mid = *max = 0.0f;
   1.767 +    }
   1.768 +    else
   1.769 +    {
   1.770 +	*mid = ((*mid - *min) * sat) / t;
   1.771 +	*max = sat;
   1.772 +    }
   1.773 +
   1.774 +    *min = 0.0f;
   1.775 +}
   1.776 +
   1.777 +/*
   1.778 + * Hue:
   1.779 + * B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb))
   1.780 + */
   1.781 +static force_inline void
   1.782 +blend_hsl_hue (rgb_t *res,
   1.783 +	       const rgb_t *dest, float da,
   1.784 +	       const rgb_t *src, float sa)
   1.785 +{
   1.786 +    res->r = src->r * da;
   1.787 +    res->g = src->g * da;
   1.788 +    res->b = src->b * da;
   1.789 +
   1.790 +    set_sat (res, get_sat (dest) * sa);
   1.791 +    set_lum (res, sa * da, get_lum (dest) * sa);
   1.792 +}
   1.793 +
   1.794 +/*
   1.795 + * Saturation:
   1.796 + * B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb))
   1.797 + */
   1.798 +static force_inline void
   1.799 +blend_hsl_saturation (rgb_t *res,
   1.800 +		      const rgb_t *dest, float da,
   1.801 +		      const rgb_t *src, float sa)
   1.802 +{
   1.803 +    res->r = dest->r * sa;
   1.804 +    res->g = dest->g * sa;
   1.805 +    res->b = dest->b * sa;
   1.806 +
   1.807 +    set_sat (res, get_sat (src) * da);
   1.808 +    set_lum (res, sa * da, get_lum (dest) * sa);
   1.809 +}
   1.810 +
   1.811 +/*
   1.812 + * Color:
   1.813 + * B(Cb, Cs) = set_lum (Cs, LUM (Cb))
   1.814 + */
   1.815 +static force_inline void
   1.816 +blend_hsl_color (rgb_t *res,
   1.817 +		 const rgb_t *dest, float da,
   1.818 +		 const rgb_t *src, float sa)
   1.819 +{
   1.820 +    res->r = src->r * da;
   1.821 +    res->g = src->g * da;
   1.822 +    res->b = src->b * da;
   1.823 +
   1.824 +    set_lum (res, sa * da, get_lum (dest) * sa);
   1.825 +}
   1.826 +
   1.827 +/*
   1.828 + * Luminosity:
   1.829 + * B(Cb, Cs) = set_lum (Cb, LUM (Cs))
   1.830 + */
   1.831 +static force_inline void
   1.832 +blend_hsl_luminosity (rgb_t *res,
   1.833 +		      const rgb_t *dest, float da,
   1.834 +		      const rgb_t *src, float sa)
   1.835 +{
   1.836 +    res->r = dest->r * sa;
   1.837 +    res->g = dest->g * sa;
   1.838 +    res->b = dest->b * sa;
   1.839 +
   1.840 +    set_lum (res, sa * da, get_lum (src) * da);
   1.841 +}
   1.842 +
   1.843 +#define MAKE_NON_SEPARABLE_PDF_COMBINERS(name)				\
   1.844 +    static void								\
   1.845 +    combine_ ## name ## _u_float (pixman_implementation_t *imp,		\
   1.846 +				  pixman_op_t              op,		\
   1.847 +				  float                   *dest,	\
   1.848 +				  const float             *src,		\
   1.849 +				  const float             *mask,	\
   1.850 +				  int		           n_pixels)	\
   1.851 +    {									\
   1.852 +    	int i;								\
   1.853 +									\
   1.854 +	for (i = 0; i < 4 * n_pixels; i += 4)				\
   1.855 +	{								\
   1.856 +	    float sa, da;						\
   1.857 +	    rgb_t sc, dc, rc;						\
   1.858 +									\
   1.859 +	    sa = src[i + 0];						\
   1.860 +	    sc.r = src[i + 1];						\
   1.861 +	    sc.g = src[i + 2];						\
   1.862 +	    sc.b = src[i + 3];						\
   1.863 +									\
   1.864 +	    da = dest[i + 0];						\
   1.865 +	    dc.r = dest[i + 1];						\
   1.866 +	    dc.g = dest[i + 2];						\
   1.867 +	    dc.b = dest[i + 3];						\
   1.868 +									\
   1.869 +	    if (mask)							\
   1.870 +	    {								\
   1.871 +		float ma = mask[i + 0];					\
   1.872 +									\
   1.873 +		/* Component alpha is not supported for HSL modes */	\
   1.874 +		sa *= ma;						\
   1.875 +		sc.r *= ma;						\
   1.876 +		sc.g *= ma;						\
   1.877 +		sc.g *= ma;						\
   1.878 +	    }								\
   1.879 +									\
   1.880 +	    blend_ ## name (&rc, &dc, da, &sc, sa);			\
   1.881 +									\
   1.882 +	    dest[i + 0] = sa + da - sa * da;				\
   1.883 +	    dest[i + 1] = (1 - sa) * dc.r + (1 - da) * sc.r + rc.r;	\
   1.884 +	    dest[i + 2] = (1 - sa) * dc.g + (1 - da) * sc.g + rc.g;	\
   1.885 +	    dest[i + 3] = (1 - sa) * dc.b + (1 - da) * sc.b + rc.b;	\
   1.886 +	}								\
   1.887 +    }
   1.888 +
   1.889 +MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_hue)
   1.890 +MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_saturation)
   1.891 +MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_color)
   1.892 +MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_luminosity)
   1.893 +
   1.894 +void
   1.895 +_pixman_setup_combiner_functions_float (pixman_implementation_t *imp)
   1.896 +{
   1.897 +    /* Unified alpha */
   1.898 +    imp->combine_float[PIXMAN_OP_CLEAR] = combine_clear_u_float;
   1.899 +    imp->combine_float[PIXMAN_OP_SRC] = combine_src_u_float;
   1.900 +    imp->combine_float[PIXMAN_OP_DST] = combine_dst_u_float;
   1.901 +    imp->combine_float[PIXMAN_OP_OVER] = combine_over_u_float;
   1.902 +    imp->combine_float[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u_float;
   1.903 +    imp->combine_float[PIXMAN_OP_IN] = combine_in_u_float;
   1.904 +    imp->combine_float[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_u_float;
   1.905 +    imp->combine_float[PIXMAN_OP_OUT] = combine_out_u_float;
   1.906 +    imp->combine_float[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_u_float;
   1.907 +    imp->combine_float[PIXMAN_OP_ATOP] = combine_atop_u_float;
   1.908 +    imp->combine_float[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u_float;
   1.909 +    imp->combine_float[PIXMAN_OP_XOR] = combine_xor_u_float;
   1.910 +    imp->combine_float[PIXMAN_OP_ADD] = combine_add_u_float;
   1.911 +    imp->combine_float[PIXMAN_OP_SATURATE] = combine_saturate_u_float;
   1.912 +
   1.913 +    /* Disjoint, unified */
   1.914 +    imp->combine_float[PIXMAN_OP_DISJOINT_CLEAR] = combine_disjoint_clear_u_float;
   1.915 +    imp->combine_float[PIXMAN_OP_DISJOINT_SRC] = combine_disjoint_src_u_float;
   1.916 +    imp->combine_float[PIXMAN_OP_DISJOINT_DST] = combine_disjoint_dst_u_float;
   1.917 +    imp->combine_float[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_u_float;
   1.918 +    imp->combine_float[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_disjoint_over_reverse_u_float;
   1.919 +    imp->combine_float[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_u_float;
   1.920 +    imp->combine_float[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_u_float;
   1.921 +    imp->combine_float[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_u_float;
   1.922 +    imp->combine_float[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_u_float;
   1.923 +    imp->combine_float[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_u_float;
   1.924 +    imp->combine_float[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_u_float;
   1.925 +    imp->combine_float[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_u_float;
   1.926 +
   1.927 +    /* Conjoint, unified */
   1.928 +    imp->combine_float[PIXMAN_OP_CONJOINT_CLEAR] = combine_conjoint_clear_u_float;
   1.929 +    imp->combine_float[PIXMAN_OP_CONJOINT_SRC] = combine_conjoint_src_u_float;
   1.930 +    imp->combine_float[PIXMAN_OP_CONJOINT_DST] = combine_conjoint_dst_u_float;
   1.931 +    imp->combine_float[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_u_float;
   1.932 +    imp->combine_float[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_u_float;
   1.933 +    imp->combine_float[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_u_float;
   1.934 +    imp->combine_float[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_u_float;
   1.935 +    imp->combine_float[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_u_float;
   1.936 +    imp->combine_float[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_u_float;
   1.937 +    imp->combine_float[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_u_float;
   1.938 +    imp->combine_float[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_u_float;
   1.939 +    imp->combine_float[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_u_float;
   1.940 +
   1.941 +    /* PDF operators, unified */
   1.942 +    imp->combine_float[PIXMAN_OP_MULTIPLY] = combine_multiply_u_float;
   1.943 +    imp->combine_float[PIXMAN_OP_SCREEN] = combine_screen_u_float;
   1.944 +    imp->combine_float[PIXMAN_OP_OVERLAY] = combine_overlay_u_float;
   1.945 +    imp->combine_float[PIXMAN_OP_DARKEN] = combine_darken_u_float;
   1.946 +    imp->combine_float[PIXMAN_OP_LIGHTEN] = combine_lighten_u_float;
   1.947 +    imp->combine_float[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_u_float;
   1.948 +    imp->combine_float[PIXMAN_OP_COLOR_BURN] = combine_color_burn_u_float;
   1.949 +    imp->combine_float[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u_float;
   1.950 +    imp->combine_float[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_u_float;
   1.951 +    imp->combine_float[PIXMAN_OP_DIFFERENCE] = combine_difference_u_float;
   1.952 +    imp->combine_float[PIXMAN_OP_EXCLUSION] = combine_exclusion_u_float;
   1.953 +
   1.954 +    imp->combine_float[PIXMAN_OP_HSL_HUE] = combine_hsl_hue_u_float;
   1.955 +    imp->combine_float[PIXMAN_OP_HSL_SATURATION] = combine_hsl_saturation_u_float;
   1.956 +    imp->combine_float[PIXMAN_OP_HSL_COLOR] = combine_hsl_color_u_float;
   1.957 +    imp->combine_float[PIXMAN_OP_HSL_LUMINOSITY] = combine_hsl_luminosity_u_float;
   1.958 +
   1.959 +    /* Component alpha combiners */
   1.960 +    imp->combine_float_ca[PIXMAN_OP_CLEAR] = combine_clear_ca_float;
   1.961 +    imp->combine_float_ca[PIXMAN_OP_SRC] = combine_src_ca_float;
   1.962 +    imp->combine_float_ca[PIXMAN_OP_DST] = combine_dst_ca_float;
   1.963 +    imp->combine_float_ca[PIXMAN_OP_OVER] = combine_over_ca_float;
   1.964 +    imp->combine_float_ca[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_ca_float;
   1.965 +    imp->combine_float_ca[PIXMAN_OP_IN] = combine_in_ca_float;
   1.966 +    imp->combine_float_ca[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_ca_float;
   1.967 +    imp->combine_float_ca[PIXMAN_OP_OUT] = combine_out_ca_float;
   1.968 +    imp->combine_float_ca[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_ca_float;
   1.969 +    imp->combine_float_ca[PIXMAN_OP_ATOP] = combine_atop_ca_float;
   1.970 +    imp->combine_float_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca_float;
   1.971 +    imp->combine_float_ca[PIXMAN_OP_XOR] = combine_xor_ca_float;
   1.972 +    imp->combine_float_ca[PIXMAN_OP_ADD] = combine_add_ca_float;
   1.973 +    imp->combine_float_ca[PIXMAN_OP_SATURATE] = combine_saturate_ca_float;
   1.974 +
   1.975 +    /* Disjoint CA */
   1.976 +    imp->combine_float_ca[PIXMAN_OP_DISJOINT_CLEAR] = combine_disjoint_clear_ca_float;
   1.977 +    imp->combine_float_ca[PIXMAN_OP_DISJOINT_SRC] = combine_disjoint_src_ca_float;
   1.978 +    imp->combine_float_ca[PIXMAN_OP_DISJOINT_DST] = combine_disjoint_dst_ca_float;
   1.979 +    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_ca_float;
   1.980 +    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_disjoint_over_reverse_ca_float;
   1.981 +    imp->combine_float_ca[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_ca_float;
   1.982 +    imp->combine_float_ca[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_ca_float;
   1.983 +    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_ca_float;
   1.984 +    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_ca_float;
   1.985 +    imp->combine_float_ca[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_ca_float;
   1.986 +    imp->combine_float_ca[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_ca_float;
   1.987 +    imp->combine_float_ca[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_ca_float;
   1.988 +
   1.989 +    /* Conjoint CA */
   1.990 +    imp->combine_float_ca[PIXMAN_OP_CONJOINT_CLEAR] = combine_conjoint_clear_ca_float;
   1.991 +    imp->combine_float_ca[PIXMAN_OP_CONJOINT_SRC] = combine_conjoint_src_ca_float;
   1.992 +    imp->combine_float_ca[PIXMAN_OP_CONJOINT_DST] = combine_conjoint_dst_ca_float;
   1.993 +    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_ca_float;
   1.994 +    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_ca_float;
   1.995 +    imp->combine_float_ca[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_ca_float;
   1.996 +    imp->combine_float_ca[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_ca_float;
   1.997 +    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_ca_float;
   1.998 +    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_ca_float;
   1.999 +    imp->combine_float_ca[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_ca_float;
  1.1000 +    imp->combine_float_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_ca_float;
  1.1001 +    imp->combine_float_ca[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_ca_float;
  1.1002 +
  1.1003 +    /* PDF operators CA */
  1.1004 +    imp->combine_float_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca_float;
  1.1005 +    imp->combine_float_ca[PIXMAN_OP_SCREEN] = combine_screen_ca_float;
  1.1006 +    imp->combine_float_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca_float;
  1.1007 +    imp->combine_float_ca[PIXMAN_OP_DARKEN] = combine_darken_ca_float;
  1.1008 +    imp->combine_float_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca_float;
  1.1009 +    imp->combine_float_ca[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_ca_float;
  1.1010 +    imp->combine_float_ca[PIXMAN_OP_COLOR_BURN] = combine_color_burn_ca_float;
  1.1011 +    imp->combine_float_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca_float;
  1.1012 +    imp->combine_float_ca[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_ca_float;
  1.1013 +    imp->combine_float_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca_float;
  1.1014 +    imp->combine_float_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca_float;
  1.1015 +
  1.1016 +    /* It is not clear that these make sense, so make them noops for now */
  1.1017 +    imp->combine_float_ca[PIXMAN_OP_HSL_HUE] = combine_dst_u_float;
  1.1018 +    imp->combine_float_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst_u_float;
  1.1019 +    imp->combine_float_ca[PIXMAN_OP_HSL_COLOR] = combine_dst_u_float;
  1.1020 +    imp->combine_float_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst_u_float;
  1.1021 +}

mercurial