Flutter Impeller
canvas_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "flutter/testing/testing.h"
6 #include "impeller/aiks/canvas.h"
8 
9 // TODO(zanderso): https://github.com/flutter/flutter/issues/127701
10 // NOLINTBEGIN(bugprone-unchecked-optional-access)
11 
12 namespace impeller {
13 namespace testing {
14 
15 using AiksCanvasTest = ::testing::Test;
16 
17 TEST(AiksCanvasTest, EmptyCullRect) {
18  Canvas canvas;
19 
20  ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
21 }
22 
23 TEST(AiksCanvasTest, InitialCullRect) {
24  Rect initial_cull(0, 0, 10, 10);
25 
26  Canvas canvas(initial_cull);
27 
28  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
29  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), initial_cull);
30 }
31 
32 TEST(AiksCanvasTest, TranslatedCullRect) {
33  Rect initial_cull(5, 5, 10, 10);
34  Rect translated_cull(0, 0, 10, 10);
35 
36  Canvas canvas(initial_cull);
37  canvas.Translate(Vector3(5, 5, 0));
38 
39  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
40  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), translated_cull);
41 }
42 
43 TEST(AiksCanvasTest, ScaledCullRect) {
44  Rect initial_cull(5, 5, 10, 10);
45  Rect scaled_cull(10, 10, 20, 20);
46 
47  Canvas canvas(initial_cull);
48  canvas.Scale(Vector2(0.5, 0.5));
49 
50  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
51  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), scaled_cull);
52 }
53 
54 TEST(AiksCanvasTest, RectClipIntersectAgainstEmptyCullRect) {
55  Rect rect_clip(5, 5, 10, 10);
56 
57  Canvas canvas;
59 
60  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
61  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), rect_clip);
62 }
63 
64 TEST(AiksCanvasTest, RectClipDiffAgainstEmptyCullRect) {
65  Rect rect_clip(5, 5, 10, 10);
66 
67  Canvas canvas;
69 
70  ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
71 }
72 
73 TEST(AiksCanvasTest, RectClipIntersectAgainstCullRect) {
74  Rect initial_cull(0, 0, 10, 10);
75  Rect rect_clip(5, 5, 10, 10);
76  Rect result_cull(5, 5, 5, 5);
77 
78  Canvas canvas(initial_cull);
80 
81  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
82  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
83 }
84 
85 TEST(AiksCanvasTest, RectClipDiffAgainstNonCoveredCullRect) {
86  Rect initial_cull(0, 0, 10, 10);
87  Rect rect_clip(5, 5, 10, 10);
88  Rect result_cull(0, 0, 10, 10);
89 
90  Canvas canvas(initial_cull);
92 
93  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
94  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
95 }
96 
97 TEST(AiksCanvasTest, RectClipDiffAboveCullRect) {
98  Rect initial_cull(5, 5, 10, 10);
99  Rect rect_clip(0, 0, 20, 4);
100  Rect result_cull(5, 5, 10, 10);
101 
102  Canvas canvas(initial_cull);
103  canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
104 
105  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
106  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
107 }
108 
109 TEST(AiksCanvasTest, RectClipDiffBelowCullRect) {
110  Rect initial_cull(5, 5, 10, 10);
111  Rect rect_clip(0, 16, 20, 4);
112  Rect result_cull(5, 5, 10, 10);
113 
114  Canvas canvas(initial_cull);
115  canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
116 
117  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
118  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
119 }
120 
121 TEST(AiksCanvasTest, RectClipDiffLeftOfCullRect) {
122  Rect initial_cull(5, 5, 10, 10);
123  Rect rect_clip(0, 0, 4, 20);
124  Rect result_cull(5, 5, 10, 10);
125 
126  Canvas canvas(initial_cull);
127  canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
128 
129  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
130  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
131 }
132 
133 TEST(AiksCanvasTest, RectClipDiffRightOfCullRect) {
134  Rect initial_cull(5, 5, 10, 10);
135  Rect rect_clip(16, 0, 4, 20);
136  Rect result_cull(5, 5, 10, 10);
137 
138  Canvas canvas(initial_cull);
139  canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
140 
141  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
142  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
143 }
144 
145 TEST(AiksCanvasTest, RectClipDiffAgainstVCoveredCullRect) {
146  Rect initial_cull(0, 0, 10, 10);
147  Rect rect_clip(5, 0, 10, 10);
148  Rect result_cull(0, 0, 5, 10);
149 
150  Canvas canvas(initial_cull);
151  canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
152 
153  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
154  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
155 }
156 
157 TEST(AiksCanvasTest, RectClipDiffAgainstHCoveredCullRect) {
158  Rect initial_cull(0, 0, 10, 10);
159  Rect rect_clip(0, 5, 10, 10);
160  Rect result_cull(0, 0, 10, 5);
161 
162  Canvas canvas(initial_cull);
163  canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
164 
165  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
166  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
167 }
168 
169 TEST(AiksCanvasTest, RRectClipIntersectAgainstEmptyCullRect) {
170  Rect rect_clip(5, 5, 10, 10);
171 
172  Canvas canvas;
173  canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kIntersect);
174 
175  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
176  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), rect_clip);
177 }
178 
179 TEST(AiksCanvasTest, RRectClipDiffAgainstEmptyCullRect) {
180  Rect rect_clip(5, 5, 10, 10);
181 
182  Canvas canvas;
183  canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
184 
185  ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
186 }
187 
188 TEST(AiksCanvasTest, RRectClipIntersectAgainstCullRect) {
189  Rect initial_cull(0, 0, 10, 10);
190  Rect rect_clip(5, 5, 10, 10);
191  Rect result_cull(5, 5, 5, 5);
192 
193  Canvas canvas(initial_cull);
194  canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kIntersect);
195 
196  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
197  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
198 }
199 
200 TEST(AiksCanvasTest, RRectClipDiffAgainstNonCoveredCullRect) {
201  Rect initial_cull(0, 0, 10, 10);
202  Rect rect_clip(5, 5, 10, 10);
203  Rect result_cull(0, 0, 10, 10);
204 
205  Canvas canvas(initial_cull);
206  canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
207 
208  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
209  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
210 }
211 
212 TEST(AiksCanvasTest, RRectClipDiffAgainstVPartiallyCoveredCullRect) {
213  Rect initial_cull(0, 0, 10, 10);
214  Rect rect_clip(5, 0, 10, 10);
215  Rect result_cull(0, 0, 6, 10);
216 
217  Canvas canvas(initial_cull);
218  canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
219 
220  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
221  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
222 }
223 
224 TEST(AiksCanvasTest, RRectClipDiffAgainstVFullyCoveredCullRect) {
225  Rect initial_cull(0, 0, 10, 10);
226  Rect rect_clip(5, -2, 10, 14);
227  Rect result_cull(0, 0, 5, 10);
228 
229  Canvas canvas(initial_cull);
230  canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
231 
232  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
233  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
234 }
235 
236 TEST(AiksCanvasTest, RRectClipDiffAgainstHPartiallyCoveredCullRect) {
237  Rect initial_cull(0, 0, 10, 10);
238  Rect rect_clip(0, 5, 10, 10);
239  Rect result_cull(0, 0, 10, 6);
240 
241  Canvas canvas(initial_cull);
242  canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
243 
244  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
245  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
246 }
247 
248 TEST(AiksCanvasTest, RRectClipDiffAgainstHFullyCoveredCullRect) {
249  Rect initial_cull(0, 0, 10, 10);
250  Rect rect_clip(-2, 5, 14, 10);
251  Rect result_cull(0, 0, 10, 5);
252 
253  Canvas canvas(initial_cull);
254  canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
255 
256  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
257  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
258 }
259 
260 TEST(AiksCanvasTest, PathClipIntersectAgainstEmptyCullRect) {
261  PathBuilder builder;
262  builder.AddRect({5, 5, 1, 1});
263  builder.AddRect({5, 14, 1, 1});
264  builder.AddRect({14, 5, 1, 1});
265  builder.AddRect({14, 14, 1, 1});
266  Path path = builder.TakePath();
267  Rect rect_clip(5, 5, 10, 10);
268 
269  Canvas canvas;
271 
272  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
273  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), rect_clip);
274 }
275 
276 TEST(AiksCanvasTest, PathClipDiffAgainstEmptyCullRect) {
277  PathBuilder builder;
278  builder.AddRect({5, 5, 1, 1});
279  builder.AddRect({5, 14, 1, 1});
280  builder.AddRect({14, 5, 1, 1});
281  builder.AddRect({14, 14, 1, 1});
282  Path path = builder.TakePath();
283 
284  Canvas canvas;
286 
287  ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
288 }
289 
290 TEST(AiksCanvasTest, PathClipIntersectAgainstCullRect) {
291  Rect initial_cull(0, 0, 10, 10);
292  PathBuilder builder;
293  builder.AddRect({5, 5, 1, 1});
294  builder.AddRect({5, 14, 1, 1});
295  builder.AddRect({14, 5, 1, 1});
296  builder.AddRect({14, 14, 1, 1});
297  Path path = builder.TakePath();
298  Rect result_cull(5, 5, 5, 5);
299 
300  Canvas canvas(initial_cull);
302 
303  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
304  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
305 }
306 
307 TEST(AiksCanvasTest, PathClipDiffAgainstNonCoveredCullRect) {
308  Rect initial_cull(0, 0, 10, 10);
309  PathBuilder builder;
310  builder.AddRect({5, 5, 1, 1});
311  builder.AddRect({5, 14, 1, 1});
312  builder.AddRect({14, 5, 1, 1});
313  builder.AddRect({14, 14, 1, 1});
314  Path path = builder.TakePath();
315  Rect result_cull(0, 0, 10, 10);
316 
317  Canvas canvas(initial_cull);
319 
320  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
321  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
322 }
323 
324 TEST(AiksCanvasTest, PathClipDiffAgainstFullyCoveredCullRect) {
325  Rect initial_cull(5, 5, 10, 10);
326  PathBuilder builder;
327  builder.AddRect({0, 0, 100, 100});
328  Path path = builder.TakePath();
329  // Diff clip of Paths is ignored due to complexity
330  Rect result_cull(5, 5, 10, 10);
331 
332  Canvas canvas(initial_cull);
334 
335  ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
336  ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
337 }
338 
339 } // namespace testing
340 } // namespace impeller
341 
342 // NOLINTEND(bugprone-unchecked-optional-access)
impeller::Entity::ClipOperation::kIntersect
@ kIntersect
impeller::Entity::ClipOperation::kDifference
@ kDifference
impeller::Canvas
Definition: canvas.h:50
impeller::PathBuilder
Definition: path_builder.h:13
impeller::testing::TEST
TEST(AiksCanvasTest, EmptyCullRect)
Definition: canvas_unittests.cc:17
impeller::Vector2
Point Vector2
Definition: point.h:310
impeller::PathBuilder::AddRect
PathBuilder & AddRect(Rect rect)
Definition: path_builder.cc:181
path_builder.h
impeller::Canvas::Scale
void Scale(const Vector2 &scale)
Definition: canvas.cc:145
impeller::Path
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Definition: path.h:54
canvas.h
impeller::PathBuilder::TakePath
Path TakePath(FillType fill=FillType::kNonZero)
Definition: path_builder.cc:21
impeller::testing::AiksCanvasTest
::testing::Test AiksCanvasTest
Definition: canvas_unittests.cc:15
impeller::Canvas::ClipRRect
void ClipRRect(const Rect &rect, Scalar corner_radius, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
Definition: canvas.cc:315
impeller::Canvas::GetCurrentLocalCullingBounds
const std::optional< Rect > GetCurrentLocalCullingBounds() const
Definition: canvas.cc:132
impeller::Canvas::ClipRect
void ClipRect(const Rect &rect, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
Definition: canvas.cc:294
impeller
Definition: aiks_context.cc:10
impeller::TRect< Scalar >
impeller::Vector3
Definition: vector.h:17
impeller::Canvas::Translate
void Translate(const Vector3 &offset)
Definition: canvas.cc:141
impeller::Canvas::ClipPath
void ClipPath(const Path &path, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
Definition: canvas.cc:284