From d910f544439fffa6c2bcc5181b79b2811a4c130a Mon Sep 17 00:00:00 2001 From: mtklein Date: Fri, 22 Aug 2014 09:06:34 -0700 Subject: Fix saveLayer() with a pixel-moving filter vs SkBBoxHierarchyRecord / SkRecordDraw In SkBBoxHierarchyRecord: Since the bounds we pass to saveLayer are in the pre-filtering coordinate space, they aren't correct for determining the actual device pixels touched by the saveLayer in this case. The easiest fix for now is to pass the clip bounds, since the final draw done in restore() will never draw outside the clip. In SkRecordDraw: We do adjust the bounds passed to saveLayer, so we just need to make sure that when we're using a paint that may affect transparent black, we ignore the calculated bounds of draw ops and use the clip intersected with those adjusted bounds. See originally crrev.com/497773002 BUG=skia: R=reed@google.com, senorblanco@chromium.org, junov@chromium.org, mtklein@google.com Author: mtklein@chromium.org Review URL: https://codereview.chromium.org/496963003 --- tests/ImageFilterTest.cpp | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'tests') diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp index 214aed950c..f87f99ce98 100644 --- a/tests/ImageFilterTest.cpp +++ b/tests/ImageFilterTest.cpp @@ -421,6 +421,54 @@ DEF_TEST(ImageFilterDrawTiled, reporter) { } } +static void drawSaveLayerPicture(int width, int height, int tileSize, SkBBHFactory* factory, SkBitmap* result) { + + SkMatrix matrix; + matrix.setTranslate(SkIntToScalar(50), 0); + + SkAutoTUnref cf(SkColorFilter::CreateModeFilter(SK_ColorWHITE, SkXfermode::kSrc_Mode)); + SkAutoTUnref cfif(SkColorFilterImageFilter::Create(cf.get())); + SkAutoTUnref imageFilter(SkMatrixImageFilter::Create(matrix, SkPaint::kNone_FilterLevel, cfif.get())); + + SkPaint paint; + paint.setImageFilter(imageFilter.get()); + SkPictureRecorder recorder; + SkRect bounds = SkRect::Make(SkIRect::MakeXYWH(0, 0, 50, 50)); + SkCanvas* recordingCanvas = recorder.beginRecording(width, height, factory, 0); + recordingCanvas->translate(-55, 0); + recordingCanvas->saveLayer(&bounds, &paint); + recordingCanvas->restore(); + SkAutoTUnref picture1(recorder.endRecording()); + + result->allocN32Pixels(width, height); + SkCanvas canvas(*result); + canvas.clear(0); + canvas.clipRect(SkRect::Make(SkIRect::MakeWH(tileSize, tileSize))); + canvas.drawPicture(picture1.get()); +} + +DEF_TEST(ImageFilterDrawMatrixBBH, reporter) { + // Check that matrix filter when drawn tiled with BBH exactly + // matches the same thing drawn without BBH. + // Tests pass by not asserting. + + const int width = 200, height = 200; + const int tileSize = 100; + SkBitmap result1, result2; + SkRTreeFactory factory; + + drawSaveLayerPicture(width, height, tileSize, &factory, &result1); + drawSaveLayerPicture(width, height, tileSize, NULL, &result2); + + for (int y = 0; y < height; y++) { + int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes()); + REPORTER_ASSERT(reporter, !diffs); + if (diffs) { + break; + } + } +} + static void drawBlurredRect(SkCanvas* canvas) { SkAutoTUnref filter(SkBlurImageFilter::Create(SkIntToScalar(8), 0)); SkPaint filterPaint; -- cgit v1.2.3