aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar senorblanco <senorblanco@chromium.org>2016-04-01 16:41:10 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-04-01 16:41:10 -0700
commit6db0a7bdceb6be85721bfb0db8dea7fd27db5970 (patch)
treeb963703827c0a0b99e40b6a4d7e5a9afed9947a1 /src
parent2d9c6f81353597aebf5934547e5cba7a872196fb (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')
-rw-r--r--src/core/SkImageFilter.cpp36
-rw-r--r--src/effects/SkColorFilterImageFilter.cpp7
-rw-r--r--src/effects/SkMatrixConvolutionImageFilter.cpp4
-rwxr-xr-xsrc/effects/SkMergeImageFilter.cpp5
-rw-r--r--src/effects/SkPaintImageFilter.cpp7
5 files changed, 36 insertions, 23 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;
}
diff --git a/src/effects/SkColorFilterImageFilter.cpp b/src/effects/SkColorFilterImageFilter.cpp
index beb3138c84..a5904ea60b 100644
--- a/src/effects/SkColorFilterImageFilter.cpp
+++ b/src/effects/SkColorFilterImageFilter.cpp
@@ -106,11 +106,8 @@ bool SkColorFilterImageFilter::onIsColorFilterNode(SkColorFilter** filter) const
return false;
}
-bool SkColorFilterImageFilter::canComputeFastBounds() const {
- if (fColorFilter->affectsTransparentBlack()) {
- return false;
- }
- return INHERITED::canComputeFastBounds();
+bool SkColorFilterImageFilter::affectsTransparentBlack() const {
+ return fColorFilter->affectsTransparentBlack();
}
#ifndef SK_IGNORE_TO_STRING
diff --git a/src/effects/SkMatrixConvolutionImageFilter.cpp b/src/effects/SkMatrixConvolutionImageFilter.cpp
index c8b43bbfd0..2a32fd5cdc 100644
--- a/src/effects/SkMatrixConvolutionImageFilter.cpp
+++ b/src/effects/SkMatrixConvolutionImageFilter.cpp
@@ -337,10 +337,10 @@ SkIRect SkMatrixConvolutionImageFilter::onFilterNodeBounds(const SkIRect& src, c
return dst;
}
-bool SkMatrixConvolutionImageFilter::canComputeFastBounds() const {
+bool SkMatrixConvolutionImageFilter::affectsTransparentBlack() const {
// Because the kernel is applied in device-space, we have no idea what
// pixels it will affect in object-space.
- return false;
+ return true;
}
#if SK_SUPPORT_GPU
diff --git a/src/effects/SkMergeImageFilter.cpp b/src/effects/SkMergeImageFilter.cpp
index 07b2c1cf3e..cd16d43db3 100755
--- a/src/effects/SkMergeImageFilter.cpp
+++ b/src/effects/SkMergeImageFilter.cpp
@@ -86,7 +86,10 @@ sk_sp<SkSpecialImage> SkMergeImageFilter::onFilterImage(SkSpecialImage* source,
}
// Apply the crop rect to the union of the inputs' bounds.
- this->getCropRect().applyTo(bounds, ctx.ctm(), &bounds);
+ // Note that the crop rect can only reduce the bounds, since this
+ // filter does not affect transparent black.
+ bool embiggen = false;
+ this->getCropRect().applyTo(bounds, ctx.ctm(), embiggen, &bounds);
if (!bounds.intersect(ctx.clipBounds())) {
return nullptr;
}
diff --git a/src/effects/SkPaintImageFilter.cpp b/src/effects/SkPaintImageFilter.cpp
index cbd793a692..4462b757f5 100644
--- a/src/effects/SkPaintImageFilter.cpp
+++ b/src/effects/SkPaintImageFilter.cpp
@@ -66,11 +66,8 @@ sk_sp<SkSpecialImage> SkPaintImageFilter::onFilterImage(SkSpecialImage* source,
return surf->makeImageSnapshot();
}
-bool SkPaintImageFilter::canComputeFastBounds() const {
- // http:skbug.com/4627: "make computeFastBounds and onFilterBounds() CropRect-aware"
- // computeFastBounds() doesn't currently take the crop rect into account,
- // so we can't compute it. If a full crop rect is set, we should return true here.
- return false;
+bool SkPaintImageFilter::affectsTransparentBlack() const {
+ return true;
}
#ifndef SK_IGNORE_TO_STRING