aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/PathBench.cpp14
-rw-r--r--include/core/SkPath.h13
-rw-r--r--src/core/SkPath.cpp22
-rw-r--r--src/core/SkPathPriv.h2
-rw-r--r--tests/PathTest.cpp3
5 files changed, 33 insertions, 21 deletions
diff --git a/bench/PathBench.cpp b/bench/PathBench.cpp
index de8be6c758..10cffc20c2 100644
--- a/bench/PathBench.cpp
+++ b/bench/PathBench.cpp
@@ -1079,10 +1079,10 @@ private:
class TightBoundsBench : public Benchmark {
SkPath fPath;
SkString fName;
- bool (*fProc)(const SkPath&, SkRect*);
+ SkRect (*fProc)(const SkPath&);
public:
- TightBoundsBench(bool (*proc)(const SkPath&, SkRect*), const char suffix[]) : fProc(proc) {
+ TightBoundsBench(SkRect (*proc)(const SkPath&), const char suffix[]) : fProc(proc) {
fName.printf("tight_bounds_%s", suffix);
const int N = 100;
@@ -1106,9 +1106,8 @@ protected:
const char* onGetName() override { return fName.c_str(); }
void onDraw(int loops, SkCanvas* canvas) override {
- SkRect bounds;
for (int i = 0; i < loops*100; ++i) {
- fProc(fPath, &bounds);
+ fProc(fPath);
}
}
@@ -1186,8 +1185,11 @@ DEF_BENCH( return new ConservativelyContainsBench(ConservativelyContainsBench::k
#include "SkPathOps.h"
#include "SkPathPriv.h"
-DEF_BENCH( return new TightBoundsBench(SkPathPriv::ComputeTightBounds, "priv"); )
-DEF_BENCH( return new TightBoundsBench(TightBounds, "pathops"); )
+DEF_BENCH( return new TightBoundsBench([](const SkPath& path){ return path.computeTightBounds();},
+ "priv"); )
+DEF_BENCH( return new TightBoundsBench([](const SkPath& path) {
+ SkRect bounds; TightBounds(path, &bounds); return bounds;
+ }, "pathops"); )
// These seem to be optimized away, which is troublesome for timing.
/*
diff --git a/include/core/SkPath.h b/include/core/SkPath.h
index 486a993231..8bdfbc48b8 100644
--- a/include/core/SkPath.h
+++ b/include/core/SkPath.h
@@ -358,6 +358,19 @@ public:
}
/**
+ * Computes a bounds that is conservatively "snug" around the path. This assumes that the
+ * path will be filled. It does not attempt to collapse away contours that are logically
+ * empty (e.g. moveTo(x, y) + lineTo(x, y)) but will include them in the calculation.
+ *
+ * It differs from getBounds() in that it will look at the snug bounds of curves, whereas
+ * getBounds() just returns the bounds of the control-points. Thus computing this may be
+ * slower than just calling getBounds().
+ *
+ * If the path is empty (i.e. no points or verbs), it will return SkRect::MakeEmpty().
+ */
+ SkRect computeTightBounds() const;
+
+ /**
* Does a conservative test to see whether a rectangle is inside a path. Currently it only
* will ever return true for single convex contour paths. The empty-status of the rect is not
* considered (e.g. a rect that is a point can be inside a path). Points or line segments where
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index 4c18e63b23..84dfca1fc7 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -3435,23 +3435,22 @@ static int compute_cubic_extremas(const SkPoint src[3], SkPoint extremas[5]) {
return n + 1;
}
-bool SkPathPriv::ComputeTightBounds(const SkPath& path, SkRect* bounds) {
- if (0 == path.countVerbs()) {
- return false;
+SkRect SkPath::computeTightBounds() const {
+ if (0 == this->countVerbs()) {
+ return SkRect::MakeEmpty();
}
- if (path.getSegmentMasks() == SkPath::kLine_SegmentMask) {
- *bounds = path.getBounds();
- return true;
+ if (this->getSegmentMasks() == SkPath::kLine_SegmentMask) {
+ return this->getBounds();
}
SkPoint extremas[5]; // big enough to hold worst-case curve type (cubic) extremas + 1
SkPoint pts[4];
- SkPath::RawIter iter(path);
+ SkPath::RawIter iter(*this);
// initial with the first MoveTo, so we don't have to check inside the switch
Sk2s min, max;
- min = max = from_point(path.getPoint(0));
+ min = max = from_point(this->getPoint(0));
for (;;) {
int count = 0;
switch (iter.next(pts)) {
@@ -3484,7 +3483,8 @@ bool SkPathPriv::ComputeTightBounds(const SkPath& path, SkRect* bounds) {
}
}
DONE:
- min.store((SkPoint*)&bounds->fLeft);
- max.store((SkPoint*)&bounds->fRight);
- return true;
+ SkRect bounds;
+ min.store((SkPoint*)&bounds.fLeft);
+ max.store((SkPoint*)&bounds.fRight);
+ return bounds;
}
diff --git a/src/core/SkPathPriv.h b/src/core/SkPathPriv.h
index cbbb83edab..029cb759de 100644
--- a/src/core/SkPathPriv.h
+++ b/src/core/SkPathPriv.h
@@ -121,8 +121,6 @@ public:
static const SkScalar* ConicWeightData(const SkPath& path) {
return path.fPathRef->conicWeights();
}
-
- static bool ComputeTightBounds(const SkPath&, SkRect*);
};
#endif
diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp
index 38bac25ba7..694dab57ee 100644
--- a/tests/PathTest.cpp
+++ b/tests/PathTest.cpp
@@ -4741,8 +4741,7 @@ DEF_TEST(path_tight_bounds, reporter) {
SkPath path;
rand_path(&path, rand, verb, n);
SkRect bounds = path.getBounds();
- SkRect tight;
- SkPathPriv::ComputeTightBounds(path, &tight);
+ SkRect tight = path.computeTightBounds();
REPORTER_ASSERT(reporter, bounds.contains(tight));
SkRect tight2;