blob: 65fc42fd5d029bc4c82204eeae4e21cdec8df0c7 [file] [log] [blame]
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/desktop_capture/desktop_region.h"
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000012
13#include <algorithm>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "test/gtest.h"
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000016
17namespace webrtc {
18
19namespace {
20
21int RadmonInt(int max) {
22 return (rand() / 256) % max;
23}
24
25void CompareRegion(const DesktopRegion& region,
Yves Gerey665174f2018-06-19 15:03:05 +020026 const DesktopRect rects[],
27 int rects_size) {
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000028 DesktopRegion::Iterator it(region);
29 for (int i = 0; i < rects_size; ++i) {
30 SCOPED_TRACE(i);
31 ASSERT_FALSE(it.IsAtEnd());
32 EXPECT_TRUE(it.rect().equals(rects[i]))
33 << it.rect().left() << "-" << it.rect().right() << "."
34 << it.rect().top() << "-" << it.rect().bottom() << " "
Yves Gerey665174f2018-06-19 15:03:05 +020035 << rects[i].left() << "-" << rects[i].right() << "." << rects[i].top()
36 << "-" << rects[i].bottom();
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000037 it.Advance();
38 }
39 EXPECT_TRUE(it.IsAtEnd());
40}
41
42} // namespace
43
44// Verify that regions are empty when created.
45TEST(DesktopRegionTest, Empty) {
46 DesktopRegion r;
47 CompareRegion(r, NULL, 0);
48}
49
50// Verify that empty rectangles are ignored.
51TEST(DesktopRegionTest, AddEmpty) {
52 DesktopRegion r;
53 DesktopRect rect = DesktopRect::MakeXYWH(1, 2, 0, 0);
54 r.AddRect(rect);
55 CompareRegion(r, NULL, 0);
56}
57
58// Verify that regions with a single rectangles are handled properly.
59TEST(DesktopRegionTest, SingleRect) {
60 DesktopRegion r;
61 DesktopRect rect = DesktopRect::MakeXYWH(1, 2, 3, 4);
62 r.AddRect(rect);
63 CompareRegion(r, &rect, 1);
64}
65
66// Verify that non-overlapping rectangles are not merged.
67TEST(DesktopRegionTest, NonOverlappingRects) {
68 struct Case {
69 int count;
70 DesktopRect rects[4];
71 } cases[] = {
Yves Gerey665174f2018-06-19 15:03:05 +020072 {1, {DesktopRect::MakeXYWH(10, 10, 10, 10)}},
73 {2,
74 {DesktopRect::MakeXYWH(10, 10, 10, 10),
75 DesktopRect::MakeXYWH(30, 10, 10, 15)}},
76 {2,
77 {DesktopRect::MakeXYWH(10, 10, 10, 10),
78 DesktopRect::MakeXYWH(10, 30, 10, 5)}},
79 {3,
80 {DesktopRect::MakeXYWH(10, 10, 10, 9),
81 DesktopRect::MakeXYWH(30, 10, 15, 10),
82 DesktopRect::MakeXYWH(10, 30, 8, 10)}},
83 {4,
84 {DesktopRect::MakeXYWH(0, 0, 30, 10),
85 DesktopRect::MakeXYWH(40, 0, 10, 30),
86 DesktopRect::MakeXYWH(0, 20, 10, 30),
87 DesktopRect::MakeXYWH(20, 40, 30, 10)}},
88 {4,
89 {DesktopRect::MakeXYWH(0, 0, 10, 100),
90 DesktopRect::MakeXYWH(20, 10, 30, 10),
91 DesktopRect::MakeXYWH(20, 30, 30, 10),
92 DesktopRect::MakeXYWH(20, 50, 30, 10)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000093 };
94
95 for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) {
96 SCOPED_TRACE(i);
97
98 DesktopRegion r;
99
100 for (int j = 0; j < cases[i].count; ++j) {
101 r.AddRect(cases[i].rects[j]);
102 }
103 CompareRegion(r, cases[i].rects, cases[i].count);
104
105 SCOPED_TRACE("Reverse");
106
107 // Try inserting rects in reverse order.
108 r.Clear();
109 for (int j = cases[i].count - 1; j >= 0; --j) {
110 r.AddRect(cases[i].rects[j]);
111 }
112 CompareRegion(r, cases[i].rects, cases[i].count);
113 }
114}
115
116TEST(DesktopRegionTest, TwoRects) {
117 struct Case {
118 DesktopRect input_rect1;
119 DesktopRect input_rect2;
120 int expected_count;
121 DesktopRect expected_rects[3];
122 } cases[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200123 // Touching rectangles that merge into one.
124 {DesktopRect::MakeLTRB(100, 100, 200, 200),
125 DesktopRect::MakeLTRB(0, 100, 100, 200),
126 1,
127 {DesktopRect::MakeLTRB(0, 100, 200, 200)}},
128 {DesktopRect::MakeLTRB(100, 100, 200, 200),
129 DesktopRect::MakeLTRB(100, 0, 200, 100),
130 1,
131 {DesktopRect::MakeLTRB(100, 0, 200, 200)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000132
Yves Gerey665174f2018-06-19 15:03:05 +0200133 // Rectangles touching on the vertical edge.
134 {DesktopRect::MakeLTRB(100, 100, 200, 200),
135 DesktopRect::MakeLTRB(0, 150, 100, 250),
136 3,
137 {DesktopRect::MakeLTRB(100, 100, 200, 150),
138 DesktopRect::MakeLTRB(0, 150, 200, 200),
139 DesktopRect::MakeLTRB(0, 200, 100, 250)}},
140 {DesktopRect::MakeLTRB(100, 100, 200, 200),
141 DesktopRect::MakeLTRB(0, 50, 100, 150),
142 3,
143 {DesktopRect::MakeLTRB(0, 50, 100, 100),
144 DesktopRect::MakeLTRB(0, 100, 200, 150),
145 DesktopRect::MakeLTRB(100, 150, 200, 200)}},
146 {DesktopRect::MakeLTRB(100, 100, 200, 200),
147 DesktopRect::MakeLTRB(0, 120, 100, 180),
148 3,
149 {DesktopRect::MakeLTRB(100, 100, 200, 120),
150 DesktopRect::MakeLTRB(0, 120, 200, 180),
151 DesktopRect::MakeLTRB(100, 180, 200, 200)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000152
Yves Gerey665174f2018-06-19 15:03:05 +0200153 // Rectangles touching on the horizontal edge.
154 {DesktopRect::MakeLTRB(100, 100, 200, 200),
155 DesktopRect::MakeLTRB(150, 0, 250, 100),
156 2,
157 {DesktopRect::MakeLTRB(150, 0, 250, 100),
158 DesktopRect::MakeLTRB(100, 100, 200, 200)}},
159 {DesktopRect::MakeLTRB(100, 100, 200, 200),
160 DesktopRect::MakeLTRB(50, 0, 150, 100),
161 2,
162 {DesktopRect::MakeLTRB(50, 0, 150, 100),
163 DesktopRect::MakeLTRB(100, 100, 200, 200)}},
164 {DesktopRect::MakeLTRB(100, 100, 200, 200),
165 DesktopRect::MakeLTRB(120, 0, 180, 100),
166 2,
167 {DesktopRect::MakeLTRB(120, 0, 180, 100),
168 DesktopRect::MakeLTRB(100, 100, 200, 200)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000169
Yves Gerey665174f2018-06-19 15:03:05 +0200170 // Overlapping rectangles.
171 {DesktopRect::MakeLTRB(100, 100, 200, 200),
172 DesktopRect::MakeLTRB(50, 50, 150, 150),
173 3,
174 {DesktopRect::MakeLTRB(50, 50, 150, 100),
175 DesktopRect::MakeLTRB(50, 100, 200, 150),
176 DesktopRect::MakeLTRB(100, 150, 200, 200)}},
177 {DesktopRect::MakeLTRB(100, 100, 200, 200),
178 DesktopRect::MakeLTRB(150, 50, 250, 150),
179 3,
180 {DesktopRect::MakeLTRB(150, 50, 250, 100),
181 DesktopRect::MakeLTRB(100, 100, 250, 150),
182 DesktopRect::MakeLTRB(100, 150, 200, 200)}},
183 {DesktopRect::MakeLTRB(100, 100, 200, 200),
184 DesktopRect::MakeLTRB(0, 120, 150, 180),
185 3,
186 {DesktopRect::MakeLTRB(100, 100, 200, 120),
187 DesktopRect::MakeLTRB(0, 120, 200, 180),
188 DesktopRect::MakeLTRB(100, 180, 200, 200)}},
189 {DesktopRect::MakeLTRB(100, 100, 200, 200),
190 DesktopRect::MakeLTRB(120, 0, 180, 150),
191 2,
192 {DesktopRect::MakeLTRB(120, 0, 180, 100),
193 DesktopRect::MakeLTRB(100, 100, 200, 200)}},
194 {DesktopRect::MakeLTRB(100, 0, 200, 300),
195 DesktopRect::MakeLTRB(0, 100, 300, 200),
196 3,
197 {DesktopRect::MakeLTRB(100, 0, 200, 100),
198 DesktopRect::MakeLTRB(0, 100, 300, 200),
199 DesktopRect::MakeLTRB(100, 200, 200, 300)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000200
Yves Gerey665174f2018-06-19 15:03:05 +0200201 // One rectangle enclosing another.
202 {DesktopRect::MakeLTRB(100, 100, 200, 200),
203 DesktopRect::MakeLTRB(150, 150, 180, 180),
204 1,
205 {DesktopRect::MakeLTRB(100, 100, 200, 200)}},
206 {DesktopRect::MakeLTRB(100, 100, 200, 200),
207 DesktopRect::MakeLTRB(100, 100, 180, 180),
208 1,
209 {DesktopRect::MakeLTRB(100, 100, 200, 200)}},
210 {DesktopRect::MakeLTRB(100, 100, 200, 200),
211 DesktopRect::MakeLTRB(150, 150, 200, 200),
212 1,
213 {DesktopRect::MakeLTRB(100, 100, 200, 200)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000214 };
215
216 for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) {
217 SCOPED_TRACE(i);
218
219 DesktopRegion r;
220
221 r.AddRect(cases[i].input_rect1);
222 r.AddRect(cases[i].input_rect2);
223 CompareRegion(r, cases[i].expected_rects, cases[i].expected_count);
224
225 SCOPED_TRACE("Reverse");
226
227 // Run the same test with rectangles inserted in reverse order.
228 r.Clear();
229 r.AddRect(cases[i].input_rect2);
230 r.AddRect(cases[i].input_rect1);
231 CompareRegion(r, cases[i].expected_rects, cases[i].expected_count);
232 }
233}
234
235// Verify that DesktopRegion::AddRectToRow() works correctly by creating a row
236// of not overlapping rectangles and insert an overlapping rectangle into the
237// row at different positions. Result is verified by building a map of the
238// region in an array and comparing it with the expected values.
239TEST(DesktopRegionTest, SameRow) {
240 const int kMapWidth = 50;
241 const int kLastRectSizes[] = {3, 27};
242
243 DesktopRegion base_region;
Yves Gerey665174f2018-06-19 15:03:05 +0200244 bool base_map[kMapWidth] = {
245 false,
246 };
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000247
248 base_region.AddRect(DesktopRect::MakeXYWH(5, 0, 5, 1));
249 std::fill_n(base_map + 5, 5, true);
250 base_region.AddRect(DesktopRect::MakeXYWH(15, 0, 5, 1));
251 std::fill_n(base_map + 15, 5, true);
252 base_region.AddRect(DesktopRect::MakeXYWH(25, 0, 5, 1));
253 std::fill_n(base_map + 25, 5, true);
254 base_region.AddRect(DesktopRect::MakeXYWH(35, 0, 5, 1));
255 std::fill_n(base_map + 35, 5, true);
256 base_region.AddRect(DesktopRect::MakeXYWH(45, 0, 5, 1));
257 std::fill_n(base_map + 45, 5, true);
258
259 for (size_t i = 0; i < sizeof(kLastRectSizes) / sizeof(kLastRectSizes[0]);
260 i++) {
261 int last_rect_size = kLastRectSizes[i];
262 for (int x = 0; x < kMapWidth - last_rect_size; x++) {
263 SCOPED_TRACE(x);
264
265 DesktopRegion r = base_region;
Yves Gerey665174f2018-06-19 15:03:05 +0200266 r.AddRect(DesktopRect::MakeXYWH(x, 0, last_rect_size, 1));
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000267
268 bool expected_map[kMapWidth];
269 std::copy(base_map, base_map + kMapWidth, expected_map);
270 std::fill_n(expected_map + x, last_rect_size, true);
271
Yves Gerey665174f2018-06-19 15:03:05 +0200272 bool map[kMapWidth] = {
273 false,
274 };
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000275
276 int pos = -1;
277 for (DesktopRegion::Iterator it(r); !it.IsAtEnd(); it.Advance()) {
278 EXPECT_GT(it.rect().left(), pos);
279 pos = it.rect().right();
280 std::fill_n(map + it.rect().left(), it.rect().width(), true);
281 }
282
283 EXPECT_TRUE(std::equal(map, map + kMapWidth, expected_map));
284 }
285 }
286}
287
288TEST(DesktopRegionTest, ComplexRegions) {
289 struct Case {
290 int input_count;
291 DesktopRect input_rects[4];
292 int expected_count;
293 DesktopRect expected_rects[6];
294 } cases[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200295 {3,
296 {
297 DesktopRect::MakeLTRB(100, 100, 200, 200),
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000298 DesktopRect::MakeLTRB(0, 100, 100, 200),
Yves Gerey665174f2018-06-19 15:03:05 +0200299 DesktopRect::MakeLTRB(310, 110, 320, 120),
300 },
301 2,
302 {DesktopRect::MakeLTRB(0, 100, 200, 200),
303 DesktopRect::MakeLTRB(310, 110, 320, 120)}},
304 {3,
305 {DesktopRect::MakeLTRB(100, 100, 200, 200),
306 DesktopRect::MakeLTRB(50, 50, 150, 150),
307 DesktopRect::MakeLTRB(300, 125, 350, 175)},
308 4,
309 {DesktopRect::MakeLTRB(50, 50, 150, 100),
310 DesktopRect::MakeLTRB(50, 100, 200, 150),
311 DesktopRect::MakeLTRB(300, 125, 350, 175),
312 DesktopRect::MakeLTRB(100, 150, 200, 200)}},
313 {4,
314 {DesktopRect::MakeLTRB(0, 0, 30, 30),
315 DesktopRect::MakeLTRB(10, 10, 40, 40),
316 DesktopRect::MakeLTRB(20, 20, 50, 50),
317 DesktopRect::MakeLTRB(50, 0, 65, 15)},
318 6,
319 {DesktopRect::MakeLTRB(0, 0, 30, 10),
320 DesktopRect::MakeLTRB(50, 0, 65, 15),
321 DesktopRect::MakeLTRB(0, 10, 40, 20),
322 DesktopRect::MakeLTRB(0, 20, 50, 30),
323 DesktopRect::MakeLTRB(10, 30, 50, 40),
324 DesktopRect::MakeLTRB(20, 40, 50, 50)}},
325 {3,
326 {DesktopRect::MakeLTRB(10, 10, 40, 20),
327 DesktopRect::MakeLTRB(10, 30, 40, 40),
328 DesktopRect::MakeLTRB(10, 20, 40, 30)},
329 1,
330 {DesktopRect::MakeLTRB(10, 10, 40, 40)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000331 };
332
333 for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) {
334 SCOPED_TRACE(i);
335
336 DesktopRegion r;
337 r.AddRects(cases[i].input_rects, cases[i].input_count);
338 CompareRegion(r, cases[i].expected_rects, cases[i].expected_count);
339
340 // Try inserting rectangles in reverse order.
341 r.Clear();
342 for (int j = cases[i].input_count - 1; j >= 0; --j) {
343 r.AddRect(cases[i].input_rects[j]);
344 }
345 CompareRegion(r, cases[i].expected_rects, cases[i].expected_count);
346 }
347}
348
349TEST(DesktopRegionTest, Equals) {
350 struct Region {
351 int count;
352 DesktopRect rects[4];
353 int id;
354 } regions[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200355 // Same region with one of the rectangles 1 pixel wider/taller.
356 {2,
357 {DesktopRect::MakeLTRB(0, 100, 200, 200),
358 DesktopRect::MakeLTRB(310, 110, 320, 120)},
359 0},
360 {2,
361 {DesktopRect::MakeLTRB(0, 100, 201, 200),
362 DesktopRect::MakeLTRB(310, 110, 320, 120)},
363 1},
364 {2,
365 {DesktopRect::MakeLTRB(0, 100, 200, 201),
366 DesktopRect::MakeLTRB(310, 110, 320, 120)},
367 2},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000368
Yves Gerey665174f2018-06-19 15:03:05 +0200369 // Same region with one of the rectangles shifted horizontally and
370 // vertically.
371 {4,
372 {DesktopRect::MakeLTRB(0, 0, 30, 30),
373 DesktopRect::MakeLTRB(10, 10, 40, 40),
374 DesktopRect::MakeLTRB(20, 20, 50, 50),
375 DesktopRect::MakeLTRB(50, 0, 65, 15)},
376 3},
377 {4,
378 {DesktopRect::MakeLTRB(0, 0, 30, 30),
379 DesktopRect::MakeLTRB(10, 10, 40, 40),
380 DesktopRect::MakeLTRB(20, 20, 50, 50),
381 DesktopRect::MakeLTRB(50, 1, 65, 16)},
382 4},
383 {4,
384 {DesktopRect::MakeLTRB(0, 0, 30, 30),
385 DesktopRect::MakeLTRB(10, 10, 40, 40),
386 DesktopRect::MakeLTRB(20, 20, 50, 50),
387 DesktopRect::MakeLTRB(51, 0, 66, 15)},
388 5},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000389
Yves Gerey665174f2018-06-19 15:03:05 +0200390 // Same region defined by a different set of rectangles - one of the
391 // rectangle is split horizontally into two.
392 {3,
393 {DesktopRect::MakeLTRB(100, 100, 200, 200),
394 DesktopRect::MakeLTRB(50, 50, 150, 150),
395 DesktopRect::MakeLTRB(300, 125, 350, 175)},
396 6},
397 {4,
398 {DesktopRect::MakeLTRB(100, 100, 200, 200),
399 DesktopRect::MakeLTRB(50, 50, 100, 150),
400 DesktopRect::MakeLTRB(100, 50, 150, 150),
401 DesktopRect::MakeLTRB(300, 125, 350, 175)},
402 6},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000403
Yves Gerey665174f2018-06-19 15:03:05 +0200404 // Rectangle region defined by a set of rectangles that merge into one.
405 {3,
406 {DesktopRect::MakeLTRB(10, 10, 40, 20),
407 DesktopRect::MakeLTRB(10, 30, 40, 40),
408 DesktopRect::MakeLTRB(10, 20, 40, 30)},
409 7},
410 {1, {DesktopRect::MakeLTRB(10, 10, 40, 40)}, 7},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000411 };
412 int kTotalRegions = sizeof(regions) / sizeof(Region);
413
414 for (int i = 0; i < kTotalRegions; ++i) {
415 SCOPED_TRACE(i);
416
417 DesktopRegion r1(regions[i].rects, regions[i].count);
418 for (int j = 0; j < kTotalRegions; ++j) {
419 SCOPED_TRACE(j);
420
421 DesktopRegion r2(regions[j].rects, regions[j].count);
422 EXPECT_EQ(regions[i].id == regions[j].id, r1.Equals(r2));
423 }
424 }
425}
426
427TEST(DesktopRegionTest, Translate) {
428 struct Case {
429 int input_count;
430 DesktopRect input_rects[4];
431 int dx;
432 int dy;
433 int expected_count;
434 DesktopRect expected_rects[5];
435 } cases[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200436 {3,
437 {DesktopRect::MakeLTRB(0, 0, 30, 30),
438 DesktopRect::MakeLTRB(10, 10, 40, 40),
439 DesktopRect::MakeLTRB(20, 20, 50, 50)},
440 3,
441 5,
442 5,
443 {DesktopRect::MakeLTRB(3, 5, 33, 15),
444 DesktopRect::MakeLTRB(3, 15, 43, 25),
445 DesktopRect::MakeLTRB(3, 25, 53, 35),
446 DesktopRect::MakeLTRB(13, 35, 53, 45),
447 DesktopRect::MakeLTRB(23, 45, 53, 55)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000448 };
449
450 for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) {
451 SCOPED_TRACE(i);
452
453 DesktopRegion r(cases[i].input_rects, cases[i].input_count);
454 r.Translate(cases[i].dx, cases[i].dy);
455 CompareRegion(r, cases[i].expected_rects, cases[i].expected_count);
456 }
457}
458
459TEST(DesktopRegionTest, Intersect) {
460 struct Case {
461 int input1_count;
462 DesktopRect input1_rects[4];
463 int input2_count;
464 DesktopRect input2_rects[4];
465 int expected_count;
466 DesktopRect expected_rects[5];
467 } cases[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200468 {1,
469 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
470 1,
471 {DesktopRect::MakeLTRB(50, 50, 150, 150)},
472 1,
473 {DesktopRect::MakeLTRB(50, 50, 100, 100)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000474
Yves Gerey665174f2018-06-19 15:03:05 +0200475 {1,
476 {DesktopRect::MakeLTRB(100, 0, 200, 300)},
477 1,
478 {DesktopRect::MakeLTRB(0, 100, 300, 200)},
479 1,
480 {DesktopRect::MakeLTRB(100, 100, 200, 200)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000481
Yves Gerey665174f2018-06-19 15:03:05 +0200482 {1,
483 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
484 2,
485 {DesktopRect::MakeLTRB(50, 10, 150, 30),
486 DesktopRect::MakeLTRB(50, 30, 160, 50)},
487 1,
488 {DesktopRect::MakeLTRB(50, 10, 100, 50)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000489
Yves Gerey665174f2018-06-19 15:03:05 +0200490 {1,
491 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
492 2,
493 {DesktopRect::MakeLTRB(50, 10, 150, 30),
494 DesktopRect::MakeLTRB(50, 30, 90, 50)},
495 2,
496 {DesktopRect::MakeLTRB(50, 10, 100, 30),
497 DesktopRect::MakeLTRB(50, 30, 90, 50)}},
498 {1,
499 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
500 1,
501 {DesktopRect::MakeLTRB(100, 50, 200, 200)},
502 0,
503 {}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000504 };
505
506 for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) {
507 SCOPED_TRACE(i);
508
509 DesktopRegion r1(cases[i].input1_rects, cases[i].input1_count);
510 DesktopRegion r2(cases[i].input2_rects, cases[i].input2_count);
511
512 DesktopRegion r;
513 r.Intersect(r1, r2);
514
515 CompareRegion(r, cases[i].expected_rects, cases[i].expected_count);
516 }
517}
518
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000519TEST(DesktopRegionTest, Subtract) {
520 struct Case {
521 int input1_count;
522 DesktopRect input1_rects[4];
523 int input2_count;
524 DesktopRect input2_rects[4];
525 int expected_count;
526 DesktopRect expected_rects[5];
527 } cases[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200528 // Subtract one rect from another.
529 {1,
530 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
531 1,
532 {DesktopRect::MakeLTRB(50, 50, 150, 150)},
533 2,
534 {DesktopRect::MakeLTRB(0, 0, 100, 50),
535 DesktopRect::MakeLTRB(0, 50, 50, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000536
Yves Gerey665174f2018-06-19 15:03:05 +0200537 {1,
538 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
539 1,
540 {DesktopRect::MakeLTRB(-50, -50, 50, 50)},
541 2,
542 {DesktopRect::MakeLTRB(50, 0, 100, 50),
543 DesktopRect::MakeLTRB(0, 50, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000544
Yves Gerey665174f2018-06-19 15:03:05 +0200545 {1,
546 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
547 1,
548 {DesktopRect::MakeLTRB(-50, 50, 50, 150)},
549 2,
550 {DesktopRect::MakeLTRB(0, 0, 100, 50),
551 DesktopRect::MakeLTRB(50, 50, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000552
Yves Gerey665174f2018-06-19 15:03:05 +0200553 {1,
554 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
555 1,
556 {DesktopRect::MakeLTRB(50, 50, 150, 70)},
557 3,
558 {DesktopRect::MakeLTRB(0, 0, 100, 50),
559 DesktopRect::MakeLTRB(0, 50, 50, 70),
560 DesktopRect::MakeLTRB(0, 70, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000561
Yves Gerey665174f2018-06-19 15:03:05 +0200562 {1,
563 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
564 1,
565 {DesktopRect::MakeLTRB(50, 50, 70, 70)},
566 4,
567 {DesktopRect::MakeLTRB(0, 0, 100, 50),
568 DesktopRect::MakeLTRB(0, 50, 50, 70),
569 DesktopRect::MakeLTRB(70, 50, 100, 70),
570 DesktopRect::MakeLTRB(0, 70, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000571
Yves Gerey665174f2018-06-19 15:03:05 +0200572 // Empty result.
573 {1,
574 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
575 1,
576 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
577 0,
578 {}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000579
Yves Gerey665174f2018-06-19 15:03:05 +0200580 {1,
581 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
582 1,
583 {DesktopRect::MakeLTRB(-10, -10, 110, 110)},
584 0,
585 {}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000586
Yves Gerey665174f2018-06-19 15:03:05 +0200587 {2,
588 {DesktopRect::MakeLTRB(0, 0, 100, 100),
589 DesktopRect::MakeLTRB(50, 50, 150, 150)},
590 2,
591 {DesktopRect::MakeLTRB(0, 0, 100, 100),
592 DesktopRect::MakeLTRB(50, 50, 150, 150)},
593 0,
594 {}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000595
Yves Gerey665174f2018-06-19 15:03:05 +0200596 // One rect out of disjoint set.
597 {3,
598 {DesktopRect::MakeLTRB(0, 0, 10, 10),
599 DesktopRect::MakeLTRB(20, 20, 30, 30),
600 DesktopRect::MakeLTRB(40, 0, 50, 10)},
601 1,
602 {DesktopRect::MakeLTRB(20, 20, 30, 30)},
603 2,
604 {DesktopRect::MakeLTRB(0, 0, 10, 10),
605 DesktopRect::MakeLTRB(40, 0, 50, 10)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000606
Yves Gerey665174f2018-06-19 15:03:05 +0200607 // Row merging.
608 {3,
609 {DesktopRect::MakeLTRB(0, 0, 100, 50),
610 DesktopRect::MakeLTRB(0, 50, 150, 70),
611 DesktopRect::MakeLTRB(0, 70, 100, 100)},
612 1,
613 {DesktopRect::MakeLTRB(100, 50, 150, 70)},
614 1,
615 {DesktopRect::MakeLTRB(0, 0, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000616
Yves Gerey665174f2018-06-19 15:03:05 +0200617 // No-op subtraction.
618 {1,
619 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
620 1,
621 {DesktopRect::MakeLTRB(100, 0, 200, 100)},
622 1,
623 {DesktopRect::MakeLTRB(0, 0, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000624
Yves Gerey665174f2018-06-19 15:03:05 +0200625 {1,
626 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
627 1,
628 {DesktopRect::MakeLTRB(-100, 0, 0, 100)},
629 1,
630 {DesktopRect::MakeLTRB(0, 0, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000631
Yves Gerey665174f2018-06-19 15:03:05 +0200632 {1,
633 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
634 1,
635 {DesktopRect::MakeLTRB(0, 100, 0, 200)},
636 1,
637 {DesktopRect::MakeLTRB(0, 0, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000638
Yves Gerey665174f2018-06-19 15:03:05 +0200639 {1,
640 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
641 1,
642 {DesktopRect::MakeLTRB(0, -100, 100, 0)},
643 1,
644 {DesktopRect::MakeLTRB(0, 0, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000645 };
646
647 for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) {
648 SCOPED_TRACE(i);
649
650 DesktopRegion r1(cases[i].input1_rects, cases[i].input1_count);
651 DesktopRegion r2(cases[i].input2_rects, cases[i].input2_count);
652
653 r1.Subtract(r2);
654
655 CompareRegion(r1, cases[i].expected_rects, cases[i].expected_count);
656 }
657}
658
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000659// Verify that DesktopRegion::SubtractRows() works correctly by creating a row
660// of not overlapping rectangles and subtracting a set of rectangle. Result
661// is verified by building a map of the region in an array and comparing it with
662// the expected values.
663TEST(DesktopRegionTest, SubtractRectOnSameRow) {
664 const int kMapWidth = 50;
665
666 struct SpanSet {
667 int count;
668 struct Range {
Yves Gerey665174f2018-06-19 15:03:05 +0200669 int start;
670 int end;
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000671 } spans[3];
672 } span_sets[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200673 {1, {{0, 3}}},
674 {1, {{0, 5}}},
675 {1, {{0, 7}}},
676 {1, {{0, 12}}},
677 {2, {{0, 3}, {4, 5}, {6, 16}}},
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000678 };
679
680 DesktopRegion base_region;
Yves Gerey665174f2018-06-19 15:03:05 +0200681 bool base_map[kMapWidth] = {
682 false,
683 };
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000684
685 base_region.AddRect(DesktopRect::MakeXYWH(5, 0, 5, 1));
686 std::fill_n(base_map + 5, 5, true);
687 base_region.AddRect(DesktopRect::MakeXYWH(15, 0, 5, 1));
688 std::fill_n(base_map + 15, 5, true);
689 base_region.AddRect(DesktopRect::MakeXYWH(25, 0, 5, 1));
690 std::fill_n(base_map + 25, 5, true);
691 base_region.AddRect(DesktopRect::MakeXYWH(35, 0, 5, 1));
692 std::fill_n(base_map + 35, 5, true);
693 base_region.AddRect(DesktopRect::MakeXYWH(45, 0, 5, 1));
694 std::fill_n(base_map + 45, 5, true);
695
696 for (size_t i = 0; i < sizeof(span_sets) / sizeof(span_sets[0]); i++) {
697 SCOPED_TRACE(i);
698 SpanSet& span_set = span_sets[i];
699 int span_set_end = span_set.spans[span_set.count - 1].end;
700 for (int x = 0; x < kMapWidth - span_set_end; ++x) {
701 SCOPED_TRACE(x);
702
703 DesktopRegion r = base_region;
704
705 bool expected_map[kMapWidth];
706 std::copy(base_map, base_map + kMapWidth, expected_map);
707
708 DesktopRegion region2;
709 for (int span = 0; span < span_set.count; span++) {
710 std::fill_n(x + expected_map + span_set.spans[span].start,
711 span_set.spans[span].end - span_set.spans[span].start,
712 false);
713 region2.AddRect(DesktopRect::MakeLTRB(x + span_set.spans[span].start, 0,
714 x + span_set.spans[span].end, 1));
715 }
716 r.Subtract(region2);
717
Yves Gerey665174f2018-06-19 15:03:05 +0200718 bool map[kMapWidth] = {
719 false,
720 };
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000721
722 int pos = -1;
723 for (DesktopRegion::Iterator it(r); !it.IsAtEnd(); it.Advance()) {
724 EXPECT_GT(it.rect().left(), pos);
725 pos = it.rect().right();
726 std::fill_n(map + it.rect().left(), it.rect().width(), true);
727 }
728
729 EXPECT_TRUE(std::equal(map, map + kMapWidth, expected_map));
730 }
731 }
732}
733
734// Verify that DesktopRegion::Subtract() works correctly by creating a column of
735// not overlapping rectangles and subtracting a set of rectangle on the same
736// column. Result is verified by building a map of the region in an array and
737// comparing it with the expected values.
738TEST(DesktopRegionTest, SubtractRectOnSameCol) {
739 const int kMapHeight = 50;
740
741 struct SpanSet {
742 int count;
743 struct Range {
Yves Gerey665174f2018-06-19 15:03:05 +0200744 int start;
745 int end;
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000746 } spans[3];
747 } span_sets[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200748 {1, {{0, 3}}},
749 {1, {{0, 5}}},
750 {1, {{0, 7}}},
751 {1, {{0, 12}}},
752 {2, {{0, 3}, {4, 5}, {6, 16}}},
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000753 };
754
755 DesktopRegion base_region;
Yves Gerey665174f2018-06-19 15:03:05 +0200756 bool base_map[kMapHeight] = {
757 false,
758 };
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000759
760 base_region.AddRect(DesktopRect::MakeXYWH(0, 5, 1, 5));
761 std::fill_n(base_map + 5, 5, true);
762 base_region.AddRect(DesktopRect::MakeXYWH(0, 15, 1, 5));
763 std::fill_n(base_map + 15, 5, true);
764 base_region.AddRect(DesktopRect::MakeXYWH(0, 25, 1, 5));
765 std::fill_n(base_map + 25, 5, true);
766 base_region.AddRect(DesktopRect::MakeXYWH(0, 35, 1, 5));
767 std::fill_n(base_map + 35, 5, true);
768 base_region.AddRect(DesktopRect::MakeXYWH(0, 45, 1, 5));
769 std::fill_n(base_map + 45, 5, true);
770
771 for (size_t i = 0; i < sizeof(span_sets) / sizeof(span_sets[0]); i++) {
772 SCOPED_TRACE(i);
773 SpanSet& span_set = span_sets[i];
774 int span_set_end = span_set.spans[span_set.count - 1].end;
775 for (int y = 0; y < kMapHeight - span_set_end; ++y) {
776 SCOPED_TRACE(y);
777
778 DesktopRegion r = base_region;
779
780 bool expected_map[kMapHeight];
781 std::copy(base_map, base_map + kMapHeight, expected_map);
782
783 DesktopRegion region2;
784 for (int span = 0; span < span_set.count; span++) {
785 std::fill_n(y + expected_map + span_set.spans[span].start,
786 span_set.spans[span].end - span_set.spans[span].start,
787 false);
788 region2.AddRect(DesktopRect::MakeLTRB(0, y + span_set.spans[span].start,
789 1, y + span_set.spans[span].end));
790 }
791 r.Subtract(region2);
792
Yves Gerey665174f2018-06-19 15:03:05 +0200793 bool map[kMapHeight] = {
794 false,
795 };
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000796
797 int pos = -1;
798 for (DesktopRegion::Iterator it(r); !it.IsAtEnd(); it.Advance()) {
799 EXPECT_GT(it.rect().top(), pos);
800 pos = it.rect().bottom();
801 std::fill_n(map + it.rect().top(), it.rect().height(), true);
802 }
803
804 for (int j = 0; j < kMapHeight; j++) {
805 EXPECT_EQ(expected_map[j], map[j]) << "j = " << j;
806 }
807 }
808 }
809}
810
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000811TEST(DesktopRegionTest, DISABLED_Performance) {
812 for (int c = 0; c < 1000; ++c) {
813 DesktopRegion r;
814 for (int i = 0; i < 10; ++i) {
Yves Gerey665174f2018-06-19 15:03:05 +0200815 r.AddRect(
816 DesktopRect::MakeXYWH(RadmonInt(1000), RadmonInt(1000), 200, 200));
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000817 }
818
819 for (int i = 0; i < 1000; ++i) {
Yves Gerey665174f2018-06-19 15:03:05 +0200820 r.AddRect(DesktopRect::MakeXYWH(RadmonInt(1000), RadmonInt(1000),
821 5 + RadmonInt(10) * 5,
822 5 + RadmonInt(10) * 5));
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000823 }
824
825 // Iterate over the rectangles.
826 for (DesktopRegion::Iterator it(r); !it.IsAtEnd(); it.Advance()) {
827 }
828 }
829}
830
831} // namespace webrtc