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

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);