/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkGaussianEdgeShader.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"

 /** \class SkGaussianEdgeShaderImpl
 This subclass of shader applies a Gaussian to shadow edge

 If largerBlur is false:
 The radius of the Gaussian blur is specified by the g value of the color, in 6.2 fixed point.
 For spot shadows, we increase the stroke width to set the shadow against the shape. This pad
 is specified by b, also in 6.2 fixed point. The r value represents the max final alpha.
 The incoming alpha should be 1.

 If largerBlur is true:
 The radius of the Gaussian blur is specified by the r & g values of the color in 14.2 fixed point.
 For spot shadows, we increase the stroke width to set the shadow against the shape. This pad
 is specified by b, also in 6.2 fixed point. The a value represents the max final alpha.

 LargerBlur will be removed once Android is migrated to the updated shader.
 */
class SkGaussianEdgeShaderImpl : public SkShader {
public:
    SkGaussianEdgeShaderImpl() {}

    bool isOpaque() const override;

#if SK_SUPPORT_GPU
    sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override;
#endif

    SK_TO_STRING_OVERRIDE()
    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkGaussianEdgeShaderImpl)

protected:
    void flatten(SkWriteBuffer&) const override;

private:
    friend class SkGaussianEdgeShader;

    typedef SkShader INHERITED;
};

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

#if SK_SUPPORT_GPU

#include "GrCoordTransform.h"
#include "GrFragmentProcessor.h"
#include "GrInvariantOutput.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLProgramDataManager.h"
#include "glsl/GrGLSLUniformHandler.h"
#include "SkGr.h"
#include "SkGrPriv.h"

class GaussianEdgeFP : public GrFragmentProcessor {
public:
    GaussianEdgeFP() {
        this->initClassID<GaussianEdgeFP>();

        // enable output of distance information for shape
        fUsesDistanceVectorField = true;
    }

    class GLSLGaussianEdgeFP : public GrGLSLFragmentProcessor {
    public:
        GLSLGaussianEdgeFP() {}

        void emitCode(EmitArgs& args) override {
            GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;

            if (!args.fGpImplementsDistanceVector) {
                fragBuilder->codeAppendf("// GP does not implement fsDistanceVector - "
                                         " returning grey in GLSLGaussianEdgeFP\n");
                fragBuilder->codeAppendf("vec4 color = %s;", args.fInputColor);
                fragBuilder->codeAppendf("%s = vec4(0.0, 0.0, 0.0, color.r);", args.fOutputColor);
            } else {
                fragBuilder->codeAppendf("vec4 color = %s;", args.fInputColor);
                fragBuilder->codeAppend("float radius = color.r*256.0*64.0 + color.g*64.0;");
                fragBuilder->codeAppend("float pad = color.b*64.0;");

                fragBuilder->codeAppendf("float factor = 1.0 - clamp((%s.z - pad)/radius, 0.0, 1.0);",
                                         fragBuilder->distanceVectorName());
                fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.018;");
                fragBuilder->codeAppendf("%s = factor*vec4(0.0, 0.0, 0.0, color.a);",
                                         args.fOutputColor);
            }
        }

        static void GenKey(const GrProcessor& proc, const GrShaderCaps&, GrProcessorKeyBuilder* b) {
            // only one shader generated currently
            b->add32(0x0);
        }

    protected:
        void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override {}

        bool fLargerBlur;
    };

    void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
        GLSLGaussianEdgeFP::GenKey(*this, caps, b);
    }

    const char* name() const override { return "GaussianEdgeFP"; }

    void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
        inout->mulByUnknownFourComponents();
    }

private:
    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
        return new GLSLGaussianEdgeFP();
    }

    bool onIsEqual(const GrFragmentProcessor& proc) const override { return true; }
};

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

sk_sp<GrFragmentProcessor> SkGaussianEdgeShaderImpl::asFragmentProcessor(const AsFPArgs&) const {
    return sk_make_sp<GaussianEdgeFP>();
}

#endif

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

bool SkGaussianEdgeShaderImpl::isOpaque() const {
    return false;
}

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

#ifndef SK_IGNORE_TO_STRING
void SkGaussianEdgeShaderImpl::toString(SkString* str) const {
    str->appendf("GaussianEdgeShader: ()");
}
#endif

sk_sp<SkFlattenable> SkGaussianEdgeShaderImpl::CreateProc(SkReadBuffer& buf) {
    return sk_make_sp<SkGaussianEdgeShaderImpl>();
}

void SkGaussianEdgeShaderImpl::flatten(SkWriteBuffer& buf) const {
}

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

sk_sp<SkShader> SkGaussianEdgeShader::Make() {
    return sk_make_sp<SkGaussianEdgeShaderImpl>();
}

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

SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGaussianEdgeShader)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkGaussianEdgeShaderImpl)
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END

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