| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "SkBlurMaskFilter.h" | 9 #include "SkBlurMaskFilter.h" |
| 10 #include "SkBlurMask.h" | 10 #include "SkBlurMask.h" |
| 11 #include "SkGpuBlurUtils.h" | 11 #include "SkGpuBlurUtils.h" |
| 12 #include "SkFlattenableBuffers.h" | 12 #include "SkFlattenableBuffers.h" |
| 13 #include "SkMaskFilter.h" | 13 #include "SkMaskFilter.h" |
| 14 #include "SkRTConf.h" | 14 #include "SkRTConf.h" |
| 15 #include "SkStringUtils.h" | 15 #include "SkStringUtils.h" |
| 16 #include "SkStrokeRec.h" | 16 #include "SkStrokeRec.h" |
| 17 | 17 |
| 18 #if SK_SUPPORT_GPU | 18 #if SK_SUPPORT_GPU |
| 19 #include "GrContext.h" | 19 #include "GrContext.h" |
| 20 #include "GrTexture.h" | 20 #include "GrTexture.h" |
| 21 #include "effects/GrSimpleTextureEffect.h" | 21 #include "effects/GrSimpleTextureEffect.h" |
| 22 #include "SkGrPixelRef.h" | 22 #include "SkGrPixelRef.h" |
| 23 #endif | 23 #endif |
| 24 | 24 |
| 25 class SkBlurMaskFilterImpl : public SkMaskFilter { | 25 class SkBlurMaskFilterImpl : public SkMaskFilter { |
| 26 public: | 26 public: |
| 27 SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle, | 27 SkBlurMaskFilterImpl(SkScalar sigma, SkBlurMaskFilter::BlurStyle, uint32_t f
lags); |
| 28 uint32_t flags); | |
| 29 | 28 |
| 30 // overrides from SkMaskFilter | 29 // overrides from SkMaskFilter |
| 31 virtual SkMask::Format getFormat() const SK_OVERRIDE; | 30 virtual SkMask::Format getFormat() const SK_OVERRIDE; |
| 32 virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, | 31 virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, |
| 33 SkIPoint* margin) const SK_OVERRIDE; | 32 SkIPoint* margin) const SK_OVERRIDE; |
| 34 | 33 |
| 35 #if SK_SUPPORT_GPU | 34 #if SK_SUPPORT_GPU |
| 36 virtual bool canFilterMaskGPU(const SkRect& devBounds, | 35 virtual bool canFilterMaskGPU(const SkRect& devBounds, |
| 37 const SkIRect& clipBounds, | 36 const SkIRect& clipBounds, |
| 38 const SkMatrix& ctm, | 37 const SkMatrix& ctm, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 53 const SkIRect& clipBounds, | 52 const SkIRect& clipBounds, |
| 54 NinePatch*) const SK_OVERRIDE; | 53 NinePatch*) const SK_OVERRIDE; |
| 55 | 54 |
| 56 bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix, | 55 bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix, |
| 57 SkIPoint* margin, SkMask::CreateMode createMode) const; | 56 SkIPoint* margin, SkMask::CreateMode createMode) const; |
| 58 | 57 |
| 59 private: | 58 private: |
| 60 // To avoid unseemly allocation requests (esp. for finite platforms like | 59 // To avoid unseemly allocation requests (esp. for finite platforms like |
| 61 // handset) we limit the radius so something manageable. (as opposed to | 60 // handset) we limit the radius so something manageable. (as opposed to |
| 62 // a request like 10,000) | 61 // a request like 10,000) |
| 63 static const SkScalar kMAX_BLUR_RADIUS; | 62 static const SkScalar kMAX_BLUR_SIGMA; |
| 64 // This constant approximates the scaling done in the software path's | |
| 65 // "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)). | |
| 66 // IMHO, it actually should be 1: we blur "less" than we should do | |
| 67 // according to the CSS and canvas specs, simply because Safari does the sam
e. | |
| 68 // Firefox used to do the same too, until 4.0 where they fixed it. So at so
me | |
| 69 // point we should probably get rid of these scaling constants and rebaselin
e | |
| 70 // all the blur tests. | |
| 71 static const SkScalar kBLUR_SIGMA_SCALE; | |
| 72 | 63 |
| 73 SkScalar fRadius; | 64 SkScalar fSigma; |
| 74 SkBlurMaskFilter::BlurStyle fBlurStyle; | 65 SkBlurMaskFilter::BlurStyle fBlurStyle; |
| 75 uint32_t fBlurFlags; | 66 uint32_t fBlurFlags; |
| 76 | 67 |
| 77 SkBlurMaskFilterImpl(SkFlattenableReadBuffer&); | 68 SkBlurMaskFilterImpl(SkFlattenableReadBuffer&); |
| 78 virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; | 69 virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; |
| 79 #if SK_SUPPORT_GPU | 70 |
| 80 SkScalar computeXformedRadius(const SkMatrix& ctm) const { | 71 SkScalar computeXformedSigma(const SkMatrix& ctm) const { |
| 81 bool ignoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTr
ansform_BlurFlag); | 72 bool ignoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTr
ansform_BlurFlag); |
| 82 | 73 |
| 83 SkScalar xformedRadius = ignoreTransform ? fRadius | 74 SkScalar xformedSigma = ignoreTransform ? fSigma : ctm.mapRadius(fSigma)
; |
| 84 : ctm.mapRadius(fRadius); | 75 return SkMinScalar(xformedSigma, kMAX_BLUR_SIGMA); |
| 85 return SkMinScalar(xformedRadius, kMAX_BLUR_RADIUS); | |
| 86 } | 76 } |
| 87 #endif | |
| 88 | 77 |
| 89 typedef SkMaskFilter INHERITED; | 78 typedef SkMaskFilter INHERITED; |
| 90 }; | 79 }; |
| 91 | 80 |
| 92 const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_RADIUS = SkIntToScalar(128); | 81 const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128); |
| 93 const SkScalar SkBlurMaskFilterImpl::kBLUR_SIGMA_SCALE = SkFloatToScalar(0.6f); | |
| 94 | 82 |
| 95 SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius, | 83 SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius, |
| 96 SkBlurMaskFilter::BlurStyle style, | 84 SkBlurMaskFilter::BlurStyle style, |
| 97 uint32_t flags) { | 85 uint32_t flags) { |
| 98 // use !(radius > 0) instead of radius <= 0 to reject NaN values | 86 // use !(radius > 0) instead of radius <= 0 to reject NaN values |
| 99 if (!(radius > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount | 87 if (!(radius > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount |
| 100 || flags > SkBlurMaskFilter::kAll_BlurFlag) { | 88 || flags > SkBlurMaskFilter::kAll_BlurFlag) { |
| 101 return NULL; | 89 return NULL; |
| 102 } | 90 } |
| 103 | 91 |
| 104 return SkNEW_ARGS(SkBlurMaskFilterImpl, (radius, style, flags)); | 92 SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius); |
| 93 |
| 94 return SkNEW_ARGS(SkBlurMaskFilterImpl, (sigma, style, flags)); |
| 95 } |
| 96 |
| 97 SkMaskFilter* SkBlurMaskFilter::Create(SkBlurMaskFilter::BlurStyle style, |
| 98 SkScalar sigma, |
| 99 uint32_t flags) { |
| 100 // use !(sigma > 0) instead of sigma <= 0 to reject NaN values |
| 101 if (!(sigma > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount |
| 102 || flags > SkBlurMaskFilter::kAll_BlurFlag) { |
| 103 return NULL; |
| 104 } |
| 105 |
| 106 return SkNEW_ARGS(SkBlurMaskFilterImpl, (sigma, style, flags)); |
| 105 } | 107 } |
| 106 | 108 |
| 107 /////////////////////////////////////////////////////////////////////////////// | 109 /////////////////////////////////////////////////////////////////////////////// |
| 108 | 110 |
| 109 SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius, | 111 SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar sigma, |
| 110 SkBlurMaskFilter::BlurStyle style, | 112 SkBlurMaskFilter::BlurStyle style, |
| 111 uint32_t flags) | 113 uint32_t flags) |
| 112 : fRadius(radius), fBlurStyle(style), fBlurFlags(flags) { | 114 : fSigma(sigma), fBlurStyle(style), fBlurFlags(flags) { |
| 113 #if 0 | 115 #if 0 |
| 114 fGamma = NULL; | 116 fGamma = NULL; |
| 115 if (gammaScale) { | 117 if (gammaScale) { |
| 116 fGamma = new U8[256]; | 118 fGamma = new U8[256]; |
| 117 if (gammaScale > 0) | 119 if (gammaScale > 0) |
| 118 SkBlurMask::BuildSqrGamma(fGamma, gammaScale); | 120 SkBlurMask::BuildSqrGamma(fGamma, gammaScale); |
| 119 else | 121 else |
| 120 SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale); | 122 SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale); |
| 121 } | 123 } |
| 122 #endif | 124 #endif |
| 123 SkASSERT(radius >= 0); | 125 SkASSERT(fSigma >= 0); |
| 124 SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount); | 126 SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount); |
| 125 SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag); | 127 SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag); |
| 126 } | 128 } |
| 127 | 129 |
| 128 SkMask::Format SkBlurMaskFilterImpl::getFormat() const { | 130 SkMask::Format SkBlurMaskFilterImpl::getFormat() const { |
| 129 return SkMask::kA8_Format; | 131 return SkMask::kA8_Format; |
| 130 } | 132 } |
| 131 | 133 |
| 132 bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, | 134 bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, |
| 133 const SkMatrix& matrix, | 135 const SkMatrix& matrix, |
| 134 SkIPoint* margin) const{ | 136 SkIPoint* margin) const{ |
| 135 SkScalar radius; | 137 SkScalar sigma = this->computeXformedSigma(matrix); |
| 136 if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) { | |
| 137 radius = fRadius; | |
| 138 } else { | |
| 139 radius = matrix.mapRadius(fRadius); | |
| 140 } | |
| 141 | 138 |
| 142 radius = SkMinScalar(radius, kMAX_BLUR_RADIUS); | |
| 143 SkBlurMask::Quality blurQuality = | 139 SkBlurMask::Quality blurQuality = |
| 144 (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ? | 140 (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ? |
| 145 SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality; | 141 SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality; |
| 146 | 142 |
| 147 return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle, | 143 return SkBlurMask::BoxBlur(dst, src, sigma, (SkBlurMask::Style)fBlurStyle, |
| 148 blurQuality, margin); | 144 blurQuality, margin); |
| 149 } | 145 } |
| 150 | 146 |
| 151 bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r, | 147 bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r, |
| 152 const SkMatrix& matrix, | 148 const SkMatrix& matrix, |
| 153 SkIPoint* margin, SkMask::CreateMode c
reateMode) const{ | 149 SkIPoint* margin, SkMask::CreateMode c
reateMode) const{ |
| 154 SkScalar radius; | 150 SkScalar sigma = computeXformedSigma(matrix); |
| 155 if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) { | |
| 156 radius = fRadius; | |
| 157 } else { | |
| 158 radius = matrix.mapRadius(fRadius); | |
| 159 } | |
| 160 | 151 |
| 161 radius = SkMinScalar(radius, kMAX_BLUR_RADIUS); | 152 return SkBlurMask::BlurRect(sigma, dst, r, (SkBlurMask::Style)fBlurStyle, |
| 162 | |
| 163 return SkBlurMask::BlurRect(dst, r, radius, (SkBlurMask::Style)fBlurStyle, | |
| 164 margin, createMode); | 153 margin, createMode); |
| 165 } | 154 } |
| 166 | 155 |
| 167 #include "SkCanvas.h" | 156 #include "SkCanvas.h" |
| 168 | 157 |
| 169 static bool drawRectsIntoMask(const SkRect rects[], int count, SkMask* mask) { | 158 static bool drawRectsIntoMask(const SkRect rects[], int count, SkMask* mask) { |
| 170 rects[0].roundOut(&mask->fBounds); | 159 rects[0].roundOut(&mask->fBounds); |
| 171 mask->fRowBytes = SkAlign4(mask->fBounds.width()); | 160 mask->fRowBytes = SkAlign4(mask->fBounds.width()); |
| 172 mask->fFormat = SkMask::kA8_Format; | 161 mask->fFormat = SkMask::kA8_Format; |
| 173 size_t size = mask->computeImageSize(); | 162 size_t size = mask->computeImageSize(); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 327 } | 316 } |
| 328 } | 317 } |
| 329 patch->fMask.fBounds.offsetTo(0, 0); | 318 patch->fMask.fBounds.offsetTo(0, 0); |
| 330 patch->fOuterRect = dstM.fBounds; | 319 patch->fOuterRect = dstM.fBounds; |
| 331 patch->fCenter = center; | 320 patch->fCenter = center; |
| 332 return kTrue_FilterReturn; | 321 return kTrue_FilterReturn; |
| 333 } | 322 } |
| 334 | 323 |
| 335 void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, | 324 void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, |
| 336 SkRect* dst) const { | 325 SkRect* dst) const { |
| 337 SkScalar gpuPad, rasterPad; | 326 SkScalar pad = 3.0f * fSigma; |
| 338 | |
| 339 { | |
| 340 // GPU path | |
| 341 SkScalar sigma = SkScalarMul(fRadius, kBLUR_SIGMA_SCALE); | |
| 342 gpuPad = sigma * 3.0f; | |
| 343 } | |
| 344 | |
| 345 { | |
| 346 // raster path | |
| 347 SkScalar radius = SkScalarMul(fRadius, SkBlurMask::kBlurRadiusFudgeFacto
r); | |
| 348 | |
| 349 radius = (radius + .5f) * 2.f; | |
| 350 | |
| 351 rasterPad = SkIntToScalar(SkScalarRoundToInt(radius * 3)/2); | |
| 352 } | |
| 353 | |
| 354 SkScalar pad = SkMaxScalar(gpuPad, rasterPad); | |
| 355 | 327 |
| 356 dst->set(src.fLeft - pad, src.fTop - pad, | 328 dst->set(src.fLeft - pad, src.fTop - pad, |
| 357 src.fRight + pad, src.fBottom + pad); | 329 src.fRight + pad, src.fBottom + pad); |
| 358 } | 330 } |
| 359 | 331 |
| 360 SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer) | 332 SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer) |
| 361 : SkMaskFilter(buffer) { | 333 : SkMaskFilter(buffer) { |
| 362 fRadius = buffer.readScalar(); | 334 fSigma = buffer.readScalar(); |
| 335 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V13_AND_ALL_OTHER_INSTANCES_TO
O |
| 336 // Fixing this must be done in two stages. When the skps are recaptured in V
13, |
| 337 // remove the ConvertRadiusToSigma but retain the absolute value. |
| 338 // At the same time, switch the code in flatten to write a positive value. |
| 339 // When the skps are captured in V14 the absolute value can be removed. |
| 340 if (fSigma > 0) { |
| 341 fSigma = SkBlurMask::ConvertRadiusToSigma(fSigma); |
| 342 } else { |
| 343 fSigma = -fSigma; |
| 344 } |
| 345 #endif |
| 363 fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readInt(); | 346 fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readInt(); |
| 364 fBlurFlags = buffer.readUInt() & SkBlurMaskFilter::kAll_BlurFlag; | 347 fBlurFlags = buffer.readUInt() & SkBlurMaskFilter::kAll_BlurFlag; |
| 365 SkASSERT(fRadius >= 0); | 348 SkASSERT(fSigma >= 0); |
| 366 SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount); | 349 SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount); |
| 367 } | 350 } |
| 368 | 351 |
| 369 void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const { | 352 void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const { |
| 370 this->INHERITED::flatten(buffer); | 353 this->INHERITED::flatten(buffer); |
| 371 buffer.writeScalar(fRadius); | 354 buffer.writeScalar(-fSigma); |
| 372 buffer.writeInt(fBlurStyle); | 355 buffer.writeInt(fBlurStyle); |
| 373 buffer.writeUInt(fBlurFlags); | 356 buffer.writeUInt(fBlurFlags); |
| 374 } | 357 } |
| 375 | 358 |
| 376 #if SK_SUPPORT_GPU | 359 #if SK_SUPPORT_GPU |
| 377 | 360 |
| 378 bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds, | 361 bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds, |
| 379 const SkIRect& clipBounds, | 362 const SkIRect& clipBounds, |
| 380 const SkMatrix& ctm, | 363 const SkMatrix& ctm, |
| 381 SkRect* maskRect) const { | 364 SkRect* maskRect) const { |
| 382 SkScalar xformedRadius = this->computeXformedRadius(ctm); | 365 SkScalar xformedSigma = this->computeXformedSigma(ctm); |
| 383 if (xformedRadius <= 0) { | 366 if (xformedSigma <= 0) { |
| 384 return false; | 367 return false; |
| 385 } | 368 } |
| 386 | 369 |
| 387 static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); | 370 static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); |
| 388 static const SkScalar kMIN_GPU_BLUR_RADIUS = SkIntToScalar(32); | 371 static const SkScalar kMIN_GPU_BLUR_SIGMA = SkIntToScalar(32); |
| 389 | 372 |
| 390 if (srcBounds.width() <= kMIN_GPU_BLUR_SIZE && | 373 if (srcBounds.width() <= kMIN_GPU_BLUR_SIZE && |
| 391 srcBounds.height() <= kMIN_GPU_BLUR_SIZE && | 374 srcBounds.height() <= kMIN_GPU_BLUR_SIZE && |
| 392 xformedRadius <= kMIN_GPU_BLUR_RADIUS) { | 375 xformedSigma <= kMIN_GPU_BLUR_SIGMA) { |
| 393 // We prefer to blur small rect with small radius via CPU. | 376 // We prefer to blur small rect with small radius via CPU. |
| 394 return false; | 377 return false; |
| 395 } | 378 } |
| 396 | 379 |
| 397 if (NULL == maskRect) { | 380 if (NULL == maskRect) { |
| 398 // don't need to compute maskRect | 381 // don't need to compute maskRect |
| 399 return true; | 382 return true; |
| 400 } | 383 } |
| 401 | 384 |
| 402 float sigma3 = 3 * SkScalarToFloat(xformedRadius) * kBLUR_SIGMA_SCALE; | 385 float sigma3 = 3 * SkScalarToFloat(xformedSigma); |
| 403 | 386 |
| 404 SkRect clipRect = SkRect::MakeFromIRect(clipBounds); | 387 SkRect clipRect = SkRect::MakeFromIRect(clipBounds); |
| 405 SkRect srcRect(srcBounds); | 388 SkRect srcRect(srcBounds); |
| 406 | 389 |
| 407 // Outset srcRect and clipRect by 3 * sigma, to compute affected blur area. | 390 // Outset srcRect and clipRect by 3 * sigma, to compute affected blur area. |
| 408 srcRect.outset(SkFloatToScalar(sigma3), SkFloatToScalar(sigma3)); | 391 srcRect.outset(SkFloatToScalar(sigma3), SkFloatToScalar(sigma3)); |
| 409 clipRect.outset(SkFloatToScalar(sigma3), SkFloatToScalar(sigma3)); | 392 clipRect.outset(SkFloatToScalar(sigma3), SkFloatToScalar(sigma3)); |
| 410 srcRect.intersect(clipRect); | 393 srcRect.intersect(clipRect); |
| 411 *maskRect = srcRect; | 394 *maskRect = srcRect; |
| 412 return true; | 395 return true; |
| 413 } | 396 } |
| 414 | 397 |
| 415 bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src, | 398 bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src, |
| 416 const SkRect& maskRect, | 399 const SkRect& maskRect, |
| 417 GrTexture** result, | 400 GrTexture** result, |
| 418 bool canOverwriteSrc) const { | 401 bool canOverwriteSrc) const { |
| 419 SkRect clipRect = SkRect::MakeWH(maskRect.width(), maskRect.height()); | 402 SkRect clipRect = SkRect::MakeWH(maskRect.width(), maskRect.height()); |
| 420 | 403 |
| 421 GrContext* context = src->getContext(); | 404 GrContext* context = src->getContext(); |
| 422 | 405 |
| 423 GrContext::AutoWideOpenIdentityDraw awo(context, NULL); | 406 GrContext::AutoWideOpenIdentityDraw awo(context, NULL); |
| 424 | 407 |
| 425 SkScalar xformedRadius = this->computeXformedRadius(context->getMatrix()); | 408 SkScalar xformedSigma = this->computeXformedSigma(context->getMatrix()); |
| 426 SkASSERT(xformedRadius > 0); | 409 SkASSERT(xformedSigma > 0); |
| 427 | |
| 428 float sigma = SkScalarToFloat(xformedRadius) * kBLUR_SIGMA_SCALE; | |
| 429 | 410 |
| 430 // If we're doing a normal blur, we can clobber the pathTexture in the | 411 // If we're doing a normal blur, we can clobber the pathTexture in the |
| 431 // gaussianBlur. Otherwise, we need to save it for later compositing. | 412 // gaussianBlur. Otherwise, we need to save it for later compositing. |
| 432 bool isNormalBlur = (SkBlurMaskFilter::kNormal_BlurStyle == fBlurStyle); | 413 bool isNormalBlur = (SkBlurMaskFilter::kNormal_BlurStyle == fBlurStyle); |
| 433 *result = SkGpuBlurUtils::GaussianBlur(context, src, isNormalBlur && canOver
writeSrc, | 414 *result = SkGpuBlurUtils::GaussianBlur(context, src, isNormalBlur && canOver
writeSrc, |
| 434 clipRect, false, sigma, sigma); | 415 clipRect, false, xformedSigma, xforme
dSigma); |
| 435 if (NULL == *result) { | 416 if (NULL == *result) { |
| 436 return false; | 417 return false; |
| 437 } | 418 } |
| 438 | 419 |
| 439 if (!isNormalBlur) { | 420 if (!isNormalBlur) { |
| 440 context->setIdentityMatrix(); | 421 context->setIdentityMatrix(); |
| 441 GrPaint paint; | 422 GrPaint paint; |
| 442 SkMatrix matrix; | 423 SkMatrix matrix; |
| 443 matrix.setIDiv(src->width(), src->height()); | 424 matrix.setIDiv(src->width(), src->height()); |
| 444 // Blend pathTexture over blurTexture. | 425 // Blend pathTexture over blurTexture. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 462 return true; | 443 return true; |
| 463 } | 444 } |
| 464 | 445 |
| 465 #endif // SK_SUPPORT_GPU | 446 #endif // SK_SUPPORT_GPU |
| 466 | 447 |
| 467 | 448 |
| 468 #ifdef SK_DEVELOPER | 449 #ifdef SK_DEVELOPER |
| 469 void SkBlurMaskFilterImpl::toString(SkString* str) const { | 450 void SkBlurMaskFilterImpl::toString(SkString* str) const { |
| 470 str->append("SkBlurMaskFilterImpl: ("); | 451 str->append("SkBlurMaskFilterImpl: ("); |
| 471 | 452 |
| 472 str->append("radius: "); | 453 str->append("sigma: "); |
| 473 str->appendScalar(fRadius); | 454 str->appendScalar(fSigma); |
| 474 str->append(" "); | 455 str->append(" "); |
| 475 | 456 |
| 476 static const char* gStyleName[SkBlurMaskFilter::kBlurStyleCount] = { | 457 static const char* gStyleName[SkBlurMaskFilter::kBlurStyleCount] = { |
| 477 "normal", "solid", "outer", "inner" | 458 "normal", "solid", "outer", "inner" |
| 478 }; | 459 }; |
| 479 | 460 |
| 480 str->appendf("style: %s ", gStyleName[fBlurStyle]); | 461 str->appendf("style: %s ", gStyleName[fBlurStyle]); |
| 481 str->append("flags: ("); | 462 str->append("flags: ("); |
| 482 if (fBlurFlags) { | 463 if (fBlurFlags) { |
| 483 bool needSeparator = false; | 464 bool needSeparator = false; |
| 484 SkAddFlagToString(str, | 465 SkAddFlagToString(str, |
| 485 SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransfo
rm_BlurFlag), | 466 SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransfo
rm_BlurFlag), |
| 486 "IgnoreXform", &needSeparator); | 467 "IgnoreXform", &needSeparator); |
| 487 SkAddFlagToString(str, | 468 SkAddFlagToString(str, |
| 488 SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_B
lurFlag), | 469 SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_B
lurFlag), |
| 489 "HighQuality", &needSeparator); | 470 "HighQuality", &needSeparator); |
| 490 } else { | 471 } else { |
| 491 str->append("None"); | 472 str->append("None"); |
| 492 } | 473 } |
| 493 str->append("))"); | 474 str->append("))"); |
| 494 } | 475 } |
| 495 #endif | 476 #endif |
| 496 | 477 |
| 497 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) | 478 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) |
| 498 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) | 479 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) |
| 499 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 480 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| OLD | NEW |