|  | /* | 
|  | * 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 "include/utils/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()); | 
|  | } |