add computeFastBounds to SkPathEffect, so we can attempt quickReject
authorreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 15 May 2012 20:47:50 +0000 (20:47 +0000)
committerreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 15 May 2012 20:47:50 +0000 (20:47 +0000)
Review URL: https://codereview.appspot.com/6209070

git-svn-id: http://skia.googlecode.com/svn/trunk@3964 2bbb7eff-a529-9590-31e7-b0007b416f81

include/core/SkPaint.h
include/core/SkPathEffect.h
src/core/SkPaint.cpp
src/core/SkPathEffect.cpp

index a9b8cc8..c5f7c9c 100644 (file)
@@ -1,4 +1,5 @@
 
+
 /*
  * Copyright 2006 The Android Open Source Project
  *
@@ -441,9 +442,7 @@ public:
         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
@@ -468,9 +467,14 @@ public:
         }
     */
     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);
index b160f8f..c4a60d2 100644 (file)
@@ -34,6 +34,12 @@ public:
     */
     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) {}
 
index 15fdbd1..66fa0df 100644 (file)
@@ -2044,16 +2044,24 @@ bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const {
     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());
@@ -2065,13 +2073,12 @@ const SkRect& SkPaint::doComputeFastBounds(const SkRect& src,
                 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);
     }
index 8731aed..dcce6d6 100644 (file)
 #include "SkPath.h"
 #include "SkBuffer.h"
 
+void SkPathEffect::computeFastBounds(SkRect* dst, const SkRect& src) {
+    *dst = src;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 SkPairPathEffect::SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1)