Index: src/effects/SkBlurMaskFilter.cpp |
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp |
index c49a785024da8e20e8b713f2bd7ddbf0a7626bb9..327332557093d0285ab58fc02747cf3a4e56b8d1 100644 |
--- a/src/effects/SkBlurMaskFilter.cpp |
+++ b/src/effects/SkBlurMaskFilter.cpp |
@@ -10,6 +10,9 @@ |
#include "SkBlurMask.h" |
#include "SkFlattenableBuffers.h" |
#include "SkMaskFilter.h" |
+#include "SkBounder.h" |
+#include "SkRasterClip.h" |
+#include "SkRTConf.h" |
class SkBlurMaskFilterImpl : public SkMaskFilter { |
public: |
@@ -20,6 +23,7 @@ public: |
virtual SkMask::Format getFormat() const SK_OVERRIDE; |
virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, |
SkIPoint* margin) const SK_OVERRIDE; |
+ |
virtual BlurType asABlur(BlurInfo*) const SK_OVERRIDE; |
virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; |
@@ -29,6 +33,9 @@ protected: |
virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMatrix&, |
const SkIRect& clipBounds, |
NinePatch*) const SK_OVERRIDE; |
+ |
+ bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix, |
+ SkIPoint* margin, SkMask::CreateMode createMode) const; |
private: |
SkScalar fRadius; |
@@ -106,6 +113,26 @@ bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, |
#endif |
} |
+bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r, |
+ const SkMatrix& matrix, |
+ SkIPoint* margin, SkMask::CreateMode createMode) const{ |
+ SkScalar radius; |
+ if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) { |
+ radius = fRadius; |
+ } else { |
+ radius = matrix.mapRadius(fRadius); |
+ } |
+ |
+ // To avoid unseemly allocation requests (esp. for finite platforms like |
+ // handset) we limit the radius so something manageable. (as opposed to |
+ // a request like 10,000) |
+ static const SkScalar MAX_RADIUS = SkIntToScalar(128); |
+ radius = SkMinScalar(radius, MAX_RADIUS); |
+ |
+ return SkBlurMask::BlurRect(dst, r, radius, (SkBlurMask::Style)fBlurStyle, |
+ margin, createMode); |
+} |
+ |
#include "SkCanvas.h" |
static bool drawRectsIntoMask(const SkRect rects[], int count, SkMask* mask) { |
@@ -150,6 +177,14 @@ static bool rect_exceeds(const SkRect& r, SkScalar v) { |
r.width() > v || r.height() > v; |
} |
+SK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", |
+#ifdef SK_IGNORE_FAST_RECT_BLUR |
+ false, |
+#else |
+ true, |
+#endif |
+ "Use the faster analytic blur approach for ninepatch rects" ); |
+ |
SkMaskFilter::FilterReturn |
SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, |
const SkMatrix& matrix, |
@@ -177,7 +212,18 @@ SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, |
srcM.fImage = NULL; |
srcM.fFormat = SkMask::kA8_Format; |
srcM.fRowBytes = 0; |
- if (!this->filterMask(&dstM, srcM, matrix, &margin)) { |
+ |
+ bool filterResult = false; |
+ if (count == 1 && c_analyticBlurNinepatch) { |
+ // special case for fast rect blur |
+ // don't actually do the blur the first time, just compute the correct size |
+ filterResult = this->filterRectMask(&dstM, rects[0], matrix, &margin, |
+ SkMask::kJustComputeBounds_CreateMode); |
+ } else { |
+ filterResult = this->filterMask(&dstM, srcM, matrix, &margin); |
+ } |
+ |
+ if (!filterResult) { |
return kFalse_FilterReturn; |
} |
@@ -235,14 +281,21 @@ SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, |
SkASSERT(!smallR[1].isEmpty()); |
} |
- if (!drawRectsIntoMask(smallR, count, &srcM)) { |
- return kFalse_FilterReturn; |
- } |
+ if (count > 1 || !c_analyticBlurNinepatch) { |
+ if (!drawRectsIntoMask(smallR, count, &srcM)) { |
+ return kFalse_FilterReturn; |
+ } |
- SkAutoMaskFreeImage amf(srcM.fImage); |
+ SkAutoMaskFreeImage amf(srcM.fImage); |
- if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { |
- return kFalse_FilterReturn; |
+ if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { |
+ return kFalse_FilterReturn; |
+ } |
+ } else { |
+ if (!this->filterRectMask(&patch->fMask, smallR[0], matrix, &margin, |
+ SkMask::kComputeBoundsAndRenderImage_CreateMode)) { |
+ return kFalse_FilterReturn; |
+ } |
} |
patch->fMask.fBounds.offsetTo(0, 0); |
patch->fOuterRect = dstM.fBounds; |