aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-23 13:13:12 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-23 13:13:12 +0000
commiteaa77979908d1b9fff00b73d02c4576901448933 (patch)
treeebd7aacc3b4f02ac7935573deb8c20a260d00302 /src
parent44a77c8158016996f79eb0ac98bb85996174bb89 (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.cpp221
-rw-r--r--src/ports/SkGlobalInitialization_chromium.cpp2
-rw-r--r--src/ports/SkGlobalInitialization_default.cpp2
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)