Remove SkPath::RawIter from tests/tools/samplecode

Change-Id: I66c1b4aee9b07a4db294ed0cd82d01f3097c6acb
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/287857
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
Chris Dalton 2020-05-05 15:06:30 -06:00 committed by Skia Commit-Bot
parent 999257d870
commit de5003768b
9 changed files with 279 additions and 314 deletions

View File

@ -1507,15 +1507,24 @@ private:
: fVerb(verbs), fPoints(points), fWeights(weights) {
SkDEBUGCODE(fInitialPoints = fPoints;)
}
void operator++() {
bool operator!=(const RangeIter& that) const {
return fVerb != that.fVerb;
}
bool operator==(const RangeIter& that) const {
return fVerb == that.fVerb;
}
RangeIter& operator++() {
auto verb = static_cast<SkPathVerb>(*fVerb++);
fPoints += pts_advance_after_verb(verb);
if (verb == SkPathVerb::kConic) {
++fWeights;
}
return *this;
}
bool operator!=(const RangeIter& that) const {
return fVerb != that.fVerb;
RangeIter operator++(int) {
RangeIter copy = *this;
this->operator++();
return copy;
}
std::tuple<SkPathVerb, const SkPoint*, const SkScalar*> operator*() const {
auto verb = static_cast<SkPathVerb>(*fVerb);

View File

@ -129,73 +129,63 @@ static SkScalar get_path_weight(int index, const SkPath& path) {
static void add_path_segment(int index, SkPath* path) {
SkPath result;
SkPoint pts[4];
SkPoint firstPt = { 0, 0 }; // init to avoid warning
SkPoint lastPt = { 0, 0 }; // init to avoid warning
SkPath::Verb verb;
SkPath::RawIter iter(*path);
int counter = -1;
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
SkScalar weight SK_INIT_TO_AVOID_WARNING;
SkPoint chop[7];
SkConic conicChop[2];
for (auto [verb, pts, w] : SkPathPriv::Iterate(*path)) {
if (++counter == index) {
switch (verb) {
case SkPath::kLine_Verb:
case SkPathVerb::kLine:
result.lineTo((pts[0].fX + pts[1].fX) / 2, (pts[0].fY + pts[1].fY) / 2);
break;
case SkPath::kQuad_Verb: {
SkPoint chop[5];
case SkPathVerb::kQuad: {
SkChopQuadAtHalf(pts, chop);
result.quadTo(chop[1], chop[2]);
pts[1] = chop[3];
pts = chop + 2;
} break;
case SkPath::kConic_Verb: {
SkConic chop[2];
case SkPathVerb::kConic: {
SkConic conic;
conic.set(pts, iter.conicWeight());
if (!conic.chopAt(0.5f, chop)) {
conic.set(pts, *w);
if (!conic.chopAt(0.5f, conicChop)) {
return;
}
result.conicTo(chop[0].fPts[1], chop[0].fPts[2], chop[0].fW);
pts[1] = chop[1].fPts[1];
weight = chop[1].fW;
result.conicTo(conicChop[0].fPts[1], conicChop[0].fPts[2], conicChop[0].fW);
pts = conicChop[1].fPts;
w = &conicChop[1].fW;
} break;
case SkPath::kCubic_Verb: {
SkPoint chop[7];
case SkPathVerb::kCubic: {
SkChopCubicAtHalf(pts, chop);
result.cubicTo(chop[1], chop[2], chop[3]);
pts[1] = chop[4];
pts[2] = chop[5];
pts = chop + 3;
} break;
case SkPath::kClose_Verb: {
case SkPathVerb::kClose: {
result.lineTo((lastPt.fX + firstPt.fX) / 2, (lastPt.fY + firstPt.fY) / 2);
} break;
default:
SkASSERT(0);
}
} else if (verb == SkPath::kConic_Verb) {
weight = iter.conicWeight();
}
switch (verb) {
case SkPath::kMove_Verb:
case SkPathVerb::kMove:
result.moveTo(firstPt = pts[0]);
break;
case SkPath::kLine_Verb:
case SkPathVerb::kLine:
result.lineTo(lastPt = pts[1]);
break;
case SkPath::kQuad_Verb:
case SkPathVerb::kQuad:
result.quadTo(pts[1], lastPt = pts[2]);
break;
case SkPath::kConic_Verb:
result.conicTo(pts[1], lastPt = pts[2], weight);
case SkPathVerb::kConic:
result.conicTo(pts[1], lastPt = pts[2], *w);
break;
case SkPath::kCubic_Verb:
case SkPathVerb::kCubic:
result.cubicTo(pts[1], pts[2], lastPt = pts[3]);
break;
case SkPath::kClose_Verb:
case SkPathVerb::kClose:
result.close();
break;
case SkPath::kDone_Verb:
break;
default:
SkASSERT(0);
}
@ -205,35 +195,30 @@ static void add_path_segment(int index, SkPath* path) {
static void delete_path_segment(int index, SkPath* path) {
SkPath result;
SkPoint pts[4];
SkPath::Verb verb;
SkPath::RawIter iter(*path);
int counter = -1;
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
for (auto [verb, pts, w] : SkPathPriv::Iterate(*path)) {
if (++counter == index) {
continue;
}
switch (verb) {
case SkPath::kMove_Verb:
case SkPathVerb::kMove:
result.moveTo(pts[0]);
break;
case SkPath::kLine_Verb:
case SkPathVerb::kLine:
result.lineTo(pts[1]);
break;
case SkPath::kQuad_Verb:
case SkPathVerb::kQuad:
result.quadTo(pts[1], pts[2]);
break;
case SkPath::kConic_Verb:
result.conicTo(pts[1], pts[2], iter.conicWeight());
case SkPathVerb::kConic:
result.conicTo(pts[1], pts[2], *w);
break;
case SkPath::kCubic_Verb:
case SkPathVerb::kCubic:
result.cubicTo(pts[1], pts[2], pts[3]);
break;
case SkPath::kClose_Verb:
case SkPathVerb::kClose:
result.close();
break;
case SkPath::kDone_Verb:
break;
default:
SkASSERT(0);
}

View File

@ -10,6 +10,7 @@
#include "include/core/SkPath.h"
#include "include/utils/SkRandom.h"
#include "samplecode/Sample.h"
#include "src/core/SkPathPriv.h"
#include "src/core/SkScalerCache.h"
#include "src/core/SkStrikeCache.h"
#include "src/core/SkStrikeSpec.h"
@ -280,35 +281,30 @@ public:
backpath->reset();
backpath->setFillType(SkPathFillType::kEvenOdd);
SkPath::RawIter iter(glyph.fPath);
SkPath::Verb verb;
SkPoint pts[4];
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
for (auto [verb, pts, w] : SkPathPriv::Iterate(glyph.fPath)) {
switch (verb) {
case SkPath::kMove_Verb: {
case SkPathVerb::kMove: {
SkPoint pt = fWaves.apply(tsec, matrix, pts[0]);
backpath->moveTo(pt.x(), pt.y());
break;
}
case SkPath::kLine_Verb: {
case SkPathVerb::kLine: {
SkPoint endpt = fWaves.apply(tsec, matrix, pts[1]);
backpath->lineTo(endpt.x(), endpt.y());
break;
}
case SkPath::kQuad_Verb: {
case SkPathVerb::kQuad: {
SkPoint controlPt = fWaves.apply(tsec, matrix, pts[1]);
SkPoint endpt = fWaves.apply(tsec, matrix, pts[2]);
backpath->quadTo(controlPt.x(), controlPt.y(), endpt.x(), endpt.y());
break;
}
case SkPath::kClose_Verb: {
case SkPathVerb::kClose: {
backpath->close();
break;
}
case SkPath::kCubic_Verb:
case SkPath::kConic_Verb:
case SkPath::kDone_Verb:
case SkPathVerb::kCubic:
case SkPathVerb::kConic:
SK_ABORT("Unexpected path verb");
break;
}

View File

@ -28,6 +28,7 @@
#include "include/utils/SkTextUtils.h"
#include "samplecode/Sample.h"
#include "src/core/SkGeometry.h"
#include "src/core/SkPathPriv.h"
#include "src/core/SkPointPriv.h"
#include "src/core/SkStroke.h"
#include "tools/ToolUtils.h"
@ -42,18 +43,14 @@ static bool hittest(const SkPoint& target, SkScalar x, SkScalar y) {
}
static int getOnCurvePoints(const SkPath& path, SkPoint storage[]) {
SkPath::RawIter iter(path);
SkPoint pts[4];
SkPath::Verb verb;
int count = 0;
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
switch (verb) {
case SkPath::kMove_Verb:
case SkPath::kLine_Verb:
case SkPath::kQuad_Verb:
case SkPath::kConic_Verb:
case SkPath::kCubic_Verb:
case SkPathVerb::kMove:
case SkPathVerb::kLine:
case SkPathVerb::kQuad:
case SkPathVerb::kConic:
case SkPathVerb::kCubic:
storage[count++] = pts[0];
break;
default:
@ -64,25 +61,21 @@ static int getOnCurvePoints(const SkPath& path, SkPoint storage[]) {
}
static void getContourCounts(const SkPath& path, SkTArray<int>* contourCounts) {
SkPath::RawIter iter(path);
SkPoint pts[4];
SkPath::Verb verb;
int count = 0;
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
switch (verb) {
case SkPath::kMove_Verb:
case SkPath::kLine_Verb:
case SkPathVerb::kMove:
case SkPathVerb::kLine:
count += 1;
break;
case SkPath::kQuad_Verb:
case SkPath::kConic_Verb:
case SkPathVerb::kQuad:
case SkPathVerb::kConic:
count += 2;
break;
case SkPath::kCubic_Verb:
case SkPathVerb::kCubic:
count += 3;
break;
case SkPath::kClose_Verb:
case SkPathVerb::kClose:
contourCounts->push_back(count);
count = 0;
break;
@ -356,14 +349,14 @@ protected:
for (SkScalar dist = 0; dist <= total; dist += delta) {
++ribs;
}
SkPath::RawIter iter(path);
SkPoint pts[4];
if (SkPath::kMove_Verb != iter.next(pts)) {
const uint8_t* verbs = SkPathPriv::VerbData(path);
if (path.countVerbs() < 2 || SkPath::kMove_Verb != verbs[0]) {
SkASSERT(0);
return;
}
SkPath::Verb verb = iter.next(pts);
auto verb = static_cast<SkPath::Verb>(verbs[1]);
SkASSERT(SkPath::kLine_Verb <= verb && verb <= SkPath::kCubic_Verb);
const SkPoint* pts = SkPathPriv::PointData(path);
SkPoint pos, tan;
for (int index = 0; index < ribs; ++index) {
SkScalar t = (SkScalar) index / ribs;
@ -379,7 +372,7 @@ protected:
tan = SkEvalQuadTangentAt(pts, t);
break;
case SkPath::kConic_Verb: {
SkConic conic(pts, iter.conicWeight());
SkConic conic(pts, SkPathPriv::ConicWeightData(path)[0]);
pos = conic.evalAt(t);
tan = conic.evalTangentAt(t);
} break;

View File

@ -972,44 +972,38 @@ static void test_islastcontourclosed(skiatest::Reporter* reporter) {
//
static void test_poly(skiatest::Reporter* reporter, const SkPath& path,
const SkPoint srcPts[], bool expectClose) {
SkPath::RawIter iter(path);
SkPoint pts[4];
bool firstTime = true;
bool foundClose = false;
for (;;) {
switch (iter.next(pts)) {
case SkPath::kMove_Verb:
for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
switch (verb) {
case SkPathVerb::kMove:
REPORTER_ASSERT(reporter, firstTime);
REPORTER_ASSERT(reporter, pts[0] == srcPts[0]);
srcPts++;
firstTime = false;
break;
case SkPath::kLine_Verb:
case SkPathVerb::kLine:
REPORTER_ASSERT(reporter, !firstTime);
REPORTER_ASSERT(reporter, pts[1] == srcPts[0]);
srcPts++;
break;
case SkPath::kQuad_Verb:
case SkPathVerb::kQuad:
REPORTER_ASSERT(reporter, false, "unexpected quad verb");
break;
case SkPath::kConic_Verb:
case SkPathVerb::kConic:
REPORTER_ASSERT(reporter, false, "unexpected conic verb");
break;
case SkPath::kCubic_Verb:
case SkPathVerb::kCubic:
REPORTER_ASSERT(reporter, false, "unexpected cubic verb");
break;
case SkPath::kClose_Verb:
case SkPathVerb::kClose:
REPORTER_ASSERT(reporter, !firstTime);
REPORTER_ASSERT(reporter, !foundClose);
REPORTER_ASSERT(reporter, expectClose);
foundClose = true;
break;
case SkPath::kDone_Verb:
goto DONE;
}
}
DONE:
REPORTER_ASSERT(reporter, foundClose == expectClose);
}
@ -2276,17 +2270,14 @@ static void test_is_simple_closed_rect(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleClosedRect(path2, &r, &d, &s));
// Make the path by hand, manually closing it.
path2.reset();
SkPath::RawIter iter(path);
SkPath::Verb v;
SkPoint verbPts[4];
SkPoint firstPt = {0.f, 0.f};
while ((v = iter.next(verbPts)) != SkPath::kDone_Verb) {
for (auto [v, verbPts, w] : SkPathPriv::Iterate(path)) {
switch(v) {
case SkPath::kMove_Verb:
case SkPathVerb::kMove:
firstPt = verbPts[0];
path2.moveTo(verbPts[0]);
break;
case SkPath::kLine_Verb:
case SkPathVerb::kLine:
path2.lineTo(verbPts[1]);
break;
default:
@ -3055,78 +3046,106 @@ static void test_iter(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, SK_ScalarRoot2Over2 == iter.conicWeight());
}
static void test_raw_iter(skiatest::Reporter* reporter) {
SkPath p;
SkPoint pts[4];
// Test an iterator with no path
SkPath::RawIter noPathIter;
REPORTER_ASSERT(reporter, noPathIter.next(pts) == SkPath::kDone_Verb);
// Test that setting an empty path works
noPathIter.setPath(p);
REPORTER_ASSERT(reporter, noPathIter.next(pts) == SkPath::kDone_Verb);
static void test_range_iter(skiatest::Reporter* reporter) {
SkPath path;
// Test an iterator with an initial empty path
SkPath::RawIter iter(p);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kDone_Verb);
SkPathPriv::Iterate iterate(path);
REPORTER_ASSERT(reporter, iterate.begin() == iterate.end());
// Test that a move-only path returns the move.
p.moveTo(SK_Scalar1, 0);
iter.setPath(p);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kMove_Verb);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1);
REPORTER_ASSERT(reporter, pts[0].fY == 0);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kDone_Verb);
path.moveTo(SK_Scalar1, 0);
iterate = SkPathPriv::Iterate(path);
SkPathPriv::RangeIter iter = iterate.begin();
{
auto [verb, pts, w] = *iter++;
REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1);
REPORTER_ASSERT(reporter, pts[0].fY == 0);
}
REPORTER_ASSERT(reporter, iter == iterate.end());
// No matter how many moves we add, we should get them all back
p.moveTo(SK_Scalar1*2, SK_Scalar1);
p.moveTo(SK_Scalar1*3, SK_Scalar1*2);
iter.setPath(p);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kMove_Verb);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1);
REPORTER_ASSERT(reporter, pts[0].fY == 0);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kMove_Verb);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*2);
REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kMove_Verb);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*3);
REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1*2);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kDone_Verb);
path.moveTo(SK_Scalar1*2, SK_Scalar1);
path.moveTo(SK_Scalar1*3, SK_Scalar1*2);
iterate = SkPathPriv::Iterate(path);
iter = iterate.begin();
{
auto [verb, pts, w] = *iter++;
REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1);
REPORTER_ASSERT(reporter, pts[0].fY == 0);
}
{
auto [verb, pts, w] = *iter++;
REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*2);
REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1);
}
{
auto [verb, pts, w] = *iter++;
REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*3);
REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1*2);
}
REPORTER_ASSERT(reporter, iter == iterate.end());
// Initial close is never ever stored
p.reset();
p.close();
iter.setPath(p);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kDone_Verb);
path.reset();
path.close();
iterate = SkPathPriv::Iterate(path);
REPORTER_ASSERT(reporter, iterate.begin() == iterate.end());
// Move/close sequences
p.reset();
p.close(); // Not stored, no purpose
p.moveTo(SK_Scalar1, 0);
p.close();
p.close(); // Not stored, no purpose
p.moveTo(SK_Scalar1*2, SK_Scalar1);
p.close();
p.moveTo(SK_Scalar1*3, SK_Scalar1*2);
p.moveTo(SK_Scalar1*4, SK_Scalar1*3);
p.close();
iter.setPath(p);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kMove_Verb);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1);
REPORTER_ASSERT(reporter, pts[0].fY == 0);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kClose_Verb);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kMove_Verb);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*2);
REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kClose_Verb);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kMove_Verb);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*3);
REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1*2);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kMove_Verb);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*4);
REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1*3);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kClose_Verb);
REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kDone_Verb);
path.reset();
path.close(); // Not stored, no purpose
path.moveTo(SK_Scalar1, 0);
path.close();
path.close(); // Not stored, no purpose
path.moveTo(SK_Scalar1*2, SK_Scalar1);
path.close();
path.moveTo(SK_Scalar1*3, SK_Scalar1*2);
path.moveTo(SK_Scalar1*4, SK_Scalar1*3);
path.close();
iterate = SkPathPriv::Iterate(path);
iter = iterate.begin();
{
auto [verb, pts, w] = *iter++;
REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1);
REPORTER_ASSERT(reporter, pts[0].fY == 0);
}
{
auto [verb, pts, w] = *iter++;
REPORTER_ASSERT(reporter, verb == SkPathVerb::kClose);
}
{
auto [verb, pts, w] = *iter++;
REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*2);
REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1);
}
{
auto [verb, pts, w] = *iter++;
REPORTER_ASSERT(reporter, verb == SkPathVerb::kClose);
}
{
auto [verb, pts, w] = *iter++;
REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*3);
REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1*2);
}
{
auto [verb, pts, w] = *iter++;
REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove);
REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*4);
REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1*3);
}
{
auto [verb, pts, w] = *iter++;
REPORTER_ASSERT(reporter, verb == SkPathVerb::kClose);
}
REPORTER_ASSERT(reporter, iter == iterate.end());
// Generate random paths and verify
SkPoint randomPts[25];
@ -3138,12 +3157,12 @@ static void test_raw_iter(skiatest::Reporter* reporter) {
// Max of 10 segments, max 3 points per segment
SkRandom rand(9876543);
SkPoint expectedPts[31]; // May have leading moveTo
SkPath::Verb expectedVerbs[22]; // May have leading moveTo
SkPath::Verb nextVerb;
SkPoint expectedPts[31]; // May have leading moveTo
SkPathVerb expectedVerbs[22]; // May have leading moveTo
SkPathVerb nextVerb;
for (int i = 0; i < 500; ++i) {
p.reset();
path.reset();
bool lastWasClose = true;
bool haveMoveTo = false;
SkPoint lastMoveToPt = { 0, 0 };
@ -3152,69 +3171,69 @@ static void test_raw_iter(skiatest::Reporter* reporter) {
int numIterVerbs = 0;
for (int j = 0; j < numVerbs; ++j) {
do {
nextVerb = static_cast<SkPath::Verb>((rand.nextU() >> 16) % SkPath::kDone_Verb);
} while (lastWasClose && nextVerb == SkPath::kClose_Verb);
nextVerb = static_cast<SkPathVerb>((rand.nextU() >> 16) % SkPath::kDone_Verb);
} while (lastWasClose && nextVerb == SkPathVerb::kClose);
switch (nextVerb) {
case SkPath::kMove_Verb:
case SkPathVerb::kMove:
expectedPts[numPoints] = randomPts[(rand.nextU() >> 16) % 25];
p.moveTo(expectedPts[numPoints]);
path.moveTo(expectedPts[numPoints]);
lastMoveToPt = expectedPts[numPoints];
numPoints += 1;
lastWasClose = false;
haveMoveTo = true;
break;
case SkPath::kLine_Verb:
case SkPathVerb::kLine:
if (!haveMoveTo) {
expectedPts[numPoints++] = lastMoveToPt;
expectedVerbs[numIterVerbs++] = SkPath::kMove_Verb;
expectedVerbs[numIterVerbs++] = SkPathVerb::kMove;
haveMoveTo = true;
}
expectedPts[numPoints] = randomPts[(rand.nextU() >> 16) % 25];
p.lineTo(expectedPts[numPoints]);
path.lineTo(expectedPts[numPoints]);
numPoints += 1;
lastWasClose = false;
break;
case SkPath::kQuad_Verb:
case SkPathVerb::kQuad:
if (!haveMoveTo) {
expectedPts[numPoints++] = lastMoveToPt;
expectedVerbs[numIterVerbs++] = SkPath::kMove_Verb;
expectedVerbs[numIterVerbs++] = SkPathVerb::kMove;
haveMoveTo = true;
}
expectedPts[numPoints] = randomPts[(rand.nextU() >> 16) % 25];
expectedPts[numPoints + 1] = randomPts[(rand.nextU() >> 16) % 25];
p.quadTo(expectedPts[numPoints], expectedPts[numPoints + 1]);
path.quadTo(expectedPts[numPoints], expectedPts[numPoints + 1]);
numPoints += 2;
lastWasClose = false;
break;
case SkPath::kConic_Verb:
case SkPathVerb::kConic:
if (!haveMoveTo) {
expectedPts[numPoints++] = lastMoveToPt;
expectedVerbs[numIterVerbs++] = SkPath::kMove_Verb;
expectedVerbs[numIterVerbs++] = SkPathVerb::kMove;
haveMoveTo = true;
}
expectedPts[numPoints] = randomPts[(rand.nextU() >> 16) % 25];
expectedPts[numPoints + 1] = randomPts[(rand.nextU() >> 16) % 25];
p.conicTo(expectedPts[numPoints], expectedPts[numPoints + 1],
rand.nextUScalar1() * 4);
path.conicTo(expectedPts[numPoints], expectedPts[numPoints + 1],
rand.nextUScalar1() * 4);
numPoints += 2;
lastWasClose = false;
break;
case SkPath::kCubic_Verb:
case SkPathVerb::kCubic:
if (!haveMoveTo) {
expectedPts[numPoints++] = lastMoveToPt;
expectedVerbs[numIterVerbs++] = SkPath::kMove_Verb;
expectedVerbs[numIterVerbs++] = SkPathVerb::kMove;
haveMoveTo = true;
}
expectedPts[numPoints] = randomPts[(rand.nextU() >> 16) % 25];
expectedPts[numPoints + 1] = randomPts[(rand.nextU() >> 16) % 25];
expectedPts[numPoints + 2] = randomPts[(rand.nextU() >> 16) % 25];
p.cubicTo(expectedPts[numPoints], expectedPts[numPoints + 1],
expectedPts[numPoints + 2]);
path.cubicTo(expectedPts[numPoints], expectedPts[numPoints + 1],
expectedPts[numPoints + 2]);
numPoints += 3;
lastWasClose = false;
break;
case SkPath::kClose_Verb:
p.close();
case SkPathVerb::kClose:
path.close();
haveMoveTo = false;
lastWasClose = true;
break;
@ -3224,7 +3243,6 @@ static void test_raw_iter(skiatest::Reporter* reporter) {
expectedVerbs[numIterVerbs++] = nextVerb;
}
iter.setPath(p);
numVerbs = numIterVerbs;
numIterVerbs = 0;
int numIterPts = 0;
@ -3232,25 +3250,25 @@ static void test_raw_iter(skiatest::Reporter* reporter) {
SkPoint lastPt;
lastMoveTo.set(0, 0);
lastPt.set(0, 0);
while ((nextVerb = iter.next(pts)) != SkPath::kDone_Verb) {
for (auto [nextVerb, pts, w] : SkPathPriv::Iterate(path)) {
REPORTER_ASSERT(reporter, nextVerb == expectedVerbs[numIterVerbs]);
numIterVerbs++;
switch (nextVerb) {
case SkPath::kMove_Verb:
case SkPathVerb::kMove:
REPORTER_ASSERT(reporter, numIterPts < numPoints);
REPORTER_ASSERT(reporter, pts[0] == expectedPts[numIterPts]);
lastPt = lastMoveTo = pts[0];
numIterPts += 1;
break;
case SkPath::kLine_Verb:
case SkPathVerb::kLine:
REPORTER_ASSERT(reporter, numIterPts < numPoints + 1);
REPORTER_ASSERT(reporter, pts[0] == lastPt);
REPORTER_ASSERT(reporter, pts[1] == expectedPts[numIterPts]);
lastPt = pts[1];
numIterPts += 1;
break;
case SkPath::kQuad_Verb:
case SkPath::kConic_Verb:
case SkPathVerb::kQuad:
case SkPathVerb::kConic:
REPORTER_ASSERT(reporter, numIterPts < numPoints + 2);
REPORTER_ASSERT(reporter, pts[0] == lastPt);
REPORTER_ASSERT(reporter, pts[1] == expectedPts[numIterPts]);
@ -3258,7 +3276,7 @@ static void test_raw_iter(skiatest::Reporter* reporter) {
lastPt = pts[2];
numIterPts += 2;
break;
case SkPath::kCubic_Verb:
case SkPathVerb::kCubic:
REPORTER_ASSERT(reporter, numIterPts < numPoints + 3);
REPORTER_ASSERT(reporter, pts[0] == lastPt);
REPORTER_ASSERT(reporter, pts[1] == expectedPts[numIterPts]);
@ -3267,7 +3285,7 @@ static void test_raw_iter(skiatest::Reporter* reporter) {
lastPt = pts[3];
numIterPts += 3;
break;
case SkPath::kClose_Verb:
case SkPathVerb::kClose:
lastPt = lastMoveTo;
break;
default:
@ -3773,56 +3791,52 @@ static void test_arc_ovals(skiatest::Reporter* reporter) {
}
}
static void check_move(skiatest::Reporter* reporter, SkPath::RawIter* iter,
static void check_move(skiatest::Reporter* reporter, SkPathPriv::RangeIter* iter,
SkScalar x0, SkScalar y0) {
SkPoint pts[4];
SkPath::Verb v = iter->next(pts);
REPORTER_ASSERT(reporter, v == SkPath::kMove_Verb);
auto [v, pts, w] = *(*iter)++;
REPORTER_ASSERT(reporter, v == SkPathVerb::kMove);
REPORTER_ASSERT(reporter, pts[0].fX == x0);
REPORTER_ASSERT(reporter, pts[0].fY == y0);
}
static void check_line(skiatest::Reporter* reporter, SkPath::RawIter* iter,
static void check_line(skiatest::Reporter* reporter, SkPathPriv::RangeIter* iter,
SkScalar x1, SkScalar y1) {
SkPoint pts[4];
SkPath::Verb v = iter->next(pts);
REPORTER_ASSERT(reporter, v == SkPath::kLine_Verb);
auto [v, pts, w] = *(*iter)++;
REPORTER_ASSERT(reporter, v == SkPathVerb::kLine);
REPORTER_ASSERT(reporter, pts[1].fX == x1);
REPORTER_ASSERT(reporter, pts[1].fY == y1);
}
static void check_quad(skiatest::Reporter* reporter, SkPath::RawIter* iter,
static void check_quad(skiatest::Reporter* reporter, SkPathPriv::RangeIter* iter,
SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
SkPoint pts[4];
SkPath::Verb v = iter->next(pts);
REPORTER_ASSERT(reporter, v == SkPath::kQuad_Verb);
auto [v, pts, w] = *(*iter)++;
REPORTER_ASSERT(reporter, v == SkPathVerb::kQuad);
REPORTER_ASSERT(reporter, pts[1].fX == x1);
REPORTER_ASSERT(reporter, pts[1].fY == y1);
REPORTER_ASSERT(reporter, pts[2].fX == x2);
REPORTER_ASSERT(reporter, pts[2].fY == y2);
}
static void check_done(skiatest::Reporter* reporter, SkPath* p, SkPath::RawIter* iter) {
SkPoint pts[4];
SkPath::Verb v = iter->next(pts);
REPORTER_ASSERT(reporter, v == SkPath::kDone_Verb);
static void check_done(skiatest::Reporter* reporter, SkPath* p, SkPathPriv::RangeIter* iter) {
REPORTER_ASSERT(reporter, *iter == SkPathPriv::Iterate(*p).end());
}
static void check_done_and_reset(skiatest::Reporter* reporter, SkPath* p, SkPath::RawIter* iter) {
static void check_done_and_reset(skiatest::Reporter* reporter, SkPath* p,
SkPathPriv::RangeIter* iter) {
check_done(reporter, p, iter);
p->reset();
}
static void check_path_is_move_and_reset(skiatest::Reporter* reporter, SkPath* p,
SkScalar x0, SkScalar y0) {
SkPath::RawIter iter(*p);
SkPathPriv::RangeIter iter = SkPathPriv::Iterate(*p).begin();
check_move(reporter, &iter, x0, y0);
check_done_and_reset(reporter, p, &iter);
}
static void check_path_is_line_and_reset(skiatest::Reporter* reporter, SkPath* p,
SkScalar x1, SkScalar y1) {
SkPath::RawIter iter(*p);
SkPathPriv::RangeIter iter = SkPathPriv::Iterate(*p).begin();
check_move(reporter, &iter, 0, 0);
check_line(reporter, &iter, x1, y1);
check_done_and_reset(reporter, p, &iter);
@ -3830,7 +3844,7 @@ static void check_path_is_line_and_reset(skiatest::Reporter* reporter, SkPath* p
static void check_path_is_line(skiatest::Reporter* reporter, SkPath* p,
SkScalar x1, SkScalar y1) {
SkPath::RawIter iter(*p);
SkPathPriv::RangeIter iter = SkPathPriv::Iterate(*p).begin();
check_move(reporter, &iter, 0, 0);
check_line(reporter, &iter, x1, y1);
check_done(reporter, p, &iter);
@ -3838,7 +3852,7 @@ static void check_path_is_line(skiatest::Reporter* reporter, SkPath* p,
static void check_path_is_line_pair_and_reset(skiatest::Reporter* reporter, SkPath* p,
SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
SkPath::RawIter iter(*p);
SkPathPriv::RangeIter iter = SkPathPriv::Iterate(*p).begin();
check_move(reporter, &iter, 0, 0);
check_line(reporter, &iter, x1, y1);
check_line(reporter, &iter, x2, y2);
@ -3847,7 +3861,7 @@ static void check_path_is_line_pair_and_reset(skiatest::Reporter* reporter, SkPa
static void check_path_is_quad_and_reset(skiatest::Reporter* reporter, SkPath* p,
SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
SkPath::RawIter iter(*p);
SkPathPriv::RangeIter iter = SkPathPriv::Iterate(*p).begin();
check_move(reporter, &iter, 0, 0);
check_quad(reporter, &iter, x1, y1, x2, y2);
check_done_and_reset(reporter, p, &iter);
@ -4906,7 +4920,7 @@ DEF_TEST(Paths, reporter) {
test_transform(reporter);
test_bounds(reporter);
test_iter(reporter);
test_raw_iter(reporter);
test_range_iter(reporter);
test_circle(reporter);
test_oval(reporter);
test_strokerec(reporter);
@ -5079,16 +5093,8 @@ DEF_TEST(PathRefSerialization, reporter) {
DEF_TEST(NonFinitePathIteration, reporter) {
SkPath path;
path.moveTo(SK_ScalarInfinity, SK_ScalarInfinity);
int verbs = 0;
SkPath::RawIter iter(path);
SkPoint pts[4];
while (iter.next(pts) != SkPath::kDone_Verb) {
verbs++;
}
REPORTER_ASSERT(reporter, verbs == 0);
SkPathPriv::Iterate iterate(path);
REPORTER_ASSERT(reporter, iterate.begin() == iterate.end());
}
DEF_TEST(AndroidArc, reporter) {

View File

@ -105,13 +105,9 @@ static void test_undetected_paths(skiatest::Reporter* reporter) {
// factory made corporate paths produced by SkPath.
SkPath dummyPath;
dummyPath.addCircle(0, 0, 10);
SkPath::RawIter iter(dummyPath);
SkPoint dummyPts[4];
SkPath::Verb v = iter.next(dummyPts);
REPORTER_ASSERT(reporter, SkPath::kMove_Verb == v);
v = iter.next(dummyPts);
REPORTER_ASSERT(reporter, SkPath::kConic_Verb == v);
const SkScalar weight = iter.conicWeight();
REPORTER_ASSERT(reporter, SkPath::kMove_Verb == SkPathPriv::VerbData(dummyPath)[0]);
REPORTER_ASSERT(reporter, SkPath::kConic_Verb == SkPathPriv::VerbData(dummyPath)[1]);
const SkScalar weight = SkPathPriv::ConicWeightData(dummyPath)[0];
SkPath path;
path.moveTo(0, 62.5f);

View File

@ -6,6 +6,7 @@
*/
#include "src/core/SkMathPriv.h"
#include "src/core/SkPathPriv.h"
#include "tests/SubsetPath.h"
SubsetPath::SubsetPath(const SkPath& path)
@ -61,22 +62,19 @@ bool SubsetPath::subset(bool testFailed, SkPath* sub) {
SubsetContours::SubsetContours(const SkPath& path)
: SubsetPath(path) {
SkPath::RawIter iter(fPath);
uint8_t verb;
SkPoint pts[4];
bool foundCurve = false;
int contourCount = 0;
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
switch (verb) {
case SkPath::kMove_Verb:
case SkPathVerb::kMove:
break;
case SkPath::kLine_Verb:
case SkPath::kQuad_Verb:
case SkPath::kConic_Verb:
case SkPath::kCubic_Verb:
case SkPathVerb::kLine:
case SkPathVerb::kQuad:
case SkPathVerb::kConic:
case SkPathVerb::kCubic:
foundCurve = true;
break;
case SkPath::kClose_Verb:
case SkPathVerb::kClose:
++contourCount;
foundCurve = false;
break;
@ -98,41 +96,38 @@ SkPath SubsetContours::getSubsetPath() const {
if (!fSelected.count()) {
return result;
}
SkPath::RawIter iter(fPath);
uint8_t verb;
SkPoint pts[4];
int contourCount = 0;
bool enabled = fSelected[0];
bool addMoveTo = true;
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
if (enabled && addMoveTo) {
result.moveTo(pts[0]);
addMoveTo = false;
}
switch (verb) {
case SkPath::kMove_Verb:
case SkPathVerb::kMove:
break;
case SkPath::kLine_Verb:
case SkPathVerb::kLine:
if (enabled) {
result.lineTo(pts[1]);
}
break;
case SkPath::kQuad_Verb:
case SkPathVerb::kQuad:
if (enabled) {
result.quadTo(pts[1], pts[2]);
}
break;
case SkPath::kConic_Verb:
case SkPathVerb::kConic:
if (enabled) {
result.conicTo(pts[1], pts[2], iter.conicWeight());
result.conicTo(pts[1], pts[2], *w);
}
break;
case SkPath::kCubic_Verb:
case SkPathVerb::kCubic:
if (enabled) {
result.cubicTo(pts[1], pts[2], pts[3]);
}
break;
case SkPath::kClose_Verb:
case SkPathVerb::kClose:
if (enabled) {
result.close();
}
@ -152,21 +147,18 @@ SkPath SubsetContours::getSubsetPath() const {
SubsetVerbs::SubsetVerbs(const SkPath& path)
: SubsetPath(path) {
SkPath::RawIter iter(fPath);
uint8_t verb;
SkPoint pts[4];
int verbCount = 0;
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
switch (verb) {
case SkPath::kMove_Verb:
case SkPathVerb::kMove:
break;
case SkPath::kLine_Verb:
case SkPath::kQuad_Verb:
case SkPath::kConic_Verb:
case SkPath::kCubic_Verb:
case SkPathVerb::kLine:
case SkPathVerb::kQuad:
case SkPathVerb::kConic:
case SkPathVerb::kCubic:
++verbCount;
break;
case SkPath::kClose_Verb:
case SkPathVerb::kClose:
break;
default:
SkDEBUGFAIL("bad verb");
@ -185,14 +177,11 @@ SkPath SubsetVerbs::getSubsetPath() const {
if (!fSelected.count()) {
return result;
}
SkPath::RawIter iter(fPath);
uint8_t verb;
SkPoint pts[4];
int verbIndex = 0;
bool addMoveTo = true;
bool addLineTo = false;
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
bool enabled = SkPath::kLine_Verb <= verb && verb <= SkPath::kCubic_Verb
for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
bool enabled = SkPathVerb::kLine <= verb && verb <= SkPathVerb::kCubic
? fSelected[verbIndex++] : false;
if (enabled) {
if (addMoveTo) {
@ -204,29 +193,29 @@ SkPath SubsetVerbs::getSubsetPath() const {
}
}
switch (verb) {
case SkPath::kMove_Verb:
case SkPathVerb::kMove:
break;
case SkPath::kLine_Verb:
case SkPathVerb::kLine:
if (enabled) {
result.lineTo(pts[1]);
}
break;
case SkPath::kQuad_Verb:
case SkPathVerb::kQuad:
if (enabled) {
result.quadTo(pts[1], pts[2]);
}
break;
case SkPath::kConic_Verb:
case SkPathVerb::kConic:
if (enabled) {
result.conicTo(pts[1], pts[2], iter.conicWeight());
result.conicTo(pts[1], pts[2], *w);
}
break;
case SkPath::kCubic_Verb:
case SkPathVerb::kCubic:
if (enabled) {
result.cubicTo(pts[1], pts[2], pts[3]);
}
break;
case SkPath::kClose_Verb:
case SkPathVerb::kClose:
result.close();
addMoveTo = true;
addLineTo = false;

View File

@ -1121,17 +1121,14 @@ void path_to_quads(const SkPath& path, SkPath* quadPath) {
SkTArray<SkPoint, true> qPts;
SkAutoConicToQuads converter;
const SkPoint* quadPts;
SkPath::RawIter iter(path);
uint8_t verb;
SkPoint pts[4];
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
switch (verb) {
case SkPath::kMove_Verb: quadPath->moveTo(pts[0].fX, pts[0].fY); break;
case SkPath::kLine_Verb: quadPath->lineTo(pts[1].fX, pts[1].fY); break;
case SkPath::kQuad_Verb:
case SkPathVerb::kMove: quadPath->moveTo(pts[0].fX, pts[0].fY); break;
case SkPathVerb::kLine: quadPath->lineTo(pts[1].fX, pts[1].fY); break;
case SkPathVerb::kQuad:
quadPath->quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
break;
case SkPath::kCubic_Verb:
case SkPathVerb::kCubic:
qPts.reset();
convertCubicToQuads(pts, SK_Scalar1, &qPts);
for (int i = 0; i < qPts.count(); i += 3) {
@ -1139,8 +1136,8 @@ void path_to_quads(const SkPath& path, SkPath* quadPath) {
qPts[i + 1].fX, qPts[i + 1].fY, qPts[i + 2].fX, qPts[i + 2].fY);
}
break;
case SkPath::kConic_Verb:
quadPts = converter.computeQuads(pts, iter.conicWeight(), SK_Scalar1);
case SkPathVerb::kConic:
quadPts = converter.computeQuads(pts, *w, SK_Scalar1);
for (int i = 0; i < converter.countQuads(); ++i) {
quadPath->quadTo(quadPts[i * 2 + 1].fX,
quadPts[i * 2 + 1].fY,
@ -1148,8 +1145,7 @@ void path_to_quads(const SkPath& path, SkPath* quadPath) {
quadPts[i * 2 + 2].fY);
}
break;
case SkPath::kClose_Verb: quadPath->close(); break;
default: SkDEBUGFAIL("bad verb"); return;
case SkPathVerb::kClose: quadPath->close(); break;
}
}
}
@ -1204,19 +1200,16 @@ public:
fOut->writeDecAsText(ibounds.fBottom);
fOut->writeText("\">\n");
SkPath::RawIter iter(quads);
uint8_t verb;
SkPoint pts[4];
bool contourOpen = false;
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
bool contourOpen = false;
for (auto [verb, pts, w] : SkPathPriv::Iterate(quads)) {
switch (verb) {
case SkPath::kMove_Verb:
case SkPathVerb::kMove:
if (contourOpen) {
fOut->writeText(" </contour>\n");
contourOpen = false;
}
break;
case SkPath::kLine_Verb:
case SkPathVerb::kLine:
if (!contourOpen) {
fOut->writeText(" <contour>\n");
this->writePoint(pts[0].fX, pts[0].fY, true);
@ -1224,7 +1217,7 @@ public:
}
this->writePoint(pts[1].fX, pts[1].fY, true);
break;
case SkPath::kQuad_Verb:
case SkPathVerb::kQuad:
if (!contourOpen) {
fOut->writeText(" <contour>\n");
this->writePoint(pts[0].fX, pts[0].fY, true);
@ -1233,7 +1226,7 @@ public:
this->writePoint(pts[1].fX, pts[1].fY, false);
this->writePoint(pts[2].fX, pts[2].fY, true);
break;
case SkPath::kClose_Verb:
case SkPathVerb::kClose:
if (contourOpen) {
fOut->writeText(" </contour>\n");
contourOpen = false;

View File

@ -17,6 +17,7 @@
#include "include/core/SkTypeface.h"
#include "include/private/SkTArray.h"
#include "src/core/SkOSFile.h"
#include "src/core/SkPathPriv.h"
#include "src/core/SkSpan.h"
#include "src/core/SkTSort.h"
#include "src/utils/SkOSPath.h"
@ -128,25 +129,22 @@ static void output_path_data(const SkFont& font,
uint16_t glyphID = font.unicharToGlyph(index);
SkPath path;
font.getPath(glyphID, &path);
SkPath::RawIter iter(path);
SkPath::Verb verb;
SkPoint pts[4];
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
*verbs->append() = verb;
for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
*verbs->append() = (SkPath::Verb)verb;
switch (verb) {
case SkPath::kMove_Verb:
case SkPathVerb::kMove:
output_points(&pts[0], emSize, 1, ptsOut);
break;
case SkPath::kLine_Verb:
case SkPathVerb::kLine:
output_points(&pts[1], emSize, 1, ptsOut);
break;
case SkPath::kQuad_Verb:
case SkPathVerb::kQuad:
output_points(&pts[1], emSize, 2, ptsOut);
break;
case SkPath::kCubic_Verb:
case SkPathVerb::kCubic:
output_points(&pts[1], emSize, 3, ptsOut);
break;
case SkPath::kClose_Verb:
case SkPathVerb::kClose:
break;
default:
SkDEBUGFAIL("bad verb");