expose new tight-bounds method on SkPath

BUG=skia:

Change-Id: Ie50df49c1758af203042a84dc2cd505046373d2c
Reviewed-on: https://skia-review.googlesource.com/7996
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2017-02-03 11:34:13 -05:00 committed by Skia Commit-Bot
parent 20f00784b8
commit 8d3196bdfc
5 changed files with 33 additions and 21 deletions

View File

@ -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.
/*

View File

@ -357,6 +357,19 @@ public:
this->getBounds();
}
/**
* 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

View File

@ -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;
}

View File

@ -121,8 +121,6 @@ public:
static const SkScalar* ConicWeightData(const SkPath& path) {
return path.fPathRef->conicWeights();
}
static bool ComputeTightBounds(const SkPath&, SkRect*);
};
#endif

View File

@ -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;