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