Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
2 /*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
10 #include "SkXfermode.h"
11 #include "SkXfermode_proccoeff.h"
12 #include "SkColorPriv.h"
13 #include "SkReadBuffer.h"
14 #include "SkWriteBuffer.h"
15 #include "SkMathPriv.h"
16 #include "SkString.h"
17 #include "SkUtilsArm.h"
19 #if !SK_ARM_NEON_IS_NONE
20 #include "SkXfermode_opts_arm_neon.h"
21 #endif
23 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b)
25 #if 0
26 // idea for higher precision blends in xfer procs (and slightly faster)
27 // see DstATop as a probable caller
28 static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
29 SkASSERT(a <= 255);
30 SkASSERT(b <= 255);
31 SkASSERT(c <= 255);
32 SkASSERT(d <= 255);
33 unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
34 unsigned result = (prod + (prod >> 8)) >> 8;
35 SkASSERT(result <= 255);
36 return result;
37 }
38 #endif
40 static inline unsigned saturated_add(unsigned a, unsigned b) {
41 SkASSERT(a <= 255);
42 SkASSERT(b <= 255);
43 unsigned sum = a + b;
44 if (sum > 255) {
45 sum = 255;
46 }
47 return sum;
48 }
50 static inline int clamp_signed_byte(int n) {
51 if (n < 0) {
52 n = 0;
53 } else if (n > 255) {
54 n = 255;
55 }
56 return n;
57 }
59 static inline int clamp_div255round(int prod) {
60 if (prod <= 0) {
61 return 0;
62 } else if (prod >= 255*255) {
63 return 255;
64 } else {
65 return SkDiv255Round(prod);
66 }
67 }
69 ///////////////////////////////////////////////////////////////////////////////
71 // kClear_Mode, //!< [0, 0]
72 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
73 return 0;
74 }
76 // kSrc_Mode, //!< [Sa, Sc]
77 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
78 return src;
79 }
81 // kDst_Mode, //!< [Da, Dc]
82 static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
83 return dst;
84 }
86 // kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
87 static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
88 #if 0
89 // this is the old, more-correct way, but it doesn't guarantee that dst==255
90 // will always stay opaque
91 return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
92 #else
93 // this is slightly faster, but more importantly guarantees that dst==255
94 // will always stay opaque
95 return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
96 #endif
97 }
99 // kDstOver_Mode, //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
100 static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
101 // this is the reverse of srcover, just flipping src and dst
102 // see srcover's comment about the 256 for opaqueness guarantees
103 return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
104 }
106 // kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
107 static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
108 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
109 }
111 // kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
112 static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
113 return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
114 }
116 // kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
117 static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
118 return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
119 }
121 // kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
122 static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
123 return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
124 }
126 // kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
127 static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
128 unsigned sa = SkGetPackedA32(src);
129 unsigned da = SkGetPackedA32(dst);
130 unsigned isa = 255 - sa;
132 return SkPackARGB32(da,
133 SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
134 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
135 SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
136 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
137 SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
138 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
139 }
141 // kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
142 static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
143 unsigned sa = SkGetPackedA32(src);
144 unsigned da = SkGetPackedA32(dst);
145 unsigned ida = 255 - da;
147 return SkPackARGB32(sa,
148 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
149 SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
150 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
151 SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
152 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
153 SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
154 }
156 // kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
157 static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
158 unsigned sa = SkGetPackedA32(src);
159 unsigned da = SkGetPackedA32(dst);
160 unsigned isa = 255 - sa;
161 unsigned ida = 255 - da;
163 return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
164 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
165 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
166 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
167 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
168 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
169 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
170 }
172 ///////////////////////////////////////////////////////////////////////////////
174 // kPlus_Mode
175 static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
176 unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
177 unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
178 unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
179 unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
180 return SkPackARGB32(a, r, g, b);
181 }
183 // kModulate_Mode
184 static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
185 int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
186 int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
187 int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
188 int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
189 return SkPackARGB32(a, r, g, b);
190 }
192 static inline int srcover_byte(int a, int b) {
193 return a + b - SkAlphaMulAlpha(a, b);
194 }
196 // kMultiply_Mode
197 // B(Cb, Cs) = Cb x Cs
198 // multiply uses its own version of blendfunc_byte because sa and da are not needed
199 static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
200 return clamp_div255round(sc * (255 - da) + dc * (255 - sa) + sc * dc);
201 }
203 static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
204 int sa = SkGetPackedA32(src);
205 int da = SkGetPackedA32(dst);
206 int a = srcover_byte(sa, da);
207 int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
208 int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
209 int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
210 return SkPackARGB32(a, r, g, b);
211 }
213 // kScreen_Mode
214 static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
215 int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
216 int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
217 int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
218 int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
219 return SkPackARGB32(a, r, g, b);
220 }
222 // kOverlay_Mode
223 static inline int overlay_byte(int sc, int dc, int sa, int da) {
224 int tmp = sc * (255 - da) + dc * (255 - sa);
225 int rc;
226 if (2 * dc <= da) {
227 rc = 2 * sc * dc;
228 } else {
229 rc = sa * da - 2 * (da - dc) * (sa - sc);
230 }
231 return clamp_div255round(rc + tmp);
232 }
233 static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
234 int sa = SkGetPackedA32(src);
235 int da = SkGetPackedA32(dst);
236 int a = srcover_byte(sa, da);
237 int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
238 int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
239 int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
240 return SkPackARGB32(a, r, g, b);
241 }
243 // kDarken_Mode
244 static inline int darken_byte(int sc, int dc, int sa, int da) {
245 int sd = sc * da;
246 int ds = dc * sa;
247 if (sd < ds) {
248 // srcover
249 return sc + dc - SkDiv255Round(ds);
250 } else {
251 // dstover
252 return dc + sc - SkDiv255Round(sd);
253 }
254 }
255 static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
256 int sa = SkGetPackedA32(src);
257 int da = SkGetPackedA32(dst);
258 int a = srcover_byte(sa, da);
259 int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
260 int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
261 int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
262 return SkPackARGB32(a, r, g, b);
263 }
265 // kLighten_Mode
266 static inline int lighten_byte(int sc, int dc, int sa, int da) {
267 int sd = sc * da;
268 int ds = dc * sa;
269 if (sd > ds) {
270 // srcover
271 return sc + dc - SkDiv255Round(ds);
272 } else {
273 // dstover
274 return dc + sc - SkDiv255Round(sd);
275 }
276 }
277 static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
278 int sa = SkGetPackedA32(src);
279 int da = SkGetPackedA32(dst);
280 int a = srcover_byte(sa, da);
281 int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
282 int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
283 int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
284 return SkPackARGB32(a, r, g, b);
285 }
287 // kColorDodge_Mode
288 static inline int colordodge_byte(int sc, int dc, int sa, int da) {
289 int diff = sa - sc;
290 int rc;
291 if (0 == dc) {
292 return SkAlphaMulAlpha(sc, 255 - da);
293 } else if (0 == diff) {
294 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
295 } else {
296 diff = dc * sa / diff;
297 rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
298 }
299 return clamp_div255round(rc);
300 }
301 static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
302 int sa = SkGetPackedA32(src);
303 int da = SkGetPackedA32(dst);
304 int a = srcover_byte(sa, da);
305 int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
306 int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
307 int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
308 return SkPackARGB32(a, r, g, b);
309 }
311 // kColorBurn_Mode
312 static inline int colorburn_byte(int sc, int dc, int sa, int da) {
313 int rc;
314 if (dc == da) {
315 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
316 } else if (0 == sc) {
317 return SkAlphaMulAlpha(dc, 255 - sa);
318 } else {
319 int tmp = (da - dc) * sa / sc;
320 rc = sa * (da - ((da < tmp) ? da : tmp))
321 + sc * (255 - da) + dc * (255 - sa);
322 }
323 return clamp_div255round(rc);
324 }
325 static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
326 int sa = SkGetPackedA32(src);
327 int da = SkGetPackedA32(dst);
328 int a = srcover_byte(sa, da);
329 int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
330 int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
331 int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
332 return SkPackARGB32(a, r, g, b);
333 }
335 // kHardLight_Mode
336 static inline int hardlight_byte(int sc, int dc, int sa, int da) {
337 int rc;
338 if (2 * sc <= sa) {
339 rc = 2 * sc * dc;
340 } else {
341 rc = sa * da - 2 * (da - dc) * (sa - sc);
342 }
343 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
344 }
345 static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
346 int sa = SkGetPackedA32(src);
347 int da = SkGetPackedA32(dst);
348 int a = srcover_byte(sa, da);
349 int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
350 int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
351 int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
352 return SkPackARGB32(a, r, g, b);
353 }
355 // returns 255 * sqrt(n/255)
356 static U8CPU sqrt_unit_byte(U8CPU n) {
357 return SkSqrtBits(n, 15+4);
358 }
360 // kSoftLight_Mode
361 static inline int softlight_byte(int sc, int dc, int sa, int da) {
362 int m = da ? dc * 256 / da : 0;
363 int rc;
364 if (2 * sc <= sa) {
365 rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
366 } else if (4 * dc <= da) {
367 int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
368 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
369 } else {
370 int tmp = sqrt_unit_byte(m) - m;
371 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
372 }
373 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
374 }
375 static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
376 int sa = SkGetPackedA32(src);
377 int da = SkGetPackedA32(dst);
378 int a = srcover_byte(sa, da);
379 int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
380 int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
381 int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
382 return SkPackARGB32(a, r, g, b);
383 }
385 // kDifference_Mode
386 static inline int difference_byte(int sc, int dc, int sa, int da) {
387 int tmp = SkMin32(sc * da, dc * sa);
388 return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
389 }
390 static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
391 int sa = SkGetPackedA32(src);
392 int da = SkGetPackedA32(dst);
393 int a = srcover_byte(sa, da);
394 int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
395 int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
396 int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
397 return SkPackARGB32(a, r, g, b);
398 }
400 // kExclusion_Mode
401 static inline int exclusion_byte(int sc, int dc, int, int) {
402 // this equations is wacky, wait for SVG to confirm it
403 //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
405 // The above equation can be simplified as follows
406 int r = 255*(sc + dc) - 2 * sc * dc;
407 return clamp_div255round(r);
408 }
409 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
410 int sa = SkGetPackedA32(src);
411 int da = SkGetPackedA32(dst);
412 int a = srcover_byte(sa, da);
413 int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
414 int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
415 int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
416 return SkPackARGB32(a, r, g, b);
417 }
419 // The CSS compositing spec introduces the following formulas:
420 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
421 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
422 // while PDF and CG uses the one from Rec. Rec. 601
423 // See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
424 static inline int Lum(int r, int g, int b)
425 {
426 return SkDiv255Round(r * 77 + g * 150 + b * 28);
427 }
429 static inline int min2(int a, int b) { return a < b ? a : b; }
430 static inline int max2(int a, int b) { return a > b ? a : b; }
431 #define minimum(a, b, c) min2(min2(a, b), c)
432 #define maximum(a, b, c) max2(max2(a, b), c)
434 static inline int Sat(int r, int g, int b) {
435 return maximum(r, g, b) - minimum(r, g, b);
436 }
438 static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
439 if(*Cmax > *Cmin) {
440 *Cmid = SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
441 *Cmax = s;
442 } else {
443 *Cmax = 0;
444 *Cmid = 0;
445 }
447 *Cmin = 0;
448 }
450 static inline void SetSat(int* r, int* g, int* b, int s) {
451 if(*r <= *g) {
452 if(*g <= *b) {
453 setSaturationComponents(r, g, b, s);
454 } else if(*r <= *b) {
455 setSaturationComponents(r, b, g, s);
456 } else {
457 setSaturationComponents(b, r, g, s);
458 }
459 } else if(*r <= *b) {
460 setSaturationComponents(g, r, b, s);
461 } else if(*g <= *b) {
462 setSaturationComponents(g, b, r, s);
463 } else {
464 setSaturationComponents(b, g, r, s);
465 }
466 }
468 static inline void clipColor(int* r, int* g, int* b, int a) {
469 int L = Lum(*r, *g, *b);
470 int n = minimum(*r, *g, *b);
471 int x = maximum(*r, *g, *b);
472 int denom;
473 if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
474 *r = L + SkMulDiv(*r - L, L, denom);
475 *g = L + SkMulDiv(*g - L, L, denom);
476 *b = L + SkMulDiv(*b - L, L, denom);
477 }
479 if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
480 int numer = a - L;
481 *r = L + SkMulDiv(*r - L, numer, denom);
482 *g = L + SkMulDiv(*g - L, numer, denom);
483 *b = L + SkMulDiv(*b - L, numer, denom);
484 }
485 }
487 static inline void SetLum(int* r, int* g, int* b, int a, int l) {
488 int d = l - Lum(*r, *g, *b);
489 *r += d;
490 *g += d;
491 *b += d;
493 clipColor(r, g, b, a);
494 }
496 // non-separable blend modes are done in non-premultiplied alpha
497 #define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
498 clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendval)
500 // kHue_Mode
501 // B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
502 // Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
503 static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
504 int sr = SkGetPackedR32(src);
505 int sg = SkGetPackedG32(src);
506 int sb = SkGetPackedB32(src);
507 int sa = SkGetPackedA32(src);
509 int dr = SkGetPackedR32(dst);
510 int dg = SkGetPackedG32(dst);
511 int db = SkGetPackedB32(dst);
512 int da = SkGetPackedA32(dst);
513 int Sr, Sg, Sb;
515 if(sa && da) {
516 Sr = sr * sa;
517 Sg = sg * sa;
518 Sb = sb * sa;
519 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
520 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
521 } else {
522 Sr = 0;
523 Sg = 0;
524 Sb = 0;
525 }
527 int a = srcover_byte(sa, da);
528 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
529 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
530 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
531 return SkPackARGB32(a, r, g, b);
532 }
534 // kSaturation_Mode
535 // B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
536 // Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
537 static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
538 int sr = SkGetPackedR32(src);
539 int sg = SkGetPackedG32(src);
540 int sb = SkGetPackedB32(src);
541 int sa = SkGetPackedA32(src);
543 int dr = SkGetPackedR32(dst);
544 int dg = SkGetPackedG32(dst);
545 int db = SkGetPackedB32(dst);
546 int da = SkGetPackedA32(dst);
547 int Dr, Dg, Db;
549 if(sa && da) {
550 Dr = dr * sa;
551 Dg = dg * sa;
552 Db = db * sa;
553 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
554 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
555 } else {
556 Dr = 0;
557 Dg = 0;
558 Db = 0;
559 }
561 int a = srcover_byte(sa, da);
562 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
563 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
564 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
565 return SkPackARGB32(a, r, g, b);
566 }
568 // kColor_Mode
569 // B(Cb, Cs) = SetLum(Cs, Lum(Cb))
570 // Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
571 static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
572 int sr = SkGetPackedR32(src);
573 int sg = SkGetPackedG32(src);
574 int sb = SkGetPackedB32(src);
575 int sa = SkGetPackedA32(src);
577 int dr = SkGetPackedR32(dst);
578 int dg = SkGetPackedG32(dst);
579 int db = SkGetPackedB32(dst);
580 int da = SkGetPackedA32(dst);
581 int Sr, Sg, Sb;
583 if(sa && da) {
584 Sr = sr * da;
585 Sg = sg * da;
586 Sb = sb * da;
587 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
588 } else {
589 Sr = 0;
590 Sg = 0;
591 Sb = 0;
592 }
594 int a = srcover_byte(sa, da);
595 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
596 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
597 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
598 return SkPackARGB32(a, r, g, b);
599 }
601 // kLuminosity_Mode
602 // B(Cb, Cs) = SetLum(Cb, Lum(Cs))
603 // Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
604 static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
605 int sr = SkGetPackedR32(src);
606 int sg = SkGetPackedG32(src);
607 int sb = SkGetPackedB32(src);
608 int sa = SkGetPackedA32(src);
610 int dr = SkGetPackedR32(dst);
611 int dg = SkGetPackedG32(dst);
612 int db = SkGetPackedB32(dst);
613 int da = SkGetPackedA32(dst);
614 int Dr, Dg, Db;
616 if(sa && da) {
617 Dr = dr * sa;
618 Dg = dg * sa;
619 Db = db * sa;
620 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
621 } else {
622 Dr = 0;
623 Dg = 0;
624 Db = 0;
625 }
627 int a = srcover_byte(sa, da);
628 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
629 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
630 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
631 return SkPackARGB32(a, r, g, b);
632 }
634 const ProcCoeff gProcCoeffs[] = {
635 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff },
636 { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff },
637 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff },
638 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff },
639 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff },
640 { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff },
641 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff },
642 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff },
643 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff },
644 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff },
645 { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff },
646 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff },
648 { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff },
649 { modulate_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff },
650 { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff },
651 { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
652 { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
653 { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
654 { colordodge_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
655 { colorburn_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
656 { hardlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
657 { softlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
658 { difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
659 { exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
660 { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
661 { hue_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
662 { saturation_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
663 { color_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
664 { luminosity_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
665 };
667 ///////////////////////////////////////////////////////////////////////////////
669 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const {
670 return false;
671 }
673 bool SkXfermode::asMode(Mode* mode) const {
674 return false;
675 }
677 bool SkXfermode::asNewEffect(GrEffectRef** effect, GrTexture* background) const {
678 return false;
679 }
681 bool SkXfermode::AsNewEffectOrCoeff(SkXfermode* xfermode,
682 GrEffectRef** effect,
683 Coeff* src,
684 Coeff* dst,
685 GrTexture* background) {
686 if (NULL == xfermode) {
687 return ModeAsCoeff(kSrcOver_Mode, src, dst);
688 } else if (xfermode->asCoeff(src, dst)) {
689 return true;
690 } else {
691 return xfermode->asNewEffect(effect, background);
692 }
693 }
695 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
696 // no-op. subclasses should override this
697 return dst;
698 }
700 void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
701 const SkPMColor* SK_RESTRICT src, int count,
702 const SkAlpha* SK_RESTRICT aa) const {
703 SkASSERT(dst && src && count >= 0);
705 if (NULL == aa) {
706 for (int i = count - 1; i >= 0; --i) {
707 dst[i] = this->xferColor(src[i], dst[i]);
708 }
709 } else {
710 for (int i = count - 1; i >= 0; --i) {
711 unsigned a = aa[i];
712 if (0 != a) {
713 SkPMColor dstC = dst[i];
714 SkPMColor C = this->xferColor(src[i], dstC);
715 if (0xFF != a) {
716 C = SkFourByteInterp(C, dstC, a);
717 }
718 dst[i] = C;
719 }
720 }
721 }
722 }
724 void SkXfermode::xfer16(uint16_t* dst,
725 const SkPMColor* SK_RESTRICT src, int count,
726 const SkAlpha* SK_RESTRICT aa) const {
727 SkASSERT(dst && src && count >= 0);
729 if (NULL == aa) {
730 for (int i = count - 1; i >= 0; --i) {
731 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
732 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
733 }
734 } else {
735 for (int i = count - 1; i >= 0; --i) {
736 unsigned a = aa[i];
737 if (0 != a) {
738 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
739 SkPMColor C = this->xferColor(src[i], dstC);
740 if (0xFF != a) {
741 C = SkFourByteInterp(C, dstC, a);
742 }
743 dst[i] = SkPixel32ToPixel16_ToU16(C);
744 }
745 }
746 }
747 }
749 void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
750 const SkPMColor src[], int count,
751 const SkAlpha* SK_RESTRICT aa) const {
752 SkASSERT(dst && src && count >= 0);
754 if (NULL == aa) {
755 for (int i = count - 1; i >= 0; --i) {
756 SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
757 dst[i] = SkToU8(SkGetPackedA32(res));
758 }
759 } else {
760 for (int i = count - 1; i >= 0; --i) {
761 unsigned a = aa[i];
762 if (0 != a) {
763 SkAlpha dstA = dst[i];
764 unsigned A = SkGetPackedA32(this->xferColor(src[i],
765 (SkPMColor)(dstA << SK_A32_SHIFT)));
766 if (0xFF != a) {
767 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
768 }
769 dst[i] = SkToU8(A);
770 }
771 }
772 }
773 }
775 ///////////////////////////////////////////////////////////////////////////////
777 void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
778 const SkPMColor* SK_RESTRICT src, int count,
779 const SkAlpha* SK_RESTRICT aa) const {
780 SkASSERT(dst && src && count >= 0);
782 SkXfermodeProc proc = fProc;
784 if (NULL != proc) {
785 if (NULL == aa) {
786 for (int i = count - 1; i >= 0; --i) {
787 dst[i] = proc(src[i], dst[i]);
788 }
789 } else {
790 for (int i = count - 1; i >= 0; --i) {
791 unsigned a = aa[i];
792 if (0 != a) {
793 SkPMColor dstC = dst[i];
794 SkPMColor C = proc(src[i], dstC);
795 if (a != 0xFF) {
796 C = SkFourByteInterp(C, dstC, a);
797 }
798 dst[i] = C;
799 }
800 }
801 }
802 }
803 }
805 void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst,
806 const SkPMColor* SK_RESTRICT src, int count,
807 const SkAlpha* SK_RESTRICT aa) const {
808 SkASSERT(dst && src && count >= 0);
810 SkXfermodeProc proc = fProc;
812 if (NULL != proc) {
813 if (NULL == aa) {
814 for (int i = count - 1; i >= 0; --i) {
815 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
816 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
817 }
818 } else {
819 for (int i = count - 1; i >= 0; --i) {
820 unsigned a = aa[i];
821 if (0 != a) {
822 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
823 SkPMColor C = proc(src[i], dstC);
824 if (0xFF != a) {
825 C = SkFourByteInterp(C, dstC, a);
826 }
827 dst[i] = SkPixel32ToPixel16_ToU16(C);
828 }
829 }
830 }
831 }
832 }
834 void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
835 const SkPMColor* SK_RESTRICT src, int count,
836 const SkAlpha* SK_RESTRICT aa) const {
837 SkASSERT(dst && src && count >= 0);
839 SkXfermodeProc proc = fProc;
841 if (NULL != proc) {
842 if (NULL == aa) {
843 for (int i = count - 1; i >= 0; --i) {
844 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
845 dst[i] = SkToU8(SkGetPackedA32(res));
846 }
847 } else {
848 for (int i = count - 1; i >= 0; --i) {
849 unsigned a = aa[i];
850 if (0 != a) {
851 SkAlpha dstA = dst[i];
852 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
853 unsigned A = SkGetPackedA32(res);
854 if (0xFF != a) {
855 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
856 }
857 dst[i] = SkToU8(A);
858 }
859 }
860 }
861 }
862 }
864 SkProcXfermode::SkProcXfermode(SkReadBuffer& buffer)
865 : SkXfermode(buffer) {
866 fProc = NULL;
867 if (!buffer.isCrossProcess()) {
868 fProc = (SkXfermodeProc)buffer.readFunctionPtr();
869 }
870 }
872 void SkProcXfermode::flatten(SkWriteBuffer& buffer) const {
873 this->INHERITED::flatten(buffer);
874 if (!buffer.isCrossProcess()) {
875 buffer.writeFunctionPtr((void*)fProc);
876 }
877 }
879 #ifndef SK_IGNORE_TO_STRING
880 void SkProcXfermode::toString(SkString* str) const {
881 str->appendf("SkProcXfermode: %p", fProc);
882 }
883 #endif
885 //////////////////////////////////////////////////////////////////////////////
887 #if SK_SUPPORT_GPU
889 #include "GrEffect.h"
890 #include "GrCoordTransform.h"
891 #include "GrEffectUnitTest.h"
892 #include "GrTBackendEffectFactory.h"
893 #include "gl/GrGLEffect.h"
895 /**
896 * GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs.
897 */
898 class XferEffect : public GrEffect {
899 public:
900 static bool IsSupportedMode(SkXfermode::Mode mode) {
901 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
902 }
904 static GrEffectRef* Create(SkXfermode::Mode mode, GrTexture* background) {
905 if (!IsSupportedMode(mode)) {
906 return NULL;
907 } else {
908 AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode, background)));
909 return CreateEffectRef(effect);
910 }
911 }
913 virtual void getConstantColorComponents(GrColor* color,
914 uint32_t* validFlags) const SK_OVERRIDE {
915 *validFlags = 0;
916 }
918 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
919 return GrTBackendEffectFactory<XferEffect>::getInstance();
920 }
922 static const char* Name() { return "XferEffect"; }
924 SkXfermode::Mode mode() const { return fMode; }
925 const GrTextureAccess& backgroundAccess() const { return fBackgroundAccess; }
927 class GLEffect : public GrGLEffect {
928 public:
929 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
930 : GrGLEffect(factory) {
931 }
932 virtual void emitCode(GrGLShaderBuilder* builder,
933 const GrDrawEffect& drawEffect,
934 EffectKey key,
935 const char* outputColor,
936 const char* inputColor,
937 const TransformedCoordsArray& coords,
938 const TextureSamplerArray& samplers) SK_OVERRIDE {
939 SkXfermode::Mode mode = drawEffect.castEffect<XferEffect>().mode();
940 const GrTexture* backgroundTex = drawEffect.castEffect<XferEffect>().backgroundAccess().getTexture();
941 const char* dstColor;
942 if (backgroundTex) {
943 dstColor = "bgColor";
944 builder->fsCodeAppendf("\t\tvec4 %s = ", dstColor);
945 builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
946 builder->fsCodeAppendf(";\n");
947 } else {
948 dstColor = builder->dstColor();
949 }
950 SkASSERT(NULL != dstColor);
952 // We don't try to optimize for this case at all
953 if (NULL == inputColor) {
954 builder->fsCodeAppendf("\t\tconst vec4 ones = vec4(1);\n");
955 inputColor = "ones";
956 }
957 builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode));
959 // These all perform src-over on the alpha channel.
960 builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n",
961 outputColor, inputColor, inputColor, dstColor);
963 switch (mode) {
964 case SkXfermode::kOverlay_Mode:
965 // Overlay is Hard-Light with the src and dst reversed
966 HardLight(builder, outputColor, dstColor, inputColor);
967 break;
968 case SkXfermode::kDarken_Mode:
969 builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, "
970 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
971 outputColor,
972 inputColor, dstColor, inputColor,
973 dstColor, inputColor, dstColor);
974 break;
975 case SkXfermode::kLighten_Mode:
976 builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, "
977 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
978 outputColor,
979 inputColor, dstColor, inputColor,
980 dstColor, inputColor, dstColor);
981 break;
982 case SkXfermode::kColorDodge_Mode:
983 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'r');
984 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'g');
985 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'b');
986 break;
987 case SkXfermode::kColorBurn_Mode:
988 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'r');
989 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'g');
990 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'b');
991 break;
992 case SkXfermode::kHardLight_Mode:
993 HardLight(builder, outputColor, inputColor, dstColor);
994 break;
995 case SkXfermode::kSoftLight_Mode:
996 builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor);
997 builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor);
998 builder->fsCodeAppendf("\t\t} else {\n");
999 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'r');
1000 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'g');
1001 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'b');
1002 builder->fsCodeAppendf("\t\t}\n");
1003 break;
1004 case SkXfermode::kDifference_Mode:
1005 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -"
1006 "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n",
1007 outputColor, inputColor, dstColor, inputColor, dstColor,
1008 dstColor, inputColor);
1009 break;
1010 case SkXfermode::kExclusion_Mode:
1011 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - "
1012 "2.0 * %s.rgb * %s.rgb;\n",
1013 outputColor, dstColor, inputColor, dstColor, inputColor);
1014 break;
1015 case SkXfermode::kMultiply_Mode:
1016 builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + "
1017 "(1.0 - %s.a) * %s.rgb + "
1018 "%s.rgb * %s.rgb;\n",
1019 outputColor, inputColor, dstColor, dstColor, inputColor,
1020 inputColor, dstColor);
1021 break;
1022 case SkXfermode::kHue_Mode: {
1023 // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S
1024 SkString setSat, setLum;
1025 AddSatFunction(builder, &setSat);
1026 AddLumFunction(builder, &setLum);
1027 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
1028 dstColor, inputColor);
1029 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
1030 outputColor, setLum.c_str(), setSat.c_str(), inputColor,
1031 dstColor);
1032 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1033 outputColor, inputColor, dstColor, dstColor, inputColor);
1034 break;
1035 }
1036 case SkXfermode::kSaturation_Mode: {
1037 // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S
1038 SkString setSat, setLum;
1039 AddSatFunction(builder, &setSat);
1040 AddLumFunction(builder, &setLum);
1041 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
1042 dstColor, inputColor);
1043 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
1044 outputColor, setLum.c_str(), setSat.c_str(), inputColor,
1045 dstColor);
1046 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1047 outputColor, inputColor, dstColor, dstColor, inputColor);
1048 break;
1049 }
1050 case SkXfermode::kColor_Mode: {
1051 // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
1052 SkString setLum;
1053 AddLumFunction(builder, &setLum);
1054 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
1055 inputColor, dstColor);
1056 builder->fsCodeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n",
1057 outputColor, setLum.c_str(), dstColor, inputColor);
1058 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1059 outputColor, inputColor, dstColor, dstColor, inputColor);
1060 break;
1061 }
1062 case SkXfermode::kLuminosity_Mode: {
1063 // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
1064 SkString setLum;
1065 AddLumFunction(builder, &setLum);
1066 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
1067 inputColor, dstColor);
1068 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n",
1069 outputColor, setLum.c_str(), dstColor, inputColor);
1070 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1071 outputColor, inputColor, dstColor, dstColor, inputColor);
1072 break;
1073 }
1074 default:
1075 GrCrash("Unknown XferEffect mode.");
1076 break;
1077 }
1078 }
1080 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
1081 return drawEffect.castEffect<XferEffect>().mode();
1082 }
1084 private:
1085 static void HardLight(GrGLShaderBuilder* builder,
1086 const char* final,
1087 const char* src,
1088 const char* dst) {
1089 static const char kComponents[] = {'r', 'g', 'b'};
1090 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) {
1091 char component = kComponents[i];
1092 builder->fsCodeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
1093 builder->fsCodeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component);
1094 builder->fsCodeAppend("\t\t} else {\n");
1095 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n",
1096 final, component, src, dst, dst, dst, component, src, src, component);
1097 builder->fsCodeAppend("\t\t}\n");
1098 }
1099 builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n",
1100 final, src, dst, dst, src);
1101 }
1103 // Does one component of color-dodge
1104 static void ColorDodgeComponent(GrGLShaderBuilder* builder,
1105 const char* final,
1106 const char* src,
1107 const char* dst,
1108 const char component) {
1109 builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component);
1110 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1111 final, component, src, component, dst);
1112 builder->fsCodeAppend("\t\t} else {\n");
1113 builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component);
1114 builder->fsCodeAppend("\t\t\tif (0.0 == d) {\n");
1115 builder->fsCodeAppendf("\t\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1116 final, component, src, dst, src, component, dst, dst, component,
1117 src);
1118 builder->fsCodeAppend("\t\t\t} else {\n");
1119 builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n",
1120 dst, dst, component, src);
1121 builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1122 final, component, src, src, component, dst, dst, component, src);
1123 builder->fsCodeAppend("\t\t\t}\n");
1124 builder->fsCodeAppend("\t\t}\n");
1125 }
1127 // Does one component of color-burn
1128 static void ColorBurnComponent(GrGLShaderBuilder* builder,
1129 const char* final,
1130 const char* src,
1131 const char* dst,
1132 const char component) {
1133 builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component);
1134 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1135 final, component, src, dst, src, component, dst, dst, component,
1136 src);
1137 builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component);
1138 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1139 final, component, dst, component, src);
1140 builder->fsCodeAppend("\t\t} else {\n");
1141 builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n",
1142 dst, dst, dst, component, src, src, component);
1143 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1144 final, component, src, src, component, dst, dst, component, src);
1145 builder->fsCodeAppend("\t\t}\n");
1146 }
1148 // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
1149 static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder,
1150 const char* final,
1151 const char* src,
1152 const char* dst,
1153 const char component) {
1154 // if (2S < Sa)
1155 builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
1156 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
1157 builder->fsCodeAppendf("\t\t\t\t%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a + (1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);\n",
1158 final, component, dst, component, dst, component, src, src,
1159 component, dst, dst, src, component, dst, component, src, src,
1160 component);
1161 // else if (4D < Da)
1162 builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n",
1163 dst, component, dst);
1164 builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n",
1165 dst, component, dst, component);
1166 builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component);
1167 builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst);
1168 builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst);
1169 // (Da^3 (-S)+Da^2 (S-D (3 Sa-6 S-1))+12 Da D^2 (Sa-2 S)-16 D^3 (Sa-2 S))/Da^2
1170 builder->fsCodeAppendf("\t\t\t\t%s.%c = (-DaCub*%s.%c + DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) + 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s.a - 2.0*%s.%c)) / DaSqd;\n",
1171 final, component, src, component, src, component, dst, component,
1172 src, src, component, dst, src, src, component, src, src,
1173 component);
1174 builder->fsCodeAppendf("\t\t\t} else {\n");
1175 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
1176 builder->fsCodeAppendf("\t\t\t\t%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2.0*%s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c;\n",
1177 final, component, dst, dst, component, src, src, component, dst,
1178 src, component, dst, component, src, src, component, src,
1179 component);
1180 builder->fsCodeAppendf("\t\t\t}\n");
1181 }
1183 // Adds a function that takes two colors and an alpha as input. It produces a color with the
1184 // hue and saturation of the first color, the luminosity of the second color, and the input
1185 // alpha. It has this signature:
1186 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor).
1187 static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumFunction) {
1188 // Emit a helper that gets the luminance of a color.
1189 SkString getFunction;
1190 GrGLShaderVar getLumArgs[] = {
1191 GrGLShaderVar("color", kVec3f_GrSLType),
1192 };
1193 SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n");
1194 builder->fsEmitFunction(kFloat_GrSLType,
1195 "luminance",
1196 SK_ARRAY_COUNT(getLumArgs), getLumArgs,
1197 getLumBody.c_str(),
1198 &getFunction);
1200 // Emit the set luminance function.
1201 GrGLShaderVar setLumArgs[] = {
1202 GrGLShaderVar("hueSat", kVec3f_GrSLType),
1203 GrGLShaderVar("alpha", kFloat_GrSLType),
1204 GrGLShaderVar("lumColor", kVec3f_GrSLType),
1205 };
1206 SkString setLumBody;
1207 setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str());
1208 setLumBody.append("\tvec3 outColor = hueSat + diff;\n");
1209 setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str());
1210 setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n"
1211 "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n"
1212 "\tif (minComp < 0.0) {\n"
1213 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n"
1214 "\t}\n"
1215 "\tif (maxComp > alpha) {\n"
1216 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n"
1217 "\t}\n"
1218 "\treturn outColor;\n");
1219 builder->fsEmitFunction(kVec3f_GrSLType,
1220 "set_luminance",
1221 SK_ARRAY_COUNT(setLumArgs), setLumArgs,
1222 setLumBody.c_str(),
1223 setLumFunction);
1224 }
1226 // Adds a function that creates a color with the hue and luminosity of one input color and
1227 // the saturation of another color. It will have this signature:
1228 // float set_saturation(vec3 hueLumColor, vec3 satColor)
1229 static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatFunction) {
1230 // Emit a helper that gets the saturation of a color
1231 SkString getFunction;
1232 GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) };
1233 SkString getSatBody;
1234 getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - "
1235 "min(min(color.r, color.g), color.b);\n");
1236 builder->fsEmitFunction(kFloat_GrSLType,
1237 "saturation",
1238 SK_ARRAY_COUNT(getSatArgs), getSatArgs,
1239 getSatBody.c_str(),
1240 &getFunction);
1242 // Emit a helper that sets the saturation given sorted input channels. This used
1243 // to use inout params for min, mid, and max components but that seems to cause
1244 // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b are the
1245 // adjusted min, mid, and max inputs, respectively.
1246 SkString helperFunction;
1247 GrGLShaderVar helperArgs[] = {
1248 GrGLShaderVar("minComp", kFloat_GrSLType),
1249 GrGLShaderVar("midComp", kFloat_GrSLType),
1250 GrGLShaderVar("maxComp", kFloat_GrSLType),
1251 GrGLShaderVar("sat", kFloat_GrSLType),
1252 };
1253 static const char kHelperBody[] = "\tif (minComp < maxComp) {\n"
1254 "\t\tvec3 result;\n"
1255 "\t\tresult.r = 0.0;\n"
1256 "\t\tresult.g = sat * (midComp - minComp) / (maxComp - minComp);\n"
1257 "\t\tresult.b = sat;\n"
1258 "\t\treturn result;\n"
1259 "\t} else {\n"
1260 "\t\treturn vec3(0, 0, 0);\n"
1261 "\t}\n";
1262 builder->fsEmitFunction(kVec3f_GrSLType,
1263 "set_saturation_helper",
1264 SK_ARRAY_COUNT(helperArgs), helperArgs,
1265 kHelperBody,
1266 &helperFunction);
1268 GrGLShaderVar setSatArgs[] = {
1269 GrGLShaderVar("hueLumColor", kVec3f_GrSLType),
1270 GrGLShaderVar("satColor", kVec3f_GrSLType),
1271 };
1272 const char* helpFunc = helperFunction.c_str();
1273 SkString setSatBody;
1274 setSatBody.appendf("\tfloat sat = %s(satColor);\n"
1275 "\tif (hueLumColor.r <= hueLumColor.g) {\n"
1276 "\t\tif (hueLumColor.g <= hueLumColor.b) {\n"
1277 "\t\t\thueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n"
1278 "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1279 "\t\t\thueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n"
1280 "\t\t} else {\n"
1281 "\t\t\thueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n"
1282 "\t\t}\n"
1283 "\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1284 "\t\thueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n"
1285 "\t} else if (hueLumColor.g <= hueLumColor.b) {\n"
1286 "\t\thueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n"
1287 "\t} else {\n"
1288 "\t\thueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n"
1289 "\t}\n"
1290 "\treturn hueLumColor;\n",
1291 getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
1292 helpFunc, helpFunc);
1293 builder->fsEmitFunction(kVec3f_GrSLType,
1294 "set_saturation",
1295 SK_ARRAY_COUNT(setSatArgs), setSatArgs,
1296 setSatBody.c_str(),
1297 setSatFunction);
1299 }
1301 typedef GrGLEffect INHERITED;
1302 };
1304 GR_DECLARE_EFFECT_TEST;
1306 private:
1307 XferEffect(SkXfermode::Mode mode, GrTexture* background)
1308 : fMode(mode) {
1309 if (background) {
1310 fBackgroundTransform.reset(kLocal_GrCoordSet, background);
1311 this->addCoordTransform(&fBackgroundTransform);
1312 fBackgroundAccess.reset(background);
1313 this->addTextureAccess(&fBackgroundAccess);
1314 } else {
1315 this->setWillReadDstColor();
1316 }
1317 }
1318 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
1319 const XferEffect& s = CastEffect<XferEffect>(other);
1320 return fMode == s.fMode &&
1321 fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture();
1322 }
1324 SkXfermode::Mode fMode;
1325 GrCoordTransform fBackgroundTransform;
1326 GrTextureAccess fBackgroundAccess;
1328 typedef GrEffect INHERITED;
1329 };
1331 GR_DEFINE_EFFECT_TEST(XferEffect);
1332 GrEffectRef* XferEffect::TestCreate(SkRandom* rand,
1333 GrContext*,
1334 const GrDrawTargetCaps&,
1335 GrTexture*[]) {
1336 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
1338 AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode), NULL)));
1339 return CreateEffectRef(gEffect);
1340 }
1342 #endif
1344 ///////////////////////////////////////////////////////////////////////////////
1345 ///////////////////////////////////////////////////////////////////////////////
1347 SkProcCoeffXfermode::SkProcCoeffXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {
1348 uint32_t mode32 = buffer.read32() % SK_ARRAY_COUNT(gProcCoeffs);
1349 if (mode32 >= SK_ARRAY_COUNT(gProcCoeffs)) {
1350 // out of range, just set to something harmless
1351 mode32 = SkXfermode::kSrcOut_Mode;
1352 }
1353 fMode = (SkXfermode::Mode)mode32;
1355 const ProcCoeff& rec = gProcCoeffs[fMode];
1356 // these may be valid, or may be CANNOT_USE_COEFF
1357 fSrcCoeff = rec.fSC;
1358 fDstCoeff = rec.fDC;
1359 // now update our function-ptr in the super class
1360 this->INHERITED::setProc(rec.fProc);
1361 }
1363 bool SkProcCoeffXfermode::asMode(Mode* mode) const {
1364 if (mode) {
1365 *mode = fMode;
1366 }
1367 return true;
1368 }
1370 bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const {
1371 if (CANNOT_USE_COEFF == fSrcCoeff) {
1372 return false;
1373 }
1375 if (sc) {
1376 *sc = fSrcCoeff;
1377 }
1378 if (dc) {
1379 *dc = fDstCoeff;
1380 }
1381 return true;
1382 }
1384 #if SK_SUPPORT_GPU
1385 bool SkProcCoeffXfermode::asNewEffect(GrEffectRef** effect,
1386 GrTexture* background) const {
1387 if (XferEffect::IsSupportedMode(fMode)) {
1388 if (NULL != effect) {
1389 *effect = XferEffect::Create(fMode, background);
1390 SkASSERT(NULL != *effect);
1391 }
1392 return true;
1393 }
1394 return false;
1395 }
1396 #endif
1398 void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
1399 this->INHERITED::flatten(buffer);
1400 buffer.write32(fMode);
1401 }
1403 const char* SkXfermode::ModeName(Mode mode) {
1404 SkASSERT((unsigned) mode <= (unsigned)kLastMode);
1405 const char* gModeStrings[] = {
1406 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
1407 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
1408 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
1409 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
1410 "Multiply", "Hue", "Saturation", "Color", "Luminosity"
1411 };
1412 return gModeStrings[mode];
1413 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
1414 }
1416 #ifndef SK_IGNORE_TO_STRING
1417 void SkProcCoeffXfermode::toString(SkString* str) const {
1418 str->append("SkProcCoeffXfermode: ");
1420 str->append("mode: ");
1421 str->append(ModeName(fMode));
1423 static const char* gCoeffStrings[kCoeffCount] = {
1424 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
1425 };
1427 str->append(" src: ");
1428 if (CANNOT_USE_COEFF == fSrcCoeff) {
1429 str->append("can't use");
1430 } else {
1431 str->append(gCoeffStrings[fSrcCoeff]);
1432 }
1434 str->append(" dst: ");
1435 if (CANNOT_USE_COEFF == fDstCoeff) {
1436 str->append("can't use");
1437 } else {
1438 str->append(gCoeffStrings[fDstCoeff]);
1439 }
1440 }
1441 #endif
1443 ///////////////////////////////////////////////////////////////////////////////
1445 class SkClearXfermode : public SkProcCoeffXfermode {
1446 public:
1447 static SkClearXfermode* Create(const ProcCoeff& rec) {
1448 return SkNEW_ARGS(SkClearXfermode, (rec));
1449 }
1451 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1452 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1454 SK_TO_STRING_OVERRIDE()
1455 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode)
1457 private:
1458 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1459 SkClearXfermode(SkReadBuffer& buffer)
1460 : SkProcCoeffXfermode(buffer) {}
1462 typedef SkProcCoeffXfermode INHERITED;
1463 };
1465 void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1466 const SkPMColor* SK_RESTRICT, int count,
1467 const SkAlpha* SK_RESTRICT aa) const {
1468 SkASSERT(dst && count >= 0);
1470 if (NULL == aa) {
1471 memset(dst, 0, count << 2);
1472 } else {
1473 for (int i = count - 1; i >= 0; --i) {
1474 unsigned a = aa[i];
1475 if (0xFF == a) {
1476 dst[i] = 0;
1477 } else if (a != 0) {
1478 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1479 }
1480 }
1481 }
1482 }
1483 void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1484 const SkPMColor* SK_RESTRICT, int count,
1485 const SkAlpha* SK_RESTRICT aa) const {
1486 SkASSERT(dst && count >= 0);
1488 if (NULL == aa) {
1489 memset(dst, 0, count);
1490 } else {
1491 for (int i = count - 1; i >= 0; --i) {
1492 unsigned a = aa[i];
1493 if (0xFF == a) {
1494 dst[i] = 0;
1495 } else if (0 != a) {
1496 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1497 }
1498 }
1499 }
1500 }
1502 #ifndef SK_IGNORE_TO_STRING
1503 void SkClearXfermode::toString(SkString* str) const {
1504 this->INHERITED::toString(str);
1505 }
1506 #endif
1508 ///////////////////////////////////////////////////////////////////////////////
1510 class SkSrcXfermode : public SkProcCoeffXfermode {
1511 public:
1512 static SkSrcXfermode* Create(const ProcCoeff& rec) {
1513 return SkNEW_ARGS(SkSrcXfermode, (rec));
1514 }
1516 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1517 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1519 SK_TO_STRING_OVERRIDE()
1520 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode)
1522 private:
1523 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1524 SkSrcXfermode(SkReadBuffer& buffer)
1525 : SkProcCoeffXfermode(buffer) {}
1527 typedef SkProcCoeffXfermode INHERITED;
1528 };
1530 void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1531 const SkPMColor* SK_RESTRICT src, int count,
1532 const SkAlpha* SK_RESTRICT aa) const {
1533 SkASSERT(dst && src && count >= 0);
1535 if (NULL == aa) {
1536 memcpy(dst, src, count << 2);
1537 } else {
1538 for (int i = count - 1; i >= 0; --i) {
1539 unsigned a = aa[i];
1540 if (a == 0xFF) {
1541 dst[i] = src[i];
1542 } else if (a != 0) {
1543 dst[i] = SkFourByteInterp(src[i], dst[i], a);
1544 }
1545 }
1546 }
1547 }
1549 void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1550 const SkPMColor* SK_RESTRICT src, int count,
1551 const SkAlpha* SK_RESTRICT aa) const {
1552 SkASSERT(dst && src && count >= 0);
1554 if (NULL == aa) {
1555 for (int i = count - 1; i >= 0; --i) {
1556 dst[i] = SkToU8(SkGetPackedA32(src[i]));
1557 }
1558 } else {
1559 for (int i = count - 1; i >= 0; --i) {
1560 unsigned a = aa[i];
1561 if (0 != a) {
1562 unsigned srcA = SkGetPackedA32(src[i]);
1563 if (a == 0xFF) {
1564 dst[i] = SkToU8(srcA);
1565 } else {
1566 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1567 }
1568 }
1569 }
1570 }
1571 }
1572 #ifndef SK_IGNORE_TO_STRING
1573 void SkSrcXfermode::toString(SkString* str) const {
1574 this->INHERITED::toString(str);
1575 }
1576 #endif
1578 ///////////////////////////////////////////////////////////////////////////////
1580 class SkDstInXfermode : public SkProcCoeffXfermode {
1581 public:
1582 static SkDstInXfermode* Create(const ProcCoeff& rec) {
1583 return SkNEW_ARGS(SkDstInXfermode, (rec));
1584 }
1586 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1588 SK_TO_STRING_OVERRIDE()
1589 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode)
1591 private:
1592 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1593 SkDstInXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {}
1595 typedef SkProcCoeffXfermode INHERITED;
1596 };
1598 void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1599 const SkPMColor* SK_RESTRICT src, int count,
1600 const SkAlpha* SK_RESTRICT aa) const {
1601 SkASSERT(dst && src);
1603 if (count <= 0) {
1604 return;
1605 }
1606 if (NULL != aa) {
1607 return this->INHERITED::xfer32(dst, src, count, aa);
1608 }
1610 do {
1611 unsigned a = SkGetPackedA32(*src);
1612 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1613 dst++;
1614 src++;
1615 } while (--count != 0);
1616 }
1618 #ifndef SK_IGNORE_TO_STRING
1619 void SkDstInXfermode::toString(SkString* str) const {
1620 this->INHERITED::toString(str);
1621 }
1622 #endif
1624 ///////////////////////////////////////////////////////////////////////////////
1626 class SkDstOutXfermode : public SkProcCoeffXfermode {
1627 public:
1628 static SkDstOutXfermode* Create(const ProcCoeff& rec) {
1629 return SkNEW_ARGS(SkDstOutXfermode, (rec));
1630 }
1632 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1634 SK_TO_STRING_OVERRIDE()
1635 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode)
1637 private:
1638 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1639 SkDstOutXfermode(SkReadBuffer& buffer)
1640 : INHERITED(buffer) {}
1642 typedef SkProcCoeffXfermode INHERITED;
1643 };
1645 void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1646 const SkPMColor* SK_RESTRICT src, int count,
1647 const SkAlpha* SK_RESTRICT aa) const {
1648 SkASSERT(dst && src);
1650 if (count <= 0) {
1651 return;
1652 }
1653 if (NULL != aa) {
1654 return this->INHERITED::xfer32(dst, src, count, aa);
1655 }
1657 do {
1658 unsigned a = SkGetPackedA32(*src);
1659 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1660 dst++;
1661 src++;
1662 } while (--count != 0);
1663 }
1665 #ifndef SK_IGNORE_TO_STRING
1666 void SkDstOutXfermode::toString(SkString* str) const {
1667 this->INHERITED::toString(str);
1668 }
1669 #endif
1671 ///////////////////////////////////////////////////////////////////////////////
1673 SK_DECLARE_STATIC_MUTEX(gCachedXfermodesMutex);
1674 static SkXfermode* gCachedXfermodes[SkXfermode::kLastMode + 1];
1676 void SkXfermode::Term() {
1677 SkAutoMutexAcquire ac(gCachedXfermodesMutex);
1679 for (size_t i = 0; i < SK_ARRAY_COUNT(gCachedXfermodes); ++i) {
1680 SkSafeUnref(gCachedXfermodes[i]);
1681 gCachedXfermodes[i] = NULL;
1682 }
1683 }
1685 extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec,
1686 SkXfermode::Mode mode);
1687 extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
1689 SkXfermode* SkXfermode::Create(Mode mode) {
1690 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1691 SkASSERT(SK_ARRAY_COUNT(gCachedXfermodes) == kModeCount);
1693 if ((unsigned)mode >= kModeCount) {
1694 // report error
1695 return NULL;
1696 }
1698 // Skia's "defaut" mode is srcover. NULL in SkPaint is interpreted as srcover
1699 // so we can just return NULL from the factory.
1700 if (kSrcOver_Mode == mode) {
1701 return NULL;
1702 }
1704 // guard our access to gCachedXfermodes, since we may write into it
1705 SkAutoMutexAcquire ac(gCachedXfermodesMutex);
1707 SkXfermode* xfer = gCachedXfermodes[mode];
1708 if (NULL == xfer) {
1709 ProcCoeff rec = gProcCoeffs[mode];
1711 SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
1713 if (pp != NULL) {
1714 rec.fProc = pp;
1715 }
1717 // check if we have a platform optim for that
1718 SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
1719 if (xfm != NULL) {
1720 xfer = xfm;
1721 } else {
1722 // All modes can in theory be represented by the ProcCoeff rec, since
1723 // it contains function ptrs. However, a few modes are both simple and
1724 // commonly used, so we call those out for their own subclasses here.
1725 switch (mode) {
1726 case kClear_Mode:
1727 xfer = SkClearXfermode::Create(rec);
1728 break;
1729 case kSrc_Mode:
1730 xfer = SkSrcXfermode::Create(rec);
1731 break;
1732 case kSrcOver_Mode:
1733 SkASSERT(false); // should not land here
1734 break;
1735 case kDstIn_Mode:
1736 xfer = SkDstInXfermode::Create(rec);
1737 break;
1738 case kDstOut_Mode:
1739 xfer = SkDstOutXfermode::Create(rec);
1740 break;
1741 default:
1742 // no special-case, just rely in the rec and its function-ptrs
1743 xfer = SkProcCoeffXfermode::Create(rec, mode);
1744 break;
1745 }
1746 }
1747 gCachedXfermodes[mode] = xfer;
1748 }
1749 return SkSafeRef(xfer);
1750 }
1752 SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1753 SkXfermodeProc proc = NULL;
1754 if ((unsigned)mode < kModeCount) {
1755 proc = gProcCoeffs[mode].fProc;
1756 }
1757 return proc;
1758 }
1760 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1761 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1763 if ((unsigned)mode >= (unsigned)kModeCount) {
1764 // illegal mode parameter
1765 return false;
1766 }
1768 const ProcCoeff& rec = gProcCoeffs[mode];
1770 if (CANNOT_USE_COEFF == rec.fSC) {
1771 return false;
1772 }
1774 SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1775 if (src) {
1776 *src = rec.fSC;
1777 }
1778 if (dst) {
1779 *dst = rec.fDC;
1780 }
1781 return true;
1782 }
1784 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1785 if (NULL == xfer) {
1786 if (mode) {
1787 *mode = kSrcOver_Mode;
1788 }
1789 return true;
1790 }
1791 return xfer->asMode(mode);
1792 }
1794 bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
1795 if (NULL == xfer) {
1796 return ModeAsCoeff(kSrcOver_Mode, src, dst);
1797 }
1798 return xfer->asCoeff(src, dst);
1799 }
1801 bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1802 // if xfer==null then the mode is srcover
1803 Mode m = kSrcOver_Mode;
1804 if (xfer && !xfer->asMode(&m)) {
1805 return false;
1806 }
1807 return mode == m;
1808 }
1810 ///////////////////////////////////////////////////////////////////////////////
1811 //////////// 16bit xfermode procs
1813 #ifdef SK_DEBUG
1814 static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1815 static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1816 #endif
1818 static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1819 SkASSERT(require_255(src));
1820 return SkPixel32ToPixel16(src);
1821 }
1823 static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1824 return dst;
1825 }
1827 static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1828 SkASSERT(require_0(src));
1829 return dst;
1830 }
1832 static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1833 SkASSERT(require_255(src));
1834 return SkPixel32ToPixel16(src);
1835 }
1837 static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1838 SkASSERT(require_0(src));
1839 return dst;
1840 }
1842 static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1843 SkASSERT(require_255(src));
1844 return dst;
1845 }
1847 static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1848 SkASSERT(require_255(src));
1849 return SkPixel32ToPixel16(src);
1850 }
1852 static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1853 SkASSERT(require_255(src));
1854 return dst;
1855 }
1857 static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1858 SkASSERT(require_0(src));
1859 return dst;
1860 }
1862 static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1863 unsigned isa = 255 - SkGetPackedA32(src);
1865 return SkPackRGB16(
1866 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1867 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1868 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1869 }
1871 static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1872 SkASSERT(require_0(src));
1873 return dst;
1874 }
1876 static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1877 SkASSERT(require_255(src));
1878 return SkPixel32ToPixel16(src);
1879 }
1881 static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1882 SkASSERT(require_255(src));
1883 return dst;
1884 }
1886 /*********
1887 darken and lighten boil down to this.
1889 darken = (1 - Sa) * Dc + min(Sc, Dc)
1890 lighten = (1 - Sa) * Dc + max(Sc, Dc)
1892 if (Sa == 0) these become
1893 darken = Dc + min(0, Dc) = 0
1894 lighten = Dc + max(0, Dc) = Dc
1896 if (Sa == 1) these become
1897 darken = min(Sc, Dc)
1898 lighten = max(Sc, Dc)
1899 */
1901 static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1902 SkASSERT(require_0(src));
1903 return 0;
1904 }
1906 static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1907 SkASSERT(require_255(src));
1908 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1909 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1910 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1911 return SkPackRGB16(r, g, b);
1912 }
1914 static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1915 SkASSERT(require_0(src));
1916 return dst;
1917 }
1919 static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1920 SkASSERT(require_255(src));
1921 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1922 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1923 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1924 return SkPackRGB16(r, g, b);
1925 }
1927 struct Proc16Rec {
1928 SkXfermodeProc16 fProc16_0;
1929 SkXfermodeProc16 fProc16_255;
1930 SkXfermodeProc16 fProc16_General;
1931 };
1933 static const Proc16Rec gModeProcs16[] = {
1934 { NULL, NULL, NULL }, // CLEAR
1935 { NULL, src_modeproc16_255, NULL },
1936 { dst_modeproc16, dst_modeproc16, dst_modeproc16 },
1937 { srcover_modeproc16_0, srcover_modeproc16_255, NULL },
1938 { dstover_modeproc16_0, dstover_modeproc16_255, NULL },
1939 { NULL, srcin_modeproc16_255, NULL },
1940 { NULL, dstin_modeproc16_255, NULL },
1941 { NULL, NULL, NULL },// SRC_OUT
1942 { dstout_modeproc16_0, NULL, NULL },
1943 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 },
1944 { NULL, dstatop_modeproc16_255, NULL },
1945 { NULL, NULL, NULL }, // XOR
1947 { NULL, NULL, NULL }, // plus
1948 { NULL, NULL, NULL }, // modulate
1949 { NULL, NULL, NULL }, // screen
1950 { NULL, NULL, NULL }, // overlay
1951 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken
1952 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten
1953 { NULL, NULL, NULL }, // colordodge
1954 { NULL, NULL, NULL }, // colorburn
1955 { NULL, NULL, NULL }, // hardlight
1956 { NULL, NULL, NULL }, // softlight
1957 { NULL, NULL, NULL }, // difference
1958 { NULL, NULL, NULL }, // exclusion
1959 { NULL, NULL, NULL }, // multiply
1960 { NULL, NULL, NULL }, // hue
1961 { NULL, NULL, NULL }, // saturation
1962 { NULL, NULL, NULL }, // color
1963 { NULL, NULL, NULL }, // luminosity
1964 };
1966 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1967 SkXfermodeProc16 proc16 = NULL;
1968 if ((unsigned)mode < kModeCount) {
1969 const Proc16Rec& rec = gModeProcs16[mode];
1970 unsigned a = SkColorGetA(srcColor);
1972 if (0 == a) {
1973 proc16 = rec.fProc16_0;
1974 } else if (255 == a) {
1975 proc16 = rec.fProc16_255;
1976 } else {
1977 proc16 = rec.fProc16_General;
1978 }
1979 }
1980 return proc16;
1981 }
1983 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1984 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1985 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
1986 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
1987 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
1988 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
1989 #if !SK_ARM_NEON_IS_NONE
1990 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkNEONProcCoeffXfermode)
1991 #endif
1992 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END