| 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);
|
|
|