1/*
2 * Copyright 2020 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "include/utils/SkRandom.h"
9#include "src/core/SkPathPriv.h"
10#include "tests/Test.h"
11
12SkPoint next_point(SkRandom& rand) { return {rand.nextF(), rand.nextF()}; }
13
14DEF_TEST(SkPath_RangeIter, r) {
15    enum class Verb {
16        kMove = (int)SkPathVerb::kMove,
17        kLine = (int)SkPathVerb::kLine,
18        kQuad = (int)SkPathVerb::kQuad,
19        kConic = (int)SkPathVerb::kConic,
20        kCubic = (int)SkPathVerb::kCubic,
21        kClose = (int)SkPathVerb::kClose,
22        kImplicitMove
23    };
24
25    Verb verbs[] = {
26        Verb::kImplicitMove,
27        Verb::kLine,
28        Verb::kConic,
29        Verb::kClose,
30        Verb::kImplicitMove,
31        Verb::kCubic,
32        Verb::kMove,
33        Verb::kConic,
34        Verb::kLine,
35        Verb::kClose,
36        Verb::kMove,
37        Verb::kMove
38    };
39
40    class : SkRandom {
41    public:
42        SkPoint p() { return {this->SkRandom::nextF(), this->SkRandom::nextF()}; }
43        float w() { return this->SkRandom::nextF(); }
44    } genData, testData;
45
46    for (int i = 0; i < 10; ++i) {
47        if (genData.p() != testData.p() || genData.w() != testData.w()) {
48            ERRORF(r, "genData and testData not in sync.");
49            return;
50        }
51    }
52
53    // Build the path.
54    SkPath path;
55    for (Verb verb : verbs) {
56        switch (verb) {
57            case Verb::kImplicitMove:
58                break;
59            case Verb::kMove:
60                path.moveTo(genData.p());
61                break;
62            case Verb::kLine:
63                path.lineTo(genData.p());
64                break;
65            case Verb::kQuad: {
66                auto a = genData.p();
67                auto b = genData.p();
68                path.quadTo(a, b);
69                break;
70            }
71            case Verb::kCubic: {
72                auto a = genData.p();
73                auto b = genData.p();
74                auto c = genData.p();
75                path.cubicTo(a, b, c);
76                break;
77            }
78            case Verb::kConic: {
79                auto a = genData.p();
80                auto b = genData.p();
81                path.conicTo(a, b, genData.w());
82                break;
83            }
84            case Verb::kClose:
85                path.close();
86                break;
87        }
88    }
89
90    // Verify sure the RangeIter works as expected.
91    SkPathPriv::Iterate iterate(path);
92    auto iter = iterate.begin();
93    SkPoint startPt = {0,0};
94    SkPoint lastPt = {0,0};
95    for (Verb verb : verbs) {
96        auto [pathVerb, pathPts, pathWt] = *iter++;
97        switch (verb) {
98            case Verb::kImplicitMove:
99                REPORTER_ASSERT(r, pathPts[0] == startPt);
100                lastPt = pathPts[0];
101                break;
102            case Verb::kMove:
103                REPORTER_ASSERT(r, pathPts[0] == testData.p());
104                startPt = lastPt = pathPts[0];
105                break;
106            case Verb::kLine:
107                REPORTER_ASSERT(r, pathPts[0] == lastPt);
108                REPORTER_ASSERT(r, pathPts[1] == testData.p());
109                lastPt = pathPts[1];
110                break;
111            case Verb::kQuad:
112                REPORTER_ASSERT(r, pathPts[0] == lastPt);
113                REPORTER_ASSERT(r, pathPts[1] == testData.p());
114                REPORTER_ASSERT(r, pathPts[2] == testData.p());
115                lastPt = pathPts[2];
116                break;
117            case Verb::kCubic:
118                REPORTER_ASSERT(r, pathPts[0] == lastPt);
119                REPORTER_ASSERT(r, pathPts[1] == testData.p());
120                REPORTER_ASSERT(r, pathPts[2] == testData.p());
121                REPORTER_ASSERT(r, pathPts[3] == testData.p());
122                lastPt = pathPts[3];
123                break;
124            case Verb::kConic:
125                REPORTER_ASSERT(r, pathPts[0] == lastPt);
126                REPORTER_ASSERT(r, pathPts[1] == testData.p());
127                REPORTER_ASSERT(r, pathPts[2] == testData.p());
128                REPORTER_ASSERT(r, *pathWt == testData.w());
129                lastPt = pathPts[2];
130                break;
131            case Verb::kClose:
132                REPORTER_ASSERT(r, pathPts[0] == lastPt);
133                break;
134        }
135    }
136    REPORTER_ASSERT(r, iter == iterate.end());
137}
138