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