/*
 * 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/SkGradientShader.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 onShortName() override {
        return SkString("fillrect_gradient");
    }

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

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

        for (const GradientStop& stop : stops) {
            colors.push_back(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 = SkGradientShader::MakeLinear(points,
                                                              colors.data(),
                                                              positions.data(),
                                                              colors.size(),
                                                              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 = SkGradientShader::MakeRadial(SkPoint::Make(kCellSize / 2, kCellSize / 2),
                                              kCellSize / 2,
                                              colors.data(),
                                              positions.data(),
                                              colors.size(),
                                              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;)
