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

#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkMatrix.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/SkTileMode.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkGradientShader.h"
#include "include/private/base/SkFloatingPoint.h"

constexpr SkColor gColors[] = {
    SK_ColorRED, SK_ColorYELLOW
};

// These annoying defines are necessary, because the only other alternative
// is to use SkIntToScalar(...) everywhere.
constexpr SkScalar sZero = 0;
constexpr SkScalar sHalf = SK_ScalarHalf;
constexpr SkScalar sOne = SK_Scalar1;

// These arrays define the gradient stop points
// as x1, y1, x2, y2 per gradient to draw.
constexpr SkPoint linearPts[][2] = {
    {{sZero, sZero}, {sOne,  sZero}},
    {{sZero, sZero}, {sZero, sOne}},
    {{sOne,  sZero}, {sZero, sZero}},
    {{sZero, sOne},  {sZero, sZero}},

    {{sZero, sZero}, {sOne,  sOne}},
    {{sOne,  sOne},  {sZero, sZero}},
    {{sOne,  sZero}, {sZero, sOne}},
    {{sZero, sOne},  {sOne,  sZero}}
};

constexpr SkPoint radialPts[][2] = {
    {{sZero, sHalf}, {sOne,  sHalf}},
    {{sHalf, sZero}, {sHalf, sOne}},
    {{sOne,  sHalf}, {sZero, sHalf}},
    {{sHalf, sOne},  {sHalf, sZero}},

    {{sZero, sZero}, {sOne,  sOne}},
    {{sOne,  sOne},  {sZero, sZero}},
    {{sOne,  sZero}, {sZero, sOne}},
    {{sZero, sOne},  {sOne,  sZero}}
};

// These define the pixels allocated to each gradient image.
constexpr SkScalar TESTGRID_X = SkIntToScalar(200);
constexpr SkScalar TESTGRID_Y = SkIntToScalar(200);

constexpr int IMAGES_X = 4;             // number of images per row

static sk_sp<SkShader> make_linear_gradient(const SkPoint pts[2], const SkMatrix& localMatrix) {
    return SkGradientShader::MakeLinear(pts, gColors, nullptr, std::size(gColors),
                                        SkTileMode::kClamp, 0, &localMatrix);
}

static sk_sp<SkShader> make_radial_gradient(const SkPoint pts[2], const SkMatrix& localMatrix) {
    SkPoint center;
    center.set(sk_float_midpoint(pts[0].fX, pts[1].fX),
               sk_float_midpoint(pts[0].fY, pts[1].fY));
    float radius = (center - pts[0]).length();
    return SkGradientShader::MakeRadial(center, radius, gColors, nullptr, std::size(gColors),
                                        SkTileMode::kClamp, 0, &localMatrix);
}

static void draw_gradients(SkCanvas* canvas,
                           sk_sp<SkShader> (*makeShader)(const SkPoint[2], const SkMatrix&),
                           const SkPoint ptsArray[][2], int numImages) {
    // Use some nice prime numbers for the rectangle and matrix with
    // different scaling along the x and y axes (which is the bug this
    // test addresses, where incorrect order of operations mixed up the axes)
    SkRect rectGrad = {
        SkIntToScalar(43),  SkIntToScalar(61),
        SkIntToScalar(181), SkIntToScalar(167) };
    SkMatrix shaderMat;
    shaderMat.setScale(rectGrad.width(), rectGrad.height());
    shaderMat.postTranslate(rectGrad.left(), rectGrad.top());

    canvas->save();
    for (int i = 0; i < numImages; i++) {
        // Advance line downwards if necessary.
        if (i % IMAGES_X == 0 && i != 0) {
            canvas->restore();
            canvas->translate(0, TESTGRID_Y);
            canvas->save();
        }

        SkPaint paint;
        paint.setShader(makeShader(*ptsArray, shaderMat));
        canvas->drawRect(rectGrad, paint);

        // Advance to next position.
        canvas->translate(TESTGRID_X, 0);
        ptsArray++;
    }
    canvas->restore();
}

DEF_SIMPLE_GM_BG(gradient_matrix, canvas, 800, 800, 0xFFDDDDDD) {
        draw_gradients(canvas, &make_linear_gradient,
                      linearPts, std::size(linearPts));

        canvas->translate(0, TESTGRID_Y);

        draw_gradients(canvas, &make_radial_gradient,
                      radialPts, std::size(radialPts));
}
