Make SkComposeImageFilter::onFilterImage filter the bounds given to the inner filter.
Previously, the bounds requested by the caller would be passed to both the inner and outer filter, but since the outer filter may move pixels, this is not necessarily sufficient to supply the pixels required by the outer filter to fill the bounds. Unit test included. GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1813373002 Review URL: https://codereview.chromium.org/1813373002
This commit is contained in:
parent
b95f55510b
commit
17a652017a
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user