| Index: src/effects/SkBlurMaskFilter.cpp
|
| ===================================================================
|
| --- src/effects/SkBlurMaskFilter.cpp (revision 10932)
|
| +++ src/effects/SkBlurMaskFilter.cpp (working copy)
|
| @@ -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 @@
|
| // 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;
|
| + static const SkScalar kMAX_BLUR_SIGMA;
|
|
|
| - SkScalar fRadius;
|
| + 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 @@
|
| 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 @@
|
| 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 @@
|
| 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,41 +323,35 @@
|
|
|
| void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src,
|
| SkRect* dst) const {
|
| - SkScalar gpuPad, rasterPad;
|
| + SkScalar pad = 3.0f * fSigma;
|
|
|
| - {
|
| - // 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);
|
| -
|
| dst->set(src.fLeft - pad, src.fTop - pad,
|
| src.fRight + pad, src.fBottom + pad);
|
| }
|
|
|
| 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 @@
|
| 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 @@
|
| 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 @@
|
|
|
| GrContext::AutoWideOpenIdentityDraw awo(context, NULL);
|
|
|
| - SkScalar xformedRadius = this->computeXformedRadius(context->getMatrix());
|
| - SkASSERT(xformedRadius > 0);
|
| + SkScalar xformedSigma = this->computeXformedSigma(context->getMatrix());
|
| + SkASSERT(xformedSigma > 0);
|
|
|
| - float sigma = SkScalarToFloat(xformedRadius) * kBLUR_SIGMA_SCALE;
|
| -
|
| // 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 @@
|
| 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] = {
|
|
|