diff options
-rw-r--r-- | include/core/SkImageFilter.h | 11 | ||||
-rw-r--r-- | include/effects/SkColorFilterImageFilter.h | 2 | ||||
-rw-r--r-- | include/effects/SkLightingImageFilter.h | 2 | ||||
-rw-r--r-- | include/effects/SkMatrixConvolutionImageFilter.h | 2 | ||||
-rw-r--r-- | include/effects/SkPaintImageFilter.h | 2 | ||||
-rw-r--r-- | src/core/SkImageFilter.cpp | 36 | ||||
-rw-r--r-- | src/effects/SkColorFilterImageFilter.cpp | 7 | ||||
-rw-r--r-- | src/effects/SkMatrixConvolutionImageFilter.cpp | 4 | ||||
-rwxr-xr-x | src/effects/SkMergeImageFilter.cpp | 5 | ||||
-rw-r--r-- | src/effects/SkPaintImageFilter.cpp | 7 |
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 |