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

#include <array>

namespace skiagm {

// This GM tests a grab-bag of non-closed paths. All these paths look like
// closed rects, but they don't call path.close(). Depending on the stroke
// settings these slightly different paths give widely different results.
class NonClosedPathsGM: public GM {
public:
    NonClosedPathsGM() {}

    enum ClosureType {
        TotallyNonClosed,  // The last point doesn't coincide with the first one in the contour.
                           // The path looks not closed at all.

        FakeCloseCorner,   // The last point coincides with the first one at a corner.
                           // The path looks closed, but final rendering has 2 ends with cap.

        FakeCloseMiddle,   // The last point coincides with the first one in the middle of a line.
                           // The path looks closed, and the final rendering looks closed too.

        kClosureTypeCount
    };

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

    // 12 * 18 + 3 cases, every case is 100 * 100 pixels.
    SkISize getISize() override { return SkISize::Make(1220, 1920); }

    // Use rect-like geometry for non-closed path, for right angles make it
    // easier to show the visual difference of lineCap and lineJoin.
    static SkPath MakePath(ClosureType type) {
        SkPathBuilder path;
        if (FakeCloseMiddle == type) {
            path.moveTo(30, 50);
            path.lineTo(30, 30);
        } else {
            path.moveTo(30, 30);
        }
        path.lineTo(70, 30);
        path.lineTo(70, 70);
        path.lineTo(30, 70);
        path.lineTo(30, 50);
        if (FakeCloseCorner == type) {
            path.lineTo(30, 30);
        }
        return path.detach();
    }

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

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

        static constexpr auto kStyle = std::to_array<SkPaint::Style>(
                {SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style});

        static constexpr auto kCap = std::to_array<SkPaint::Cap>({
                SkPaint::kButt_Cap,
                SkPaint::kRound_Cap,
                SkPaint::kSquare_Cap,
        });

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

        static constexpr auto kType = std::to_array<ClosureType>({
                TotallyNonClosed,
                FakeCloseCorner,
                FakeCloseMiddle,
        });

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

        // For stroke style painter and fill-and-stroke style painter
        for (size_t type = 0; type < kClosureTypeCount; ++type) {
            for (size_t style = 0; style < std::size(kStyle); ++style) {
                for (size_t cap = 0; cap < std::size(kCap); ++cap) {
                    for (size_t join = 0; join < std::size(kJoin); ++join) {
                        for (int width = 0; width < numWidths; ++width) {
                            canvas->save();
                            SetLocation(canvas, counter, SkPaint::kJoinCount * numWidths);

                            SkPath path = MakePath(kType[type]);

                            paint.setStyle(kStyle[style]);
                            paint.setStrokeCap(kCap[cap]);
                            paint.setStrokeJoin(kJoin[join]);
                            paint.setStrokeWidth(SkIntToScalar(kStrokeWidth[width]));

                            canvas->drawPath(path, paint);
                            canvas->restore();
                            ++counter;
                        }
                    }
                }
            }
        }

        // For fill style painter
        paint.setStyle(SkPaint::kFill_Style);
        for (size_t type = 0; type < kClosureTypeCount; ++type) {
            canvas->save();
            SetLocation(canvas, counter, SkPaint::kJoinCount * numWidths);

            SkPath path = MakePath(kType[type]);

            canvas->drawPath(path, paint);
            canvas->restore();
            ++counter;
        }
    }

private:
    using INHERITED = GM;
};

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

DEF_GM(return new NonClosedPathsGM;)

}  // namespace skiagm
