955 {
956
957 if (fSigmaW < 2.0 && fSigmaH < 2.0) {
958 return small_blur(fSigmaW, fSigmaH, src, dst);
959 }
960
961
963
964 PlanGauss planW(fSigmaW);
965 PlanGauss planH(fSigmaH);
966
967 int borderW = planW.border(),
968 borderH = planH.border();
969 SkASSERT(borderH >= 0 && borderW >= 0);
970
972 if (
src.fImage ==
nullptr) {
973 return {SkTo<int32_t>(borderW), SkTo<int32_t>(borderH)};
974 }
975 if (
dst->fImage ==
nullptr) {
976 dst->bounds().setEmpty();
977 return {0, 0};
978 }
979
980 int srcW =
src.fBounds.width(),
981 srcH =
src.fBounds.height(),
982 dstW =
dst->fBounds.width(),
983 dstH =
dst->fBounds.height();
984 SkASSERT(srcW >= 0 && srcH >= 0 && dstW >= 0 && dstH >= 0);
985
986 auto bufferSize = std::max(planW.bufferSize(), planH.bufferSize());
988
989
990 int tmpW = srcH,
991 tmpH = dstW;
992
993
994 if (tmpH > std::numeric_limits<int>::max() / tmpW) {
995 return {0, 0};
996 }
998
999
1000 const PlanGauss::Scan& scanW = planW.makeBlurScan(srcW,
buffer);
1001 switch (
src.fFormat) {
1003 const uint8_t* bwStart =
src.fImage;
1006 for (
int y = 0; y < srcH; ++y, start >>=
src.fRowBytes,
end >>=
src.fRowBytes) {
1007 auto tmpStart = &tmp[
y];
1008 scanW.blur(
start,
end, tmpStart, tmpW, tmpStart + tmpW * tmpH);
1009 }
1010 } break;
1012 const uint8_t* a8Start =
src.fImage;
1015 for (
int y = 0; y < srcH; ++y, start >>=
src.fRowBytes,
end >>=
src.fRowBytes) {
1016 auto tmpStart = &tmp[
y];
1017 scanW.blur(
start,
end, tmpStart, tmpW, tmpStart + tmpW * tmpH);
1018 }
1019 } break;
1021 const uint32_t* argbStart =
reinterpret_cast<const uint32_t*
>(
src.fImage);
1024 for (
int y = 0; y < srcH; ++y, start >>=
src.fRowBytes,
end >>=
src.fRowBytes) {
1025 auto tmpStart = &tmp[
y];
1026 scanW.blur(
start,
end, tmpStart, tmpW, tmpStart + tmpW * tmpH);
1027 }
1028 } break;
1030 const uint16_t* lcdStart =
reinterpret_cast<const uint16_t*
>(
src.fImage);
1033 for (
int y = 0; y < srcH; ++y, start >>=
src.fRowBytes,
end >>=
src.fRowBytes) {
1034 auto tmpStart = &tmp[
y];
1035 scanW.blur(
start,
end, tmpStart, tmpW, tmpStart + tmpW * tmpH);
1036 }
1037 } break;
1038 default:
1040 }
1041
1042
1043
1044 const PlanGauss::Scan& scanH = planH.makeBlurScan(tmpW,
buffer);
1045 for (
int y = 0;
y < tmpH;
y++) {
1046 auto tmpStart = &tmp[
y * tmpW];
1047 auto dstStart = &
dst->image()[
y];
1048
1049 scanH.blur(tmpStart, tmpStart + tmpW,
1050 dstStart,
dst->fRowBytes, dstStart +
dst->fRowBytes * dstH);
1051 }
1052
1053 return {SkTo<int32_t>(borderW), SkTo<int32_t>(borderH)};
1054}
#define SK_ABORT(message,...)
static SkIPoint small_blur(double sigmaX, double sigmaY, const SkMask &src, SkMaskBuilder *dst)
T * makeArrayDefault(size_t count)
static const uint8_t buffer[]
static SkMaskBuilder PrepareDestination(int radiusX, int radiusY, const SkMask &src)
@ 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)