Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions flow/layers/color_filter_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ void ColorFilterLayer::Paint(PaintContext& context) const {
}
}

// If the color filter modifies transparent black, then when it's applied to
// a saveLayer, that layer will extend beyond the paint bounds provided in the
// SaveLayerRec (which defines the bounds of the content within the layer, not
// the extent of the layer during the restore()). ColorFilterLayer must clip
// before the saveLayer in these cases to ensure it doesn't go beyond its
// reported paint_bounds().
if (filter_ && filter_->modifies_transparent_black()) {
mutator.clipRect(paint_bounds(), /*is_aa=*/false);
}

// Now apply the color filter and then try rendering children either from
// cache or directly.
mutator.applyColorFilter(paint_bounds(), filter_);
Expand Down
43 changes: 43 additions & 0 deletions flow/layers/color_filter_layer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -447,5 +447,48 @@ TEST_F(ColorFilterLayerTest, OpacityInheritance) {
EXPECT_TRUE(DisplayListsEQ_Verbose(expected_builder.Build(), display_list()));
}

TEST_F(ColorFilterLayerTest, ModifiesTransparentBlack) {
// In Skia, saveLayers with a color filter that modifies transparent black
// will fill all pixels within the clip, going beyond the user bounds hint.
// ColorFilterLayer must insert a clipRect before saveLayer to ensure it
// doesn't draw beyond its reported bounds.
// clang-format off
float matrix[20] = {
-1, 0, 0, 0, 1,
0,-1, 0, 0, 1,
0, 0,-1, 0, 1,
0, 0, 0,-1, 1,
};
// clang-format on
auto layer_filter = DlMatrixColorFilter(matrix);
ASSERT_TRUE(layer_filter.modifies_transparent_black());

const SkPath child_path = SkPath().addRect(SkRect::MakeWH(5.0f, 5.0f));
auto mock_layer = std::make_shared<MockLayer>(child_path);
auto color_filter_layer = std::make_shared<ColorFilterLayer>(
std::make_shared<DlMatrixColorFilter>(matrix));
color_filter_layer->Add(mock_layer);

color_filter_layer->Preroll(preroll_context());

DisplayListBuilder expected_builder;
/* ColorFilterLayer::Paint() */ {
DlPaint dl_paint;
dl_paint.setColorFilter(&layer_filter);
expected_builder.Save();
expected_builder.ClipRect(child_path.getBounds(),
DlCanvas::ClipOp::kIntersect, /*is_aa=*/false);
expected_builder.SaveLayer(&child_path.getBounds(), &dl_paint);
/* MockLayer::Paint() */ {
expected_builder.DrawPath(child_path, DlPaint(0xFF000000));
}
expected_builder.Restore();
expected_builder.Restore();
}

color_filter_layer->Paint(display_list_paint_context());
EXPECT_TRUE(DisplayListsEQ_Verbose(expected_builder.Build(), display_list()));
}

} // namespace testing
} // namespace flutter
2 changes: 0 additions & 2 deletions tools/gn
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,6 @@ def to_gn_args(args):
gn_args['skia_use_wuffs'] = True
gn_args['skia_use_expat'] = args.target_os == 'android'
gn_args['skia_use_fontconfig'] = args.enable_fontconfig
gn_args['skia_use_legacy_layer_bounds'
] = True # Temporary: See skbug.com/12083, skbug.com/12303.
gn_args['skia_use_legacy_colorfilter_imagefilter'] = True # Temporary staging
gn_args['skia_use_icu'] = True
gn_args['is_official_build'] = True # Disable Skia test utilities.
Expand Down