/*
 * 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/gm.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkColorFilter.h"
#include "include/effects/SkGradientShader.h"
#include "include/effects/SkLumaColorFilter.h"
#include "include/effects/SkTableColorFilter.h"
#include "tools/timer/AnimTimer.h"

// 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 SkColorFilters::MatrixRowMajor255(tint_matrix)
    ->makeComposed(SkLumaColorFilter::Make());
}

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(
                    SkColorFilters::Lerp(static_cast<float>(i) / (fTileCount - 1), cf0, cf1));
                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);
    }

    using INHERITED = skiagm::GM;
};

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

#include "tools/Resources.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),
                                        SkTileMode::kClamp);
}

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 sh = SkShaders::Lerp(sh2, fS0, fS1);
        canvas->translate(SIZE + 10.0f, 0);
        paint.setShader(sh);
        canvas->drawRect(r, paint);
    }

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

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