Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 353d694

Browse files
authored
make sure CanvasRecorder updates clip bounds methods (#38325)
1 parent 61e95ba commit 353d694

File tree

3 files changed

+118
-3
lines changed

3 files changed

+118
-3
lines changed

display_list/display_list_builder.cc

+3-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ DisplayListBuilder::DisplayListBuilder(const SkRect& cull_rect,
7474
accumulator_ = std::make_unique<RectBoundsAccumulator>();
7575
}
7676

77-
layer_stack_.emplace_back(SkM44(), SkMatrix::I(), cull_rect);
77+
// isEmpty protects us against NaN as we normalize any empty cull rects
78+
SkRect cull = cull_rect.isEmpty() ? SkRect::MakeEmpty() : cull_rect;
79+
layer_stack_.emplace_back(SkM44(), SkMatrix::I(), cull);
7880
current_layer_ = &layer_stack_.back();
7981
}
8082

display_list/display_list_canvas_recorder.cc

+9-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@ namespace flutter {
2121

2222
DisplayListCanvasRecorder::DisplayListCanvasRecorder(const SkRect& bounds,
2323
bool prepare_rtree)
24-
: SkCanvasVirtualEnforcer(bounds.width(), bounds.height()),
25-
builder_(sk_make_sp<DisplayListBuilder>(bounds, prepare_rtree)) {}
24+
: SkCanvasVirtualEnforcer(0, 0),
25+
builder_(sk_make_sp<DisplayListBuilder>(bounds, prepare_rtree)) {
26+
// isEmpty protects us against NaN as we normalize any empty cull rects
27+
SkIRect cull = bounds.isEmpty() ? SkIRect::MakeEmpty() : bounds.roundOut();
28+
SkCanvasVirtualEnforcer::resetCanvas(cull);
29+
}
2630

2731
sk_sp<DisplayList> DisplayListCanvasRecorder::Build() {
2832
CHECK_DISPOSE(nullptr);
@@ -57,20 +61,23 @@ void DisplayListCanvasRecorder::onClipRect(const SkRect& rect,
5761
CHECK_DISPOSE();
5862
builder_->clipRect(rect, clip_op,
5963
edge_style == ClipEdgeStyle::kSoft_ClipEdgeStyle);
64+
SkCanvasVirtualEnforcer::onClipRect(rect, clip_op, edge_style);
6065
}
6166
void DisplayListCanvasRecorder::onClipRRect(const SkRRect& rrect,
6267
SkClipOp clip_op,
6368
ClipEdgeStyle edge_style) {
6469
CHECK_DISPOSE();
6570
builder_->clipRRect(rrect, clip_op,
6671
edge_style == ClipEdgeStyle::kSoft_ClipEdgeStyle);
72+
SkCanvasVirtualEnforcer::onClipRRect(rrect, clip_op, edge_style);
6773
}
6874
void DisplayListCanvasRecorder::onClipPath(const SkPath& path,
6975
SkClipOp clip_op,
7076
ClipEdgeStyle edge_style) {
7177
CHECK_DISPOSE();
7278
builder_->clipPath(path, clip_op,
7379
edge_style == ClipEdgeStyle::kSoft_ClipEdgeStyle);
80+
SkCanvasVirtualEnforcer::onClipPath(path, clip_op, edge_style);
7481
}
7582

7683
void DisplayListCanvasRecorder::willSave() {

display_list/display_list_unittests.cc

+106
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,112 @@ TEST(DisplayList, CallMethodAfterBuild) {
3838
}
3939
#endif // NDEBUG
4040

41+
TEST(DisplayList, RecorderInitialClipBounds) {
42+
SkRect cull_rect = SkRect::MakeWH(100, 100);
43+
SkIRect clip_bounds = SkIRect::MakeWH(100, 100);
44+
DisplayListCanvasRecorder recorder(cull_rect);
45+
SkCanvas* canvas = &recorder;
46+
ASSERT_EQ(canvas->getDeviceClipBounds(), clip_bounds);
47+
}
48+
49+
TEST(DisplayList, RecorderInitialClipBoundsNaN) {
50+
SkRect cull_rect = SkRect::MakeWH(SK_ScalarNaN, SK_ScalarNaN);
51+
SkIRect clip_bounds = SkIRect::MakeEmpty();
52+
DisplayListCanvasRecorder recorder(cull_rect);
53+
SkCanvas* canvas = &recorder;
54+
ASSERT_EQ(canvas->getDeviceClipBounds(), clip_bounds);
55+
}
56+
57+
TEST(DisplayList, RecorderClipBoundsAfterClipRect) {
58+
SkRect cull_rect = SkRect::MakeWH(100, 100);
59+
SkRect clip_rect = SkRect::MakeLTRB(10, 10, 20, 20);
60+
SkIRect clip_bounds = SkIRect::MakeLTRB(10, 10, 20, 20);
61+
DisplayListCanvasRecorder recorder(cull_rect);
62+
SkCanvas* canvas = &recorder;
63+
canvas->clipRect(clip_rect);
64+
ASSERT_EQ(canvas->getDeviceClipBounds(), clip_bounds);
65+
}
66+
67+
TEST(DisplayList, RecorderClipBoundsAfterClipRRect) {
68+
SkRect cull_rect = SkRect::MakeWH(100, 100);
69+
SkRect clip_rect = SkRect::MakeLTRB(10, 10, 20, 20);
70+
SkRRect clip_rrect = SkRRect::MakeRectXY(clip_rect, 2, 2);
71+
SkIRect clip_bounds = SkIRect::MakeLTRB(10, 10, 20, 20);
72+
DisplayListCanvasRecorder recorder(cull_rect);
73+
SkCanvas* canvas = &recorder;
74+
canvas->clipRRect(clip_rrect);
75+
ASSERT_EQ(canvas->getDeviceClipBounds(), clip_bounds);
76+
}
77+
78+
TEST(DisplayList, RecorderClipBoundsAfterClipPath) {
79+
SkRect cull_rect = SkRect::MakeWH(100, 100);
80+
SkPath clip_path = SkPath().addRect(10, 10, 15, 15).addRect(15, 15, 20, 20);
81+
SkIRect clip_bounds = SkIRect::MakeLTRB(10, 10, 20, 20);
82+
DisplayListCanvasRecorder recorder(cull_rect);
83+
SkCanvas* canvas = &recorder;
84+
canvas->clipPath(clip_path);
85+
ASSERT_EQ(canvas->getDeviceClipBounds(), clip_bounds);
86+
}
87+
88+
TEST(DisplayList, RecorderInitialClipBoundsNonZero) {
89+
SkRect cull_rect = SkRect::MakeLTRB(10, 10, 100, 100);
90+
SkIRect clip_bounds = SkIRect::MakeLTRB(10, 10, 100, 100);
91+
DisplayListCanvasRecorder recorder(cull_rect);
92+
SkCanvas* canvas = &recorder;
93+
ASSERT_EQ(canvas->getDeviceClipBounds(), clip_bounds);
94+
}
95+
96+
TEST(DisplayList, BuilderInitialClipBounds) {
97+
SkRect cull_rect = SkRect::MakeWH(100, 100);
98+
SkRect clip_bounds = SkRect::MakeWH(100, 100);
99+
DisplayListBuilder builder(cull_rect);
100+
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
101+
}
102+
103+
TEST(DisplayList, BuilderInitialClipBoundsNaN) {
104+
SkRect cull_rect = SkRect::MakeWH(SK_ScalarNaN, SK_ScalarNaN);
105+
SkRect clip_bounds = SkRect::MakeEmpty();
106+
DisplayListBuilder builder(cull_rect);
107+
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
108+
}
109+
110+
TEST(DisplayList, BuilderClipBoundsAfterClipRect) {
111+
SkRect cull_rect = SkRect::MakeWH(100, 100);
112+
SkRect clip_rect = SkRect::MakeLTRB(10, 10, 20, 20);
113+
SkRect clip_bounds = SkRect::MakeLTRB(10, 10, 20, 20);
114+
DisplayListBuilder builder(cull_rect);
115+
builder.clipRect(clip_rect, SkClipOp::kIntersect, false);
116+
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
117+
}
118+
119+
TEST(DisplayList, BuilderClipBoundsAfterClipRRect) {
120+
SkRect cull_rect = SkRect::MakeWH(100, 100);
121+
SkRect clip_rect = SkRect::MakeLTRB(10, 10, 20, 20);
122+
SkRRect clip_rrect = SkRRect::MakeRectXY(clip_rect, 2, 2);
123+
SkRect clip_bounds = SkRect::MakeLTRB(10, 10, 20, 20);
124+
DisplayListBuilder builder(cull_rect);
125+
builder.clipRRect(clip_rrect, SkClipOp::kIntersect, false);
126+
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
127+
}
128+
129+
TEST(DisplayList, BuilderClipBoundsAfterClipPath) {
130+
SkRect cull_rect = SkRect::MakeWH(100, 100);
131+
SkPath clip_path = SkPath().addRect(10, 10, 15, 15).addRect(15, 15, 20, 20);
132+
SkRect clip_bounds = SkRect::MakeLTRB(10, 10, 20, 20);
133+
DisplayListCanvasRecorder recorder(cull_rect);
134+
DisplayListBuilder builder(cull_rect);
135+
builder.clipPath(clip_path, SkClipOp::kIntersect, false);
136+
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
137+
}
138+
139+
TEST(DisplayList, BuilderInitialClipBoundsNonZero) {
140+
SkRect cull_rect = SkRect::MakeLTRB(10, 10, 100, 100);
141+
SkRect clip_bounds = SkRect::MakeLTRB(10, 10, 100, 100);
142+
DisplayListCanvasRecorder recorder(cull_rect);
143+
DisplayListBuilder builder(cull_rect);
144+
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
145+
}
146+
41147
TEST(DisplayList, SingleOpSizes) {
42148
for (auto& group : allGroups) {
43149
for (size_t i = 0; i < group.variants.size(); i++) {

0 commit comments

Comments
 (0)