| Index: src/effects/SkLumaColorFilter.cpp
|
| diff --git a/src/effects/SkLumaColorFilter.cpp b/src/effects/SkLumaColorFilter.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c9f1fb02c3a17d49c841ee69dcf38a6f29d75541
|
| --- /dev/null
|
| +++ b/src/effects/SkLumaColorFilter.cpp
|
| @@ -0,0 +1,152 @@
|
| +/*
|
| + * 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 "SkLumaColorFilter.h"
|
| +
|
| +#include "SkColorPriv.h"
|
| +#include "SkString.h"
|
| +#include "SkUnPreMultiply.h"
|
| +
|
| +#if SK_SUPPORT_GPU
|
| +#include "gl/GrGLEffect.h"
|
| +#include "GrContext.h"
|
| +#include "GrTBackendEffectFactory.h"
|
| +#endif
|
| +
|
| +void SkLumaColorFilter::filterSpan(const SkPMColor src[], int count,
|
| + SkPMColor dst[]) const {
|
| + const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
|
| +
|
| + for (int i = 0; i < count; ++i) {
|
| + SkPMColor c = src[i];
|
| +
|
| + unsigned r = SkGetPackedR32(c);
|
| + unsigned g = SkGetPackedG32(c);
|
| + unsigned b = SkGetPackedB32(c);
|
| + unsigned a = SkGetPackedA32(c);
|
| +
|
| + // No need to do anything for white (luminance == 1.0)
|
| + if (a != r || a != g || a != b) {
|
| + /*
|
| + * To avoid un-premultiplying multiple components, we can start
|
| + * with the luminance computed in PM space:
|
| + *
|
| + * Lum = i * (r / a) + j * (g / a) + k * (b / a)
|
| + * Lum = (i * r + j * g + k * b) / a
|
| + * Lum = Lum'(PM) / a
|
| + *
|
| + * Then the filter function is:
|
| + *
|
| + * C' = [ Lum * a, Lum * r, Lum * g, Lum * b ]
|
| + *
|
| + * which is equivalent to:
|
| + *
|
| + * C' = [ Lum'(PM), Lum * r, Lum * g, Lum * b ]
|
| + */
|
| + unsigned pm_lum = SkComputeLuminance(r, g, b);
|
| + unsigned lum = SkUnPreMultiply::ApplyScale(table[a], pm_lum);
|
| +
|
| + c = SkPackARGB32(pm_lum,
|
| + SkMulDiv255Round(r, lum),
|
| + SkMulDiv255Round(g, lum),
|
| + SkMulDiv255Round(b, lum));
|
| + }
|
| +
|
| + dst[i] = c;
|
| + }
|
| +}
|
| +
|
| +SkColorFilter* SkLumaColorFilter::Create() {
|
| + return SkNEW(SkLumaColorFilter);
|
| +}
|
| +
|
| +SkLumaColorFilter::SkLumaColorFilter()
|
| + : INHERITED() {
|
| +}
|
| +
|
| +SkLumaColorFilter::SkLumaColorFilter(SkFlattenableReadBuffer& buffer)
|
| + : INHERITED(buffer) {
|
| +}
|
| +
|
| +void SkLumaColorFilter::flatten(SkFlattenableWriteBuffer&) const {
|
| +}
|
| +
|
| +#ifdef SK_DEVELOPER
|
| +void SkLumaColorFilter::toString(SkString* str) const {
|
| + str->append("SkLumaColorFilter ");
|
| +}
|
| +#endif
|
| +
|
| +#if SK_SUPPORT_GPU
|
| +class LumaColorFilterEffect : public GrEffect {
|
| +public:
|
| + static GrEffectRef* Create() {
|
| + AutoEffectUnref effect(SkNEW(LumaColorFilterEffect));
|
| + return CreateEffectRef(effect);
|
| + }
|
| +
|
| + static const char* Name() { return "Luminance-to-Alpha"; }
|
| +
|
| + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
|
| + return GrTBackendEffectFactory<LumaColorFilterEffect>::getInstance();
|
| + }
|
| +
|
| + virtual void getConstantColorComponents(GrColor* color,
|
| + uint32_t* validFlags) const SK_OVERRIDE {
|
| + *validFlags = 0;
|
| + }
|
| +
|
| + class GLEffect : public GrGLEffect {
|
| + public:
|
| + GLEffect(const GrBackendEffectFactory& factory,
|
| + const GrDrawEffect&)
|
| + : INHERITED(factory) {
|
| + }
|
| +
|
| + static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) {
|
| + // this class always generates the same code.
|
| + return 0;
|
| + }
|
| +
|
| + virtual void emitCode(GrGLShaderBuilder* builder,
|
| + const GrDrawEffect&,
|
| + EffectKey,
|
| + const char* outputColor,
|
| + const char* inputColor,
|
| + const TransformedCoordsArray&,
|
| + const TextureSamplerArray&) SK_OVERRIDE {
|
| + if (NULL == inputColor) {
|
| + inputColor = GrGLSLOnesVecf(4);
|
| + }
|
| +
|
| + // The max() is to guard against 0 / 0 during unpremul when the incoming color is
|
| + // transparent black.
|
| + builder->fsCodeAppendf("\tfloat nonZeroAlpha = max(%s.a, 0.00001);\n", inputColor);
|
| + builder->fsCodeAppendf("\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,
|
| + inputColor);
|
| + builder->fsCodeAppendf("\t%s = vec4(%s.rgb * luma / nonZeroAlpha, luma);\n",
|
| + outputColor, inputColor);
|
| +
|
| + }
|
| +
|
| + private:
|
| + typedef GrGLEffect INHERITED;
|
| + };
|
| +
|
| +private:
|
| + virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE {
|
| + return true;
|
| + }
|
| +};
|
| +
|
| +GrEffectRef* SkLumaColorFilter::asNewEffect(GrContext*) const {
|
| + return LumaColorFilterEffect::Create();
|
| +}
|
| +#endif
|
|
|