diff options
-rw-r--r-- | src/core/SkCanvas.cpp | 23 | ||||
-rw-r--r-- | tests/CanvasTest.cpp | 50 |
2 files changed, 59 insertions, 14 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 0f079aac01..7fbb952d22 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -953,9 +953,6 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlag if (imageFilter) { clipBounds = imageFilter->filterBounds(clipBounds, ctm); - if (clipBounds.isEmpty()) { - return false; - } if (bounds && !imageFilter->canComputeFastBounds()) { bounds = nullptr; } @@ -963,21 +960,21 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlag SkIRect ir; if (bounds) { SkRect r; - ctm.mapRect(&r, *bounds); r.roundOut(&ir); - // early exit if the layer's bounds are clipped out - if (!ir.intersect(clipBounds)) { - if (BoundsAffectsClip(saveLayerFlags)) { - fMCRec->fTopLayer->fDevice->clipRegion(SkRegion(), SkClipOp::kIntersect); // empty - fMCRec->fRasterClip.setEmpty(); - fDeviceClipBounds.setEmpty(); - } - return false; - } } else { // no user bounds, so just use the clip ir = clipBounds; } + + // early exit if the layer's bounds are clipped out + if (!ir.intersect(clipBounds)) { + if (BoundsAffectsClip(saveLayerFlags)) { + fMCRec->fTopLayer->fDevice->clipRegion(SkRegion(), SkClipOp::kIntersect); // empty + fMCRec->fRasterClip.setEmpty(); + fDeviceClipBounds.setEmpty(); + } + return false; + } SkASSERT(!ir.isEmpty()); if (BoundsAffectsClip(saveLayerFlags)) { diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp index 9b1e0c9bbb..e83777ba96 100644 --- a/tests/CanvasTest.cpp +++ b/tests/CanvasTest.cpp @@ -61,10 +61,11 @@ #include "SkRect.h" #include "SkRegion.h" #include "SkShader.h" +#include "SkSpecialImage.h" #include "SkStream.h" #include "SkSurface.h" -#include "SkTemplates.h" #include "SkTDArray.h" +#include "SkTemplates.h" #include "SkVertices.h" #include "Test.h" @@ -812,3 +813,50 @@ DEF_TEST(Canvas_LegacyColorBehavior, r) { REPORTER_ASSERT(r, SK_ColorRED == SkSwizzle_BGRA_to_PMColor(*bitmap.getAddr32(0, 0))); } #endif + +namespace { + +class ZeroBoundsImageFilter : public SkImageFilter { +public: + static sk_sp<SkImageFilter> Make() { return sk_sp<SkImageFilter>(new ZeroBoundsImageFilter); } + + SK_TO_STRING_OVERRIDE() + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(ZeroBoundsImageFilter) + +protected: + sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage*, const Context&, SkIPoint*) const override { + return nullptr; + } + sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override { return nullptr; } + SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix&, MapDirection) const override { + return SkIRect::MakeEmpty(); + } + +private: + ZeroBoundsImageFilter() : INHERITED(nullptr, 0, nullptr) {} + + typedef SkImageFilter INHERITED; +}; + +sk_sp<SkFlattenable> ZeroBoundsImageFilter::CreateProc(SkReadBuffer& buffer) { + SkDEBUGFAIL("Should never get here"); + return nullptr; +} + +#ifndef SK_IGNORE_TO_STRING +void ZeroBoundsImageFilter::toString(SkString* str) const { + str->appendf("ZeroBoundsImageFilter: ()"); +} +#endif + +} // anonymous namespace + +DEF_TEST(Canvas_SaveLayerWithNullBoundsAndZeroBoundsImageFilter, r) { + SkCanvas canvas(10, 10); + SkPaint p; + p.setImageFilter(ZeroBoundsImageFilter::Make()); + // This should not fail any assert. + canvas.saveLayer(nullptr, &p); + REPORTER_ASSERT(r, canvas.getDeviceClipBounds().isEmpty()); + canvas.restore(); +} |