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