diff options
-rw-r--r-- | bench/PathBench.cpp | 14 | ||||
-rw-r--r-- | include/core/SkPath.h | 13 | ||||
-rw-r--r-- | src/core/SkPath.cpp | 22 | ||||
-rw-r--r-- | src/core/SkPathPriv.h | 2 | ||||
-rw-r--r-- | tests/PathTest.cpp | 3 |
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; |