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

/*
 * This GM presents a variety of gradients meant to test the correctness of the analytic unrolled
 * binary gradient colorizer, which can handle arbitrary gradients with 1 to 8 interpolation
 * intervals. These intervals can be either hardstops or smooth color transitions.
 *
 * It produces an image similar to that of GM_hardstop_gradients, but is arranged as follows:
 *
 *            | Clamp          |
 *            |________________|
 *            | M1  M2  M3  M4 |
 * ___________|________________|
 *      1     |
 *      2     |
 *      3     |
 *      4     |
 *      5     |
 *      6     |
 *      7     |
 *      8     |
 * The M-modes are different ways of interlveaving hardstops with smooth transitions:
 *   - M1 = All smooth transitions
 *   - M2 = All hard stops
 *   - M5 = Alternating smooth then hard
 *   - M6 = Alternating hard then smooth
 *
 * Only clamping is tested since this is focused more on within the interpolation region behavior,
 * compared to overall behavior.
 */

#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/core/SkTypes.h"
#include "include/effects/SkGradientShader.h"
#include "include/private/base/SkTemplates.h"

using namespace skia_private;

// All positions must be divided by the target interval count, which will produce the expected
// normalized position array for that interval number (assuming an appropriate color count is
// provided).
const int M1_POSITIONS[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
const int M2_POSITIONS[] = { 0, 1,1, 2,2, 3,3, 4,4, 5,5, 6,6, 7,7, 8 };
const int M3_POSITIONS[] = { 0, 1, 2,2, 3, 4,4, 5, 6,6, 7, 8 };
const int M4_POSITIONS[] = { 0, 1,1, 2, 3,3, 4, 5,5, 6, 7,7, 8 };

// Color count = index of first occurrence of interval count value in Mx_POSITIONS array.
const int INT1_COLOR_COUNTS[] = { 2, 2, 2, 2 };
const int INT2_COLOR_COUNTS[] = { 3, 4, 3, 4 };
const int INT3_COLOR_COUNTS[] = { 4, 6, 5, 5 };
const int INT4_COLOR_COUNTS[] = { 5, 8, 6, 7 };
const int INT5_COLOR_COUNTS[] = { 6, 10, 8, 8 };
const int INT6_COLOR_COUNTS[] = { 7, 12, 9, 10 };
const int INT7_COLOR_COUNTS[] = { 8, 14, 11, 11 };
const int INT8_COLOR_COUNTS[] = { 9, 16, 12, 13 };

// Cycle through defined colors for positions 0 through 8.
const SkColor COLORS[] = {
    SK_ColorDKGRAY,
    SK_ColorRED,
    SK_ColorYELLOW,
    SK_ColorGREEN,
    SK_ColorCYAN,
    SK_ColorBLUE,
    SK_ColorMAGENTA,
    SK_ColorBLACK,
    SK_ColorLTGRAY
};

const int* INTERVAL_COLOR_COUNTS[] = {
    INT1_COLOR_COUNTS,
    INT2_COLOR_COUNTS,
    INT3_COLOR_COUNTS,
    INT4_COLOR_COUNTS,
    INT5_COLOR_COUNTS,
    INT6_COLOR_COUNTS,
    INT7_COLOR_COUNTS,
    INT8_COLOR_COUNTS
};
const int COLOR_COUNT = std::size(COLORS);

const int* M_POSITIONS[] = {
    M1_POSITIONS,
    M2_POSITIONS,
    M3_POSITIONS,
    M4_POSITIONS
};

const int WIDTH  = 500;
const int HEIGHT = 500;

const int NUM_ROWS = 8;
const int NUM_COLS = 4;

const int CELL_WIDTH  = WIDTH  / NUM_COLS;
const int CELL_HEIGHT = HEIGHT / NUM_ROWS;

const int PAD_WIDTH  = 3;
const int PAD_HEIGHT = 3;

const int RECT_WIDTH  = CELL_WIDTH  - (2 * PAD_WIDTH);
const int RECT_HEIGHT = CELL_HEIGHT - (2 * PAD_HEIGHT);

static void shade_rect(SkCanvas* canvas, sk_sp<SkShader> shader, int cellRow, int cellCol) {
    SkPaint paint;
    paint.setShader(shader);

    canvas->save();
    canvas->translate(SkIntToScalar(cellCol * CELL_WIDTH + PAD_WIDTH),
                      SkIntToScalar(cellRow * CELL_HEIGHT + PAD_HEIGHT));

    const SkRect rect = SkRect::MakeWH(SkIntToScalar(RECT_WIDTH), SkIntToScalar(RECT_HEIGHT));
    canvas->drawRect(rect, paint);
    canvas->restore();
}

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

    }

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

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

    void onDraw(SkCanvas* canvas) override {
        const SkPoint points[2] = { SkPoint::Make(0, 0), SkPoint::Make(RECT_WIDTH, 0.0) };

        for (int cellRow = 0; cellRow < NUM_ROWS; cellRow++) {
            // Each interval has 4 different color counts, one per mode
            const int* colorCounts = INTERVAL_COLOR_COUNTS[cellRow]; // Has len = 4

            for (int cellCol = 0; cellCol < NUM_COLS; cellCol++) {
                // create_gradient_points(cellRow, cellCol, points);

                // Get the color count dependent on interval and mode
                int colorCount = colorCounts[cellCol];
                // Get the positions given the mode
                const int* layout = M_POSITIONS[cellCol];

                // Collect positions and colors specific to the interval+mode normalizing the
                // position based on the interval count (== cellRow+1)
                AutoSTMalloc<4, SkColor> colors(colorCount);
                AutoSTMalloc<4, SkScalar> positions(colorCount);
                int j = 0;
                for (int i = 0; i < colorCount; i++) {
                    positions[i] = SkIntToScalar(layout[i]) / (cellRow + 1);
                    colors[i] = COLORS[j % COLOR_COUNT];
                    j++;
                }

                auto shader = SkGradientShader::MakeLinear(
                                points,
                                colors.get(),
                                positions.get(),
                                colorCount,
                                SkTileMode::kClamp,
                                0,
                                nullptr);

                shade_rect(canvas, shader, cellRow, cellCol);
            }
        }
    }

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

DEF_GM(return new AnalyticGradientShaderGM;)
