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