/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "bench/Benchmark.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColorPriv.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkShader.h"
#include "include/core/SkString.h"
#include "src/base/SkRandom.h"
#include "src/core/SkPathPriv.h"

enum class PathIterType {
    kIter,
    kRaw,
    kEdge,
};
const char* gPathIterNames[] = {
    "iter", "raw", "edge"
};

static int rand_pts(SkRandom& rand, SkPoint pts[4]) {
    int n = rand.nextU() & 3;
    n += 1;

    for (int i = 0; i < n; ++i) {
        pts[i].fX = rand.nextSScalar1();
        pts[i].fY = rand.nextSScalar1();
    }
    return n;
}

class PathIterBench : public Benchmark {
    SkString        fName;
    SkPath          fPath;
    PathIterType    fType;

    int fVerbInc = 0;
    SkScalar fXInc = 0, fYInc = 0;

public:
    PathIterBench(PathIterType t) : fType(t) {
        fName.printf("pathiter_%s", gPathIterNames[static_cast<unsigned>(t)]);

        SkRandom rand;
        for (int i = 0; i < 1000; ++i) {
            SkPoint pts[4];
            int n = rand_pts(rand, pts);
            switch (n) {
                case 1:
                    fPath.moveTo(pts[0]);
                    break;
                case 2:
                    fPath.lineTo(pts[1]);
                    break;
                case 3:
                    fPath.quadTo(pts[1], pts[2]);
                    break;
                case 4:
                    fPath.cubicTo(pts[1], pts[2], pts[3]);
                    break;
            }
        }
    }

    bool isSuitableFor(Backend backend) override {
        return backend == Backend::kNonRendering;
    }

protected:
    const char* onGetName() override {
        return fName.c_str();
    }

    void onDraw(int loops, SkCanvas*) override {
        // Need to do *something* with the results, so the compile doesn't elide
        // away the code we want to time.
        auto handle = [this](int verb, const SkPoint pts[]) {
            fVerbInc += verb;
            fXInc += pts[0].fX;
            fYInc += pts[0].fY;
        };

        switch (fType) {
            case PathIterType::kIter:
                for (int i = 0; i < loops; ++i) {
                    SkPath::Iter iter(fPath, true);
                    SkPath::Verb verb;
                    SkPoint      pts[4];
                    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
                        handle(verb, pts);
                    }
                }
                break;
            case PathIterType::kRaw:
                for (int i = 0; i < loops; ++i) {
                    for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
                        handle((SkPath::Verb)verb, pts);
                    }
                }
                break;
            case PathIterType::kEdge:
                for (int i = 0; i < loops; ++i) {
                    SkPathEdgeIter iter(fPath);
                    while (auto r = iter.next()) {
                        handle((int)r.fEdge, r.fPts);
                    }
                }
                break;
        }
    }

private:
    using INHERITED = Benchmark;
};

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

DEF_BENCH( return new PathIterBench(PathIterType::kIter); )
DEF_BENCH( return new PathIterBench(PathIterType::kRaw); )
DEF_BENCH( return new PathIterBench(PathIterType::kEdge); )
