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

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial