/*
 * Copyright 2018 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 "SkGradientShader.h"

// NOTE: The positions define hardstops for the red and green borders. For the repeating degenerate
// gradients, that means the red and green are never visible, so the average color used should only
// be based off of the white, blue, black blend.
static const SkColor COLORS[] = { SK_ColorRED, SK_ColorWHITE, SK_ColorBLUE,
                                  SK_ColorBLACK, SK_ColorGREEN };
static const SkScalar POS[] = { 0.0, 0.0, 0.5, 1.0, 1.0 };
static const int COLOR_CT = SK_ARRAY_COUNT(COLORS);

static const SkShader::TileMode TILE_MODES[] = { SkShader::kDecal_TileMode,
                                                 SkShader::kRepeat_TileMode,
                                                 SkShader::kMirror_TileMode,
                                                 SkShader::kClamp_TileMode };
static const char* TILE_NAMES[] = { "decal", "repeat", "mirror", "clamp" };
static const int TILE_MODE_CT = SK_ARRAY_COUNT(TILE_MODES);

static constexpr int TILE_SIZE = 100;
static constexpr int TILE_GAP = 10;

static const SkPoint CENTER = SkPoint::Make(TILE_SIZE / 2, TILE_SIZE / 2);

typedef sk_sp<SkShader> (*GradientFactory)(SkShader::TileMode tm);

static void draw_tile_header(SkCanvas* canvas) {
    canvas->save();

    SkPaint paint;
    paint.setColor(SK_ColorBLACK);
    paint.setTextSize(12.0f);
    paint.setAntiAlias(true);

    for (int i = 0; i < TILE_MODE_CT; ++i) {
        canvas->drawString(TILE_NAMES[i], 0, 0, paint);
        canvas->translate(TILE_SIZE + TILE_GAP, 0);
    }

    canvas->restore();

    // Now adjust to start at rows below the header
    canvas->translate(0, 2 * TILE_GAP);
}

static void draw_row(SkCanvas* canvas, const char* desc, GradientFactory factory) {
    canvas->save();

    SkPaint text;
    text.setColor(SK_ColorBLACK);
    text.setTextSize(12.0f);
    text.setAntiAlias(true);

    canvas->translate(0, TILE_GAP);
    canvas->drawString(desc, 0, 0, text);
    canvas->translate(0, TILE_GAP);

    SkPaint paint;
    paint.setColor(SK_ColorBLACK);
    paint.setStyle(SkPaint::kStrokeAndFill_Style);
    paint.setStrokeWidth(2.0f);

    for (int i = 0; i < TILE_MODE_CT; ++i) {
        paint.setShader(factory(TILE_MODES[i]));
        canvas->drawRect(SkRect::MakeWH(TILE_SIZE, TILE_SIZE), paint);
        canvas->translate(TILE_SIZE + TILE_GAP, 0);
    }

    canvas->restore();

    // Now adjust to start the next row below this one (1 gap for text and 2 gap for margin)
    canvas->translate(0, 3 * TILE_GAP + TILE_SIZE);
}

static sk_sp<SkShader> make_linear(SkShader::TileMode mode) {
    // Same position
    SkPoint pts[2] = {CENTER, CENTER};
    return SkGradientShader::MakeLinear(pts, COLORS, POS, COLOR_CT, mode);
}

static sk_sp<SkShader> make_radial(SkShader::TileMode mode) {
    // Radius = 0
    return SkGradientShader::MakeRadial(CENTER, 0.0, COLORS, POS, COLOR_CT, mode);
}

static sk_sp<SkShader> make_sweep(SkShader::TileMode mode) {
    // Start and end angles at 45
    static constexpr SkScalar SWEEP_ANG = 45.0;
    return SkGradientShader::MakeSweep(CENTER.fX, CENTER.fY, COLORS, POS, COLOR_CT, mode,
                                       SWEEP_ANG, SWEEP_ANG, 0, nullptr);
}

static sk_sp<SkShader> make_sweep_zero_ang(SkShader::TileMode mode) {
    // Start and end angles at 0
    return SkGradientShader::MakeSweep(CENTER.fX, CENTER.fY, COLORS, POS, COLOR_CT, mode,
                                       0.0, 0.0, 0, nullptr);
}

static sk_sp<SkShader> make_2pt_conic(SkShader::TileMode mode) {
    // Start and end radius = TILE_SIZE, same position
    return SkGradientShader::MakeTwoPointConical(CENTER, TILE_SIZE / 2, CENTER, TILE_SIZE / 2,
                                                 COLORS, POS, COLOR_CT, mode);
}

static sk_sp<SkShader> make_2pt_conic_zero_rad(SkShader::TileMode mode) {
    // Start and end radius = 0, same position
    return SkGradientShader::MakeTwoPointConical(CENTER, 0.0, CENTER, 0.0, COLORS, POS,
                                                 COLOR_CT, mode);
}

class DegenerateGradientGM : public skiagm::GM {
public:
    DegenerateGradientGM() {

    }

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

    SkISize onISize() override {
        return SkISize::Make(800, 800);
    }

    void onDraw(SkCanvas* canvas) override {
        canvas->translate(3 * TILE_GAP, 3 * TILE_GAP);
        draw_tile_header(canvas);

        draw_row(canvas, "linear: empty, blue, blue, green", make_linear);
        draw_row(canvas, "radial:  empty, blue, blue, green", make_radial);
        draw_row(canvas, "sweep-0: empty, blue, blue, green", make_sweep_zero_ang);
        draw_row(canvas, "sweep-45: empty, blue, blue, red 45 degree sector then green",
                 make_sweep);
        draw_row(canvas, "2pt-conic-0: empty, blue, blue, green", make_2pt_conic_zero_rad);
        draw_row(canvas, "2pt-conic-1: empty, blue, blue, full red circle on green",
                 make_2pt_conic);
    }

private:
    typedef skiagm::GM INHERITED;
};

DEF_GM(return new DegenerateGradientGM;)
