mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
699 lines
26 KiB
Diff
699 lines
26 KiB
Diff
|
# 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);
|
||
|
|