/*
 * 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/SkPaint.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPoint.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/private/SkTArray.h"
#include "src/core/SkRandom.h"

#include <array>

using namespace skia_private;

namespace skiagm {

// This GM tests a grab-bag of convex and concave polygons. They are triangles,
// trapezoid, diamond, polygons with lots of edges, several concave polygons...
// But rectangles are excluded.
class PolygonsGM: public GM {
public:
    PolygonsGM() {}

protected:
    SkString getName() const override { return SkString("polygons"); }

    SkISize getISize() override {
        int width = kNumPolygons * kCellSize + 40;
        int height = (kNumJoins * kNumStrokeWidths + kNumExtraStyles) * kCellSize + 40;
        return SkISize::Make(width, height);
    }

    // Construct all polygons
    void onOnceBeforeDraw() override {
        static constexpr auto p0 = std::to_array<SkPoint>({ // triangle
                {0, 0}, {60, 0}, {90, 40}
        });
        static constexpr auto p1 = std::to_array<SkPoint>({ // trapezoid
                {0, 0}, {0, 40}, {60, 40}, {40, 0}
        });
        static constexpr auto p2 = std::to_array<SkPoint>({ // diamond
                {0, 0}, {40, 40}, {80, 40}, {40, 0}
        });
        static constexpr auto p3 = std::to_array<SkPoint>({ // octagon
                {10, 0}, {50, 0}, {60, 10}, {60, 30}, {50, 40}, {10, 40}, {0, 30}, {0, 10}
        });
        std::array<SkPoint, 32> p4;                         // circle-like polygons with 32-edges.
        static constexpr auto p5 = std::to_array<SkPoint>({ // concave polygon with 4 edges
                {0, 0}, {20, 20}, {0, 40}, {60, 20}
        });
        static constexpr auto p6 = std::to_array<SkPoint>({ // stairs-like polygon
                {0, 40}, {0, 30}, {15, 30}, {15, 20}, {30, 20},
                {30, 10}, {45, 10}, {45, 0}, {60, 0}, {60, 40}
        });
        static constexpr auto p7 = std::to_array<SkPoint>({ // five-point stars
                {0, 20}, {20, 20}, {30, 0}, {40, 20}, {60, 20},
                {45, 30}, {55, 50}, {30, 40}, {5, 50}, {15, 30}
        });

        for (size_t i = 0; i < std::size(p4); ++i) {
            SkScalar angle = 2 * SK_ScalarPI * i / std::size(p4);
            p4[i].set(20 * SkScalarCos(angle) + 20, 20 * SkScalarSin(angle) + 20);
        }

        struct Polygons {
            const SkPoint* fPoints;
            size_t fPointNum;
        };
        auto pgs = std::to_array<Polygons>({
                Polygons{p0.data(), std::size(p0)},
                Polygons{p1.data(), std::size(p1)},
                Polygons{p2.data(), std::size(p2)},
                Polygons{p3.data(), std::size(p3)},
                Polygons{p4.data(), std::size(p4)},
                Polygons{p5.data(), std::size(p5)},
                Polygons{p6.data(), std::size(p6)},
                Polygons{p7.data(), std::size(p7)}
        });

        SkASSERT(std::size(pgs) == kNumPolygons);
        for (size_t pgIndex = 0; pgIndex < std::size(pgs); ++pgIndex) {
            SkPathBuilder b;
            b.moveTo(pgs[pgIndex].fPoints[0].fX,
                     pgs[pgIndex].fPoints[0].fY);
            for (size_t ptIndex = 1; ptIndex < pgs[pgIndex].fPointNum; ++ptIndex) {
                b.lineTo(pgs[pgIndex].fPoints[ptIndex].fX,
                         pgs[pgIndex].fPoints[ptIndex].fY);
            }
            b.close();
            fPolygons.push_back(b.detach());
        }
    }

    // Set the location for the current test on the canvas
    static void SetLocation(SkCanvas* canvas, int counter, int lineNum) {
        SkScalar x = SK_Scalar1 * kCellSize * (counter % lineNum) + 30 + SK_Scalar1 / 4;
        SkScalar y = SK_Scalar1 * kCellSize * (counter / lineNum) + 30 + 3 * SK_Scalar1 / 4;
        canvas->translate(x, y);
    }

    static void SetColorAndAlpha(SkPaint* paint, SkRandom* rand) {
        SkColor color = rand->nextU();
        color |= 0xff000000;
        paint->setColor(color);
        if (40 == paint->getStrokeWidth()) {
            paint->setAlpha(0xA0);
        }
    }

    void onDraw(SkCanvas* canvas) override {
        // Stroke widths are:
        // 0(may use hairline rendering), 10(common case for stroke-style)
        // 40(>= geometry width/height, make the contour filled in fact)
        static constexpr auto kStrokeWidths = std::to_array<int>({0, 10, 40});
        SkASSERT(kNumStrokeWidths == std::size(kStrokeWidths));

        static constexpr auto kJoins = std::to_array<SkPaint::Join>({
                SkPaint::kMiter_Join,
                SkPaint::kRound_Join,
                SkPaint::kBevel_Join,
        });
        SkASSERT(kNumJoins == std::size(kJoins));

        int counter = 0;
        SkPaint paint;
        paint.setAntiAlias(true);

        SkRandom rand;
        // For stroke style painter
        paint.setStyle(SkPaint::kStroke_Style);
        for (int join = 0; join < kNumJoins; ++join) {
            for (int width = 0; width < kNumStrokeWidths; ++width) {
                for (int i = 0; i < fPolygons.size(); ++i) {
                    canvas->save();
                    SetLocation(canvas, counter, fPolygons.size());

                    SetColorAndAlpha(&paint, &rand);
                    paint.setStrokeJoin(kJoins[join]);
                    paint.setStrokeWidth(SkIntToScalar(kStrokeWidths[width]));

                    canvas->drawPath(fPolygons[i], paint);
                    canvas->restore();
                    ++counter;
                }
            }
        }

        // For stroke-and-fill style painter and fill style painter
        static constexpr auto kStyles = std::to_array<SkPaint::Style>(
                {SkPaint::kStrokeAndFill_Style, SkPaint::kFill_Style});
        SkASSERT(kNumExtraStyles == std::size(kStyles));

        paint.setStrokeJoin(SkPaint::kMiter_Join);
        paint.setStrokeWidth(SkIntToScalar(20));
        for (int style = 0; style < kNumExtraStyles; ++style) {
            paint.setStyle(kStyles[style]);
            for (int i = 0; i < fPolygons.size(); ++i) {
                canvas->save();
                SetLocation(canvas, counter, fPolygons.size());
                SetColorAndAlpha(&paint, &rand);
                canvas->drawPath(fPolygons[i], paint);
                canvas->restore();
                ++counter;
            }
        }
    }

private:
    inline static constexpr int kNumPolygons = 8;
    inline static constexpr int kCellSize = 100;
    inline static constexpr int kNumExtraStyles = 2;
    inline static constexpr int kNumStrokeWidths = 3;
    inline static constexpr int kNumJoins = 3;

    TArray<SkPath> fPolygons;
    using INHERITED = GM;
};

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

DEF_GM(return new PolygonsGM;)

// see crbug.com/1197461
DEF_SIMPLE_GM(conjoined_polygons, canvas, 400, 400) {
    SkPathBuilder b;
    b.moveTo(0.f, 120.f);
    b.lineTo(0.f, 0.f);
    b.lineTo(50.f, 330.f);
    b.lineTo(90.f, 0.f);
    b.lineTo(340.f, 0.f);
    b.lineTo(90.f, 330.f);
    b.lineTo(50.f, 330.f);
    b.close();

    SkPaint paint;
    paint.setAntiAlias(true);
    canvas->drawPath(b.detach(), paint);
}

}  // namespace skiagm
