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