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