diff options
-rw-r--r-- | src/effects/SkComposeImageFilter.cpp | 8 | ||||
-rw-r--r-- | tests/ImageFilterTest.cpp | 45 |
2 files changed, 52 insertions, 1 deletions
diff --git a/src/effects/SkComposeImageFilter.cpp b/src/effects/SkComposeImageFilter.cpp index 90844ef9dc..b9216611ab 100644 --- a/src/effects/SkComposeImageFilter.cpp +++ b/src/effects/SkComposeImageFilter.cpp @@ -23,8 +23,14 @@ void SkComposeImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) con SkSpecialImage* SkComposeImageFilter::onFilterImage(SkSpecialImage* source, const Context& ctx, SkIPoint* offset) const { + // The bounds passed to the inner filter must be filtered by the outer + // filter, so that the inner filter produces the pixels that the outer + // filter requires as input. This matters if the outer filter moves pixels. + SkIRect innerClipBounds; + getInput(0)->filterBounds(ctx.clipBounds(), ctx.ctm(), &innerClipBounds); + Context innerContext(ctx.ctm(), innerClipBounds, ctx.cache()); SkIPoint innerOffset = SkIPoint::Make(0, 0); - SkAutoTUnref<SkSpecialImage> inner(this->filterInput(1, source, ctx, &innerOffset)); + SkAutoTUnref<SkSpecialImage> inner(this->filterInput(1, source, innerContext, &innerOffset)); if (!inner) { return nullptr; } diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp index 6a2f942658..b9b0028f2d 100644 --- a/tests/ImageFilterTest.cpp +++ b/tests/ImageFilterTest.cpp @@ -1369,6 +1369,51 @@ DEF_GPUTEST_FOR_NATIVE_CONTEXT(ComposedImageFilterOffset_Gpu, reporter, context) } #endif +static void test_composed_imagefilter_bounds(SkImageFilter::Proxy* proxy, + skiatest::Reporter* reporter, + GrContext* context) { + // The bounds passed to the inner filter must be filtered by the outer + // filter, so that the inner filter produces the pixels that the outer + // filter requires as input. This matters if the outer filter moves pixels. + // Here, accounting for the outer offset is necessary so that the green + // pixels of the picture are not clipped. + + SkPictureRecorder recorder; + SkCanvas* recordingCanvas = recorder.beginRecording(SkRect::MakeWH(200, 100)); + recordingCanvas->clipRect(SkRect::MakeXYWH(100, 0, 100, 100)); + recordingCanvas->clear(SK_ColorGREEN); + sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture(); + sk_sp<SkImageFilter> pictureFilter( + SkPictureImageFilter::Create(picture.get())); + SkImageFilter::CropRect cropRect(SkRect::MakeWH(100, 100)); + sk_sp<SkImageFilter> offsetFilter(SkOffsetImageFilter::Create(-100, 0, nullptr, &cropRect)); + sk_sp<SkImageFilter> composedFilter( + SkComposeImageFilter::Create(offsetFilter.get(), pictureFilter.get())); + + sk_sp<SkSpecialImage> sourceImage(create_empty_special_image(context, proxy, 100)); + SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr); + SkIPoint offset; + sk_sp<SkSpecialImage> result(composedFilter->filterImage(sourceImage.get(), ctx, &offset)); + REPORTER_ASSERT(reporter, offset.isZero()); + REPORTER_ASSERT(reporter, result); + REPORTER_ASSERT(reporter, result->subset().size() == SkISize::Make(100, 100)); + + SkBitmap resultBM; + TestingSpecialImageAccess::GetROPixels(result.get(), &resultBM); + SkAutoLockPixels lock(resultBM); + REPORTER_ASSERT(reporter, resultBM.getColor(50, 50) == SK_ColorGREEN); +} + +DEF_TEST(ComposedImageFilterBounds, reporter) { + run_raster_test(reporter, 100, test_composed_imagefilter_bounds); +} + +#if SK_SUPPORT_GPU +DEF_GPUTEST_FOR_NATIVE_CONTEXT(ComposedImageFilterBounds_Gpu, reporter, context) { + run_gpu_test(reporter, context, 100, test_composed_imagefilter_bounds); +} +#endif + static void test_partial_crop_rect(SkImageFilter::Proxy* proxy, skiatest::Reporter* reporter, GrContext* context) { |