Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkXfermode.h"
      9 #include "SkXfermode_proccoeff.h"
     10 #include "SkColorPriv.h"
     11 #include "SkMathPriv.h"
     12 #include "SkOncePtr.h"
     13 #include "SkOpts.h"
     14 #include "SkReadBuffer.h"
     15 #include "SkString.h"
     16 #include "SkWriteBuffer.h"
     17 #include "SkPM4f.h"
     18 
     19 #define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
     20 
     21 static inline unsigned saturated_add(unsigned a, unsigned b) {
     22     SkASSERT(a <= 255);
     23     SkASSERT(b <= 255);
     24     unsigned sum = a + b;
     25     if (sum > 255) {
     26         sum = 255;
     27     }
     28     return sum;
     29 }
     30 
     31 static inline int clamp_signed_byte(int n) {
     32     if (n < 0) {
     33         n = 0;
     34     } else if (n > 255) {
     35         n = 255;
     36     }
     37     return n;
     38 }
     39 
     40 static inline int clamp_div255round(int prod) {
     41     if (prod <= 0) {
     42         return 0;
     43     } else if (prod >= 255*255) {
     44         return 255;
     45     } else {
     46         return SkDiv255Round(prod);
     47     }
     48 }
     49 
     50 ///////////////////////////////////////////////////////////////////////////////
     51 #include "SkNx.h"
     52 
     53 static Sk4f     alpha(const Sk4f& color) { return Sk4f(color[3]); }
     54 static Sk4f inv_alpha(const Sk4f& color) { return Sk4f(1 - color[3]); }
     55 static Sk4f     pin_1(const Sk4f& value) { return Sk4f::Min(value, Sk4f(1)); }
     56 
     57 static Sk4f color_alpha(const Sk4f& color, float newAlpha) {
     58     return Sk4f(color[0], color[1], color[2], newAlpha);
     59 }
     60 static Sk4f color_alpha(const Sk4f& color, const Sk4f& newAlpha) {
     61     return color_alpha(color, newAlpha[3]);
     62 }
     63 
     64 static Sk4f set_argb(float a, float r, float g, float b) {
     65     if (0 == SkPM4f::R) {
     66         return Sk4f(r, g, b, a);
     67     } else {
     68         return Sk4f(b, g, r, a);
     69     }
     70 }
     71 
     72 static Sk4f    clear_4f(const Sk4f& s, const Sk4f& d) { return Sk4f(0); }
     73 static Sk4f      src_4f(const Sk4f& s, const Sk4f& d) { return s; }
     74 static Sk4f      dst_4f(const Sk4f& s, const Sk4f& d) { return d; }
     75 static Sk4f  srcover_4f(const Sk4f& s, const Sk4f& d) { return s + inv_alpha(s) * d; }
     76 static Sk4f  dstover_4f(const Sk4f& s, const Sk4f& d) { return d + inv_alpha(d) * s; }
     77 static Sk4f    srcin_4f(const Sk4f& s, const Sk4f& d) { return s * alpha(d); }
     78 static Sk4f    dstin_4f(const Sk4f& s, const Sk4f& d) { return d * alpha(s); }
     79 static Sk4f   srcout_4f(const Sk4f& s, const Sk4f& d) { return s * inv_alpha(d); }
     80 static Sk4f   dstout_4f(const Sk4f& s, const Sk4f& d) { return d * inv_alpha(s); }
     81 static Sk4f  srcatop_4f(const Sk4f& s, const Sk4f& d) { return s * alpha(d) + d * inv_alpha(s); }
     82 static Sk4f  dstatop_4f(const Sk4f& s, const Sk4f& d) { return d * alpha(s) + s * inv_alpha(d); }
     83 static Sk4f      xor_4f(const Sk4f& s, const Sk4f& d) { return s * inv_alpha(d) + d * inv_alpha(s);}
     84 static Sk4f     plus_4f(const Sk4f& s, const Sk4f& d) { return pin_1(s + d); }
     85 static Sk4f modulate_4f(const Sk4f& s, const Sk4f& d) { return s * d; }
     86 static Sk4f   screen_4f(const Sk4f& s, const Sk4f& d) { return s + d - s * d; }
     87 
     88 static Sk4f multiply_4f(const Sk4f& s, const Sk4f& d) {
     89     return s * inv_alpha(d) + d * inv_alpha(s) + s * d;
     90 }
     91 
     92 static Sk4f overlay_4f(const Sk4f& s, const Sk4f& d) {
     93     Sk4f sa = alpha(s);
     94     Sk4f da = alpha(d);
     95     Sk4f two = Sk4f(2);
     96     Sk4f rc = (two * d <= da).thenElse(two * s * d,
     97                                        sa * da - two * (da - d) * (sa - s));
     98     return pin_1(s + d - s * da + color_alpha(rc - d * sa, 0));
     99 }
    100 
    101 static Sk4f hardlight_4f(const Sk4f& s, const Sk4f& d) {
    102     return overlay_4f(d, s);
    103 }
    104 
    105 static Sk4f darken_4f(const Sk4f& s, const Sk4f& d) {
    106     Sk4f sa = alpha(s);
    107     Sk4f da = alpha(d);
    108     return s + d - Sk4f::Max(s * da, d * sa);
    109 }
    110 
    111 static Sk4f lighten_4f(const Sk4f& s, const Sk4f& d) {
    112     Sk4f sa = alpha(s);
    113     Sk4f da = alpha(d);
    114     return s + d - Sk4f::Min(s * da, d * sa);
    115 }
    116 
    117 static Sk4f colordodge_4f(const Sk4f& s, const Sk4f& d) {
    118     Sk4f sa = alpha(s);
    119     Sk4f da = alpha(d);
    120     Sk4f isa = Sk4f(1) - sa;
    121     Sk4f ida = Sk4f(1) - da;
    122 
    123     Sk4f srcover = s + d * isa;
    124     Sk4f dstover = d + s * ida;
    125     Sk4f otherwise = sa * Sk4f::Min(da, (d * sa) / (sa - s)) + s * ida + d * isa;
    126 
    127     // Order matters here, preferring d==0 over s==sa.
    128     auto colors = (d == Sk4f(0)).thenElse(dstover,
    129                                           (s == sa).thenElse(srcover,
    130                                                              otherwise));
    131     return color_alpha(colors, srcover);
    132 }
    133 
    134 static Sk4f colorburn_4f(const Sk4f& s, const Sk4f& d) {
    135     Sk4f sa  = alpha(s);
    136     Sk4f da  = alpha(d);
    137     Sk4f isa = Sk4f(1) - sa;
    138     Sk4f ida = Sk4f(1) - da;
    139 
    140     Sk4f srcover = s + d * isa;
    141     Sk4f dstover = d + s * ida;
    142     Sk4f otherwise = sa * (da - Sk4f::Min(da, (da - d) * sa / s)) + s * ida + d * isa;
    143 
    144     // Order matters here, preferring d==da over s==0.
    145     auto colors = (d == da).thenElse(dstover,
    146                                      (s == Sk4f(0)).thenElse(srcover,
    147                                                              otherwise));
    148     return color_alpha(colors, srcover);
    149 }
    150 
    151 static Sk4f softlight_4f(const Sk4f& s, const Sk4f& d) {
    152     Sk4f sa  = alpha(s);
    153     Sk4f da  = alpha(d);
    154     Sk4f isa = Sk4f(1) - sa;
    155     Sk4f ida = Sk4f(1) - da;
    156 
    157     // Some common terms.
    158     Sk4f m  = (da > Sk4f(0)).thenElse(d / da, Sk4f(0));
    159     Sk4f s2 = Sk4f(2) * s;
    160     Sk4f m4 = Sk4f(4) * m;
    161 
    162     // The logic forks three ways:
    163     //    1. dark src?
    164     //    2. light src, dark dst?
    165     //    3. light src, light dst?
    166     Sk4f darkSrc = d * (sa + (s2 - sa) * (Sk4f(1) - m));            // Used in case 1.
    167     Sk4f darkDst = (m4 * m4 + m4) * (m - Sk4f(1)) + Sk4f(7) * m;    // Used in case 2.
    168     Sk4f liteDst = m.sqrt() - m;                                    // Used in case 3.
    169     Sk4f liteSrc = d * sa + da * (s2 - sa) * (Sk4f(4) * d <= da).thenElse(darkDst,
    170                                                                           liteDst); // Case 2 or 3?
    171 
    172     return color_alpha(s * ida + d * isa + (s2 <= sa).thenElse(darkSrc, liteSrc), // Case 1 or 2/3?
    173                        s + d * isa);
    174 }
    175 
    176 static Sk4f difference_4f(const Sk4f& s, const Sk4f& d) {
    177     Sk4f min = Sk4f::Min(s * alpha(d), d * alpha(s));
    178     return s + d - min - color_alpha(min, 0);
    179 }
    180 
    181 static Sk4f exclusion_4f(const Sk4f& s, const Sk4f& d) {
    182     Sk4f product = s * d;
    183     return s + d - product - color_alpha(product, 0);
    184 }
    185 
    186 ////////////////////////////////////////////////////
    187 
    188 // The CSS compositing spec introduces the following formulas:
    189 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
    190 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
    191 // while PDF and CG uses the one from Rec. Rec. 601
    192 // See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
    193 static inline float Lum(float r, float g, float b) {
    194     return r * 0.2126f + g * 0.7152f + b * 0.0722f;
    195 }
    196 
    197 static inline float max(float a, float b, float c) {
    198     return SkTMax(a, SkTMax(b, c));
    199 }
    200 
    201 static inline float min(float a, float b, float c) {
    202     return SkTMin(a, SkTMin(b, c));
    203 }
    204 
    205 static inline float Sat(float r, float g, float b) {
    206     return max(r, g, b) - min(r, g, b);
    207 }
    208 
    209 static inline void setSaturationComponents(float* Cmin, float* Cmid, float* Cmax, float s) {
    210     if(*Cmax > *Cmin) {
    211         *Cmid = (*Cmid - *Cmin) * s / (*Cmax - *Cmin);
    212         *Cmax = s;
    213     } else {
    214         *Cmax = 0;
    215         *Cmid = 0;
    216     }
    217     *Cmin = 0;
    218 }
    219 
    220 static inline void SetSat(float* r, float* g, float* b, float s) {
    221     if(*r <= *g) {
    222         if(*g <= *b) {
    223             setSaturationComponents(r, g, b, s);
    224         } else if(*r <= *b) {
    225             setSaturationComponents(r, b, g, s);
    226         } else {
    227             setSaturationComponents(b, r, g, s);
    228         }
    229     } else if(*r <= *b) {
    230         setSaturationComponents(g, r, b, s);
    231     } else if(*g <= *b) {
    232         setSaturationComponents(g, b, r, s);
    233     } else {
    234         setSaturationComponents(b, g, r, s);
    235     }
    236 }
    237 
    238 static inline void clipColor(float* r, float* g, float* b, float a) {
    239     float L = Lum(*r, *g, *b);
    240     float n = min(*r, *g, *b);
    241     float x = max(*r, *g, *b);
    242     float denom;
    243     if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
    244         float scale = L / denom;
    245         *r = L + (*r - L) * scale;
    246         *g = L + (*g - L) * scale;
    247         *b = L + (*b - L) * scale;
    248     }
    249 
    250     if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
    251         float scale = (a - L) / denom;
    252         *r = L + (*r - L) * scale;
    253         *g = L + (*g - L) * scale;
    254         *b = L + (*b - L) * scale;
    255     }
    256 }
    257 
    258 static inline void SetLum(float* r, float* g, float* b, float a, float l) {
    259     float d = l - Lum(*r, *g, *b);
    260     *r += d;
    261     *g += d;
    262     *b += d;
    263     clipColor(r, g, b, a);
    264 }
    265 
    266 static Sk4f hue_4f(const Sk4f& s, const Sk4f& d) {
    267     float sa = s[SkPM4f::A];
    268     float sr = s[SkPM4f::R];
    269     float sg = s[SkPM4f::G];
    270     float sb = s[SkPM4f::B];
    271 
    272     float da = d[SkPM4f::A];
    273     float dr = d[SkPM4f::R];
    274     float dg = d[SkPM4f::G];
    275     float db = d[SkPM4f::B];
    276 
    277     float Sr = sr;
    278     float Sg = sg;
    279     float Sb = sb;
    280     SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
    281     SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
    282 
    283     return color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Sr, Sg, Sb),
    284                        sa + da - sa * da);
    285 }
    286 
    287 static Sk4f saturation_4f(const Sk4f& s, const Sk4f& d) {
    288     float sa = s[SkPM4f::A];
    289     float sr = s[SkPM4f::R];
    290     float sg = s[SkPM4f::G];
    291     float sb = s[SkPM4f::B];
    292 
    293     float da = d[SkPM4f::A];
    294     float dr = d[SkPM4f::R];
    295     float dg = d[SkPM4f::G];
    296     float db = d[SkPM4f::B];
    297 
    298     float Dr = dr;
    299     float Dg = dg;
    300     float Db = db;
    301     SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
    302     SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
    303 
    304     return color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Dr, Dg, Db),
    305                        sa + da - sa * da);
    306 }
    307 
    308 static Sk4f color_4f(const Sk4f& s, const Sk4f& d) {
    309     float sa = s[SkPM4f::A];
    310     float sr = s[SkPM4f::R];
    311     float sg = s[SkPM4f::G];
    312     float sb = s[SkPM4f::B];
    313 
    314     float da = d[SkPM4f::A];
    315     float dr = d[SkPM4f::R];
    316     float dg = d[SkPM4f::G];
    317     float db = d[SkPM4f::B];
    318 
    319     float Sr = sr;
    320     float Sg = sg;
    321     float Sb = sb;
    322     SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
    323 
    324     Sk4f res = color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Sr, Sg, Sb),
    325                            sa + da - sa * da);
    326     // Can return tiny negative values ...
    327     return Sk4f::Max(res, Sk4f(0));
    328 }
    329 
    330 static Sk4f luminosity_4f(const Sk4f& s, const Sk4f& d) {
    331     float sa = s[SkPM4f::A];
    332     float sr = s[SkPM4f::R];
    333     float sg = s[SkPM4f::G];
    334     float sb = s[SkPM4f::B];
    335 
    336     float da = d[SkPM4f::A];
    337     float dr = d[SkPM4f::R];
    338     float dg = d[SkPM4f::G];
    339     float db = d[SkPM4f::B];
    340 
    341     float Dr = dr;
    342     float Dg = dg;
    343     float Db = db;
    344     SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
    345 
    346     Sk4f res = color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Dr, Dg, Db),
    347                            sa + da - sa * da);
    348     // Can return tiny negative values ...
    349     return Sk4f::Max(res, Sk4f(0));
    350 }
    351 
    352 ///////////////////////////////////////////////////////////////////////////////
    353 
    354 //  kClear_Mode,    //!< [0, 0]
    355 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
    356     return 0;
    357 }
    358 
    359 //  kSrc_Mode,      //!< [Sa, Sc]
    360 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
    361     return src;
    362 }
    363 
    364 //  kDst_Mode,      //!< [Da, Dc]
    365 static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
    366     return dst;
    367 }
    368 
    369 //  kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
    370 static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
    371 #if 0
    372     // this is the old, more-correct way, but it doesn't guarantee that dst==255
    373     // will always stay opaque
    374     return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
    375 #else
    376     // this is slightly faster, but more importantly guarantees that dst==255
    377     // will always stay opaque
    378     return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
    379 #endif
    380 }
    381 
    382 //  kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
    383 static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
    384     // this is the reverse of srcover, just flipping src and dst
    385     // see srcover's comment about the 256 for opaqueness guarantees
    386     return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
    387 }
    388 
    389 //  kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
    390 static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
    391     return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
    392 }
    393 
    394 //  kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
    395 static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
    396     return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
    397 }
    398 
    399 //  kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
    400 static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
    401     return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
    402 }
    403 
    404 //  kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
    405 static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
    406     return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
    407 }
    408 
    409 //  kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
    410 static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
    411     unsigned sa = SkGetPackedA32(src);
    412     unsigned da = SkGetPackedA32(dst);
    413     unsigned isa = 255 - sa;
    414 
    415     return SkPackARGB32(da,
    416                         SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
    417                             SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
    418                         SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
    419                             SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
    420                         SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
    421                             SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
    422 }
    423 
    424 //  kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
    425 static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
    426     unsigned sa = SkGetPackedA32(src);
    427     unsigned da = SkGetPackedA32(dst);
    428     unsigned ida = 255 - da;
    429 
    430     return SkPackARGB32(sa,
    431                         SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
    432                             SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
    433                         SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
    434                             SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
    435                         SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
    436                             SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
    437 }
    438 
    439 //  kXor_Mode   [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
    440 static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
    441     unsigned sa = SkGetPackedA32(src);
    442     unsigned da = SkGetPackedA32(dst);
    443     unsigned isa = 255 - sa;
    444     unsigned ida = 255 - da;
    445 
    446     return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
    447                         SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
    448                             SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
    449                         SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
    450                             SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
    451                         SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
    452                             SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
    453 }
    454 
    455 ///////////////////////////////////////////////////////////////////////////////
    456 
    457 // kPlus_Mode
    458 static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
    459     unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
    460     unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
    461     unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
    462     unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
    463     return SkPackARGB32(a, r, g, b);
    464 }
    465 
    466 // kModulate_Mode
    467 static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
    468     int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
    469     int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
    470     int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
    471     int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
    472     return SkPackARGB32(a, r, g, b);
    473 }
    474 
    475 static inline int srcover_byte(int a, int b) {
    476     return a + b - SkAlphaMulAlpha(a, b);
    477 }
    478 
    479 // kMultiply_Mode
    480 // B(Cb, Cs) = Cb x Cs
    481 // multiply uses its own version of blendfunc_byte because sa and da are not needed
    482 static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
    483     return clamp_div255round(sc * (255 - da)  + dc * (255 - sa)  + sc * dc);
    484 }
    485 
    486 static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
    487     int sa = SkGetPackedA32(src);
    488     int da = SkGetPackedA32(dst);
    489     int a = srcover_byte(sa, da);
    490     int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    491     int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    492     int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    493     return SkPackARGB32(a, r, g, b);
    494 }
    495 
    496 // kScreen_Mode
    497 static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
    498     int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
    499     int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
    500     int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
    501     int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
    502     return SkPackARGB32(a, r, g, b);
    503 }
    504 
    505 // kOverlay_Mode
    506 static inline int overlay_byte(int sc, int dc, int sa, int da) {
    507     int tmp = sc * (255 - da) + dc * (255 - sa);
    508     int rc;
    509     if (2 * dc <= da) {
    510         rc = 2 * sc * dc;
    511     } else {
    512         rc = sa * da - 2 * (da - dc) * (sa - sc);
    513     }
    514     return clamp_div255round(rc + tmp);
    515 }
    516 static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
    517     int sa = SkGetPackedA32(src);
    518     int da = SkGetPackedA32(dst);
    519     int a = srcover_byte(sa, da);
    520     int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    521     int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    522     int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    523     return SkPackARGB32(a, r, g, b);
    524 }
    525 
    526 // kDarken_Mode
    527 static inline int darken_byte(int sc, int dc, int sa, int da) {
    528     int sd = sc * da;
    529     int ds = dc * sa;
    530     if (sd < ds) {
    531         // srcover
    532         return sc + dc - SkDiv255Round(ds);
    533     } else {
    534         // dstover
    535         return dc + sc - SkDiv255Round(sd);
    536     }
    537 }
    538 static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
    539     int sa = SkGetPackedA32(src);
    540     int da = SkGetPackedA32(dst);
    541     int a = srcover_byte(sa, da);
    542     int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    543     int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    544     int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    545     return SkPackARGB32(a, r, g, b);
    546 }
    547 
    548 // kLighten_Mode
    549 static inline int lighten_byte(int sc, int dc, int sa, int da) {
    550     int sd = sc * da;
    551     int ds = dc * sa;
    552     if (sd > ds) {
    553         // srcover
    554         return sc + dc - SkDiv255Round(ds);
    555     } else {
    556         // dstover
    557         return dc + sc - SkDiv255Round(sd);
    558     }
    559 }
    560 static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
    561     int sa = SkGetPackedA32(src);
    562     int da = SkGetPackedA32(dst);
    563     int a = srcover_byte(sa, da);
    564     int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    565     int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    566     int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    567     return SkPackARGB32(a, r, g, b);
    568 }
    569 
    570 // kColorDodge_Mode
    571 static inline int colordodge_byte(int sc, int dc, int sa, int da) {
    572     int diff = sa - sc;
    573     int rc;
    574     if (0 == dc) {
    575         return SkAlphaMulAlpha(sc, 255 - da);
    576     } else if (0 == diff) {
    577         rc = sa * da + sc * (255 - da) + dc * (255 - sa);
    578     } else {
    579         diff = dc * sa / diff;
    580         rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
    581     }
    582     return clamp_div255round(rc);
    583 }
    584 static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
    585     int sa = SkGetPackedA32(src);
    586     int da = SkGetPackedA32(dst);
    587     int a = srcover_byte(sa, da);
    588     int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    589     int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    590     int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    591     return SkPackARGB32(a, r, g, b);
    592 }
    593 
    594 // kColorBurn_Mode
    595 static inline int colorburn_byte(int sc, int dc, int sa, int da) {
    596     int rc;
    597     if (dc == da) {
    598         rc = sa * da + sc * (255 - da) + dc * (255 - sa);
    599     } else if (0 == sc) {
    600         return SkAlphaMulAlpha(dc, 255 - sa);
    601     } else {
    602         int tmp = (da - dc) * sa / sc;
    603         rc = sa * (da - ((da < tmp) ? da : tmp))
    604             + sc * (255 - da) + dc * (255 - sa);
    605     }
    606     return clamp_div255round(rc);
    607 }
    608 static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
    609     int sa = SkGetPackedA32(src);
    610     int da = SkGetPackedA32(dst);
    611     int a = srcover_byte(sa, da);
    612     int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    613     int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    614     int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    615     return SkPackARGB32(a, r, g, b);
    616 }
    617 
    618 // kHardLight_Mode
    619 static inline int hardlight_byte(int sc, int dc, int sa, int da) {
    620     int rc;
    621     if (2 * sc <= sa) {
    622         rc = 2 * sc * dc;
    623     } else {
    624         rc = sa * da - 2 * (da - dc) * (sa - sc);
    625     }
    626     return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
    627 }
    628 static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
    629     int sa = SkGetPackedA32(src);
    630     int da = SkGetPackedA32(dst);
    631     int a = srcover_byte(sa, da);
    632     int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    633     int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    634     int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    635     return SkPackARGB32(a, r, g, b);
    636 }
    637 
    638 // returns 255 * sqrt(n/255)
    639 static U8CPU sqrt_unit_byte(U8CPU n) {
    640     return SkSqrtBits(n, 15+4);
    641 }
    642 
    643 // kSoftLight_Mode
    644 static inline int softlight_byte(int sc, int dc, int sa, int da) {
    645     int m = da ? dc * 256 / da : 0;
    646     int rc;
    647     if (2 * sc <= sa) {
    648         rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
    649     } else if (4 * dc <= da) {
    650         int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
    651         rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
    652     } else {
    653         int tmp = sqrt_unit_byte(m) - m;
    654         rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
    655     }
    656     return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
    657 }
    658 static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
    659     int sa = SkGetPackedA32(src);
    660     int da = SkGetPackedA32(dst);
    661     int a = srcover_byte(sa, da);
    662     int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    663     int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    664     int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    665     return SkPackARGB32(a, r, g, b);
    666 }
    667 
    668 // kDifference_Mode
    669 static inline int difference_byte(int sc, int dc, int sa, int da) {
    670     int tmp = SkMin32(sc * da, dc * sa);
    671     return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
    672 }
    673 static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
    674     int sa = SkGetPackedA32(src);
    675     int da = SkGetPackedA32(dst);
    676     int a = srcover_byte(sa, da);
    677     int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    678     int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    679     int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    680     return SkPackARGB32(a, r, g, b);
    681 }
    682 
    683 // kExclusion_Mode
    684 static inline int exclusion_byte(int sc, int dc, int, int) {
    685     // this equations is wacky, wait for SVG to confirm it
    686     //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
    687 
    688     // The above equation can be simplified as follows
    689     int r = 255*(sc + dc) - 2 * sc * dc;
    690     return clamp_div255round(r);
    691 }
    692 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
    693     int sa = SkGetPackedA32(src);
    694     int da = SkGetPackedA32(dst);
    695     int a = srcover_byte(sa, da);
    696     int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    697     int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    698     int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    699     return SkPackARGB32(a, r, g, b);
    700 }
    701 
    702 // The CSS compositing spec introduces the following formulas:
    703 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
    704 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
    705 // while PDF and CG uses the one from Rec. Rec. 601
    706 // See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
    707 static inline int Lum(int r, int g, int b)
    708 {
    709     return SkDiv255Round(r * 77 + g * 150 + b * 28);
    710 }
    711 
    712 static inline int min2(int a, int b) { return a < b ? a : b; }
    713 static inline int max2(int a, int b) { return a > b ? a : b; }
    714 #define minimum(a, b, c) min2(min2(a, b), c)
    715 #define maximum(a, b, c) max2(max2(a, b), c)
    716 
    717 static inline int Sat(int r, int g, int b) {
    718     return maximum(r, g, b) - minimum(r, g, b);
    719 }
    720 
    721 static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
    722     if(*Cmax > *Cmin) {
    723         *Cmid =  SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
    724         *Cmax = s;
    725     } else {
    726         *Cmax = 0;
    727         *Cmid = 0;
    728     }
    729 
    730     *Cmin = 0;
    731 }
    732 
    733 static inline void SetSat(int* r, int* g, int* b, int s) {
    734     if(*r <= *g) {
    735         if(*g <= *b) {
    736             setSaturationComponents(r, g, b, s);
    737         } else if(*r <= *b) {
    738             setSaturationComponents(r, b, g, s);
    739         } else {
    740             setSaturationComponents(b, r, g, s);
    741         }
    742     } else if(*r <= *b) {
    743         setSaturationComponents(g, r, b, s);
    744     } else if(*g <= *b) {
    745         setSaturationComponents(g, b, r, s);
    746     } else {
    747         setSaturationComponents(b, g, r, s);
    748     }
    749 }
    750 
    751 static inline void clipColor(int* r, int* g, int* b, int a) {
    752     int L = Lum(*r, *g, *b);
    753     int n = minimum(*r, *g, *b);
    754     int x = maximum(*r, *g, *b);
    755     int denom;
    756     if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
    757        *r = L + SkMulDiv(*r - L, L, denom);
    758        *g = L + SkMulDiv(*g - L, L, denom);
    759        *b = L + SkMulDiv(*b - L, L, denom);
    760     }
    761 
    762     if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
    763        int numer = a - L;
    764        *r = L + SkMulDiv(*r - L, numer, denom);
    765        *g = L + SkMulDiv(*g - L, numer, denom);
    766        *b = L + SkMulDiv(*b - L, numer, denom);
    767     }
    768 }
    769 
    770 static inline void SetLum(int* r, int* g, int* b, int a, int l) {
    771   int d = l - Lum(*r, *g, *b);
    772   *r +=  d;
    773   *g +=  d;
    774   *b +=  d;
    775 
    776   clipColor(r, g, b, a);
    777 }
    778 
    779 // non-separable blend modes are done in non-premultiplied alpha
    780 #define  blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
    781   clamp_div255round(sc * (255 - da) +  dc * (255 - sa) + blendval)
    782 
    783 // kHue_Mode
    784 // B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
    785 // Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
    786 static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
    787     int sr = SkGetPackedR32(src);
    788     int sg = SkGetPackedG32(src);
    789     int sb = SkGetPackedB32(src);
    790     int sa = SkGetPackedA32(src);
    791 
    792     int dr = SkGetPackedR32(dst);
    793     int dg = SkGetPackedG32(dst);
    794     int db = SkGetPackedB32(dst);
    795     int da = SkGetPackedA32(dst);
    796     int Sr, Sg, Sb;
    797 
    798     if(sa && da) {
    799         Sr = sr * sa;
    800         Sg = sg * sa;
    801         Sb = sb * sa;
    802         SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
    803         SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
    804     } else {
    805         Sr = 0;
    806         Sg = 0;
    807         Sb = 0;
    808     }
    809 
    810     int a = srcover_byte(sa, da);
    811     int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
    812     int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
    813     int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
    814     return SkPackARGB32(a, r, g, b);
    815 }
    816 
    817 // kSaturation_Mode
    818 // B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
    819 // Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
    820 static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
    821     int sr = SkGetPackedR32(src);
    822     int sg = SkGetPackedG32(src);
    823     int sb = SkGetPackedB32(src);
    824     int sa = SkGetPackedA32(src);
    825 
    826     int dr = SkGetPackedR32(dst);
    827     int dg = SkGetPackedG32(dst);
    828     int db = SkGetPackedB32(dst);
    829     int da = SkGetPackedA32(dst);
    830     int Dr, Dg, Db;
    831 
    832     if(sa && da) {
    833         Dr = dr * sa;
    834         Dg = dg * sa;
    835         Db = db * sa;
    836         SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
    837         SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
    838     } else {
    839         Dr = 0;
    840         Dg = 0;
    841         Db = 0;
    842     }
    843 
    844     int a = srcover_byte(sa, da);
    845     int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
    846     int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
    847     int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
    848     return SkPackARGB32(a, r, g, b);
    849 }
    850 
    851 // kColor_Mode
    852 // B(Cb, Cs) = SetLum(Cs, Lum(Cb))
    853 // Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
    854 static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
    855     int sr = SkGetPackedR32(src);
    856     int sg = SkGetPackedG32(src);
    857     int sb = SkGetPackedB32(src);
    858     int sa = SkGetPackedA32(src);
    859 
    860     int dr = SkGetPackedR32(dst);
    861     int dg = SkGetPackedG32(dst);
    862     int db = SkGetPackedB32(dst);
    863     int da = SkGetPackedA32(dst);
    864     int Sr, Sg, Sb;
    865 
    866     if(sa && da) {
    867         Sr = sr * da;
    868         Sg = sg * da;
    869         Sb = sb * da;
    870         SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
    871     } else {
    872         Sr = 0;
    873         Sg = 0;
    874         Sb = 0;
    875     }
    876 
    877     int a = srcover_byte(sa, da);
    878     int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
    879     int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
    880     int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
    881     return SkPackARGB32(a, r, g, b);
    882 }
    883 
    884 // kLuminosity_Mode
    885 // B(Cb, Cs) = SetLum(Cb, Lum(Cs))
    886 // Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
    887 static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
    888     int sr = SkGetPackedR32(src);
    889     int sg = SkGetPackedG32(src);
    890     int sb = SkGetPackedB32(src);
    891     int sa = SkGetPackedA32(src);
    892 
    893     int dr = SkGetPackedR32(dst);
    894     int dg = SkGetPackedG32(dst);
    895     int db = SkGetPackedB32(dst);
    896     int da = SkGetPackedA32(dst);
    897     int Dr, Dg, Db;
    898 
    899     if(sa && da) {
    900         Dr = dr * sa;
    901         Dg = dg * sa;
    902         Db = db * sa;
    903         SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
    904     } else {
    905         Dr = 0;
    906         Dg = 0;
    907         Db = 0;
    908     }
    909 
    910     int a = srcover_byte(sa, da);
    911     int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
    912     int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
    913     int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
    914     return SkPackARGB32(a, r, g, b);
    915 }
    916 
    917 ///////////////////////////////////////////////////////////////////////////////////////////////////
    918 
    919 static SkPM4f as_pm4f(const Sk4f& x) {
    920     SkPM4f pm4;
    921     x.store(pm4.fVec);
    922     return pm4;
    923 }
    924 
    925 static Sk4f as_4f(const SkPM4f& pm4) {
    926     return Sk4f::Load(pm4.fVec);
    927 }
    928 
    929 static void assert_unit(const SkPM4f& r) {
    930 #ifdef SK_DEBUG
    931     const float eps = 0.00001f;
    932     const float min = 0 - eps;
    933     const float max = 1 + eps;
    934     for (int i = 0; i < 4; ++i) {
    935         SkASSERT(r.fVec[i] >= min && r.fVec[i] <= max);
    936     }
    937 #endif
    938 }
    939 
    940 template <Sk4f (blend)(const Sk4f&, const Sk4f&)> SkPM4f proc_4f(const SkPM4f& s, const SkPM4f& d) {
    941     assert_unit(s);
    942     assert_unit(d);
    943     SkPM4f r = as_pm4f(blend(as_4f(s), as_4f(d)));
    944     assert_unit(r);
    945     return r;
    946 }
    947 
    948 const ProcCoeff gProcCoeffs[] = {
    949     { clear_modeproc,       proc_4f<clear_4f>,      SkXfermode::kZero_Coeff,    SkXfermode::kZero_Coeff },
    950     { src_modeproc,         proc_4f<src_4f>,        SkXfermode::kOne_Coeff,     SkXfermode::kZero_Coeff },
    951     { dst_modeproc,         proc_4f<dst_4f>,        SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff  },
    952     { srcover_modeproc,     proc_4f<srcover_4f>,    SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff  },
    953     { dstover_modeproc,     proc_4f<dstover_4f>,    SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff  },
    954     { srcin_modeproc,       proc_4f<srcin_4f>,      SkXfermode::kDA_Coeff,      SkXfermode::kZero_Coeff },
    955     { dstin_modeproc,       proc_4f<dstin_4f>,      SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff   },
    956     { srcout_modeproc,      proc_4f<srcout_4f>,     SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
    957     { dstout_modeproc,      proc_4f<dstout_4f>,     SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff  },
    958     { srcatop_modeproc,     proc_4f<srcatop_4f>,    SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff  },
    959     { dstatop_modeproc,     proc_4f<dstatop_4f>,    SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff   },
    960     { xor_modeproc,         proc_4f<xor_4f>,        SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff  },
    961 
    962     { plus_modeproc,        proc_4f<plus_4f>,       SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff  },
    963     { modulate_modeproc,    proc_4f<modulate_4f>,   SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff   },
    964     { screen_modeproc,      proc_4f<screen_4f>,     SkXfermode::kOne_Coeff,     SkXfermode::kISC_Coeff  },
    965     { overlay_modeproc,     proc_4f<overlay_4f>,    CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    966     { darken_modeproc,      proc_4f<darken_4f>,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    967     { lighten_modeproc,     proc_4f<lighten_4f>,    CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    968     { colordodge_modeproc,  proc_4f<colordodge_4f>, CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    969     { colorburn_modeproc,   proc_4f<colorburn_4f>,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    970     { hardlight_modeproc,   proc_4f<hardlight_4f>,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    971     { softlight_modeproc,   proc_4f<softlight_4f>,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    972     { difference_modeproc,  proc_4f<difference_4f>, CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    973     { exclusion_modeproc,   proc_4f<exclusion_4f>,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    974     { multiply_modeproc,    proc_4f<multiply_4f>,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    975     { hue_modeproc,         proc_4f<hue_4f>,        CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    976     { saturation_modeproc,  proc_4f<saturation_4f>, CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    977     { color_modeproc,       proc_4f<color_4f>,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    978     { luminosity_modeproc,  proc_4f<luminosity_4f>, CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    979 };
    980 
    981 ///////////////////////////////////////////////////////////////////////////////
    982 
    983 bool SkXfermode::asMode(Mode* mode) const {
    984     return false;
    985 }
    986 
    987 #if SK_SUPPORT_GPU
    988 const GrFragmentProcessor* SkXfermode::getFragmentProcessorForImageFilter(
    989                                                                 const GrFragmentProcessor*) const {
    990     // This should never be called.
    991     // TODO: make pure virtual in SkXfermode once Android update lands
    992     SkASSERT(0);
    993     return nullptr;
    994 }
    995 
    996 GrXPFactory* SkXfermode::asXPFactory() const {
    997     // This should never be called.
    998     // TODO: make pure virtual in SkXfermode once Android update lands
    999     SkASSERT(0);
   1000     return nullptr;
   1001 }
   1002 #endif
   1003 
   1004 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
   1005     // no-op. subclasses should override this
   1006     return dst;
   1007 }
   1008 
   1009 void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
   1010                         const SkPMColor* SK_RESTRICT src, int count,
   1011                         const SkAlpha* SK_RESTRICT aa) const {
   1012     SkASSERT(dst && src && count >= 0);
   1013 
   1014     if (nullptr == aa) {
   1015         for (int i = count - 1; i >= 0; --i) {
   1016             dst[i] = this->xferColor(src[i], dst[i]);
   1017         }
   1018     } else {
   1019         for (int i = count - 1; i >= 0; --i) {
   1020             unsigned a = aa[i];
   1021             if (0 != a) {
   1022                 SkPMColor dstC = dst[i];
   1023                 SkPMColor C = this->xferColor(src[i], dstC);
   1024                 if (0xFF != a) {
   1025                     C = SkFourByteInterp(C, dstC, a);
   1026                 }
   1027                 dst[i] = C;
   1028             }
   1029         }
   1030     }
   1031 }
   1032 
   1033 void SkXfermode::xfer16(uint16_t* dst,
   1034                         const SkPMColor* SK_RESTRICT src, int count,
   1035                         const SkAlpha* SK_RESTRICT aa) const {
   1036     SkASSERT(dst && src && count >= 0);
   1037 
   1038     if (nullptr == aa) {
   1039         for (int i = count - 1; i >= 0; --i) {
   1040             SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
   1041             dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
   1042         }
   1043     } else {
   1044         for (int i = count - 1; i >= 0; --i) {
   1045             unsigned a = aa[i];
   1046             if (0 != a) {
   1047                 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
   1048                 SkPMColor C = this->xferColor(src[i], dstC);
   1049                 if (0xFF != a) {
   1050                     C = SkFourByteInterp(C, dstC, a);
   1051                 }
   1052                 dst[i] = SkPixel32ToPixel16_ToU16(C);
   1053             }
   1054         }
   1055     }
   1056 }
   1057 
   1058 void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
   1059                         const SkPMColor src[], int count,
   1060                         const SkAlpha* SK_RESTRICT aa) const {
   1061     SkASSERT(dst && src && count >= 0);
   1062 
   1063     if (nullptr == aa) {
   1064         for (int i = count - 1; i >= 0; --i) {
   1065             SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
   1066             dst[i] = SkToU8(SkGetPackedA32(res));
   1067         }
   1068     } else {
   1069         for (int i = count - 1; i >= 0; --i) {
   1070             unsigned a = aa[i];
   1071             if (0 != a) {
   1072                 SkAlpha dstA = dst[i];
   1073                 unsigned A = SkGetPackedA32(this->xferColor(src[i],
   1074                                             (SkPMColor)(dstA << SK_A32_SHIFT)));
   1075                 if (0xFF != a) {
   1076                     A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
   1077                 }
   1078                 dst[i] = SkToU8(A);
   1079             }
   1080         }
   1081     }
   1082 }
   1083 
   1084 bool SkXfermode::supportsCoverageAsAlpha() const {
   1085     return false;
   1086 }
   1087 
   1088 bool SkXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
   1089     return false;
   1090 }
   1091 
   1092 ///////////////////////////////////////////////////////////////////////////////
   1093 ///////////////////////////////////////////////////////////////////////////////
   1094 
   1095 SkFlattenable* SkProcCoeffXfermode::CreateProc(SkReadBuffer& buffer) {
   1096     uint32_t mode32 = buffer.read32();
   1097     if (!buffer.validate(mode32 < SK_ARRAY_COUNT(gProcCoeffs))) {
   1098         return nullptr;
   1099     }
   1100     return SkXfermode::Create((SkXfermode::Mode)mode32);
   1101 }
   1102 
   1103 void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
   1104     buffer.write32(fMode);
   1105 }
   1106 
   1107 bool SkProcCoeffXfermode::asMode(Mode* mode) const {
   1108     if (mode) {
   1109         *mode = fMode;
   1110     }
   1111     return true;
   1112 }
   1113 
   1114 bool SkProcCoeffXfermode::supportsCoverageAsAlpha() const {
   1115     if (CANNOT_USE_COEFF == fSrcCoeff) {
   1116         return false;
   1117     }
   1118 
   1119     switch (fDstCoeff) {
   1120         case SkXfermode::kOne_Coeff:
   1121         case SkXfermode::kISA_Coeff:
   1122         case SkXfermode::kISC_Coeff:
   1123             return true;
   1124         default:
   1125             return false;
   1126     }
   1127 }
   1128 
   1129 bool SkProcCoeffXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
   1130     if (CANNOT_USE_COEFF == fSrcCoeff) {
   1131         return false;
   1132     }
   1133 
   1134     if (SkXfermode::kDA_Coeff == fSrcCoeff || SkXfermode::kDC_Coeff == fSrcCoeff ||
   1135         SkXfermode::kIDA_Coeff == fSrcCoeff || SkXfermode::kIDC_Coeff == fSrcCoeff) {
   1136         return false;
   1137     }
   1138 
   1139     switch (fDstCoeff) {
   1140         case SkXfermode::kZero_Coeff:
   1141             return true;
   1142         case SkXfermode::kISA_Coeff:
   1143             return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
   1144         case SkXfermode::kSA_Coeff:
   1145             return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType ||
   1146                    SkXfermode::kTransparentAlpha_SrcColorOpacity == opacityType;
   1147         case SkXfermode::kSC_Coeff:
   1148             return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType;
   1149         default:
   1150             return false;
   1151     }
   1152 
   1153 }
   1154 
   1155 void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
   1156                                  const SkPMColor* SK_RESTRICT src, int count,
   1157                                  const SkAlpha* SK_RESTRICT aa) const {
   1158     SkASSERT(dst && src && count >= 0);
   1159 
   1160     SkXfermodeProc proc = fProc;
   1161 
   1162     if (proc) {
   1163         if (nullptr == aa) {
   1164             for (int i = count - 1; i >= 0; --i) {
   1165                 dst[i] = proc(src[i], dst[i]);
   1166             }
   1167         } else {
   1168             for (int i = count - 1; i >= 0; --i) {
   1169                 unsigned a = aa[i];
   1170                 if (0 != a) {
   1171                     SkPMColor dstC = dst[i];
   1172                     SkPMColor C = proc(src[i], dstC);
   1173                     if (a != 0xFF) {
   1174                         C = SkFourByteInterp(C, dstC, a);
   1175                     }
   1176                     dst[i] = C;
   1177                 }
   1178             }
   1179         }
   1180     }
   1181 }
   1182 
   1183 void SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
   1184                                  const SkPMColor* SK_RESTRICT src, int count,
   1185                                  const SkAlpha* SK_RESTRICT aa) const {
   1186     SkASSERT(dst && src && count >= 0);
   1187 
   1188     SkXfermodeProc proc = fProc;
   1189 
   1190     if (proc) {
   1191         if (nullptr == aa) {
   1192             for (int i = count - 1; i >= 0; --i) {
   1193                 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
   1194                 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
   1195             }
   1196         } else {
   1197             for (int i = count - 1; i >= 0; --i) {
   1198                 unsigned a = aa[i];
   1199                 if (0 != a) {
   1200                     SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
   1201                     SkPMColor C = proc(src[i], dstC);
   1202                     if (0xFF != a) {
   1203                         C = SkFourByteInterp(C, dstC, a);
   1204                     }
   1205                     dst[i] = SkPixel32ToPixel16_ToU16(C);
   1206                 }
   1207             }
   1208         }
   1209     }
   1210 }
   1211 
   1212 void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
   1213                                  const SkPMColor* SK_RESTRICT src, int count,
   1214                                  const SkAlpha* SK_RESTRICT aa) const {
   1215     SkASSERT(dst && src && count >= 0);
   1216 
   1217     SkXfermodeProc proc = fProc;
   1218 
   1219     if (proc) {
   1220         if (nullptr == aa) {
   1221             for (int i = count - 1; i >= 0; --i) {
   1222                 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
   1223                 dst[i] = SkToU8(SkGetPackedA32(res));
   1224             }
   1225         } else {
   1226             for (int i = count - 1; i >= 0; --i) {
   1227                 unsigned a = aa[i];
   1228                 if (0 != a) {
   1229                     SkAlpha dstA = dst[i];
   1230                     SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
   1231                     unsigned A = SkGetPackedA32(res);
   1232                     if (0xFF != a) {
   1233                         A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
   1234                     }
   1235                     dst[i] = SkToU8(A);
   1236                 }
   1237             }
   1238         }
   1239     }
   1240 }
   1241 
   1242 #if SK_SUPPORT_GPU
   1243 #include "effects/GrCustomXfermode.h"
   1244 #include "effects/GrPorterDuffXferProcessor.h"
   1245 #include "effects/GrXfermodeFragmentProcessor.h"
   1246 
   1247 const GrFragmentProcessor* SkProcCoeffXfermode::getFragmentProcessorForImageFilter(
   1248                                                             const GrFragmentProcessor* dst) const {
   1249     SkASSERT(dst);
   1250     return GrXfermodeFragmentProcessor::CreateFromDstProcessor(dst, fMode);
   1251 }
   1252 
   1253 GrXPFactory* SkProcCoeffXfermode::asXPFactory() const {
   1254     if (CANNOT_USE_COEFF != fSrcCoeff) {
   1255         GrXPFactory* result = GrPorterDuffXPFactory::Create(fMode);
   1256         SkASSERT(result);
   1257         return result;
   1258     }
   1259 
   1260     SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
   1261     return GrCustomXfermode::CreateXPFactory(fMode);
   1262 }
   1263 #endif
   1264 
   1265 const char* SkXfermode::ModeName(Mode mode) {
   1266     SkASSERT((unsigned) mode <= (unsigned)kLastMode);
   1267     const char* gModeStrings[] = {
   1268         "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
   1269         "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
   1270         "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
   1271         "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
   1272         "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
   1273     };
   1274     return gModeStrings[mode];
   1275     static_assert(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, "mode_count");
   1276 }
   1277 
   1278 #ifndef SK_IGNORE_TO_STRING
   1279 void SkProcCoeffXfermode::toString(SkString* str) const {
   1280     str->append("SkProcCoeffXfermode: ");
   1281 
   1282     str->append("mode: ");
   1283     str->append(ModeName(fMode));
   1284 
   1285     static const char* gCoeffStrings[kCoeffCount] = {
   1286         "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
   1287     };
   1288 
   1289     str->append(" src: ");
   1290     if (CANNOT_USE_COEFF == fSrcCoeff) {
   1291         str->append("can't use");
   1292     } else {
   1293         str->append(gCoeffStrings[fSrcCoeff]);
   1294     }
   1295 
   1296     str->append(" dst: ");
   1297     if (CANNOT_USE_COEFF == fDstCoeff) {
   1298         str->append("can't use");
   1299     } else {
   1300         str->append(gCoeffStrings[fDstCoeff]);
   1301     }
   1302 }
   1303 #endif
   1304 
   1305 
   1306 SK_DECLARE_STATIC_ONCE_PTR(SkXfermode, cached[SkXfermode::kLastMode + 1]);
   1307 
   1308 SkXfermode* SkXfermode::Create(Mode mode) {
   1309     SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
   1310 
   1311     if ((unsigned)mode >= kModeCount) {
   1312         // report error
   1313         return nullptr;
   1314     }
   1315 
   1316     // Skia's "default" mode is srcover. nullptr in SkPaint is interpreted as srcover
   1317     // so we can just return nullptr from the factory.
   1318     if (kSrcOver_Mode == mode) {
   1319         return nullptr;
   1320     }
   1321 
   1322     return SkSafeRef(cached[mode].get([=]{
   1323         ProcCoeff rec = gProcCoeffs[mode];
   1324         if (auto xfermode = SkOpts::create_xfermode(rec, mode)) {
   1325             return xfermode;
   1326         }
   1327         return (SkXfermode*) new SkProcCoeffXfermode(rec, mode);
   1328     }));
   1329 }
   1330 
   1331 SkXfermodeProc SkXfermode::GetProc(Mode mode) {
   1332     SkXfermodeProc  proc = nullptr;
   1333     if ((unsigned)mode < kModeCount) {
   1334         proc = gProcCoeffs[mode].fProc;
   1335     }
   1336     return proc;
   1337 }
   1338 
   1339 SkXfermodeProc4f SkXfermode::GetProc4f(Mode mode) {
   1340     SkXfermodeProc4f  proc = nullptr;
   1341     if ((unsigned)mode < kModeCount) {
   1342         proc = gProcCoeffs[mode].fProc4f;
   1343     }
   1344     return proc;
   1345 }
   1346 
   1347 static SkPM4f missing_proc4f(const SkPM4f& src, const SkPM4f& dst) {
   1348     return src;
   1349 }
   1350 
   1351 SkXfermodeProc4f SkXfermode::getProc4f() const {
   1352     Mode mode;
   1353     return this->asMode(&mode) ? GetProc4f(mode) : missing_proc4f;
   1354 }
   1355 
   1356 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
   1357     SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
   1358 
   1359     if ((unsigned)mode >= (unsigned)kModeCount) {
   1360         // illegal mode parameter
   1361         return false;
   1362     }
   1363 
   1364     const ProcCoeff& rec = gProcCoeffs[mode];
   1365 
   1366     if (CANNOT_USE_COEFF == rec.fSC) {
   1367         return false;
   1368     }
   1369 
   1370     SkASSERT(CANNOT_USE_COEFF != rec.fDC);
   1371     if (src) {
   1372         *src = rec.fSC;
   1373     }
   1374     if (dst) {
   1375         *dst = rec.fDC;
   1376     }
   1377     return true;
   1378 }
   1379 
   1380 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
   1381     if (nullptr == xfer) {
   1382         if (mode) {
   1383             *mode = kSrcOver_Mode;
   1384         }
   1385         return true;
   1386     }
   1387     return xfer->asMode(mode);
   1388 }
   1389 
   1390 bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
   1391     // if xfer==null then the mode is srcover
   1392     Mode m = kSrcOver_Mode;
   1393     if (xfer && !xfer->asMode(&m)) {
   1394         return false;
   1395     }
   1396     return mode == m;
   1397 }
   1398 
   1399 bool SkXfermode::SupportsCoverageAsAlpha(const SkXfermode* xfer) {
   1400     // if xfer is nullptr we treat it as srcOver which always supports coverageAsAlpha
   1401     if (!xfer) {
   1402         return true;
   1403     }
   1404 
   1405     return xfer->supportsCoverageAsAlpha();
   1406 }
   1407 
   1408 bool SkXfermode::IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType) {
   1409     // if xfer is nullptr we treat it as srcOver which is opaque if our src is opaque
   1410     if (!xfer) {
   1411         return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
   1412     }
   1413 
   1414     return xfer->isOpaque(opacityType);
   1415 }
   1416 
   1417 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
   1418     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
   1419 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
   1420