diff --git a/engine/src/flutter/display_list/display_list_unittests.cc b/engine/src/flutter/display_list/display_list_unittests.cc index b234b049f53..98f97b51c9c 100644 --- a/engine/src/flutter/display_list/display_list_unittests.cc +++ b/engine/src/flutter/display_list/display_list_unittests.cc @@ -5939,5 +5939,66 @@ TEST_F(DisplayListTest, DisplayListDetectsRuntimeEffect) { } } +namespace { +typedef void BuilderTransformer(DisplayListBuilder& builder); + +sk_sp TestSaveLayerWithMatrix(BuilderTransformer transform) { + const DlScalar xoffset = 50; + const DlScalar yoffset = 50; + const DlScalar sigma = 10.0; + + DisplayListBuilder builder; + + const auto blur_filter = + DlImageFilter::MakeBlur(sigma, sigma, DlTileMode::kClamp); + + builder.Translate(xoffset, yoffset); + transform(builder); + + const DlPaint paint; + builder.DrawImage(kTestImage1, DlPoint(100.0, 100.0), + DlImageSampling::kNearestNeighbor, &paint); + + DlPaint save_paint; + save_paint.setBlendMode(DlBlendMode::kSrc); + builder.SaveLayer(std::nullopt, &save_paint, blur_filter.get()); + builder.Restore(); + + return builder.Build(); +} +} // namespace + +TEST_F(DisplayListTest, SaveLayerWithValidScaleDoesNotCrash) { + EXPECT_NE(TestSaveLayerWithMatrix([](DisplayListBuilder& builder) { + builder.Scale(0.7, 0.7); + EXPECT_TRUE(builder.GetMatrix().IsInvertible()); + }), + nullptr); +} + +TEST_F(DisplayListTest, SaveLayerWithZeroXScaleDoesNotCrash) { + EXPECT_NE(TestSaveLayerWithMatrix([](DisplayListBuilder& builder) { + builder.Scale(0.0, 0.7); + EXPECT_FALSE(builder.GetMatrix().IsInvertible()); + }), + nullptr); +} + +TEST_F(DisplayListTest, SaveLayerWithZeroYScaleDoesNotCrash) { + EXPECT_NE(TestSaveLayerWithMatrix([](DisplayListBuilder& builder) { + builder.Scale(0.7, 0.0); + EXPECT_FALSE(builder.GetMatrix().IsInvertible()); + }), + nullptr); +} + +TEST_F(DisplayListTest, SaveLayerWithLinearSkewDoesNotCrash) { + EXPECT_NE(TestSaveLayerWithMatrix([](DisplayListBuilder& builder) { + builder.Skew(1.0f, 1.0f); + EXPECT_FALSE(builder.GetMatrix().IsInvertible()); + }), + nullptr); +} + } // namespace testing } // namespace flutter diff --git a/engine/src/flutter/display_list/dl_builder.cc b/engine/src/flutter/display_list/dl_builder.cc index a5a70aea621..0ac5796dd5f 100644 --- a/engine/src/flutter/display_list/dl_builder.cc +++ b/engine/src/flutter/display_list/dl_builder.cc @@ -461,11 +461,7 @@ void DisplayListBuilder::saveLayer(const DlRect& bounds, // with its full bounds and the right op_index so that it doesn't // get culled during rendering. if (will_be_unbounded) { - // Accumulate should always return true here because if the - // clip was empty then that would have been caught up above - // when we tested the PaintResult. - [[maybe_unused]] bool unclipped = AccumulateUnbounded(); - FML_DCHECK(unclipped); + AccumulateUnbounded(); } // Accumulate information for the SaveInfo we are about to push onto the