/*
 * 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"

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 onShortName() override {
        return SkString("nonclosedpaths");
    }

    // 12 * 18 + 3 cases, every case is 100 * 100 pixels.
    SkISize onISize() 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)
        constexpr int kStrokeWidth[] = {0, 10, 40, 50};
        int numWidths = std::size(kStrokeWidth);

        constexpr SkPaint::Style kStyle[] = {
            SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style
        };

        constexpr SkPaint::Cap kCap[] = {
            SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap
        };

        constexpr SkPaint::Join kJoin[] = {
            SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join
        };

        constexpr ClosureType kType[] = {
            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
