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