| /* | |
| * Copyright 2020 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "include/core/SkPath.h" | |
| #include "include/core/SkPathTypes.h" | |
| #include "include/core/SkPoint.h" | |
| #include "src/base/SkRandom.h" | |
| #include "src/core/SkPathPriv.h" | |
| #include "tests/Test.h" | |
| SkPoint next_point(SkRandom& rand) { return {rand.nextF(), rand.nextF()}; } | |
| DEF_TEST(SkPath_RangeIter, r) { | |
| enum class Verb { | |
| kMove = (int)SkPathVerb::kMove, | |
| kLine = (int)SkPathVerb::kLine, | |
| kQuad = (int)SkPathVerb::kQuad, | |
| kConic = (int)SkPathVerb::kConic, | |
| kCubic = (int)SkPathVerb::kCubic, | |
| kClose = (int)SkPathVerb::kClose, | |
| kImplicitMove | |
| }; | |
| Verb verbs[] = { | |
| Verb::kImplicitMove, | |
| Verb::kLine, | |
| Verb::kConic, | |
| Verb::kClose, | |
| Verb::kImplicitMove, | |
| Verb::kCubic, | |
| Verb::kMove, | |
| Verb::kConic, | |
| Verb::kLine, | |
| Verb::kClose, | |
| Verb::kMove, | |
| Verb::kMove | |
| }; | |
| class : SkRandom { | |
| public: | |
| SkPoint p() { return {this->SkRandom::nextF(), this->SkRandom::nextF()}; } | |
| float w() { return this->SkRandom::nextF(); } | |
| } genData, testData; | |
| for (int i = 0; i < 10; ++i) { | |
| if (genData.p() != testData.p() || genData.w() != testData.w()) { | |
| ERRORF(r, "genData and testData not in sync."); | |
| return; | |
| } | |
| } | |
| // Build the path. | |
| SkPath path; | |
| for (Verb verb : verbs) { | |
| switch (verb) { | |
| case Verb::kImplicitMove: | |
| break; | |
| case Verb::kMove: | |
| path.moveTo(genData.p()); | |
| break; | |
| case Verb::kLine: | |
| path.lineTo(genData.p()); | |
| break; | |
| case Verb::kQuad: { | |
| auto a = genData.p(); | |
| auto b = genData.p(); | |
| path.quadTo(a, b); | |
| break; | |
| } | |
| case Verb::kCubic: { | |
| auto a = genData.p(); | |
| auto b = genData.p(); | |
| auto c = genData.p(); | |
| path.cubicTo(a, b, c); | |
| break; | |
| } | |
| case Verb::kConic: { | |
| auto a = genData.p(); | |
| auto b = genData.p(); | |
| path.conicTo(a, b, genData.w()); | |
| break; | |
| } | |
| case Verb::kClose: | |
| path.close(); | |
| break; | |
| } | |
| } | |
| // Verify sure the RangeIter works as expected. | |
| SkPathPriv::Iterate iterate(path); | |
| auto iter = iterate.begin(); | |
| SkPoint startPt = {0,0}; | |
| SkPoint lastPt = {0,0}; | |
| for (Verb verb : verbs) { | |
| auto [pathVerb, pathPts, pathWt] = *iter++; | |
| switch (verb) { | |
| case Verb::kImplicitMove: | |
| REPORTER_ASSERT(r, pathPts[0] == startPt); | |
| lastPt = pathPts[0]; | |
| break; | |
| case Verb::kMove: | |
| REPORTER_ASSERT(r, pathPts[0] == testData.p()); | |
| startPt = lastPt = pathPts[0]; | |
| break; | |
| case Verb::kLine: | |
| REPORTER_ASSERT(r, pathPts[0] == lastPt); | |
| REPORTER_ASSERT(r, pathPts[1] == testData.p()); | |
| lastPt = pathPts[1]; | |
| break; | |
| case Verb::kQuad: | |
| REPORTER_ASSERT(r, pathPts[0] == lastPt); | |
| REPORTER_ASSERT(r, pathPts[1] == testData.p()); | |
| REPORTER_ASSERT(r, pathPts[2] == testData.p()); | |
| lastPt = pathPts[2]; | |
| break; | |
| case Verb::kCubic: | |
| REPORTER_ASSERT(r, pathPts[0] == lastPt); | |
| REPORTER_ASSERT(r, pathPts[1] == testData.p()); | |
| REPORTER_ASSERT(r, pathPts[2] == testData.p()); | |
| REPORTER_ASSERT(r, pathPts[3] == testData.p()); | |
| lastPt = pathPts[3]; | |
| break; | |
| case Verb::kConic: | |
| REPORTER_ASSERT(r, pathPts[0] == lastPt); | |
| REPORTER_ASSERT(r, pathPts[1] == testData.p()); | |
| REPORTER_ASSERT(r, pathPts[2] == testData.p()); | |
| REPORTER_ASSERT(r, *pathWt == testData.w()); | |
| lastPt = pathPts[2]; | |
| break; | |
| case Verb::kClose: | |
| REPORTER_ASSERT(r, pathPts[0] == lastPt); | |
| break; | |
| } | |
| } | |
| REPORTER_ASSERT(r, iter == iterate.end()); | |
| } |