/*
 * 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"

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;)
