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