gfx/skia/patches/archive/0010-Bug-836892-Add-new-blending-modes-to-SkXfermode.patch

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 # HG changeset patch
     2 # User Rik Cabanier <cabanier@adobe.com>
     3 # Date 1360273929 -46800
     4 # Node ID 3ac8edca3a03b3d22240b5a5b95ae3b5ada9877d
     5 # Parent  cbb67fe70b864b36165061e1fd3b083cd09af087
     6 Bug 836892 - Add new blending modes to SkXfermode. r=gw280
     8 diff --git a/gfx/skia/include/core/SkXfermode.h b/gfx/skia/include/core/SkXfermode.h
     9 --- a/gfx/skia/include/core/SkXfermode.h
    10 +++ b/gfx/skia/include/core/SkXfermode.h
    11 @@ -96,33 +96,37 @@ public:
    12          kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
    13          kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
    14          kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
    15          kXor_Mode,      //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
    17          // all remaining modes are defined in the SVG Compositing standard
    18          // http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/
    19          kPlus_Mode,
    20 -        kMultiply_Mode,
    22          // all above modes can be expressed as pair of src/dst Coeffs
    23          kCoeffModesCnt,
    25 -        kScreen_Mode = kCoeffModesCnt,
    26 +        kMultiply_Mode = kCoeffModesCnt,
    27 +        kScreen_Mode,
    28          kOverlay_Mode,
    29          kDarken_Mode,
    30          kLighten_Mode,
    31          kColorDodge_Mode,
    32          kColorBurn_Mode,
    33          kHardLight_Mode,
    34          kSoftLight_Mode,
    35          kDifference_Mode,
    36          kExclusion_Mode,
    37 +        kHue_Mode,
    38 +        kSaturation_Mode,
    39 +        kColor_Mode,
    40 +        kLuminosity_Mode,
    42 -        kLastMode = kExclusion_Mode
    43 +        kLastMode = kLuminosity_Mode
    44      };
    46      /**
    47       *  If the xfermode is one of the modes in the Mode enum, then asMode()
    48       *  returns true and sets (if not null) mode accordingly. Otherwise it
    49       *  returns false and ignores the mode parameter.
    50       */
    51      virtual bool asMode(Mode* mode);
    52 diff --git a/gfx/skia/src/core/SkXfermode.cpp b/gfx/skia/src/core/SkXfermode.cpp
    53 --- a/gfx/skia/src/core/SkXfermode.cpp
    54 +++ b/gfx/skia/src/core/SkXfermode.cpp
    55 @@ -7,16 +7,18 @@
    56   */
    59  #include "SkXfermode.h"
    60  #include "SkColorPriv.h"
    61  #include "SkFlattenableBuffers.h"
    62  #include "SkMathPriv.h"
    64 +#include <algorithm>
    65 +
    66  SK_DEFINE_INST_COUNT(SkXfermode)
    68  #define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
    70  #if 0
    71  // idea for higher precision blends in xfer procs (and slightly faster)
    72  // see DstATop as a probable caller
    73  static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
    74 @@ -176,244 +178,439 @@ static SkPMColor xor_modeproc(SkPMColor 
    75  static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
    76      unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
    77      unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
    78      unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
    79      unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
    80      return SkPackARGB32(a, r, g, b);
    81  }
    83 +static inline int srcover_byte(int a, int b) {
    84 +    return a + b - SkAlphaMulAlpha(a, b);
    85 +}
    86 +
    87 +#define  blendfunc_byte(sc, dc, sa, da, blendfunc) \
    88 +  clamp_div255round(sc * (255 - da)  + dc * (255 - sa)  + blendfunc(sc, dc, sa, da))
    89 +
    90  // kMultiply_Mode
    91 +static inline int multiply_byte(int sc, int dc, int sa, int da) {
    92 +    return sc * dc;
    93 +}
    94  static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
    95 -    int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
    96 -    int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
    97 -    int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
    98 -    int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
    99 +    int sa = SkGetPackedA32(src);
   100 +    int da = SkGetPackedA32(dst);
   101 +    int a = srcover_byte(sa, da);
   102 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, multiply_byte);
   103 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, multiply_byte);
   104 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, multiply_byte);
   105      return SkPackARGB32(a, r, g, b);
   106  }
   108  // kScreen_Mode
   109 -static inline int srcover_byte(int a, int b) {
   110 -    return a + b - SkAlphaMulAlpha(a, b);
   111 +static inline int screen_byte(int sc, int dc, int sa, int da) {
   112 +    return sc * da + sa * dc - sc * dc;
   113  }
   114  static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
   115 -    int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
   116 -    int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
   117 -    int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
   118 -    int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
   119 +    int sa = SkGetPackedA32(src);
   120 +    int da = SkGetPackedA32(dst);
   121 +    int a = srcover_byte(sa, da);
   122 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, screen_byte);
   123 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, screen_byte);
   124 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, screen_byte);
   125 +    return SkPackARGB32(a, r, g, b);
   126 +}
   127 +
   128 +// kHardLight_Mode
   129 +static inline int hardlight_byte(int sc, int dc, int sa, int da) {
   130 +    if(!sa || !da)
   131 +        return sc * da;
   132 +    float Sc = (float)sc/sa;
   133 +    float Dc = (float)dc/da;
   134 +    if(Sc <= 0.5)
   135 +        Sc *= 2 * Dc;
   136 +    else
   137 +        Sc = -1 + 2 * Sc + 2 * Dc - 2 * Sc * Dc;
   138 +
   139 +    return Sc * sa * da;
   140 +}
   141 +static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
   142 +    int sa = SkGetPackedA32(src);
   143 +    int da = SkGetPackedA32(dst);
   144 +    int a = srcover_byte(sa, da);
   145 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, hardlight_byte);
   146 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, hardlight_byte);
   147 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, hardlight_byte);
   148      return SkPackARGB32(a, r, g, b);
   149  }
   151  // kOverlay_Mode
   152  static inline int overlay_byte(int sc, int dc, int sa, int da) {
   153 -    int tmp = sc * (255 - da) + dc * (255 - sa);
   154 -    int rc;
   155 -    if (2 * dc <= da) {
   156 -        rc = 2 * sc * dc;
   157 -    } else {
   158 -        rc = sa * da - 2 * (da - dc) * (sa - sc);
   159 -    }
   160 -    return clamp_div255round(rc + tmp);
   161 +    return hardlight_byte(dc, sc, da, sa);
   162  }
   163  static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
   164      int sa = SkGetPackedA32(src);
   165      int da = SkGetPackedA32(dst);
   166      int a = srcover_byte(sa, da);
   167 -    int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   168 -    int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   169 -    int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   170 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, overlay_byte);
   171 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, overlay_byte);
   172 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, overlay_byte);
   173      return SkPackARGB32(a, r, g, b);
   174  }
   176  // kDarken_Mode
   177  static inline int darken_byte(int sc, int dc, int sa, int da) {
   178 -    int sd = sc * da;
   179 -    int ds = dc * sa;
   180 -    if (sd < ds) {
   181 -        // srcover
   182 -        return sc + dc - SkDiv255Round(ds);
   183 -    } else {
   184 -        // dstover
   185 -        return dc + sc - SkDiv255Round(sd);
   186 -    }
   187 +    return SkMin32(sc * da, sa * dc);
   188  }
   189  static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
   190      int sa = SkGetPackedA32(src);
   191      int da = SkGetPackedA32(dst);
   192      int a = srcover_byte(sa, da);
   193 -    int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   194 -    int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   195 -    int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   196 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, darken_byte);
   197 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, darken_byte);
   198 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, darken_byte);
   199      return SkPackARGB32(a, r, g, b);
   200  }
   202  // kLighten_Mode
   203  static inline int lighten_byte(int sc, int dc, int sa, int da) {
   204 -    int sd = sc * da;
   205 -    int ds = dc * sa;
   206 -    if (sd > ds) {
   207 -        // srcover
   208 -        return sc + dc - SkDiv255Round(ds);
   209 -    } else {
   210 -        // dstover
   211 -        return dc + sc - SkDiv255Round(sd);
   212 -    }
   213 +    return SkMax32(sc * da, sa * dc);
   214  }
   215  static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
   216      int sa = SkGetPackedA32(src);
   217      int da = SkGetPackedA32(dst);
   218      int a = srcover_byte(sa, da);
   219 -    int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   220 -    int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   221 -    int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   222 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, lighten_byte);
   223 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, lighten_byte);
   224 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, lighten_byte);
   225      return SkPackARGB32(a, r, g, b);
   226  }
   228  // kColorDodge_Mode
   229  static inline int colordodge_byte(int sc, int dc, int sa, int da) {
   230 -    int diff = sa - sc;
   231 -    int rc;
   232 -    if (0 == diff) {
   233 -        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
   234 -        rc = SkDiv255Round(rc);
   235 -    } else {
   236 -        int tmp = (dc * sa << 15) / (da * diff);
   237 -        rc = SkDiv255Round(sa * da) * tmp >> 15;
   238 -        // don't clamp here, since we'll do it in our modeproc
   239 -    }
   240 -    return rc;
   241 +    if (dc == 0)
   242 +        return 0;
   243 +    // Avoid division by 0
   244 +    if (sc == sa)
   245 +        return da * sa;
   246 +
   247 +    return SkMin32(sa * da, sa * sa * dc / (sa - sc));
   248  }
   249  static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
   250 -    // added to avoid div-by-zero in colordodge_byte
   251 -    if (0 == dst) {
   252 -        return src;
   253 -    }
   254 -
   255      int sa = SkGetPackedA32(src);
   256      int da = SkGetPackedA32(dst);
   257      int a = srcover_byte(sa, da);
   258 -    int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   259 -    int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   260 -    int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   261 -    r = clamp_max(r, a);
   262 -    g = clamp_max(g, a);
   263 -    b = clamp_max(b, a);
   264 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, colordodge_byte);
   265 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, colordodge_byte);
   266 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, colordodge_byte);
   267      return SkPackARGB32(a, r, g, b);
   268  }
   270  // kColorBurn_Mode
   271  static inline int colorburn_byte(int sc, int dc, int sa, int da) {
   272 -    int rc;
   273 -    if (dc == da && 0 == sc) {
   274 -        rc = sa * da + dc * (255 - sa);
   275 -    } else if (0 == sc) {
   276 -        return SkAlphaMulAlpha(dc, 255 - sa);
   277 -    } else {
   278 -        int tmp = (sa * (da - dc) * 256) / (sc * da);
   279 -        if (tmp > 256) {
   280 -            tmp = 256;
   281 -        }
   282 -        int tmp2 = sa * da;
   283 -        rc = tmp2 - (tmp2 * tmp >> 8) + sc * (255 - da) + dc * (255 - sa);
   284 -    }
   285 -    return SkDiv255Round(rc);
   286 +    // Avoid division by 0
   287 +    if(dc == da)
   288 +        return sa * da;
   289 +    if(sc == 0)
   290 +        return 0;
   291 +
   292 +    return sa * da - SkMin32(sa * da, sa * sa * (da - dc) / sc);
   293  }
   294  static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
   295 -    // added to avoid div-by-zero in colorburn_byte
   296 -    if (0 == dst) {
   297 -        return src;
   298 -    }
   299 -
   300      int sa = SkGetPackedA32(src);
   301      int da = SkGetPackedA32(dst);
   302      int a = srcover_byte(sa, da);
   303 -    int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   304 -    int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   305 -    int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   306 -    return SkPackARGB32(a, r, g, b);
   307 -}
   308 -
   309 -// kHardLight_Mode
   310 -static inline int hardlight_byte(int sc, int dc, int sa, int da) {
   311 -    int rc;
   312 -    if (2 * sc <= sa) {
   313 -        rc = 2 * sc * dc;
   314 -    } else {
   315 -        rc = sa * da - 2 * (da - dc) * (sa - sc);
   316 -    }
   317 -    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
   318 -}
   319 -static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
   320 -    int sa = SkGetPackedA32(src);
   321 -    int da = SkGetPackedA32(dst);
   322 -    int a = srcover_byte(sa, da);
   323 -    int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   324 -    int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   325 -    int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   326 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, colorburn_byte);
   327 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, colorburn_byte);
   328 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, colorburn_byte);
   329      return SkPackARGB32(a, r, g, b);
   330  }
   332  // returns 255 * sqrt(n/255)
   333  static U8CPU sqrt_unit_byte(U8CPU n) {
   334      return SkSqrtBits(n, 15+4);
   335  }
   337  // kSoftLight_Mode
   338  static inline int softlight_byte(int sc, int dc, int sa, int da) {
   339      int m = da ? dc * 256 / da : 0;
   340      int rc;
   341 -    if (2 * sc <= sa) {
   342 -        rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
   343 -    } else if (4 * dc <= da) {
   344 +    if (2 * sc <= sa)
   345 +       return dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
   346 +
   347 +    if (4 * dc <= da) {
   348          int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
   349 -        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
   350 -    } else {
   351 -        int tmp = sqrt_unit_byte(m) - m;
   352 -        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
   353 +        return dc * sa + (da * (2 * sc - sa) * tmp >> 8);
   354      }
   355 -    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
   356 +    int tmp = sqrt_unit_byte(m) - m;
   357 +    return rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
   358  }
   359  static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
   360      int sa = SkGetPackedA32(src);
   361      int da = SkGetPackedA32(dst);
   362      int a = srcover_byte(sa, da);
   363 -    int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   364 -    int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   365 -    int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   366 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, softlight_byte);
   367 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, softlight_byte);
   368 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, softlight_byte);
   369      return SkPackARGB32(a, r, g, b);
   370  }
   372  // kDifference_Mode
   373  static inline int difference_byte(int sc, int dc, int sa, int da) {
   374 -    int tmp = SkMin32(sc * da, dc * sa);
   375 -    return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
   376 +    int tmp = dc * sa - sc * da;
   377 +    if(tmp<0)
   378 +        return - tmp;
   379 +
   380 +    return tmp;
   381  }
   382  static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
   383      int sa = SkGetPackedA32(src);
   384      int da = SkGetPackedA32(dst);
   385      int a = srcover_byte(sa, da);
   386 -    int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   387 -    int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   388 -    int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   389 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, difference_byte);
   390 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, difference_byte);
   391 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, difference_byte);
   392      return SkPackARGB32(a, r, g, b);
   393  }
   395  // kExclusion_Mode
   396  static inline int exclusion_byte(int sc, int dc, int sa, int da) {
   397 -    // this equations is wacky, wait for SVG to confirm it
   398 -    int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
   399 -    return clamp_div255round(r);
   400 +    return sc * da + dc * sa - 2 * dc * sc;
   401  }
   402  static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
   403      int sa = SkGetPackedA32(src);
   404      int da = SkGetPackedA32(dst);
   405      int a = srcover_byte(sa, da);
   406 -    int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   407 -    int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   408 -    int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   409 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, exclusion_byte);
   410 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, exclusion_byte);
   411 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, exclusion_byte);
   412 +    return SkPackARGB32(a, r, g, b);
   413 +}
   414 +
   415 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   416 +struct BlendColor {
   417 +    float r;
   418 +    float g;
   419 +    float b;
   420 +
   421 +    BlendColor(): r(0), g(0), b(0)
   422 +      {}
   423 +};
   424 +
   425 +static inline float Lum(BlendColor C)
   426 +{
   427 +    return C.r * 0.3 + C.g * 0.59 + C.b* 0.11;
   428 +}
   429 +
   430 +static inline float SkMinFloat(float a, float b)
   431 +{
   432 +  if (a > b)
   433 +    a = b;
   434 +  return a;
   435 +}
   436 +
   437 +static inline float SkMaxFloat(float a, float b)
   438 +{
   439 +  if (a < b)
   440 +    a = b;
   441 +  return a;
   442 +}
   443 +
   444 +#define minimum(C) SkMinFloat(SkMinFloat(C.r, C.g), C.b)
   445 +#define maximum(C) SkMaxFloat(SkMaxFloat(C.r, C.g), C.b)
   446 +
   447 +static inline float Sat(BlendColor c) {
   448 +    return maximum(c) - minimum(c);
   449 +}
   450 +
   451 +static inline void setSaturationComponents(float& Cmin, float& Cmid, float& Cmax, float s) {
   452 +    if(Cmax > Cmin) {
   453 +        Cmid =  (((Cmid - Cmin) * s ) / (Cmax - Cmin));
   454 +        Cmax = s;
   455 +    } else {
   456 +        Cmax = 0;
   457 +        Cmid = 0;
   458 +    }
   459 +    Cmin = 0;
   460 +}
   461 +
   462 +static inline BlendColor SetSat(BlendColor C, float s) {
   463 +    if(C.r <= C.g) {
   464 +        if(C.g <= C.b)
   465 +            setSaturationComponents(C.r, C.g, C.b, s);
   466 +        else
   467 +        if(C.r <= C.b)
   468 +            setSaturationComponents(C.r, C.b, C.g, s);
   469 +        else
   470 +            setSaturationComponents(C.b, C.r, C.g, s);
   471 +        } else if(C.r <= C.b)
   472 +            setSaturationComponents(C.g, C.r, C.b, s);
   473 +        else
   474 +        if(C.g <= C.b)
   475 +            setSaturationComponents(C.g, C.b, C.r, s);
   476 +        else
   477 +            setSaturationComponents(C.b, C.g, C.r, s);
   478 +
   479 +        return C;
   480 +}
   481 +
   482 +static inline BlendColor clipColor(BlendColor C) {
   483 +    float L = Lum(C);
   484 +    float n = minimum(C);
   485 +    float x = maximum(C);
   486 +    if(n < 0) {
   487 +       C.r = L + (((C.r - L) * L) / (L - n));
   488 +       C.g = L + (((C.g - L) * L) / (L - n));
   489 +       C.b = L + (((C.b - L) * L) / (L - n));
   490 +    }
   491 +
   492 +    if(x > 1) {
   493 +       C.r = L + (((C.r - L) * (1 - L)) / (x - L));
   494 +       C.g = L + (((C.g - L) * (1 - L)) / (x - L));
   495 +       C.b = L + (((C.b - L) * (1 - L)) / (x - L));
   496 +    }
   497 +    return C;
   498 +}
   499 +
   500 +static inline BlendColor SetLum(BlendColor C, float l) {
   501 +  float d = l - Lum(C);
   502 +  C.r +=  d;
   503 +  C.g +=  d;
   504 +  C.b +=  d;
   505 +
   506 +  return clipColor(C);
   507 +}
   508 +
   509 +#define  blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
   510 +  clamp_div255round(sc * (255 - da)  + dc * (255 - sa)  +  (int)(sa * da * blendval))
   511 +
   512 +static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
   513 +    int sr = SkGetPackedR32(src);
   514 +    int sg = SkGetPackedG32(src);
   515 +    int sb = SkGetPackedB32(src);
   516 +    int sa = SkGetPackedA32(src);
   517 +
   518 +    int dr = SkGetPackedR32(dst);
   519 +    int dg = SkGetPackedG32(dst);
   520 +    int db = SkGetPackedB32(dst);
   521 +    int da = SkGetPackedA32(dst);
   522 +
   523 +    BlendColor Cs;
   524 +    if(sa) {
   525 +        Cs.r  = (float)sr / sa;
   526 +        Cs.g = (float)sg / sa;
   527 +        Cs.b = (float)sb / sa;
   528 +        BlendColor Cd;
   529 +        if(da) {
   530 +            Cd.r =  (float)dr / da;
   531 +            Cd.g = (float)dg / da;
   532 +            Cd.b = (float)db / da;
   533 +            Cs = SetLum(SetSat(Cs, Sat(Cd)), Lum(Cd));
   534 +        }
   535 +    }
   536 +
   537 +    int a = srcover_byte(sa, da);
   538 +    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r);
   539 +    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g);
   540 +    int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b);
   541 +    return SkPackARGB32(a, r, g, b);
   542 +}
   543 +
   544 +static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
   545 +    int sr = SkGetPackedR32(src);
   546 +    int sg = SkGetPackedG32(src);
   547 +    int sb = SkGetPackedB32(src);
   548 +    int sa = SkGetPackedA32(src);
   549 +
   550 +    int dr = SkGetPackedR32(dst);
   551 +    int dg = SkGetPackedG32(dst);
   552 +    int db = SkGetPackedB32(dst);
   553 +    int da = SkGetPackedA32(dst);
   554 +
   555 +    BlendColor Cs;
   556 +    if(sa) {
   557 +        Cs.r  = (float)sr / sa;
   558 +        Cs.g = (float)sg / sa;
   559 +        Cs.b = (float)sb / sa;
   560 +        BlendColor Cd;
   561 +        if(da) {
   562 +            Cd.r =  (float)dr / da;
   563 +            Cd.g = (float)dg / da;
   564 +            Cd.b = (float)db / da;
   565 +            Cs = SetLum(SetSat(Cd, Sat(Cs)), Lum(Cd));
   566 +        }
   567 +    }
   568 +
   569 +    int a = srcover_byte(sa, da);
   570 +    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r);
   571 +    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g);
   572 +    int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b);
   573 +    return SkPackARGB32(a, r, g, b);
   574 +}
   575 +
   576 +static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
   577 +    int sr = SkGetPackedR32(src);
   578 +    int sg = SkGetPackedG32(src);
   579 +    int sb = SkGetPackedB32(src);
   580 +    int sa = SkGetPackedA32(src);
   581 +
   582 +    int dr = SkGetPackedR32(dst);
   583 +    int dg = SkGetPackedG32(dst);
   584 +    int db = SkGetPackedB32(dst);
   585 +    int da = SkGetPackedA32(dst);
   586 +
   587 +    BlendColor Cs;
   588 +    if(sa) {
   589 +        Cs.r  = (float)sr / sa;
   590 +        Cs.g = (float)sg / sa;
   591 +        Cs.b = (float)sb / sa;
   592 +        BlendColor Cd;
   593 +        if(da) {
   594 +            Cd.r =  (float)dr / da;
   595 +            Cd.g = (float)dg / da;
   596 +            Cd.b = (float)db / da;
   597 +            Cs = SetLum(Cs, Lum(Cd));
   598 +            }
   599 +    }
   600 +
   601 +    int a = srcover_byte(sa, da);
   602 +    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r);
   603 +    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g);
   604 +    int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b);
   605 +    return SkPackARGB32(a, r, g, b);
   606 +}
   607 +
   608 +static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
   609 +    int sr = SkGetPackedR32(src);
   610 +    int sg = SkGetPackedG32(src);
   611 +    int sb = SkGetPackedB32(src);
   612 +    int sa = SkGetPackedA32(src);
   613 +
   614 +    int dr = SkGetPackedR32(dst);
   615 +    int dg = SkGetPackedG32(dst);
   616 +    int db = SkGetPackedB32(dst);
   617 +    int da = SkGetPackedA32(dst);
   618 +
   619 +    BlendColor Cs;
   620 +    if(sa) {
   621 +        Cs.r  = (float)sr / sa;
   622 +        Cs.g = (float)sg / sa;
   623 +        Cs.b = (float)sb / sa;
   624 +        BlendColor Cd;
   625 +        if(da) {
   626 +            Cd.r =  (float)dr / da;
   627 +            Cd.g = (float)dg / da;
   628 +            Cd.b = (float)db / da;
   629 +            Cs = SetLum(Cd, Lum(Cs));
   630 +            }
   631 +    }
   632 +
   633 +    int a = srcover_byte(sa, da);
   634 +    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r);
   635 +    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g);
   636 +    int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b);
   637      return SkPackARGB32(a, r, g, b);
   638  }
   640  struct ProcCoeff {
   641      SkXfermodeProc      fProc;
   642      SkXfermode::Coeff   fSC;
   643      SkXfermode::Coeff   fDC;
   644  };
   645 @@ -430,27 +627,31 @@ static const ProcCoeff gProcCoeffs[] = {
   646      { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
   647      { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
   648      { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
   649      { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
   650      { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
   651      { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
   653      { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
   654 -    { multiply_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
   655 +    { multiply_modeproc,    CANNOT_USE_COEFF,       CANNOT_USE_COEFF},
   656      { screen_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   657      { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   658      { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   659      { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   660      { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   661      { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   662      { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   663      { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   664      { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   665      { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   666 +    { hue_modeproc,         CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   667 +    { saturation_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   668 +    { color_modeproc,       CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   669 +    { luminosity_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   670  };
   672  ///////////////////////////////////////////////////////////////////////////////
   674  bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) {
   675      return false;
   676  }
   678 @@ -1172,16 +1373,20 @@ static const Proc16Rec gModeProcs16[] = 
   679      { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
   680      { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
   681      { NULL,                 NULL,                   NULL            }, // colordodge
   682      { NULL,                 NULL,                   NULL            }, // colorburn
   683      { NULL,                 NULL,                   NULL            }, // hardlight
   684      { NULL,                 NULL,                   NULL            }, // softlight
   685      { NULL,                 NULL,                   NULL            }, // difference
   686      { NULL,                 NULL,                   NULL            }, // exclusion
   687 +    { NULL,                 NULL,                   NULL            }, // hue
   688 +    { NULL,                 NULL,                   NULL            }, // saturation
   689 +    { NULL,                 NULL,                   NULL            }, // color
   690 +    { NULL,                 NULL,                   NULL            }, // luminosity
   691  };
   693  SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
   694      SkXfermodeProc16  proc16 = NULL;
   695      if ((unsigned)mode < kModeCount) {
   696          const Proc16Rec& rec = gModeProcs16[mode];
   697          unsigned a = SkColorGetA(srcColor);

mercurial