Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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
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]
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,
22 // all above modes can be expressed as pair of src/dst Coeffs
23 kCoeffModesCnt,
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,
42 - kLastMode = kExclusion_Mode
43 + kLastMode = kLuminosity_Mode
44 };
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 */
59 #include "SkXfermode.h"
60 #include "SkColorPriv.h"
61 #include "SkFlattenableBuffers.h"
62 #include "SkMathPriv.h"
64 +#include <algorithm>
65 +
66 SK_DEFINE_INST_COUNT(SkXfermode)
68 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b)
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
332 // returns 255 * sqrt(n/255)
333 static U8CPU sqrt_unit_byte(U8CPU n) {
334 return SkSqrtBits(n, 15+4);
335 }
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 }
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 }
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 }
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 },
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 };
672 ///////////////////////////////////////////////////////////////////////////////
674 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) {
675 return false;
676 }
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 };
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);