| 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 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 point values between 0 and 255 for the profile signature of | 671 point values between 0 and 255 for the profile signature of |
| 672 a blurred half-plane with the given blur radius. Since we're | 672 a blurred half-plane with the given blur radius. Since we're |
| 673 going to be doing screened multiplications (i.e., 1 - (1-x)(1-y)) | 673 going to be doing screened multiplications (i.e., 1 - (1-x)(1-y)) |
| 674 all the time, we actually fill in the profile pre-inverted | 674 all the time, we actually fill in the profile pre-inverted |
| 675 (already done 255-x). | 675 (already done 255-x). |
| 676 | 676 |
| 677 It's the responsibility of the caller to delete the | 677 It's the responsibility of the caller to delete the |
| 678 memory returned in profile_out. | 678 memory returned in profile_out. |
| 679 */ | 679 */ |
| 680 | 680 |
| 681 void SkBlurMask::ComputeBlurProfile(SkScalar sigma, uint8_t **profile_out) { | 681 uint8_t* SkBlurMask::ComputeBlurProfile(SkScalar sigma) { |
| 682 int size = SkScalarCeilToInt(6*sigma); | 682 int size = SkScalarCeilToInt(6*sigma); |
| 683 | 683 |
| 684 int center = size >> 1; | 684 int center = size >> 1; |
| 685 uint8_t* profile = new uint8_t[size]; | 685 uint8_t* profile = new uint8_t[size]; |
| 686 | 686 |
| 687 float invr = 1.f/(2*sigma); | 687 float invr = 1.f/(2*sigma); |
| 688 | 688 |
| 689 profile[0] = 255; | 689 profile[0] = 255; |
| 690 for (int x = 1 ; x < size ; ++x) { | 690 for (int x = 1 ; x < size ; ++x) { |
| 691 float scaled_x = (center - x - .5f) * invr; | 691 float scaled_x = (center - x - .5f) * invr; |
| 692 float gi = gaussianIntegral(scaled_x); | 692 float gi = gaussianIntegral(scaled_x); |
| 693 profile[x] = 255 - (uint8_t) (255.f * gi); | 693 profile[x] = 255 - (uint8_t) (255.f * gi); |
| 694 } | 694 } |
| 695 | 695 |
| 696 *profile_out = profile; | 696 return profile; |
| 697 } | 697 } |
| 698 | 698 |
| 699 // TODO MAYBE: Maintain a profile cache to avoid recomputing this for | 699 // TODO MAYBE: Maintain a profile cache to avoid recomputing this for |
| 700 // commonly used radii. Consider baking some of the most common blur radii | 700 // commonly used radii. Consider baking some of the most common blur radii |
| 701 // directly in as static data? | 701 // directly in as static data? |
| 702 | 702 |
| 703 // Implementation adapted from Michael Herf's approach: | 703 // Implementation adapted from Michael Herf's approach: |
| 704 // http://stereopsis.com/shadowrect/ | 704 // http://stereopsis.com/shadowrect/ |
| 705 | 705 |
| 706 uint8_t SkBlurMask::ProfileLookup(const uint8_t *profile, int loc, int blurred_w
idth, int sharp_width) { | 706 uint8_t SkBlurMask::ProfileLookup(const uint8_t *profile, int loc, int blurred_w
idth, int sharp_width) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 if (createMode == SkMask::kJustComputeBounds_CreateMode) { | 762 if (createMode == SkMask::kJustComputeBounds_CreateMode) { |
| 763 if (style == kInner_SkBlurStyle) { | 763 if (style == kInner_SkBlurStyle) { |
| 764 dst->fBounds.set(SkScalarRoundToInt(src.fLeft), | 764 dst->fBounds.set(SkScalarRoundToInt(src.fLeft), |
| 765 SkScalarRoundToInt(src.fTop), | 765 SkScalarRoundToInt(src.fTop), |
| 766 SkScalarRoundToInt(src.fRight), | 766 SkScalarRoundToInt(src.fRight), |
| 767 SkScalarRoundToInt(src.fBottom)); // restore trimme
d bounds | 767 SkScalarRoundToInt(src.fBottom)); // restore trimme
d bounds |
| 768 dst->fRowBytes = sw; | 768 dst->fRowBytes = sw; |
| 769 } | 769 } |
| 770 return true; | 770 return true; |
| 771 } | 771 } |
| 772 uint8_t *profile = nullptr; | |
| 773 | 772 |
| 774 ComputeBlurProfile(sigma, &profile); | 773 SkAutoTDeleteArray<uint8_t> profile(ComputeBlurProfile(sigma)); |
| 775 SkAutoTDeleteArray<uint8_t> ada(profile); | |
| 776 | 774 |
| 777 size_t dstSize = dst->computeImageSize(); | 775 size_t dstSize = dst->computeImageSize(); |
| 778 if (0 == dstSize) { | 776 if (0 == dstSize) { |
| 779 return false; // too big to allocate, abort | 777 return false; // too big to allocate, abort |
| 780 } | 778 } |
| 781 | 779 |
| 782 uint8_t* dp = SkMask::AllocImage(dstSize); | 780 uint8_t* dp = SkMask::AllocImage(dstSize); |
| 783 | 781 |
| 784 dst->fImage = dp; | 782 dst->fImage = dp; |
| 785 | 783 |
| 786 int dstHeight = dst->fBounds.height(); | 784 int dstHeight = dst->fBounds.height(); |
| 787 int dstWidth = dst->fBounds.width(); | 785 int dstWidth = dst->fBounds.width(); |
| 788 | 786 |
| 789 uint8_t *outptr = dp; | 787 uint8_t *outptr = dp; |
| 790 | 788 |
| 791 SkAutoTMalloc<uint8_t> horizontalScanline(dstWidth); | 789 SkAutoTMalloc<uint8_t> horizontalScanline(dstWidth); |
| 792 SkAutoTMalloc<uint8_t> verticalScanline(dstHeight); | 790 SkAutoTMalloc<uint8_t> verticalScanline(dstHeight); |
| 793 | 791 |
| 794 ComputeBlurredScanline(horizontalScanline, profile, dstWidth, sigma); | 792 ComputeBlurredScanline(horizontalScanline, profile.get(), dstWidth, sigma); |
| 795 ComputeBlurredScanline(verticalScanline, profile, dstHeight, sigma); | 793 ComputeBlurredScanline(verticalScanline, profile.get(), dstHeight, sigma); |
| 796 | 794 |
| 797 for (int y = 0 ; y < dstHeight ; ++y) { | 795 for (int y = 0 ; y < dstHeight ; ++y) { |
| 798 for (int x = 0 ; x < dstWidth ; x++) { | 796 for (int x = 0 ; x < dstWidth ; x++) { |
| 799 unsigned int maskval = SkMulDiv255Round(horizontalScanline[x], verti
calScanline[y]); | 797 unsigned int maskval = SkMulDiv255Round(horizontalScanline[x], verti
calScanline[y]); |
| 800 *(outptr++) = maskval; | 798 *(outptr++) = maskval; |
| 801 } | 799 } |
| 802 } | 800 } |
| 803 | 801 |
| 804 if (style == kInner_SkBlurStyle) { | 802 if (style == kInner_SkBlurStyle) { |
| 805 // now we allocate the "real" dst, mirror the size of src | 803 // now we allocate the "real" dst, mirror the size of src |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 987 (void)autoCall.detach(); | 985 (void)autoCall.detach(); |
| 988 } | 986 } |
| 989 | 987 |
| 990 if (style == kInner_SkBlurStyle) { | 988 if (style == kInner_SkBlurStyle) { |
| 991 dst->fBounds = src.fBounds; // restore trimmed bounds | 989 dst->fBounds = src.fBounds; // restore trimmed bounds |
| 992 dst->fRowBytes = src.fRowBytes; | 990 dst->fRowBytes = src.fRowBytes; |
| 993 } | 991 } |
| 994 | 992 |
| 995 return true; | 993 return true; |
| 996 } | 994 } |
| OLD | NEW |