+
/*
* Copyright 2006 The Android Open Source Project
*
if (this->getLooper()) {
return this->getLooper()->canComputeFastBounds(*this);
}
- // use bit-or since no need for early exit
- return (reinterpret_cast<uintptr_t>(this->getRasterizer()) |
- reinterpret_cast<uintptr_t>(this->getPathEffect())) == 0;
+ return !this->getRasterizer();
}
/** Only call this if canComputeFastBounds() returned true. This takes a
}
*/
const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const {
- if (this->getStyle() == kFill_Style &&
- !this->getLooper() && !this->getMaskFilter()) {
- return orig;
+ // ultra fast-case: filling with no effects that affect geometry
+ if (this->getStyle() == kFill_Style) {
+ uintptr_t effects = reinterpret_cast<uintptr_t>(this->getLooper());
+ effects |= reinterpret_cast<uintptr_t>(this->getMaskFilter());
+ effects |= reinterpret_cast<uintptr_t>(this->getPathEffect());
+ if (!effects) {
+ return orig;
+ }
}
return this->doComputeFastBounds(orig, storage);
*/
virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width) = 0;
+ /**
+ * Compute a conservative bounds for its effect, given the src bounds.
+ * The baseline implementation just assigns src to dst.
+ */
+ virtual void computeFastBounds(SkRect* dst, const SkRect& src);
+
protected:
SkPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
return width != 0; // return true if we're filled, or false if we're hairline (width == 0)
}
-const SkRect& SkPaint::doComputeFastBounds(const SkRect& src,
+const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
SkRect* storage) const {
SkASSERT(storage);
+ const SkRect* src = &origSrc;
+
if (this->getLooper()) {
SkASSERT(this->getLooper()->canComputeFastBounds(*this));
- this->getLooper()->computeFastBounds(*this, src, storage);
+ this->getLooper()->computeFastBounds(*this, *src, storage);
return *storage;
}
+ SkRect tmpSrc;
+ if (this->getPathEffect()) {
+ this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc);
+ src = &tmpSrc;
+ }
+
if (this->getStyle() != SkPaint::kFill_Style) {
// since we're stroked, outset the rect by the radius (and join type)
SkScalar radius = SkScalarHalf(this->getStrokeWidth());
radius = SkScalarMul(radius, scale);
}
}
- storage->set(src.fLeft - radius, src.fTop - radius,
- src.fRight + radius, src.fBottom + radius);
+ storage->set(src->fLeft - radius, src->fTop - radius,
+ src->fRight + radius, src->fBottom + radius);
} else {
- *storage = src;
+ *storage = *src;
}
- // check the mask filter
if (this->getMaskFilter()) {
this->getMaskFilter()->computeFastBounds(*storage, storage);
}