/*
 * 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 "SkAlphaThresholdFilter.h"
#include "SkBitmap.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"
#include "SkRegion.h"

class SK_API SkAlphaThresholdFilterImpl : public SkImageFilter {
public:
    SkAlphaThresholdFilterImpl(const SkRegion& region, SkScalar innerThreshold,
                               SkScalar outerThreshold, SkImageFilter* input);

    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAlphaThresholdFilterImpl)

protected:
    explicit SkAlphaThresholdFilterImpl(SkReadBuffer& buffer);
    virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;

    virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
                               SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE;
#if SK_SUPPORT_GPU
    virtual bool asNewEffect(GrEffect** effect, GrTexture* texture,
                             const SkMatrix& matrix, const SkIRect& bounds) const SK_OVERRIDE;
#endif

private:
    SkRegion fRegion;
    SkScalar fInnerThreshold;
    SkScalar fOuterThreshold;
    typedef SkImageFilter INHERITED;
};

SkImageFilter* SkAlphaThresholdFilter::Create(const SkRegion& region,
                                              SkScalar innerThreshold,
                                              SkScalar outerThreshold,
                                              SkImageFilter* input) {
    return SkNEW_ARGS(SkAlphaThresholdFilterImpl, (region, innerThreshold, outerThreshold, input));
}

#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "GrCoordTransform.h"
#include "GrEffect.h"
#include "gl/GrGLEffect.h"
#include "gl/GrGLShaderBuilder.h"
#include "GrTBackendEffectFactory.h"
#include "GrTextureAccess.h"

#include "SkGr.h"

class GrGLAlphaThresholdEffect;

class AlphaThresholdEffect : public GrEffect {

public:
    static GrEffect* Create(GrTexture* texture,
                            GrTexture* maskTexture,
                            float innerThreshold,
                            float outerThreshold) {
        return SkNEW_ARGS(AlphaThresholdEffect, (texture,
                                                 maskTexture,
                                                 innerThreshold,
                                                 outerThreshold));
    }

    virtual ~AlphaThresholdEffect() {};

    static const char* Name() { return "Alpha Threshold"; }

    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
    virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;

    float innerThreshold() const { return fInnerThreshold; }
    float outerThreshold() const { return fOuterThreshold; }

    typedef GrGLAlphaThresholdEffect GLEffect;

private:
    AlphaThresholdEffect(GrTexture* texture,
                         GrTexture* maskTexture,
                         float innerThreshold,
                         float outerThreshold)
        : fInnerThreshold(innerThreshold)
        , fOuterThreshold(outerThreshold)
        , fImageCoordTransform(kLocal_GrCoordSet, MakeDivByTextureWHMatrix(texture), texture)
        , fImageTextureAccess(texture)
        , fMaskCoordTransform(kLocal_GrCoordSet, MakeDivByTextureWHMatrix(maskTexture), maskTexture)
        , fMaskTextureAccess(maskTexture) {
        this->addCoordTransform(&fImageCoordTransform);
        this->addTextureAccess(&fImageTextureAccess);
        this->addCoordTransform(&fMaskCoordTransform);
        this->addTextureAccess(&fMaskTextureAccess);
    }

    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;

    GR_DECLARE_EFFECT_TEST;

    float fInnerThreshold;
    float fOuterThreshold;
    GrCoordTransform fImageCoordTransform;
    GrTextureAccess  fImageTextureAccess;
    GrCoordTransform fMaskCoordTransform;
    GrTextureAccess  fMaskTextureAccess;

    typedef GrEffect INHERITED;
};

class GrGLAlphaThresholdEffect : public GrGLEffect {
public:
    GrGLAlphaThresholdEffect(const GrBackendEffectFactory&, const GrDrawEffect&);

    virtual void emitCode(GrGLShaderBuilder*,
                          const GrDrawEffect&,
                          const GrEffectKey&,
                          const char* outputColor,
                          const char* inputColor,
                          const TransformedCoordsArray&,
                          const TextureSamplerArray&) SK_OVERRIDE;

    virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;

private:

    GrGLUniformManager::UniformHandle       fInnerThresholdVar;
    GrGLUniformManager::UniformHandle       fOuterThresholdVar;

    typedef GrGLEffect INHERITED;
};

GrGLAlphaThresholdEffect::GrGLAlphaThresholdEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
    : INHERITED(factory) {
}

void GrGLAlphaThresholdEffect::emitCode(GrGLShaderBuilder* builder,
                                        const GrDrawEffect&,
                                        const GrEffectKey& key,
                                        const char* outputColor,
                                        const char* inputColor,
                                        const TransformedCoordsArray& coords,
                                        const TextureSamplerArray& samplers) {
    SkString coords2D = builder->ensureFSCoords2D(coords, 0);
    SkString maskCoords2D = builder->ensureFSCoords2D(coords, 1);
    fInnerThresholdVar = builder->addUniform(
        GrGLShaderBuilder::kFragment_Visibility,
        kFloat_GrSLType, "inner_threshold");
    fOuterThresholdVar = builder->addUniform(
        GrGLShaderBuilder::kFragment_Visibility,
        kFloat_GrSLType, "outer_threshold");

    builder->fsCodeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
    builder->fsCodeAppendf("\t\tvec2 mask_coord = %s;\n", maskCoords2D.c_str());
    builder->fsCodeAppend("\t\tvec4 input_color = ");
    builder->fsAppendTextureLookup(samplers[0], "coord");
    builder->fsCodeAppend(";\n");
    builder->fsCodeAppend("\t\tvec4 mask_color = ");
    builder->fsAppendTextureLookup(samplers[1], "mask_coord");
    builder->fsCodeAppend(";\n");

    builder->fsCodeAppendf("\t\tfloat inner_thresh = %s;\n",
                           builder->getUniformCStr(fInnerThresholdVar));
    builder->fsCodeAppendf("\t\tfloat outer_thresh = %s;\n",
                           builder->getUniformCStr(fOuterThresholdVar));
    builder->fsCodeAppend("\t\tfloat mask = mask_color.a;\n");

    builder->fsCodeAppend("vec4 color = input_color;\n");
    builder->fsCodeAppend("\t\tif (mask < 0.5) {\n"
                          "\t\t\tif (color.a > outer_thresh) {\n"
                          "\t\t\t\tfloat scale = outer_thresh / color.a;\n"
                          "\t\t\t\tcolor.rgb *= scale;\n"
                          "\t\t\t\tcolor.a = outer_thresh;\n"
                          "\t\t\t}\n"
                          "\t\t} else if (color.a < inner_thresh) {\n"
                          "\t\t\tfloat scale = inner_thresh / max(0.001, color.a);\n"
                          "\t\t\tcolor.rgb *= scale;\n"
                          "\t\t\tcolor.a = inner_thresh;\n"
                          "\t\t}\n");

    builder->fsCodeAppendf("%s = %s;\n", outputColor,
                           (GrGLSLExpr4(inputColor) * GrGLSLExpr4("color")).c_str());
}

void GrGLAlphaThresholdEffect::setData(const GrGLUniformManager& uman,
                                  const GrDrawEffect& drawEffect) {
    const AlphaThresholdEffect& alpha_threshold =
        drawEffect.castEffect<AlphaThresholdEffect>();
    uman.set1f(fInnerThresholdVar, alpha_threshold.innerThreshold());
    uman.set1f(fOuterThresholdVar, alpha_threshold.outerThreshold());
}

/////////////////////////////////////////////////////////////////////

GR_DEFINE_EFFECT_TEST(AlphaThresholdEffect);

GrEffect* AlphaThresholdEffect::TestCreate(SkRandom* random,
                                           GrContext* context,
                                           const GrDrawTargetCaps&,
                                           GrTexture** textures) {
    GrTexture* bmpTex = textures[GrEffectUnitTest::kSkiaPMTextureIdx];
    GrTexture* maskTex = textures[GrEffectUnitTest::kAlphaTextureIdx];
    float inner_thresh = random->nextUScalar1();
    float outer_thresh = random->nextUScalar1();
    return AlphaThresholdEffect::Create(bmpTex, maskTex, inner_thresh, outer_thresh);
}

///////////////////////////////////////////////////////////////////////////////

const GrBackendEffectFactory& AlphaThresholdEffect::getFactory() const {
    return GrTBackendEffectFactory<AlphaThresholdEffect>::getInstance();
}

bool AlphaThresholdEffect::onIsEqual(const GrEffect& sBase) const {
    const AlphaThresholdEffect& s = CastEffect<AlphaThresholdEffect>(sBase);
    return (this->texture(0) == s.texture(0) &&
            this->fInnerThreshold == s.fInnerThreshold &&
            this->fOuterThreshold == s.fOuterThreshold);
}

void AlphaThresholdEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
    if ((*validFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(*color) &&
        GrPixelConfigIsOpaque(this->texture(0)->config())) {
        *validFlags = kA_GrColorComponentFlag;
    } else {
        *validFlags = 0;
    }
}

#endif

SkAlphaThresholdFilterImpl::SkAlphaThresholdFilterImpl(SkReadBuffer& buffer)
  : INHERITED(1, buffer) {
    fInnerThreshold = buffer.readScalar();
    fOuterThreshold = buffer.readScalar();
    buffer.readRegion(&fRegion);
}

SkAlphaThresholdFilterImpl::SkAlphaThresholdFilterImpl(const SkRegion& region,
                                                       SkScalar innerThreshold,
                                                       SkScalar outerThreshold,
                                                       SkImageFilter* input)
    : INHERITED(1, &input)
    , fRegion(region)
    , fInnerThreshold(innerThreshold)
    , fOuterThreshold(outerThreshold) {
}

#if SK_SUPPORT_GPU
bool SkAlphaThresholdFilterImpl::asNewEffect(GrEffect** effect, GrTexture* texture,
                                             const SkMatrix& in_matrix, const SkIRect&) const {
    if (effect) {
        GrContext* context = texture->getContext();
        GrTextureDesc maskDesc;
        if (context->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
            maskDesc.fConfig = kAlpha_8_GrPixelConfig;
        } else {
            maskDesc.fConfig = kRGBA_8888_GrPixelConfig;
        }
        maskDesc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
        // Add one pixel of border to ensure that clamp mode will be all zeros
        // the outside.
        maskDesc.fWidth = texture->width();
        maskDesc.fHeight = texture->height();
        GrAutoScratchTexture ast(context, maskDesc, GrContext::kApprox_ScratchTexMatch);
        GrTexture*  maskTexture = ast.texture();
        if (NULL == maskTexture) {
            return false;
        }

        {
            GrContext::AutoRenderTarget art(context, ast.texture()->asRenderTarget());
            GrPaint grPaint;
            grPaint.setBlendFunc(kOne_GrBlendCoeff, kZero_GrBlendCoeff);
            SkRegion::Iterator iter(fRegion);
            context->clear(NULL, 0x0, true);

            SkMatrix old_matrix = context->getMatrix();
            context->setMatrix(in_matrix);

            while (!iter.done()) {
                SkRect rect = SkRect::Make(iter.rect());
                context->drawRect(grPaint, rect);
                iter.next();
            }
            context->setMatrix(old_matrix);
        }

        *effect = AlphaThresholdEffect::Create(texture,
                                               maskTexture,
                                               fInnerThreshold,
                                               fOuterThreshold);
    }
    return true;
}
#endif

void SkAlphaThresholdFilterImpl::flatten(SkWriteBuffer& buffer) const {
    this->INHERITED::flatten(buffer);
    buffer.writeScalar(fInnerThreshold);
    buffer.writeScalar(fOuterThreshold);
    buffer.writeRegion(fRegion);
}

bool SkAlphaThresholdFilterImpl::onFilterImage(Proxy*, const SkBitmap& src,
                                               const Context& ctx, SkBitmap* dst,
                                               SkIPoint* offset) const {
    SkASSERT(src.colorType() == kN32_SkColorType);

    if (src.colorType() != kN32_SkColorType) {
        return false;
    }

    SkMatrix localInverse;
    if (!ctx.ctm().invert(&localInverse)) {
        return false;
    }

    SkAutoLockPixels alp(src);
    SkASSERT(src.getPixels());
    if (!src.getPixels() || src.width() <= 0 || src.height() <= 0) {
        return false;
    }

    if (!dst->allocPixels(src.info())) {
        return false;
    }

    U8CPU innerThreshold = (U8CPU)(fInnerThreshold * 0xFF);
    U8CPU outerThreshold = (U8CPU)(fOuterThreshold * 0xFF);
    SkColor* sptr = src.getAddr32(0, 0);
    SkColor* dptr = dst->getAddr32(0, 0);
    int width = src.width(), height = src.height();
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            const SkColor& source = sptr[y * width + x];
            SkColor output_color(source);
            SkPoint position;
            localInverse.mapXY((SkScalar)x, (SkScalar)y, &position);
            if (fRegion.contains((int32_t)position.x(), (int32_t)position.y())) {
                if (SkColorGetA(source) < innerThreshold) {
                    U8CPU alpha = SkColorGetA(source);
                    if (alpha == 0)
                        alpha = 1;
                    float scale = (float)innerThreshold / alpha;
                    output_color = SkColorSetARGB(innerThreshold,
                                                  (U8CPU)(SkColorGetR(source) * scale),
                                                  (U8CPU)(SkColorGetG(source) * scale),
                                                  (U8CPU)(SkColorGetB(source) * scale));
                }
            } else {
                if (SkColorGetA(source) > outerThreshold) {
                    float scale = (float)outerThreshold / SkColorGetA(source);
                    output_color = SkColorSetARGB(outerThreshold,
                                                  (U8CPU)(SkColorGetR(source) * scale),
                                                  (U8CPU)(SkColorGetG(source) * scale),
                                                  (U8CPU)(SkColorGetB(source) * scale));
                }
            }
            dptr[y * dst->width() + x] = output_color;
        }
    }

    return true;
}
