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

#include "bench/Benchmark.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkPaint.h"
#include "include/core/SkShader.h"
#include "include/core/SkString.h"
#include "include/effects/SkGradientShader.h"

#include "tools/ToolUtils.h"

class HardStopGradientBench_ScaleNumColors : public Benchmark {
public:
    HardStopGradientBench_ScaleNumColors(SkTileMode tilemode, int count) {
        fName.printf("hardstop_scale_num_colors_%s_%03d_colors",
                     ToolUtils::tilemode_name(tilemode), count);

        fTileMode   = tilemode;
        fColorCount = count;
    }

    const char* onGetName() override {
        return fName.c_str();
    }

    SkISize onGetSize() override {
        return SkISize::Make(kSize, kSize);
    }

    /*
     * Set up a linear gradient from left to right with
     * fColorCount colors alternating between four
     * different colors. The positions are evenly spaced,
     * with the exception of the first two; these create a
     * hard stop in order to trigger the hard stop code.
     */
    void onPreDraw(SkCanvas* canvas) override {
        // Left to right
        SkPoint points[2] = {
            SkPoint::Make(0,        kSize/2),
            SkPoint::Make(kSize-1,  kSize/2),
        };

        constexpr int kNumColorChoices = 4;
        SkColor color_choices[kNumColorChoices] = {
            SK_ColorRED,
            SK_ColorGREEN,
            SK_ColorBLUE,
            SK_ColorYELLOW,
        };

        // Alternate between different choices
        SkColor  colors[100];
        for (int i = 0; i < fColorCount; i++) {
            colors[i] = color_choices[i % kNumColorChoices];
        }

        // Create a hard stop
        SkScalar positions[100];
        positions[0] = 0.0f;
        positions[1] = 0.0f;
        for (int i = 2; i < fColorCount; i++) {
            // Evenly spaced afterwards
            positions[i] = i / (fColorCount - 1.0f);
        }

        fPaint.setShader(SkGradientShader::MakeLinear(points,
                                                      colors,
                                                      positions,
                                                      fColorCount,
                                                      fTileMode,
                                                      0,
                                                      nullptr));
    }

    /*
     * Draw simple linear gradient from left to right
     */
    void onDraw(int loops, SkCanvas* canvas) override {
        for (int i = 0; i < loops; i++) {
            canvas->drawPaint(fPaint);
        }
    }

private:
    static const int kSize = 500;

    SkTileMode  fTileMode;
    SkString    fName;
    int         fColorCount;
    SkPaint     fPaint;

    using INHERITED = Benchmark;
};

// Clamp
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kClamp,   3);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kClamp,   4);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kClamp,   5);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kClamp,  10);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kClamp,  25);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kClamp,  50);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kClamp, 100);)

// Repeat
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kRepeat,   3);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kRepeat,   4);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kRepeat,   5);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kRepeat,  10);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kRepeat,  25);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kRepeat,  50);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kRepeat, 100);)

// Mirror
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kMirror,   3);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kMirror,   4);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kMirror,   5);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kMirror,  10);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kMirror,  25);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kMirror,  50);)
DEF_BENCH(return new HardStopGradientBench_ScaleNumColors(SkTileMode::kMirror, 100);)
