| 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 653 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 664 | 664 | 
| 665     if ( x > 0.5f ) { | 665     if ( x > 0.5f ) { | 
| 666         return 0.5625f - (x3 / 6.0f - 3.0f * x2 * 0.25f + 1.125f * x); | 666         return 0.5625f - (x3 / 6.0f - 3.0f * x2 * 0.25f + 1.125f * x); | 
| 667     } | 667     } | 
| 668     if ( x > -0.5f ) { | 668     if ( x > -0.5f ) { | 
| 669         return 0.5f - (0.75f * x - x3 / 3.0f); | 669         return 0.5f - (0.75f * x - x3 / 3.0f); | 
| 670     } | 670     } | 
| 671     return 0.4375f + (-x3 / 6.0f - 3.0f * x2 * 0.25f - 1.125f * x); | 671     return 0.4375f + (-x3 / 6.0f - 3.0f * x2 * 0.25f - 1.125f * x); | 
| 672 } | 672 } | 
| 673 | 673 | 
| 674 /*  compute_profile allocates and fills in an array of floating | 674 /*  ComputeBlurProfile allocates and fills in an array of floating | 
| 675     point values between 0 and 255 for the profile signature of | 675     point values between 0 and 255 for the profile signature of | 
| 676     a blurred half-plane with the given blur radius.  Since we're | 676     a blurred half-plane with the given blur radius.  Since we're | 
| 677     going to be doing screened multiplications (i.e., 1 - (1-x)(1-y)) | 677     going to be doing screened multiplications (i.e., 1 - (1-x)(1-y)) | 
| 678     all the time, we actually fill in the profile pre-inverted | 678     all the time, we actually fill in the profile pre-inverted | 
| 679     (already done 255-x). | 679     (already done 255-x). | 
| 680 | 680 | 
| 681     It's the responsibility of the caller to delete the | 681     It's the responsibility of the caller to delete the | 
| 682     memory returned in profile_out. | 682     memory returned in profile_out. | 
| 683 */ | 683 */ | 
| 684 | 684 | 
| 685 static void compute_profile(SkScalar sigma, unsigned int **profile_out) { | 685 void SkBlurMask::ComputeBlurProfile(SkScalar sigma, uint8_t **profile_out) { | 
| 686     int size = SkScalarCeilToInt(6*sigma); | 686     int size = SkScalarCeilToInt(6*sigma); | 
| 687 | 687 | 
| 688     int center = size >> 1; | 688     int center = size >> 1; | 
| 689     unsigned int *profile = SkNEW_ARRAY(unsigned int, size); | 689     uint8_t *profile = SkNEW_ARRAY(uint8_t, size); | 
| 690 | 690 | 
| 691     float invr = 1.f/(2*sigma); | 691     float invr = 1.f/(2*sigma); | 
| 692 | 692 | 
| 693     profile[0] = 255; | 693     profile[0] = 255; | 
| 694     for (int x = 1 ; x < size ; ++x) { | 694     for (int x = 1 ; x < size ; ++x) { | 
| 695         float scaled_x = (center - x - .5f) * invr; | 695         float scaled_x = (center - x - .5f) * invr; | 
| 696         float gi = gaussianIntegral(scaled_x); | 696         float gi = gaussianIntegral(scaled_x); | 
| 697         profile[x] = 255 - (uint8_t) (255.f * gi); | 697         profile[x] = 255 - (uint8_t) (255.f * gi); | 
| 698     } | 698     } | 
| 699 | 699 | 
| 700     *profile_out = profile; | 700     *profile_out = profile; | 
| 701 } | 701 } | 
| 702 | 702 | 
| 703 // TODO MAYBE: Maintain a profile cache to avoid recomputing this for | 703 // TODO MAYBE: Maintain a profile cache to avoid recomputing this for | 
| 704 // commonly used radii.  Consider baking some of the most common blur radii | 704 // commonly used radii.  Consider baking some of the most common blur radii | 
| 705 // directly in as static data? | 705 // directly in as static data? | 
| 706 | 706 | 
| 707 // Implementation adapted from Michael Herf's approach: | 707 // Implementation adapted from Michael Herf's approach: | 
| 708 // http://stereopsis.com/shadowrect/ | 708 // http://stereopsis.com/shadowrect/ | 
| 709 | 709 | 
| 710 static inline unsigned int profile_lookup( unsigned int *profile, int loc, int b
      lurred_width, int sharp_width ) { | 710 uint8_t SkBlurMask::ProfileLookup(const uint8_t *profile, int loc, int blurred_w
      idth, int sharp_width) { | 
| 711     int dx = SkAbs32(((loc << 1) + 1) - blurred_width) - sharp_width; // how far
       are we from the original edge? | 711     int dx = SkAbs32(((loc << 1) + 1) - blurred_width) - sharp_width; // how far
       are we from the original edge? | 
| 712     int ox = dx >> 1; | 712     int ox = dx >> 1; | 
| 713     if (ox < 0) { | 713     if (ox < 0) { | 
| 714         ox = 0; | 714         ox = 0; | 
| 715     } | 715     } | 
| 716 | 716 | 
| 717     return profile[ox]; | 717     return profile[ox]; | 
| 718 } | 718 } | 
| 719 | 719 | 
|  | 720 void SkBlurMask::ComputeBlurredScanline(uint8_t *pixels, const uint8_t *profile, | 
|  | 721                                         unsigned int width, SkScalar sigma) { | 
|  | 722 | 
|  | 723     unsigned int profile_size = SkScalarCeilToInt(6*sigma); | 
|  | 724     SkAutoTMalloc<uint8_t> horizontalScanline(width); | 
|  | 725 | 
|  | 726     unsigned int sw = width - profile_size; | 
|  | 727     // nearest odd number less than the profile size represents the center | 
|  | 728     // of the (2x scaled) profile | 
|  | 729     int center = ( profile_size & ~1 ) - 1; | 
|  | 730 | 
|  | 731     int w = sw - center; | 
|  | 732 | 
|  | 733     for (unsigned int x = 0 ; x < width ; ++x) { | 
|  | 734        if (profile_size <= sw) { | 
|  | 735            pixels[x] = ProfileLookup(profile, x, width, w); | 
|  | 736        } else { | 
|  | 737            float span = float(sw)/(2*sigma); | 
|  | 738            float giX = 1.5f - (x+.5f)/(2*sigma); | 
|  | 739            pixels[x] = (uint8_t) (255 * (gaussianIntegral(giX) - gaussianIntegra
      l(giX + span))); | 
|  | 740        } | 
|  | 741     } | 
|  | 742 } | 
|  | 743 | 
| 720 bool SkBlurMask::BlurRect(SkMask *dst, const SkRect &src, | 744 bool SkBlurMask::BlurRect(SkMask *dst, const SkRect &src, | 
| 721                           SkScalar radius, Style style, | 745                           SkScalar radius, Style style, | 
| 722                           SkIPoint *margin, SkMask::CreateMode createMode) { | 746                           SkIPoint *margin, SkMask::CreateMode createMode) { | 
| 723     return SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(radius), | 747     return SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(radius), | 
| 724                                 dst, src, | 748                                 dst, src, | 
| 725                                 style, margin, createMode); | 749                                 style, margin, createMode); | 
| 726 } | 750 } | 
| 727 | 751 | 
| 728 bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst, | 752 bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst, | 
| 729                           const SkRect &src, Style style, | 753                           const SkRect &src, Style style, | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 750     if (createMode == SkMask::kJustComputeBounds_CreateMode) { | 774     if (createMode == SkMask::kJustComputeBounds_CreateMode) { | 
| 751         if (style == kInner_Style) { | 775         if (style == kInner_Style) { | 
| 752             dst->fBounds.set(SkScalarRoundToInt(src.fLeft), | 776             dst->fBounds.set(SkScalarRoundToInt(src.fLeft), | 
| 753                              SkScalarRoundToInt(src.fTop), | 777                              SkScalarRoundToInt(src.fTop), | 
| 754                              SkScalarRoundToInt(src.fRight), | 778                              SkScalarRoundToInt(src.fRight), | 
| 755                              SkScalarRoundToInt(src.fBottom)); // restore trimme
      d bounds | 779                              SkScalarRoundToInt(src.fBottom)); // restore trimme
      d bounds | 
| 756             dst->fRowBytes = sw; | 780             dst->fRowBytes = sw; | 
| 757         } | 781         } | 
| 758         return true; | 782         return true; | 
| 759     } | 783     } | 
| 760     unsigned int *profile = NULL; | 784     uint8_t *profile = NULL; | 
| 761 | 785 | 
| 762     compute_profile(sigma, &profile); | 786     ComputeBlurProfile(sigma, &profile); | 
| 763     SkAutoTDeleteArray<unsigned int> ada(profile); | 787     SkAutoTDeleteArray<uint8_t> ada(profile); | 
| 764 | 788 | 
| 765     size_t dstSize = dst->computeImageSize(); | 789     size_t dstSize = dst->computeImageSize(); | 
| 766     if (0 == dstSize) { | 790     if (0 == dstSize) { | 
| 767         return false;   // too big to allocate, abort | 791         return false;   // too big to allocate, abort | 
| 768     } | 792     } | 
| 769 | 793 | 
| 770     uint8_t*        dp = SkMask::AllocImage(dstSize); | 794     uint8_t*        dp = SkMask::AllocImage(dstSize); | 
| 771 | 795 | 
| 772     dst->fImage = dp; | 796     dst->fImage = dp; | 
| 773 | 797 | 
| 774     int dstHeight = dst->fBounds.height(); | 798     int dstHeight = dst->fBounds.height(); | 
| 775     int dstWidth = dst->fBounds.width(); | 799     int dstWidth = dst->fBounds.width(); | 
| 776 | 800 | 
| 777     // nearest odd number less than the profile size represents the center |  | 
| 778     // of the (2x scaled) profile |  | 
| 779     int center = ( profile_size & ~1 ) - 1; |  | 
| 780 |  | 
| 781     int w = sw - center; |  | 
| 782     int h = sh - center; |  | 
| 783 |  | 
| 784     uint8_t *outptr = dp; | 801     uint8_t *outptr = dp; | 
| 785 | 802 | 
| 786     SkAutoTMalloc<uint8_t> horizontalScanline(dstWidth); | 803     SkAutoTMalloc<uint8_t> horizontalScanline(dstWidth); | 
| 787 | 804     SkAutoTMalloc<uint8_t> verticalScanline(dstHeight); | 
| 788     for (int x = 0 ; x < dstWidth ; ++x) { | 805 | 
| 789         if (profile_size <= sw) { | 806     ComputeBlurredScanline(horizontalScanline, profile, dstWidth, sigma); | 
| 790             horizontalScanline[x] = profile_lookup(profile, x, dstWidth, w); | 807     ComputeBlurredScanline(verticalScanline, profile, dstHeight, sigma); | 
| 791         } else { |  | 
| 792             float span = float(sw)/(2*sigma); |  | 
| 793             float giX = 1.5f - (x+.5f)/(2*sigma); |  | 
| 794             horizontalScanline[x] = (uint8_t) (255 * (gaussianIntegral(giX) - ga
      ussianIntegral(giX + span))); |  | 
| 795         } |  | 
| 796     } |  | 
| 797 | 808 | 
| 798     for (int y = 0 ; y < dstHeight ; ++y) { | 809     for (int y = 0 ; y < dstHeight ; ++y) { | 
| 799         unsigned int profile_y; |  | 
| 800         if (profile_size <= sh) { |  | 
| 801             profile_y = profile_lookup(profile, y, dstHeight, h); |  | 
| 802         } else { |  | 
| 803             float span = float(sh)/(2*sigma); |  | 
| 804             float giY = 1.5f - (y+.5f)/(2*sigma); |  | 
| 805             profile_y = (uint8_t) (255 * (gaussianIntegral(giY) - gaussianIntegr
      al(giY + span))); |  | 
| 806         } |  | 
| 807 |  | 
| 808         for (int x = 0 ; x < dstWidth ; x++) { | 810         for (int x = 0 ; x < dstWidth ; x++) { | 
| 809             unsigned int maskval = SkMulDiv255Round(horizontalScanline[x], profi
      le_y); | 811             unsigned int maskval = SkMulDiv255Round(horizontalScanline[x], verti
      calScanline[y]); | 
| 810             *(outptr++) = maskval; | 812             *(outptr++) = maskval; | 
| 811         } | 813         } | 
| 812     } | 814     } | 
| 813 | 815 | 
| 814     if (style == kInner_Style) { | 816     if (style == kInner_Style) { | 
| 815         // now we allocate the "real" dst, mirror the size of src | 817         // now we allocate the "real" dst, mirror the size of src | 
| 816         size_t srcSize = (size_t)(src.width() * src.height()); | 818         size_t srcSize = (size_t)(src.width() * src.height()); | 
| 817         if (0 == srcSize) { | 819         if (0 == srcSize) { | 
| 818             return false;   // too big to allocate, abort | 820             return false;   // too big to allocate, abort | 
| 819         } | 821         } | 
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 992         (void)autoCall.detach(); | 994         (void)autoCall.detach(); | 
| 993     } | 995     } | 
| 994 | 996 | 
| 995     if (style == kInner_Style) { | 997     if (style == kInner_Style) { | 
| 996         dst->fBounds = src.fBounds; // restore trimmed bounds | 998         dst->fBounds = src.fBounds; // restore trimmed bounds | 
| 997         dst->fRowBytes = src.fRowBytes; | 999         dst->fRowBytes = src.fRowBytes; | 
| 998     } | 1000     } | 
| 999 | 1001 | 
| 1000     return true; | 1002     return true; | 
| 1001 } | 1003 } | 
| OLD | NEW | 
|---|