diff options
author | robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-08-27 16:14:03 +0000 |
---|---|---|
committer | robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-08-27 16:14:03 +0000 |
commit | 7ce661d19c5cf4484305a1b20c44bd111f129847 (patch) | |
tree | f92424e3d513b3f002481b2c66985113725cf488 /src/effects/SkBlurMaskFilter.cpp | |
parent | 45891b8e37e131b8298f64ff81b80999ba23b8d6 (diff) |
Blur refactoring
https://codereview.chromium.org/21835004/
git-svn-id: http://skia.googlecode.com/svn/trunk@10936 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/effects/SkBlurMaskFilter.cpp')
-rw-r--r-- | src/effects/SkBlurMaskFilter.cpp | 135 |
1 files changed, 58 insertions, 77 deletions
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp index b54c33004c..88333582a6 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -24,8 +24,7 @@ class SkBlurMaskFilterImpl : public SkMaskFilter { public: - SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle, - uint32_t flags); + SkBlurMaskFilterImpl(SkScalar sigma, SkBlurMaskFilter::BlurStyle, uint32_t flags); // overrides from SkMaskFilter virtual SkMask::Format getFormat() const SK_OVERRIDE; @@ -60,37 +59,26 @@ private: // 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 kMAX_BLUR_RADIUS; - // This constant approximates the scaling done in the software path's - // "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)). - // IMHO, it actually should be 1: we blur "less" than we should do - // according to the CSS and canvas specs, simply because Safari does the same. - // Firefox used to do the same too, until 4.0 where they fixed it. So at some - // point we should probably get rid of these scaling constants and rebaseline - // all the blur tests. - static const SkScalar kBLUR_SIGMA_SCALE; - - SkScalar fRadius; + static const SkScalar kMAX_BLUR_SIGMA; + + SkScalar fSigma; SkBlurMaskFilter::BlurStyle fBlurStyle; uint32_t fBlurFlags; SkBlurMaskFilterImpl(SkFlattenableReadBuffer&); virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; -#if SK_SUPPORT_GPU - SkScalar computeXformedRadius(const SkMatrix& ctm) const { + + SkScalar computeXformedSigma(const SkMatrix& ctm) const { bool ignoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag); - SkScalar xformedRadius = ignoreTransform ? fRadius - : ctm.mapRadius(fRadius); - return SkMinScalar(xformedRadius, kMAX_BLUR_RADIUS); + SkScalar xformedSigma = ignoreTransform ? fSigma : ctm.mapRadius(fSigma); + return SkMinScalar(xformedSigma, kMAX_BLUR_SIGMA); } -#endif typedef SkMaskFilter INHERITED; }; -const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_RADIUS = SkIntToScalar(128); -const SkScalar SkBlurMaskFilterImpl::kBLUR_SIGMA_SCALE = SkFloatToScalar(0.6f); +const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128); SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius, SkBlurMaskFilter::BlurStyle style, @@ -101,15 +89,29 @@ SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius, return NULL; } - return SkNEW_ARGS(SkBlurMaskFilterImpl, (radius, style, flags)); + SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius); + + return SkNEW_ARGS(SkBlurMaskFilterImpl, (sigma, style, flags)); +} + +SkMaskFilter* SkBlurMaskFilter::Create(SkBlurMaskFilter::BlurStyle style, + SkScalar sigma, + uint32_t flags) { + // use !(sigma > 0) instead of sigma <= 0 to reject NaN values + if (!(sigma > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount + || flags > SkBlurMaskFilter::kAll_BlurFlag) { + return NULL; + } + + return SkNEW_ARGS(SkBlurMaskFilterImpl, (sigma, style, flags)); } /////////////////////////////////////////////////////////////////////////////// -SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius, +SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar sigma, SkBlurMaskFilter::BlurStyle style, uint32_t flags) - : fRadius(radius), fBlurStyle(style), fBlurFlags(flags) { + : fSigma(sigma), fBlurStyle(style), fBlurFlags(flags) { #if 0 fGamma = NULL; if (gammaScale) { @@ -120,7 +122,7 @@ SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius, SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale); } #endif - SkASSERT(radius >= 0); + SkASSERT(fSigma >= 0); SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount); SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag); } @@ -132,35 +134,22 @@ SkMask::Format SkBlurMaskFilterImpl::getFormat() const { bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, const SkMatrix& matrix, SkIPoint* margin) const{ - SkScalar radius; - if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) { - radius = fRadius; - } else { - radius = matrix.mapRadius(fRadius); - } + SkScalar sigma = this->computeXformedSigma(matrix); - radius = SkMinScalar(radius, kMAX_BLUR_RADIUS); SkBlurMask::Quality blurQuality = (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ? SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality; - return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle, - blurQuality, margin); + return SkBlurMask::BoxBlur(dst, src, sigma, (SkBlurMask::Style)fBlurStyle, + blurQuality, margin); } 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); - } + SkScalar sigma = computeXformedSigma(matrix); - radius = SkMinScalar(radius, kMAX_BLUR_RADIUS); - - return SkBlurMask::BlurRect(dst, r, radius, (SkBlurMask::Style)fBlurStyle, + return SkBlurMask::BlurRect(sigma, dst, r, (SkBlurMask::Style)fBlurStyle, margin, createMode); } @@ -334,24 +323,7 @@ SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, SkRect* dst) const { - SkScalar gpuPad, rasterPad; - - { - // GPU path - SkScalar sigma = SkScalarMul(fRadius, kBLUR_SIGMA_SCALE); - gpuPad = sigma * 3.0f; - } - - { - // raster path - SkScalar radius = SkScalarMul(fRadius, SkBlurMask::kBlurRadiusFudgeFactor); - - radius = (radius + .5f) * 2.f; - - rasterPad = SkIntToScalar(SkScalarRoundToInt(radius * 3)/2); - } - - SkScalar pad = SkMaxScalar(gpuPad, rasterPad); + SkScalar pad = 3.0f * fSigma; dst->set(src.fLeft - pad, src.fTop - pad, src.fRight + pad, src.fBottom + pad); @@ -359,16 +331,27 @@ void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer) : SkMaskFilter(buffer) { - fRadius = buffer.readScalar(); + fSigma = buffer.readScalar(); +#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V13_AND_ALL_OTHER_INSTANCES_TOO + // Fixing this must be done in two stages. When the skps are recaptured in V13, + // remove the ConvertRadiusToSigma but retain the absolute value. + // At the same time, switch the code in flatten to write a positive value. + // When the skps are captured in V14 the absolute value can be removed. + if (fSigma > 0) { + fSigma = SkBlurMask::ConvertRadiusToSigma(fSigma); + } else { + fSigma = -fSigma; + } +#endif fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readInt(); fBlurFlags = buffer.readUInt() & SkBlurMaskFilter::kAll_BlurFlag; - SkASSERT(fRadius >= 0); + SkASSERT(fSigma >= 0); SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount); } void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const { this->INHERITED::flatten(buffer); - buffer.writeScalar(fRadius); + buffer.writeScalar(-fSigma); buffer.writeInt(fBlurStyle); buffer.writeUInt(fBlurFlags); } @@ -379,17 +362,17 @@ bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds, const SkIRect& clipBounds, const SkMatrix& ctm, SkRect* maskRect) const { - SkScalar xformedRadius = this->computeXformedRadius(ctm); - if (xformedRadius <= 0) { + SkScalar xformedSigma = this->computeXformedSigma(ctm); + if (xformedSigma <= 0) { return false; } - static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); - static const SkScalar kMIN_GPU_BLUR_RADIUS = SkIntToScalar(32); + static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); + static const SkScalar kMIN_GPU_BLUR_SIGMA = SkIntToScalar(32); if (srcBounds.width() <= kMIN_GPU_BLUR_SIZE && srcBounds.height() <= kMIN_GPU_BLUR_SIZE && - xformedRadius <= kMIN_GPU_BLUR_RADIUS) { + xformedSigma <= kMIN_GPU_BLUR_SIGMA) { // We prefer to blur small rect with small radius via CPU. return false; } @@ -399,7 +382,7 @@ bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds, return true; } - float sigma3 = 3 * SkScalarToFloat(xformedRadius) * kBLUR_SIGMA_SCALE; + float sigma3 = 3 * SkScalarToFloat(xformedSigma); SkRect clipRect = SkRect::MakeFromIRect(clipBounds); SkRect srcRect(srcBounds); @@ -422,16 +405,14 @@ bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src, GrContext::AutoWideOpenIdentityDraw awo(context, NULL); - SkScalar xformedRadius = this->computeXformedRadius(context->getMatrix()); - SkASSERT(xformedRadius > 0); - - float sigma = SkScalarToFloat(xformedRadius) * kBLUR_SIGMA_SCALE; + SkScalar xformedSigma = this->computeXformedSigma(context->getMatrix()); + SkASSERT(xformedSigma > 0); // If we're doing a normal blur, we can clobber the pathTexture in the // gaussianBlur. Otherwise, we need to save it for later compositing. bool isNormalBlur = (SkBlurMaskFilter::kNormal_BlurStyle == fBlurStyle); *result = SkGpuBlurUtils::GaussianBlur(context, src, isNormalBlur && canOverwriteSrc, - clipRect, false, sigma, sigma); + clipRect, false, xformedSigma, xformedSigma); if (NULL == *result) { return false; } @@ -469,8 +450,8 @@ bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src, void SkBlurMaskFilterImpl::toString(SkString* str) const { str->append("SkBlurMaskFilterImpl: ("); - str->append("radius: "); - str->appendScalar(fRadius); + str->append("sigma: "); + str->appendScalar(fSigma); str->append(" "); static const char* gStyleName[SkBlurMaskFilter::kBlurStyleCount] = { |