diff options
author | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-08-23 13:13:12 +0000 |
---|---|---|
committer | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-08-23 13:13:12 +0000 |
commit | eaa77979908d1b9fff00b73d02c4576901448933 (patch) | |
tree | ebd7aacc3b4f02ac7935573deb8c20a260d00302 /src | |
parent | 44a77c8158016996f79eb0ac98bb85996174bb89 (diff) |
Add luminance mask transfer modes.
This adds kSrcInLum_Mode and kDstInLum_Mode, to support CSS and SVG luminance masks (http://www.w3.org/TR/css-masking/#MaskValues , http://www.w3.org/TR/SVG/masking.html#Masking ).
The transfer coefficient is computed according to http://www.w3.org/TR/2011/REC-SVG11-20110816/filters.html#feColorMatrixElement "luminance-to-alpha":
luma = 0.2125 * r + 0.7154 * g + 0.0721 * b
R=bsalomon@google.com, reed@google.com, robertphillips@google.com, vandebo@chromium.org
Author: fmalita@chromium.org
Review URL: https://chromiumcodereview.appspot.com/22918012
git-svn-id: http://skia.googlecode.com/svn/trunk@10887 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/effects/SkLumaXfermode.cpp | 221 | ||||
-rw-r--r-- | src/ports/SkGlobalInitialization_chromium.cpp | 2 | ||||
-rw-r--r-- | src/ports/SkGlobalInitialization_default.cpp | 2 |
3 files changed, 225 insertions, 0 deletions
diff --git a/src/effects/SkLumaXfermode.cpp b/src/effects/SkLumaXfermode.cpp new file mode 100644 index 0000000000..df0a663c3b --- /dev/null +++ b/src/effects/SkLumaXfermode.cpp @@ -0,0 +1,221 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkLumaXfermode.h" +#include "SkColorPriv.h" +#include "SkFlattenableBuffers.h" +#include "SkString.h" + +#if SK_SUPPORT_GPU +#include "gl/GrGLEffect.h" +#include "gl/GrGLEffectMatrix.h" +#include "GrContext.h" +#include "GrTBackendEffectFactory.h" +#endif + +static inline SkPMColor luma_proc(const SkPMColor a, const SkPMColor b) { + unsigned luma = SkComputeLuminance(SkGetPackedR32(b), + SkGetPackedG32(b), + SkGetPackedB32(b)); + return SkAlphaMulQ(a, SkAlpha255To256(luma)); +} + +template <typename T> +static inline const T* lumaOpA(SkXfermode::Mode mode, + const T* src, const T* dst) { + return SkXfermode::kSrcIn_Mode == mode ? src : dst; +} + +template <typename T> +static inline const T* lumaOpB(SkXfermode::Mode mode, + const T* src, const T* dst) { + return SkXfermode::kSrcIn_Mode == mode ? dst : src; +} + +SkXfermode* SkLumaMaskXfermode::Create(SkXfermode::Mode mode) { + if (kSrcIn_Mode == mode || kDstIn_Mode == mode) { + return SkNEW_ARGS(SkLumaMaskXfermode, (mode)); + } + return NULL; +} + +SkLumaMaskXfermode::SkLumaMaskXfermode(SkXfermode::Mode mode) + : fMode(mode) { + SkASSERT(kSrcIn_Mode == mode || kDstIn_Mode == mode); +} + +SkLumaMaskXfermode::SkLumaMaskXfermode(SkFlattenableReadBuffer& buffer) + : INHERITED(buffer) + , fMode((SkXfermode::Mode)buffer.readUInt()) { + SkASSERT(kSrcIn_Mode == fMode || kDstIn_Mode == fMode); +} + +void SkLumaMaskXfermode::flatten(SkFlattenableWriteBuffer& buffer) const { + INHERITED::flatten(buffer); + buffer.writeUInt(fMode); +} + +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); +} + +void SkLumaMaskXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], + int count, const SkAlpha aa[]) const { + const SkPMColor* a = lumaOpA<SkPMColor>(fMode, src, dst); + const SkPMColor* b = lumaOpB<SkPMColor>(fMode, src, dst); + + if (aa) { + for (int i = 0; i < count; ++i) { + unsigned cov = aa[i]; + if (cov) { + unsigned resC = luma_proc(a[i], b[i]); + if (cov < 255) { + resC = SkAlphaMulQ(resC, SkAlpha255To256(cov)); + } + dst[i] = resC; + } + } + } else { + for (int i = 0; i < count; ++i) { + dst[i] = luma_proc(a[i], b[i]); + } + } +} + +#ifdef SK_DEVELOPER +void SkLumaMaskXfermode::toString(SkString* str) const { + str->printf("SkLumaMaskXfermode: mode: %s", + fMode == kSrcIn_Mode ? "SRC_IN" : "DST_IN"); +} +#endif + +#if SK_SUPPORT_GPU +////////////////////////////////////////////////////////////////////////////// + +class GrGLLumaMaskEffect : public GrGLEffect { +public: + GrGLLumaMaskEffect(const GrBackendEffectFactory&, const GrDrawEffect&); + virtual ~GrGLLumaMaskEffect(); + + virtual void emitCode(GrGLShaderBuilder*, + const GrDrawEffect&, + EffectKey, + const char* outputColor, + const char* inputColor, + const TextureSamplerArray&) SK_OVERRIDE; + + static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); + +private: + typedef GrGLEffect INHERITED; +}; + +class GrLumaMaskEffect : public GrEffect { +public: + static GrEffectRef* Create(SkXfermode::Mode mode) { + AutoEffectUnref effect(SkNEW_ARGS(GrLumaMaskEffect, (mode))); + return CreateEffectRef(effect); + } + + virtual ~GrLumaMaskEffect(); + + typedef GrGLLumaMaskEffect GLEffect; + static const char* Name() { return "LumaMask"; } + + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; + virtual void getConstantColorComponents(GrColor*, uint32_t*) const SK_OVERRIDE; + + SkXfermode::Mode getMode() const { return fMode; } + +private: + GrLumaMaskEffect(SkXfermode::Mode); + + virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; + + const SkXfermode::Mode fMode; +}; + +////////////////////////////////////////////////////////////////////////////// + +GrGLLumaMaskEffect::GrGLLumaMaskEffect(const GrBackendEffectFactory& factory, + const GrDrawEffect&) + : INHERITED(factory) { +} + +GrGLLumaMaskEffect::~GrGLLumaMaskEffect() { +} + +void GrGLLumaMaskEffect::emitCode(GrGLShaderBuilder* builder, + const GrDrawEffect& effect, + EffectKey key, + const char* outputColor, + const char* inputColor, + const TextureSamplerArray& samplers) { + + const GrLumaMaskEffect& lumaEffect = effect.castEffect<GrLumaMaskEffect>(); + const char* dstColor = builder->dstColor(); + SkASSERT(NULL != dstColor); + if (NULL == inputColor) { + inputColor = GrGLSLOnesVecf(4); + } + + const char *opA = lumaOpA<char>(lumaEffect.getMode(), inputColor, dstColor); + const char *opB = lumaOpB<char>(lumaEffect.getMode(), inputColor, dstColor); + + builder->fsCodeAppendf("\t\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb); \n", + SK_ITU_BT709_LUM_COEFF_R, + SK_ITU_BT709_LUM_COEFF_G, + SK_ITU_BT709_LUM_COEFF_B, + opB); + builder->fsCodeAppendf("\t\t%s = %s * luma;\n", outputColor, opA); +} + +GrGLEffect::EffectKey GrGLLumaMaskEffect::GenKey(const GrDrawEffect& drawEffect, + const GrGLCaps&) { + const GrLumaMaskEffect& effect = drawEffect.castEffect<GrLumaMaskEffect>(); + return (EffectKey)effect.getMode(); +} + +////////////////////////////////////////////////////////////////////////////// + +GrLumaMaskEffect::GrLumaMaskEffect(SkXfermode::Mode mode) + : fMode(mode) { + this->setWillReadDstColor(); +} + +GrLumaMaskEffect::~GrLumaMaskEffect() { +} + +const GrBackendEffectFactory& GrLumaMaskEffect::getFactory() const { + return GrTBackendEffectFactory<GrLumaMaskEffect>::getInstance(); +} + +void GrLumaMaskEffect::getConstantColorComponents(GrColor*, uint32_t *validFlags) const { + *validFlags = 0; +} + +bool GrLumaMaskEffect::onIsEqual(const GrEffect& sBase) const { + return fMode == CastEffect<GrLumaMaskEffect>(sBase).fMode; +} + +////////////////////////////////////////////////////////////////////////////// + +bool SkLumaMaskXfermode::asNewEffectOrCoeff(GrContext*, GrEffectRef** effect, + Coeff*, Coeff*, + GrTexture* background) const { + // No background texture support. + if (effect && !background) { + *effect = GrLumaMaskEffect::Create(fMode); + return true; + } + + return false; +} + +#endif // SK_SUPPORT_GPU diff --git a/src/ports/SkGlobalInitialization_chromium.cpp b/src/ports/SkGlobalInitialization_chromium.cpp index d05af70995..ebdbffb7ca 100644 --- a/src/ports/SkGlobalInitialization_chromium.cpp +++ b/src/ports/SkGlobalInitialization_chromium.cpp @@ -15,6 +15,7 @@ #include "SkLayerDrawLooper.h" #include "SkMallocPixelRef.h" #include "SkXfermode.h" +#include "SkLumaXfermode.h" #include "SkMagnifierImageFilter.h" void SkFlattenable::InitializeFlattenables() { @@ -24,6 +25,7 @@ void SkFlattenable::InitializeFlattenables() { SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkCornerPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDashPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLayerDrawLooper) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLumaMaskXfermode) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMallocPixelRef) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMagnifierImageFilter) diff --git a/src/ports/SkGlobalInitialization_default.cpp b/src/ports/SkGlobalInitialization_default.cpp index 24edd31e65..05c3c4e146 100644 --- a/src/ports/SkGlobalInitialization_default.cpp +++ b/src/ports/SkGlobalInitialization_default.cpp @@ -46,6 +46,7 @@ #include "SkLayerRasterizer.h" #include "SkLerpXfermode.h" #include "SkLightingImageFilter.h" +#include "SkLumaXfermode.h" #include "SkMagnifierImageFilter.h" #include "SkMatrixConvolutionImageFilter.h" #include "SkMergeImageFilter.h" @@ -86,6 +87,7 @@ void SkFlattenable::InitializeFlattenables() { SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLayerDrawLooper) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLayerRasterizer) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLerpXfermode) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLumaMaskXfermode) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath1DPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(Sk2DPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLine2DPathEffect) |