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:
parent
20f00784b8
commit
8d3196bdfc
@ -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.
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -121,8 +121,6 @@ public:
|
||||
static const SkScalar* ConicWeightData(const SkPath& path) {
|
||||
return path.fPathRef->conicWeights();
|
||||
}
|
||||
|
||||
static bool ComputeTightBounds(const SkPath&, SkRect*);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user