| 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 "SkBitmapCache.h" |
| 9 #include "SkBlurMaskFilter.h" | 10 #include "SkBlurMaskFilter.h" |
| 10 #include "SkBlurMask.h" | 11 #include "SkBlurMask.h" |
| 11 #include "SkGpuBlurUtils.h" | 12 #include "SkGpuBlurUtils.h" |
| 12 #include "SkReadBuffer.h" | 13 #include "SkReadBuffer.h" |
| 13 #include "SkWriteBuffer.h" | 14 #include "SkWriteBuffer.h" |
| 14 #include "SkMaskFilter.h" | 15 #include "SkMaskFilter.h" |
| 15 #include "SkRRect.h" | 16 #include "SkRRect.h" |
| 16 #include "SkRTConf.h" | 17 #include "SkRTConf.h" |
| 17 #include "SkStringUtils.h" | 18 #include "SkStringUtils.h" |
| 18 #include "SkStrokeRec.h" | 19 #include "SkStrokeRec.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 virtual bool filterMaskGPU(GrTexture* src, | 60 virtual bool filterMaskGPU(GrTexture* src, |
| 60 const SkMatrix& ctm, | 61 const SkMatrix& ctm, |
| 61 const SkRect& maskRect, | 62 const SkRect& maskRect, |
| 62 GrTexture** result, | 63 GrTexture** result, |
| 63 bool canOverwriteSrc) const SK_OVERRIDE; | 64 bool canOverwriteSrc) const SK_OVERRIDE; |
| 64 #endif | 65 #endif |
| 65 | 66 |
| 66 virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; | 67 virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; |
| 67 virtual bool asABlur(BlurRec*) const SK_OVERRIDE; | 68 virtual bool asABlur(BlurRec*) const SK_OVERRIDE; |
| 68 | 69 |
| 70 static bool getCachedBlurMask(SkScalar sigma, |
| 71 unsigned rectCount, |
| 72 const SkRect rects[], |
| 73 SkCachedMask &mask); |
| 74 static bool getCachedBlurMask(SkScalar sigma, |
| 75 const SkRRect rrect, |
| 76 SkCachedMask &mask); |
| 77 |
| 69 SK_TO_STRING_OVERRIDE() | 78 SK_TO_STRING_OVERRIDE() |
| 70 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl) | 79 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl) |
| 71 | 80 |
| 72 protected: | 81 protected: |
| 73 virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMa
trix&, | 82 virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMa
trix&, |
| 74 const SkIRect& clipBounds, | 83 const SkIRect& clipBounds, |
| 75 NinePatch*) const SK_OVERRIDE; | 84 NinePatch*) const SK_OVERRIDE; |
| 76 | 85 |
| 77 virtual FilterReturn filterRRectToNine(const SkRRect&, const SkMatrix&, | 86 virtual FilterReturn filterRRectToNine(const SkRRect&, const SkMatrix&, |
| 78 const SkIRect& clipBounds, | 87 const SkIRect& clipBounds, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 108 return SkMinScalar(xformedSigma, kMAX_BLUR_SIGMA); | 117 return SkMinScalar(xformedSigma, kMAX_BLUR_SIGMA); |
| 109 } | 118 } |
| 110 | 119 |
| 111 friend class SkBlurMaskFilter; | 120 friend class SkBlurMaskFilter; |
| 112 | 121 |
| 113 typedef SkMaskFilter INHERITED; | 122 typedef SkMaskFilter INHERITED; |
| 114 }; | 123 }; |
| 115 | 124 |
| 116 const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128); | 125 const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128); |
| 117 | 126 |
| 127 bool SkBlurMaskFilterImpl::getCachedBlurMask(SkScalar sigma, |
| 128 const SkRRect rrect, |
| 129 SkCachedMask &mask) { |
| 130 SkBitmap bitmap; |
| 131 SkBitmapCache::ID* cacheId = SkBitmapCache::FindAndLock(sigma, rrect, &bitma
p); |
| 132 if (cacheId) { |
| 133 SkAutoLockPixels autoLockPixels(bitmap); |
| 134 if (bitmap.getPixels()) { |
| 135 mask.fMask.fBounds.set(0, 0, bitmap.width(), bitmap.height()); |
| 136 mask.fMask.fRowBytes = mask.fMask.fBounds.width(); |
| 137 mask.fMask.fFormat = SkMask::kA8_Format; |
| 138 mask.fMask.fImage = static_cast<uint8_t*>(bitmap.getPixels()); |
| 139 mask.fCacheId = cacheId; |
| 140 return true; |
| 141 } |
| 142 } |
| 143 return false; |
| 144 } |
| 145 |
| 146 bool SkBlurMaskFilterImpl::getCachedBlurMask(SkScalar sigma, |
| 147 unsigned rectCount, |
| 148 const SkRect rects[], |
| 149 SkCachedMask &mask) { |
| 150 SkBitmap bitmap; |
| 151 SkBitmapCache::ID* cacheId = SkBitmapCache::FindAndLock(sigma, rectCount, re
cts, &bitmap); |
| 152 if (cacheId) { |
| 153 SkAutoLockPixels autoLockPixels(bitmap); |
| 154 if (bitmap.getPixels()) { |
| 155 mask.fMask.fBounds.set(0, 0, bitmap.width(), bitmap.height()); |
| 156 mask.fMask.fRowBytes = mask.fMask.fBounds.width(); |
| 157 mask.fMask.fFormat = SkMask::kA8_Format; |
| 158 mask.fMask.fImage = static_cast<uint8_t*>(bitmap.getPixels()); |
| 159 mask.fCacheId = cacheId; |
| 160 return true; |
| 161 } |
| 162 } |
| 163 return false; |
| 164 } |
| 165 |
| 118 SkMaskFilter* SkBlurMaskFilter::Create(SkBlurStyle style, SkScalar sigma, uint32
_t flags) { | 166 SkMaskFilter* SkBlurMaskFilter::Create(SkBlurStyle style, SkScalar sigma, uint32
_t flags) { |
| 119 if (!SkScalarIsFinite(sigma) || sigma <= 0) { | 167 if (!SkScalarIsFinite(sigma) || sigma <= 0) { |
| 120 return NULL; | 168 return NULL; |
| 121 } | 169 } |
| 122 if ((unsigned)style > (unsigned)kLastEnum_SkBlurStyle) { | 170 if ((unsigned)style > (unsigned)kLastEnum_SkBlurStyle) { |
| 123 return NULL; | 171 return NULL; |
| 124 } | 172 } |
| 125 if (flags > SkBlurMaskFilter::kAll_BlurFlag) { | 173 if (flags > SkBlurMaskFilter::kAll_BlurFlag) { |
| 126 return NULL; | 174 return NULL; |
| 127 } | 175 } |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 SkRect smallR = SkRect::MakeWH(totalSmallWidth, totalSmallHeight); | 409 SkRect smallR = SkRect::MakeWH(totalSmallWidth, totalSmallHeight); |
| 362 | 410 |
| 363 SkRRect smallRR; | 411 SkRRect smallRR; |
| 364 SkVector radii[4]; | 412 SkVector radii[4]; |
| 365 radii[SkRRect::kUpperLeft_Corner] = UL; | 413 radii[SkRRect::kUpperLeft_Corner] = UL; |
| 366 radii[SkRRect::kUpperRight_Corner] = UR; | 414 radii[SkRRect::kUpperRight_Corner] = UR; |
| 367 radii[SkRRect::kLowerRight_Corner] = LR; | 415 radii[SkRRect::kLowerRight_Corner] = LR; |
| 368 radii[SkRRect::kLowerLeft_Corner] = LL; | 416 radii[SkRRect::kLowerLeft_Corner] = LL; |
| 369 smallRR.setRectRadii(smallR, radii); | 417 smallRR.setRectRadii(smallR, radii); |
| 370 | 418 |
| 419 SkScalar sigma = this->computeXformedSigma(matrix); |
| 420 SkCachedMask cachedBlurMask; |
| 421 cachedBlurMask.fCacheId = NULL; |
| 422 if (getCachedBlurMask(sigma, rrect, cachedBlurMask)) { |
| 423 patch->fCachedMask = cachedBlurMask; |
| 424 patch->fOuterRect = dstM.fBounds; |
| 425 patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1; |
| 426 patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1; |
| 427 return kTrue_FilterReturn; |
| 428 } |
| 429 |
| 371 bool analyticBlurWorked = false; | 430 bool analyticBlurWorked = false; |
| 372 if (c_analyticBlurRRect) { | 431 if (c_analyticBlurRRect) { |
| 373 analyticBlurWorked = | 432 analyticBlurWorked = |
| 374 this->filterRRectMask(&patch->fMask, smallRR, matrix, &margin, | 433 this->filterRRectMask(&(patch->fCachedMask.fMask), smallRR, matrix,
&margin, |
| 375 SkMask::kComputeBoundsAndRenderImage_CreateMod
e); | 434 SkMask::kComputeBoundsAndRenderImage_CreateMod
e); |
| 376 } | 435 } |
| 377 | 436 |
| 378 if (!analyticBlurWorked) { | 437 if (!analyticBlurWorked) { |
| 379 if (!draw_rrect_into_mask(smallRR, &srcM)) { | 438 if (!draw_rrect_into_mask(smallRR, &srcM)) { |
| 380 return kFalse_FilterReturn; | 439 return kFalse_FilterReturn; |
| 381 } | 440 } |
| 382 | 441 |
| 383 SkAutoMaskFreeImage amf(srcM.fImage); | 442 SkAutoMaskFreeImage amf(srcM.fImage); |
| 384 | 443 |
| 385 if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { | 444 if (!this->filterMask(&(patch->fCachedMask.fMask), srcM, matrix, &margin
)) { |
| 386 return kFalse_FilterReturn; | 445 return kFalse_FilterReturn; |
| 387 } | 446 } |
| 388 } | 447 } |
| 389 | 448 |
| 390 patch->fMask.fBounds.offsetTo(0, 0); | 449 patch->fCachedMask.fMask.fBounds.offsetTo(0, 0); |
| 391 patch->fOuterRect = dstM.fBounds; | 450 patch->fOuterRect = dstM.fBounds; |
| 392 patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1; | 451 patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1; |
| 393 patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1; | 452 patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1; |
| 453 if (!cachedBlurMask.fCacheId) { |
| 454 SkBitmap bitmap; |
| 455 bitmap.installMaskPixels(patch->fCachedMask.fMask); |
| 456 patch->fCachedMask.fCacheId = SkBitmapCache::AddAndLock(sigma, rrect, bi
tmap); |
| 457 } |
| 458 |
| 394 return kTrue_FilterReturn; | 459 return kTrue_FilterReturn; |
| 395 } | 460 } |
| 396 | 461 |
| 397 SK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch",
true, "Use the faster analytic blur approach for ninepatch rects" ); | 462 SK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch",
true, "Use the faster analytic blur approach for ninepatch rects" ); |
| 398 | 463 |
| 399 SkMaskFilter::FilterReturn | 464 SkMaskFilter::FilterReturn |
| 400 SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, | 465 SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, |
| 401 const SkMatrix& matrix, | 466 const SkMatrix& matrix, |
| 402 const SkIRect& clipBounds, | 467 const SkIRect& clipBounds, |
| 403 NinePatch* patch) const { | 468 NinePatch* patch) const { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 if (1 == count) { | 528 if (1 == count) { |
| 464 innerIR = srcM.fBounds; | 529 innerIR = srcM.fBounds; |
| 465 center.set(smallW, smallH); | 530 center.set(smallW, smallH); |
| 466 } else { | 531 } else { |
| 467 SkASSERT(2 == count); | 532 SkASSERT(2 == count); |
| 468 rects[1].roundIn(&innerIR); | 533 rects[1].roundIn(&innerIR); |
| 469 center.set(smallW + (innerIR.left() - srcM.fBounds.left()), | 534 center.set(smallW + (innerIR.left() - srcM.fBounds.left()), |
| 470 smallH + (innerIR.top() - srcM.fBounds.top())); | 535 smallH + (innerIR.top() - srcM.fBounds.top())); |
| 471 } | 536 } |
| 472 | 537 |
| 538 SkScalar sigma = this->computeXformedSigma(matrix); |
| 539 SkCachedMask cachedBlurMask; |
| 540 cachedBlurMask.fCacheId = NULL; |
| 541 if (getCachedBlurMask(sigma, count, rects, cachedBlurMask)) { |
| 542 patch->fCachedMask = cachedBlurMask; |
| 543 patch->fOuterRect = dstM.fBounds; |
| 544 patch->fCenter = center; |
| 545 return kTrue_FilterReturn; |
| 546 } |
| 547 |
| 473 // +1 so we get a clean, stretchable, center row/col | 548 // +1 so we get a clean, stretchable, center row/col |
| 474 smallW += 1; | 549 smallW += 1; |
| 475 smallH += 1; | 550 smallH += 1; |
| 476 | 551 |
| 477 // we want the inset amounts to be integral, so we don't change any | 552 // we want the inset amounts to be integral, so we don't change any |
| 478 // fractional phase on the fRight or fBottom of our smallR. | 553 // fractional phase on the fRight or fBottom of our smallR. |
| 479 const SkScalar dx = SkIntToScalar(innerIR.width() - smallW); | 554 const SkScalar dx = SkIntToScalar(innerIR.width() - smallW); |
| 480 const SkScalar dy = SkIntToScalar(innerIR.height() - smallH); | 555 const SkScalar dy = SkIntToScalar(innerIR.height() - smallH); |
| 481 if (dx < 0 || dy < 0) { | 556 if (dx < 0 || dy < 0) { |
| 482 // we're too small, relative to our blur, to break into nine-patch, | 557 // we're too small, relative to our blur, to break into nine-patch, |
| 483 // so we ask to have our normal filterMask() be called. | 558 // so we ask to have our normal filterMask() be called. |
| 484 return kUnimplemented_FilterReturn; | 559 return kUnimplemented_FilterReturn; |
| 485 } | 560 } |
| 486 | 561 |
| 487 smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[
0].bottom() - dy); | 562 smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[
0].bottom() - dy); |
| 488 if (smallR[0].width() < 2 || smallR[0].height() < 2) { | 563 if (smallR[0].width() < 2 || smallR[0].height() < 2) { |
| 489 return kUnimplemented_FilterReturn; | 564 return kUnimplemented_FilterReturn; |
| 490 } | 565 } |
| 491 if (2 == count) { | 566 if (2 == count) { |
| 492 smallR[1].set(rects[1].left(), rects[1].top(), | 567 smallR[1].set(rects[1].left(), rects[1].top(), |
| 493 rects[1].right() - dx, rects[1].bottom() - dy); | 568 rects[1].right() - dx, rects[1].bottom() - dy); |
| 494 SkASSERT(!smallR[1].isEmpty()); | 569 SkASSERT(!smallR[1].isEmpty()); |
| 495 } | 570 } |
| 496 | 571 |
| 497 if (count > 1 || !c_analyticBlurNinepatch) { | 572 if (count > 1 || !c_analyticBlurNinepatch) { |
| 498 if (!draw_rects_into_mask(smallR, count, &srcM)) { | 573 if (!draw_rects_into_mask(smallR, count, &srcM)) { |
| 499 return kFalse_FilterReturn; | 574 return kFalse_FilterReturn; |
| 500 } | 575 } |
| 501 | |
| 502 SkAutoMaskFreeImage amf(srcM.fImage); | 576 SkAutoMaskFreeImage amf(srcM.fImage); |
| 503 | 577 |
| 504 if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { | 578 if (!this->filterMask(&patch->fCachedMask.fMask, srcM, matrix, &margin))
{ |
| 505 return kFalse_FilterReturn; | 579 return kFalse_FilterReturn; |
| 506 } | 580 } |
| 507 } else { | 581 } else { |
| 508 if (!this->filterRectMask(&patch->fMask, smallR[0], matrix, &margin, | 582 if (!this->filterRectMask(&patch->fCachedMask.fMask, smallR[0], matrix,
&margin, |
| 509 SkMask::kComputeBoundsAndRenderImage_CreateMod
e)) { | 583 SkMask::kComputeBoundsAndRenderImage_CreateMod
e)) { |
| 510 return kFalse_FilterReturn; | 584 return kFalse_FilterReturn; |
| 511 } | 585 } |
| 512 } | 586 } |
| 513 patch->fMask.fBounds.offsetTo(0, 0); | 587 patch->fCachedMask.fMask.fBounds.offsetTo(0, 0); |
| 514 patch->fOuterRect = dstM.fBounds; | 588 patch->fOuterRect = dstM.fBounds; |
| 515 patch->fCenter = center; | 589 patch->fCenter = center; |
| 590 if (!cachedBlurMask.fCacheId) { |
| 591 SkBitmap bitmap; |
| 592 bitmap.installMaskPixels(patch->fCachedMask.fMask); |
| 593 patch->fCachedMask.fCacheId = SkBitmapCache::AddAndLock(sigma, count, re
cts, bitmap); |
| 594 } |
| 595 |
| 516 return kTrue_FilterReturn; | 596 return kTrue_FilterReturn; |
| 517 } | 597 } |
| 518 | 598 |
| 519 void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, | 599 void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, |
| 520 SkRect* dst) const { | 600 SkRect* dst) const { |
| 521 SkScalar pad = 3.0f * fSigma; | 601 SkScalar pad = 3.0f * fSigma; |
| 522 | 602 |
| 523 dst->set(src.fLeft - pad, src.fTop - pad, | 603 dst->set(src.fLeft - pad, src.fTop - pad, |
| 524 src.fRight + pad, src.fBottom + pad); | 604 src.fRight + pad, src.fBottom + pad); |
| 525 } | 605 } |
| (...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1216 } else { | 1296 } else { |
| 1217 str->append("None"); | 1297 str->append("None"); |
| 1218 } | 1298 } |
| 1219 str->append("))"); | 1299 str->append("))"); |
| 1220 } | 1300 } |
| 1221 #endif | 1301 #endif |
| 1222 | 1302 |
| 1223 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) | 1303 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) |
| 1224 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) | 1304 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) |
| 1225 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 1305 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| OLD | NEW |