Index: src/core/SkMaskFilter.cpp |
diff --git a/src/core/SkMaskFilter.cpp b/src/core/SkMaskFilter.cpp |
index c9783e76d6113e7bd9abb9a800341a1d83591c42..755a33e95c46f39aa84eedfe56c2b1b2f542472a 100644 |
--- a/src/core/SkMaskFilter.cpp |
+++ b/src/core/SkMaskFilter.cpp |
@@ -10,6 +10,7 @@ |
#include "SkMaskFilter.h" |
#include "SkBlitter.h" |
#include "SkDraw.h" |
+#include "SkMaskCache.h" |
#include "SkRasterClip.h" |
#include "SkRRect.h" |
#include "SkTypes.h" |
@@ -223,6 +224,11 @@ bool SkMaskFilter::filterRRect(const SkRRect& devRRect, const SkMatrix& matrix, |
return true; |
} |
+static bool rect_exceeds(const SkRect& r, SkScalar v) { |
+ return r.fLeft < -v || r.fTop < -v || r.fRight > v || r.fBottom > v || |
+ r.width() > v || r.height() > v; |
+} |
+ |
bool SkMaskFilter::filterPath(const SkPath& devPath, const SkMatrix& matrix, |
const SkRasterClip& clip, SkBlitter* blitter, |
SkPaint::Style style) const { |
@@ -263,10 +269,72 @@ bool SkMaskFilter::filterPath(const SkPath& devPath, const SkMatrix& matrix, |
} |
SkAutoMaskFreeImage autoSrc(srcM.fImage); |
- if (!this->filterMask(&dstM, srcM, matrix, NULL)) { |
+ // Don't actually do the blur the first time, just compute the correct bounds. |
+ SkMask tmpSrc, tmpDst; |
+ tmpSrc = srcM; |
+ tmpSrc.fImage = NULL; |
+ if (!this->filterMask(&tmpDst, tmpSrc, matrix, NULL)) { |
return false; |
} |
- SkAutoMaskFreeImage autoDst(dstM.fImage); |
+ |
+ BlurRec rec; |
+ uint8_t* maskImage = NULL; |
+ |
+ // Try to cache blur effect applied on a path which is consist of 1 or 2 rects. |
+ // Dst mask of unclipped path is saved in the cache. |
+ // Actual clipped dst mask is extracted from the unclipped dst mask according bounds. |
+ if (this->asABlur(&rec) && rectCount && !rect_exceeds(rects[0], SkIntToScalar(32767))) { |
+ SkMask srcMUnclipped, dstMUnclipped; |
+ SkScalar scaledSigma = matrix.mapRadius(rec.fSigma); |
+ |
+ if (SkMaskCache::FindAndCopy(scaledSigma, rec.fStyle, rec.fQuality, |
+ rects, rectCount, &dstMUnclipped)) { |
+ if (!SkDraw::DrawToMask(devPath, NULL, this, &matrix, &srcMUnclipped, |
+ SkMask::kJustComputeBounds_CreateMode, |
+ style)) { |
+ return false; |
+ } |
+ srcMUnclipped.fFormat = SkMask::kA8_Format; |
+ srcMUnclipped.fRowBytes = srcMUnclipped.fBounds.width(); |
+ } else { |
+ if (!SkDraw::DrawToMask(devPath, NULL, this, &matrix, &srcMUnclipped, |
+ SkMask::kComputeBoundsAndRenderImage_CreateMode, |
+ style)) { |
+ return false; |
+ } |
+ SkAutoMaskFreeImage autoSrcUnclipped(srcMUnclipped.fImage); |
+ if (!this->filterMask(&dstMUnclipped, srcMUnclipped, matrix, NULL)) { |
+ return false; |
+ } |
+ dstMUnclipped.fBounds.offsetTo(0, 0); |
+ SkMaskCache::AddAndCopy(scaledSigma, rec.fStyle, rec.fQuality, |
+ rects, rectCount, dstMUnclipped); |
+ } |
+ |
+ SkMask tmpSrcUnclipped, tmpDstUnclipped; |
+ tmpSrcUnclipped = srcMUnclipped; |
+ tmpSrcUnclipped.fImage = NULL; |
+ if (!this->filterMask(&tmpDstUnclipped, tmpSrcUnclipped, matrix, NULL)) { |
+ return false; |
+ } |
+ SkASSERT(tmpDstUnclipped.fBounds.contains(tmpDst.fBounds)); |
+ |
+ dstM.fBounds = tmpDst.fBounds; |
+ dstM.fBounds.offsetTo(tmpDst.fBounds.fLeft - tmpDstUnclipped.fBounds.fLeft, |
+ tmpDst.fBounds.fTop - tmpDstUnclipped.fBounds.fTop); |
+ extractMaskSubset(dstMUnclipped, &dstM); |
+ dstM.fBounds.offsetTo(tmpDst.fBounds.fLeft, tmpDst.fBounds.fTop); |
+ |
+ maskImage = dstMUnclipped.fImage; |
+ } else { |
+ if (!this->filterMask(&dstM, srcM, matrix, NULL)) { |
+ return false; |
+ } |
+ |
+ maskImage = dstM.fImage; |
+ } |
+ |
+ SkAutoMaskFreeImage autoDst(maskImage); |
// if we get here, we need to (possibly) resolve the clip and blitter |
SkAAClipBlitterWrapper wrapper(clip, blitter); |