/*
 * 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/SkRRect.h"
#include "include/core/SkRect.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/SkTArray.h"
#include "include/utils/SkRandom.h"
#include "tools/ToolUtils.h"

namespace skiagm {

static SkColor gen_color(SkRandom* rand) {
    SkScalar hsv[3];
    hsv[0] = rand->nextRangeF(0.0f, 360.0f);
    hsv[1] = rand->nextRangeF(0.75f, 1.0f);
    hsv[2] = rand->nextRangeF(0.75f, 1.0f);

    return ToolUtils::color_to_565(SkHSVToColor(hsv));
}

class RoundRectGM : public GM {
public:
    RoundRectGM() {
        this->setBGColor(0xFF000000);
        this->makePaints();
        this->makeMatrices();
    }

protected:

    SkString onShortName() override {
        return SkString("roundrects");
    }

    SkISize onISize() override {
        return SkISize::Make(1200, 900);
    }

    void makePaints() {
        {
            // no AA
            SkPaint p;
            fPaints.push_back(p);
        }

        {
            // AA
            SkPaint p;
            p.setAntiAlias(true);
            fPaints.push_back(p);
        }

        {
            // AA with stroke style
            SkPaint p;
            p.setAntiAlias(true);
            p.setStyle(SkPaint::kStroke_Style);
            p.setStrokeWidth(SkIntToScalar(5));
            fPaints.push_back(p);
        }

        {
            // AA with stroke style, width = 0
            SkPaint p;
            p.setAntiAlias(true);
            p.setStyle(SkPaint::kStroke_Style);
            fPaints.push_back(p);
        }

        {
            // AA with stroke and fill style
            SkPaint p;
            p.setAntiAlias(true);
            p.setStyle(SkPaint::kStrokeAndFill_Style);
            p.setStrokeWidth(SkIntToScalar(3));
            fPaints.push_back(p);
        }
    }

    void makeMatrices() {
        {
            SkMatrix m;
            m.setIdentity();
            fMatrices.push_back(m);
        }

        {
            SkMatrix m;
            m.setScale(SkIntToScalar(3), SkIntToScalar(2));
            fMatrices.push_back(m);
        }

        {
            SkMatrix m;
            m.setScale(SkIntToScalar(2), SkIntToScalar(2));
            fMatrices.push_back(m);
        }

        {
            SkMatrix m;
            m.setScale(SkIntToScalar(1), SkIntToScalar(2));
            fMatrices.push_back(m);
        }

        {
            SkMatrix m;
            m.setScale(SkIntToScalar(4), SkIntToScalar(1));
            fMatrices.push_back(m);
        }

        {
            SkMatrix m;
            m.setRotate(SkIntToScalar(90));
            fMatrices.push_back(m);
        }

        {
            SkMatrix m;
            m.setSkew(SkIntToScalar(2), SkIntToScalar(3));
            fMatrices.push_back(m);
        }

        {
            SkMatrix m;
            m.setRotate(SkIntToScalar(60));
            fMatrices.push_back(m);
        }
    }

    void onDraw(SkCanvas* canvas) override {
        SkRandom rand(1);
        canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
        const SkRect kRect = SkRect::MakeLTRB(-20, -30, 20, 30);
        SkRRect circleRRect;
        circleRRect.setRectXY(kRect, 5, 5);

        const SkScalar kXStart = 60.0f;
        const SkScalar kYStart = 80.0f;
        const int kXStep = 150;
        const int kYStep = 160;
        int maxX = fMatrices.size();

        SkPaint rectPaint;
        rectPaint.setAntiAlias(true);
        rectPaint.setStyle(SkPaint::kStroke_Style);
        rectPaint.setStrokeWidth(SkIntToScalar(0));
        rectPaint.setColor(SK_ColorLTGRAY);

        int testCount = 0;
        for (int i = 0; i < fPaints.size(); ++i) {
            for (int j = 0; j < fMatrices.size(); ++j) {
                canvas->save();
                SkMatrix mat = fMatrices[j];
                // position the roundrect, and make it at off-integer coords.
                mat.postTranslate(kXStart + SK_Scalar1 * kXStep * (testCount % maxX) +
                                  SK_Scalar1 / 4,
                                  kYStart + SK_Scalar1 * kYStep * (testCount / maxX) +
                                  3 * SK_Scalar1 / 4);
                canvas->concat(mat);

                SkColor color = gen_color(&rand);
                fPaints[i].setColor(color);

                canvas->drawRect(kRect, rectPaint);
                canvas->drawRRect(circleRRect, fPaints[i]);

                canvas->restore();

                ++testCount;
            }
        }

        // special cases

        // non-scaled tall and skinny roundrect
        for (int i = 0; i < fPaints.size(); ++i) {
            SkRect rect = SkRect::MakeLTRB(-20, -60, 20, 60);
            SkRRect ellipseRect;
            ellipseRect.setRectXY(rect, 5, 10);

            canvas->save();
            // position the roundrect, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.55f + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);

            SkColor color = gen_color(&rand);
            fPaints[i].setColor(color);

            canvas->drawRect(rect, rectPaint);
            canvas->drawRRect(ellipseRect, fPaints[i]);
            canvas->restore();
        }

        // non-scaled wide and short roundrect
        for (int i = 0; i < fPaints.size(); ++i) {
            SkRect rect = SkRect::MakeLTRB(-80, -30, 80, 30);
            SkRRect ellipseRect;
            ellipseRect.setRectXY(rect, 20, 5);

            canvas->save();
            // position the roundrect, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 4 + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
                              SK_ScalarHalf * kYStep);

            SkColor color = gen_color(&rand);
            fPaints[i].setColor(color);

            canvas->drawRect(rect, rectPaint);
            canvas->drawRRect(ellipseRect, fPaints[i]);
            canvas->restore();
        }

        // super skinny roundrect
        for (int i = 0; i < fPaints.size(); ++i) {
            SkRect rect = SkRect::MakeLTRB(0, -60, 1, 60);
            SkRRect circleRect;
            circleRect.setRectXY(rect, 5, 5);

            canvas->save();
            // position the roundrect, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 3.25f + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);

            SkColor color = gen_color(&rand);
            fPaints[i].setColor(color);

            canvas->drawRRect(circleRect, fPaints[i]);
            canvas->restore();
        }

        // super short roundrect
        for (int i = 0; i < fPaints.size(); ++i) {
            SkRect rect = SkRect::MakeLTRB(-80, -1, 80, 0);
            SkRRect circleRect;
            circleRect.setRectXY(rect, 5, 5);

            canvas->save();
            // position the roundrect, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.5f + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
                              SK_ScalarHalf * kYStep);

            SkColor color = gen_color(&rand);
            fPaints[i].setColor(color);

            canvas->drawRRect(circleRect, fPaints[i]);
            canvas->restore();
        }

        // radial gradient
        SkPoint center = SkPoint::Make(SkIntToScalar(0), SkIntToScalar(0));
        SkColor colors[] = { SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN };
        SkScalar pos[] = { 0, SK_ScalarHalf, SK_Scalar1 };
        auto shader = SkGradientShader::MakeRadial(center, 20, colors, pos, std::size(colors),
                                                   SkTileMode::kClamp);

        for (int i = 0; i < fPaints.size(); ++i) {
            canvas->save();
            // position the path, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 0 + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
                              SK_ScalarHalf * kYStep);

            SkColor color = gen_color(&rand);
            fPaints[i].setColor(color);
            fPaints[i].setShader(shader);

            canvas->drawRect(kRect, rectPaint);
            canvas->drawRRect(circleRRect, fPaints[i]);

            fPaints[i].setShader(nullptr);

            canvas->restore();
        }

        // strokes and radii
        {
            SkScalar radii[][2] = {
                {10,10},
                {5,15},
                {5,15},
                {5,15}
            };

            SkScalar strokeWidths[] = {
                20, 10, 20, 40
            };

            for (int i = 0; i < 4; ++i) {
                SkRRect circleRect;
                circleRect.setRectXY(kRect, radii[i][0], radii[i][1]);

                canvas->save();
                // position the roundrect, and make it at off-integer coords.
                canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4,
                                  kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
                                  SK_ScalarHalf * kYStep);

                SkColor color = gen_color(&rand);

                SkPaint p;
                p.setAntiAlias(true);
                p.setStyle(SkPaint::kStroke_Style);
                p.setStrokeWidth(strokeWidths[i]);
                p.setColor(color);

                canvas->drawRRect(circleRect, p);
                canvas->restore();
            }
        }

        // test old entry point ( https://bug.skia.org/3786 )
        {
            canvas->save();

            canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4,
                              kYStart + SK_Scalar1 * kYStep * 4 + SK_Scalar1 / 4 +
                              SK_ScalarHalf * kYStep);

            const SkColor color = gen_color(&rand);

            SkPaint p;
            p.setColor(color);

            const SkRect oooRect = { 20, 30, -20, -30 };     // intentionally out of order
            canvas->drawRoundRect(oooRect, 10, 10, p);

            canvas->restore();
        }

        // rrect with stroke > radius/2
        {
            SkRect smallRect = { -30, -20, 30, 20 };
            SkRRect circleRect;
            circleRect.setRectXY(smallRect, 5, 5);

            canvas->save();
            // position the roundrect, and make it at off-integer coords.
            canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4,
                              kYStart - SK_Scalar1 * kYStep + 73 * SK_Scalar1 / 4 +
                              SK_ScalarHalf * kYStep);

            SkColor color = gen_color(&rand);

            SkPaint p;
            p.setAntiAlias(true);
            p.setStyle(SkPaint::kStroke_Style);
            p.setStrokeWidth(25);
            p.setColor(color);

            canvas->drawRRect(circleRect, p);
            canvas->restore();
        }
    }

private:
    SkTArray<SkPaint> fPaints;
    SkTArray<SkMatrix> fMatrices;

    using INHERITED = GM;
};

//////////////////////////////////////////////////////////////////////////////

DEF_GM( return new RoundRectGM; )

}  // namespace skiagm
