Index: src/effects/SkBlurMaskFilter.cpp |
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp |
index 6f69aaf4ab02481e299e5deee7573bd08216fac4..f0bd3757a6d691a2eef7d793170ff619378a2460 100644 |
--- a/src/effects/SkBlurMaskFilter.cpp |
+++ b/src/effects/SkBlurMaskFilter.cpp |
@@ -257,6 +257,58 @@ static bool rect_exceeds(const SkRect& r, SkScalar v) { |
r.width() > v || r.height() > v; |
} |
+#include "SkMaskCache.h" |
+ |
+static bool copy_cacheddata_to_mask(SkCachedData* data, SkMask* mask) { |
+ const size_t size = data->size(); |
+ SkASSERT(mask->computeTotalImageSize() <= size); |
+ |
+ mask->fImage = SkMask::AllocImage(size); |
+ if (mask->fImage) { |
+ memcpy(mask->fImage, data->data(), size); |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+static SkCachedData* copy_mask_to_cacheddata(const SkMask& mask) { |
+ const size_t size = mask.computeTotalImageSize(); |
+ SkCachedData* data = SkResourceCache::NewCachedData(size); |
+ if (data) { |
+ memcpy(data->writable_data(), mask.fImage, size); |
+ return data; |
+ } |
+ return NULL; |
+} |
+ |
+static bool find_cached_rrect(SkMask* mask, SkScalar sigma, SkBlurStyle style, |
+ SkBlurQuality quality, const SkRRect& rrect) { |
+ SkAutoTUnref<SkCachedData> data(SkMaskCache::FindAndRef(sigma, style, quality, rrect, mask)); |
+ return data.get() && copy_cacheddata_to_mask(data, mask); |
+} |
+ |
+static void add_cached_rrect(const SkMask& mask, SkScalar sigma, SkBlurStyle style, |
+ SkBlurQuality quality, const SkRRect& rrect) { |
+ SkAutoTUnref<SkCachedData> data(copy_mask_to_cacheddata(mask)); |
+ if (data.get()) { |
+ SkMaskCache::Add(sigma, style, quality, rrect, mask, data); |
+ } |
+} |
+ |
+static bool find_cached_rects(SkMask* mask, SkScalar sigma, SkBlurStyle style, |
+ SkBlurQuality quality, const SkRect rects[], int count) { |
+ SkAutoTUnref<SkCachedData> data(SkMaskCache::FindAndRef(sigma, style, quality, rects, count, mask)); |
+ return data.get() && copy_cacheddata_to_mask(data, mask); |
+} |
+ |
+static void add_cached_rects(const SkMask& mask, SkScalar sigma, SkBlurStyle style, |
+ SkBlurQuality quality, const SkRect rects[], int count) { |
+ SkAutoTUnref<SkCachedData> data(copy_mask_to_cacheddata(mask)); |
+ if (data.get()) { |
+ SkMaskCache::Add(sigma, style, quality, rects, count, mask, data); |
+ } |
+} |
+ |
#ifdef SK_IGNORE_FAST_RRECT_BLUR |
SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", false, "Use the faster analytic blur approach for ninepatch rects" ); |
#else |
@@ -368,23 +420,27 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma |
radii[SkRRect::kLowerLeft_Corner] = LL; |
smallRR.setRectRadii(smallR, radii); |
- bool analyticBlurWorked = false; |
- if (c_analyticBlurRRect) { |
- analyticBlurWorked = |
- this->filterRRectMask(&patch->fMask, smallRR, matrix, &margin, |
- SkMask::kComputeBoundsAndRenderImage_CreateMode); |
- } |
- |
- if (!analyticBlurWorked) { |
- if (!draw_rrect_into_mask(smallRR, &srcM)) { |
- return kFalse_FilterReturn; |
+ const SkScalar sigma = this->computeXformedSigma(matrix); |
+ if (!find_cached_rrect(&patch->fMask, sigma, fBlurStyle, this->getQuality(), smallRR)) { |
+ 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; |
+ } |
} |
+ add_cached_rrect(patch->fMask, sigma, fBlurStyle, this->getQuality(), smallRR); |
} |
patch->fMask.fBounds.offsetTo(0, 0); |
@@ -494,21 +550,25 @@ SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, |
SkASSERT(!smallR[1].isEmpty()); |
} |
- if (count > 1 || !c_analyticBlurNinepatch) { |
- if (!draw_rects_into_mask(smallR, count, &srcM)) { |
- return kFalse_FilterReturn; |
- } |
- |
- SkAutoMaskFreeImage amf(srcM.fImage); |
- |
- 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; |
+ const SkScalar sigma = this->computeXformedSigma(matrix); |
+ if (!find_cached_rects(&patch->fMask, sigma, fBlurStyle, this->getQuality(), rects, count)) { |
+ if (count > 1 || !c_analyticBlurNinepatch) { |
+ if (!draw_rects_into_mask(smallR, count, &srcM)) { |
+ return kFalse_FilterReturn; |
+ } |
+ |
+ SkAutoMaskFreeImage amf(srcM.fImage); |
+ |
+ 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; |
+ } |
} |
+ add_cached_rects(patch->fMask, sigma, fBlurStyle, this->getQuality(), rects, count); |
} |
patch->fMask.fBounds.offsetTo(0, 0); |
patch->fOuterRect = dstM.fBounds; |