| 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 | 9 |
| 10 #include "SkBlurMask.h" | 10 #include "SkBlurMask.h" |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 } | 428 } |
| 429 dst += dstRB; | 429 dst += dstRB; |
| 430 src += srcRB; | 430 src += srcRB; |
| 431 blur += blurRB; | 431 blur += blurRB; |
| 432 } | 432 } |
| 433 } | 433 } |
| 434 | 434 |
| 435 static void clamp_with_orig(uint8_t dst[], int dstRowBytes, | 435 static void clamp_with_orig(uint8_t dst[], int dstRowBytes, |
| 436 const uint8_t src[], int srcRowBytes, | 436 const uint8_t src[], int srcRowBytes, |
| 437 int sw, int sh, | 437 int sw, int sh, |
| 438 SkBlurMask::Style style) { | 438 SkBlurStyle style) { |
| 439 int x; | 439 int x; |
| 440 while (--sh >= 0) { | 440 while (--sh >= 0) { |
| 441 switch (style) { | 441 switch (style) { |
| 442 case SkBlurMask::kSolid_Style: | 442 case kSolid_SkBlurStyle: |
| 443 for (x = sw - 1; x >= 0; --x) { | 443 for (x = sw - 1; x >= 0; --x) { |
| 444 int s = *src; | 444 int s = *src; |
| 445 int d = *dst; | 445 int d = *dst; |
| 446 *dst = SkToU8(s + d - SkMulDiv255Round(s, d)); | 446 *dst = SkToU8(s + d - SkMulDiv255Round(s, d)); |
| 447 dst += 1; | 447 dst += 1; |
| 448 src += 1; | 448 src += 1; |
| 449 } | 449 } |
| 450 break; | 450 break; |
| 451 case SkBlurMask::kOuter_Style: | 451 case kOuter_SkBlurStyle: |
| 452 for (x = sw - 1; x >= 0; --x) { | 452 for (x = sw - 1; x >= 0; --x) { |
| 453 if (*src) { | 453 if (*src) { |
| 454 *dst = SkToU8(SkAlphaMul(*dst, SkAlpha255To256(255 - *src)))
; | 454 *dst = SkToU8(SkAlphaMul(*dst, SkAlpha255To256(255 - *src)))
; |
| 455 } | 455 } |
| 456 dst += 1; | 456 dst += 1; |
| 457 src += 1; | 457 src += 1; |
| 458 } | 458 } |
| 459 break; | 459 break; |
| 460 default: | 460 default: |
| 461 SkDEBUGFAIL("Unexpected blur style here"); | 461 SkDEBUGFAIL("Unexpected blur style here"); |
| 462 break; | 462 break; |
| 463 } | 463 } |
| 464 dst += dstRowBytes - sw; | 464 dst += dstRowBytes - sw; |
| 465 src += srcRowBytes - sw; | 465 src += srcRowBytes - sw; |
| 466 } | 466 } |
| 467 } | 467 } |
| 468 | 468 |
| 469 /////////////////////////////////////////////////////////////////////////////// | 469 /////////////////////////////////////////////////////////////////////////////// |
| 470 | 470 |
| 471 // we use a local function to wrap the class static method to work around | 471 // we use a local function to wrap the class static method to work around |
| 472 // a bug in gcc98 | 472 // a bug in gcc98 |
| 473 void SkMask_FreeImage(uint8_t* image); | 473 void SkMask_FreeImage(uint8_t* image); |
| 474 void SkMask_FreeImage(uint8_t* image) { | 474 void SkMask_FreeImage(uint8_t* image) { |
| 475 SkMask::FreeImage(image); | 475 SkMask::FreeImage(image); |
| 476 } | 476 } |
| 477 | 477 |
| 478 bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src, | 478 bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src, SkScalar sigma, SkBlurS
tyle style, |
| 479 SkScalar sigma, Style style, Quality quality, | 479 SkBlurQuality quality, SkIPoint* margin, bool force_qua
lity) { |
| 480 SkIPoint* margin, bool force_quality) { | |
| 481 | |
| 482 if (src.fFormat != SkMask::kA8_Format) { | 480 if (src.fFormat != SkMask::kA8_Format) { |
| 483 return false; | 481 return false; |
| 484 } | 482 } |
| 485 | 483 |
| 486 // Force high quality off for small radii (performance) | 484 // Force high quality off for small radii (performance) |
| 487 if (!force_quality && sigma <= SkIntToScalar(2)) { | 485 if (!force_quality && sigma <= SkIntToScalar(2)) { |
| 488 quality = kLow_Quality; | 486 quality = kLow_SkBlurQuality; |
| 489 } | 487 } |
| 490 | 488 |
| 491 SkScalar passRadius; | 489 SkScalar passRadius; |
| 492 if (kHigh_Quality == quality) { | 490 if (kHigh_SkBlurQuality == quality) { |
| 493 // For the high quality path the 3 pass box blur kernel width is | 491 // For the high quality path the 3 pass box blur kernel width is |
| 494 // 6*rad+1 while the full Gaussian width is 6*sigma. | 492 // 6*rad+1 while the full Gaussian width is 6*sigma. |
| 495 passRadius = sigma - (1/6.0f); | 493 passRadius = sigma - (1/6.0f); |
| 496 } else { | 494 } else { |
| 497 // For the low quality path we only attempt to cover 3*sigma of the | 495 // For the low quality path we only attempt to cover 3*sigma of the |
| 498 // Gaussian blur area (1.5*sigma on each side). The single pass box | 496 // Gaussian blur area (1.5*sigma on each side). The single pass box |
| 499 // blur's kernel size is 2*rad+1. | 497 // blur's kernel size is 2*rad+1. |
| 500 passRadius = 1.5f*sigma - 0.5f; | 498 passRadius = 1.5f*sigma - 0.5f; |
| 501 } | 499 } |
| 502 | 500 |
| 503 // highQuality: use three box blur passes as a cheap way | 501 // highQuality: use three box blur passes as a cheap way |
| 504 // to approximate a Gaussian blur | 502 // to approximate a Gaussian blur |
| 505 int passCount = (kHigh_Quality == quality) ? 3 : 1; | 503 int passCount = (kHigh_SkBlurQuality == quality) ? 3 : 1; |
| 506 | 504 |
| 507 int rx = SkScalarCeilToInt(passRadius); | 505 int rx = SkScalarCeilToInt(passRadius); |
| 508 int outerWeight = 255 - SkScalarRoundToInt((SkIntToScalar(rx) - passRadius)
* 255); | 506 int outerWeight = 255 - SkScalarRoundToInt((SkIntToScalar(rx) - passRadius)
* 255); |
| 509 | 507 |
| 510 SkASSERT(rx >= 0); | 508 SkASSERT(rx >= 0); |
| 511 SkASSERT((unsigned)outerWeight <= 255); | 509 SkASSERT((unsigned)outerWeight <= 255); |
| 512 if (rx <= 0) { | 510 if (rx <= 0) { |
| 513 return false; | 511 return false; |
| 514 } | 512 } |
| 515 | 513 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 541 SkAutoTCallVProc<uint8_t, SkMask_FreeImage> autoCall(dp); | 539 SkAutoTCallVProc<uint8_t, SkMask_FreeImage> autoCall(dp); |
| 542 | 540 |
| 543 // build the blurry destination | 541 // build the blurry destination |
| 544 SkAutoTMalloc<uint8_t> tmpBuffer(dstSize); | 542 SkAutoTMalloc<uint8_t> tmpBuffer(dstSize); |
| 545 uint8_t* tp = tmpBuffer.get(); | 543 uint8_t* tp = tmpBuffer.get(); |
| 546 int w = sw, h = sh; | 544 int w = sw, h = sh; |
| 547 | 545 |
| 548 if (outerWeight == 255) { | 546 if (outerWeight == 255) { |
| 549 int loRadius, hiRadius; | 547 int loRadius, hiRadius; |
| 550 get_adjusted_radii(passRadius, &loRadius, &hiRadius); | 548 get_adjusted_radii(passRadius, &loRadius, &hiRadius); |
| 551 if (kHigh_Quality == quality) { | 549 if (kHigh_SkBlurQuality == quality) { |
| 552 // Do three X blurs, with a transpose on the final one. | 550 // Do three X blurs, with a transpose on the final one. |
| 553 w = boxBlur(sp, src.fRowBytes, tp, loRadius, hiRadius, w, h, fal
se); | 551 w = boxBlur(sp, src.fRowBytes, tp, loRadius, hiRadius, w, h, fal
se); |
| 554 w = boxBlur(tp, w, dp, hiRadius, loRadius, w, h, fal
se); | 552 w = boxBlur(tp, w, dp, hiRadius, loRadius, w, h, fal
se); |
| 555 w = boxBlur(dp, w, tp, hiRadius, hiRadius, w, h, tru
e); | 553 w = boxBlur(dp, w, tp, hiRadius, hiRadius, w, h, tru
e); |
| 556 // Do three Y blurs, with a transpose on the final one. | 554 // Do three Y blurs, with a transpose on the final one. |
| 557 h = boxBlur(tp, h, dp, loRadius, hiRadius, h, w, fal
se); | 555 h = boxBlur(tp, h, dp, loRadius, hiRadius, h, w, fal
se); |
| 558 h = boxBlur(dp, h, tp, hiRadius, loRadius, h, w, fal
se); | 556 h = boxBlur(dp, h, tp, hiRadius, loRadius, h, w, fal
se); |
| 559 h = boxBlur(tp, h, dp, hiRadius, hiRadius, h, w, tru
e); | 557 h = boxBlur(tp, h, dp, hiRadius, hiRadius, h, w, tru
e); |
| 560 } else { | 558 } else { |
| 561 w = boxBlur(sp, src.fRowBytes, tp, rx, rx, w, h, true); | 559 w = boxBlur(sp, src.fRowBytes, tp, rx, rx, w, h, true); |
| 562 h = boxBlur(tp, h, dp, ry, ry, h, w, true); | 560 h = boxBlur(tp, h, dp, ry, ry, h, w, true); |
| 563 } | 561 } |
| 564 } else { | 562 } else { |
| 565 if (kHigh_Quality == quality) { | 563 if (kHigh_SkBlurQuality == quality) { |
| 566 // Do three X blurs, with a transpose on the final one. | 564 // Do three X blurs, with a transpose on the final one. |
| 567 w = boxBlurInterp(sp, src.fRowBytes, tp, rx, w, h, false, outerW
eight); | 565 w = boxBlurInterp(sp, src.fRowBytes, tp, rx, w, h, false, outerW
eight); |
| 568 w = boxBlurInterp(tp, w, dp, rx, w, h, false, outerW
eight); | 566 w = boxBlurInterp(tp, w, dp, rx, w, h, false, outerW
eight); |
| 569 w = boxBlurInterp(dp, w, tp, rx, w, h, true, outerWe
ight); | 567 w = boxBlurInterp(dp, w, tp, rx, w, h, true, outerWe
ight); |
| 570 // Do three Y blurs, with a transpose on the final one. | 568 // Do three Y blurs, with a transpose on the final one. |
| 571 h = boxBlurInterp(tp, h, dp, ry, h, w, false, outerW
eight); | 569 h = boxBlurInterp(tp, h, dp, ry, h, w, false, outerW
eight); |
| 572 h = boxBlurInterp(dp, h, tp, ry, h, w, false, outerW
eight); | 570 h = boxBlurInterp(dp, h, tp, ry, h, w, false, outerW
eight); |
| 573 h = boxBlurInterp(tp, h, dp, ry, h, w, true, outerWe
ight); | 571 h = boxBlurInterp(tp, h, dp, ry, h, w, true, outerWe
ight); |
| 574 } else { | 572 } else { |
| 575 w = boxBlurInterp(sp, src.fRowBytes, tp, rx, w, h, true, outerWe
ight); | 573 w = boxBlurInterp(sp, src.fRowBytes, tp, rx, w, h, true, outerWe
ight); |
| 576 h = boxBlurInterp(tp, h, dp, ry, h, w, true, outerWe
ight); | 574 h = boxBlurInterp(tp, h, dp, ry, h, w, true, outerWe
ight); |
| 577 } | 575 } |
| 578 } | 576 } |
| 579 | 577 |
| 580 dst->fImage = dp; | 578 dst->fImage = dp; |
| 581 // if need be, alloc the "real" dst (same size as src) and copy/merge | 579 // if need be, alloc the "real" dst (same size as src) and copy/merge |
| 582 // the blur into it (applying the src) | 580 // the blur into it (applying the src) |
| 583 if (style == kInner_Style) { | 581 if (style == kInner_SkBlurStyle) { |
| 584 // now we allocate the "real" dst, mirror the size of src | 582 // now we allocate the "real" dst, mirror the size of src |
| 585 size_t srcSize = src.computeImageSize(); | 583 size_t srcSize = src.computeImageSize(); |
| 586 if (0 == srcSize) { | 584 if (0 == srcSize) { |
| 587 return false; // too big to allocate, abort | 585 return false; // too big to allocate, abort |
| 588 } | 586 } |
| 589 dst->fImage = SkMask::AllocImage(srcSize); | 587 dst->fImage = SkMask::AllocImage(srcSize); |
| 590 merge_src_with_blur(dst->fImage, src.fRowBytes, | 588 merge_src_with_blur(dst->fImage, src.fRowBytes, |
| 591 sp, src.fRowBytes, | 589 sp, src.fRowBytes, |
| 592 dp + passCount * (rx + ry * dst->fRowBytes), | 590 dp + passCount * (rx + ry * dst->fRowBytes), |
| 593 dst->fRowBytes, sw, sh); | 591 dst->fRowBytes, sw, sh); |
| 594 SkMask::FreeImage(dp); | 592 SkMask::FreeImage(dp); |
| 595 } else if (style != kNormal_Style) { | 593 } else if (style != kNormal_SkBlurStyle) { |
| 596 clamp_with_orig(dp + passCount * (rx + ry * dst->fRowBytes), | 594 clamp_with_orig(dp + passCount * (rx + ry * dst->fRowBytes), |
| 597 dst->fRowBytes, sp, src.fRowBytes, sw, sh, style); | 595 dst->fRowBytes, sp, src.fRowBytes, sw, sh, style); |
| 598 } | 596 } |
| 599 (void)autoCall.detach(); | 597 (void)autoCall.detach(); |
| 600 } | 598 } |
| 601 | 599 |
| 602 if (style == kInner_Style) { | 600 if (style == kInner_SkBlurStyle) { |
| 603 dst->fBounds = src.fBounds; // restore trimmed bounds | 601 dst->fBounds = src.fBounds; // restore trimmed bounds |
| 604 dst->fRowBytes = src.fRowBytes; | 602 dst->fRowBytes = src.fRowBytes; |
| 605 } | 603 } |
| 606 | 604 |
| 607 return true; | 605 return true; |
| 608 } | 606 } |
| 609 | 607 |
| 610 /* Convolving a box with itself three times results in a piecewise | 608 /* Convolving a box with itself three times results in a piecewise |
| 611 quadratic function: | 609 quadratic function: |
| 612 | 610 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 pixels[x] = ProfileLookup(profile, x, width, w); | 725 pixels[x] = ProfileLookup(profile, x, width, w); |
| 728 } else { | 726 } else { |
| 729 float span = float(sw)/(2*sigma); | 727 float span = float(sw)/(2*sigma); |
| 730 float giX = 1.5f - (x+.5f)/(2*sigma); | 728 float giX = 1.5f - (x+.5f)/(2*sigma); |
| 731 pixels[x] = (uint8_t) (255 * (gaussianIntegral(giX) - gaussianIntegra
l(giX + span))); | 729 pixels[x] = (uint8_t) (255 * (gaussianIntegral(giX) - gaussianIntegra
l(giX + span))); |
| 732 } | 730 } |
| 733 } | 731 } |
| 734 } | 732 } |
| 735 | 733 |
| 736 bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst, | 734 bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst, |
| 737 const SkRect &src, Style style, | 735 const SkRect &src, SkBlurStyle style, |
| 738 SkIPoint *margin, SkMask::CreateMode createMode) { | 736 SkIPoint *margin, SkMask::CreateMode createMode) { |
| 739 int profile_size = SkScalarCeilToInt(6*sigma); | 737 int profile_size = SkScalarCeilToInt(6*sigma); |
| 740 | 738 |
| 741 int pad = profile_size/2; | 739 int pad = profile_size/2; |
| 742 if (margin) { | 740 if (margin) { |
| 743 margin->set( pad, pad ); | 741 margin->set( pad, pad ); |
| 744 } | 742 } |
| 745 | 743 |
| 746 dst->fBounds.set(SkScalarRoundToInt(src.fLeft - pad), | 744 dst->fBounds.set(SkScalarRoundToInt(src.fLeft - pad), |
| 747 SkScalarRoundToInt(src.fTop - pad), | 745 SkScalarRoundToInt(src.fTop - pad), |
| 748 SkScalarRoundToInt(src.fRight + pad), | 746 SkScalarRoundToInt(src.fRight + pad), |
| 749 SkScalarRoundToInt(src.fBottom + pad)); | 747 SkScalarRoundToInt(src.fBottom + pad)); |
| 750 | 748 |
| 751 dst->fRowBytes = dst->fBounds.width(); | 749 dst->fRowBytes = dst->fBounds.width(); |
| 752 dst->fFormat = SkMask::kA8_Format; | 750 dst->fFormat = SkMask::kA8_Format; |
| 753 dst->fImage = NULL; | 751 dst->fImage = NULL; |
| 754 | 752 |
| 755 int sw = SkScalarFloorToInt(src.width()); | 753 int sw = SkScalarFloorToInt(src.width()); |
| 756 int sh = SkScalarFloorToInt(src.height()); | 754 int sh = SkScalarFloorToInt(src.height()); |
| 757 | 755 |
| 758 if (createMode == SkMask::kJustComputeBounds_CreateMode) { | 756 if (createMode == SkMask::kJustComputeBounds_CreateMode) { |
| 759 if (style == kInner_Style) { | 757 if (style == kInner_SkBlurStyle) { |
| 760 dst->fBounds.set(SkScalarRoundToInt(src.fLeft), | 758 dst->fBounds.set(SkScalarRoundToInt(src.fLeft), |
| 761 SkScalarRoundToInt(src.fTop), | 759 SkScalarRoundToInt(src.fTop), |
| 762 SkScalarRoundToInt(src.fRight), | 760 SkScalarRoundToInt(src.fRight), |
| 763 SkScalarRoundToInt(src.fBottom)); // restore trimme
d bounds | 761 SkScalarRoundToInt(src.fBottom)); // restore trimme
d bounds |
| 764 dst->fRowBytes = sw; | 762 dst->fRowBytes = sw; |
| 765 } | 763 } |
| 766 return true; | 764 return true; |
| 767 } | 765 } |
| 768 uint8_t *profile = NULL; | 766 uint8_t *profile = NULL; |
| 769 | 767 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 790 ComputeBlurredScanline(horizontalScanline, profile, dstWidth, sigma); | 788 ComputeBlurredScanline(horizontalScanline, profile, dstWidth, sigma); |
| 791 ComputeBlurredScanline(verticalScanline, profile, dstHeight, sigma); | 789 ComputeBlurredScanline(verticalScanline, profile, dstHeight, sigma); |
| 792 | 790 |
| 793 for (int y = 0 ; y < dstHeight ; ++y) { | 791 for (int y = 0 ; y < dstHeight ; ++y) { |
| 794 for (int x = 0 ; x < dstWidth ; x++) { | 792 for (int x = 0 ; x < dstWidth ; x++) { |
| 795 unsigned int maskval = SkMulDiv255Round(horizontalScanline[x], verti
calScanline[y]); | 793 unsigned int maskval = SkMulDiv255Round(horizontalScanline[x], verti
calScanline[y]); |
| 796 *(outptr++) = maskval; | 794 *(outptr++) = maskval; |
| 797 } | 795 } |
| 798 } | 796 } |
| 799 | 797 |
| 800 if (style == kInner_Style) { | 798 if (style == kInner_SkBlurStyle) { |
| 801 // now we allocate the "real" dst, mirror the size of src | 799 // now we allocate the "real" dst, mirror the size of src |
| 802 size_t srcSize = (size_t)(src.width() * src.height()); | 800 size_t srcSize = (size_t)(src.width() * src.height()); |
| 803 if (0 == srcSize) { | 801 if (0 == srcSize) { |
| 804 return false; // too big to allocate, abort | 802 return false; // too big to allocate, abort |
| 805 } | 803 } |
| 806 dst->fImage = SkMask::AllocImage(srcSize); | 804 dst->fImage = SkMask::AllocImage(srcSize); |
| 807 for (int y = 0 ; y < sh ; y++) { | 805 for (int y = 0 ; y < sh ; y++) { |
| 808 uint8_t *blur_scanline = dp + (y+pad)*dstWidth + pad; | 806 uint8_t *blur_scanline = dp + (y+pad)*dstWidth + pad; |
| 809 uint8_t *inner_scanline = dst->fImage + y*sw; | 807 uint8_t *inner_scanline = dst->fImage + y*sw; |
| 810 memcpy(inner_scanline, blur_scanline, sw); | 808 memcpy(inner_scanline, blur_scanline, sw); |
| 811 } | 809 } |
| 812 SkMask::FreeImage(dp); | 810 SkMask::FreeImage(dp); |
| 813 | 811 |
| 814 dst->fBounds.set(SkScalarRoundToInt(src.fLeft), | 812 dst->fBounds.set(SkScalarRoundToInt(src.fLeft), |
| 815 SkScalarRoundToInt(src.fTop), | 813 SkScalarRoundToInt(src.fTop), |
| 816 SkScalarRoundToInt(src.fRight), | 814 SkScalarRoundToInt(src.fRight), |
| 817 SkScalarRoundToInt(src.fBottom)); // restore trimmed bo
unds | 815 SkScalarRoundToInt(src.fBottom)); // restore trimmed bo
unds |
| 818 dst->fRowBytes = sw; | 816 dst->fRowBytes = sw; |
| 819 | 817 |
| 820 } else if (style == kOuter_Style) { | 818 } else if (style == kOuter_SkBlurStyle) { |
| 821 for (int y = pad ; y < dstHeight-pad ; y++) { | 819 for (int y = pad ; y < dstHeight-pad ; y++) { |
| 822 uint8_t *dst_scanline = dp + y*dstWidth + pad; | 820 uint8_t *dst_scanline = dp + y*dstWidth + pad; |
| 823 memset(dst_scanline, 0, sw); | 821 memset(dst_scanline, 0, sw); |
| 824 } | 822 } |
| 825 } else if (style == kSolid_Style) { | 823 } else if (style == kSolid_SkBlurStyle) { |
| 826 for (int y = pad ; y < dstHeight-pad ; y++) { | 824 for (int y = pad ; y < dstHeight-pad ; y++) { |
| 827 uint8_t *dst_scanline = dp + y*dstWidth + pad; | 825 uint8_t *dst_scanline = dp + y*dstWidth + pad; |
| 828 memset(dst_scanline, 0xff, sw); | 826 memset(dst_scanline, 0xff, sw); |
| 829 } | 827 } |
| 830 } | 828 } |
| 831 // normal and solid styles are the same for analytic rect blurs, so don't | 829 // normal and solid styles are the same for analytic rect blurs, so don't |
| 832 // need to handle solid specially. | 830 // need to handle solid specially. |
| 833 | 831 |
| 834 return true; | 832 return true; |
| 835 } | 833 } |
| 836 | 834 |
| 837 bool SkBlurMask::BlurRRect(SkScalar sigma, SkMask *dst, | 835 bool SkBlurMask::BlurRRect(SkScalar sigma, SkMask *dst, |
| 838 const SkRRect &src, Style style, | 836 const SkRRect &src, SkBlurStyle style, |
| 839 SkIPoint *margin, SkMask::CreateMode createMode) { | 837 SkIPoint *margin, SkMask::CreateMode createMode) { |
| 840 // Temporary for now -- always fail, should cause caller to fall back | 838 // Temporary for now -- always fail, should cause caller to fall back |
| 841 // to old path. Plumbing just to land API and parallelize effort. | 839 // to old path. Plumbing just to land API and parallelize effort. |
| 842 | 840 |
| 843 return false; | 841 return false; |
| 844 } | 842 } |
| 845 | 843 |
| 846 // The "simple" blur is a direct implementation of separable convolution with a
discrete | 844 // The "simple" blur is a direct implementation of separable convolution with a
discrete |
| 847 // gaussian kernel. It's "ground truth" in a sense; too slow to be used, but ve
ry | 845 // gaussian kernel. It's "ground truth" in a sense; too slow to be used, but ve
ry |
| 848 // useful for correctness comparisons. | 846 // useful for correctness comparisons. |
| 849 | 847 |
| 850 bool SkBlurMask::BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src, | 848 bool SkBlurMask::BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src, |
| 851 Style style, SkIPoint* margin) { | 849 SkBlurStyle style, SkIPoint* margin) { |
| 852 | 850 |
| 853 if (src.fFormat != SkMask::kA8_Format) { | 851 if (src.fFormat != SkMask::kA8_Format) { |
| 854 return false; | 852 return false; |
| 855 } | 853 } |
| 856 | 854 |
| 857 float variance = sigma * sigma; | 855 float variance = sigma * sigma; |
| 858 | 856 |
| 859 int windowSize = SkScalarCeilToInt(sigma*6); | 857 int windowSize = SkScalarCeilToInt(sigma*6); |
| 860 // round window size up to nearest odd number | 858 // round window size up to nearest odd number |
| 861 windowSize |= 1; | 859 windowSize |= 1; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 957 finalValue /= windowSum; | 955 finalValue /= windowSum; |
| 958 uint8_t *outPixel = dstPixels + (x-pad)*dstWidth + y; // transpo
sed output | 956 uint8_t *outPixel = dstPixels + (x-pad)*dstWidth + y; // transpo
sed output |
| 959 int integerPixel = int(finalValue + 0.5f); | 957 int integerPixel = int(finalValue + 0.5f); |
| 960 *outPixel = SkClampMax( SkClampPos(integerPixel), 255 ); | 958 *outPixel = SkClampMax( SkClampPos(integerPixel), 255 ); |
| 961 } | 959 } |
| 962 } | 960 } |
| 963 | 961 |
| 964 dst->fImage = dstPixels; | 962 dst->fImage = dstPixels; |
| 965 // if need be, alloc the "real" dst (same size as src) and copy/merge | 963 // if need be, alloc the "real" dst (same size as src) and copy/merge |
| 966 // the blur into it (applying the src) | 964 // the blur into it (applying the src) |
| 967 if (style == kInner_Style) { | 965 if (style == kInner_SkBlurStyle) { |
| 968 // now we allocate the "real" dst, mirror the size of src | 966 // now we allocate the "real" dst, mirror the size of src |
| 969 size_t srcSize = src.computeImageSize(); | 967 size_t srcSize = src.computeImageSize(); |
| 970 if (0 == srcSize) { | 968 if (0 == srcSize) { |
| 971 return false; // too big to allocate, abort | 969 return false; // too big to allocate, abort |
| 972 } | 970 } |
| 973 dst->fImage = SkMask::AllocImage(srcSize); | 971 dst->fImage = SkMask::AllocImage(srcSize); |
| 974 merge_src_with_blur(dst->fImage, src.fRowBytes, | 972 merge_src_with_blur(dst->fImage, src.fRowBytes, |
| 975 srcPixels, src.fRowBytes, | 973 srcPixels, src.fRowBytes, |
| 976 dstPixels + pad*dst->fRowBytes + pad, | 974 dstPixels + pad*dst->fRowBytes + pad, |
| 977 dst->fRowBytes, srcWidth, srcHeight); | 975 dst->fRowBytes, srcWidth, srcHeight); |
| 978 SkMask::FreeImage(dstPixels); | 976 SkMask::FreeImage(dstPixels); |
| 979 } else if (style != kNormal_Style) { | 977 } else if (style != kNormal_SkBlurStyle) { |
| 980 clamp_with_orig(dstPixels + pad*dst->fRowBytes + pad, | 978 clamp_with_orig(dstPixels + pad*dst->fRowBytes + pad, |
| 981 dst->fRowBytes, srcPixels, src.fRowBytes, srcWidth, srcHeight, s
tyle); | 979 dst->fRowBytes, srcPixels, src.fRowBytes, srcWidth, srcHeight, s
tyle); |
| 982 } | 980 } |
| 983 (void)autoCall.detach(); | 981 (void)autoCall.detach(); |
| 984 } | 982 } |
| 985 | 983 |
| 986 if (style == kInner_Style) { | 984 if (style == kInner_SkBlurStyle) { |
| 987 dst->fBounds = src.fBounds; // restore trimmed bounds | 985 dst->fBounds = src.fBounds; // restore trimmed bounds |
| 988 dst->fRowBytes = src.fRowBytes; | 986 dst->fRowBytes = src.fRowBytes; |
| 989 } | 987 } |
| 990 | 988 |
| 991 return true; | 989 return true; |
| 992 } | 990 } |
| OLD | NEW |