48template <
typename AlphaIter>
50 AlphaIter src,
int srcRB,
51 const uint8_t blur[],
int blurRB,
56 AlphaIter rowSrc(src);
57 for (
int x = sw - 1;
x >= 0; --
x) {
69template <
typename AlphaIter>
71 AlphaIter src,
int srcRowBytes,
75 AlphaIter rowSrc(src);
76 for (
x = sw - 1;
x >= 0; --
x) {
83 dst += dstRowBytes - sw;
88template <
typename AlphaIter>
90 AlphaIter src,
int srcRowBytes,
94 AlphaIter rowSrc(src);
95 for (
x = sw - 1;
x >= 0; --
x) {
96 int srcValue = *rowSrc;
103 dst += dstRowBytes - sw;
127 if (blurFilter.hasNoBlur()) {
131 dst->image() =
nullptr;
133 dst->rowBytes() = dst->fBounds.width();
135 if (margin !=
nullptr) {
145 const SkIPoint border = blurFilter.blur(src, dst);
147 if (src.fImage !=
nullptr && dst->fImage ==
nullptr) {
151 if (margin !=
nullptr) {
155 if (src.fImage ==
nullptr) {
157 dst->bounds() = src.fBounds;
158 dst->rowBytes() = dst->fBounds.width();
167 auto dstStart = &dst->image()[border.
x() + border.
y() * dst->fRowBytes];
168 switch (src.fFormat) {
171 dstStart, dst->fRowBytes,
173 src.fBounds.width(), src.fBounds.height());
177 dstStart, dst->fRowBytes,
179 src.fBounds.width(), src.fBounds.height());
182 const uint32_t* srcARGB =
reinterpret_cast<const uint32_t*
>(src.fImage);
184 dstStart, dst->fRowBytes,
186 src.fBounds.width(), src.fBounds.height());
189 const uint16_t* srcLCD =
reinterpret_cast<const uint16_t*
>(src.fImage);
191 dstStart, dst->fRowBytes,
193 src.fBounds.width(), src.fBounds.height());
200 auto dstStart = &dst->image()[border.
x() + border.
y() * dst->fRowBytes];
201 switch (src.fFormat) {
204 dstStart, dst->fRowBytes,
206 src.fBounds.width(), src.fBounds.height());
210 dstStart, dst->fRowBytes,
212 src.fBounds.width(), src.fBounds.height());
215 const uint32_t* srcARGB =
reinterpret_cast<const uint32_t*
>(src.fImage);
217 dstStart, dst->fRowBytes,
219 src.fBounds.width(), src.fBounds.height());
222 const uint16_t* srcLCD =
reinterpret_cast<const uint16_t*
>(src.fImage);
224 dstStart, dst->fRowBytes,
226 src.fBounds.width(), src.fBounds.height());
238 size_t dstSize = dst->computeImageSize();
245 switch (src.fFormat) {
248 dst->image(), dst->fRowBytes,
251 src.fBounds.width(), src.fBounds.height());
255 dst->image(), dst->fRowBytes,
258 src.fBounds.width(), src.fBounds.height());
261 const uint32_t* srcARGB =
reinterpret_cast<const uint32_t*
>(src.fImage);
263 dst->image(), dst->fRowBytes,
266 src.fBounds.width(), src.fBounds.height());
269 const uint16_t* srcLCD =
reinterpret_cast<const uint16_t*
>(src.fImage);
271 dst->image(), dst->fRowBytes,
274 src.fBounds.width(), src.fBounds.height());
333 return 0.5625f - (x3 / 6.0f - 3.0f * x2 * 0.25f + 1.125f *
x);
336 return 0.5f - (0.75f *
x - x3 / 3.0f);
338 return 0.4375f + (-x3 / 6.0f - 3.0f * x2 * 0.25f - 1.125f *
x);
354 float invr = 1.f/(2*sigma);
357 for (
int x = 1 ;
x < size ; ++
x) {
358 float scaled_x = (
center -
x - .5f) * invr;
360 profile[
x] = 255 - (uint8_t) (255.f * gi);
372 int blurredWidth,
int sharpWidth) {
374 int dx =
SkAbs32(((loc << 1) + 1) - blurredWidth) - sharpWidth;
389 unsigned int sw =
width - profile_size;
392 int center = ( profile_size & ~1 ) - 1;
396 for (
unsigned int x = 0 ;
x <
width ; ++
x) {
397 if (profile_size <= sw) {
400 float span = float(sw)/(2*sigma);
401 float giX = 1.5f - (
x+.5f)/(2*sigma);
411 if (profileSize <= 0) {
415 int pad = profileSize/2;
417 margin->
set( pad, pad );
425 dst->rowBytes() = dst->fBounds.width();
427 dst->image() =
nullptr;
434 dst->bounds() = src.round();
435 dst->rowBytes() = sw;
444 size_t dstSize = dst->computeImageSize();
452 int dstHeight = dst->fBounds.height();
453 int dstWidth = dst->fBounds.width();
455 uint8_t *outptr = dp;
463 for (
int y = 0 ;
y < dstHeight ; ++
y) {
464 for (
int x = 0 ;
x < dstWidth ;
x++) {
466 *(outptr++) = maskval;
472 size_t srcSize = (size_t)(src.width() * src.height());
477 for (
int y = 0 ;
y < sh ;
y++) {
478 uint8_t *blur_scanline = dp + (
y+pad)*dstWidth + pad;
484 dst->bounds() = src.round();
485 dst->rowBytes() = sw;
488 for (
int y = pad ;
y < dstHeight-pad ;
y++) {
489 uint8_t *dst_scanline = dp +
y*dstWidth + pad;
490 memset(dst_scanline, 0, sw);
493 for (
int y = pad ;
y < dstHeight-pad ;
y++) {
494 uint8_t *dst_scanline = dp +
y*dstWidth + pad;
495 memset(dst_scanline, 0xff, sw);
524 float variance = sigma * sigma;
532 int halfWindow = windowSize >> 1;
534 gaussWindow[halfWindow] = 1;
537 for (
int x = 1 ;
x <= halfWindow ; ++
x) {
539 gaussWindow[halfWindow +
x] = gaussWindow[halfWindow-
x] =
gaussian;
546 int pad = halfWindow;
548 margin->
set( pad, pad );
551 dst->bounds() = src.fBounds;
552 dst->bounds().outset(pad, pad);
554 dst->rowBytes() = dst->fBounds.width();
556 dst->image() =
nullptr;
560 size_t dstSize = dst->computeImageSize();
565 int srcWidth = src.fBounds.width();
566 int srcHeight = src.fBounds.height();
567 int dstWidth = dst->fBounds.width();
569 const uint8_t* srcPixels = src.fImage;
576 int padWidth = srcWidth + 4*pad;
577 int padHeight = srcHeight;
578 int padSize = padWidth * padHeight;
581 memset(padPixels, 0, padSize);
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);
593 int tmpWidth = padHeight + 4*pad;
594 int tmpHeight = padWidth - 2*pad;
595 int tmpSize = tmpWidth * tmpHeight;
598 memset(tmpImage, 0, tmpSize*
sizeof(tmpImage[0]));
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];
608 *outPixel /= windowSum;
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];
624 finalValue /= windowSum;
625 uint8_t *outPixel = dstPixels + (
x-pad)*dstWidth +
y;
626 int integerPixel =
int(finalValue + 0.5f);
631 dst->image() = dstPixels;
637 dstPixels + pad*dst->fRowBytes + pad, dst->fRowBytes,
639 srcWidth, srcHeight);
643 dstPixels + pad*dst->fRowBytes + pad, dst->fRowBytes,
645 srcWidth, srcHeight);
649 size_t srcSize = src.computeImageSize();
656 dstPixels + pad*dst->fRowBytes + pad,
657 dst->fRowBytes, srcWidth, srcHeight);
661 autoFreeDstPixels.release();
665 dst->bounds() = src.fBounds;
666 dst->rowBytes() = src.fRowBytes;
static float gaussian(int x, SkScalar sigma)
#define SK_ABORT(message,...)
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 const SkScalar kBLUR_SIGMA_SCALE
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)
static float gaussianIntegral(float x)
void SkMask_FreeImage(uint8_t *image)
@ kOuter_SkBlurStyle
nothing inside, fuzzy outside
@ kSolid_SkBlurStyle
solid inside, fuzzy outside
@ kInner_SkBlurStyle
fuzzy inside, nothing outside
@ kNormal_SkBlurStyle
fuzzy inside and outside
#define SkAlphaMul(value, alpha256)
static unsigned SkAlpha255To256(U8CPU alpha)
std::unique_ptr< uint8_t, SkFunctionObject< SkMaskBuilder::FreeImage > > SkAutoMaskFreeImage
static int SkClampPos(int value)
static U8CPU SkMulDiv255Round(U16CPU a, U16CPU b)
static int32_t SkAbs32(int32_t value)
#define SkScalarRoundToInt(x)
#define SkScalarCeilToInt(x)
#define SkScalarFloorToInt(x)
static void inner_scanline(FDot8 L, int top, FDot8 R, U8CPU alpha, SkBlitter *blitter)
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
constexpr uint8_t SkToU8(S x)
static SkScalar center(float pos0, float pos1)
Type::kYUV Type::kRGBA() int(0.7 *637)
static void ComputeBlurProfile(uint8_t *profile, int size, SkScalar sigma)
static void ComputeBlurredScanline(uint8_t *pixels, const uint8_t *profile, unsigned int width, SkScalar sigma)
static bool BlurRect(SkScalar sigma, SkMaskBuilder *dst, const SkRect &src, SkBlurStyle, SkIPoint *margin=nullptr, SkMaskBuilder::CreateMode createMode=SkMaskBuilder::kComputeBoundsAndRenderImage_CreateMode)
static bool BlurRRect(SkScalar sigma, SkMaskBuilder *dst, const SkRRect &src, SkBlurStyle, SkIPoint *margin=nullptr, SkMaskBuilder::CreateMode createMode=SkMaskBuilder::kComputeBoundsAndRenderImage_CreateMode)
static SkScalar SK_SPI ConvertSigmaToRadius(SkScalar sigma)
static SkScalar SK_SPI ConvertRadiusToSigma(SkScalar radius)
static bool BlurGroundTruth(SkScalar sigma, SkMaskBuilder *dst, const SkMask &src, SkBlurStyle, SkIPoint *margin=nullptr)
static bool BoxBlur(SkMaskBuilder *dst, const SkMask &src, SkScalar sigma, SkBlurStyle style, SkIPoint *margin=nullptr)
static uint8_t ProfileLookup(const uint8_t *profile, int loc, int blurredWidth, int sharpWidth)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
constexpr int32_t y() const
void set(int32_t x, int32_t y)
constexpr int32_t x() const
static constexpr SkIRect MakeEmpty()
static void FreeImage(void *image)
@ kJustComputeBounds_CreateMode
compute bounds and return
static uint8_t * AllocImage(size_t bytes, AllocType=kUninit_Alloc)
@ kA8_Format
8bits per pixel mask (e.g. antialiasing)
@ kLCD16_Format
565 alpha for r/g/b
@ kARGB32_Format
SkPMColor.
@ kBW_Format
1bit per pixel mask (e.g. monochrome)