3 * Copyright 2006 The Android Open Source Project
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
9 #include "SkXfermode.h"
10 #include "SkXfermode_opts_SSE2.h"
11 #include "SkXfermode_proccoeff.h"
12 #include "SkColorPriv.h"
13 #include "SkLazyPtr.h"
14 #include "SkMathPriv.h"
15 #include "SkReadBuffer.h"
17 #include "SkUtilsArm.h"
18 #include "SkWriteBuffer.h"
20 #if !SK_ARM_NEON_IS_NONE
21 #include "SkXfermode_opts_arm_neon.h"
24 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b)
27 // idea for higher precision blends in xfer procs (and slightly faster)
28 // see DstATop as a probable caller
29 static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
34 unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
35 unsigned result = (prod + (prod >> 8)) >> 8;
36 SkASSERT(result <= 255);
41 static inline unsigned saturated_add(unsigned a, unsigned b) {
51 static inline int clamp_signed_byte(int n) {
60 static inline int clamp_div255round(int prod) {
63 } else if (prod >= 255*255) {
66 return SkDiv255Round(prod);
70 ///////////////////////////////////////////////////////////////////////////////
72 // kClear_Mode, //!< [0, 0]
73 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
77 // kSrc_Mode, //!< [Sa, Sc]
78 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
82 // kDst_Mode, //!< [Da, Dc]
83 static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
87 // kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
88 static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
90 // this is the old, more-correct way, but it doesn't guarantee that dst==255
91 // will always stay opaque
92 return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
94 // this is slightly faster, but more importantly guarantees that dst==255
95 // will always stay opaque
96 return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
100 // kDstOver_Mode, //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
101 static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
102 // this is the reverse of srcover, just flipping src and dst
103 // see srcover's comment about the 256 for opaqueness guarantees
104 return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
107 // kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
108 static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
109 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
112 // kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
113 static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
114 return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
117 // kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
118 static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
119 return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
122 // kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
123 static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
124 return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
127 // kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
128 static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
129 unsigned sa = SkGetPackedA32(src);
130 unsigned da = SkGetPackedA32(dst);
131 unsigned isa = 255 - sa;
133 return SkPackARGB32(da,
134 SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
135 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
136 SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
137 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
138 SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
139 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
142 // kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
143 static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
144 unsigned sa = SkGetPackedA32(src);
145 unsigned da = SkGetPackedA32(dst);
146 unsigned ida = 255 - da;
148 return SkPackARGB32(sa,
149 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
150 SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
151 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
152 SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
153 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
154 SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
157 // kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
158 static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
159 unsigned sa = SkGetPackedA32(src);
160 unsigned da = SkGetPackedA32(dst);
161 unsigned isa = 255 - sa;
162 unsigned ida = 255 - da;
164 return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
165 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
166 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
167 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
168 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
169 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
170 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
173 ///////////////////////////////////////////////////////////////////////////////
176 static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
177 unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
178 unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
179 unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
180 unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
181 return SkPackARGB32(a, r, g, b);
185 static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
186 int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
187 int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
188 int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
189 int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
190 return SkPackARGB32(a, r, g, b);
193 static inline int srcover_byte(int a, int b) {
194 return a + b - SkAlphaMulAlpha(a, b);
198 // B(Cb, Cs) = Cb x Cs
199 // multiply uses its own version of blendfunc_byte because sa and da are not needed
200 static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
201 return clamp_div255round(sc * (255 - da) + dc * (255 - sa) + sc * dc);
204 static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
205 int sa = SkGetPackedA32(src);
206 int da = SkGetPackedA32(dst);
207 int a = srcover_byte(sa, da);
208 int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
209 int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
210 int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
211 return SkPackARGB32(a, r, g, b);
215 static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
216 int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
217 int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
218 int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
219 int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
220 return SkPackARGB32(a, r, g, b);
224 static inline int overlay_byte(int sc, int dc, int sa, int da) {
225 int tmp = sc * (255 - da) + dc * (255 - sa);
230 rc = sa * da - 2 * (da - dc) * (sa - sc);
232 return clamp_div255round(rc + tmp);
234 static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
235 int sa = SkGetPackedA32(src);
236 int da = SkGetPackedA32(dst);
237 int a = srcover_byte(sa, da);
238 int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
239 int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
240 int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
241 return SkPackARGB32(a, r, g, b);
245 static inline int darken_byte(int sc, int dc, int sa, int da) {
250 return sc + dc - SkDiv255Round(ds);
253 return dc + sc - SkDiv255Round(sd);
256 static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
257 int sa = SkGetPackedA32(src);
258 int da = SkGetPackedA32(dst);
259 int a = srcover_byte(sa, da);
260 int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
261 int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
262 int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
263 return SkPackARGB32(a, r, g, b);
267 static inline int lighten_byte(int sc, int dc, int sa, int da) {
272 return sc + dc - SkDiv255Round(ds);
275 return dc + sc - SkDiv255Round(sd);
278 static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
279 int sa = SkGetPackedA32(src);
280 int da = SkGetPackedA32(dst);
281 int a = srcover_byte(sa, da);
282 int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
283 int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
284 int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
285 return SkPackARGB32(a, r, g, b);
289 static inline int colordodge_byte(int sc, int dc, int sa, int da) {
293 return SkAlphaMulAlpha(sc, 255 - da);
294 } else if (0 == diff) {
295 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
297 diff = dc * sa / diff;
298 rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
300 return clamp_div255round(rc);
302 static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
303 int sa = SkGetPackedA32(src);
304 int da = SkGetPackedA32(dst);
305 int a = srcover_byte(sa, da);
306 int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
307 int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
308 int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
309 return SkPackARGB32(a, r, g, b);
313 static inline int colorburn_byte(int sc, int dc, int sa, int da) {
316 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
317 } else if (0 == sc) {
318 return SkAlphaMulAlpha(dc, 255 - sa);
320 int tmp = (da - dc) * sa / sc;
321 rc = sa * (da - ((da < tmp) ? da : tmp))
322 + sc * (255 - da) + dc * (255 - sa);
324 return clamp_div255round(rc);
326 static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
327 int sa = SkGetPackedA32(src);
328 int da = SkGetPackedA32(dst);
329 int a = srcover_byte(sa, da);
330 int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
331 int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
332 int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
333 return SkPackARGB32(a, r, g, b);
337 static inline int hardlight_byte(int sc, int dc, int sa, int da) {
342 rc = sa * da - 2 * (da - dc) * (sa - sc);
344 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
346 static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
347 int sa = SkGetPackedA32(src);
348 int da = SkGetPackedA32(dst);
349 int a = srcover_byte(sa, da);
350 int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
351 int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
352 int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
353 return SkPackARGB32(a, r, g, b);
356 // returns 255 * sqrt(n/255)
357 static U8CPU sqrt_unit_byte(U8CPU n) {
358 return SkSqrtBits(n, 15+4);
362 static inline int softlight_byte(int sc, int dc, int sa, int da) {
363 int m = da ? dc * 256 / da : 0;
366 rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
367 } else if (4 * dc <= da) {
368 int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
369 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
371 int tmp = sqrt_unit_byte(m) - m;
372 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
374 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
376 static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
377 int sa = SkGetPackedA32(src);
378 int da = SkGetPackedA32(dst);
379 int a = srcover_byte(sa, da);
380 int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
381 int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
382 int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
383 return SkPackARGB32(a, r, g, b);
387 static inline int difference_byte(int sc, int dc, int sa, int da) {
388 int tmp = SkMin32(sc * da, dc * sa);
389 return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
391 static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
392 int sa = SkGetPackedA32(src);
393 int da = SkGetPackedA32(dst);
394 int a = srcover_byte(sa, da);
395 int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
396 int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
397 int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
398 return SkPackARGB32(a, r, g, b);
402 static inline int exclusion_byte(int sc, int dc, int, int) {
403 // this equations is wacky, wait for SVG to confirm it
404 //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
406 // The above equation can be simplified as follows
407 int r = 255*(sc + dc) - 2 * sc * dc;
408 return clamp_div255round(r);
410 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
411 int sa = SkGetPackedA32(src);
412 int da = SkGetPackedA32(dst);
413 int a = srcover_byte(sa, da);
414 int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
415 int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
416 int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
417 return SkPackARGB32(a, r, g, b);
420 // The CSS compositing spec introduces the following formulas:
421 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
422 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
423 // while PDF and CG uses the one from Rec. Rec. 601
424 // See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
425 static inline int Lum(int r, int g, int b)
427 return SkDiv255Round(r * 77 + g * 150 + b * 28);
430 static inline int min2(int a, int b) { return a < b ? a : b; }
431 static inline int max2(int a, int b) { return a > b ? a : b; }
432 #define minimum(a, b, c) min2(min2(a, b), c)
433 #define maximum(a, b, c) max2(max2(a, b), c)
435 static inline int Sat(int r, int g, int b) {
436 return maximum(r, g, b) - minimum(r, g, b);
439 static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
441 *Cmid = SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
451 static inline void SetSat(int* r, int* g, int* b, int s) {
454 setSaturationComponents(r, g, b, s);
455 } else if(*r <= *b) {
456 setSaturationComponents(r, b, g, s);
458 setSaturationComponents(b, r, g, s);
460 } else if(*r <= *b) {
461 setSaturationComponents(g, r, b, s);
462 } else if(*g <= *b) {
463 setSaturationComponents(g, b, r, s);
465 setSaturationComponents(b, g, r, s);
469 static inline void clipColor(int* r, int* g, int* b, int a) {
470 int L = Lum(*r, *g, *b);
471 int n = minimum(*r, *g, *b);
472 int x = maximum(*r, *g, *b);
474 if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
475 *r = L + SkMulDiv(*r - L, L, denom);
476 *g = L + SkMulDiv(*g - L, L, denom);
477 *b = L + SkMulDiv(*b - L, L, denom);
480 if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
482 *r = L + SkMulDiv(*r - L, numer, denom);
483 *g = L + SkMulDiv(*g - L, numer, denom);
484 *b = L + SkMulDiv(*b - L, numer, denom);
488 static inline void SetLum(int* r, int* g, int* b, int a, int l) {
489 int d = l - Lum(*r, *g, *b);
494 clipColor(r, g, b, a);
497 // non-separable blend modes are done in non-premultiplied alpha
498 #define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
499 clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendval)
502 // B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
503 // Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
504 static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
505 int sr = SkGetPackedR32(src);
506 int sg = SkGetPackedG32(src);
507 int sb = SkGetPackedB32(src);
508 int sa = SkGetPackedA32(src);
510 int dr = SkGetPackedR32(dst);
511 int dg = SkGetPackedG32(dst);
512 int db = SkGetPackedB32(dst);
513 int da = SkGetPackedA32(dst);
520 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
521 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
528 int a = srcover_byte(sa, da);
529 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
530 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
531 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
532 return SkPackARGB32(a, r, g, b);
536 // B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
537 // Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
538 static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
539 int sr = SkGetPackedR32(src);
540 int sg = SkGetPackedG32(src);
541 int sb = SkGetPackedB32(src);
542 int sa = SkGetPackedA32(src);
544 int dr = SkGetPackedR32(dst);
545 int dg = SkGetPackedG32(dst);
546 int db = SkGetPackedB32(dst);
547 int da = SkGetPackedA32(dst);
554 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
555 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
562 int a = srcover_byte(sa, da);
563 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
564 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
565 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
566 return SkPackARGB32(a, r, g, b);
570 // B(Cb, Cs) = SetLum(Cs, Lum(Cb))
571 // Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
572 static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
573 int sr = SkGetPackedR32(src);
574 int sg = SkGetPackedG32(src);
575 int sb = SkGetPackedB32(src);
576 int sa = SkGetPackedA32(src);
578 int dr = SkGetPackedR32(dst);
579 int dg = SkGetPackedG32(dst);
580 int db = SkGetPackedB32(dst);
581 int da = SkGetPackedA32(dst);
588 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
595 int a = srcover_byte(sa, da);
596 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
597 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
598 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
599 return SkPackARGB32(a, r, g, b);
603 // B(Cb, Cs) = SetLum(Cb, Lum(Cs))
604 // Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
605 static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
606 int sr = SkGetPackedR32(src);
607 int sg = SkGetPackedG32(src);
608 int sb = SkGetPackedB32(src);
609 int sa = SkGetPackedA32(src);
611 int dr = SkGetPackedR32(dst);
612 int dg = SkGetPackedG32(dst);
613 int db = SkGetPackedB32(dst);
614 int da = SkGetPackedA32(dst);
621 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
628 int a = srcover_byte(sa, da);
629 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
630 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
631 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
632 return SkPackARGB32(a, r, g, b);
635 const ProcCoeff gProcCoeffs[] = {
636 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff },
637 { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff },
638 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff },
639 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff },
640 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff },
641 { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff },
642 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff },
643 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff },
644 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff },
645 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff },
646 { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff },
647 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff },
649 { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff },
650 { modulate_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff },
651 { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff },
652 { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
653 { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
654 { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
655 { colordodge_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
656 { colorburn_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
657 { hardlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
658 { softlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
659 { difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
660 { exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
661 { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
662 { hue_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
663 { saturation_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
664 { color_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
665 { luminosity_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
668 ///////////////////////////////////////////////////////////////////////////////
670 bool SkXfermode::asMode(Mode* mode) const {
674 bool SkXfermode::asFragmentProcessor(GrFragmentProcessor**, GrTexture*) const {
678 bool SkXfermode::asXPFactory(GrXPFactory**) const {
684 #include "effects/GrPorterDuffXferProcessor.h"
686 bool SkXfermode::AsXPFactory(SkXfermode* xfermode, GrXPFactory** xpf) {
687 if (NULL == xfermode) {
689 *xpf = GrPorterDuffXPFactory::Create(kSrcOver_Mode);
693 return xfermode->asXPFactory(xpf);
697 bool SkXfermode::AsXPFactory(SkXfermode* xfermode, GrXPFactory** xpf) {
702 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
703 // no-op. subclasses should override this
707 void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
708 const SkPMColor* SK_RESTRICT src, int count,
709 const SkAlpha* SK_RESTRICT aa) const {
710 SkASSERT(dst && src && count >= 0);
713 for (int i = count - 1; i >= 0; --i) {
714 dst[i] = this->xferColor(src[i], dst[i]);
717 for (int i = count - 1; i >= 0; --i) {
720 SkPMColor dstC = dst[i];
721 SkPMColor C = this->xferColor(src[i], dstC);
723 C = SkFourByteInterp(C, dstC, a);
731 void SkXfermode::xfer16(uint16_t* dst,
732 const SkPMColor* SK_RESTRICT src, int count,
733 const SkAlpha* SK_RESTRICT aa) const {
734 SkASSERT(dst && src && count >= 0);
737 for (int i = count - 1; i >= 0; --i) {
738 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
739 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
742 for (int i = count - 1; i >= 0; --i) {
745 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
746 SkPMColor C = this->xferColor(src[i], dstC);
748 C = SkFourByteInterp(C, dstC, a);
750 dst[i] = SkPixel32ToPixel16_ToU16(C);
756 void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
757 const SkPMColor src[], int count,
758 const SkAlpha* SK_RESTRICT aa) const {
759 SkASSERT(dst && src && count >= 0);
762 for (int i = count - 1; i >= 0; --i) {
763 SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
764 dst[i] = SkToU8(SkGetPackedA32(res));
767 for (int i = count - 1; i >= 0; --i) {
770 SkAlpha dstA = dst[i];
771 unsigned A = SkGetPackedA32(this->xferColor(src[i],
772 (SkPMColor)(dstA << SK_A32_SHIFT)));
774 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
782 bool SkXfermode::supportsCoverageAsAlpha() const {
786 bool SkXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
790 ///////////////////////////////////////////////////////////////////////////////
791 ///////////////////////////////////////////////////////////////////////////////
793 SkFlattenable* SkProcCoeffXfermode::CreateProc(SkReadBuffer& buffer) {
794 uint32_t mode32 = buffer.read32();
795 if (!buffer.validate(mode32 < SK_ARRAY_COUNT(gProcCoeffs))) {
798 return SkXfermode::Create((SkXfermode::Mode)mode32);
801 void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
802 buffer.write32(fMode);
805 bool SkProcCoeffXfermode::asMode(Mode* mode) const {
812 bool SkProcCoeffXfermode::supportsCoverageAsAlpha() const {
813 if (CANNOT_USE_COEFF == fSrcCoeff) {
818 case SkXfermode::kOne_Coeff:
819 case SkXfermode::kISA_Coeff:
820 case SkXfermode::kISC_Coeff:
827 bool SkProcCoeffXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
828 if (CANNOT_USE_COEFF == fSrcCoeff) {
832 if (SkXfermode::kDA_Coeff == fSrcCoeff || SkXfermode::kDC_Coeff == fSrcCoeff ||
833 SkXfermode::kIDA_Coeff == fSrcCoeff || SkXfermode::kIDC_Coeff == fSrcCoeff) {
838 case SkXfermode::kZero_Coeff:
840 case SkXfermode::kISA_Coeff:
841 return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
842 case SkXfermode::kSA_Coeff:
843 return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType ||
844 SkXfermode::kTransparentAlpha_SrcColorOpacity == opacityType;
845 case SkXfermode::kSC_Coeff:
846 return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType;
853 void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
854 const SkPMColor* SK_RESTRICT src, int count,
855 const SkAlpha* SK_RESTRICT aa) const {
856 SkASSERT(dst && src && count >= 0);
858 SkXfermodeProc proc = fProc;
862 for (int i = count - 1; i >= 0; --i) {
863 dst[i] = proc(src[i], dst[i]);
866 for (int i = count - 1; i >= 0; --i) {
869 SkPMColor dstC = dst[i];
870 SkPMColor C = proc(src[i], dstC);
872 C = SkFourByteInterp(C, dstC, a);
881 void SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
882 const SkPMColor* SK_RESTRICT src, int count,
883 const SkAlpha* SK_RESTRICT aa) const {
884 SkASSERT(dst && src && count >= 0);
886 SkXfermodeProc proc = fProc;
890 for (int i = count - 1; i >= 0; --i) {
891 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
892 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
895 for (int i = count - 1; i >= 0; --i) {
898 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
899 SkPMColor C = proc(src[i], dstC);
901 C = SkFourByteInterp(C, dstC, a);
903 dst[i] = SkPixel32ToPixel16_ToU16(C);
910 void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
911 const SkPMColor* SK_RESTRICT src, int count,
912 const SkAlpha* SK_RESTRICT aa) const {
913 SkASSERT(dst && src && count >= 0);
915 SkXfermodeProc proc = fProc;
919 for (int i = count - 1; i >= 0; --i) {
920 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
921 dst[i] = SkToU8(SkGetPackedA32(res));
924 for (int i = count - 1; i >= 0; --i) {
927 SkAlpha dstA = dst[i];
928 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
929 unsigned A = SkGetPackedA32(res);
931 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
941 #include "effects/GrCustomXfermode.h"
943 bool SkProcCoeffXfermode::asFragmentProcessor(GrFragmentProcessor** fp,
944 GrTexture* background) const {
945 if (GrCustomXfermode::IsSupportedMode(fMode)) {
947 *fp = GrCustomXfermode::CreateFP(fMode, background);
955 bool SkProcCoeffXfermode::asXPFactory(GrXPFactory** xp) const {
956 if (CANNOT_USE_COEFF != fSrcCoeff) {
958 *xp = GrPorterDuffXPFactory::Create(fMode);
964 if (GrCustomXfermode::IsSupportedMode(fMode)) {
966 *xp = GrCustomXfermode::CreateXPFactory(fMode);
975 const char* SkXfermode::ModeName(Mode mode) {
976 SkASSERT((unsigned) mode <= (unsigned)kLastMode);
977 const char* gModeStrings[] = {
978 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
979 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
980 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
981 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
982 "Multiply", "Hue", "Saturation", "Color", "Luminosity"
984 return gModeStrings[mode];
985 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
988 #ifndef SK_IGNORE_TO_STRING
989 void SkProcCoeffXfermode::toString(SkString* str) const {
990 str->append("SkProcCoeffXfermode: ");
992 str->append("mode: ");
993 str->append(ModeName(fMode));
995 static const char* gCoeffStrings[kCoeffCount] = {
996 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
999 str->append(" src: ");
1000 if (CANNOT_USE_COEFF == fSrcCoeff) {
1001 str->append("can't use");
1003 str->append(gCoeffStrings[fSrcCoeff]);
1006 str->append(" dst: ");
1007 if (CANNOT_USE_COEFF == fDstCoeff) {
1008 str->append("can't use");
1010 str->append(gCoeffStrings[fDstCoeff]);
1015 ///////////////////////////////////////////////////////////////////////////////
1017 class SkClearXfermode : public SkProcCoeffXfermode {
1019 static SkClearXfermode* Create(const ProcCoeff& rec) {
1020 return SkNEW_ARGS(SkClearXfermode, (rec));
1023 void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1024 void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const override;
1026 SK_TO_STRING_OVERRIDE()
1029 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1031 typedef SkProcCoeffXfermode INHERITED;
1034 void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1035 const SkPMColor* SK_RESTRICT, int count,
1036 const SkAlpha* SK_RESTRICT aa) const {
1037 SkASSERT(dst && count >= 0);
1040 memset(dst, 0, count << 2);
1042 for (int i = count - 1; i >= 0; --i) {
1046 } else if (a != 0) {
1047 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1052 void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1053 const SkPMColor* SK_RESTRICT, int count,
1054 const SkAlpha* SK_RESTRICT aa) const {
1055 SkASSERT(dst && count >= 0);
1058 memset(dst, 0, count);
1060 for (int i = count - 1; i >= 0; --i) {
1064 } else if (0 != a) {
1065 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1071 #ifndef SK_IGNORE_TO_STRING
1072 void SkClearXfermode::toString(SkString* str) const {
1073 this->INHERITED::toString(str);
1077 ///////////////////////////////////////////////////////////////////////////////
1079 class SkSrcXfermode : public SkProcCoeffXfermode {
1081 static SkSrcXfermode* Create(const ProcCoeff& rec) {
1082 return SkNEW_ARGS(SkSrcXfermode, (rec));
1085 void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1086 void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const override;
1088 SK_TO_STRING_OVERRIDE()
1091 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1092 typedef SkProcCoeffXfermode INHERITED;
1095 void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1096 const SkPMColor* SK_RESTRICT src, int count,
1097 const SkAlpha* SK_RESTRICT aa) const {
1098 SkASSERT(dst && src && count >= 0);
1101 memcpy(dst, src, count << 2);
1103 for (int i = count - 1; i >= 0; --i) {
1107 } else if (a != 0) {
1108 dst[i] = SkFourByteInterp(src[i], dst[i], a);
1114 void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1115 const SkPMColor* SK_RESTRICT src, int count,
1116 const SkAlpha* SK_RESTRICT aa) const {
1117 SkASSERT(dst && src && count >= 0);
1120 for (int i = count - 1; i >= 0; --i) {
1121 dst[i] = SkToU8(SkGetPackedA32(src[i]));
1124 for (int i = count - 1; i >= 0; --i) {
1127 unsigned srcA = SkGetPackedA32(src[i]);
1129 dst[i] = SkToU8(srcA);
1131 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1137 #ifndef SK_IGNORE_TO_STRING
1138 void SkSrcXfermode::toString(SkString* str) const {
1139 this->INHERITED::toString(str);
1143 ///////////////////////////////////////////////////////////////////////////////
1145 class SkDstInXfermode : public SkProcCoeffXfermode {
1147 static SkDstInXfermode* Create(const ProcCoeff& rec) {
1148 return SkNEW_ARGS(SkDstInXfermode, (rec));
1151 void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1153 SK_TO_STRING_OVERRIDE()
1156 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1158 typedef SkProcCoeffXfermode INHERITED;
1161 void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1162 const SkPMColor* SK_RESTRICT src, int count,
1163 const SkAlpha* SK_RESTRICT aa) const {
1164 SkASSERT(dst && src);
1170 return this->INHERITED::xfer32(dst, src, count, aa);
1174 unsigned a = SkGetPackedA32(*src);
1175 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1178 } while (--count != 0);
1181 #ifndef SK_IGNORE_TO_STRING
1182 void SkDstInXfermode::toString(SkString* str) const {
1183 this->INHERITED::toString(str);
1187 ///////////////////////////////////////////////////////////////////////////////
1189 class SkDstOutXfermode : public SkProcCoeffXfermode {
1191 static SkDstOutXfermode* Create(const ProcCoeff& rec) {
1192 return SkNEW_ARGS(SkDstOutXfermode, (rec));
1195 void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1197 SK_TO_STRING_OVERRIDE()
1200 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1202 typedef SkProcCoeffXfermode INHERITED;
1205 void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1206 const SkPMColor* SK_RESTRICT src, int count,
1207 const SkAlpha* SK_RESTRICT aa) const {
1208 SkASSERT(dst && src);
1214 return this->INHERITED::xfer32(dst, src, count, aa);
1218 unsigned a = SkGetPackedA32(*src);
1219 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1222 } while (--count != 0);
1225 #ifndef SK_IGNORE_TO_STRING
1226 void SkDstOutXfermode::toString(SkString* str) const {
1227 this->INHERITED::toString(str);
1231 ///////////////////////////////////////////////////////////////////////////////
1233 extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, SkXfermode::Mode mode);
1234 extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
1236 // Technically, can't be static and passed as a template parameter. So we use anonymous namespace.
1238 SkXfermode* create_mode(int iMode) {
1239 SkXfermode::Mode mode = (SkXfermode::Mode)iMode;
1241 ProcCoeff rec = gProcCoeffs[mode];
1242 SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
1247 SkXfermode* xfer = NULL;
1248 // check if we have a platform optim for that
1249 SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
1253 // All modes can in theory be represented by the ProcCoeff rec, since
1254 // it contains function ptrs. However, a few modes are both simple and
1255 // commonly used, so we call those out for their own subclasses here.
1257 case SkXfermode::kClear_Mode:
1258 xfer = SkClearXfermode::Create(rec);
1260 case SkXfermode::kSrc_Mode:
1261 xfer = SkSrcXfermode::Create(rec);
1263 case SkXfermode::kSrcOver_Mode:
1264 SkASSERT(false); // should not land here
1266 case SkXfermode::kDstIn_Mode:
1267 xfer = SkDstInXfermode::Create(rec);
1269 case SkXfermode::kDstOut_Mode:
1270 xfer = SkDstOutXfermode::Create(rec);
1273 // no special-case, just rely in the rec and its function-ptrs
1274 xfer = SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1282 SK_DECLARE_STATIC_LAZY_PTR_ARRAY(SkXfermode, cached, SkXfermode::kLastMode + 1, create_mode);
1284 SkXfermode* SkXfermode::Create(Mode mode) {
1285 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1287 if ((unsigned)mode >= kModeCount) {
1292 // Skia's "default" mode is srcover. NULL in SkPaint is interpreted as srcover
1293 // so we can just return NULL from the factory.
1294 if (kSrcOver_Mode == mode) {
1298 return SkSafeRef(cached[mode]);
1301 SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1302 SkXfermodeProc proc = NULL;
1303 if ((unsigned)mode < kModeCount) {
1304 proc = gProcCoeffs[mode].fProc;
1309 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1310 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1312 if ((unsigned)mode >= (unsigned)kModeCount) {
1313 // illegal mode parameter
1317 const ProcCoeff& rec = gProcCoeffs[mode];
1319 if (CANNOT_USE_COEFF == rec.fSC) {
1323 SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1333 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1336 *mode = kSrcOver_Mode;
1340 return xfer->asMode(mode);
1343 bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1344 // if xfer==null then the mode is srcover
1345 Mode m = kSrcOver_Mode;
1346 if (xfer && !xfer->asMode(&m)) {
1352 bool SkXfermode::SupportsCoverageAsAlpha(const SkXfermode* xfer) {
1353 // if xfer is NULL we treat it as srcOver which always supports coverageAsAlpha
1358 return xfer->supportsCoverageAsAlpha();
1361 bool SkXfermode::IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType) {
1362 // if xfer is NULL we treat it as srcOver which is opaque if our src is opaque
1364 return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
1367 return xfer->isOpaque(opacityType);
1370 ///////////////////////////////////////////////////////////////////////////////
1371 //////////// 16bit xfermode procs
1374 static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1375 static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1378 static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1379 SkASSERT(require_255(src));
1380 return SkPixel32ToPixel16(src);
1383 static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1387 static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1388 SkASSERT(require_0(src));
1392 static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1393 SkASSERT(require_255(src));
1394 return SkPixel32ToPixel16(src);
1397 static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1398 SkASSERT(require_0(src));
1402 static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1403 SkASSERT(require_255(src));
1407 static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1408 SkASSERT(require_255(src));
1409 return SkPixel32ToPixel16(src);
1412 static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1413 SkASSERT(require_255(src));
1417 static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1418 SkASSERT(require_0(src));
1422 static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1423 unsigned isa = 255 - SkGetPackedA32(src);
1426 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1427 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1428 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1431 static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1432 SkASSERT(require_0(src));
1436 static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1437 SkASSERT(require_255(src));
1438 return SkPixel32ToPixel16(src);
1441 static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1442 SkASSERT(require_255(src));
1447 darken and lighten boil down to this.
1449 darken = (1 - Sa) * Dc + min(Sc, Dc)
1450 lighten = (1 - Sa) * Dc + max(Sc, Dc)
1452 if (Sa == 0) these become
1453 darken = Dc + min(0, Dc) = 0
1454 lighten = Dc + max(0, Dc) = Dc
1456 if (Sa == 1) these become
1457 darken = min(Sc, Dc)
1458 lighten = max(Sc, Dc)
1461 static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1462 SkASSERT(require_0(src));
1466 static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1467 SkASSERT(require_255(src));
1468 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1469 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1470 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1471 return SkPackRGB16(r, g, b);
1474 static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1475 SkASSERT(require_0(src));
1479 static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1480 SkASSERT(require_255(src));
1481 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1482 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1483 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1484 return SkPackRGB16(r, g, b);
1488 SkXfermodeProc16 fProc16_0;
1489 SkXfermodeProc16 fProc16_255;
1490 SkXfermodeProc16 fProc16_General;
1493 static const Proc16Rec gModeProcs16[] = {
1494 { NULL, NULL, NULL }, // CLEAR
1495 { NULL, src_modeproc16_255, NULL },
1496 { dst_modeproc16, dst_modeproc16, dst_modeproc16 },
1497 { srcover_modeproc16_0, srcover_modeproc16_255, NULL },
1498 { dstover_modeproc16_0, dstover_modeproc16_255, NULL },
1499 { NULL, srcin_modeproc16_255, NULL },
1500 { NULL, dstin_modeproc16_255, NULL },
1501 { NULL, NULL, NULL },// SRC_OUT
1502 { dstout_modeproc16_0, NULL, NULL },
1503 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 },
1504 { NULL, dstatop_modeproc16_255, NULL },
1505 { NULL, NULL, NULL }, // XOR
1507 { NULL, NULL, NULL }, // plus
1508 { NULL, NULL, NULL }, // modulate
1509 { NULL, NULL, NULL }, // screen
1510 { NULL, NULL, NULL }, // overlay
1511 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken
1512 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten
1513 { NULL, NULL, NULL }, // colordodge
1514 { NULL, NULL, NULL }, // colorburn
1515 { NULL, NULL, NULL }, // hardlight
1516 { NULL, NULL, NULL }, // softlight
1517 { NULL, NULL, NULL }, // difference
1518 { NULL, NULL, NULL }, // exclusion
1519 { NULL, NULL, NULL }, // multiply
1520 { NULL, NULL, NULL }, // hue
1521 { NULL, NULL, NULL }, // saturation
1522 { NULL, NULL, NULL }, // color
1523 { NULL, NULL, NULL }, // luminosity
1526 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1527 SkXfermodeProc16 proc16 = NULL;
1528 if ((unsigned)mode < kModeCount) {
1529 const Proc16Rec& rec = gModeProcs16[mode];
1530 unsigned a = SkColorGetA(srcColor);
1533 proc16 = rec.fProc16_0;
1534 } else if (255 == a) {
1535 proc16 = rec.fProc16_255;
1537 proc16 = rec.fProc16_General;
1543 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1544 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1545 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END