diff options
author | senorblanco <senorblanco@chromium.org> | 2016-04-01 16:41:10 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-04-01 16:41:10 -0700 |
commit | 6db0a7bdceb6be85721bfb0db8dea7fd27db5970 (patch) | |
tree | b963703827c0a0b99e40b6a4d7e5a9afed9947a1 /src/core | |
parent | 2d9c6f81353597aebf5934547e5cba7a872196fb (diff) |
Image filters: optimize crop rect application.
If a filter does not affect transparent black, there's no
reason to allow the crop rect to expand beyond the optimal
size determined by onFilterNodeBounds(). So don't enlarge
the bounds unless the filter affects transparent black.
In order to determine which filters affect transparent
black, I've pulled the inverse of the canComputeFastBounds()
logic into a non-recursive, affectsTransparentBlack()
virtual, and left canComputeFastBounds() as a non-virtual,
recursive function that calls it.
BUG=599933
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1848953002
TBR=reed@google.com
Review URL: https://codereview.chromium.org/1848953002
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkImageFilter.cpp | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp index 3b4ad31456..11a2f74c70 100644 --- a/src/core/SkImageFilter.cpp +++ b/src/core/SkImageFilter.cpp @@ -69,25 +69,38 @@ void SkImageFilter::CropRect::toString(SkString* str) const { void SkImageFilter::CropRect::applyTo(const SkIRect& imageBounds, const SkMatrix& ctm, + bool embiggen, SkIRect* cropped) const { *cropped = imageBounds; if (fFlags) { SkRect devCropR; ctm.mapRect(&devCropR, fRect); - const SkIRect devICropR = devCropR.roundOut(); + SkIRect devICropR = devCropR.roundOut(); - // Compute the left/top first, in case we have to read them to compute right/bottom + // Compute the left/top first, in case we need to modify the right/bottom for a missing edge if (fFlags & kHasLeft_CropEdge) { - cropped->fLeft = devICropR.fLeft; + if (embiggen || devICropR.fLeft > cropped->fLeft) { + cropped->fLeft = devICropR.fLeft; + } + } else { + devICropR.fRight = cropped->fLeft + devICropR.width(); } if (fFlags & kHasTop_CropEdge) { - cropped->fTop = devICropR.fTop; + if (embiggen || devICropR.fTop > cropped->fTop) { + cropped->fTop = devICropR.fTop; + } + } else { + devICropR.fBottom = cropped->fTop + devICropR.height(); } if (fFlags & kHasWidth_CropEdge) { - cropped->fRight = cropped->fLeft + devICropR.width(); + if (embiggen || devICropR.fRight < cropped->fRight) { + cropped->fRight = devICropR.fRight; + } } if (fFlags & kHasHeight_CropEdge) { - cropped->fBottom = cropped->fTop + devICropR.height(); + if (embiggen || devICropR.fBottom < cropped->fBottom) { + cropped->fBottom = devICropR.fBottom; + } } } } @@ -306,7 +319,7 @@ SkIRect SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect bounds = this->onFilterBounds(src, ctm, direction); bounds = this->onFilterNodeBounds(bounds, ctm, direction); SkIRect dst; - this->getCropRect().applyTo(bounds, ctm, &dst); + this->getCropRect().applyTo(bounds, ctm, this->affectsTransparentBlack(), &dst); return dst; } } @@ -328,6 +341,9 @@ SkRect SkImageFilter::computeFastBounds(const SkRect& src) const { } bool SkImageFilter::canComputeFastBounds() const { + if (this->affectsTransparentBlack()) { + return false; + } for (int i = 0; i < fInputCount; i++) { SkImageFilter* input = this->getInput(i); if (input && !input->canComputeFastBounds()) { @@ -437,7 +453,7 @@ bool SkImageFilter::asAColorFilter(SkColorFilter** filterPtr) const { bool SkImageFilter::applyCropRect(const Context& ctx, const SkIRect& srcBounds, SkIRect* dstBounds) const { SkIRect temp = this->onFilterNodeBounds(srcBounds, ctx.ctm(), kForward_MapDirection); - fCropRect.applyTo(temp, ctx.ctm(), dstBounds); + fCropRect.applyTo(temp, ctx.ctm(), this->affectsTransparentBlack(), dstBounds); // Intersect against the clip bounds, in case the crop rect has // grown the bounds beyond the original clip. This can happen for // example in tiling, where the clip is much smaller than the filtered @@ -453,7 +469,7 @@ bool SkImageFilter::applyCropRectDeprecated(const Context& ctx, Proxy* proxy, co src.getBounds(&srcBounds); srcBounds.offset(*srcOffset); SkIRect dstBounds = this->onFilterNodeBounds(srcBounds, ctx.ctm(), kForward_MapDirection); - fCropRect.applyTo(dstBounds, ctx.ctm(), bounds); + fCropRect.applyTo(dstBounds, ctx.ctm(), this->affectsTransparentBlack(), bounds); if (!bounds->intersect(ctx.clipBounds())) { return false; } @@ -504,7 +520,7 @@ sk_sp<SkSpecialImage> SkImageFilter::applyCropRect(const Context& ctx, srcBounds = SkIRect::MakeXYWH(srcOffset->fX, srcOffset->fY, src->width(), src->height()); SkIRect dstBounds = this->onFilterNodeBounds(srcBounds, ctx.ctm(), kForward_MapDirection); - fCropRect.applyTo(dstBounds, ctx.ctm(), bounds); + fCropRect.applyTo(dstBounds, ctx.ctm(), this->affectsTransparentBlack(), bounds); if (!bounds->intersect(ctx.clipBounds())) { return nullptr; } |