diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /gfx/skia/patches/archive/0010-Bug-836892-Add-new-blending-modes-to-SkXfermode.patch | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | gfx/skia/patches/archive/0010-Bug-836892-Add-new-blending-modes-to-SkXfermode.patch | 698 |
1 files changed, 698 insertions, 0 deletions
diff --git a/gfx/skia/patches/archive/0010-Bug-836892-Add-new-blending-modes-to-SkXfermode.patch b/gfx/skia/patches/archive/0010-Bug-836892-Add-new-blending-modes-to-SkXfermode.patch new file mode 100644 index 0000000000..a446037de0 --- /dev/null +++ b/gfx/skia/patches/archive/0010-Bug-836892-Add-new-blending-modes-to-SkXfermode.patch @@ -0,0 +1,698 @@ +# HG changeset patch +# User Rik Cabanier <cabanier@adobe.com> +# Date 1360273929 -46800 +# Node ID 3ac8edca3a03b3d22240b5a5b95ae3b5ada9877d +# Parent cbb67fe70b864b36165061e1fd3b083cd09af087 +Bug 836892 - Add new blending modes to SkXfermode. r=gw280 + +diff --git a/gfx/skia/include/core/SkXfermode.h b/gfx/skia/include/core/SkXfermode.h +--- a/gfx/skia/include/core/SkXfermode.h ++++ b/gfx/skia/include/core/SkXfermode.h +@@ -96,33 +96,37 @@ public: + kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)] + kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc] + kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)] + kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] + + // all remaining modes are defined in the SVG Compositing standard + // http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/ + kPlus_Mode, +- kMultiply_Mode, + + // all above modes can be expressed as pair of src/dst Coeffs + kCoeffModesCnt, + +- kScreen_Mode = kCoeffModesCnt, ++ kMultiply_Mode = kCoeffModesCnt, ++ kScreen_Mode, + kOverlay_Mode, + kDarken_Mode, + kLighten_Mode, + kColorDodge_Mode, + kColorBurn_Mode, + kHardLight_Mode, + kSoftLight_Mode, + kDifference_Mode, + kExclusion_Mode, ++ kHue_Mode, ++ kSaturation_Mode, ++ kColor_Mode, ++ kLuminosity_Mode, + +- kLastMode = kExclusion_Mode ++ kLastMode = kLuminosity_Mode + }; + + /** + * If the xfermode is one of the modes in the Mode enum, then asMode() + * returns true and sets (if not null) mode accordingly. Otherwise it + * returns false and ignores the mode parameter. + */ + virtual bool asMode(Mode* mode); +diff --git a/gfx/skia/src/core/SkXfermode.cpp b/gfx/skia/src/core/SkXfermode.cpp +--- a/gfx/skia/src/core/SkXfermode.cpp ++++ b/gfx/skia/src/core/SkXfermode.cpp +@@ -7,16 +7,18 @@ + */ + + + #include "SkXfermode.h" + #include "SkColorPriv.h" + #include "SkFlattenableBuffers.h" + #include "SkMathPriv.h" + ++#include <algorithm> ++ + SK_DEFINE_INST_COUNT(SkXfermode) + + #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b) + + #if 0 + // idea for higher precision blends in xfer procs (and slightly faster) + // see DstATop as a probable caller + static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) { +@@ -176,244 +178,439 @@ static SkPMColor xor_modeproc(SkPMColor + static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) { + unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst)); + unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst)); + unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst)); + unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst)); + return SkPackARGB32(a, r, g, b); + } + ++static inline int srcover_byte(int a, int b) { ++ return a + b - SkAlphaMulAlpha(a, b); ++} ++ ++#define blendfunc_byte(sc, dc, sa, da, blendfunc) \ ++ clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendfunc(sc, dc, sa, da)) ++ + // kMultiply_Mode ++static inline int multiply_byte(int sc, int dc, int sa, int da) { ++ return sc * dc; ++} + static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) { +- int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst)); +- int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst)); +- int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst)); +- int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst)); ++ int sa = SkGetPackedA32(src); ++ int da = SkGetPackedA32(dst); ++ int a = srcover_byte(sa, da); ++ int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, multiply_byte); ++ int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, multiply_byte); ++ int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, multiply_byte); + return SkPackARGB32(a, r, g, b); + } + + // kScreen_Mode +-static inline int srcover_byte(int a, int b) { +- return a + b - SkAlphaMulAlpha(a, b); ++static inline int screen_byte(int sc, int dc, int sa, int da) { ++ return sc * da + sa * dc - sc * dc; + } + static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) { +- int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst)); +- int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst)); +- int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst)); +- int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst)); ++ int sa = SkGetPackedA32(src); ++ int da = SkGetPackedA32(dst); ++ int a = srcover_byte(sa, da); ++ int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, screen_byte); ++ int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, screen_byte); ++ int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, screen_byte); ++ return SkPackARGB32(a, r, g, b); ++} ++ ++// kHardLight_Mode ++static inline int hardlight_byte(int sc, int dc, int sa, int da) { ++ if(!sa || !da) ++ return sc * da; ++ float Sc = (float)sc/sa; ++ float Dc = (float)dc/da; ++ if(Sc <= 0.5) ++ Sc *= 2 * Dc; ++ else ++ Sc = -1 + 2 * Sc + 2 * Dc - 2 * Sc * Dc; ++ ++ return Sc * sa * da; ++} ++static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) { ++ int sa = SkGetPackedA32(src); ++ int da = SkGetPackedA32(dst); ++ int a = srcover_byte(sa, da); ++ int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, hardlight_byte); ++ int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, hardlight_byte); ++ int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, hardlight_byte); + return SkPackARGB32(a, r, g, b); + } + + // kOverlay_Mode + static inline int overlay_byte(int sc, int dc, int sa, int da) { +- int tmp = sc * (255 - da) + dc * (255 - sa); +- int rc; +- if (2 * dc <= da) { +- rc = 2 * sc * dc; +- } else { +- rc = sa * da - 2 * (da - dc) * (sa - sc); +- } +- return clamp_div255round(rc + tmp); ++ return hardlight_byte(dc, sc, da, sa); + } + static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) { + int sa = SkGetPackedA32(src); + int da = SkGetPackedA32(dst); + int a = srcover_byte(sa, da); +- int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); +- int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); +- int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); ++ int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, overlay_byte); ++ int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, overlay_byte); ++ int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, overlay_byte); + return SkPackARGB32(a, r, g, b); + } + + // kDarken_Mode + static inline int darken_byte(int sc, int dc, int sa, int da) { +- int sd = sc * da; +- int ds = dc * sa; +- if (sd < ds) { +- // srcover +- return sc + dc - SkDiv255Round(ds); +- } else { +- // dstover +- return dc + sc - SkDiv255Round(sd); +- } ++ return SkMin32(sc * da, sa * dc); + } + static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) { + int sa = SkGetPackedA32(src); + int da = SkGetPackedA32(dst); + int a = srcover_byte(sa, da); +- int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); +- int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); +- int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); ++ int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, darken_byte); ++ int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, darken_byte); ++ int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, darken_byte); + return SkPackARGB32(a, r, g, b); + } + + // kLighten_Mode + static inline int lighten_byte(int sc, int dc, int sa, int da) { +- int sd = sc * da; +- int ds = dc * sa; +- if (sd > ds) { +- // srcover +- return sc + dc - SkDiv255Round(ds); +- } else { +- // dstover +- return dc + sc - SkDiv255Round(sd); +- } ++ return SkMax32(sc * da, sa * dc); + } + static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) { + int sa = SkGetPackedA32(src); + int da = SkGetPackedA32(dst); + int a = srcover_byte(sa, da); +- int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); +- int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); +- int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); ++ int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, lighten_byte); ++ int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, lighten_byte); ++ int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, lighten_byte); + return SkPackARGB32(a, r, g, b); + } + + // kColorDodge_Mode + static inline int colordodge_byte(int sc, int dc, int sa, int da) { +- int diff = sa - sc; +- int rc; +- if (0 == diff) { +- rc = sa * da + sc * (255 - da) + dc * (255 - sa); +- rc = SkDiv255Round(rc); +- } else { +- int tmp = (dc * sa << 15) / (da * diff); +- rc = SkDiv255Round(sa * da) * tmp >> 15; +- // don't clamp here, since we'll do it in our modeproc +- } +- return rc; ++ if (dc == 0) ++ return 0; ++ // Avoid division by 0 ++ if (sc == sa) ++ return da * sa; ++ ++ return SkMin32(sa * da, sa * sa * dc / (sa - sc)); + } + static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) { +- // added to avoid div-by-zero in colordodge_byte +- if (0 == dst) { +- return src; +- } +- + int sa = SkGetPackedA32(src); + int da = SkGetPackedA32(dst); + int a = srcover_byte(sa, da); +- int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); +- int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); +- int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); +- r = clamp_max(r, a); +- g = clamp_max(g, a); +- b = clamp_max(b, a); ++ int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, colordodge_byte); ++ int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, colordodge_byte); ++ int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, colordodge_byte); + return SkPackARGB32(a, r, g, b); + } + + // kColorBurn_Mode + static inline int colorburn_byte(int sc, int dc, int sa, int da) { +- int rc; +- if (dc == da && 0 == sc) { +- rc = sa * da + dc * (255 - sa); +- } else if (0 == sc) { +- return SkAlphaMulAlpha(dc, 255 - sa); +- } else { +- int tmp = (sa * (da - dc) * 256) / (sc * da); +- if (tmp > 256) { +- tmp = 256; +- } +- int tmp2 = sa * da; +- rc = tmp2 - (tmp2 * tmp >> 8) + sc * (255 - da) + dc * (255 - sa); +- } +- return SkDiv255Round(rc); ++ // Avoid division by 0 ++ if(dc == da) ++ return sa * da; ++ if(sc == 0) ++ return 0; ++ ++ return sa * da - SkMin32(sa * da, sa * sa * (da - dc) / sc); + } + static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) { +- // added to avoid div-by-zero in colorburn_byte +- if (0 == dst) { +- return src; +- } +- + int sa = SkGetPackedA32(src); + int da = SkGetPackedA32(dst); + int a = srcover_byte(sa, da); +- int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); +- int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); +- int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); +- return SkPackARGB32(a, r, g, b); +-} +- +-// kHardLight_Mode +-static inline int hardlight_byte(int sc, int dc, int sa, int da) { +- int rc; +- if (2 * sc <= sa) { +- rc = 2 * sc * dc; +- } else { +- rc = sa * da - 2 * (da - dc) * (sa - sc); +- } +- return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa)); +-} +-static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) { +- int sa = SkGetPackedA32(src); +- int da = SkGetPackedA32(dst); +- int a = srcover_byte(sa, da); +- int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); +- int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); +- int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); ++ int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, colorburn_byte); ++ int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, colorburn_byte); ++ int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, colorburn_byte); + return SkPackARGB32(a, r, g, b); + } + + // returns 255 * sqrt(n/255) + static U8CPU sqrt_unit_byte(U8CPU n) { + return SkSqrtBits(n, 15+4); + } + + // kSoftLight_Mode + static inline int softlight_byte(int sc, int dc, int sa, int da) { + int m = da ? dc * 256 / da : 0; + int rc; +- if (2 * sc <= sa) { +- rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8)); +- } else if (4 * dc <= da) { ++ if (2 * sc <= sa) ++ return dc * (sa + ((2 * sc - sa) * (256 - m) >> 8)); ++ ++ if (4 * dc <= da) { + int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m; +- rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); +- } else { +- int tmp = sqrt_unit_byte(m) - m; +- rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); ++ return dc * sa + (da * (2 * sc - sa) * tmp >> 8); + } +- return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa)); ++ int tmp = sqrt_unit_byte(m) - m; ++ return rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); + } + static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) { + int sa = SkGetPackedA32(src); + int da = SkGetPackedA32(dst); + int a = srcover_byte(sa, da); +- int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); +- int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); +- int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); ++ int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, softlight_byte); ++ int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, softlight_byte); ++ int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, softlight_byte); + return SkPackARGB32(a, r, g, b); + } + + // kDifference_Mode + static inline int difference_byte(int sc, int dc, int sa, int da) { +- int tmp = SkMin32(sc * da, dc * sa); +- return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp)); ++ int tmp = dc * sa - sc * da; ++ if(tmp<0) ++ return - tmp; ++ ++ return tmp; + } + static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) { + int sa = SkGetPackedA32(src); + int da = SkGetPackedA32(dst); + int a = srcover_byte(sa, da); +- int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); +- int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); +- int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); ++ int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, difference_byte); ++ int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, difference_byte); ++ int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, difference_byte); + return SkPackARGB32(a, r, g, b); + } + + // kExclusion_Mode + static inline int exclusion_byte(int sc, int dc, int sa, int da) { +- // this equations is wacky, wait for SVG to confirm it +- int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa); +- return clamp_div255round(r); ++ return sc * da + dc * sa - 2 * dc * sc; + } + static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) { + int sa = SkGetPackedA32(src); + int da = SkGetPackedA32(dst); + int a = srcover_byte(sa, da); +- int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); +- int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); +- int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); ++ int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, exclusion_byte); ++ int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, exclusion_byte); ++ int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, exclusion_byte); ++ return SkPackARGB32(a, r, g, b); ++} ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ++struct BlendColor { ++ float r; ++ float g; ++ float b; ++ ++ BlendColor(): r(0), g(0), b(0) ++ {} ++}; ++ ++static inline float Lum(BlendColor C) ++{ ++ return C.r * 0.3 + C.g * 0.59 + C.b* 0.11; ++} ++ ++static inline float SkMinFloat(float a, float b) ++{ ++ if (a > b) ++ a = b; ++ return a; ++} ++ ++static inline float SkMaxFloat(float a, float b) ++{ ++ if (a < b) ++ a = b; ++ return a; ++} ++ ++#define minimum(C) SkMinFloat(SkMinFloat(C.r, C.g), C.b) ++#define maximum(C) SkMaxFloat(SkMaxFloat(C.r, C.g), C.b) ++ ++static inline float Sat(BlendColor c) { ++ return maximum(c) - minimum(c); ++} ++ ++static inline void setSaturationComponents(float& Cmin, float& Cmid, float& Cmax, float s) { ++ if(Cmax > Cmin) { ++ Cmid = (((Cmid - Cmin) * s ) / (Cmax - Cmin)); ++ Cmax = s; ++ } else { ++ Cmax = 0; ++ Cmid = 0; ++ } ++ Cmin = 0; ++} ++ ++static inline BlendColor SetSat(BlendColor C, float s) { ++ if(C.r <= C.g) { ++ if(C.g <= C.b) ++ setSaturationComponents(C.r, C.g, C.b, s); ++ else ++ if(C.r <= C.b) ++ setSaturationComponents(C.r, C.b, C.g, s); ++ else ++ setSaturationComponents(C.b, C.r, C.g, s); ++ } else if(C.r <= C.b) ++ setSaturationComponents(C.g, C.r, C.b, s); ++ else ++ if(C.g <= C.b) ++ setSaturationComponents(C.g, C.b, C.r, s); ++ else ++ setSaturationComponents(C.b, C.g, C.r, s); ++ ++ return C; ++} ++ ++static inline BlendColor clipColor(BlendColor C) { ++ float L = Lum(C); ++ float n = minimum(C); ++ float x = maximum(C); ++ if(n < 0) { ++ C.r = L + (((C.r - L) * L) / (L - n)); ++ C.g = L + (((C.g - L) * L) / (L - n)); ++ C.b = L + (((C.b - L) * L) / (L - n)); ++ } ++ ++ if(x > 1) { ++ C.r = L + (((C.r - L) * (1 - L)) / (x - L)); ++ C.g = L + (((C.g - L) * (1 - L)) / (x - L)); ++ C.b = L + (((C.b - L) * (1 - L)) / (x - L)); ++ } ++ return C; ++} ++ ++static inline BlendColor SetLum(BlendColor C, float l) { ++ float d = l - Lum(C); ++ C.r += d; ++ C.g += d; ++ C.b += d; ++ ++ return clipColor(C); ++} ++ ++#define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \ ++ clamp_div255round(sc * (255 - da) + dc * (255 - sa) + (int)(sa * da * blendval)) ++ ++static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) { ++ int sr = SkGetPackedR32(src); ++ int sg = SkGetPackedG32(src); ++ int sb = SkGetPackedB32(src); ++ int sa = SkGetPackedA32(src); ++ ++ int dr = SkGetPackedR32(dst); ++ int dg = SkGetPackedG32(dst); ++ int db = SkGetPackedB32(dst); ++ int da = SkGetPackedA32(dst); ++ ++ BlendColor Cs; ++ if(sa) { ++ Cs.r = (float)sr / sa; ++ Cs.g = (float)sg / sa; ++ Cs.b = (float)sb / sa; ++ BlendColor Cd; ++ if(da) { ++ Cd.r = (float)dr / da; ++ Cd.g = (float)dg / da; ++ Cd.b = (float)db / da; ++ Cs = SetLum(SetSat(Cs, Sat(Cd)), Lum(Cd)); ++ } ++ } ++ ++ int a = srcover_byte(sa, da); ++ int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r); ++ int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g); ++ int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b); ++ return SkPackARGB32(a, r, g, b); ++} ++ ++static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) { ++ int sr = SkGetPackedR32(src); ++ int sg = SkGetPackedG32(src); ++ int sb = SkGetPackedB32(src); ++ int sa = SkGetPackedA32(src); ++ ++ int dr = SkGetPackedR32(dst); ++ int dg = SkGetPackedG32(dst); ++ int db = SkGetPackedB32(dst); ++ int da = SkGetPackedA32(dst); ++ ++ BlendColor Cs; ++ if(sa) { ++ Cs.r = (float)sr / sa; ++ Cs.g = (float)sg / sa; ++ Cs.b = (float)sb / sa; ++ BlendColor Cd; ++ if(da) { ++ Cd.r = (float)dr / da; ++ Cd.g = (float)dg / da; ++ Cd.b = (float)db / da; ++ Cs = SetLum(SetSat(Cd, Sat(Cs)), Lum(Cd)); ++ } ++ } ++ ++ int a = srcover_byte(sa, da); ++ int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r); ++ int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g); ++ int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b); ++ return SkPackARGB32(a, r, g, b); ++} ++ ++static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) { ++ int sr = SkGetPackedR32(src); ++ int sg = SkGetPackedG32(src); ++ int sb = SkGetPackedB32(src); ++ int sa = SkGetPackedA32(src); ++ ++ int dr = SkGetPackedR32(dst); ++ int dg = SkGetPackedG32(dst); ++ int db = SkGetPackedB32(dst); ++ int da = SkGetPackedA32(dst); ++ ++ BlendColor Cs; ++ if(sa) { ++ Cs.r = (float)sr / sa; ++ Cs.g = (float)sg / sa; ++ Cs.b = (float)sb / sa; ++ BlendColor Cd; ++ if(da) { ++ Cd.r = (float)dr / da; ++ Cd.g = (float)dg / da; ++ Cd.b = (float)db / da; ++ Cs = SetLum(Cs, Lum(Cd)); ++ } ++ } ++ ++ int a = srcover_byte(sa, da); ++ int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r); ++ int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g); ++ int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b); ++ return SkPackARGB32(a, r, g, b); ++} ++ ++static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) { ++ int sr = SkGetPackedR32(src); ++ int sg = SkGetPackedG32(src); ++ int sb = SkGetPackedB32(src); ++ int sa = SkGetPackedA32(src); ++ ++ int dr = SkGetPackedR32(dst); ++ int dg = SkGetPackedG32(dst); ++ int db = SkGetPackedB32(dst); ++ int da = SkGetPackedA32(dst); ++ ++ BlendColor Cs; ++ if(sa) { ++ Cs.r = (float)sr / sa; ++ Cs.g = (float)sg / sa; ++ Cs.b = (float)sb / sa; ++ BlendColor Cd; ++ if(da) { ++ Cd.r = (float)dr / da; ++ Cd.g = (float)dg / da; ++ Cd.b = (float)db / da; ++ Cs = SetLum(Cd, Lum(Cs)); ++ } ++ } ++ ++ int a = srcover_byte(sa, da); ++ int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r); ++ int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g); ++ int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b); + return SkPackARGB32(a, r, g, b); + } + + struct ProcCoeff { + SkXfermodeProc fProc; + SkXfermode::Coeff fSC; + SkXfermode::Coeff fDC; + }; +@@ -430,27 +627,31 @@ static const ProcCoeff gProcCoeffs[] = { + { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff }, + { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff }, + { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff }, + { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff }, + { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff }, + { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff }, + + { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff }, +- { multiply_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff }, ++ { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF}, + { screen_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, + { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, + { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, + { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, + { colordodge_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, + { colorburn_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, + { hardlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, + { softlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, + { difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, + { exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, ++ { hue_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, ++ { saturation_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, ++ { color_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, ++ { luminosity_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, + }; + + /////////////////////////////////////////////////////////////////////////////// + + bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) { + return false; + } + +@@ -1172,16 +1373,20 @@ static const Proc16Rec gModeProcs16[] = + { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken + { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten + { NULL, NULL, NULL }, // colordodge + { NULL, NULL, NULL }, // colorburn + { NULL, NULL, NULL }, // hardlight + { NULL, NULL, NULL }, // softlight + { NULL, NULL, NULL }, // difference + { NULL, NULL, NULL }, // exclusion ++ { NULL, NULL, NULL }, // hue ++ { NULL, NULL, NULL }, // saturation ++ { NULL, NULL, NULL }, // color ++ { NULL, NULL, NULL }, // luminosity + }; + + SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) { + SkXfermodeProc16 proc16 = NULL; + if ((unsigned)mode < kModeCount) { + const Proc16Rec& rec = gModeProcs16[mode]; + unsigned a = SkColorGetA(srcColor); + |