aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkImageFilter.h11
-rw-r--r--include/effects/SkColorFilterImageFilter.h2
-rw-r--r--include/effects/SkLightingImageFilter.h2
-rw-r--r--include/effects/SkMatrixConvolutionImageFilter.h2
-rw-r--r--include/effects/SkPaintImageFilter.h2
-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
10 files changed, 48 insertions, 30 deletions
diff --git a/include/core/SkImageFilter.h b/include/core/SkImageFilter.h
index d1b1483386..4493d282dd 100644
--- a/include/core/SkImageFilter.h
+++ b/include/core/SkImageFilter.h
@@ -88,12 +88,16 @@ public:
/**
* Apply this cropRect to the imageBounds. If a given edge of the cropRect is not
- * set, then the corresponding edge from imageBounds will be used.
+ * set, then the corresponding edge from imageBounds will be used. If "embiggen"
+ * is true, the crop rect is allowed to enlarge the size of the rect, otherwise
+ * it may only reduce the rect. Filters that can affect transparent black should
+ * pass "true", while all other filters should pass "false".
*
* Note: imageBounds is in "device" space, as the output cropped rectangle will be,
* so the matrix is ignored for those. It is only applied the croprect's bounds.
*/
- void applyTo(const SkIRect& imageBounds, const SkMatrix&, SkIRect* cropped) const;
+ void applyTo(const SkIRect& imageBounds, const SkMatrix&, bool embiggen,
+ SkIRect* cropped) const;
private:
SkRect fRect;
@@ -249,7 +253,7 @@ public:
virtual SkRect computeFastBounds(const SkRect&) const;
// Can this filter DAG compute the resulting bounds of an object-space rectangle?
- virtual bool canComputeFastBounds() const;
+ bool canComputeFastBounds() const;
/**
* If this filter can be represented by another filter + a localMatrix, return that filter,
@@ -466,6 +470,7 @@ private:
SkBitmap* result, SkIPoint* offset) const;
bool usesSrcInput() const { return fUsesSrcInput; }
+ virtual bool affectsTransparentBlack() const { return false; }
typedef SkFlattenable INHERITED;
int fInputCount;
diff --git a/include/effects/SkColorFilterImageFilter.h b/include/effects/SkColorFilterImageFilter.h
index 90e6e4bd71..ebe263930d 100644
--- a/include/effects/SkColorFilterImageFilter.h
+++ b/include/effects/SkColorFilterImageFilter.h
@@ -25,7 +25,7 @@ protected:
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
bool onIsColorFilterNode(SkColorFilter**) const override;
- bool canComputeFastBounds() const override;
+ bool affectsTransparentBlack() const override;
private:
SkColorFilterImageFilter(SkColorFilter* cf,
diff --git a/include/effects/SkLightingImageFilter.h b/include/effects/SkLightingImageFilter.h
index 33cfceccb2..fb356c52e4 100644
--- a/include/effects/SkLightingImageFilter.h
+++ b/include/effects/SkLightingImageFilter.h
@@ -49,7 +49,7 @@ protected:
void flatten(SkWriteBuffer&) const override;
const SkImageFilterLight* light() const { return fLight.get(); }
SkScalar surfaceScale() const { return fSurfaceScale; }
- bool canComputeFastBounds() const override { return false; }
+ bool affectsTransparentBlack() const override { return true; }
private:
typedef SkImageFilter INHERITED;
diff --git a/include/effects/SkMatrixConvolutionImageFilter.h b/include/effects/SkMatrixConvolutionImageFilter.h
index a4abb0d0cf..092af08f0c 100644
--- a/include/effects/SkMatrixConvolutionImageFilter.h
+++ b/include/effects/SkMatrixConvolutionImageFilter.h
@@ -80,7 +80,7 @@ protected:
bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&,
SkBitmap* result, SkIPoint* loc) const override;
SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix&, MapDirection) const override;
- bool canComputeFastBounds() const override;
+ bool affectsTransparentBlack() const override;
#if SK_SUPPORT_GPU
bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
diff --git a/include/effects/SkPaintImageFilter.h b/include/effects/SkPaintImageFilter.h
index 2876c0431b..35a76b80fb 100644
--- a/include/effects/SkPaintImageFilter.h
+++ b/include/effects/SkPaintImageFilter.h
@@ -26,7 +26,7 @@ public:
return sk_sp<SkImageFilter>(new SkPaintImageFilter(paint, cropRect));
}
- bool canComputeFastBounds() const override;
+ bool affectsTransparentBlack() const override;
SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPaintImageFilter)
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