plumb API for analytic rrect blur

BUG=skia:2281
R=bsalomon@google.com, reed@google.com

Author: humper@google.com

Review URL: https://codereview.chromium.org/189663012

git-svn-id: http://skia.googlecode.com/svn/trunk@13733 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/effects/SkBlurMask.cpp b/src/effects/SkBlurMask.cpp
index 50c16f4..9712ecc 100644
--- a/src/effects/SkBlurMask.cpp
+++ b/src/effects/SkBlurMask.cpp
@@ -475,14 +475,6 @@
     SkMask::FreeImage(image);
 }
 
-bool SkBlurMask::Blur(SkMask* dst, const SkMask& src,
-                      SkScalar radius, Style style, Quality quality,
-                      SkIPoint* margin) {
-    return SkBlurMask::BoxBlur(dst, src,
-                               SkBlurMask::ConvertRadiusToSigma(radius),
-                               style, quality, margin);
-}
-
 bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
                          SkScalar sigma, Style style, Quality quality,
                          SkIPoint* margin) {
@@ -741,14 +733,6 @@
     }
 }
 
-bool SkBlurMask::BlurRect(SkMask *dst, const SkRect &src,
-                          SkScalar radius, Style style,
-                          SkIPoint *margin, SkMask::CreateMode createMode) {
-    return SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(radius),
-                                dst, src,
-                                style, margin, createMode);
-}
-
 bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst,
                           const SkRect &src, Style style,
                           SkIPoint *margin, SkMask::CreateMode createMode) {
@@ -850,10 +834,15 @@
     return true;
 }
 
-bool SkBlurMask::BlurGroundTruth(SkMask* dst, const SkMask& src, SkScalar radius,
-                                 Style style, SkIPoint* margin) {
-    return BlurGroundTruth(ConvertRadiusToSigma(radius), dst, src, style, margin);
+bool SkBlurMask::BlurRRect(SkScalar sigma, SkMask *dst,
+                           const SkRRect &src, Style style,
+                           SkIPoint *margin, SkMask::CreateMode createMode) {
+    // Temporary for now -- always fail, should cause caller to fall back
+    // to old path.  Plumbing just to land API and parallelize effort.
+
+    return false;
 }
+
 // The "simple" blur is a direct implementation of separable convolution with a discrete
 // gaussian kernel.  It's "ground truth" in a sense; too slow to be used, but very
 // useful for correctness comparisons.
diff --git a/src/effects/SkBlurMask.h b/src/effects/SkBlurMask.h
index 354fa84..eb67d4c 100644
--- a/src/effects/SkBlurMask.h
+++ b/src/effects/SkBlurMask.h
@@ -12,6 +12,7 @@
 
 #include "SkShader.h"
 #include "SkMask.h"
+#include "SkRRect.h"
 
 class SkBlurMask {
 public:
@@ -34,6 +35,11 @@
                          SkIPoint *margin = NULL,
                          SkMask::CreateMode createMode =
                                                 SkMask::kComputeBoundsAndRenderImage_CreateMode);
+    static bool BlurRRect(SkScalar sigma, SkMask *dst, const SkRRect &src,
+                         Style style,
+                         SkIPoint *margin = NULL,
+                         SkMask::CreateMode createMode =
+                                                SkMask::kComputeBoundsAndRenderImage_CreateMode);
     static bool BoxBlur(SkMask* dst, const SkMask& src,
                         SkScalar sigma, Style style, Quality quality,
                         SkIPoint* margin = NULL);
@@ -44,23 +50,6 @@
                                 Style style,
                                 SkIPoint* margin = NULL);
 
-    SK_ATTR_DEPRECATED("use sigma version")
-    static bool BlurRect(SkMask *dst, const SkRect &src,
-                         SkScalar radius, Style style,
-                         SkIPoint *margin = NULL,
-                         SkMask::CreateMode createMode =
-                                                SkMask::kComputeBoundsAndRenderImage_CreateMode);
-
-    SK_ATTR_DEPRECATED("use sigma version")
-    static bool Blur(SkMask* dst, const SkMask& src,
-                     SkScalar radius, Style style, Quality quality,
-                     SkIPoint* margin = NULL);
-
-    SK_ATTR_DEPRECATED("use sigma version")
-    static bool BlurGroundTruth(SkMask* dst, const SkMask& src,
-                                SkScalar radius, Style style,
-                                SkIPoint* margin = NULL);
-
     static SkScalar ConvertRadiusToSigma(SkScalar radius);
 
     /* Helper functions for analytic rectangle blurs */
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index 5fc5ccc..2d7ff18 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -69,6 +69,8 @@
 
     bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix,
                         SkIPoint* margin, SkMask::CreateMode createMode) const;
+    bool filterRRectMask(SkMask* dstM, const SkRRect& r, const SkMatrix& matrix,
+                        SkIPoint* margin, SkMask::CreateMode createMode) const;
 
 private:
     // To avoid unseemly allocation requests (esp. for finite platforms like
@@ -168,6 +170,15 @@
                                 margin, createMode);
 }
 
+bool SkBlurMaskFilterImpl::filterRRectMask(SkMask* dst, const SkRRect& r,
+                                          const SkMatrix& matrix,
+                                          SkIPoint* margin, SkMask::CreateMode createMode) const{
+    SkScalar sigma = computeXformedSigma(matrix);
+
+    return SkBlurMask::BlurRRect(sigma, dst, r, (SkBlurMask::Style)fBlurStyle,
+                                margin, createMode);
+}
+
 #include "SkCanvas.h"
 
 static bool prepare_to_draw_into_mask(const SkRect& bounds, SkMask* mask) {
@@ -244,6 +255,12 @@
            r.width() > v || r.height() > v;
 }
 
+#ifdef SK_IGNORE_FAST_RRECT_BLUR
+SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticRRect", false, "Use the faster analytic blur approach for ninepatch rects" );
+#else
+SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticRRect", true, "Use the faster analytic blur approach for ninepatch round rects" );
+#endif
+
 SkMaskFilter::FilterReturn
 SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& matrix,
                                         const SkIRect& clipBounds,
@@ -293,7 +310,19 @@
     srcM.fFormat = SkMask::kA8_Format;
     srcM.fRowBytes = 0;
 
-    if (!this->filterMask(&dstM, srcM, matrix, &margin)) {
+    bool filterResult = false;
+    if (c_analyticBlurRRect) {
+        // special case for fast round rect blur
+        // don't actually do the blur the first time, just compute the correct size
+        filterResult = this->filterRRectMask(&dstM, rrect, matrix, &margin,
+                                            SkMask::kJustComputeBounds_CreateMode);
+    }
+
+    if (!filterResult) {
+        filterResult = this->filterMask(&dstM, srcM, matrix, &margin);
+    }
+
+    if (!filterResult) {
         return kFalse_FilterReturn;
     }
 
@@ -337,14 +366,23 @@
     radii[SkRRect::kLowerLeft_Corner] = LL;
     smallRR.setRectRadii(smallR, radii);
 
-    if (!draw_rrect_into_mask(smallRR, &srcM)) {
-        return kFalse_FilterReturn;
+    bool analyticBlurWorked = false;
+    if (c_analyticBlurRRect) {
+        analyticBlurWorked =
+            this->filterRRectMask(&patch->fMask, smallRR, matrix, &margin,
+                                  SkMask::kComputeBoundsAndRenderImage_CreateMode);
     }
 
-    SkAutoMaskFreeImage amf(srcM.fImage);
+    if (!analyticBlurWorked) {
+        if (!draw_rrect_into_mask(smallRR, &srcM)) {
+            return kFalse_FilterReturn;
+        }
 
-    if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) {
-        return kFalse_FilterReturn;
+        SkAutoMaskFreeImage amf(srcM.fImage);
+
+        if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) {
+            return kFalse_FilterReturn;
+        }
     }
 
     patch->fMask.fBounds.offsetTo(0, 0);