| Index: src/core/SkXfermode.cpp
|
| ===================================================================
|
| --- src/core/SkXfermode.cpp (revision 7962)
|
| +++ src/core/SkXfermode.cpp (working copy)
|
| @@ -431,6 +431,233 @@
|
| 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 @@
|
| { 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 @@
|
| { 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) {
|
|
|