• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
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  */
8 
9 
10 #include "SkXfermode.h"
11 #include "SkColorPriv.h"
12 #include "SkFlattenableBuffers.h"
13 #include "SkMathPriv.h"
14 #include "SkString.h"
15 
SK_DEFINE_INST_COUNT(SkXfermode)16 SK_DEFINE_INST_COUNT(SkXfermode)
17 
18 #define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
19 
20 #if 0
21 // idea for higher precision blends in xfer procs (and slightly faster)
22 // see DstATop as a probable caller
23 static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
24     SkASSERT(a <= 255);
25     SkASSERT(b <= 255);
26     SkASSERT(c <= 255);
27     SkASSERT(d <= 255);
28     unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
29     unsigned result = (prod + (prod >> 8)) >> 8;
30     SkASSERT(result <= 255);
31     return result;
32 }
33 #endif
34 
35 static inline unsigned saturated_add(unsigned a, unsigned b) {
36     SkASSERT(a <= 255);
37     SkASSERT(b <= 255);
38     unsigned sum = a + b;
39     if (sum > 255) {
40         sum = 255;
41     }
42     return sum;
43 }
44 
clamp_signed_byte(int n)45 static inline int clamp_signed_byte(int n) {
46     if (n < 0) {
47         n = 0;
48     } else if (n > 255) {
49         n = 255;
50     }
51     return n;
52 }
53 
clamp_div255round(int prod)54 static inline int clamp_div255round(int prod) {
55     if (prod <= 0) {
56         return 0;
57     } else if (prod >= 255*255) {
58         return 255;
59     } else {
60         return SkDiv255Round(prod);
61     }
62 }
63 
clamp_max(int value,int max)64 static inline int clamp_max(int value, int max) {
65     if (value > max) {
66         value = max;
67     }
68     return value;
69 }
70 
71 ///////////////////////////////////////////////////////////////////////////////
72 
73 //  kClear_Mode,    //!< [0, 0]
clear_modeproc(SkPMColor src,SkPMColor dst)74 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
75     return 0;
76 }
77 
78 //  kSrc_Mode,      //!< [Sa, Sc]
src_modeproc(SkPMColor src,SkPMColor dst)79 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
80     return src;
81 }
82 
83 //  kDst_Mode,      //!< [Da, Dc]
dst_modeproc(SkPMColor src,SkPMColor dst)84 static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
85     return dst;
86 }
87 
88 //  kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
srcover_modeproc(SkPMColor src,SkPMColor dst)89 static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
90 #if 0
91     // this is the old, more-correct way, but it doesn't guarantee that dst==255
92     // will always stay opaque
93     return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
94 #else
95     // this is slightly faster, but more importantly guarantees that dst==255
96     // will always stay opaque
97     return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
98 #endif
99 }
100 
101 //  kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
dstover_modeproc(SkPMColor src,SkPMColor dst)102 static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
103     // this is the reverse of srcover, just flipping src and dst
104     // see srcover's comment about the 256 for opaqueness guarantees
105     return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
106 }
107 
108 //  kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
srcin_modeproc(SkPMColor src,SkPMColor dst)109 static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
110     return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
111 }
112 
113 //  kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
dstin_modeproc(SkPMColor src,SkPMColor dst)114 static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
115     return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
116 }
117 
118 //  kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
srcout_modeproc(SkPMColor src,SkPMColor dst)119 static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
120     return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
121 }
122 
123 //  kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
dstout_modeproc(SkPMColor src,SkPMColor dst)124 static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
125     return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
126 }
127 
128 //  kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
srcatop_modeproc(SkPMColor src,SkPMColor dst)129 static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
130     unsigned sa = SkGetPackedA32(src);
131     unsigned da = SkGetPackedA32(dst);
132     unsigned isa = 255 - sa;
133 
134     return SkPackARGB32(da,
135                         SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
136                             SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
137                         SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
138                             SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
139                         SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
140                             SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
141 }
142 
143 //  kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
dstatop_modeproc(SkPMColor src,SkPMColor dst)144 static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
145     unsigned sa = SkGetPackedA32(src);
146     unsigned da = SkGetPackedA32(dst);
147     unsigned ida = 255 - da;
148 
149     return SkPackARGB32(sa,
150                         SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
151                             SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
152                         SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
153                             SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
154                         SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
155                             SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
156 }
157 
158 //  kXor_Mode   [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
xor_modeproc(SkPMColor src,SkPMColor dst)159 static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
160     unsigned sa = SkGetPackedA32(src);
161     unsigned da = SkGetPackedA32(dst);
162     unsigned isa = 255 - sa;
163     unsigned ida = 255 - da;
164 
165     return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
166                         SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
167                             SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
168                         SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
169                             SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
170                         SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
171                             SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
172 }
173 
174 ///////////////////////////////////////////////////////////////////////////////
175 
176 // kPlus_Mode
plus_modeproc(SkPMColor src,SkPMColor dst)177 static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
178     unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
179     unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
180     unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
181     unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
182     return SkPackARGB32(a, r, g, b);
183 }
184 
185 // kModulate_Mode
modulate_modeproc(SkPMColor src,SkPMColor dst)186 static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
187     int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
188     int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
189     int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
190     int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
191     return SkPackARGB32(a, r, g, b);
192 }
193 
194 // kScreen_Mode
srcover_byte(int a,int b)195 static inline int srcover_byte(int a, int b) {
196     return a + b - SkAlphaMulAlpha(a, b);
197 }
screen_modeproc(SkPMColor src,SkPMColor dst)198 static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
199     int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
200     int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
201     int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
202     int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
203     return SkPackARGB32(a, r, g, b);
204 }
205 
206 // kOverlay_Mode
overlay_byte(int sc,int dc,int sa,int da)207 static inline int overlay_byte(int sc, int dc, int sa, int da) {
208     int tmp = sc * (255 - da) + dc * (255 - sa);
209     int rc;
210     if (2 * dc <= da) {
211         rc = 2 * sc * dc;
212     } else {
213         rc = sa * da - 2 * (da - dc) * (sa - sc);
214     }
215     return clamp_div255round(rc + tmp);
216 }
overlay_modeproc(SkPMColor src,SkPMColor dst)217 static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
218     int sa = SkGetPackedA32(src);
219     int da = SkGetPackedA32(dst);
220     int a = srcover_byte(sa, da);
221     int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
222     int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
223     int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
224     return SkPackARGB32(a, r, g, b);
225 }
226 
227 // kDarken_Mode
darken_byte(int sc,int dc,int sa,int da)228 static inline int darken_byte(int sc, int dc, int sa, int da) {
229     int sd = sc * da;
230     int ds = dc * sa;
231     if (sd < ds) {
232         // srcover
233         return sc + dc - SkDiv255Round(ds);
234     } else {
235         // dstover
236         return dc + sc - SkDiv255Round(sd);
237     }
238 }
darken_modeproc(SkPMColor src,SkPMColor dst)239 static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
240     int sa = SkGetPackedA32(src);
241     int da = SkGetPackedA32(dst);
242     int a = srcover_byte(sa, da);
243     int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
244     int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
245     int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
246     return SkPackARGB32(a, r, g, b);
247 }
248 
249 // kLighten_Mode
lighten_byte(int sc,int dc,int sa,int da)250 static inline int lighten_byte(int sc, int dc, int sa, int da) {
251     int sd = sc * da;
252     int ds = dc * sa;
253     if (sd > ds) {
254         // srcover
255         return sc + dc - SkDiv255Round(ds);
256     } else {
257         // dstover
258         return dc + sc - SkDiv255Round(sd);
259     }
260 }
lighten_modeproc(SkPMColor src,SkPMColor dst)261 static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
262     int sa = SkGetPackedA32(src);
263     int da = SkGetPackedA32(dst);
264     int a = srcover_byte(sa, da);
265     int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
266     int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
267     int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
268     return SkPackARGB32(a, r, g, b);
269 }
270 
271 // kColorDodge_Mode
colordodge_byte(int sc,int dc,int sa,int da)272 static inline int colordodge_byte(int sc, int dc, int sa, int da) {
273     int diff = sa - sc;
274     int rc;
275     if (0 == diff) {
276         rc = sa * da + sc * (255 - da) + dc * (255 - sa);
277         rc = SkDiv255Round(rc);
278     } else {
279         int tmp = (dc * sa << 15) / (da * diff);
280         rc = SkDiv255Round(sa * da) * tmp >> 15;
281         // don't clamp here, since we'll do it in our modeproc
282     }
283     return rc;
284 }
colordodge_modeproc(SkPMColor src,SkPMColor dst)285 static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
286     // added to avoid div-by-zero in colordodge_byte
287     if (0 == dst) {
288         return src;
289     }
290 
291     int sa = SkGetPackedA32(src);
292     int da = SkGetPackedA32(dst);
293     int a = srcover_byte(sa, da);
294     int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
295     int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
296     int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
297     r = clamp_max(r, a);
298     g = clamp_max(g, a);
299     b = clamp_max(b, a);
300     return SkPackARGB32(a, r, g, b);
301 }
302 
303 // kColorBurn_Mode
colorburn_byte(int sc,int dc,int sa,int da)304 static inline int colorburn_byte(int sc, int dc, int sa, int da) {
305     int rc;
306     if (dc == da && 0 == sc) {
307         rc = sa * da + dc * (255 - sa);
308     } else if (0 == sc) {
309         return SkAlphaMulAlpha(dc, 255 - sa);
310     } else {
311         int tmp = (sa * (da - dc) * 256) / (sc * da);
312         if (tmp > 256) {
313             tmp = 256;
314         }
315         int tmp2 = sa * da;
316         rc = tmp2 - (tmp2 * tmp >> 8) + sc * (255 - da) + dc * (255 - sa);
317     }
318     return SkDiv255Round(rc);
319 }
colorburn_modeproc(SkPMColor src,SkPMColor dst)320 static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
321     // added to avoid div-by-zero in colorburn_byte
322     if (0 == dst) {
323         return src;
324     }
325 
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 }
334 
335 // kHardLight_Mode
hardlight_byte(int sc,int dc,int sa,int da)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 }
hardlight_modeproc(SkPMColor src,SkPMColor dst)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 }
354 
355 // returns 255 * sqrt(n/255)
sqrt_unit_byte(U8CPU n)356 static U8CPU sqrt_unit_byte(U8CPU n) {
357     return SkSqrtBits(n, 15+4);
358 }
359 
360 // kSoftLight_Mode
softlight_byte(int sc,int dc,int sa,int da)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 }
softlight_modeproc(SkPMColor src,SkPMColor dst)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 }
384 
385 // kDifference_Mode
difference_byte(int sc,int dc,int sa,int da)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 }
difference_modeproc(SkPMColor src,SkPMColor dst)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 }
399 
400 // kExclusion_Mode
exclusion_byte(int sc,int dc,int sa,int da)401 static inline int exclusion_byte(int sc, int dc, int sa, int da) {
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);
404     return clamp_div255round(r);
405 }
exclusion_modeproc(SkPMColor src,SkPMColor dst)406 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
407     int sa = SkGetPackedA32(src);
408     int da = SkGetPackedA32(dst);
409     int a = srcover_byte(sa, da);
410     int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
411     int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
412     int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
413     return SkPackARGB32(a, r, g, b);
414 }
415 
416 struct ProcCoeff {
417     SkXfermodeProc      fProc;
418     SkXfermode::Coeff   fSC;
419     SkXfermode::Coeff   fDC;
420 };
421 
422 #define CANNOT_USE_COEFF    SkXfermode::Coeff(-1)
423 
424 static const ProcCoeff gProcCoeffs[] = {
425     { clear_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kZero_Coeff },
426     { src_modeproc,     SkXfermode::kOne_Coeff,     SkXfermode::kZero_Coeff },
427     { dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
428     { srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
429     { dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
430     { srcin_modeproc,   SkXfermode::kDA_Coeff,      SkXfermode::kZero_Coeff },
431     { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
432     { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
433     { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
434     { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
435     { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
436     { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
437 
438     { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
439     { modulate_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
440     { screen_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
441     { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
442     { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
443     { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
444     { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
445     { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
446     { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
447     { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
448     { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
449     { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
450 };
451 
452 ///////////////////////////////////////////////////////////////////////////////
453 
asCoeff(Coeff * src,Coeff * dst) const454 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const {
455     return false;
456 }
457 
asMode(Mode * mode) const458 bool SkXfermode::asMode(Mode* mode) const {
459     return false;
460 }
461 
xferColor(SkPMColor src,SkPMColor dst) const462 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
463     // no-op. subclasses should override this
464     return dst;
465 }
466 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const467 void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
468                         const SkPMColor* SK_RESTRICT src, int count,
469                         const SkAlpha* SK_RESTRICT aa) const {
470     SkASSERT(dst && src && count >= 0);
471 
472     if (NULL == aa) {
473         for (int i = count - 1; i >= 0; --i) {
474             dst[i] = this->xferColor(src[i], dst[i]);
475         }
476     } else {
477         for (int i = count - 1; i >= 0; --i) {
478             unsigned a = aa[i];
479             if (0 != a) {
480                 SkPMColor dstC = dst[i];
481                 SkPMColor C = this->xferColor(src[i], dstC);
482                 if (0xFF != a) {
483                     C = SkFourByteInterp(C, dstC, a);
484                 }
485                 dst[i] = C;
486             }
487         }
488     }
489 }
490 
xfer16(uint16_t * dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const491 void SkXfermode::xfer16(uint16_t* dst,
492                         const SkPMColor* SK_RESTRICT src, int count,
493                         const SkAlpha* SK_RESTRICT aa) const {
494     SkASSERT(dst && src && count >= 0);
495 
496     if (NULL == aa) {
497         for (int i = count - 1; i >= 0; --i) {
498             SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
499             dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
500         }
501     } else {
502         for (int i = count - 1; i >= 0; --i) {
503             unsigned a = aa[i];
504             if (0 != a) {
505                 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
506                 SkPMColor C = this->xferColor(src[i], dstC);
507                 if (0xFF != a) {
508                     C = SkFourByteInterp(C, dstC, a);
509                 }
510                 dst[i] = SkPixel32ToPixel16_ToU16(C);
511             }
512         }
513     }
514 }
515 
xfer4444(SkPMColor16 * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const516 void SkXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst,
517                           const SkPMColor* SK_RESTRICT src, int count,
518                           const SkAlpha* SK_RESTRICT aa) const {
519     SkASSERT(dst && src && count >= 0);
520 
521     if (NULL == aa) {
522         for (int i = count - 1; i >= 0; --i) {
523             SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
524             dst[i] = SkPixel32ToPixel4444(this->xferColor(src[i], dstC));
525         }
526     } else {
527         for (int i = count - 1; i >= 0; --i) {
528             unsigned a = aa[i];
529             if (0 != a) {
530                 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
531                 SkPMColor C = this->xferColor(src[i], dstC);
532                 if (0xFF != a) {
533                     C = SkFourByteInterp(C, dstC, a);
534                 }
535                 dst[i] = SkPixel32ToPixel4444(C);
536             }
537         }
538     }
539 }
540 
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor src[],int count,const SkAlpha * SK_RESTRICT aa) const541 void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
542                         const SkPMColor src[], int count,
543                         const SkAlpha* SK_RESTRICT aa) const {
544     SkASSERT(dst && src && count >= 0);
545 
546     if (NULL == aa) {
547         for (int i = count - 1; i >= 0; --i) {
548             SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
549             dst[i] = SkToU8(SkGetPackedA32(res));
550         }
551     } else {
552         for (int i = count - 1; i >= 0; --i) {
553             unsigned a = aa[i];
554             if (0 != a) {
555                 SkAlpha dstA = dst[i];
556                 unsigned A = SkGetPackedA32(this->xferColor(src[i],
557                                             (SkPMColor)(dstA << SK_A32_SHIFT)));
558                 if (0xFF != a) {
559                     A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
560                 }
561                 dst[i] = SkToU8(A);
562             }
563         }
564     }
565 }
566 
567 ///////////////////////////////////////////////////////////////////////////////
568 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const569 void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
570                             const SkPMColor* SK_RESTRICT src, int count,
571                             const SkAlpha* SK_RESTRICT aa) const {
572     SkASSERT(dst && src && count >= 0);
573 
574     SkXfermodeProc proc = fProc;
575 
576     if (NULL != proc) {
577         if (NULL == aa) {
578             for (int i = count - 1; i >= 0; --i) {
579                 dst[i] = proc(src[i], dst[i]);
580             }
581         } else {
582             for (int i = count - 1; i >= 0; --i) {
583                 unsigned a = aa[i];
584                 if (0 != a) {
585                     SkPMColor dstC = dst[i];
586                     SkPMColor C = proc(src[i], dstC);
587                     if (a != 0xFF) {
588                         C = SkFourByteInterp(C, dstC, a);
589                     }
590                     dst[i] = C;
591                 }
592             }
593         }
594     }
595 }
596 
xfer16(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const597 void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst,
598                             const SkPMColor* SK_RESTRICT src, int count,
599                             const SkAlpha* SK_RESTRICT aa) const {
600     SkASSERT(dst && src && count >= 0);
601 
602     SkXfermodeProc proc = fProc;
603 
604     if (NULL != proc) {
605         if (NULL == aa) {
606             for (int i = count - 1; i >= 0; --i) {
607                 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
608                 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
609             }
610         } else {
611             for (int i = count - 1; i >= 0; --i) {
612                 unsigned a = aa[i];
613                 if (0 != a) {
614                     SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
615                     SkPMColor C = proc(src[i], dstC);
616                     if (0xFF != a) {
617                         C = SkFourByteInterp(C, dstC, a);
618                     }
619                     dst[i] = SkPixel32ToPixel16_ToU16(C);
620                 }
621             }
622         }
623     }
624 }
625 
xfer4444(SkPMColor16 * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const626 void SkProcXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst,
627                               const SkPMColor* SK_RESTRICT src, int count,
628                               const SkAlpha* SK_RESTRICT aa) const {
629     SkASSERT(dst && src && count >= 0);
630 
631     SkXfermodeProc proc = fProc;
632 
633     if (NULL != proc) {
634         if (NULL == aa) {
635             for (int i = count - 1; i >= 0; --i) {
636                 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
637                 dst[i] = SkPixel32ToPixel4444(proc(src[i], dstC));
638             }
639         } else {
640             for (int i = count - 1; i >= 0; --i) {
641                 unsigned a = aa[i];
642                 if (0 != a) {
643                     SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
644                     SkPMColor C = proc(src[i], dstC);
645                     if (0xFF != a) {
646                         C = SkFourByteInterp(C, dstC, a);
647                     }
648                     dst[i] = SkPixel32ToPixel4444(C);
649                 }
650             }
651         }
652     }
653 }
654 
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const655 void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
656                             const SkPMColor* SK_RESTRICT src, int count,
657                             const SkAlpha* SK_RESTRICT aa) const {
658     SkASSERT(dst && src && count >= 0);
659 
660     SkXfermodeProc proc = fProc;
661 
662     if (NULL != proc) {
663         if (NULL == aa) {
664             for (int i = count - 1; i >= 0; --i) {
665                 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
666                 dst[i] = SkToU8(SkGetPackedA32(res));
667             }
668         } else {
669             for (int i = count - 1; i >= 0; --i) {
670                 unsigned a = aa[i];
671                 if (0 != a) {
672                     SkAlpha dstA = dst[i];
673                     SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
674                     unsigned A = SkGetPackedA32(res);
675                     if (0xFF != a) {
676                         A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
677                     }
678                     dst[i] = SkToU8(A);
679                 }
680             }
681         }
682     }
683 }
684 
SkProcXfermode(SkFlattenableReadBuffer & buffer)685 SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer)
686         : SkXfermode(buffer) {
687     fProc = NULL;
688     if (!buffer.isCrossProcess()) {
689         fProc = (SkXfermodeProc)buffer.readFunctionPtr();
690     }
691 }
692 
flatten(SkFlattenableWriteBuffer & buffer) const693 void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
694     this->INHERITED::flatten(buffer);
695     if (!buffer.isCrossProcess()) {
696         buffer.writeFunctionPtr((void*)fProc);
697     }
698 }
699 
700 #ifdef SK_DEVELOPER
toString(SkString * str) const701 void SkProcXfermode::toString(SkString* str) const {
702     str->appendf("SkProcXfermode: %p", fProc);
703 }
704 #endif
705 
706 ///////////////////////////////////////////////////////////////////////////////
707 ///////////////////////////////////////////////////////////////////////////////
708 
709 class SkProcCoeffXfermode : public SkProcXfermode {
710 public:
SkProcCoeffXfermode(const ProcCoeff & rec,Mode mode)711     SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode)
712             : INHERITED(rec.fProc) {
713         fMode = mode;
714         // these may be valid, or may be CANNOT_USE_COEFF
715         fSrcCoeff = rec.fSC;
716         fDstCoeff = rec.fDC;
717     }
718 
asMode(Mode * mode) const719     virtual bool asMode(Mode* mode) const SK_OVERRIDE {
720         if (mode) {
721             *mode = fMode;
722         }
723         return true;
724     }
725 
asCoeff(Coeff * sc,Coeff * dc) const726     virtual bool asCoeff(Coeff* sc, Coeff* dc) const SK_OVERRIDE {
727         if (CANNOT_USE_COEFF == fSrcCoeff) {
728             return false;
729         }
730 
731         if (sc) {
732             *sc = fSrcCoeff;
733         }
734         if (dc) {
735             *dc = fDstCoeff;
736         }
737         return true;
738     }
739 
740     SK_DEVELOPER_TO_STRING()
741     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode)
742 
743 protected:
SkProcCoeffXfermode(SkFlattenableReadBuffer & buffer)744     SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
745         fMode = (SkXfermode::Mode)buffer.read32();
746 
747         const ProcCoeff& rec = gProcCoeffs[fMode];
748         // these may be valid, or may be CANNOT_USE_COEFF
749         fSrcCoeff = rec.fSC;
750         fDstCoeff = rec.fDC;
751         // now update our function-ptr in the super class
752         this->INHERITED::setProc(rec.fProc);
753     }
754 
flatten(SkFlattenableWriteBuffer & buffer) const755     virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
756         this->INHERITED::flatten(buffer);
757         buffer.write32(fMode);
758     }
759 
760 private:
761     Mode    fMode;
762     Coeff   fSrcCoeff, fDstCoeff;
763 
764     typedef SkProcXfermode INHERITED;
765 };
766 
767 #ifdef SK_DEVELOPER
toString(SkString * str) const768 void SkProcCoeffXfermode::toString(SkString* str) const {
769     str->append("SkProcCoeffXfermode: ");
770 
771     const char *gModeStrings[kLastMode+1] = {
772         "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
773         "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
774         "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
775         "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion"
776     };
777 
778     str->append("mode: ");
779     str->append(gModeStrings[fMode]);
780 
781     static const char* gCoeffStrings[kCoeffCount] = {
782         "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
783     };
784 
785     str->append(" src: ");
786     if (CANNOT_USE_COEFF == fSrcCoeff) {
787         str->append("can't use");
788     } else {
789         str->append(gCoeffStrings[fSrcCoeff]);
790     }
791 
792     str->append(" dst: ");
793     if (CANNOT_USE_COEFF == fDstCoeff) {
794         str->append("can't use");
795     } else {
796         str->append(gCoeffStrings[fDstCoeff]);
797     }
798 }
799 #endif
800 
801 ///////////////////////////////////////////////////////////////////////////////
802 
803 class SkClearXfermode : public SkProcCoeffXfermode {
804 public:
SkClearXfermode(const ProcCoeff & rec)805     SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
806 
807     virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
808     virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
809 
810     SK_DEVELOPER_TO_STRING()
811     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode)
812 
813 private:
SkClearXfermode(SkFlattenableReadBuffer & buffer)814     SkClearXfermode(SkFlattenableReadBuffer& buffer)
815         : SkProcCoeffXfermode(buffer) {}
816 
817     typedef SkProcCoeffXfermode INHERITED;
818 };
819 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT,int count,const SkAlpha * SK_RESTRICT aa) const820 void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
821                              const SkPMColor* SK_RESTRICT, int count,
822                              const SkAlpha* SK_RESTRICT aa) const {
823     SkASSERT(dst && count >= 0);
824 
825     if (NULL == aa) {
826         memset(dst, 0, count << 2);
827     } else {
828         for (int i = count - 1; i >= 0; --i) {
829             unsigned a = aa[i];
830             if (0xFF == a) {
831                 dst[i] = 0;
832             } else if (a != 0) {
833                 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
834             }
835         }
836     }
837 }
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT,int count,const SkAlpha * SK_RESTRICT aa) const838 void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
839                              const SkPMColor* SK_RESTRICT, int count,
840                              const SkAlpha* SK_RESTRICT aa) const {
841     SkASSERT(dst && count >= 0);
842 
843     if (NULL == aa) {
844         memset(dst, 0, count);
845     } else {
846         for (int i = count - 1; i >= 0; --i) {
847             unsigned a = aa[i];
848             if (0xFF == a) {
849                 dst[i] = 0;
850             } else if (0 != a) {
851                 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
852             }
853         }
854     }
855 }
856 
857 #ifdef SK_DEVELOPER
toString(SkString * str) const858 void SkClearXfermode::toString(SkString* str) const {
859     this->INHERITED::toString(str);
860 }
861 #endif
862 
863 ///////////////////////////////////////////////////////////////////////////////
864 
865 class SkSrcXfermode : public SkProcCoeffXfermode {
866 public:
SkSrcXfermode(const ProcCoeff & rec)867     SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
868 
869     virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
870     virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
871 
872     SK_DEVELOPER_TO_STRING()
873     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode)
874 
875 private:
SkSrcXfermode(SkFlattenableReadBuffer & buffer)876     SkSrcXfermode(SkFlattenableReadBuffer& buffer)
877         : SkProcCoeffXfermode(buffer) {}
878 
879     typedef SkProcCoeffXfermode INHERITED;
880 };
881 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const882 void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
883                            const SkPMColor* SK_RESTRICT src, int count,
884                            const SkAlpha* SK_RESTRICT aa) const {
885     SkASSERT(dst && src && count >= 0);
886 
887     if (NULL == aa) {
888         memcpy(dst, src, count << 2);
889     } else {
890         for (int i = count - 1; i >= 0; --i) {
891             unsigned a = aa[i];
892             if (a == 0xFF) {
893                 dst[i] = src[i];
894             } else if (a != 0) {
895                 dst[i] = SkFourByteInterp(src[i], dst[i], a);
896             }
897         }
898     }
899 }
900 
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const901 void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
902                            const SkPMColor* SK_RESTRICT src, int count,
903                            const SkAlpha* SK_RESTRICT aa) const {
904     SkASSERT(dst && src && count >= 0);
905 
906     if (NULL == aa) {
907         for (int i = count - 1; i >= 0; --i) {
908             dst[i] = SkToU8(SkGetPackedA32(src[i]));
909         }
910     } else {
911         for (int i = count - 1; i >= 0; --i) {
912             unsigned a = aa[i];
913             if (0 != a) {
914                 unsigned srcA = SkGetPackedA32(src[i]);
915                 if (a == 0xFF) {
916                     dst[i] = SkToU8(srcA);
917                 } else {
918                     dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
919                 }
920             }
921         }
922     }
923 }
924 #ifdef SK_DEVELOPER
toString(SkString * str) const925 void SkSrcXfermode::toString(SkString* str) const {
926     this->INHERITED::toString(str);
927 }
928 #endif
929 
930 ///////////////////////////////////////////////////////////////////////////////
931 
932 class SkDstInXfermode : public SkProcCoeffXfermode {
933 public:
SkDstInXfermode(const ProcCoeff & rec)934     SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
935 
936     virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
937 
938     SK_DEVELOPER_TO_STRING()
939     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode)
940 
941 private:
SkDstInXfermode(SkFlattenableReadBuffer & buffer)942     SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
943 
944     typedef SkProcCoeffXfermode INHERITED;
945 };
946 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const947 void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
948                              const SkPMColor* SK_RESTRICT src, int count,
949                              const SkAlpha* SK_RESTRICT aa) const {
950     SkASSERT(dst && src);
951 
952     if (count <= 0) {
953         return;
954     }
955     if (NULL != aa) {
956         return this->INHERITED::xfer32(dst, src, count, aa);
957     }
958 
959     do {
960         unsigned a = SkGetPackedA32(*src);
961         *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
962         dst++;
963         src++;
964     } while (--count != 0);
965 }
966 
967 #ifdef SK_DEVELOPER
toString(SkString * str) const968 void SkDstInXfermode::toString(SkString* str) const {
969     this->INHERITED::toString(str);
970 }
971 #endif
972 
973 ///////////////////////////////////////////////////////////////////////////////
974 
975 class SkDstOutXfermode : public SkProcCoeffXfermode {
976 public:
SkDstOutXfermode(const ProcCoeff & rec)977     SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
978 
979     virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
980 
981     SK_DEVELOPER_TO_STRING()
982     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode)
983 
984 private:
SkDstOutXfermode(SkFlattenableReadBuffer & buffer)985     SkDstOutXfermode(SkFlattenableReadBuffer& buffer)
986         : INHERITED(buffer) {}
987 
988     typedef SkProcCoeffXfermode INHERITED;
989 };
990 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const991 void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
992                               const SkPMColor* SK_RESTRICT src, int count,
993                               const SkAlpha* SK_RESTRICT aa) const {
994     SkASSERT(dst && src);
995 
996     if (count <= 0) {
997         return;
998     }
999     if (NULL != aa) {
1000         return this->INHERITED::xfer32(dst, src, count, aa);
1001     }
1002 
1003     do {
1004         unsigned a = SkGetPackedA32(*src);
1005         *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1006         dst++;
1007         src++;
1008     } while (--count != 0);
1009 }
1010 
1011 #ifdef SK_DEVELOPER
toString(SkString * str) const1012 void SkDstOutXfermode::toString(SkString* str) const {
1013     this->INHERITED::toString(str);
1014 }
1015 #endif
1016 
1017 ///////////////////////////////////////////////////////////////////////////////
1018 
Create(Mode mode)1019 SkXfermode* SkXfermode::Create(Mode mode) {
1020     SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1021     SkASSERT((unsigned)mode < kModeCount);
1022 
1023     const ProcCoeff& rec = gProcCoeffs[mode];
1024 
1025     switch (mode) {
1026         case kClear_Mode:
1027             return SkNEW_ARGS(SkClearXfermode, (rec));
1028         case kSrc_Mode:
1029             return SkNEW_ARGS(SkSrcXfermode, (rec));
1030         case kSrcOver_Mode:
1031             return NULL;
1032         case kDstIn_Mode:
1033             return SkNEW_ARGS(SkDstInXfermode, (rec));
1034         case kDstOut_Mode:
1035             return SkNEW_ARGS(SkDstOutXfermode, (rec));
1036         default:
1037             return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1038     }
1039 }
1040 
GetProc(Mode mode)1041 SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1042     SkXfermodeProc  proc = NULL;
1043     if ((unsigned)mode < kModeCount) {
1044         proc = gProcCoeffs[mode].fProc;
1045     }
1046     return proc;
1047 }
1048 
ModeAsCoeff(Mode mode,Coeff * src,Coeff * dst)1049 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1050     SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1051 
1052     if ((unsigned)mode >= (unsigned)kModeCount) {
1053         // illegal mode parameter
1054         return false;
1055     }
1056 
1057     const ProcCoeff& rec = gProcCoeffs[mode];
1058 
1059     if (CANNOT_USE_COEFF == rec.fSC) {
1060         return false;
1061     }
1062 
1063     SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1064     if (src) {
1065         *src = rec.fSC;
1066     }
1067     if (dst) {
1068         *dst = rec.fDC;
1069     }
1070     return true;
1071 }
1072 
AsMode(const SkXfermode * xfer,Mode * mode)1073 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1074     if (NULL == xfer) {
1075         if (mode) {
1076             *mode = kSrcOver_Mode;
1077         }
1078         return true;
1079     }
1080     return xfer->asMode(mode);
1081 }
1082 
AsCoeff(const SkXfermode * xfer,Coeff * src,Coeff * dst)1083 bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
1084     if (NULL == xfer) {
1085         return ModeAsCoeff(kSrcOver_Mode, src, dst);
1086     }
1087     return xfer->asCoeff(src, dst);
1088 }
1089 
IsMode(const SkXfermode * xfer,Mode mode)1090 bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1091     // if xfer==null then the mode is srcover
1092     Mode m = kSrcOver_Mode;
1093     if (xfer && !xfer->asMode(&m)) {
1094         return false;
1095     }
1096     return mode == m;
1097 }
1098 
1099 ///////////////////////////////////////////////////////////////////////////////
1100 //////////// 16bit xfermode procs
1101 
1102 #ifdef SK_DEBUG
require_255(SkPMColor src)1103 static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
require_0(SkPMColor src)1104 static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1105 #endif
1106 
src_modeproc16_255(SkPMColor src,uint16_t dst)1107 static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1108     SkASSERT(require_255(src));
1109     return SkPixel32ToPixel16(src);
1110 }
1111 
dst_modeproc16(SkPMColor src,uint16_t dst)1112 static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1113     return dst;
1114 }
1115 
srcover_modeproc16_0(SkPMColor src,uint16_t dst)1116 static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1117     SkASSERT(require_0(src));
1118     return dst;
1119 }
1120 
srcover_modeproc16_255(SkPMColor src,uint16_t dst)1121 static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1122     SkASSERT(require_255(src));
1123     return SkPixel32ToPixel16(src);
1124 }
1125 
dstover_modeproc16_0(SkPMColor src,uint16_t dst)1126 static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1127     SkASSERT(require_0(src));
1128     return dst;
1129 }
1130 
dstover_modeproc16_255(SkPMColor src,uint16_t dst)1131 static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1132     SkASSERT(require_255(src));
1133     return dst;
1134 }
1135 
srcin_modeproc16_255(SkPMColor src,uint16_t dst)1136 static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1137     SkASSERT(require_255(src));
1138     return SkPixel32ToPixel16(src);
1139 }
1140 
dstin_modeproc16_255(SkPMColor src,uint16_t dst)1141 static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1142     SkASSERT(require_255(src));
1143     return dst;
1144 }
1145 
dstout_modeproc16_0(SkPMColor src,uint16_t dst)1146 static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1147     SkASSERT(require_0(src));
1148     return dst;
1149 }
1150 
srcatop_modeproc16(SkPMColor src,uint16_t dst)1151 static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1152     unsigned isa = 255 - SkGetPackedA32(src);
1153 
1154     return SkPackRGB16(
1155            SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1156            SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1157            SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1158 }
1159 
srcatop_modeproc16_0(SkPMColor src,uint16_t dst)1160 static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1161     SkASSERT(require_0(src));
1162     return dst;
1163 }
1164 
srcatop_modeproc16_255(SkPMColor src,uint16_t dst)1165 static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1166     SkASSERT(require_255(src));
1167     return SkPixel32ToPixel16(src);
1168 }
1169 
dstatop_modeproc16_255(SkPMColor src,uint16_t dst)1170 static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1171     SkASSERT(require_255(src));
1172     return dst;
1173 }
1174 
1175 /*********
1176     darken and lighten boil down to this.
1177 
1178     darken  = (1 - Sa) * Dc + min(Sc, Dc)
1179     lighten = (1 - Sa) * Dc + max(Sc, Dc)
1180 
1181     if (Sa == 0) these become
1182         darken  = Dc + min(0, Dc) = 0
1183         lighten = Dc + max(0, Dc) = Dc
1184 
1185     if (Sa == 1) these become
1186         darken  = min(Sc, Dc)
1187         lighten = max(Sc, Dc)
1188 */
1189 
darken_modeproc16_0(SkPMColor src,uint16_t dst)1190 static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1191     SkASSERT(require_0(src));
1192     return 0;
1193 }
1194 
darken_modeproc16_255(SkPMColor src,uint16_t dst)1195 static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1196     SkASSERT(require_255(src));
1197     unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1198     unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1199     unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1200     return SkPackRGB16(r, g, b);
1201 }
1202 
lighten_modeproc16_0(SkPMColor src,uint16_t dst)1203 static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1204     SkASSERT(require_0(src));
1205     return dst;
1206 }
1207 
lighten_modeproc16_255(SkPMColor src,uint16_t dst)1208 static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1209     SkASSERT(require_255(src));
1210     unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1211     unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1212     unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1213     return SkPackRGB16(r, g, b);
1214 }
1215 
1216 struct Proc16Rec {
1217     SkXfermodeProc16    fProc16_0;
1218     SkXfermodeProc16    fProc16_255;
1219     SkXfermodeProc16    fProc16_General;
1220 };
1221 
1222 static const Proc16Rec gModeProcs16[] = {
1223     { NULL,                 NULL,                   NULL            }, // CLEAR
1224     { NULL,                 src_modeproc16_255,     NULL            },
1225     { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
1226     { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
1227     { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
1228     { NULL,                 srcin_modeproc16_255,   NULL            },
1229     { NULL,                 dstin_modeproc16_255,   NULL            },
1230     { NULL,                 NULL,                   NULL            },// SRC_OUT
1231     { dstout_modeproc16_0,  NULL,                   NULL            },
1232     { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
1233     { NULL,                 dstatop_modeproc16_255, NULL            },
1234     { NULL,                 NULL,                   NULL            }, // XOR
1235 
1236     { NULL,                 NULL,                   NULL            }, // plus
1237     { NULL,                 NULL,                   NULL            }, // modulate
1238     { NULL,                 NULL,                   NULL            }, // screen
1239     { NULL,                 NULL,                   NULL            }, // overlay
1240     { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
1241     { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
1242     { NULL,                 NULL,                   NULL            }, // colordodge
1243     { NULL,                 NULL,                   NULL            }, // colorburn
1244     { NULL,                 NULL,                   NULL            }, // hardlight
1245     { NULL,                 NULL,                   NULL            }, // softlight
1246     { NULL,                 NULL,                   NULL            }, // difference
1247     { NULL,                 NULL,                   NULL            }, // exclusion
1248 };
1249 
GetProc16(Mode mode,SkColor srcColor)1250 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1251     SkXfermodeProc16  proc16 = NULL;
1252     if ((unsigned)mode < kModeCount) {
1253         const Proc16Rec& rec = gModeProcs16[mode];
1254         unsigned a = SkColorGetA(srcColor);
1255 
1256         if (0 == a) {
1257             proc16 = rec.fProc16_0;
1258         } else if (255 == a) {
1259             proc16 = rec.fProc16_255;
1260         } else {
1261             proc16 = rec.fProc16_General;
1262         }
1263     }
1264     return proc16;
1265 }
1266 
1267 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1268     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1269     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
1270     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
1271     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
1272     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
1273 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1274