Flutter Engine
 
Loading...
Searching...
No Matches
dl_region_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
6
8#include "gtest/gtest.h"
9
10#include "third_party/skia/include/core/SkRegion.h"
11
12#include <random>
13
14namespace flutter {
15namespace testing {
16
17TEST(DisplayListRegion, EmptyRegion) {
18 DlRegion region;
19 EXPECT_TRUE(region.isEmpty());
20 EXPECT_TRUE(region.getRects().empty());
21}
22
23TEST(DisplayListRegion, SingleRectangle) {
24 DlRegion region({DlIRect::MakeLTRB(10, 10, 50, 50)});
25 auto rects = region.getRects();
26 ASSERT_EQ(rects.size(), 1u);
27 EXPECT_EQ(rects.front(), DlIRect::MakeLTRB(10, 10, 50, 50));
28}
29
30TEST(DisplayListRegion, NonOverlappingRectangles1) {
31 std::vector<DlIRect> rects_in;
32 for (int i = 0; i < 10; ++i) {
33 DlIRect rect = DlIRect::MakeXYWH(50 * i, 50 * i, 50, 50);
34 rects_in.push_back(rect);
35 }
36 DlRegion region(rects_in);
37 auto rects = region.getRects();
38 std::vector<DlIRect> expected{
39 DlIRect::MakeLTRB(0, 0, 50, 50),
40 DlIRect::MakeLTRB(50, 50, 100, 100),
41 DlIRect::MakeLTRB(100, 100, 150, 150),
42 DlIRect::MakeLTRB(150, 150, 200, 200),
43 DlIRect::MakeLTRB(200, 200, 250, 250),
44 DlIRect::MakeLTRB(250, 250, 300, 300),
45 DlIRect::MakeLTRB(300, 300, 350, 350),
46 DlIRect::MakeLTRB(350, 350, 400, 400),
47 DlIRect::MakeLTRB(400, 400, 450, 450),
48 DlIRect::MakeLTRB(450, 450, 500, 500),
49 };
50 EXPECT_EQ(rects, expected);
51}
52
53TEST(DisplayListRegion, NonOverlappingRectangles2) {
54 DlRegion region({
55 DlIRect::MakeXYWH(5, 5, 10, 10),
56 DlIRect::MakeXYWH(25, 5, 10, 10),
57 DlIRect::MakeXYWH(5, 25, 10, 10),
58 DlIRect::MakeXYWH(25, 25, 10, 10),
59 });
60 auto rects = region.getRects();
61 std::vector<DlIRect> expected{
62 DlIRect::MakeXYWH(5, 5, 10, 10),
63 DlIRect::MakeXYWH(25, 5, 10, 10),
64 DlIRect::MakeXYWH(5, 25, 10, 10),
65 DlIRect::MakeXYWH(25, 25, 10, 10),
66 };
67 EXPECT_EQ(rects, expected);
68}
69
70TEST(DisplayListRegion, NonOverlappingRectangles3) {
71 DlRegion region({
72 DlIRect::MakeXYWH(0, 0, 10, 10),
73 DlIRect::MakeXYWH(-11, -11, 10, 10),
74 DlIRect::MakeXYWH(11, 11, 10, 10),
75 DlIRect::MakeXYWH(-11, 0, 10, 10),
76 DlIRect::MakeXYWH(0, 11, 10, 10),
77 DlIRect::MakeXYWH(0, -11, 10, 10),
78 DlIRect::MakeXYWH(11, 0, 10, 10),
79 DlIRect::MakeXYWH(11, -11, 10, 10),
80 DlIRect::MakeXYWH(-11, 11, 10, 10),
81 });
82 auto rects = region.getRects();
83 std::vector<DlIRect> expected{
84 DlIRect::MakeXYWH(-11, -11, 10, 10), //
85 DlIRect::MakeXYWH(0, -11, 10, 10), //
86 DlIRect::MakeXYWH(11, -11, 10, 10), //
87 DlIRect::MakeXYWH(-11, 0, 10, 10), //
88 DlIRect::MakeXYWH(0, 0, 10, 10), //
89 DlIRect::MakeXYWH(11, 0, 10, 10), //
90 DlIRect::MakeXYWH(-11, 11, 10, 10), //
91 DlIRect::MakeXYWH(0, 11, 10, 10), //
92 DlIRect::MakeXYWH(11, 11, 10, 10),
93 };
94 EXPECT_EQ(rects, expected);
95}
96
97TEST(DisplayListRegion, MergeTouchingRectangles) {
98 DlRegion region({
99 DlIRect::MakeXYWH(0, 0, 10, 10),
100 DlIRect::MakeXYWH(-10, -10, 10, 10),
101 DlIRect::MakeXYWH(10, 10, 10, 10),
102 DlIRect::MakeXYWH(-10, 0, 10, 10),
103 DlIRect::MakeXYWH(0, 10, 10, 10),
104 DlIRect::MakeXYWH(0, -10, 10, 10),
105 DlIRect::MakeXYWH(10, 0, 10, 10),
106 DlIRect::MakeXYWH(10, -10, 10, 10),
107 DlIRect::MakeXYWH(-10, 10, 10, 10),
108 });
109
110 auto rects = region.getRects();
111 std::vector<DlIRect> expected{
112 DlIRect::MakeXYWH(-10, -10, 30, 30),
113 };
114 EXPECT_EQ(rects, expected);
115}
116
117TEST(DisplayListRegion, OverlappingRectangles) {
118 std::vector<DlIRect> rects_in;
119 for (int i = 0; i < 10; ++i) {
120 DlIRect rect = DlIRect::MakeXYWH(10 * i, 10 * i, 50, 50);
121 rects_in.push_back(rect);
122 }
123 DlRegion region(rects_in);
124 auto rects = region.getRects();
125 std::vector<DlIRect> expected{
126 DlIRect::MakeLTRB(0, 0, 50, 10),
127 DlIRect::MakeLTRB(0, 10, 60, 20),
128 DlIRect::MakeLTRB(0, 20, 70, 30),
129 DlIRect::MakeLTRB(0, 30, 80, 40),
130 DlIRect::MakeLTRB(0, 40, 90, 50),
131 DlIRect::MakeLTRB(10, 50, 100, 60),
132 DlIRect::MakeLTRB(20, 60, 110, 70),
133 DlIRect::MakeLTRB(30, 70, 120, 80),
134 DlIRect::MakeLTRB(40, 80, 130, 90),
135 DlIRect::MakeLTRB(50, 90, 140, 100),
136 DlIRect::MakeLTRB(60, 100, 140, 110),
137 DlIRect::MakeLTRB(70, 110, 140, 120),
138 DlIRect::MakeLTRB(80, 120, 140, 130),
139 DlIRect::MakeLTRB(90, 130, 140, 140),
140 };
141
142 EXPECT_EQ(rects, expected);
143}
144
145TEST(DisplayListRegion, Deband) {
146 DlRegion region({
147 DlIRect::MakeXYWH(0, 0, 50, 50),
148 DlIRect::MakeXYWH(60, 0, 20, 20),
149 DlIRect::MakeXYWH(90, 0, 50, 50),
150 });
151
152 auto rects_with_deband = region.getRects(true);
153 std::vector<DlIRect> expected{
154 DlIRect::MakeXYWH(60, 0, 20, 20),
155 DlIRect::MakeXYWH(0, 0, 50, 50),
156 DlIRect::MakeXYWH(90, 0, 50, 50),
157 };
158 EXPECT_EQ(rects_with_deband, expected);
159
160 auto rects_without_deband = region.getRects(false);
161 std::vector<DlIRect> expected_without_deband{
162 DlIRect::MakeXYWH(0, 0, 50, 20), //
163 DlIRect::MakeXYWH(60, 0, 20, 20), //
164 DlIRect::MakeXYWH(90, 0, 50, 20), //
165 DlIRect::MakeXYWH(0, 20, 50, 30), //
166 DlIRect::MakeXYWH(90, 20, 50, 30),
167 };
168 EXPECT_EQ(rects_without_deband, expected_without_deband);
169}
170
171TEST(DisplayListRegion, Intersects1) {
172 DlRegion region1({
173 DlIRect::MakeXYWH(0, 0, 20, 20),
174 DlIRect::MakeXYWH(20, 20, 20, 20),
175 });
176 DlRegion region2({
177 DlIRect::MakeXYWH(20, 0, 20, 20),
178 DlIRect::MakeXYWH(0, 20, 20, 20),
179 });
180 EXPECT_FALSE(region1.intersects(region2));
181 EXPECT_FALSE(region2.intersects(region1));
182
183 EXPECT_TRUE(region1.intersects(region2.bounds()));
184 EXPECT_TRUE(region2.intersects(region1.bounds()));
185
186 EXPECT_TRUE(region1.intersects(DlIRect::MakeXYWH(0, 0, 20, 20)));
187 EXPECT_FALSE(region1.intersects(DlIRect::MakeXYWH(20, 0, 20, 20)));
188
189 EXPECT_TRUE(region1.intersects(
190 DlRegion(std::vector<DlIRect>{DlIRect::MakeXYWH(0, 0, 20, 20)})));
191 EXPECT_FALSE(region1.intersects(
192 DlRegion(std::vector<DlIRect>{DlIRect::MakeXYWH(20, 0, 20, 20)})));
193
194 EXPECT_FALSE(region1.intersects(DlIRect::MakeXYWH(-1, -1, 1, 1)));
195 EXPECT_TRUE(region1.intersects(DlIRect::MakeXYWH(0, 0, 1, 1)));
196
197 EXPECT_FALSE(region1.intersects(DlIRect::MakeXYWH(40, 40, 1, 1)));
198 EXPECT_TRUE(region1.intersects(DlIRect::MakeXYWH(39, 39, 1, 1)));
199}
200
201TEST(DisplayListRegion, Intersects2) {
202 DlRegion region1({
203 DlIRect::MakeXYWH(-10, -10, 20, 20),
204 DlIRect::MakeXYWH(-30, -30, 20, 20),
205 });
206 DlRegion region2({
207 DlIRect::MakeXYWH(20, 20, 5, 5),
208 DlIRect::MakeXYWH(0, 0, 20, 20),
209 });
210 EXPECT_TRUE(region1.intersects(region2));
211 EXPECT_TRUE(region2.intersects(region1));
212}
213
214TEST(DisplayListRegion, Intersection1) {
215 DlRegion region1({
216 DlIRect::MakeXYWH(0, 0, 20, 20),
217 DlIRect::MakeXYWH(20, 20, 20, 20),
218 });
219 DlRegion region2({
220 DlIRect::MakeXYWH(20, 0, 20, 20),
221 DlIRect::MakeXYWH(0, 20, 20, 20),
222 });
223 DlRegion i = DlRegion::MakeIntersection(region1, region2);
224 EXPECT_EQ(i.bounds(), DlIRect());
225 EXPECT_TRUE(i.isEmpty());
226 auto rects = i.getRects();
227 EXPECT_TRUE(rects.empty());
228}
229
230TEST(DisplayListRegion, Intersection2) {
231 DlRegion region1({
232 DlIRect::MakeXYWH(0, 0, 20, 20),
233 DlIRect::MakeXYWH(20, 20, 20, 20),
234 });
235 DlRegion region2({
236 DlIRect::MakeXYWH(0, 0, 20, 20),
237 DlIRect::MakeXYWH(20, 20, 20, 20),
238 });
239 DlRegion i = DlRegion::MakeIntersection(region1, region2);
240 EXPECT_EQ(i.bounds(), DlIRect::MakeXYWH(0, 0, 40, 40));
241 auto rects = i.getRects();
242 std::vector<DlIRect> expected{
243 DlIRect::MakeXYWH(0, 0, 20, 20),
244 DlIRect::MakeXYWH(20, 20, 20, 20),
245 };
246 EXPECT_EQ(rects, expected);
247}
248
249TEST(DisplayListRegion, Intersection3) {
250 DlRegion region1({
251 DlIRect::MakeXYWH(0, 0, 20, 20),
252 });
253 DlRegion region2({
254 DlIRect::MakeXYWH(-10, -10, 20, 20),
255 DlIRect::MakeXYWH(10, 10, 20, 20),
256 });
257 DlRegion i = DlRegion::MakeIntersection(region1, region2);
258 EXPECT_EQ(i.bounds(), DlIRect::MakeXYWH(0, 0, 20, 20));
259 auto rects = i.getRects();
260 std::vector<DlIRect> expected{
261 DlIRect::MakeXYWH(0, 0, 10, 10),
262 DlIRect::MakeXYWH(10, 10, 10, 10),
263 };
264 EXPECT_EQ(rects, expected);
265}
266
267TEST(DisplayListRegion, Union1) {
268 DlRegion region1({
269 DlIRect::MakeXYWH(0, 0, 20, 20),
270 DlIRect::MakeXYWH(20, 20, 20, 20),
271 });
272 DlRegion region2({
273 DlIRect::MakeXYWH(20, 0, 20, 20),
274 DlIRect::MakeXYWH(0, 20, 20, 20),
275 });
276 DlRegion u = DlRegion::MakeUnion(region1, region2);
277 EXPECT_EQ(u.bounds(), DlIRect::MakeXYWH(0, 0, 40, 40));
278 EXPECT_TRUE(u.isSimple());
279 auto rects = u.getRects();
280 std::vector<DlIRect> expected{
281 DlIRect::MakeXYWH(0, 0, 40, 40), //
282 };
283 EXPECT_EQ(rects, expected);
284}
285
286TEST(DisplayListRegion, Union2) {
287 DlRegion region1({
288 DlIRect::MakeXYWH(0, 0, 20, 20),
289 DlIRect::MakeXYWH(21, 21, 20, 20),
290 });
291 DlRegion region2({
292 DlIRect::MakeXYWH(21, 0, 20, 20),
293 DlIRect::MakeXYWH(0, 21, 20, 20),
294 });
295 DlRegion u = DlRegion::MakeUnion(region1, region2);
296 EXPECT_EQ(u.bounds(), DlIRect::MakeXYWH(0, 0, 41, 41));
297 auto rects = u.getRects();
298 std::vector<DlIRect> expected{
299 DlIRect::MakeXYWH(0, 0, 20, 20),
300 DlIRect::MakeXYWH(21, 0, 20, 20),
301 DlIRect::MakeXYWH(0, 21, 20, 20),
302 DlIRect::MakeXYWH(21, 21, 20, 20),
303 };
304 EXPECT_EQ(rects, expected);
305}
306
307TEST(DisplayListRegion, Union3) {
308 DlRegion region1({
309 DlIRect::MakeXYWH(-10, -10, 20, 20),
310 });
311 DlRegion region2({
312 DlIRect::MakeXYWH(0, 0, 20, 20),
313 });
314 DlRegion u = DlRegion::MakeUnion(region1, region2);
315 EXPECT_EQ(u.bounds(), DlIRect::MakeXYWH(-10, -10, 30, 30));
316 auto rects = u.getRects();
317 std::vector<DlIRect> expected{
318 DlIRect::MakeXYWH(-10, -10, 20, 10),
319 DlIRect::MakeXYWH(-10, 0, 30, 10),
320 DlIRect::MakeXYWH(0, 10, 20, 10),
321 };
322 EXPECT_EQ(rects, expected);
323}
324
325TEST(DisplayListRegion, UnionEmpty) {
326 {
327 DlRegion region1(std::vector<DlIRect>{});
328 DlRegion region2(std::vector<DlIRect>{});
329 DlRegion u = DlRegion::MakeUnion(region1, region2);
330 EXPECT_EQ(u.bounds(), DlIRect());
331 EXPECT_TRUE(u.isEmpty());
332 auto rects = u.getRects();
333 EXPECT_TRUE(rects.empty());
334 }
335 {
336 DlRegion region1(std::vector<DlIRect>{});
337 DlRegion region2({
338 DlIRect::MakeXYWH(0, 0, 20, 20),
339 });
340 DlRegion u = DlRegion::MakeUnion(region1, region2);
341 EXPECT_EQ(u.bounds(), DlIRect::MakeXYWH(0, 0, 20, 20));
342 auto rects = u.getRects();
343 std::vector<DlIRect> expected{
344 DlIRect::MakeXYWH(0, 0, 20, 20),
345 };
346 }
347 {
348 DlRegion region1({
349 DlIRect::MakeXYWH(0, 0, 20, 20),
350 });
351 DlRegion region2(std::vector<DlIRect>{});
352 DlRegion u = DlRegion::MakeUnion(region1, region2);
353 EXPECT_EQ(u.bounds(), DlIRect::MakeXYWH(0, 0, 20, 20));
354 auto rects = u.getRects();
355 std::vector<DlIRect> expected{
356 DlIRect::MakeXYWH(0, 0, 20, 20),
357 };
358 }
359}
360
361void CheckEquality(const DlRegion& dl_region, const SkRegion& sk_region) {
362 EXPECT_EQ(dl_region.bounds(), ToDlIRect(sk_region.getBounds()));
363
364 // Do not deband the rectangles - identical to SkRegion::Iterator
365 auto rects = dl_region.getRects(false);
366
367 std::vector<DlIRect> skia_rects;
368
369 auto iterator = SkRegion::Iterator(sk_region);
370 while (!iterator.done()) {
371 skia_rects.push_back(ToDlIRect(iterator.rect()));
372 iterator.next();
373 }
374
375 EXPECT_EQ(rects, skia_rects);
376}
377
378TEST(DisplayListRegion, TestAgainstSkRegion) {
379 struct Settings {
380 int max_size;
381 };
382 std::vector<Settings> all_settings{{100}, {400}, {800}};
383
384 std::vector<size_t> iterations{1, 10, 100, 1000};
385
386 for (const auto& settings : all_settings) {
387 for (const auto iterations_1 : iterations) {
388 for (const auto iterations_2 : iterations) {
389 std::random_device d;
390 std::seed_seq seed{::testing::UnitTest::GetInstance()->random_seed()};
391 std::mt19937 rng(seed);
392
393 SkRegion sk_region1;
394 SkRegion sk_region2;
395
396 std::uniform_int_distribution pos(0, 4000);
397 std::uniform_int_distribution size(1, settings.max_size);
398
399 std::vector<DlIRect> rects_in1;
400 std::vector<DlIRect> rects_in2;
401
402 for (size_t i = 0; i < iterations_1; ++i) {
403 DlIRect rect =
404 DlIRect::MakeXYWH(pos(rng), pos(rng), size(rng), size(rng));
405 rects_in1.push_back(rect);
406 }
407
408 for (size_t i = 0; i < iterations_2; ++i) {
409 DlIRect rect =
410 DlIRect::MakeXYWH(pos(rng), pos(rng), size(rng), size(rng));
411 rects_in2.push_back(rect);
412 }
413
414 DlRegion region1(rects_in1);
415 sk_region1.setRects(ToSkIRects(rects_in1.data()), rects_in1.size());
416 CheckEquality(region1, sk_region1);
417
418 DlRegion region2(rects_in2);
419 sk_region2.setRects(ToSkIRects(rects_in2.data()), rects_in2.size());
420 CheckEquality(region2, sk_region2);
421
422 auto intersects_1 = region1.intersects(region2);
423 auto intersects_2 = region2.intersects(region1);
424 auto sk_intesects = sk_region1.intersects(sk_region2);
425 EXPECT_EQ(intersects_1, intersects_2);
426 EXPECT_EQ(intersects_1, sk_intesects);
427
428 {
429 auto rects = region2.getRects(true);
430 for (const auto& r : rects) {
431 EXPECT_EQ(region1.intersects(r),
432 sk_region1.intersects(ToSkIRect(r)));
433 }
434 }
435
436 DlRegion dl_union = DlRegion::MakeUnion(region1, region2);
437 SkRegion sk_union(sk_region1);
438 sk_union.op(sk_region2, SkRegion::kUnion_Op);
439 CheckEquality(dl_union, sk_union);
440
441 DlRegion dl_intersection = DlRegion::MakeIntersection(region1, region2);
442 SkRegion sk_intersection(sk_region1);
443 sk_intersection.op(sk_region2, SkRegion::kIntersect_Op);
444 CheckEquality(dl_intersection, sk_intersection);
445 }
446 }
447 }
448}
449
450} // namespace testing
451} // namespace flutter
static DlRegion MakeIntersection(const DlRegion &a, const DlRegion &b)
Definition dl_region.cc:496
const DlIRect & bounds() const
Definition dl_region.h:53
bool isEmpty() const
Returns true if region is empty (contains no rectangles).
Definition dl_region.h:62
std::vector< DlIRect > getRects(bool deband=true) const
Definition dl_region.cc:560
static DlRegion MakeUnion(const DlRegion &a, const DlRegion &b)
Definition dl_region.cc:405
bool intersects(const DlIRect &rect) const
Returns whether this region intersects with a rectangle.
Definition dl_region.cc:615
auto & d
Definition main.cc:28
void CheckEquality(const DlRegion &dl_region, const SkRegion &sk_region)
TEST(NativeAssetsManagerTest, NoAvailableAssets)
const SkIRect & ToSkIRect(const DlIRect &rect)
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
const DlIRect & ToDlIRect(const SkIRect &rect)
const SkIRect * ToSkIRects(const DlIRect *rects)
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129