aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/DashBench.cpp7
-rw-r--r--include/core/SkPaint.h109
-rw-r--r--src/core/SkCanvas.cpp15
-rw-r--r--src/core/SkPaint.cpp5
4 files changed, 86 insertions, 50 deletions
diff --git a/bench/DashBench.cpp b/bench/DashBench.cpp
index 40fffe6dea..3f2cfa7856 100644
--- a/bench/DashBench.cpp
+++ b/bench/DashBench.cpp
@@ -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);
}
}
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index c5f7c9c247..8fcfda26ba 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -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;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 90de54a4e8..3687d1e984 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -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)
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 66fa0df1be..1b74fa1e44 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -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