diff --git a/include/core/SkMaskFilter.h b/include/core/SkMaskFilter.h index e3da3e4d4b..a88416e90d 100644 --- a/include/core/SkMaskFilter.h +++ b/include/core/SkMaskFilter.h @@ -40,6 +40,13 @@ public: return kSkMaskFilter_Type; } + /** + * Returns the approximate bounds that would result from filtering the src rect. + * The actual result may be different, but it should be contained within the + * returned bounds. + */ + SkRect approximateFilteredBounds(const SkRect& src) const; + static sk_sp Deserialize(const void* data, size_t size, const SkDeserialProcs* procs = nullptr) { return sk_sp(static_cast( diff --git a/src/core/SkBlurMF.cpp b/src/core/SkBlurMF.cpp index 0b8486a587..8abd1ca146 100644 --- a/src/core/SkBlurMF.cpp +++ b/src/core/SkBlurMF.cpp @@ -547,6 +547,9 @@ SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, SkRect* dst) const { + // TODO: if we're doing kInner blur, should we return a different outset? + // i.e. pad == 0 ? + SkScalar pad = 3.0f * fSigma; dst->setLTRB(src.fLeft - pad, src.fTop - pad, diff --git a/src/core/SkMaskFilter.cpp b/src/core/SkMaskFilter.cpp index d4655ec4b7..d0bb09a9f8 100644 --- a/src/core/SkMaskFilter.cpp +++ b/src/core/SkMaskFilter.cpp @@ -368,6 +368,12 @@ void SkMaskFilterBase::computeFastBounds(const SkRect& src, SkRect* dst) const { } } +SkRect SkMaskFilter::approximateFilteredBounds(const SkRect& src) const { + SkRect dst; + as_MFB(this)->computeFastBounds(src, &dst); + return dst; +} + void SkMaskFilter::RegisterFlattenables() { sk_register_blur_maskfilter_createproc(); #if SK_SUPPORT_GPU diff --git a/tests/BlurTest.cpp b/tests/BlurTest.cpp index 01d28b3172..ddcc3f7193 100644 --- a/tests/BlurTest.cpp +++ b/tests/BlurTest.cpp @@ -386,6 +386,13 @@ DEF_TEST(BlurAsABlur, reporter) { } else { REPORTER_ASSERT(reporter, !success); } + + const SkRect src = {0, 0, 100, 100}; + const auto dst = mf->approximateFilteredBounds(src); + + // This is a very conservative test. With more knowledge, we could + // consider more stringent tests. + REPORTER_ASSERT(reporter, dst.contains(src)); } } }