/*
 * Copyright 2015 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/SkPath.h"
#include "include/core/SkPathEffect.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/effects/SkDashPathEffect.h"
#include "include/private/SkTArray.h"
#include "include/private/SkTemplates.h"

namespace skiagm {

class ContourStartGM : public GM {
protected:
    void onOnceBeforeDraw() override {
        const SkScalar kMaxDashLen = 100;
        const SkScalar kDashGrowth = 1.2f;

        SkSTArray<100, SkScalar> intervals;
        for (SkScalar len = 1; len < kMaxDashLen; len *= kDashGrowth) {
            intervals.push_back(len);
            intervals.push_back(len);
        }

        fDashPaint.setAntiAlias(true);
        fDashPaint.setStyle(SkPaint::kStroke_Style);
        fDashPaint.setStrokeWidth(6);
        fDashPaint.setColor(0xff008000);
        fDashPaint.setPathEffect(SkDashPathEffect::Make(intervals.begin(), intervals.count(), 0));

        fPointsPaint.setColor(0xff800000);
        fPointsPaint.setStrokeWidth(3);

        fRect = SkRect::MakeLTRB(10, 10, 100, 70);
    }

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

    SkISize onISize() override { return SkISize::Make(kImageWidth, kImageHeight); }

    void onDraw(SkCanvas* canvas) override {

        drawDirs(canvas, [](const SkRect& rect, SkPathDirection dir, unsigned startIndex) {
            return SkPath::Rect(rect, dir, startIndex);
        });

        drawDirs(canvas, [](const SkRect& rect, SkPathDirection dir, unsigned startIndex) {
            return SkPath::Oval(rect, dir, startIndex);
        });

        drawDirs(canvas, [](const SkRect& rect, SkPathDirection dir, unsigned startIndex) {
            SkRRect rrect;
            const SkVector radii[4] = { {15, 15}, {15, 15}, {15, 15}, {15, 15}};
            rrect.setRectRadii(rect, radii);
            return SkPath::RRect(rrect, dir, startIndex);
        });

        drawDirs(canvas, [](const SkRect& rect, SkPathDirection dir, unsigned startIndex) {
            SkRRect rrect;
            rrect.setRect(rect);
            return SkPath::RRect(rrect, dir, startIndex);
        });

        drawDirs(canvas, [](const SkRect& rect, SkPathDirection dir, unsigned startIndex) {
            SkRRect rrect;
            rrect.setOval(rect);
            return SkPath::RRect(rrect, dir, startIndex);
        });

    }

private:
    static constexpr int kImageWidth = 1200;
    static constexpr int kImageHeight = 600;

    SkPaint fDashPaint, fPointsPaint;
    SkRect  fRect;

    void drawDirs(SkCanvas* canvas,
                  SkPath (*makePath)(const SkRect&, SkPathDirection, unsigned)) const {
        drawOneColumn(canvas, SkPathDirection::kCW, makePath);
        canvas->translate(kImageWidth / 10, 0);
        drawOneColumn(canvas, SkPathDirection::kCCW, makePath);
        canvas->translate(kImageWidth / 10, 0);
    }

    void drawOneColumn(SkCanvas* canvas, SkPathDirection dir,
                       SkPath (*makePath)(const SkRect&, SkPathDirection, unsigned)) const {
        SkAutoCanvasRestore acr(canvas, true);

        for (unsigned i = 0; i < 8; ++i) {
            const SkPath path = makePath(fRect, dir, i);
            canvas->drawPath(path, fDashPaint);

            const int n = path.countPoints();
            SkAutoTArray<SkPoint> points(n);
            path.getPoints(points.get(), n);
            canvas->drawPoints(SkCanvas::kPoints_PointMode, n, points.get(), fPointsPaint);

            canvas->translate(0, kImageHeight / 8);
        }
    }

    using INHERITED = GM;
};

DEF_GM( return new ContourStartGM(); )

} // namespace skiagm
