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 |