Fix for empty saveLayer() with a filter which affects transparent black.
If an saveLayer()/restore() is recorded, tilegrid/rtree will cull them
out and not draw anything. This is correct for most cases, but if the
paint in the saveLayer() is one that affects transparent black (e.g.,
it contains a color filter or image filter which affects transparent
black), this is incorrect: the filter should be applied.
Fixed by adding a no-op between the saveLayer() and restore(), and
adding a bbox node pointing at that node with the saveLayer()'s bounds.
This exposed a bug in SkPictureRecord.cpp's match(), where it would
assert if the NOOP was the last op seen. Fixed with an early-out before
calling peek_op_and_size().
BUG=skia:2254
Review URL: https://codereview.chromium.org/262363007
git-svn-id: http://skia.googlecode.com/svn/trunk@14604 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp
index 08277a1..f8492a7 100644
--- a/tests/ImageFilterTest.cpp
+++ b/tests/ImageFilterTest.cpp
@@ -467,6 +467,61 @@
canvas.drawPicture(*picture);
}
+DEF_TEST(ImageFilterEmptySaveLayerTest, reporter) {
+
+ // Even when there's an empty saveLayer()/restore(), ensure that an image
+ // filter or color filter which affects transparent black still draws.
+
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(10, 10);
+ SkBitmapDevice device(bitmap);
+ SkCanvas canvas(&device);
+
+ SkRTreeFactory factory;
+ SkPictureRecorder recorder;
+
+ SkAutoTUnref<SkColorFilter> green(
+ SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrc_Mode));
+ SkAutoTUnref<SkColorFilterImageFilter> imageFilter(
+ SkColorFilterImageFilter::Create(green.get()));
+ SkPaint imageFilterPaint;
+ imageFilterPaint.setImageFilter(imageFilter.get());
+ SkPaint colorFilterPaint;
+ colorFilterPaint.setColorFilter(green.get());
+
+ SkRect bounds = SkRect::MakeWH(10, 10);
+
+ SkCanvas* recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
+ recordingCanvas->saveLayer(&bounds, &imageFilterPaint);
+ recordingCanvas->restore();
+ SkAutoTUnref<SkPicture> picture(recorder.endRecording());
+
+ canvas.clear(0);
+ canvas.drawPicture(*picture);
+ uint32_t pixel = *bitmap.getAddr32(0, 0);
+ REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
+
+ recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
+ recordingCanvas->saveLayer(NULL, &imageFilterPaint);
+ recordingCanvas->restore();
+ SkAutoTUnref<SkPicture> picture2(recorder.endRecording());
+
+ canvas.clear(0);
+ canvas.drawPicture(*picture2);
+ pixel = *bitmap.getAddr32(0, 0);
+ REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
+
+ recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
+ recordingCanvas->saveLayer(&bounds, &colorFilterPaint);
+ recordingCanvas->restore();
+ SkAutoTUnref<SkPicture> picture3(recorder.endRecording());
+
+ canvas.clear(0);
+ canvas.drawPicture(*picture3);
+ pixel = *bitmap.getAddr32(0, 0);
+ REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
+}
+
static void test_huge_blur(SkBaseDevice* device, skiatest::Reporter* reporter) {
SkCanvas canvas(device);