perform quickReject in drawPoints (which is called by drawLine) just like we
already did in drawRect and drawPath git-svn-id: http://skia.googlecode.com/svn/trunk@3968 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
7b463acd46
commit
a584aed5f7
@ -34,7 +34,8 @@ protected:
|
||||
SkString fName;
|
||||
SkTDArray<SkScalar> fIntervals;
|
||||
int fWidth;
|
||||
bool fDoClip;
|
||||
SkPoint fPts[2];
|
||||
bool fDoClip;
|
||||
|
||||
enum {
|
||||
N = SkBENCHLOOP(100)
|
||||
@ -49,6 +50,9 @@ public:
|
||||
fWidth = width;
|
||||
fName.printf("dash_%d_%s", width, doClip ? "clipped" : "noclip");
|
||||
fDoClip = doClip;
|
||||
|
||||
fPts[0].set(SkIntToScalar(10), SkIntToScalar(10));
|
||||
fPts[1].set(SkIntToScalar(600), SkIntToScalar(10));
|
||||
}
|
||||
|
||||
virtual void makePath(SkPath* path) {
|
||||
@ -87,6 +91,7 @@ protected:
|
||||
virtual void handlePath(SkCanvas* canvas, const SkPath& path,
|
||||
const SkPaint& paint, int N) {
|
||||
for (int i = 0; i < N; ++i) {
|
||||
// canvas->drawPoints(SkCanvas::kLines_PointMode, 2, fPts, paint);
|
||||
canvas->drawPath(path, paint);
|
||||
}
|
||||
}
|
||||
|
@ -434,52 +434,6 @@ public:
|
||||
*/
|
||||
bool getFillPath(const SkPath& src, SkPath* dst) const;
|
||||
|
||||
/** Returns true if the current paint settings allow for fast computation of
|
||||
bounds (i.e. there is nothing complex like a patheffect that would make
|
||||
the bounds computation expensive.
|
||||
*/
|
||||
bool canComputeFastBounds() const {
|
||||
if (this->getLooper()) {
|
||||
return this->getLooper()->canComputeFastBounds(*this);
|
||||
}
|
||||
return !this->getRasterizer();
|
||||
}
|
||||
|
||||
/** Only call this if canComputeFastBounds() returned true. This takes a
|
||||
raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
|
||||
effects in the paint (e.g. stroking). If needed, it uses the storage
|
||||
rect parameter. It returns the adjusted bounds that can then be used
|
||||
for quickReject tests.
|
||||
|
||||
The returned rect will either be orig or storage, thus the caller
|
||||
should not rely on storage being set to the result, but should always
|
||||
use the retured value. It is legal for orig and storage to be the same
|
||||
rect.
|
||||
|
||||
e.g.
|
||||
if (paint.canComputeFastBounds()) {
|
||||
SkRect r, storage;
|
||||
path.computeBounds(&r, SkPath::kFast_BoundsType);
|
||||
const SkRect& fastR = paint.computeFastBounds(r, &storage);
|
||||
if (canvas->quickReject(fastR, ...)) {
|
||||
// don't draw the path
|
||||
}
|
||||
}
|
||||
*/
|
||||
const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const {
|
||||
// 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);
|
||||
}
|
||||
|
||||
/** Get the paint's shader object.
|
||||
<p />
|
||||
The shader's reference count is not affected.
|
||||
@ -914,7 +868,66 @@ private:
|
||||
void (*proc)(const SkDescriptor*, void*),
|
||||
void* context, bool ignoreGamma = false) const;
|
||||
|
||||
const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage) const;
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Returns true if the current paint settings allow for fast computation of
|
||||
bounds (i.e. there is nothing complex like a patheffect that would make
|
||||
the bounds computation expensive.
|
||||
*/
|
||||
bool canComputeFastBounds() const {
|
||||
if (this->getLooper()) {
|
||||
return this->getLooper()->canComputeFastBounds(*this);
|
||||
}
|
||||
return !this->getRasterizer();
|
||||
}
|
||||
|
||||
/** Only call this if canComputeFastBounds() returned true. This takes a
|
||||
raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
|
||||
effects in the paint (e.g. stroking). If needed, it uses the storage
|
||||
rect parameter. It returns the adjusted bounds that can then be used
|
||||
for quickReject tests.
|
||||
|
||||
The returned rect will either be orig or storage, thus the caller
|
||||
should not rely on storage being set to the result, but should always
|
||||
use the retured value. It is legal for orig and storage to be the same
|
||||
rect.
|
||||
|
||||
e.g.
|
||||
if (paint.canComputeFastBounds()) {
|
||||
SkRect r, storage;
|
||||
path.computeBounds(&r, SkPath::kFast_BoundsType);
|
||||
const SkRect& fastR = paint.computeFastBounds(r, &storage);
|
||||
if (canvas->quickReject(fastR, ...)) {
|
||||
// don't draw the path
|
||||
}
|
||||
}
|
||||
*/
|
||||
const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const {
|
||||
SkPaint::Style style = this->getStyle();
|
||||
// ultra fast-case: filling with no effects that affect geometry
|
||||
if (kFill_Style == 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, style);
|
||||
}
|
||||
|
||||
const SkRect& computeFastStrokeBounds(const SkRect& orig,
|
||||
SkRect* storage) const {
|
||||
return this->doComputeFastBounds(orig, storage, kFill_Style);
|
||||
}
|
||||
|
||||
// Take the style explicitly, so the caller can force us to be stroked
|
||||
// without having to make a copy of the paint just to change that field.
|
||||
const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
|
||||
Style) const;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum {
|
||||
kCanonicalTextSizeForPaths = 64
|
||||
@ -922,6 +935,8 @@ private:
|
||||
friend class SkAutoGlyphCache;
|
||||
friend class SkCanvas;
|
||||
friend class SkDraw;
|
||||
friend class SkDrawLooper; // computeFastBounds
|
||||
friend class SkPictureRecord; // computeFastBounds
|
||||
friend class SkPDFDevice;
|
||||
friend class SkTextToPathIter;
|
||||
|
||||
|
@ -1452,6 +1452,21 @@ void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
|
||||
return;
|
||||
}
|
||||
|
||||
if (paint.canComputeFastBounds()) {
|
||||
SkRect r;
|
||||
// special-case 2 points (common for drawing a single line)
|
||||
if (2 == count) {
|
||||
r.set(pts[0], pts[1]);
|
||||
} else {
|
||||
r.set(pts, count);
|
||||
}
|
||||
SkRect storage;
|
||||
if (this->quickReject(paint.computeFastStrokeBounds(r, &storage),
|
||||
paint2EdgeType(&paint))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SkASSERT(pts != NULL);
|
||||
|
||||
LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type)
|
||||
|
@ -2045,7 +2045,8 @@ bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const {
|
||||
}
|
||||
|
||||
const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
|
||||
SkRect* storage) const {
|
||||
SkRect* storage,
|
||||
Style style) const {
|
||||
SkASSERT(storage);
|
||||
|
||||
const SkRect* src = &origSrc;
|
||||
@ -2062,7 +2063,7 @@ const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
|
||||
src = &tmpSrc;
|
||||
}
|
||||
|
||||
if (this->getStyle() != SkPaint::kFill_Style) {
|
||||
if (kFill_Style != style) {
|
||||
// since we're stroked, outset the rect by the radius (and join type)
|
||||
SkScalar radius = SkScalarHalf(this->getStrokeWidth());
|
||||
if (0 == radius) { // hairline
|
||||
|
Loading…
Reference in New Issue
Block a user