518 {
519
521 return false;
522 }
523
524 float variance = sigma * sigma;
525
527
528 windowSize |= 1;
529
531
532 int halfWindow = windowSize >> 1;
533
534 gaussWindow[halfWindow] = 1;
535
536 float windowSum = 1;
537 for (
int x = 1 ;
x <= halfWindow ; ++
x) {
539 gaussWindow[halfWindow +
x] = gaussWindow[halfWindow-
x] =
gaussian;
541 }
542
543
544
545
546 int pad = halfWindow;
547 if (margin) {
548 margin->
set( pad, pad );
549 }
550
551 dst->bounds() =
src.fBounds;
552 dst->bounds().outset(pad, pad);
553
554 dst->rowBytes() =
dst->fBounds.width();
556 dst->image() =
nullptr;
557
559
560 size_t dstSize =
dst->computeImageSize();
561 if (0 == dstSize) {
562 return false;
563 }
564
565 int srcWidth =
src.fBounds.width();
566 int srcHeight =
src.fBounds.height();
567 int dstWidth =
dst->fBounds.width();
568
569 const uint8_t* srcPixels =
src.fImage;
572
573
574
575
576 int padWidth = srcWidth + 4*pad;
577 int padHeight = srcHeight;
578 int padSize = padWidth * padHeight;
579
581 memset(padPixels, 0, padSize);
582
583 for (
int y = 0 ;
y < srcHeight; ++
y) {
584 uint8_t* padptr = padPixels +
y * padWidth + 2*pad;
585 const uint8_t* srcptr = srcPixels +
y * srcWidth;
586 memcpy(padptr, srcptr, srcWidth);
587 }
588
589
590
591
592
593 int tmpWidth = padHeight + 4*pad;
594 int tmpHeight = padWidth - 2*pad;
595 int tmpSize = tmpWidth * tmpHeight;
596
598 memset(tmpImage, 0, tmpSize*sizeof(tmpImage[0]));
599
600 for (
int y = 0 ;
y < padHeight ; ++
y) {
601 uint8_t *srcScanline = padPixels +
y*padWidth;
602 for (
int x = pad ;
x < padWidth - pad ; ++
x) {
603 float *outPixel = tmpImage + (
x-pad)*tmpWidth +
y + 2*pad;
604 uint8_t *windowCenter = srcScanline +
x;
605 for (
int i = -pad ;
i <= pad ; ++
i) {
606 *outPixel += gaussWindow[pad+
i]*windowCenter[
i];
607 }
608 *outPixel /= windowSum;
609 }
610 }
611
612
613
614
615
616 for (
int y = 0 ;
y < tmpHeight ; ++
y) {
617 float *srcScanline = tmpImage +
y*tmpWidth;
618 for (
int x = pad ;
x < tmpWidth - pad ; ++
x) {
619 float *windowCenter = srcScanline +
x;
620 float finalValue = 0;
621 for (
int i = -pad ;
i <= pad ; ++
i) {
622 finalValue += gaussWindow[pad+
i]*windowCenter[
i];
623 }
624 finalValue /= windowSum;
625 uint8_t *outPixel = dstPixels + (
x-pad)*dstWidth +
y;
626 int integerPixel =
int(finalValue + 0.5f);
628 }
629 }
630
631 dst->image() = dstPixels;
632 switch (style) {
634 break;
637 dstPixels + pad*
dst->fRowBytes + pad,
dst->fRowBytes,
639 srcWidth, srcHeight);
640 } break;
643 dstPixels + pad*
dst->fRowBytes + pad,
dst->fRowBytes,
645 srcWidth, srcHeight);
646 } break;
648
649 size_t srcSize =
src.computeImageSize();
650 if (0 == srcSize) {
651 return false;
652 }
656 dstPixels + pad*
dst->fRowBytes + pad,
657 dst->fRowBytes, srcWidth, srcHeight);
659 } break;
660 }
661 autoFreeDstPixels.release();
662 }
663
665 dst->bounds() =
src.fBounds;
666 dst->rowBytes() =
src.fRowBytes;
667 }
668
669 return true;
670}
static float gaussian(int x, SkScalar sigma)
static void merge_src_with_blur(uint8_t dst[], int dstRB, AlphaIter src, int srcRB, const uint8_t blur[], int blurRB, int sw, int sh)
static void clamp_solid_with_orig(uint8_t dst[], int dstRowBytes, AlphaIter src, int srcRowBytes, int sw, int sh)
static void clamp_outer_with_orig(uint8_t dst[], int dstRowBytes, AlphaIter src, int srcRowBytes, int sw, int sh)
@ kOuter_SkBlurStyle
nothing inside, fuzzy outside
@ kSolid_SkBlurStyle
solid inside, fuzzy outside
@ kInner_SkBlurStyle
fuzzy inside, nothing outside
@ kNormal_SkBlurStyle
fuzzy inside and outside
std::unique_ptr< uint8_t, SkFunctionObject< SkMaskBuilder::FreeImage > > SkAutoMaskFreeImage
static int SkClampPos(int value)
#define SkScalarCeilToInt(x)
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
void set(int32_t x, int32_t y)
static void FreeImage(void *image)
static uint8_t * AllocImage(size_t bytes, AllocType=kUninit_Alloc)
@ kA8_Format
8bits per pixel mask (e.g. antialiasing)