Index: src/effects/SkLumaXfermode.cpp |
=================================================================== |
--- src/effects/SkLumaXfermode.cpp (revision 11192) |
+++ src/effects/SkLumaXfermode.cpp (working copy) |
@@ -17,7 +17,15 @@ |
#include "GrTBackendEffectFactory.h" |
#endif |
-static inline SkPMColor luma_proc(const SkPMColor a, const SkPMColor b) { |
+class SkLumaMaskXfermodeSrcOver : public SkLumaMaskXfermode { |
+public: |
+ SkLumaMaskXfermodeSrcOver(); |
+ |
+private: |
+ virtual SkPMColor lumaProc(const SkPMColor a, const SkPMColor b) const; |
+}; |
+ |
+SkPMColor SkLumaMaskXfermode::lumaProc(const SkPMColor a, const SkPMColor b) const { |
unsigned luma = SkComputeLuminance(SkGetPackedR32(b), |
SkGetPackedG32(b), |
SkGetPackedB32(b)); |
@@ -40,18 +48,22 @@ |
if (kSrcIn_Mode == mode || kDstIn_Mode == mode) { |
return SkNEW_ARGS(SkLumaMaskXfermode, (mode)); |
} |
+ if (kSrcOver_Mode == mode) { |
+ return SkNEW_ARGS(SkLumaMaskXfermodeSrcOver, ()); |
+ } |
+ |
return NULL; |
} |
SkLumaMaskXfermode::SkLumaMaskXfermode(SkXfermode::Mode mode) |
: fMode(mode) { |
- SkASSERT(kSrcIn_Mode == mode || kDstIn_Mode == mode); |
+ SkASSERT(kSrcIn_Mode == mode || kDstIn_Mode == mode || kSrcOver_Mode == mode); |
} |
SkLumaMaskXfermode::SkLumaMaskXfermode(SkFlattenableReadBuffer& buffer) |
: INHERITED(buffer) |
, fMode((SkXfermode::Mode)buffer.readUInt()) { |
- SkASSERT(kSrcIn_Mode == fMode || kDstIn_Mode == fMode); |
+ SkASSERT(kSrcIn_Mode == fMode || kDstIn_Mode == fMode || kSrcOver_Mode == fMode); |
} |
void SkLumaMaskXfermode::flatten(SkFlattenableWriteBuffer& buffer) const { |
@@ -62,7 +74,7 @@ |
SkPMColor SkLumaMaskXfermode::xferColor(SkPMColor src, SkPMColor dst) const { |
const SkPMColor* a = lumaOpA<SkPMColor>(fMode, &src, &dst); |
const SkPMColor* b = lumaOpB<SkPMColor>(fMode, &src, &dst); |
- return luma_proc(*a, *b); |
+ return this->lumaProc(*a, *b); |
} |
void SkLumaMaskXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], |
@@ -74,7 +86,7 @@ |
for (int i = 0; i < count; ++i) { |
unsigned cov = aa[i]; |
if (cov) { |
- unsigned resC = luma_proc(a[i], b[i]); |
+ unsigned resC = this->lumaProc(a[i], b[i]); |
if (cov < 255) { |
resC = SkFastFourByteInterp256(resC, dst[i], |
SkAlpha255To256(cov)); |
@@ -84,7 +96,7 @@ |
} |
} else { |
for (int i = 0; i < count; ++i) { |
- dst[i] = luma_proc(a[i], b[i]); |
+ dst[i] = this->lumaProc(a[i], b[i]); |
} |
} |
} |
@@ -96,6 +108,27 @@ |
} |
#endif |
+SkLumaMaskXfermodeSrcOver::SkLumaMaskXfermodeSrcOver() : SkLumaMaskXfermode(kSrcOver_Mode) {} |
+ |
+SkPMColor SkLumaMaskXfermodeSrcOver::lumaProc(const SkPMColor a, const SkPMColor b) const { |
+ unsigned luma = SkComputeLuminance(SkGetPackedR32(b), |
+ SkGetPackedG32(b), |
+ SkGetPackedB32(b)); |
+ |
+ unsigned oldAlpha = SkGetPackedA32(b); |
+ unsigned newR = 0, newG = 0, newB = 0; |
+ |
+ if (oldAlpha > 0) { |
+ newR = SkGetPackedR32(b) * 255 / oldAlpha; |
+ newG = SkGetPackedG32(b) * 255 / oldAlpha; |
+ newB = SkGetPackedB32(b) * 255 / oldAlpha; |
+ } |
+ |
+ SkPMColor colorB = SkPremultiplyARGBInline(luma, newR, newG, newB); |
+ |
+ return SkPMSrcOver(colorB, a); |
+} |
+ |
#if SK_SUPPORT_GPU |
////////////////////////////////////////////////////////////////////////////// |
@@ -174,7 +207,12 @@ |
SK_ITU_BT709_LUM_COEFF_G, |
SK_ITU_BT709_LUM_COEFF_B, |
opB); |
- builder->fsCodeAppendf("\t\t%s = %s * luma;\n", outputColor, opA); |
+ if (SkXfermode::kSrcOver_Mode == lumaEffect.getMode()) { |
+ builder->fsCodeAppendf("\t\tvec4 newB = %s;\n\t\tif (newB.a > 0.0) { newB *= luma / newB.a; }\n\t\tnewB.a = luma;\n", opB); |
+ builder->fsCodeAppendf("\t\t%s = newB + %s * (1.0 - luma); \n", outputColor, opA); |
+ } else { |
+ builder->fsCodeAppendf("\t\t%s = %s * luma;\n", outputColor, opA); |
+ } |
} |
GrGLEffect::EffectKey GrGLLumaMaskEffect::GenKey(const GrDrawEffect& drawEffect, |