From f9bf65cfad8433a01a2c59571a2aac2af3ca829e Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 10 Jul 2023 12:11:08 -0700 Subject: [PATCH] Handle nested display list clips in Impeller dispatcher (#43442) (#43469) CP issue: https://github.com/flutter/flutter/issues/130149 Fixes https://github.com/flutter/flutter/issues/130084 If a display list is drawn into another display list and the child display list establishes a small clip, subsequent drawing operations are discarded when really they should not be. The test is expected to render both a blue and a red square; before the fix it renders only the blue square since the red square is incorrectly clipped out. See also https://github.com/dnfield/flutter_svg/issues/938 --- impeller/display_list/display_list_dispatcher.cc | 4 ++++ impeller/display_list/display_list_unittests.cc | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index 88f9bc593c30a..95558f3f23004 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -1252,6 +1252,10 @@ void DisplayListDispatcher::drawDisplayList( Matrix saved_initial_matrix = initial_matrix_; int restore_count = canvas_.GetSaveCount(); + // The display list may alter the clip, which must be restored to the current + // clip at the end of playback. + canvas_.Save(); + // Establish a new baseline for interpreting the new DL. // Matrix and clip are left untouched, the current // transform is saved as the new base matrix, and paint diff --git a/impeller/display_list/display_list_unittests.cc b/impeller/display_list/display_list_unittests.cc index 5164897af68fa..9364279fc6597 100644 --- a/impeller/display_list/display_list_unittests.cc +++ b/impeller/display_list/display_list_unittests.cc @@ -45,6 +45,21 @@ flutter::DlColor toColor(const float* components) { using DisplayListTest = DisplayListPlayground; INSTANTIATE_PLAYGROUND_SUITE(DisplayListTest); +TEST_P(DisplayListTest, DrawPictureWithAClip) { + flutter::DisplayListBuilder sub_builder; + sub_builder.ClipRect(SkRect::MakeXYWH(0, 0, 24, 24), + flutter::DlCanvas::ClipOp::kIntersect, + /*is_aa=*/false); + sub_builder.DrawPaint(flutter::DlPaint(flutter::DlColor::kBlue())); + + auto display_list = sub_builder.Build(); + flutter::DisplayListBuilder builder; + builder.DrawDisplayList(display_list); + builder.DrawRect(SkRect::MakeXYWH(30, 30, 24, 24), + flutter::DlPaint(flutter::DlColor::kRed())); + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + TEST_P(DisplayListTest, CanDrawRect) { flutter::DisplayListBuilder builder; builder.DrawRect(SkRect::MakeXYWH(10, 10, 100, 100),