| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "flutter/flow/layers/clip_path_layer.h" |
| #include "flutter/flow/layers/clip_rect_layer.h" |
| #include "flutter/flow/layers/clip_rrect_layer.h" |
| #include "flutter/flow/testing/layer_test.h" |
| #include "flutter/flow/testing/mock_layer.h" |
| #include "flutter/fml/macros.h" |
| #include "flutter/testing/mock_canvas.h" |
| |
| namespace flutter { |
| namespace testing { |
| |
| using CheckerBoardLayerTest = LayerTest; |
| |
| using ClipOp = DlCanvas::ClipOp; |
| |
| #ifndef NDEBUG |
| TEST_F(CheckerBoardLayerTest, ClipRectSaveLayerCheckBoard) { |
| const SkMatrix initial_matrix = SkMatrix::Translate(0.5f, 1.0f); |
| const SkRect child_bounds = SkRect::MakeXYWH(1.0, 2.0, 2.0, 2.0); |
| const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0); |
| const SkPath child_path = SkPath().addRect(child_bounds); |
| const DlPaint child_paint = DlPaint(DlColor::kYellow()); |
| auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint); |
| auto layer = std::make_shared<ClipRectLayer>(layer_bounds, |
| Clip::kAntiAliasWithSaveLayer); |
| layer->Add(mock_layer); |
| |
| preroll_context()->state_stack.set_preroll_delegate(initial_matrix); |
| layer->Preroll(preroll_context()); |
| |
| // Untouched |
| EXPECT_EQ(preroll_context()->state_stack.device_cull_rect(), kGiantRect); |
| EXPECT_TRUE(preroll_context()->state_stack.is_empty()); |
| |
| EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); |
| EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds()); |
| EXPECT_EQ(layer->child_paint_bounds(), child_bounds); |
| EXPECT_TRUE(mock_layer->needs_painting(paint_context())); |
| EXPECT_TRUE(layer->needs_painting(paint_context())); |
| EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds); |
| EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); |
| EXPECT_EQ(mock_layer->parent_mutators(), |
| std::vector({Mutator(layer_bounds)})); |
| |
| layer->Paint(display_list_paint_context()); |
| { |
| DisplayListBuilder expected_builder; |
| /* (ClipRect)layer::Paint */ { |
| expected_builder.Save(); |
| { |
| expected_builder.ClipRect(layer_bounds, DlCanvas::ClipOp::kIntersect, |
| true); |
| expected_builder.SaveLayer(&child_bounds); |
| { |
| /* mock_layer::Paint */ { |
| expected_builder.DrawPath(child_path, child_paint); |
| } |
| } |
| expected_builder.Restore(); |
| } |
| expected_builder.Restore(); |
| } |
| EXPECT_TRUE( |
| DisplayListsEQ_Verbose(display_list(), expected_builder.Build())); |
| } |
| |
| reset_display_list(); |
| layer->Paint(checkerboard_context()); |
| { |
| DisplayListBuilder expected_builder; |
| /* (ClipRect)layer::Paint */ { |
| expected_builder.Save(); |
| { |
| expected_builder.ClipRect(layer_bounds, DlCanvas::ClipOp::kIntersect, |
| true); |
| expected_builder.SaveLayer(&child_bounds); |
| { |
| /* mock_layer::Paint */ { |
| expected_builder.DrawPath(child_path, child_paint); |
| } |
| expected_builder.DrawRect(child_path.getBounds(), |
| checkerboard_paint()); |
| } |
| expected_builder.Restore(); |
| } |
| expected_builder.Restore(); |
| } |
| EXPECT_TRUE( |
| DisplayListsEQ_Verbose(display_list(), expected_builder.Build())); |
| } |
| } |
| |
| TEST_F(CheckerBoardLayerTest, ClipPathSaveLayerCheckBoard) { |
| const SkMatrix initial_matrix = SkMatrix::Translate(0.5f, 1.0f); |
| const SkRect child_bounds = SkRect::MakeXYWH(1.0, 2.0, 2.0, 2.0); |
| const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0); |
| const SkPath child_path = SkPath().addRect(child_bounds); |
| const SkPath layer_path = |
| SkPath().addRect(layer_bounds).addRect(layer_bounds); |
| const DlPaint child_paint = DlPaint(DlColor::kYellow()); |
| const DlPaint clip_paint; |
| auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint); |
| auto layer = std::make_shared<ClipPathLayer>(layer_path, |
| Clip::kAntiAliasWithSaveLayer); |
| layer->Add(mock_layer); |
| |
| preroll_context()->state_stack.set_preroll_delegate(initial_matrix); |
| layer->Preroll(preroll_context()); |
| |
| // Untouched |
| EXPECT_EQ(preroll_context()->state_stack.device_cull_rect(), kGiantRect); |
| EXPECT_TRUE(preroll_context()->state_stack.is_empty()); |
| |
| EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); |
| EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds()); |
| EXPECT_TRUE(mock_layer->needs_painting(paint_context())); |
| EXPECT_TRUE(layer->needs_painting(paint_context())); |
| EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds); |
| EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); |
| EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_path)})); |
| |
| layer->Paint(display_list_paint_context()); |
| { |
| DisplayListBuilder expected_builder; |
| /* (ClipRect)layer::Paint */ { |
| expected_builder.Save(); |
| { |
| expected_builder.ClipPath(layer_path, DlCanvas::ClipOp::kIntersect, |
| true); |
| expected_builder.SaveLayer(&child_bounds); |
| { |
| /* mock_layer::Paint */ { |
| expected_builder.DrawPath(child_path, child_paint); |
| } |
| } |
| expected_builder.Restore(); |
| } |
| expected_builder.Restore(); |
| } |
| EXPECT_TRUE( |
| DisplayListsEQ_Verbose(display_list(), expected_builder.Build())); |
| } |
| |
| reset_display_list(); |
| layer->Paint(checkerboard_context()); |
| { |
| DisplayListBuilder expected_builder; |
| /* (ClipRect)layer::Paint */ { |
| expected_builder.Save(); |
| { |
| expected_builder.ClipPath(layer_path, DlCanvas::ClipOp::kIntersect, |
| true); |
| expected_builder.SaveLayer(&child_bounds); |
| { |
| /* mock_layer::Paint */ { |
| expected_builder.DrawPath(child_path, child_paint); |
| } |
| expected_builder.DrawRect(child_path.getBounds(), |
| checkerboard_paint()); |
| } |
| expected_builder.Restore(); |
| } |
| expected_builder.Restore(); |
| } |
| EXPECT_TRUE( |
| DisplayListsEQ_Verbose(display_list(), expected_builder.Build())); |
| } |
| } |
| |
| TEST_F(CheckerBoardLayerTest, ClipRRectSaveLayerCheckBoard) { |
| const SkMatrix initial_matrix = SkMatrix::Translate(0.5f, 1.0f); |
| const SkRect child_bounds = SkRect::MakeXYWH(1.0, 2.0, 2.0, 2.0); |
| const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0); |
| const SkPath child_path = SkPath().addRect(child_bounds); |
| const SkRRect layer_rrect = SkRRect::MakeRectXY(layer_bounds, .1, .1); |
| const DlPaint child_paint = DlPaint(DlColor::kYellow()); |
| const DlPaint clip_paint; |
| auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint); |
| auto layer = std::make_shared<ClipRRectLayer>(layer_rrect, |
| Clip::kAntiAliasWithSaveLayer); |
| layer->Add(mock_layer); |
| |
| preroll_context()->state_stack.set_preroll_delegate(initial_matrix); |
| layer->Preroll(preroll_context()); |
| |
| // Untouched |
| EXPECT_EQ(preroll_context()->state_stack.device_cull_rect(), kGiantRect); |
| EXPECT_TRUE(preroll_context()->state_stack.is_empty()); |
| |
| EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); |
| EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds()); |
| EXPECT_TRUE(mock_layer->needs_painting(paint_context())); |
| EXPECT_TRUE(layer->needs_painting(paint_context())); |
| EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds); |
| EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); |
| EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_rrect)})); |
| |
| layer->Paint(display_list_paint_context()); |
| { |
| DisplayListBuilder expected_builder; |
| /* (ClipRect)layer::Paint */ { |
| expected_builder.Save(); |
| { |
| expected_builder.ClipRRect(layer_rrect, DlCanvas::ClipOp::kIntersect, |
| true); |
| expected_builder.SaveLayer(&child_bounds); |
| { |
| /* mock_layer::Paint */ { |
| expected_builder.DrawPath(child_path, child_paint); |
| } |
| } |
| expected_builder.Restore(); |
| } |
| expected_builder.Restore(); |
| } |
| EXPECT_TRUE( |
| DisplayListsEQ_Verbose(display_list(), expected_builder.Build())); |
| } |
| |
| reset_display_list(); |
| layer->Paint(checkerboard_context()); |
| { |
| DisplayListBuilder expected_builder; |
| /* (ClipRect)layer::Paint */ { |
| expected_builder.Save(); |
| { |
| expected_builder.ClipRRect(layer_rrect, DlCanvas::ClipOp::kIntersect, |
| true); |
| expected_builder.SaveLayer(&child_bounds); |
| { |
| /* mock_layer::Paint */ { |
| expected_builder.DrawPath(child_path, child_paint); |
| } |
| expected_builder.DrawRect(child_path.getBounds(), |
| checkerboard_paint()); |
| } |
| expected_builder.Restore(); |
| } |
| expected_builder.Restore(); |
| } |
| EXPECT_TRUE( |
| DisplayListsEQ_Verbose(display_list(), expected_builder.Build())); |
| } |
| } |
| |
| #endif |
| } // namespace testing |
| } // namespace flutter |