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

#include "gm.h"

#include "SkCanvas.h"
#include "SkColorFilter.h"
#include "SkGradientShader.h"
#include "SkLumaColorFilter.h"
#include "SkTableColorFilter.h"
#include "SkAnimTimer.h"

namespace {

class MixerCFGM final : public skiagm::GM {
public:
    MixerCFGM(const SkSize& tileSize, size_t tileCount)
        : fTileSize(tileSize)
        , fTileCount(tileCount) {}

protected:
    SkString onShortName() override {
        return SkString("mixerCF");
    }

    SkISize onISize() override {
        return SkISize::Make(fTileSize.width()  * 1.2f * fTileCount,
                             fTileSize.height() * 1.2f * 3);         // 3 rows
    }

    void onDraw(SkCanvas* canvas) override {
        SkPaint paint;

        const SkColor gradient_colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED };
        paint.setShader(SkGradientShader::MakeSweep(fTileSize.width()  / 2,
                                                    fTileSize.height() / 2,
                                                    gradient_colors, nullptr,
                                                    SK_ARRAY_COUNT(gradient_colors)));

        auto cf0 = MakeTintColorFilter(0xff300000, 0xffa00000);  // red tint
        auto cf1 = MakeTintColorFilter(0xff003000, 0xff00a000);  // green tint

        this->mixRow(canvas, paint, nullptr,     cf1);
        this->mixRow(canvas, paint,     cf0, nullptr);
        this->mixRow(canvas, paint,     cf0,     cf1);
    }

private:
    const SkSize fTileSize;
    const size_t fTileCount;

    void mixRow(SkCanvas* canvas, SkPaint& paint,
                sk_sp<SkColorFilter> cf0, sk_sp<SkColorFilter> cf1) {
        canvas->translate(0, fTileSize.height() * 0.1f);
        {
            SkAutoCanvasRestore arc(canvas, true);
            for (size_t i = 0; i < fTileCount; ++i) {
                paint.setColorFilter(
                    SkColorFilter::MakeLerp(cf0, cf1, static_cast<float>(i) / (fTileCount - 1)));
                canvas->translate(fTileSize.width() * 0.1f, 0);
                canvas->drawRect(SkRect::MakeWH(fTileSize.width(), fTileSize.height()), paint);
                canvas->translate(fTileSize.width() * 1.1f, 0);
            }
        }
        canvas->translate(0, fTileSize.height() * 1.1f);
    }

    // A tint filter maps colors to a given range (gradient), based on the input luminance:
    //
    //   c' = lerp(lo, hi, luma(c))
    //
    // TODO: move to public headers/API?
    //
    static sk_sp<SkColorFilter> MakeTintColorFilter(SkColor lo, SkColor hi) {
        const auto r_lo = SkColorGetR(lo),
                   g_lo = SkColorGetG(lo),
                   b_lo = SkColorGetB(lo),
                   a_lo = SkColorGetA(lo),
                   r_hi = SkColorGetR(hi),
                   g_hi = SkColorGetG(hi),
                   b_hi = SkColorGetB(hi),
                   a_hi = SkColorGetA(hi);

        // We map component-wise:
        //
        //   r' = lo.r + (hi.r - lo.r) * luma
        //   g' = lo.g + (hi.g - lo.g) * luma
        //   b' = lo.b + (hi.b - lo.b) * luma
        //   a' = lo.a + (hi.a - lo.a) * luma
        //
        // The input luminance is stored in the alpha channel
        // (and RGB are cleared -- see SkLumaColorFilter). Thus:
        const SkScalar tint_matrix[] = {
            0, 0, 0, (r_hi - r_lo) / 255.0f, SkIntToScalar(r_lo),
            0, 0, 0, (g_hi - g_lo) / 255.0f, SkIntToScalar(g_lo),
            0, 0, 0, (b_hi - b_lo) / 255.0f, SkIntToScalar(b_lo),
            0, 0, 0, (a_hi - a_lo) / 255.0f, SkIntToScalar(a_lo),
        };

        return SkColorFilter::MakeMatrixFilterRowMajor255(tint_matrix)
                 ->makeComposed(SkLumaColorFilter::Make());
    }

    using INHERITED = skiagm::GM;
};

} // namespace
DEF_GM( return new MixerCFGM(SkSize::Make(200, 250), 5); )

#include "Resources.h"
#include "SkMixer.h"

static sk_sp<SkShader> make_resource_shader(const char path[], int size) {
    auto img = GetResourceAsImage(path);
    if (!img) {
        return nullptr;
    }
    SkRect src = SkRect::MakeIWH(img->width(), img->height());
    SkRect dst = SkRect::MakeIWH(size, size);
    SkMatrix m;
    m.setRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
    return img->makeShader(&m);
}

static sk_sp<SkShader> make_grad(int size, float t) {
    SkASSERT(t >= 0 && t <= 1);
    unsigned r = SkScalarRoundToInt(t * 255);
    SkColor c = SkColorSetARGB(r, r, 0, 0);

    SkColor colors[] = { 0, c, SK_ColorRED };
    SkPoint pts[] = {{0, 0}, {size*1.0f, size*1.0f}};
    SkScalar pos[] = {0, 1 - t, 1.0f};
    return SkGradientShader::MakeLinear(pts, colors, pos, SK_ARRAY_COUNT(colors),
                                        SkShader::kClamp_TileMode);
}

class ShaderMixerGM final : public skiagm::GM {
    enum { SIZE = 256 };
    float fPos = 0.5f;
    sk_sp<SkShader> fS0, fS1;

public:
    ShaderMixerGM() {}

protected:
    SkString onShortName() override {
        return SkString("mixershader_shadermixer");
    }

    void onOnceBeforeDraw() override {
        fS0 = make_resource_shader("images/mandrill_256.png", SIZE);
        fS1 = make_resource_shader("images/baby_tux.png", SIZE);
    }

    SkISize onISize() override { return {542, 542}; }

    void onDraw(SkCanvas* canvas) override {
        SkRect r = SkRect::MakeIWH(SIZE, SIZE);

        SkPaint paint;

        canvas->translate(10, 10);

        canvas->save();
        paint.setShader(fS0);
        canvas->drawRect(r, paint);
        canvas->translate(SIZE + 10.0f, 0);
        paint.setShader(fS1);
        canvas->drawRect(r, paint);
        canvas->restore();

        auto sh2 = make_grad(SIZE, fPos);

        canvas->translate(0, SIZE + 10.0f);
        paint.setShader(sh2);
        canvas->drawRect(r, paint);

        auto mixer = SkMixer::MakeShaderLerp(sh2);  // MakeLerp(0.5)
        auto sh = SkShader::MakeMixer(fS0, fS1, mixer);
        canvas->translate(SIZE + 10.0f, 0);
        paint.setShader(sh);
        canvas->drawRect(r, paint);
    }

    bool onAnimate(const SkAnimTimer& timer) override {
        fPos = (sin(timer.secs()) + 1) * 0.5f;
        return true;
    }

private:
    using INHERITED = skiagm::GM;
};
DEF_GM( return new ShaderMixerGM; )
