Loading libs/hwui/SkiaCanvas.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -199,11 +199,11 @@ static inline SkCanvas::SaveLayerFlags layerFlags(SaveFlags::Flags flags) { int SkiaCanvas::saveLayer(float left, float top, float right, float bottom, const SkPaint* paint, SaveFlags::Flags flags) { const SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom); const SkCanvas::SaveLayerRec rec(&bounds, paint, layerFlags(flags)); //always save matrix and clip to match the behaviour of Skia and HWUI pipelines and to ensure //android state tracking behavior matches that of the Skia API (partial save is not supported) const SkCanvas::SaveLayerRec rec(&bounds, paint, layerFlags(flags | SaveFlags::MatrixClip)); int count = mCanvas->saveLayer(rec); recordPartialSave(flags); return count; return mCanvas->saveLayer(rec); } int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom, Loading libs/hwui/tests/unit/RenderNodeDrawableTests.cpp +53 −0 Original line number Diff line number Diff line Loading @@ -167,6 +167,59 @@ TEST(RenderNodeDrawable, composeOnLayer) rootNode->setLayerSurface(sk_sp<SkSurface>()); } namespace { static SkRect getRecorderClipBounds(const SkiaRecordingCanvas& recorder) { SkRect clipBounds; recorder.getClipBounds(&clipBounds); return clipBounds; } static SkMatrix getRecorderMatrix(const SkiaRecordingCanvas& recorder) { SkMatrix matrix; recorder.getMatrix(&matrix); return matrix; } } TEST(RenderNodeDrawable, saveLayerClipAndMatrixRestore) { auto surface = SkSurface::MakeRasterN32Premul(400, 800); SkCanvas& canvas = *surface->getCanvas(); canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE); auto rootNode = TestUtils::createSkiaNode(0, 0, 400, 800, [](RenderProperties& props, SkiaRecordingCanvas& recorder) { SkPaint layerPaint; ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 800), getRecorderClipBounds(recorder)); EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity()); //note we don't pass SaveFlags::MatrixClip, but matrix and clip will be saved recorder.saveLayer(0, 0, 400, 400, &layerPaint, SaveFlags::ClipToLayer); ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 400), getRecorderClipBounds(recorder)); EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity()); recorder.clipRect(50, 50, 350, 350, SkClipOp::kIntersect); ASSERT_EQ(SkRect::MakeLTRB(50, 50, 350, 350), getRecorderClipBounds(recorder)); recorder.translate(300.0f, 400.0f); EXPECT_EQ(SkMatrix::MakeTrans(300.0f, 400.0f), getRecorderMatrix(recorder)); recorder.restore(); ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 800), getRecorderClipBounds(recorder)); EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity()); SkPaint paint; paint.setAntiAlias(true); paint.setColor(SK_ColorGREEN); recorder.drawRect(0.0f, 400.0f, 400.0f, 800.0f, paint); }); RenderNodeDrawable drawable(rootNode.get(), &canvas, true); canvas.drawDrawable(&drawable); ASSERT_EQ(SK_ColorGREEN, TestUtils::getColor(surface, 200, 600)); } namespace { class ContextFactory : public IContextFactory { public: Loading Loading
libs/hwui/SkiaCanvas.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -199,11 +199,11 @@ static inline SkCanvas::SaveLayerFlags layerFlags(SaveFlags::Flags flags) { int SkiaCanvas::saveLayer(float left, float top, float right, float bottom, const SkPaint* paint, SaveFlags::Flags flags) { const SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom); const SkCanvas::SaveLayerRec rec(&bounds, paint, layerFlags(flags)); //always save matrix and clip to match the behaviour of Skia and HWUI pipelines and to ensure //android state tracking behavior matches that of the Skia API (partial save is not supported) const SkCanvas::SaveLayerRec rec(&bounds, paint, layerFlags(flags | SaveFlags::MatrixClip)); int count = mCanvas->saveLayer(rec); recordPartialSave(flags); return count; return mCanvas->saveLayer(rec); } int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom, Loading
libs/hwui/tests/unit/RenderNodeDrawableTests.cpp +53 −0 Original line number Diff line number Diff line Loading @@ -167,6 +167,59 @@ TEST(RenderNodeDrawable, composeOnLayer) rootNode->setLayerSurface(sk_sp<SkSurface>()); } namespace { static SkRect getRecorderClipBounds(const SkiaRecordingCanvas& recorder) { SkRect clipBounds; recorder.getClipBounds(&clipBounds); return clipBounds; } static SkMatrix getRecorderMatrix(const SkiaRecordingCanvas& recorder) { SkMatrix matrix; recorder.getMatrix(&matrix); return matrix; } } TEST(RenderNodeDrawable, saveLayerClipAndMatrixRestore) { auto surface = SkSurface::MakeRasterN32Premul(400, 800); SkCanvas& canvas = *surface->getCanvas(); canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE); auto rootNode = TestUtils::createSkiaNode(0, 0, 400, 800, [](RenderProperties& props, SkiaRecordingCanvas& recorder) { SkPaint layerPaint; ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 800), getRecorderClipBounds(recorder)); EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity()); //note we don't pass SaveFlags::MatrixClip, but matrix and clip will be saved recorder.saveLayer(0, 0, 400, 400, &layerPaint, SaveFlags::ClipToLayer); ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 400), getRecorderClipBounds(recorder)); EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity()); recorder.clipRect(50, 50, 350, 350, SkClipOp::kIntersect); ASSERT_EQ(SkRect::MakeLTRB(50, 50, 350, 350), getRecorderClipBounds(recorder)); recorder.translate(300.0f, 400.0f); EXPECT_EQ(SkMatrix::MakeTrans(300.0f, 400.0f), getRecorderMatrix(recorder)); recorder.restore(); ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 800), getRecorderClipBounds(recorder)); EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity()); SkPaint paint; paint.setAntiAlias(true); paint.setColor(SK_ColorGREEN); recorder.drawRect(0.0f, 400.0f, 400.0f, 800.0f, paint); }); RenderNodeDrawable drawable(rootNode.get(), &canvas, true); canvas.drawDrawable(&drawable); ASSERT_EQ(SK_ColorGREEN, TestUtils::getColor(surface, 200, 600)); } namespace { class ContextFactory : public IContextFactory { public: Loading