Use pathbuilder or factories to keep path immutable
Change-Id: I57b0bdcc9e4da67e11ae10efaf48c839a1b6b230
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1061317
Reviewed-by: Kaylee Lubick <kjlubick@google.com>
Reviewed-by: Daniel Dilan <danieldilan@google.com>
Commit-Queue: Mike Reed <mike@reedtribe.org>
Commit-Queue: Kaylee Lubick <kjlubick@google.com>
diff --git a/modules/skottie/src/text/Font.cpp b/modules/skottie/src/text/Font.cpp
index 80537c7..cdcab02 100644
--- a/modules/skottie/src/text/Font.cpp
+++ b/modules/skottie/src/text/Font.cpp
@@ -9,6 +9,7 @@
#include "include/core/SkMatrix.h"
#include "include/core/SkPath.h"
+#include "include/core/SkPathBuilder.h"
#include "include/core/SkRect.h"
#include "include/core/SkSize.h"
#include "include/core/SkTypeface.h"
@@ -83,7 +84,7 @@
return false;
}
- path.transform(SkMatrix::Scale(kPtScale, kPtScale));
+ path = path.makeTransform(SkMatrix::Scale(kPtScale, kPtScale));
fCustomBuilder.setGlyph(glyph_id, advance, path);
@@ -117,6 +118,7 @@
return true;
}
+ SkPathBuilder builder;
for (const skjson::ObjectValue* jgrp : *jshapes) {
if (!jgrp) {
return false;
@@ -142,9 +144,10 @@
return false;
}
- path->addPath(path_node->getPath());
+ builder.addPath(path_node->getPath());
}
}
+ *path = builder.detach();
return true;
}
diff --git a/modules/skottie/src/text/TextAdapter.cpp b/modules/skottie/src/text/TextAdapter.cpp
index 73197ce..949fd09 100644
--- a/modules/skottie/src/text/TextAdapter.cpp
+++ b/modules/skottie/src/text/TextAdapter.cpp
@@ -41,6 +41,7 @@
#include "modules/sksg/include/SkSGTransform.h"
#include "modules/sksg/src/SkSGTransformPriv.h"
#include "modules/skshaper/include/SkShaper_factory.h"
+#include "src/core/SkPathPriv.h"
#include <algorithm>
#include <cmath>
@@ -211,9 +212,7 @@
// reinitialize cached contour data
auto path = static_cast<SkPath>(fPath);
if (reverse) {
- SkPath reversed;
- reversed.reverseAddPath(path);
- path = reversed;
+ path = SkPathPriv::ReversePath(path);
}
SkContourMeasureIter iter(path, /*forceClosed = */false);
diff --git a/modules/skparagraph/src/Decorations.cpp b/modules/skparagraph/src/Decorations.cpp
index 0e33508..2ab7d1c 100644
--- a/modules/skparagraph/src/Decorations.cpp
+++ b/modules/skparagraph/src/Decorations.cpp
@@ -51,7 +51,7 @@
switch (textStyle.getDecorationStyle()) {
case TextDecorationStyle::kWavy: {
calculateWaves(textStyle, context.clip);
- fPath.offset(x, y);
+ fPath = fPath.makeOffset(x, y);
painter->drawPath(fPath, fDecorStyle);
break;
}
diff --git a/modules/skparagraph/src/ParagraphImpl.cpp b/modules/skparagraph/src/ParagraphImpl.cpp
index 7a4b8c1..14645d9 100644
--- a/modules/skparagraph/src/ParagraphImpl.cpp
+++ b/modules/skparagraph/src/ParagraphImpl.cpp
@@ -3,6 +3,7 @@
#include "include/core/SkFontMetrics.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPath.h"
+#include "include/core/SkPathBuilder.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkSpan.h"
#include "include/core/SkTypeface.h"
@@ -1445,6 +1446,7 @@
}
int ParagraphImpl::getPath(int lineNumber, SkPath* dest) {
+ SkPathBuilder builder;
int notConverted = 0;
auto& line = fLines[lineNumber];
line.iterateThroughVisualRuns(
@@ -1470,13 +1472,12 @@
line.offset().fY + correctedBaseline);
SkRect rect = context.clip.makeOffset(offset);
struct Rec {
- SkPath* fPath;
+ SkPathBuilder* fBuilder;
SkPoint fOffset;
const SkPoint* fPos;
int fNotConverted;
} rec =
- {dest, SkPoint::Make(rect.left(), rect.top()),
- &run->positions()[context.pos], 0};
+ {&builder, SkPoint::Make(rect.left(), rect.top()), &run->positions()[context.pos], 0};
font.getPaths({&run->glyphs()[context.pos], context.size},
[](const SkPath* path, const SkMatrix& mx, void* ctx) {
Rec* rec = reinterpret_cast<Rec*>(ctx);
@@ -1484,7 +1485,7 @@
SkMatrix total = mx;
total.postTranslate(rec->fPos->fX + rec->fOffset.fX,
rec->fPos->fY + rec->fOffset.fY);
- rec->fPath->addPath(*path, total);
+ rec->fBuilder->addPath(*path, total);
} else {
rec->fNotConverted++;
}
@@ -1492,6 +1493,7 @@
}, &rec);
notConverted += rec.fNotConverted;
});
+ *dest = builder.detach();
return true;
});
@@ -1499,12 +1501,12 @@
}
SkPath Paragraph::GetPath(SkTextBlob* textBlob) {
- SkPath path;
+ SkPathBuilder builder;
SkTextBlobRunIterator iter(textBlob);
while (!iter.done()) {
SkFont font = iter.font();
- struct Rec { SkPath* fDst; SkPoint fOffset; const SkPoint* fPos; } rec =
- {&path, {textBlob->bounds().left(), textBlob->bounds().top()},
+ struct Rec { SkPathBuilder* fBuilder; SkPoint fOffset; const SkPoint* fPos; } rec =
+ {&builder, {textBlob->bounds().left(), textBlob->bounds().top()},
iter.points()};
font.getPaths({iter.glyphs(), iter.glyphCount()},
[](const SkPath* src, const SkMatrix& mx, void* ctx) {
@@ -1513,14 +1515,14 @@
SkMatrix tmp(mx);
tmp.postTranslate(rec->fPos->fX - rec->fOffset.fX,
rec->fPos->fY - rec->fOffset.fY);
- rec->fDst->addPath(*src, tmp);
+ rec->fBuilder->addPath(*src, tmp);
}
rec->fPos += 1;
},
&rec);
iter.next();
}
- return path;
+ return builder.detach();
}
bool ParagraphImpl::containsEmoji(SkTextBlob* textBlob) {
diff --git a/modules/sksg/src/SkSGMerge.cpp b/modules/sksg/src/SkSGMerge.cpp
index 4dd2dcb..b206c3c 100644
--- a/modules/sksg/src/SkSGMerge.cpp
+++ b/modules/sksg/src/SkSGMerge.cpp
@@ -71,23 +71,23 @@
SkASSERT(this->hasInval());
SkOpBuilder builder;
+ SkPathBuilder merger;
- fMerged.reset();
bool in_builder = false;
auto append = [&](const SkPath& path) {
if (in_builder) {
if (auto result = builder.resolve()) {
- fMerged = *result;
+ merger = *result;
}
in_builder = false;
}
- if (fMerged.isEmpty()) {
+ if (merger.isEmpty()) {
// First merge path determines the fill type.
- fMerged = path;
+ merger = path;
} else {
- fMerged.addPath(path);
+ merger.addPath(path);
}
};
@@ -101,7 +101,7 @@
}
if (!in_builder) {
- builder.add(fMerged, kUnion_SkPathOp);
+ builder.add(fMerged.snapshot(), kUnion_SkPathOp);
in_builder = true;
}
@@ -110,10 +110,11 @@
if (in_builder) {
if (auto result = builder.resolve()) {
- fMerged = *result;
+ merger = *result;
}
}
+ fMerged = merger.detach();
SkPathPriv::ShrinkToFit(&fMerged);
return fMerged.computeTightBounds();
diff --git a/modules/svg/src/SkSVGClipPath.cpp b/modules/svg/src/SkSVGClipPath.cpp
index 90c7fc7..102252b 100644
--- a/modules/svg/src/SkSVGClipPath.cpp
+++ b/modules/svg/src/SkSVGClipPath.cpp
@@ -26,7 +26,5 @@
const auto obbt = ctx.transformForCurrentOBB(fClipPathUnits);
const auto m = SkMatrix::Translate(obbt.offset.x, obbt.offset.y)
* SkMatrix::Scale(obbt.scale.x, obbt.scale.y);
- clip.transform(m);
-
- return clip;
+ return clip.makeTransform(m);
}
diff --git a/tests/AAClipTest.cpp b/tests/AAClipTest.cpp
index 3f3f479..13a114a 100644
--- a/tests/AAClipTest.cpp
+++ b/tests/AAClipTest.cpp
@@ -308,11 +308,10 @@
};
SkMask expected(gExpectedImage, SkIRect::MakeWH(4, 6), 4, SkMask::kA8_Format);
- SkPath path;
- path.addRect(SkRect::MakeXYWH(0, 0,
- SkIntToScalar(4), SkIntToScalar(2)));
- path.addRect(SkRect::MakeXYWH(0, SkIntToScalar(4),
- SkIntToScalar(4), SkIntToScalar(2)));
+ SkPath path = SkPathBuilder()
+ .addRect(SkRect::MakeXYWH(0, 0, 4, 2))
+ .addRect(SkRect::MakeXYWH(0, 4, 4, 2))
+ .detach();
{
skiatest::ReporterContext context(reporter, "noAA");
@@ -342,8 +341,7 @@
SkRRect rrect;
rrect.setRectXY(SkRect::MakeWH(100, 100), 5, 5);
- SkPath path;
- path.addRRect(rrect);
+ SkPath path = SkPath::RRect(rrect);
SkAAClip clip;
clip.setPath(path, path.getBounds().roundOut(), true);
@@ -420,8 +418,7 @@
//
DEF_TEST(AAClip_crbug_422693_AvoidOverflow, reporter) {
SkRasterClip rc(SkIRect::MakeLTRB(-25000, -25000, 25000, 25000));
- SkPath path;
- path.addCircle(50, 50, 50);
+ SkPath path = SkPath::Circle(50, 50, 50);
REPORTER_ASSERT(reporter, rc.op(path, SkMatrix::I(), SkClipOp::kIntersect, true));
}
diff --git a/tests/BlurTest.cpp b/tests/BlurTest.cpp
index d20013f..970086d 100644
--- a/tests/BlurTest.cpp
+++ b/tests/BlurTest.cpp
@@ -74,15 +74,15 @@
struct BlurTest {
- void (*addPath)(SkPath*);
+ SkPath (*addPath)();
int viewLen;
SkIRect views[9];
};
//Path Draw Procs
//Beware that paths themselves my draw differently depending on the clip.
-static void draw50x50Rect(SkPath* path) {
- path->addRect(0, 0, SkIntToScalar(50), SkIntToScalar(50));
+static SkPath draw50x50Rect() {
+ return SkPath::Rect({0, 0, 50, 50});
}
//Tests
@@ -143,8 +143,7 @@
paint.setMaskFilter(SkMaskFilter::MakeBlur(blurStyle, sigma, respectCTM));
for (size_t test = 0; test < std::size(tests); ++test) {
- SkPath path;
- tests[test].addPath(&path);
+ SkPath path = tests[test].addPath();
SkPath strokedPath = skpathutils::FillPathWithPaint(path, paint);
SkRect refBound = strokedPath.getBounds();
SkIRect iref;
@@ -320,8 +319,7 @@
// The geometry is offset a smidge to trigger:
// https://code.google.com/p/chromium/issues/detail?id=282418
- SkPath rectPath;
- rectPath.addRect(0.3f, 0.3f, 100.3f, 100.3f);
+ SkPath rectPath = SkPath::Rect({0.3f, 0.3f, 100.3f, 100.3f});
SkPoint polyPts[] = {
{ 0.3f, 0.3f },
diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp
index 3111fdd..b88a96b 100644
--- a/tests/CanvasTest.cpp
+++ b/tests/CanvasTest.cpp
@@ -244,9 +244,7 @@
}
static SkPath make_path_from_rect(SkRect r) {
- SkPath path;
- path.addRect(r);
- return path;
+ return SkPath::Rect(r);
}
static SkRegion make_region_from_irect(SkIRect r) {
diff --git a/tests/ClipStackTest.cpp b/tests/ClipStackTest.cpp
index 95319f3..81da862 100644
--- a/tests/ClipStackTest.cpp
+++ b/tests/ClipStackTest.cpp
@@ -82,8 +82,7 @@
// Test that version constructed with rect-path rather than a rect is still considered equal.
s.restore();
s.save();
- SkPath rp;
- rp.addRect(r);
+ SkPath rp = SkPath::Rect(r);
s.clipPath(rp, SkMatrix::I(), SkClipOp::kDifference, doAA);
REPORTER_ASSERT(reporter, s == copy);
@@ -230,10 +229,8 @@
rrectA.setOval(rectA);
rrectB.setRectXY(rectB, SkIntToScalar(1), SkIntToScalar(2));
- SkPath pathA, pathB;
-
- pathA.addRoundRect(rectA, SkIntToScalar(5), SkIntToScalar(5));
- pathB.addRoundRect(rectB, SkIntToScalar(5), SkIntToScalar(5));
+ SkPath pathA = SkPath::RRect(rectA, 5, 5),
+ pathB = SkPath::RRect(rectB, 5, 5);
SkClipStack stack;
SkRect devClipBound;
@@ -364,8 +361,7 @@
// non-intersecting rectangles
SkRect rect = SkRect::MakeLTRB(0, 0, 10, 10);
- SkPath path;
- path.addRect(rect);
+ SkPath path = SkPath::Rect(rect);
path.toggleInverseFillType();
SkClipStack stack;
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
@@ -460,8 +456,7 @@
stack->clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, doAA);
};
SkRect rect = SkRect::MakeWH(100, 100);
- SkPath path;
- path.addCircle(50, 50, 50);
+ SkPath path = SkPath::Circle(50, 50, 50);
// Emulating replace operations with more complex geometry is not atomic, it's a replace
// with a wide-open rect and then an intersection with the complex geometry. The replace can
@@ -586,14 +581,10 @@
SkRect outsideRect = SkRect::MakeLTRB(0, 0, 50, 50);
SkRect nonIntersectingRect = SkRect::MakeLTRB(100, 100, 110, 110);
- SkPath insideCircle;
- insideCircle.addCircle(25, 25, 5);
- SkPath intersectingCircle;
- intersectingCircle.addCircle(25, 40, 10);
- SkPath outsideCircle;
- outsideCircle.addCircle(25, 25, 50);
- SkPath nonIntersectingCircle;
- nonIntersectingCircle.addCircle(100, 100, 5);
+ SkPath insideCircle = SkPath::Circle(25, 25, 5);
+ SkPath intersectingCircle = SkPath::Circle(25, 40, 10);
+ SkPath outsideCircle = SkPath::Circle(25, 25, 50);
+ SkPath nonIntersectingCircle = SkPath::Circle(100, 100, 5);
{
SkClipStack stack;
@@ -689,8 +680,7 @@
// Intersect Op tests with inverse filled rectangles
{
SkClipStack stack;
- SkPath path;
- path.addRect(outsideRect);
+ SkPath path = SkPath::Rect(outsideRect);
path.toggleInverseFillType();
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
@@ -698,8 +688,7 @@
{
SkClipStack stack;
- SkPath path;
- path.addRect(insideRect);
+ SkPath path = SkPath::Rect(insideRect);
path.toggleInverseFillType();
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
@@ -707,8 +696,7 @@
{
SkClipStack stack;
- SkPath path;
- path.addRect(intersectingRect);
+ SkPath path = SkPath::Rect(intersectingRect);
path.toggleInverseFillType();
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
@@ -716,8 +704,7 @@
{
SkClipStack stack;
- SkPath path;
- path.addRect(nonIntersectingRect);
+ SkPath path = SkPath::Rect(nonIntersectingRect);
path.toggleInverseFillType();
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
@@ -782,8 +769,7 @@
SkClipStack stack;
stack.clipRect({10, 10, 20, 20}, SkMatrix::I(), SkClipOp::kIntersect, false);
- SkPath path;
- path.addRect({30, 10, 40, 20});
+ SkPath path = SkPath::Rect({30, 10, 40, 20});
path.setFillType(SkPathFillType::kInverseWinding);
stack.clipPath(path, SkMatrix::I(), SkClipOp::kDifference, false);
diff --git a/tests/DashPathEffectTest.cpp b/tests/DashPathEffectTest.cpp
index e0c021b..f1f067c 100644
--- a/tests/DashPathEffectTest.cpp
+++ b/tests/DashPathEffectTest.cpp
@@ -131,8 +131,7 @@
SkScalar vals[] = { 98, 94, 2888458849.f, 227, 0, 197 };
SkRect cull = SkRect::MakeXYWH(43,236,57,149);
- SkPath path;
- path.addRect(cull);
+ SkPath path = SkPath::Rect(cull);
SkPathBuilder builder;
SkPaint paint;
diff --git a/tests/DrawPathTest.cpp b/tests/DrawPathTest.cpp
index 8a8d2972..481ed99 100644
--- a/tests/DrawPathTest.cpp
+++ b/tests/DrawPathTest.cpp
@@ -363,8 +363,7 @@
SkPaint paint;
paint.setAntiAlias(true);
- SkPath path;
- path.addOval(SkRect::MakeXYWH(-10, -10, 20 + W, 20 + H));
+ SkPath path = SkPath::Oval(SkRect::MakeXYWH(-10, -10, 20 + W, 20 + H));
surface->getCanvas()->drawPath(path, paint);
}
diff --git a/tests/GrStyledShapeTest.cpp b/tests/GrStyledShapeTest.cpp
index 831754d..62e6f63 100644
--- a/tests/GrStyledShapeTest.cpp
+++ b/tests/GrStyledShapeTest.cpp
@@ -180,8 +180,8 @@
REPORTER_ASSERT(r, paths_fill_same(pathA, pathB));
REPORTER_ASSERT(r, ignoreInversenessDifference || invertedA == invertedB);
} else {
- SkPath pA = pathA;
- SkPath pB = pathB;
+ SkPathBuilder pA = pathA;
+ SkPathBuilder pB = pathB;
REPORTER_ASSERT(r, a.inverseFilled() == pA.isInverseFillType());
REPORTER_ASSERT(r, b.inverseFilled() == pB.isInverseFillType());
if (ignoreInversenessDifference) {
@@ -206,7 +206,7 @@
pA.close();
pB.close();
}
- REPORTER_ASSERT(r, pA == pB);
+ REPORTER_ASSERT(r, pA.detach() == pB.detach());
REPORTER_ASSERT(r, aIsRRect == bIsRRect);
if (aIsRRect) {
REPORTER_ASSERT(r, rrectA == rrectB);
@@ -369,9 +369,7 @@
RectGeo(const SkRect& rect) : fRect(rect) {}
SkPath path() const override {
- SkPath path;
- path.addRect(fRect);
- return path;
+ return SkPath::Rect(fRect);
}
GrStyledShape makeShape(const SkPaint& paint) const override {
@@ -399,9 +397,7 @@
}
SkPath path() const override {
- SkPath path;
- path.addRRect(fRRect);
- return path;
+ return SkPath::RRect(fRRect);
}
bool strokeAndFillIsConvertedToFill(const SkPaint& paint) const override {
@@ -2061,42 +2057,39 @@
}
};
- SkPath pathA;
- SkPath pathB;
+ // Two identical path/pathbuilder
+ SkPath pathA = SkPathBuilder()
+ .lineTo(10.f, 10.f)
+ .conicTo(20.f, 20.f, 20.f, 30.f, 0.7f)
+ .detach();
- // Two identical paths
- pathA.lineTo(10.f, 10.f);
- pathA.conicTo(20.f, 20.f, 20.f, 30.f, 0.7f);
-
- pathB.lineTo(10.f, 10.f);
- pathB.conicTo(20.f, 20.f, 20.f, 30.f, 0.7f);
- compare(pathA, pathB, TestCase::kAllSame_ComparisonExpecation);
+ SkPathBuilder pathB = SkPathBuilder()
+ .lineTo(10.f, 10.f)
+ .conicTo(20.f, 20.f, 20.f, 30.f, 0.7f);
+ compare(pathA, pathB.detach(), TestCase::kAllSame_ComparisonExpecation);
// Give path b a different point
- pathB.reset();
pathB.lineTo(10.f, 10.f);
pathB.conicTo(21.f, 20.f, 20.f, 30.f, 0.7f);
- compare(pathA, pathB, TestCase::kAllDifferent_ComparisonExpecation);
+ compare(pathA, pathB.detach(), TestCase::kAllDifferent_ComparisonExpecation);
// Give path b a different conic weight
pathB.reset();
pathB.lineTo(10.f, 10.f);
pathB.conicTo(20.f, 20.f, 20.f, 30.f, 0.6f);
- compare(pathA, pathB, TestCase::kAllDifferent_ComparisonExpecation);
+ compare(pathA, pathB.detach(), TestCase::kAllDifferent_ComparisonExpecation);
// Give path b an extra lineTo verb
- pathB.reset();
pathB.lineTo(10.f, 10.f);
pathB.conicTo(20.f, 20.f, 20.f, 30.f, 0.6f);
pathB.lineTo(50.f, 50.f);
- compare(pathA, pathB, TestCase::kAllDifferent_ComparisonExpecation);
+ compare(pathA, pathB.detach(), TestCase::kAllDifferent_ComparisonExpecation);
// Give path b a close
- pathB.reset();
pathB.lineTo(10.f, 10.f);
pathB.conicTo(20.f, 20.f, 20.f, 30.f, 0.7f);
pathB.close();
- compare(pathA, pathB, TestCase::kAllDifferent_ComparisonExpecation);
+ compare(pathA, pathB.detach(), TestCase::kAllDifferent_ComparisonExpecation);
}
DEF_TEST(GrStyledShape, reporter) {
@@ -2108,8 +2101,7 @@
SkRect::MakeWH(-10, 20),
SkRect::MakeWH(10, -20)}) {
geos.emplace_back(new RectGeo(r));
- SkPath rectPath;
- rectPath.addRect(r);
+ SkPath rectPath = SkPath::Rect(r);
geos.emplace_back(new RRectPathGeo(rectPath, r, RRectPathGeo::RRectForStroke::kYes,
PathGeo::Invert::kNo));
geos.emplace_back(new RRectPathGeo(rectPath, r, RRectPathGeo::RRectForStroke::kYes,
@@ -2122,8 +2114,7 @@
SkRRect::MakeOval(SkRect::MakeWH(20, 20))}) {
geos.emplace_back(new RRectGeo(rr));
test_rrect(reporter, rr);
- SkPath rectPath;
- rectPath.addRRect(rr);
+ SkPath rectPath = SkPath::RRect(rr);
geos.emplace_back(new RRectPathGeo(rectPath, rr, RRectPathGeo::RRectForStroke::kYes,
PathGeo::Invert::kNo));
geos.emplace_back(new RRectPathGeo(rectPath, rr, RRectPathGeo::RRectForStroke::kYes,
@@ -2336,10 +2327,13 @@
}
DEF_TEST(GrShapeInversion, r) {
- SkPath path;
- SkScalar radii[] = {10.f, 10.f, 10.f, 10.f,
- 10.f, 10.f, 10.f, 10.f};
- path.addRoundRect(SkRect::MakeWH(50, 50), radii);
+ const SkVector radii[] = {
+ {10.f, 10.f}, {10.f, 10.f},
+ {10.f, 10.f}, {10.f, 10.f}
+ };
+ SkRRect rr;
+ rr.setRectRadii(SkRect::MakeWH(50, 50), radii);
+ SkPath path = SkPath::RRect(rr);
path.toggleInverseFillType();
GrShape inverseRRect(path);
diff --git a/tests/LazyStencilAttachmentTest.cpp b/tests/LazyStencilAttachmentTest.cpp
index d419af3..c6d1ed4 100644
--- a/tests/LazyStencilAttachmentTest.cpp
+++ b/tests/LazyStencilAttachmentTest.cpp
@@ -13,6 +13,7 @@
#include "include/core/SkImageInfo.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
+#include "include/core/SkPathBuilder.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
@@ -55,9 +56,10 @@
}
auto drawWithStencilClip = [&](SkSurface& surf, SkColor color) {
- SkPath clip;
- clip.addCircle(50, 50, 50);
- clip.addCircle(50, 50, 10, SkPathDirection::kCCW);
+ SkPath clip = SkPathBuilder()
+ .addCircle(50, 50, 50)
+ .addCircle(50, 50, 10, SkPathDirection::kCCW)
+ .detach();
SkPaint paint;
paint.setColor(color);
surf.getCanvas()->clipPath(clip, false);
diff --git a/tests/MultiPictureDocumentTest.cpp b/tests/MultiPictureDocumentTest.cpp
index 89215b3..423b7d4 100644
--- a/tests/MultiPictureDocumentTest.cpp
+++ b/tests/MultiPictureDocumentTest.cpp
@@ -16,6 +16,7 @@
#include "include/core/SkImageInfo.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
+#include "include/core/SkPathBuilder.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkRRect.h"
@@ -64,8 +65,9 @@
paint.setColor(SK_ColorYELLOW);
canvas->drawRoundRect(rect, 10, 10, paint);
- SkPath path;
- path.cubicTo(768, 0, -512, 256, 256, 256);
+ SkPath path = SkPathBuilder()
+ .cubicTo(768, 0, -512, 256, 256, 256)
+ .detach();
paint.setColor(SK_ColorGREEN);
canvas->drawPath(path, paint);
diff --git a/tests/ParsePathTest.cpp b/tests/ParsePathTest.cpp
index ddf8a7e..28785b1 100644
--- a/tests/ParsePathTest.cpp
+++ b/tests/ParsePathTest.cpp
@@ -6,6 +6,7 @@
*/
#include "include/core/SkPath.h"
+#include "include/core/SkPathBuilder.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkString.h"
@@ -59,13 +60,13 @@
SkRect r;
r.setLTRB(0, 0, 10, 10.5f);
- SkPath p;
+ SkPathBuilder p;
p.addRect(r);
- test_to_from(reporter, p);
+ test_to_from(reporter, p.snapshot());
p.addOval(r);
- test_to_from(reporter, p);
- p.addRoundRect(r, 4, 4.5f);
- test_to_from(reporter, p);
+ test_to_from(reporter, p.snapshot());
+ p.addRRect(SkRRect::MakeRectXY(r, 4, 4.5f));
+ test_to_from(reporter, p.snapshot());
}
static void testInvalidPath(skiatest::Reporter* reporter, const std::string& name,
diff --git a/tests/PathBuilderTest.cpp b/tests/PathBuilderTest.cpp
index c57014f..abac7f9 100644
--- a/tests/PathBuilderTest.cpp
+++ b/tests/PathBuilderTest.cpp
@@ -147,8 +147,7 @@
REPORTER_ASSERT(reporter, closed);
REPORTER_ASSERT(reporter, dir == dir2);
- SkPath p;
- p.addRect(r, dir, i);
+ SkPath p = SkPath::Rect(r, dir, i);
REPORTER_ASSERT(reporter, p == bp);
// do it again, after the detach
@@ -211,8 +210,7 @@
for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
for (int i = 0; i < 4; ++i) {
auto bp = SkPathBuilder().addOval(r, dir, i).detach();
- SkPath p;
- p.addOval(r, dir, i);
+ SkPath p = SkPath::Oval(r, dir, i);
REPORTER_ASSERT(reporter, is_eq(p, bp));
SkRect bounds;
@@ -222,8 +220,7 @@
REPORTER_ASSERT(reporter, bp.isConvex());
}
auto bp = SkPathBuilder().addOval(r, dir).detach();
- SkPath p;
- p.addOval(r, dir);
+ SkPath p = SkPath::Oval(r, dir);
REPORTER_ASSERT(reporter, is_eq(p, bp));
// test negative case -- can't have any other segments
@@ -243,13 +240,11 @@
b.addRRect(rr, dir, i);
auto bp = b.detach();
- SkPath p;
- p.addRRect(rr, dir, i);
+ SkPath p = SkPath::RRect(rr, dir, i);
REPORTER_ASSERT(reporter, is_eq(p, bp));
}
auto bp = SkPathBuilder().addRRect(rr, dir).detach();
- SkPath p;
- p.addRRect(rr, dir);
+ SkPath p = SkPath::RRect(rr, dir);
REPORTER_ASSERT(reporter, is_eq(p, bp));
// test negative case -- can't have any other segments
@@ -509,11 +504,11 @@
};
for (auto e : expectations) {
+ SkPath path;
#ifndef SK_HIDE_PATH_EDIT_METHODS
- auto path = path_add(e.fStartWithMove, e.fMode);
+ path = path_add(e.fStartWithMove, e.fMode);
REPORTER_ASSERT(reporter, path.isConvex() == e.fShouldBeConvex);
#endif
-
path = builder_add(e.fStartWithMove, e.fMode);
REPORTER_ASSERT(reporter, path.isConvex() == e.fShouldBeConvex);
}
@@ -579,6 +574,7 @@
* either the classic mutable apis, or via SkPathBuilder (SkPath::Polygon uses builder).
*/
DEF_TEST(pathbuilder_lastmoveindex, reporter) {
+#ifndef SK_HIDE_PATH_EDIT_METHODS
const SkPoint pts[] = {
{0, 1}, {2, 3}, {4, 5},
};
@@ -606,6 +602,7 @@
REPORTER_ASSERT(reporter, b_last == expected);
}
}
+#endif
}
static void assertIsMoveTo(skiatest::Reporter* reporter, SkPathPriv::RangeIter* iter,
@@ -830,7 +827,7 @@
}
DEF_TEST(SkPathBuilder_Path_arcTo, reporter) {
-
+#ifndef SK_HIDE_PATH_EDIT_METHODS
auto check_both_methods = [reporter](const SkRect& r, float start, float sweep) {
SkPath path;
path.arcTo(r, start, sweep, true);
@@ -855,6 +852,7 @@
sweep = rand.nextSScalar1() * 1000;
check_both_methods(r, start, sweep);
}
+#endif
}
DEF_TEST(SkPathBuilder_cleaning, reporter) {
diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp
index a39989a..e36be94 100644
--- a/tests/PathTest.cpp
+++ b/tests/PathTest.cpp
@@ -69,9 +69,8 @@
rrect.setRectRadii(bounds, radii);
REPORTER_ASSERT(reporter, bounds == rrect.rect());
- SkPath path;
// this line should not assert in the debug build (from validate)
- path.addRRect(rrect);
+ SkPath path = SkPath::RRect(rrect);
REPORTER_ASSERT(reporter, bounds == path.getBounds());
}
@@ -373,51 +372,57 @@
static void test_path_close_issue1474(skiatest::Reporter* reporter) {
// This test checks that r{Line,Quad,Conic,Cubic}To following a close()
// are relative to the point we close to, not relative to the point we close from.
- SkPath path;
- SkPoint last;
// Test rLineTo().
- path.rLineTo(0, 100);
- path.rLineTo(100, 0);
- path.close(); // Returns us back to 0,0.
- path.rLineTo(50, 50); // This should go to 50,50.
-
- path.getLastPt(&last);
- REPORTER_ASSERT(reporter, 50 == last.fX);
- REPORTER_ASSERT(reporter, 50 == last.fY);
+ SkPath path = SkPathBuilder()
+ .rLineTo(0, 100)
+ .rLineTo(100, 0)
+ .close() // Returns us back to 0,0.
+ .rLineTo(50, 50) // This should go to 50,50.
+ .detach();
+ auto last = path.getLastPt();
+ REPORTER_ASSERT(reporter, last.has_value());
+ REPORTER_ASSERT(reporter, 50 == last->fX);
+ REPORTER_ASSERT(reporter, 50 == last->fY);
// Test rQuadTo().
- path.rewind();
- path.rLineTo(0, 100);
- path.rLineTo(100, 0);
- path.close();
- path.rQuadTo(50, 50, 75, 75);
+ path = SkPathBuilder()
+ .rLineTo(0, 100)
+ .rLineTo(100, 0)
+ .close()
+ .rQuadTo(50, 50, 75, 75)
+ .detach();
- path.getLastPt(&last);
- REPORTER_ASSERT(reporter, 75 == last.fX);
- REPORTER_ASSERT(reporter, 75 == last.fY);
+ last = path.getLastPt();
+ REPORTER_ASSERT(reporter, last.has_value());
+ REPORTER_ASSERT(reporter, 75 == last->fX);
+ REPORTER_ASSERT(reporter, 75 == last->fY);
// Test rConicTo().
- path.rewind();
- path.rLineTo(0, 100);
- path.rLineTo(100, 0);
- path.close();
- path.rConicTo(50, 50, 85, 85, 2);
+ path = SkPathBuilder()
+ .rLineTo(0, 100)
+ .rLineTo(100, 0)
+ .close()
+ .rConicTo(50, 50, 85, 85, 2)
+ .detach();
- path.getLastPt(&last);
- REPORTER_ASSERT(reporter, 85 == last.fX);
- REPORTER_ASSERT(reporter, 85 == last.fY);
+ last = path.getLastPt();
+ REPORTER_ASSERT(reporter, last.has_value());
+ REPORTER_ASSERT(reporter, 85 == last->fX);
+ REPORTER_ASSERT(reporter, 85 == last->fY);
// Test rCubicTo().
- path.rewind();
- path.rLineTo(0, 100);
- path.rLineTo(100, 0);
- path.close();
- path.rCubicTo(50, 50, 85, 85, 95, 95);
+ path = SkPathBuilder()
+ .rLineTo(0, 100)
+ .rLineTo(100, 0)
+ .close()
+ .rCubicTo(50, 50, 85, 85, 95, 95)
+ .detach();
- path.getLastPt(&last);
- REPORTER_ASSERT(reporter, 95 == last.fX);
- REPORTER_ASSERT(reporter, 95 == last.fY);
+ last = path.getLastPt();
+ REPORTER_ASSERT(reporter, last.has_value());
+ REPORTER_ASSERT(reporter, 95 == last->fX);
+ REPORTER_ASSERT(reporter, 95 == last->fY);
}
static void test_gen_id(skiatest::Reporter* reporter) {
@@ -667,10 +672,11 @@
}
static void test_crbug_613918() {
- SkPath path;
- path.conicTo(-6.62478e-08f, 4.13885e-08f, -6.36935e-08f, 3.97927e-08f, 0.729058f);
- path.quadTo(2.28206e-09f, -1.42572e-09f, 3.91919e-09f, -2.44852e-09f);
- path.cubicTo(-16752.2f, -26792.9f, -21.4673f, 10.9347f, -8.57322f, -7.22739f);
+ SkPath path = SkPathBuilder()
+ .conicTo(-6.62478e-08f, 4.13885e-08f, -6.36935e-08f, 3.97927e-08f, 0.729058f)
+ .quadTo(2.28206e-09f, -1.42572e-09f, 3.91919e-09f, -2.44852e-09f)
+ .cubicTo(-16752.2f, -26792.9f, -21.4673f, 10.9347f, -8.57322f, -7.22739f)
+ .detach();
// This call could lead to an assert or uninitialized read due to a failure
// to check the return value from SkCubicClipper::ChopMonoAtY.
@@ -678,29 +684,34 @@
}
static void test_addrect(skiatest::Reporter* reporter) {
- SkPath path;
- path.lineTo(0, 0);
- path.addRect(SkRect::MakeWH(50, 100));
+ SkPath path = SkPathBuilder()
+ .lineTo(0, 0)
+ .addRect(SkRect::MakeWH(50, 100))
+ .detach();
REPORTER_ASSERT(reporter, path.isRect(nullptr));
- path.reset();
- path.lineTo(FLT_EPSILON, FLT_EPSILON);
- path.addRect(SkRect::MakeWH(50, 100));
+ path = SkPathBuilder()
+ .lineTo(FLT_EPSILON, FLT_EPSILON)
+ .addRect(SkRect::MakeWH(50, 100))
+ .detach();
REPORTER_ASSERT(reporter, !path.isRect(nullptr));
- path.reset();
- path.quadTo(0, 0, 0, 0);
- path.addRect(SkRect::MakeWH(50, 100));
+ path = SkPathBuilder()
+ .quadTo(0, 0, 0, 0)
+ .addRect(SkRect::MakeWH(50, 100))
+ .detach();
REPORTER_ASSERT(reporter, !path.isRect(nullptr));
- path.reset();
- path.conicTo(0, 0, 0, 0, 0.5f);
- path.addRect(SkRect::MakeWH(50, 100));
+ path = SkPathBuilder()
+ .conicTo(0, 0, 0, 0, 0.5f)
+ .addRect(SkRect::MakeWH(50, 100))
+ .detach();
REPORTER_ASSERT(reporter, !path.isRect(nullptr));
- path.reset();
- path.cubicTo(0, 0, 0, 0, 0, 0);
- path.addRect(SkRect::MakeWH(50, 100));
+ path = SkPathBuilder()
+ .cubicTo(0, 0, 0, 0, 0, 0)
+ .addRect(SkRect::MakeWH(50, 100))
+ .detach();
REPORTER_ASSERT(reporter, !path.isRect(nullptr));
}
@@ -827,9 +838,10 @@
// Inspired by http://code.google.com/p/chromium/issues/detail?id=141651
//
static void test_isfinite_after_transform(skiatest::Reporter* reporter) {
- SkPath path;
- path.quadTo(157, 366, 286, 208);
- path.arcTo(37, 442, 315, 163, 957494590897113.0f);
+ SkPath path = SkPathBuilder()
+ .quadTo(157, 366, 286, 208)
+ .arcTo({37, 442}, {315, 163}, 957494590897113.0f)
+ .detach();
SkMatrix matrix;
matrix.setScale(1000*1000, 1000*1000);
@@ -841,18 +853,18 @@
while (path.isFinite()) {
REPORTER_ASSERT(reporter, path.getBounds().isFinite());
REPORTER_ASSERT(reporter, !path.getBounds().isEmpty());
- path.transform(matrix);
+ path = path.makeTransform(matrix);
}
REPORTER_ASSERT(reporter, path.getBounds().isEmpty());
matrix.setTranslate(SK_Scalar1, SK_Scalar1);
- path.transform(matrix);
+ path = path.makeTransform(matrix);
// we need to still be non-finite
REPORTER_ASSERT(reporter, !path.isFinite());
REPORTER_ASSERT(reporter, path.getBounds().isEmpty());
}
-static void add_corner_arc(SkPath* path, const SkRect& rect,
+static void add_corner_arc(SkPathBuilder* builder, const SkRect& rect,
SkScalar xIn, SkScalar yIn,
int startAngle)
{
@@ -879,17 +891,18 @@
break;
}
- path->arcTo(arcRect, SkIntToScalar(startAngle), SkIntToScalar(90), false);
+ builder->arcTo(arcRect, SkIntToScalar(startAngle), SkIntToScalar(90), false);
}
-static void make_arb_round_rect(SkPath* path, const SkRect& r,
- SkScalar xCorner, SkScalar yCorner) {
+static SkPath make_arb_round_rect(const SkRect& r, SkScalar xCorner, SkScalar yCorner) {
+ SkPathBuilder builder;
// we are lazy here and use the same x & y for each corner
- add_corner_arc(path, r, xCorner, yCorner, 270);
- add_corner_arc(path, r, xCorner, yCorner, 0);
- add_corner_arc(path, r, xCorner, yCorner, 90);
- add_corner_arc(path, r, xCorner, yCorner, 180);
- path->close();
+ add_corner_arc(&builder, r, xCorner, yCorner, 270);
+ add_corner_arc(&builder, r, xCorner, yCorner, 0);
+ add_corner_arc(&builder, r, xCorner, yCorner, 90);
+ add_corner_arc(&builder, r, xCorner, yCorner, 180);
+ builder.close();
+ return builder.detach();
}
// Chrome creates its own round rects with each corner possibly being different.
@@ -911,9 +924,7 @@
r.fRight = r.fLeft + 2 * size;
r.fBottom = r.fTop + 2 * size;
- SkPath temp;
-
- make_arb_round_rect(&temp, r, r.width() / 10, r.height() / 15);
+ SkPath temp = make_arb_round_rect(r, r.width() / 10, r.height() / 15);
REPORTER_ASSERT(reporter, temp.isConvex());
}
@@ -938,9 +949,7 @@
r.fRight = r.fLeft + 2 * size;
r.fBottom = r.fTop + 2 * size;
- SkPath temp;
-
- make_arb_round_rect(&temp, r, 0, 0);
+ SkPath temp = make_arb_round_rect(r, 0, 0);
SkRect result;
REPORTER_ASSERT(reporter, temp.isRect(&result));
@@ -1840,10 +1849,10 @@
}
static void test_isLine(skiatest::Reporter* reporter) {
- SkPath path;
SkPoint pts[2];
const SkScalar value = SkIntToScalar(5);
+ SkPath path;
REPORTER_ASSERT(reporter, !path.isLine(nullptr));
// set some non-zero values
@@ -1858,7 +1867,9 @@
const SkScalar moveY = SkIntToScalar(2);
REPORTER_ASSERT(reporter, value != moveX && value != moveY);
- path.moveTo(moveX, moveY);
+ SkPathBuilder builder;
+ builder.moveTo(moveX, moveY);
+ path = builder.snapshot();
REPORTER_ASSERT(reporter, !path.isLine(nullptr));
REPORTER_ASSERT(reporter, !path.isLine(pts));
// check that pts was untouched
@@ -1869,7 +1880,8 @@
const SkScalar lineY = SkIntToScalar(2);
REPORTER_ASSERT(reporter, value != lineX && value != lineY);
- path.lineTo(lineX, lineY);
+ builder.lineTo(lineX, lineY);
+ path = builder.snapshot();
REPORTER_ASSERT(reporter, path.isLine(nullptr));
REPORTER_ASSERT(reporter, !pts[0].equals(moveX, moveY));
@@ -1878,20 +1890,20 @@
REPORTER_ASSERT(reporter, pts[0].equals(moveX, moveY));
REPORTER_ASSERT(reporter, pts[1].equals(lineX, lineY));
- path.lineTo(0, 0); // too many points/verbs
+ builder.lineTo(0, 0); // too many points/verbs
+ path = builder.snapshot();
REPORTER_ASSERT(reporter, !path.isLine(nullptr));
REPORTER_ASSERT(reporter, !path.isLine(pts));
REPORTER_ASSERT(reporter, pts[0].equals(moveX, moveY));
REPORTER_ASSERT(reporter, pts[1].equals(lineX, lineY));
- path.reset();
- path.quadTo(1, 1, 2, 2);
+ builder.reset();
+ builder.quadTo(1, 1, 2, 2);
+ path = builder.snapshot();
REPORTER_ASSERT(reporter, !path.isLine(nullptr));
}
static void test_conservativelyContains(skiatest::Reporter* reporter) {
- SkPath path;
-
// kBaseRect is used to construct most our test paths: a rect, a circle, and a round-rect.
static const SkRect kBaseRect = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
@@ -1992,51 +2004,51 @@
}
for (int d = 0; d < 2; ++d) {
SkPathDirection dir = d ? SkPathDirection::kCCW : SkPathDirection::kCW;
- path.reset();
- path.addRect(kBaseRect, dir);
+ SkPath path = SkPath::Rect(kBaseRect, dir);
REPORTER_ASSERT(reporter, kQueries[q].fInRect ==
path.conservativelyContainsRect(qRect));
- path.reset();
- path.addCircle(kCircleC.fX, kCircleC.fY, circleR, dir);
+ path = SkPath::Circle(kCircleC.fX, kCircleC.fY, circleR, dir);
REPORTER_ASSERT(reporter, kQueries[q].fInCircle ==
path.conservativelyContainsRect(qRect));
- path.reset();
- path.addRoundRect(kBaseRect, kRRRadii[0], kRRRadii[1], dir);
+ path = SkPath::RRect(kBaseRect, kRRRadii[0], kRRRadii[1], dir);
REPORTER_ASSERT(reporter, kQueries[q].fInRR ==
path.conservativelyContainsRect(qRect));
- path.reset();
- path.moveTo(kBaseRect.fLeft + kRRRadii[0], kBaseRect.fTop);
- path.cubicTo(kBaseRect.fLeft + kRRRadii[0] / 2, kBaseRect.fTop,
- kBaseRect.fLeft, kBaseRect.fTop + kRRRadii[1] / 2,
- kBaseRect.fLeft, kBaseRect.fTop + kRRRadii[1]);
- path.lineTo(kBaseRect.fLeft, kBaseRect.fBottom);
- path.lineTo(kBaseRect.fRight, kBaseRect.fBottom);
- path.lineTo(kBaseRect.fRight, kBaseRect.fTop);
- path.close();
+ path = SkPathBuilder()
+ .moveTo(kBaseRect.fLeft + kRRRadii[0], kBaseRect.fTop)
+ .cubicTo(kBaseRect.fLeft + kRRRadii[0] / 2, kBaseRect.fTop,
+ kBaseRect.fLeft, kBaseRect.fTop + kRRRadii[1] / 2,
+ kBaseRect.fLeft, kBaseRect.fTop + kRRRadii[1])
+ .lineTo(kBaseRect.fLeft, kBaseRect.fBottom)
+ .lineTo(kBaseRect.fRight, kBaseRect.fBottom)
+ .lineTo(kBaseRect.fRight, kBaseRect.fTop)
+ .close()
+ .detach();
REPORTER_ASSERT(reporter, kQueries[q].fInCubicRR ==
path.conservativelyContainsRect(qRect));
}
// Slightly non-convex shape, shouldn't contain any rects.
- path.reset();
- path.moveTo(0, 0);
- path.lineTo(SkIntToScalar(50), 0.05f);
- path.lineTo(SkIntToScalar(100), 0);
- path.lineTo(SkIntToScalar(100), SkIntToScalar(100));
- path.lineTo(0, SkIntToScalar(100));
- path.close();
+ SkPath path = SkPathBuilder()
+ .moveTo(0, 0)
+ .lineTo(SkIntToScalar(50), 0.05f)
+ .lineTo(SkIntToScalar(100), 0)
+ .lineTo(SkIntToScalar(100), SkIntToScalar(100))
+ .lineTo(0, SkIntToScalar(100))
+ .close()
+ .detach();
REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(qRect));
}
}
// make sure a minimal convex shape works, a right tri with edges along pos x and y axes.
- path.reset();
- path.moveTo(0, 0);
- path.lineTo(SkIntToScalar(100), 0);
- path.lineTo(0, SkIntToScalar(100));
+ SkPathBuilder builder;
+ builder.moveTo(0, 0);
+ builder.lineTo(SkIntToScalar(100), 0);
+ builder.lineTo(0, SkIntToScalar(100));
+ SkPath path = builder.snapshot();
// inside, on along top edge
REPORTER_ASSERT(reporter, path.conservativelyContainsRect(SkRect::MakeXYWH(SkIntToScalar(50), 0,
@@ -2062,17 +2074,19 @@
// Test that multiple move commands do not cause asserts.
- path.moveTo(SkIntToScalar(100), SkIntToScalar(100));
+ builder.moveTo(SkIntToScalar(100), SkIntToScalar(100));
+ path = builder.detach();
REPORTER_ASSERT(reporter, path.conservativelyContainsRect(SkRect::MakeXYWH(SkIntToScalar(50), 0,
SkIntToScalar(10),
SkIntToScalar(10))));
// Same as above path and first test but with an extra moveTo.
- path.reset();
- path.moveTo(100, 100);
- path.moveTo(0, 0);
- path.lineTo(SkIntToScalar(100), 0);
- path.lineTo(0, SkIntToScalar(100));
+ path = SkPathBuilder()
+ .moveTo(100, 100)
+ .moveTo(0, 0)
+ .lineTo(SkIntToScalar(100), 0)
+ .lineTo(0, SkIntToScalar(100))
+ .detach();
// Convexity logic treats a path as filled and closed, so that multiple (non-trailing) moveTos
// have no effect on convexity
REPORTER_ASSERT(reporter, path.conservativelyContainsRect(
@@ -2082,11 +2096,12 @@
// Same as above path and first test but with the extra moveTo making a degenerate sub-path
// following the non-empty sub-path. Verifies that this does not trigger assertions.
- path.reset();
- path.moveTo(0, 0);
- path.lineTo(SkIntToScalar(100), 0);
- path.lineTo(0, SkIntToScalar(100));
- path.moveTo(100, 100);
+ path = SkPathBuilder()
+ .moveTo(0, 0)
+ .lineTo(SkIntToScalar(100), 0)
+ .lineTo(0, SkIntToScalar(100))
+ .moveTo(100, 100)
+ .detach();
REPORTER_ASSERT(reporter, path.conservativelyContainsRect(SkRect::MakeXYWH(SkIntToScalar(50), 0,
SkIntToScalar(10),
@@ -2094,52 +2109,54 @@
// Test that multiple move commands do not cause asserts and that the function
// is not confused by the multiple moves.
- path.reset();
- path.moveTo(0, 0);
- path.lineTo(SkIntToScalar(100), 0);
- path.lineTo(0, SkIntToScalar(100));
- path.moveTo(0, SkIntToScalar(200));
- path.lineTo(SkIntToScalar(100), SkIntToScalar(200));
- path.lineTo(0, SkIntToScalar(300));
+ path = SkPathBuilder()
+ .moveTo(0, 0)
+ .lineTo(SkIntToScalar(100), 0)
+ .lineTo(0, SkIntToScalar(100))
+ .moveTo(0, SkIntToScalar(200))
+ .lineTo(SkIntToScalar(100), SkIntToScalar(200))
+ .lineTo(0, SkIntToScalar(300))
+ .detach();
REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(
SkRect::MakeXYWH(SkIntToScalar(50), 0,
SkIntToScalar(10),
SkIntToScalar(10))));
- path.reset();
- path.lineTo(100, 100);
+ path = SkPathBuilder().lineTo(100, 100).detach();
REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeXYWH(0, 0, 1, 1)));
// An empty path should not contain any rectangle. It's questionable whether an empty path
// contains an empty rectangle. However, since it is a conservative test it is ok to
// return false.
- path.reset();
+ path = SkPath();
REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeWH(1,1)));
REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeWH(0,0)));
- path.reset();
- path.moveTo(50, 50);
- path.cubicTo(0, 0, 100, 0, 50, 50);
+ path = SkPathBuilder()
+ .moveTo(50, 50)
+ .cubicTo(0, 0, 100, 0, 50, 50)
+ .detach();
REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeWH(100, 100)));
REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeWH(30, 30)));
REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeWH(1,1)));
REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeWH(0,0)));
- path.reset();
- path.moveTo(50, 50);
- path.quadTo(100, 100, 50, 50);
+ path = SkPathBuilder()
+ .moveTo(50, 50)
+ .quadTo(100, 100, 50, 50)
+ .detach();
REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeWH(1,1)));
REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeWH(0,0)));
}
static void test_isRect_open_close(skiatest::Reporter* reporter) {
- SkPath path;
+ SkPath path = SkPathBuilder()
+ .moveTo(0, 0).lineTo(1, 0).lineTo(1, 1).lineTo(0, 1)
+ .close()
+ .detach();
+
bool isClosed;
-
- path.moveTo(0, 0); path.lineTo(1, 0); path.lineTo(1, 1); path.lineTo(0, 1);
- path.close();
-
REPORTER_ASSERT(reporter, path.isRect(nullptr, &isClosed, nullptr));
REPORTER_ASSERT(reporter, isClosed);
}
@@ -2236,14 +2253,15 @@
const size_t testCount = std::size(tests);
int index;
for (size_t testIndex = 0; testIndex < testCount; ++testIndex) {
- SkPath path;
- path.moveTo(tests[testIndex].fPoints[0].fX, tests[testIndex].fPoints[0].fY);
+ SkPathBuilder builder;
+ builder.moveTo(tests[testIndex].fPoints[0].fX, tests[testIndex].fPoints[0].fY);
for (index = 1; index < tests[testIndex].fPointCount; ++index) {
- path.lineTo(tests[testIndex].fPoints[index].fX, tests[testIndex].fPoints[index].fY);
+ builder.lineTo(tests[testIndex].fPoints[index].fX, tests[testIndex].fPoints[index].fY);
}
if (tests[testIndex].fClose) {
- path.close();
+ builder.close();
}
+ SkPath path = builder.detach();
REPORTER_ASSERT(reporter, tests[testIndex].fIsRect == path.isRect(nullptr));
if (tests[testIndex].fIsRect) {
@@ -2275,58 +2293,59 @@
}
// fail, close then line
- SkPath path1;
- path1.moveTo(r1[0].fX, r1[0].fY);
+ SkPathBuilder builder;
+ builder.moveTo(r1[0].fX, r1[0].fY);
for (index = 1; index < SkToInt(std::size(r1)); ++index) {
- path1.lineTo(r1[index].fX, r1[index].fY);
+ builder.lineTo(r1[index].fX, r1[index].fY);
}
- path1.close();
- path1.lineTo(1, 0);
+ builder.close();
+ builder.lineTo(1, 0);
+ SkPath path1 = builder.detach();
REPORTER_ASSERT(reporter, !path1.isRect(nullptr));
// fail, move in the middle
- path1.reset();
- path1.moveTo(r1[0].fX, r1[0].fY);
+ builder.moveTo(r1[0].fX, r1[0].fY);
for (index = 1; index < SkToInt(std::size(r1)); ++index) {
if (index == 2) {
- path1.moveTo(1, .5f);
+ builder.moveTo(1, .5f);
}
- path1.lineTo(r1[index].fX, r1[index].fY);
+ builder.lineTo(r1[index].fX, r1[index].fY);
}
- path1.close();
+ builder.close();
+ path1 = builder.detach();
REPORTER_ASSERT(reporter, !path1.isRect(nullptr));
// fail, move on the edge
- path1.reset();
for (index = 1; index < SkToInt(std::size(r1)); ++index) {
- path1.moveTo(r1[index - 1].fX, r1[index - 1].fY);
- path1.lineTo(r1[index].fX, r1[index].fY);
+ builder.moveTo(r1[index - 1].fX, r1[index - 1].fY);
+ builder.lineTo(r1[index].fX, r1[index].fY);
}
- path1.close();
+ builder.close();
+ path1 = builder.detach();
REPORTER_ASSERT(reporter, !path1.isRect(nullptr));
// fail, quad
- path1.reset();
- path1.moveTo(r1[0].fX, r1[0].fY);
+ builder.moveTo(r1[0].fX, r1[0].fY);
for (index = 1; index < SkToInt(std::size(r1)); ++index) {
if (index == 2) {
- path1.quadTo(1, .5f, 1, .5f);
+ builder.quadTo(1, .5f, 1, .5f);
}
- path1.lineTo(r1[index].fX, r1[index].fY);
+ builder.lineTo(r1[index].fX, r1[index].fY);
}
- path1.close();
+ builder.close();
+ path1 = builder.detach();
REPORTER_ASSERT(reporter, !path1.isRect(nullptr));
// fail, cubic
- path1.reset();
- path1.moveTo(r1[0].fX, r1[0].fY);
+ builder.moveTo(r1[0].fX, r1[0].fY);
for (index = 1; index < SkToInt(std::size(r1)); ++index) {
if (index == 2) {
- path1.cubicTo(1, .5f, 1, .5f, 1, .5f);
+ builder.cubicTo(1, .5f, 1, .5f, 1, .5f);
}
- path1.lineTo(r1[index].fX, r1[index].fY);
+ builder.lineTo(r1[index].fX, r1[index].fY);
}
- path1.close();
+ builder.close();
+ path1 = builder.detach();
REPORTER_ASSERT(reporter, !path1.isRect(nullptr));
}