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

/*
 * This GM creates the same gradients as the Chromium test fillrect_gradient:
 * http://osscs/chromium/chromium/src/+/main:third_party/blink/web_tests/fast/canvas/fillrect_gradient.html
 */

#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkShader.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTileMode.h"
#include "include/effects/SkGradient.h"

#include <vector>

const int kCellSize = 50;
const int kNumColumns = 2;
const int kNumRows = 9;
const int kPadSize = 10;

class FillrectGradientGM : public skiagm::GM {
public:
    FillrectGradientGM() {}

protected:
    struct GradientStop {
        float pos;
        SkColor color;
    };

    SkString getName() const override { return SkString("fillrect_gradient"); }

    SkISize getISize() override {
        return SkISize::Make(kNumColumns * (kCellSize + kPadSize),
                             kNumRows * (kCellSize + kPadSize));
    }

    void drawGradient(SkCanvas* canvas, std::initializer_list<GradientStop> stops) {
        std::vector<SkColor4f> colors;
        std::vector<SkScalar> positions;
        colors.reserve(stops.size());
        positions.reserve(stops.size());

        for (const GradientStop& stop : stops) {
            colors.push_back(SkColor4f::FromColor(stop.color));
            positions.push_back(stop.pos);
        }

        static constexpr SkPoint points[] = {
            SkPoint::Make(kCellSize, 0),
            SkPoint::Make(kCellSize, kCellSize),
        };

        // Draw the gradient linearly.
        sk_sp<SkShader> shader = SkShaders::LinearGradient(points,
                                                   {{colors, positions, SkTileMode::kClamp}, {}});
        SkPaint paint;
        paint.setShader(shader);
        canvas->drawRect(SkRect::MakeXYWH(0, 0, kCellSize, kCellSize), paint);

        canvas->save();
        canvas->translate(kCellSize + kPadSize, 0);

        // Draw the gradient radially.
        shader = SkShaders::RadialGradient(SkPoint::Make(kCellSize / 2, kCellSize / 2),
                                           kCellSize / 2,
                                           {{colors, positions, SkTileMode::kClamp}, {}});
        paint.setShader(shader);
        canvas->drawRect(SkRect::MakeXYWH(0, 0, kCellSize, kCellSize), paint);

        canvas->restore();
        canvas->translate(0, kCellSize + kPadSize);
    }

    void onDraw(SkCanvas* canvas) override {
        // Simple gradient: Green to white
        this->drawGradient(canvas, {{0.0f, SK_ColorGREEN}, {1.0f, SK_ColorWHITE}});

        // Multiple sections: Green to white to red
        this->drawGradient(canvas,
                           {{0.0f, SK_ColorGREEN}, {0.5f, SK_ColorWHITE}, {1.0f, SK_ColorRED}});

        // No stops at 0.0 or 1.0: Larger green to white to larger red
        this->drawGradient(canvas,
                           {{0.4f, SK_ColorGREEN}, {0.5f, SK_ColorWHITE}, {0.6f, SK_ColorRED}});

        // Only one stop, at zero: Solid red
        this->drawGradient(canvas, {{0.0f, SK_ColorRED}});

        // Only one stop, at 1.0: Solid red
        this->drawGradient(canvas, {{1.0f, SK_ColorRED}});

        // Only one stop, in the middle: Solid red
        this->drawGradient(canvas, {{0.5f, SK_ColorRED}});

        // Disjoint gradients (multiple stops at the same offset)
        // Blue to white in the top (inner) half, red to yellow in the bottom (outer) half
        this->drawGradient(canvas,
                           {{0.0f, SK_ColorBLUE},
                            {0.5f, SK_ColorWHITE},
                            {0.5f, SK_ColorRED},
                            {1.0f, SK_ColorYELLOW}});

        // Ignored stops: Blue to white, red to yellow (same as previous)
        this->drawGradient(canvas,
                           {{0.0f, SK_ColorBLUE},
                            {0.5f, SK_ColorWHITE},
                            {0.5f, SK_ColorGRAY},
                            {0.5f, SK_ColorCYAN},
                            {0.5f, SK_ColorRED},
                            {1.0f, SK_ColorYELLOW}});

        // Unsorted stops: Blue to white, red to yellow
        // Unlike Chrome, we don't sort the stops, so this renders differently than the prior cell.
        this->drawGradient(canvas,
                           {{0.5f, SK_ColorWHITE},
                            {0.5f, SK_ColorGRAY},
                            {1.0f, SK_ColorYELLOW},
                            {0.5f, SK_ColorCYAN},
                            {0.5f, SK_ColorRED},
                            {0.0f, SK_ColorBLUE}});
    }

private:
    using INHERITED = skiagm::GM;
};

DEF_GM(return new FillrectGradientGM;)
