|
1 # HG changeset patch |
|
2 # User Rik Cabanier <cabanier@adobe.com> |
|
3 # Date 1360273929 -46800 |
|
4 # Node ID 3ac8edca3a03b3d22240b5a5b95ae3b5ada9877d |
|
5 # Parent cbb67fe70b864b36165061e1fd3b083cd09af087 |
|
6 Bug 836892 - Add new blending modes to SkXfermode. r=gw280 |
|
7 |
|
8 diff --git a/gfx/skia/include/core/SkXfermode.h b/gfx/skia/include/core/SkXfermode.h |
|
9 --- a/gfx/skia/include/core/SkXfermode.h |
|
10 +++ b/gfx/skia/include/core/SkXfermode.h |
|
11 @@ -96,33 +96,37 @@ public: |
|
12 kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)] |
|
13 kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc] |
|
14 kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)] |
|
15 kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] |
|
16 |
|
17 // all remaining modes are defined in the SVG Compositing standard |
|
18 // http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/ |
|
19 kPlus_Mode, |
|
20 - kMultiply_Mode, |
|
21 |
|
22 // all above modes can be expressed as pair of src/dst Coeffs |
|
23 kCoeffModesCnt, |
|
24 |
|
25 - kScreen_Mode = kCoeffModesCnt, |
|
26 + kMultiply_Mode = kCoeffModesCnt, |
|
27 + kScreen_Mode, |
|
28 kOverlay_Mode, |
|
29 kDarken_Mode, |
|
30 kLighten_Mode, |
|
31 kColorDodge_Mode, |
|
32 kColorBurn_Mode, |
|
33 kHardLight_Mode, |
|
34 kSoftLight_Mode, |
|
35 kDifference_Mode, |
|
36 kExclusion_Mode, |
|
37 + kHue_Mode, |
|
38 + kSaturation_Mode, |
|
39 + kColor_Mode, |
|
40 + kLuminosity_Mode, |
|
41 |
|
42 - kLastMode = kExclusion_Mode |
|
43 + kLastMode = kLuminosity_Mode |
|
44 }; |
|
45 |
|
46 /** |
|
47 * If the xfermode is one of the modes in the Mode enum, then asMode() |
|
48 * returns true and sets (if not null) mode accordingly. Otherwise it |
|
49 * returns false and ignores the mode parameter. |
|
50 */ |
|
51 virtual bool asMode(Mode* mode); |
|
52 diff --git a/gfx/skia/src/core/SkXfermode.cpp b/gfx/skia/src/core/SkXfermode.cpp |
|
53 --- a/gfx/skia/src/core/SkXfermode.cpp |
|
54 +++ b/gfx/skia/src/core/SkXfermode.cpp |
|
55 @@ -7,16 +7,18 @@ |
|
56 */ |
|
57 |
|
58 |
|
59 #include "SkXfermode.h" |
|
60 #include "SkColorPriv.h" |
|
61 #include "SkFlattenableBuffers.h" |
|
62 #include "SkMathPriv.h" |
|
63 |
|
64 +#include <algorithm> |
|
65 + |
|
66 SK_DEFINE_INST_COUNT(SkXfermode) |
|
67 |
|
68 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b) |
|
69 |
|
70 #if 0 |
|
71 // idea for higher precision blends in xfer procs (and slightly faster) |
|
72 // see DstATop as a probable caller |
|
73 static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) { |
|
74 @@ -176,244 +178,439 @@ static SkPMColor xor_modeproc(SkPMColor |
|
75 static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) { |
|
76 unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst)); |
|
77 unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst)); |
|
78 unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst)); |
|
79 unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst)); |
|
80 return SkPackARGB32(a, r, g, b); |
|
81 } |
|
82 |
|
83 +static inline int srcover_byte(int a, int b) { |
|
84 + return a + b - SkAlphaMulAlpha(a, b); |
|
85 +} |
|
86 + |
|
87 +#define blendfunc_byte(sc, dc, sa, da, blendfunc) \ |
|
88 + clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendfunc(sc, dc, sa, da)) |
|
89 + |
|
90 // kMultiply_Mode |
|
91 +static inline int multiply_byte(int sc, int dc, int sa, int da) { |
|
92 + return sc * dc; |
|
93 +} |
|
94 static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) { |
|
95 - int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst)); |
|
96 - int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst)); |
|
97 - int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst)); |
|
98 - int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst)); |
|
99 + int sa = SkGetPackedA32(src); |
|
100 + int da = SkGetPackedA32(dst); |
|
101 + int a = srcover_byte(sa, da); |
|
102 + int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, multiply_byte); |
|
103 + int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, multiply_byte); |
|
104 + int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, multiply_byte); |
|
105 return SkPackARGB32(a, r, g, b); |
|
106 } |
|
107 |
|
108 // kScreen_Mode |
|
109 -static inline int srcover_byte(int a, int b) { |
|
110 - return a + b - SkAlphaMulAlpha(a, b); |
|
111 +static inline int screen_byte(int sc, int dc, int sa, int da) { |
|
112 + return sc * da + sa * dc - sc * dc; |
|
113 } |
|
114 static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) { |
|
115 - int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst)); |
|
116 - int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst)); |
|
117 - int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst)); |
|
118 - int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst)); |
|
119 + int sa = SkGetPackedA32(src); |
|
120 + int da = SkGetPackedA32(dst); |
|
121 + int a = srcover_byte(sa, da); |
|
122 + int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, screen_byte); |
|
123 + int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, screen_byte); |
|
124 + int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, screen_byte); |
|
125 + return SkPackARGB32(a, r, g, b); |
|
126 +} |
|
127 + |
|
128 +// kHardLight_Mode |
|
129 +static inline int hardlight_byte(int sc, int dc, int sa, int da) { |
|
130 + if(!sa || !da) |
|
131 + return sc * da; |
|
132 + float Sc = (float)sc/sa; |
|
133 + float Dc = (float)dc/da; |
|
134 + if(Sc <= 0.5) |
|
135 + Sc *= 2 * Dc; |
|
136 + else |
|
137 + Sc = -1 + 2 * Sc + 2 * Dc - 2 * Sc * Dc; |
|
138 + |
|
139 + return Sc * sa * da; |
|
140 +} |
|
141 +static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) { |
|
142 + int sa = SkGetPackedA32(src); |
|
143 + int da = SkGetPackedA32(dst); |
|
144 + int a = srcover_byte(sa, da); |
|
145 + int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, hardlight_byte); |
|
146 + int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, hardlight_byte); |
|
147 + int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, hardlight_byte); |
|
148 return SkPackARGB32(a, r, g, b); |
|
149 } |
|
150 |
|
151 // kOverlay_Mode |
|
152 static inline int overlay_byte(int sc, int dc, int sa, int da) { |
|
153 - int tmp = sc * (255 - da) + dc * (255 - sa); |
|
154 - int rc; |
|
155 - if (2 * dc <= da) { |
|
156 - rc = 2 * sc * dc; |
|
157 - } else { |
|
158 - rc = sa * da - 2 * (da - dc) * (sa - sc); |
|
159 - } |
|
160 - return clamp_div255round(rc + tmp); |
|
161 + return hardlight_byte(dc, sc, da, sa); |
|
162 } |
|
163 static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) { |
|
164 int sa = SkGetPackedA32(src); |
|
165 int da = SkGetPackedA32(dst); |
|
166 int a = srcover_byte(sa, da); |
|
167 - int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
168 - int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
169 - int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
170 + int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, overlay_byte); |
|
171 + int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, overlay_byte); |
|
172 + int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, overlay_byte); |
|
173 return SkPackARGB32(a, r, g, b); |
|
174 } |
|
175 |
|
176 // kDarken_Mode |
|
177 static inline int darken_byte(int sc, int dc, int sa, int da) { |
|
178 - int sd = sc * da; |
|
179 - int ds = dc * sa; |
|
180 - if (sd < ds) { |
|
181 - // srcover |
|
182 - return sc + dc - SkDiv255Round(ds); |
|
183 - } else { |
|
184 - // dstover |
|
185 - return dc + sc - SkDiv255Round(sd); |
|
186 - } |
|
187 + return SkMin32(sc * da, sa * dc); |
|
188 } |
|
189 static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) { |
|
190 int sa = SkGetPackedA32(src); |
|
191 int da = SkGetPackedA32(dst); |
|
192 int a = srcover_byte(sa, da); |
|
193 - int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
194 - int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
195 - int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
196 + int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, darken_byte); |
|
197 + int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, darken_byte); |
|
198 + int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, darken_byte); |
|
199 return SkPackARGB32(a, r, g, b); |
|
200 } |
|
201 |
|
202 // kLighten_Mode |
|
203 static inline int lighten_byte(int sc, int dc, int sa, int da) { |
|
204 - int sd = sc * da; |
|
205 - int ds = dc * sa; |
|
206 - if (sd > ds) { |
|
207 - // srcover |
|
208 - return sc + dc - SkDiv255Round(ds); |
|
209 - } else { |
|
210 - // dstover |
|
211 - return dc + sc - SkDiv255Round(sd); |
|
212 - } |
|
213 + return SkMax32(sc * da, sa * dc); |
|
214 } |
|
215 static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) { |
|
216 int sa = SkGetPackedA32(src); |
|
217 int da = SkGetPackedA32(dst); |
|
218 int a = srcover_byte(sa, da); |
|
219 - int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
220 - int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
221 - int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
222 + int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, lighten_byte); |
|
223 + int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, lighten_byte); |
|
224 + int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, lighten_byte); |
|
225 return SkPackARGB32(a, r, g, b); |
|
226 } |
|
227 |
|
228 // kColorDodge_Mode |
|
229 static inline int colordodge_byte(int sc, int dc, int sa, int da) { |
|
230 - int diff = sa - sc; |
|
231 - int rc; |
|
232 - if (0 == diff) { |
|
233 - rc = sa * da + sc * (255 - da) + dc * (255 - sa); |
|
234 - rc = SkDiv255Round(rc); |
|
235 - } else { |
|
236 - int tmp = (dc * sa << 15) / (da * diff); |
|
237 - rc = SkDiv255Round(sa * da) * tmp >> 15; |
|
238 - // don't clamp here, since we'll do it in our modeproc |
|
239 - } |
|
240 - return rc; |
|
241 + if (dc == 0) |
|
242 + return 0; |
|
243 + // Avoid division by 0 |
|
244 + if (sc == sa) |
|
245 + return da * sa; |
|
246 + |
|
247 + return SkMin32(sa * da, sa * sa * dc / (sa - sc)); |
|
248 } |
|
249 static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) { |
|
250 - // added to avoid div-by-zero in colordodge_byte |
|
251 - if (0 == dst) { |
|
252 - return src; |
|
253 - } |
|
254 - |
|
255 int sa = SkGetPackedA32(src); |
|
256 int da = SkGetPackedA32(dst); |
|
257 int a = srcover_byte(sa, da); |
|
258 - int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
259 - int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
260 - int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
261 - r = clamp_max(r, a); |
|
262 - g = clamp_max(g, a); |
|
263 - b = clamp_max(b, a); |
|
264 + int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, colordodge_byte); |
|
265 + int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, colordodge_byte); |
|
266 + int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, colordodge_byte); |
|
267 return SkPackARGB32(a, r, g, b); |
|
268 } |
|
269 |
|
270 // kColorBurn_Mode |
|
271 static inline int colorburn_byte(int sc, int dc, int sa, int da) { |
|
272 - int rc; |
|
273 - if (dc == da && 0 == sc) { |
|
274 - rc = sa * da + dc * (255 - sa); |
|
275 - } else if (0 == sc) { |
|
276 - return SkAlphaMulAlpha(dc, 255 - sa); |
|
277 - } else { |
|
278 - int tmp = (sa * (da - dc) * 256) / (sc * da); |
|
279 - if (tmp > 256) { |
|
280 - tmp = 256; |
|
281 - } |
|
282 - int tmp2 = sa * da; |
|
283 - rc = tmp2 - (tmp2 * tmp >> 8) + sc * (255 - da) + dc * (255 - sa); |
|
284 - } |
|
285 - return SkDiv255Round(rc); |
|
286 + // Avoid division by 0 |
|
287 + if(dc == da) |
|
288 + return sa * da; |
|
289 + if(sc == 0) |
|
290 + return 0; |
|
291 + |
|
292 + return sa * da - SkMin32(sa * da, sa * sa * (da - dc) / sc); |
|
293 } |
|
294 static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) { |
|
295 - // added to avoid div-by-zero in colorburn_byte |
|
296 - if (0 == dst) { |
|
297 - return src; |
|
298 - } |
|
299 - |
|
300 int sa = SkGetPackedA32(src); |
|
301 int da = SkGetPackedA32(dst); |
|
302 int a = srcover_byte(sa, da); |
|
303 - int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
304 - int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
305 - int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
306 - return SkPackARGB32(a, r, g, b); |
|
307 -} |
|
308 - |
|
309 -// kHardLight_Mode |
|
310 -static inline int hardlight_byte(int sc, int dc, int sa, int da) { |
|
311 - int rc; |
|
312 - if (2 * sc <= sa) { |
|
313 - rc = 2 * sc * dc; |
|
314 - } else { |
|
315 - rc = sa * da - 2 * (da - dc) * (sa - sc); |
|
316 - } |
|
317 - return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa)); |
|
318 -} |
|
319 -static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) { |
|
320 - int sa = SkGetPackedA32(src); |
|
321 - int da = SkGetPackedA32(dst); |
|
322 - int a = srcover_byte(sa, da); |
|
323 - int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
324 - int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
325 - int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
326 + int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, colorburn_byte); |
|
327 + int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, colorburn_byte); |
|
328 + int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, colorburn_byte); |
|
329 return SkPackARGB32(a, r, g, b); |
|
330 } |
|
331 |
|
332 // returns 255 * sqrt(n/255) |
|
333 static U8CPU sqrt_unit_byte(U8CPU n) { |
|
334 return SkSqrtBits(n, 15+4); |
|
335 } |
|
336 |
|
337 // kSoftLight_Mode |
|
338 static inline int softlight_byte(int sc, int dc, int sa, int da) { |
|
339 int m = da ? dc * 256 / da : 0; |
|
340 int rc; |
|
341 - if (2 * sc <= sa) { |
|
342 - rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8)); |
|
343 - } else if (4 * dc <= da) { |
|
344 + if (2 * sc <= sa) |
|
345 + return dc * (sa + ((2 * sc - sa) * (256 - m) >> 8)); |
|
346 + |
|
347 + if (4 * dc <= da) { |
|
348 int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m; |
|
349 - rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); |
|
350 - } else { |
|
351 - int tmp = sqrt_unit_byte(m) - m; |
|
352 - rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); |
|
353 + return dc * sa + (da * (2 * sc - sa) * tmp >> 8); |
|
354 } |
|
355 - return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa)); |
|
356 + int tmp = sqrt_unit_byte(m) - m; |
|
357 + return rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); |
|
358 } |
|
359 static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) { |
|
360 int sa = SkGetPackedA32(src); |
|
361 int da = SkGetPackedA32(dst); |
|
362 int a = srcover_byte(sa, da); |
|
363 - int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
364 - int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
365 - int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
366 + int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, softlight_byte); |
|
367 + int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, softlight_byte); |
|
368 + int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, softlight_byte); |
|
369 return SkPackARGB32(a, r, g, b); |
|
370 } |
|
371 |
|
372 // kDifference_Mode |
|
373 static inline int difference_byte(int sc, int dc, int sa, int da) { |
|
374 - int tmp = SkMin32(sc * da, dc * sa); |
|
375 - return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp)); |
|
376 + int tmp = dc * sa - sc * da; |
|
377 + if(tmp<0) |
|
378 + return - tmp; |
|
379 + |
|
380 + return tmp; |
|
381 } |
|
382 static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) { |
|
383 int sa = SkGetPackedA32(src); |
|
384 int da = SkGetPackedA32(dst); |
|
385 int a = srcover_byte(sa, da); |
|
386 - int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
387 - int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
388 - int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
389 + int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, difference_byte); |
|
390 + int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, difference_byte); |
|
391 + int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, difference_byte); |
|
392 return SkPackARGB32(a, r, g, b); |
|
393 } |
|
394 |
|
395 // kExclusion_Mode |
|
396 static inline int exclusion_byte(int sc, int dc, int sa, int da) { |
|
397 - // this equations is wacky, wait for SVG to confirm it |
|
398 - int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa); |
|
399 - return clamp_div255round(r); |
|
400 + return sc * da + dc * sa - 2 * dc * sc; |
|
401 } |
|
402 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) { |
|
403 int sa = SkGetPackedA32(src); |
|
404 int da = SkGetPackedA32(dst); |
|
405 int a = srcover_byte(sa, da); |
|
406 - int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
407 - int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
408 - int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
409 + int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, exclusion_byte); |
|
410 + int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, exclusion_byte); |
|
411 + int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, exclusion_byte); |
|
412 + return SkPackARGB32(a, r, g, b); |
|
413 +} |
|
414 + |
|
415 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
416 +struct BlendColor { |
|
417 + float r; |
|
418 + float g; |
|
419 + float b; |
|
420 + |
|
421 + BlendColor(): r(0), g(0), b(0) |
|
422 + {} |
|
423 +}; |
|
424 + |
|
425 +static inline float Lum(BlendColor C) |
|
426 +{ |
|
427 + return C.r * 0.3 + C.g * 0.59 + C.b* 0.11; |
|
428 +} |
|
429 + |
|
430 +static inline float SkMinFloat(float a, float b) |
|
431 +{ |
|
432 + if (a > b) |
|
433 + a = b; |
|
434 + return a; |
|
435 +} |
|
436 + |
|
437 +static inline float SkMaxFloat(float a, float b) |
|
438 +{ |
|
439 + if (a < b) |
|
440 + a = b; |
|
441 + return a; |
|
442 +} |
|
443 + |
|
444 +#define minimum(C) SkMinFloat(SkMinFloat(C.r, C.g), C.b) |
|
445 +#define maximum(C) SkMaxFloat(SkMaxFloat(C.r, C.g), C.b) |
|
446 + |
|
447 +static inline float Sat(BlendColor c) { |
|
448 + return maximum(c) - minimum(c); |
|
449 +} |
|
450 + |
|
451 +static inline void setSaturationComponents(float& Cmin, float& Cmid, float& Cmax, float s) { |
|
452 + if(Cmax > Cmin) { |
|
453 + Cmid = (((Cmid - Cmin) * s ) / (Cmax - Cmin)); |
|
454 + Cmax = s; |
|
455 + } else { |
|
456 + Cmax = 0; |
|
457 + Cmid = 0; |
|
458 + } |
|
459 + Cmin = 0; |
|
460 +} |
|
461 + |
|
462 +static inline BlendColor SetSat(BlendColor C, float s) { |
|
463 + if(C.r <= C.g) { |
|
464 + if(C.g <= C.b) |
|
465 + setSaturationComponents(C.r, C.g, C.b, s); |
|
466 + else |
|
467 + if(C.r <= C.b) |
|
468 + setSaturationComponents(C.r, C.b, C.g, s); |
|
469 + else |
|
470 + setSaturationComponents(C.b, C.r, C.g, s); |
|
471 + } else if(C.r <= C.b) |
|
472 + setSaturationComponents(C.g, C.r, C.b, s); |
|
473 + else |
|
474 + if(C.g <= C.b) |
|
475 + setSaturationComponents(C.g, C.b, C.r, s); |
|
476 + else |
|
477 + setSaturationComponents(C.b, C.g, C.r, s); |
|
478 + |
|
479 + return C; |
|
480 +} |
|
481 + |
|
482 +static inline BlendColor clipColor(BlendColor C) { |
|
483 + float L = Lum(C); |
|
484 + float n = minimum(C); |
|
485 + float x = maximum(C); |
|
486 + if(n < 0) { |
|
487 + C.r = L + (((C.r - L) * L) / (L - n)); |
|
488 + C.g = L + (((C.g - L) * L) / (L - n)); |
|
489 + C.b = L + (((C.b - L) * L) / (L - n)); |
|
490 + } |
|
491 + |
|
492 + if(x > 1) { |
|
493 + C.r = L + (((C.r - L) * (1 - L)) / (x - L)); |
|
494 + C.g = L + (((C.g - L) * (1 - L)) / (x - L)); |
|
495 + C.b = L + (((C.b - L) * (1 - L)) / (x - L)); |
|
496 + } |
|
497 + return C; |
|
498 +} |
|
499 + |
|
500 +static inline BlendColor SetLum(BlendColor C, float l) { |
|
501 + float d = l - Lum(C); |
|
502 + C.r += d; |
|
503 + C.g += d; |
|
504 + C.b += d; |
|
505 + |
|
506 + return clipColor(C); |
|
507 +} |
|
508 + |
|
509 +#define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \ |
|
510 + clamp_div255round(sc * (255 - da) + dc * (255 - sa) + (int)(sa * da * blendval)) |
|
511 + |
|
512 +static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) { |
|
513 + int sr = SkGetPackedR32(src); |
|
514 + int sg = SkGetPackedG32(src); |
|
515 + int sb = SkGetPackedB32(src); |
|
516 + int sa = SkGetPackedA32(src); |
|
517 + |
|
518 + int dr = SkGetPackedR32(dst); |
|
519 + int dg = SkGetPackedG32(dst); |
|
520 + int db = SkGetPackedB32(dst); |
|
521 + int da = SkGetPackedA32(dst); |
|
522 + |
|
523 + BlendColor Cs; |
|
524 + if(sa) { |
|
525 + Cs.r = (float)sr / sa; |
|
526 + Cs.g = (float)sg / sa; |
|
527 + Cs.b = (float)sb / sa; |
|
528 + BlendColor Cd; |
|
529 + if(da) { |
|
530 + Cd.r = (float)dr / da; |
|
531 + Cd.g = (float)dg / da; |
|
532 + Cd.b = (float)db / da; |
|
533 + Cs = SetLum(SetSat(Cs, Sat(Cd)), Lum(Cd)); |
|
534 + } |
|
535 + } |
|
536 + |
|
537 + int a = srcover_byte(sa, da); |
|
538 + int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r); |
|
539 + int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g); |
|
540 + int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b); |
|
541 + return SkPackARGB32(a, r, g, b); |
|
542 +} |
|
543 + |
|
544 +static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) { |
|
545 + int sr = SkGetPackedR32(src); |
|
546 + int sg = SkGetPackedG32(src); |
|
547 + int sb = SkGetPackedB32(src); |
|
548 + int sa = SkGetPackedA32(src); |
|
549 + |
|
550 + int dr = SkGetPackedR32(dst); |
|
551 + int dg = SkGetPackedG32(dst); |
|
552 + int db = SkGetPackedB32(dst); |
|
553 + int da = SkGetPackedA32(dst); |
|
554 + |
|
555 + BlendColor Cs; |
|
556 + if(sa) { |
|
557 + Cs.r = (float)sr / sa; |
|
558 + Cs.g = (float)sg / sa; |
|
559 + Cs.b = (float)sb / sa; |
|
560 + BlendColor Cd; |
|
561 + if(da) { |
|
562 + Cd.r = (float)dr / da; |
|
563 + Cd.g = (float)dg / da; |
|
564 + Cd.b = (float)db / da; |
|
565 + Cs = SetLum(SetSat(Cd, Sat(Cs)), Lum(Cd)); |
|
566 + } |
|
567 + } |
|
568 + |
|
569 + int a = srcover_byte(sa, da); |
|
570 + int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r); |
|
571 + int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g); |
|
572 + int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b); |
|
573 + return SkPackARGB32(a, r, g, b); |
|
574 +} |
|
575 + |
|
576 +static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) { |
|
577 + int sr = SkGetPackedR32(src); |
|
578 + int sg = SkGetPackedG32(src); |
|
579 + int sb = SkGetPackedB32(src); |
|
580 + int sa = SkGetPackedA32(src); |
|
581 + |
|
582 + int dr = SkGetPackedR32(dst); |
|
583 + int dg = SkGetPackedG32(dst); |
|
584 + int db = SkGetPackedB32(dst); |
|
585 + int da = SkGetPackedA32(dst); |
|
586 + |
|
587 + BlendColor Cs; |
|
588 + if(sa) { |
|
589 + Cs.r = (float)sr / sa; |
|
590 + Cs.g = (float)sg / sa; |
|
591 + Cs.b = (float)sb / sa; |
|
592 + BlendColor Cd; |
|
593 + if(da) { |
|
594 + Cd.r = (float)dr / da; |
|
595 + Cd.g = (float)dg / da; |
|
596 + Cd.b = (float)db / da; |
|
597 + Cs = SetLum(Cs, Lum(Cd)); |
|
598 + } |
|
599 + } |
|
600 + |
|
601 + int a = srcover_byte(sa, da); |
|
602 + int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r); |
|
603 + int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g); |
|
604 + int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b); |
|
605 + return SkPackARGB32(a, r, g, b); |
|
606 +} |
|
607 + |
|
608 +static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) { |
|
609 + int sr = SkGetPackedR32(src); |
|
610 + int sg = SkGetPackedG32(src); |
|
611 + int sb = SkGetPackedB32(src); |
|
612 + int sa = SkGetPackedA32(src); |
|
613 + |
|
614 + int dr = SkGetPackedR32(dst); |
|
615 + int dg = SkGetPackedG32(dst); |
|
616 + int db = SkGetPackedB32(dst); |
|
617 + int da = SkGetPackedA32(dst); |
|
618 + |
|
619 + BlendColor Cs; |
|
620 + if(sa) { |
|
621 + Cs.r = (float)sr / sa; |
|
622 + Cs.g = (float)sg / sa; |
|
623 + Cs.b = (float)sb / sa; |
|
624 + BlendColor Cd; |
|
625 + if(da) { |
|
626 + Cd.r = (float)dr / da; |
|
627 + Cd.g = (float)dg / da; |
|
628 + Cd.b = (float)db / da; |
|
629 + Cs = SetLum(Cd, Lum(Cs)); |
|
630 + } |
|
631 + } |
|
632 + |
|
633 + int a = srcover_byte(sa, da); |
|
634 + int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r); |
|
635 + int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g); |
|
636 + int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b); |
|
637 return SkPackARGB32(a, r, g, b); |
|
638 } |
|
639 |
|
640 struct ProcCoeff { |
|
641 SkXfermodeProc fProc; |
|
642 SkXfermode::Coeff fSC; |
|
643 SkXfermode::Coeff fDC; |
|
644 }; |
|
645 @@ -430,27 +627,31 @@ static const ProcCoeff gProcCoeffs[] = { |
|
646 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff }, |
|
647 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff }, |
|
648 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff }, |
|
649 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff }, |
|
650 { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff }, |
|
651 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff }, |
|
652 |
|
653 { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff }, |
|
654 - { multiply_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff }, |
|
655 + { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF}, |
|
656 { screen_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
657 { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
658 { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
659 { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
660 { colordodge_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
661 { colorburn_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
662 { hardlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
663 { softlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
664 { difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
665 { exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
666 + { hue_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
667 + { saturation_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
668 + { color_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
669 + { luminosity_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
670 }; |
|
671 |
|
672 /////////////////////////////////////////////////////////////////////////////// |
|
673 |
|
674 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) { |
|
675 return false; |
|
676 } |
|
677 |
|
678 @@ -1172,16 +1373,20 @@ static const Proc16Rec gModeProcs16[] = |
|
679 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken |
|
680 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten |
|
681 { NULL, NULL, NULL }, // colordodge |
|
682 { NULL, NULL, NULL }, // colorburn |
|
683 { NULL, NULL, NULL }, // hardlight |
|
684 { NULL, NULL, NULL }, // softlight |
|
685 { NULL, NULL, NULL }, // difference |
|
686 { NULL, NULL, NULL }, // exclusion |
|
687 + { NULL, NULL, NULL }, // hue |
|
688 + { NULL, NULL, NULL }, // saturation |
|
689 + { NULL, NULL, NULL }, // color |
|
690 + { NULL, NULL, NULL }, // luminosity |
|
691 }; |
|
692 |
|
693 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) { |
|
694 SkXfermodeProc16 proc16 = NULL; |
|
695 if ((unsigned)mode < kModeCount) { |
|
696 const Proc16Rec& rec = gModeProcs16[mode]; |
|
697 unsigned a = SkColorGetA(srcColor); |
|
698 |