LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkXfermode.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 12 872 1.4 %
Date: 2017-07-14 16:53:18 Functions: 3 164 1.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13