Extract code for safely creating SkMasks try 2

This is in preparation for adding a faster small radii blur.

Be sure to obey the original semantics about handling dst
when src.fImage is null.

Change-Id: Ic0ff0ac81494799e2d5037283904f1094309c622
Reviewed-on: https://skia-review.googlesource.com/70025
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Florin Malita <fmalita@chromium.org>
This commit is contained in:
Herb Derby 2017-11-10 12:55:24 -05:00 committed by Skia Commit-Bot
parent 48723156c5
commit 9f9041813e

View File

@ -542,6 +542,32 @@ bool SkMaskBlurFilter::hasNoBlur() const {
return (3 * fSigmaW <= 1) && (3 * fSigmaH <= 1);
}
static SkMask prepare_destination(int radiusX, int radiusY, const SkMask& src) {
SkSafeMath safe;
SkMask dst;
// dstW = srcW + 2 * radiusX;
int dstW = safe.add(src.fBounds.width(), safe.add(radiusX, radiusX));
// dstH = srcH + 2 * radiusY;
int dstH = safe.add(src.fBounds.height(), safe.add(radiusY, radiusY));
dst.fBounds.set(0, 0, dstW, dstH);
dst.fBounds.offset(src.fBounds.x(), src.fBounds.y());
dst.fBounds.offset(-SkTo<int32_t>(radiusX), -SkTo<int32_t>(radiusY));
dst.fImage = nullptr;
dst.fRowBytes = SkTo<uint32_t>(dstW);
dst.fFormat = SkMask::kA8_Format;
size_t toAlloc = safe.mul(dstW, dstH);
if (safe && src.fImage != nullptr) {
dst.fImage = SkMask::AllocImage(toAlloc);
}
return dst;
}
SkIPoint SkMaskBlurFilter::blur(const SkMask& src, SkMask* dst) const {
// 1024 is a place holder guess until more analysis can be done.
@ -550,38 +576,23 @@ SkIPoint SkMaskBlurFilter::blur(const SkMask& src, SkMask* dst) const {
PlanningInterface* planW = make_plan(&alloc, fSigmaW);
PlanningInterface* planH = make_plan(&alloc, fSigmaH);
size_t borderW = planW->border();
size_t borderH = planH->border();
size_t borderW = planW->border(),
borderH = planH->border();
*dst = prepare_destination(borderW, borderH, src);
if (src.fImage == nullptr) {
return {SkTo<int32_t>(borderW), SkTo<int32_t>(borderH)};
}
if (dst->fImage == nullptr) {
dst->fBounds.setEmpty();
return {0, 0};
}
auto srcW = SkTo<size_t>(src.fBounds.width());
auto srcH = SkTo<size_t>(src.fBounds.height());
SkSafeMath safe;
// size_t dstW = srcW + 2 * borderW;
size_t dstW = safe.add(srcW, safe.add(borderW, borderW));
//size_t dstH = srcH + 2 * borderH;
size_t dstH = safe.add(srcH, safe.add(borderH, borderH));
dst->fBounds.set(0, 0, dstW, dstH);
dst->fBounds.offset(src.fBounds.x(), src.fBounds.y());
dst->fBounds.offset(-SkTo<int32_t>(borderW), -SkTo<int32_t>(borderH));
dst->fImage = nullptr;
dst->fRowBytes = SkTo<uint32_t>(dstW);
dst->fFormat = SkMask::kA8_Format;
if (src.fImage == nullptr) {
return {SkTo<int32_t>(borderW), SkTo<int32_t>(borderH)};
}
size_t toAlloc = safe.mul(dstW, dstH);
if (!safe) {
dst->fBounds = SkIRect::MakeEmpty();
// There is no border offset because we are not drawing.
return {0, 0};
}
dst->fImage = SkMask::AllocImage(toAlloc);
size_t dstW = dst->fBounds.width(),
dstH = dst->fBounds.height();
auto bufferSize = std::max(planW->bufferSize(), planH->bufferSize());
auto buffer = alloc.makeArrayDefault<uint32_t>(bufferSize);