Added support for non-separable blending modes.
Fixed scalar issue from https://codereview.appspot.com/7346044 Review URL: https://chromiumcodereview.appspot.com/12393049 git-svn-id: http://skia.googlecode.com/svn/trunk@7984 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
07631cf14e
commit
b24f89353e
@ -114,6 +114,10 @@ protected:
|
||||
{ SkXfermode::kDifference_Mode, "Difference" },
|
||||
{ SkXfermode::kExclusion_Mode, "Exclusion" },
|
||||
{ SkXfermode::kMultiply_Mode, "Multiply" },
|
||||
{ SkXfermode::kHue_Mode, "Hue" },
|
||||
{ SkXfermode::kSaturation_Mode, "Saturation" },
|
||||
{ SkXfermode::kColor_Mode, "Color" },
|
||||
{ SkXfermode::kLuminosity_Mode, "Luminosity" },
|
||||
};
|
||||
|
||||
const SkScalar w = SkIntToScalar(W);
|
||||
|
@ -99,15 +99,14 @@ public:
|
||||
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,
|
||||
kPlus_Mode, //!< [Sa + Da, Sc + Dc]
|
||||
kModulate_Mode, // multiplies all components (= alpha and color)
|
||||
|
||||
// all above modes can be expressed as pair of src/dst Coeffs
|
||||
kCoeffModesCnt,
|
||||
|
||||
// Following blend modes are defined in the CSS Compositing standard:
|
||||
// https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending
|
||||
kScreen_Mode = kCoeffModesCnt,
|
||||
kOverlay_Mode,
|
||||
kDarken_Mode,
|
||||
@ -120,7 +119,12 @@ public:
|
||||
kExclusion_Mode,
|
||||
kMultiply_Mode,
|
||||
|
||||
kLastMode = kMultiply_Mode
|
||||
kHue_Mode,
|
||||
kSaturation_Mode,
|
||||
kColor_Mode,
|
||||
kLuminosity_Mode,
|
||||
|
||||
kLastMode = kLuminosity_Mode
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -431,6 +431,233 @@ static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
|
||||
return SkPackARGB32(a, r, g, b);
|
||||
}
|
||||
|
||||
// The CSS compositing spec introduces the following formulas:
|
||||
// (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
|
||||
// SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
|
||||
// while PDF and CG uses the one from Rec. Rec. 601
|
||||
// See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
|
||||
static inline int Lum(int r, int g, int b)
|
||||
{
|
||||
return (r * 77 + g * 151 + b * 28) >> 8;
|
||||
}
|
||||
|
||||
static inline int min2(int a, int b) { return a < b ? a : b; }
|
||||
static inline int max2(int a, int b) { return a > b ? a : b; }
|
||||
#define minimum(a, b, c) min2(min2(a, b), c)
|
||||
#define maximum(a, b, c) max2(max2(a, b), c)
|
||||
|
||||
static inline int Sat(int r, int g, int b) {
|
||||
return maximum(r, g, b) - minimum(r, g, b);
|
||||
}
|
||||
|
||||
static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
|
||||
if(Cmax > Cmin) {
|
||||
*Cmid = (((*Cmid - *Cmin) * s ) / (*Cmax - *Cmin));
|
||||
*Cmax = s;
|
||||
} else {
|
||||
*Cmax = 0;
|
||||
*Cmid = 0;
|
||||
}
|
||||
|
||||
*Cmin = 0;
|
||||
}
|
||||
|
||||
static inline void SetSat(int* r, int* g, int* b, int s) {
|
||||
if(*r <= *g) {
|
||||
if(*g <= *b) {
|
||||
setSaturationComponents(r, g, b, s);
|
||||
} else if(*r <= *b) {
|
||||
setSaturationComponents(r, b, g, s);
|
||||
} else {
|
||||
setSaturationComponents(b, r, g, s);
|
||||
}
|
||||
} else if(*r <= *b) {
|
||||
setSaturationComponents(g, r, b, s);
|
||||
} else if(*g <= *b) {
|
||||
setSaturationComponents(g, b, r, s);
|
||||
} else {
|
||||
setSaturationComponents(b, g, r, s);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void clipColor(int* r, int* g, int* b) {
|
||||
int L = Lum(*r, *g, *b);
|
||||
int n = minimum(*r, *g, *b);
|
||||
int x = maximum(*r, *g, *b);
|
||||
if(n < 0) {
|
||||
*r = L + (((*r - L) * L) / (L - n));
|
||||
*g = L + (((*g - L) * L) / (L - n));
|
||||
*b = L + (((*b - L) * L) / (L - n));
|
||||
}
|
||||
|
||||
if(x > 255) {
|
||||
*r = L + (((*r - L) * (255 - L)) / (x - L));
|
||||
*g = L + (((*g - L) * (255 - L)) / (x - L));
|
||||
*b = L + (((*b - L) * (255 - L)) / (x - L));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetLum(int* r, int* g, int* b, int l) {
|
||||
int d = l - Lum(*r, *g, *b);
|
||||
*r += d;
|
||||
*g += d;
|
||||
*b += d;
|
||||
|
||||
clipColor(r, g, b);
|
||||
}
|
||||
|
||||
// non-separable blend modes are done in non-premultiplied alpha
|
||||
#define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
|
||||
clamp_div255round(sc * (255 - da) + dc * (255 - sa) + clamp_div255round(sa * da) * blendval)
|
||||
|
||||
// kHue_Mode
|
||||
// B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
|
||||
// Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
|
||||
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);
|
||||
int Sr, Sg, Sb;
|
||||
|
||||
if(sa && da) {
|
||||
Sr = SkMulDiv255Round(sr, sa);
|
||||
Sg = SkMulDiv255Round(sg, sa);
|
||||
Sb = SkMulDiv255Round(sb, sa);
|
||||
int Dr = SkMulDiv255Round(dr, da);
|
||||
int Dg = SkMulDiv255Round(dg, da);
|
||||
int Db = SkMulDiv255Round(db, da);
|
||||
SetSat(&Sr, &Sg, &Sb, Sat(Dr, Dg, Db));
|
||||
SetLum(&Sr, &Sg, &Sb, Lum(Dr, Dg, Db));
|
||||
} else {
|
||||
Sr = 0;
|
||||
Sg = 0;
|
||||
Sb = 0;
|
||||
}
|
||||
|
||||
int a = srcover_byte(sa, da);
|
||||
int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
|
||||
int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
|
||||
int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
|
||||
return SkPackARGB32(a, r, g, b);
|
||||
}
|
||||
|
||||
// kSaturation_Mode
|
||||
// B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
|
||||
// Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
|
||||
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);
|
||||
int Dr, Dg, Db;
|
||||
|
||||
if(sa && da) {
|
||||
int Sr = SkMulDiv255Round(sr, sa);
|
||||
int Sg = SkMulDiv255Round(sg, sa);
|
||||
int Sb = SkMulDiv255Round(sb, sa);
|
||||
Dr = SkMulDiv255Round(dr, da);
|
||||
Dg = SkMulDiv255Round(dg, da);
|
||||
Db = SkMulDiv255Round(db, da);
|
||||
int LumD = Lum(Dr, Dg, Db);
|
||||
SetSat(&Dr, &Dg, &Db, Sat(Sr, Sg, Sb));
|
||||
SetLum(&Dr, &Dg, &Db, LumD);
|
||||
} else {
|
||||
Dr = 0;
|
||||
Dg = 0;
|
||||
Db = 0;
|
||||
}
|
||||
|
||||
int a = srcover_byte(sa, da);
|
||||
int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
|
||||
int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
|
||||
int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
|
||||
return SkPackARGB32(a, r, g, b);
|
||||
}
|
||||
|
||||
// kColor_Mode
|
||||
// B(Cb, Cs) = SetLum(Cs, Lum(Cb))
|
||||
// Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
|
||||
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);
|
||||
int Sr, Sg, Sb;
|
||||
|
||||
if(sa && da) {
|
||||
Sr = SkMulDiv255Round(sr, sa);
|
||||
Sg = SkMulDiv255Round(sg, sa);
|
||||
Sb = SkMulDiv255Round(sb, sa);
|
||||
int Dr = SkMulDiv255Round(dr, da);
|
||||
int Dg = SkMulDiv255Round(dg, da);
|
||||
int Db = SkMulDiv255Round(db, da);
|
||||
SetLum(&Sr, &Sg, &Sb, Lum(Dr, Dg, Db));
|
||||
} else {
|
||||
Sr = 0;
|
||||
Sg = 0;
|
||||
Sb = 0;
|
||||
}
|
||||
|
||||
int a = srcover_byte(sa, da);
|
||||
int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
|
||||
int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
|
||||
int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
|
||||
return SkPackARGB32(a, r, g, b);
|
||||
}
|
||||
|
||||
// kLuminosity_Mode
|
||||
// B(Cb, Cs) = SetLum(Cb, Lum(Cs))
|
||||
// Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
|
||||
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);
|
||||
int Dr, Dg, Db;
|
||||
|
||||
if(sa && da) {
|
||||
int Sr = SkMulDiv255Round(sr, sa);
|
||||
int Sg = SkMulDiv255Round(sg, sa);
|
||||
int Sb = SkMulDiv255Round(sb, sa);
|
||||
Dr = SkMulDiv255Round(dr, da);
|
||||
Dg = SkMulDiv255Round(dg, da);
|
||||
Db = SkMulDiv255Round(db, da);
|
||||
SetLum(&Dr, &Dg, &Db, Lum(Sr, Sg, Sb));
|
||||
} else {
|
||||
Dr = 0;
|
||||
Dg = 0;
|
||||
Db = 0;
|
||||
}
|
||||
|
||||
int a = srcover_byte(sa, da);
|
||||
int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
|
||||
int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
|
||||
int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
|
||||
return SkPackARGB32(a, r, g, b);
|
||||
}
|
||||
|
||||
|
||||
struct ProcCoeff {
|
||||
SkXfermodeProc fProc;
|
||||
SkXfermode::Coeff fSC;
|
||||
@ -466,6 +693,10 @@ static const ProcCoeff gProcCoeffs[] = {
|
||||
{ difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
|
||||
{ exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
|
||||
{ multiply_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 },
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -1264,6 +1495,11 @@ static const Proc16Rec gModeProcs16[] = {
|
||||
{ NULL, NULL, NULL }, // softlight
|
||||
{ NULL, NULL, NULL }, // difference
|
||||
{ NULL, NULL, NULL }, // exclusion
|
||||
{ NULL, NULL, NULL }, // multiply
|
||||
{ NULL, NULL, NULL }, // hue
|
||||
{ NULL, NULL, NULL }, // saturation
|
||||
{ NULL, NULL, NULL }, // color
|
||||
{ NULL, NULL, NULL }, // luminosity
|
||||
};
|
||||
|
||||
SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
|
||||
|
@ -14,7 +14,9 @@
|
||||
static const char* blend_mode_from_xfermode(SkXfermode::Mode mode) {
|
||||
switch (mode) {
|
||||
case SkXfermode::kSrcOver_Mode: return "Normal";
|
||||
case SkXfermode::kModulate_Mode: return "Multiply";
|
||||
// kModulate is not really like multipy but similar most of the time.
|
||||
case SkXfermode::kModulate_Mode:
|
||||
case SkXfermode::kMultiply_Mode: return "Multiply";
|
||||
case SkXfermode::kScreen_Mode: return "Screen";
|
||||
case SkXfermode::kOverlay_Mode: return "Overlay";
|
||||
case SkXfermode::kDarken_Mode: return "Darken";
|
||||
@ -25,6 +27,10 @@ static const char* blend_mode_from_xfermode(SkXfermode::Mode mode) {
|
||||
case SkXfermode::kSoftLight_Mode: return "SoftLight";
|
||||
case SkXfermode::kDifference_Mode: return "Difference";
|
||||
case SkXfermode::kExclusion_Mode: return "Exclusion";
|
||||
case SkXfermode::kHue_Mode: return "Hue";
|
||||
case SkXfermode::kSaturation_Mode: return "Saturation";
|
||||
case SkXfermode::kColor_Mode: return "Color";
|
||||
case SkXfermode::kLuminosity_Mode: return "Luminosity";
|
||||
|
||||
// These are handled in SkPDFDevice::setUpContentEntry.
|
||||
case SkXfermode::kClear_Mode:
|
||||
@ -42,7 +48,6 @@ static const char* blend_mode_from_xfermode(SkXfermode::Mode mode) {
|
||||
case SkXfermode::kDstATop_Mode:
|
||||
case SkXfermode::kXor_Mode:
|
||||
case SkXfermode::kPlus_Mode:
|
||||
case SkXfermode::kMultiply_Mode:
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user