blob: 39982929a7ba1a4026ebca70fcd5da24d689b1e4 [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
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <stdlib.h>
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000014#include <algorithm>
Yves Gerey3e707812018-11-28 16:47:49 +010015#include <cstdint>
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000016
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "test/gtest.h"
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000018
19namespace webrtc {
20
21namespace {
22
23int RadmonInt(int max) {
24 return (rand() / 256) % max;
25}
26
27void CompareRegion(const DesktopRegion& region,
Yves Gerey665174f2018-06-19 15:03:05 +020028 const DesktopRect rects[],
29 int rects_size) {
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000030 DesktopRegion::Iterator it(region);
31 for (int i = 0; i < rects_size; ++i) {
32 SCOPED_TRACE(i);
33 ASSERT_FALSE(it.IsAtEnd());
34 EXPECT_TRUE(it.rect().equals(rects[i]))
35 << it.rect().left() << "-" << it.rect().right() << "."
36 << it.rect().top() << "-" << it.rect().bottom() << " "
Yves Gerey665174f2018-06-19 15:03:05 +020037 << rects[i].left() << "-" << rects[i].right() << "." << rects[i].top()
38 << "-" << rects[i].bottom();
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000039 it.Advance();
40 }
41 EXPECT_TRUE(it.IsAtEnd());
42}
43
44} // namespace
45
46// Verify that regions are empty when created.
47TEST(DesktopRegionTest, Empty) {
48 DesktopRegion r;
49 CompareRegion(r, NULL, 0);
50}
51
52// Verify that empty rectangles are ignored.
53TEST(DesktopRegionTest, AddEmpty) {
54 DesktopRegion r;
55 DesktopRect rect = DesktopRect::MakeXYWH(1, 2, 0, 0);
56 r.AddRect(rect);
57 CompareRegion(r, NULL, 0);
58}
59
60// Verify that regions with a single rectangles are handled properly.
61TEST(DesktopRegionTest, SingleRect) {
62 DesktopRegion r;
63 DesktopRect rect = DesktopRect::MakeXYWH(1, 2, 3, 4);
64 r.AddRect(rect);
65 CompareRegion(r, &rect, 1);
66}
67
68// Verify that non-overlapping rectangles are not merged.
69TEST(DesktopRegionTest, NonOverlappingRects) {
70 struct Case {
71 int count;
72 DesktopRect rects[4];
73 } cases[] = {
Yves Gerey665174f2018-06-19 15:03:05 +020074 {1, {DesktopRect::MakeXYWH(10, 10, 10, 10)}},
75 {2,
76 {DesktopRect::MakeXYWH(10, 10, 10, 10),
77 DesktopRect::MakeXYWH(30, 10, 10, 15)}},
78 {2,
79 {DesktopRect::MakeXYWH(10, 10, 10, 10),
80 DesktopRect::MakeXYWH(10, 30, 10, 5)}},
81 {3,
82 {DesktopRect::MakeXYWH(10, 10, 10, 9),
83 DesktopRect::MakeXYWH(30, 10, 15, 10),
84 DesktopRect::MakeXYWH(10, 30, 8, 10)}},
85 {4,
86 {DesktopRect::MakeXYWH(0, 0, 30, 10),
87 DesktopRect::MakeXYWH(40, 0, 10, 30),
88 DesktopRect::MakeXYWH(0, 20, 10, 30),
89 DesktopRect::MakeXYWH(20, 40, 30, 10)}},
90 {4,
91 {DesktopRect::MakeXYWH(0, 0, 10, 100),
92 DesktopRect::MakeXYWH(20, 10, 30, 10),
93 DesktopRect::MakeXYWH(20, 30, 30, 10),
94 DesktopRect::MakeXYWH(20, 50, 30, 10)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000095 };
96
97 for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) {
98 SCOPED_TRACE(i);
99
100 DesktopRegion r;
101
102 for (int j = 0; j < cases[i].count; ++j) {
103 r.AddRect(cases[i].rects[j]);
104 }
105 CompareRegion(r, cases[i].rects, cases[i].count);
106
107 SCOPED_TRACE("Reverse");
108
109 // Try inserting rects in reverse order.
110 r.Clear();
111 for (int j = cases[i].count - 1; j >= 0; --j) {
112 r.AddRect(cases[i].rects[j]);
113 }
114 CompareRegion(r, cases[i].rects, cases[i].count);
115 }
116}
117
118TEST(DesktopRegionTest, TwoRects) {
119 struct Case {
120 DesktopRect input_rect1;
121 DesktopRect input_rect2;
122 int expected_count;
123 DesktopRect expected_rects[3];
124 } cases[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200125 // Touching rectangles that merge into one.
126 {DesktopRect::MakeLTRB(100, 100, 200, 200),
127 DesktopRect::MakeLTRB(0, 100, 100, 200),
128 1,
129 {DesktopRect::MakeLTRB(0, 100, 200, 200)}},
130 {DesktopRect::MakeLTRB(100, 100, 200, 200),
131 DesktopRect::MakeLTRB(100, 0, 200, 100),
132 1,
133 {DesktopRect::MakeLTRB(100, 0, 200, 200)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000134
Yves Gerey665174f2018-06-19 15:03:05 +0200135 // Rectangles touching on the vertical edge.
136 {DesktopRect::MakeLTRB(100, 100, 200, 200),
137 DesktopRect::MakeLTRB(0, 150, 100, 250),
138 3,
139 {DesktopRect::MakeLTRB(100, 100, 200, 150),
140 DesktopRect::MakeLTRB(0, 150, 200, 200),
141 DesktopRect::MakeLTRB(0, 200, 100, 250)}},
142 {DesktopRect::MakeLTRB(100, 100, 200, 200),
143 DesktopRect::MakeLTRB(0, 50, 100, 150),
144 3,
145 {DesktopRect::MakeLTRB(0, 50, 100, 100),
146 DesktopRect::MakeLTRB(0, 100, 200, 150),
147 DesktopRect::MakeLTRB(100, 150, 200, 200)}},
148 {DesktopRect::MakeLTRB(100, 100, 200, 200),
149 DesktopRect::MakeLTRB(0, 120, 100, 180),
150 3,
151 {DesktopRect::MakeLTRB(100, 100, 200, 120),
152 DesktopRect::MakeLTRB(0, 120, 200, 180),
153 DesktopRect::MakeLTRB(100, 180, 200, 200)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000154
Yves Gerey665174f2018-06-19 15:03:05 +0200155 // Rectangles touching on the horizontal edge.
156 {DesktopRect::MakeLTRB(100, 100, 200, 200),
157 DesktopRect::MakeLTRB(150, 0, 250, 100),
158 2,
159 {DesktopRect::MakeLTRB(150, 0, 250, 100),
160 DesktopRect::MakeLTRB(100, 100, 200, 200)}},
161 {DesktopRect::MakeLTRB(100, 100, 200, 200),
162 DesktopRect::MakeLTRB(50, 0, 150, 100),
163 2,
164 {DesktopRect::MakeLTRB(50, 0, 150, 100),
165 DesktopRect::MakeLTRB(100, 100, 200, 200)}},
166 {DesktopRect::MakeLTRB(100, 100, 200, 200),
167 DesktopRect::MakeLTRB(120, 0, 180, 100),
168 2,
169 {DesktopRect::MakeLTRB(120, 0, 180, 100),
170 DesktopRect::MakeLTRB(100, 100, 200, 200)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000171
Yves Gerey665174f2018-06-19 15:03:05 +0200172 // Overlapping rectangles.
173 {DesktopRect::MakeLTRB(100, 100, 200, 200),
174 DesktopRect::MakeLTRB(50, 50, 150, 150),
175 3,
176 {DesktopRect::MakeLTRB(50, 50, 150, 100),
177 DesktopRect::MakeLTRB(50, 100, 200, 150),
178 DesktopRect::MakeLTRB(100, 150, 200, 200)}},
179 {DesktopRect::MakeLTRB(100, 100, 200, 200),
180 DesktopRect::MakeLTRB(150, 50, 250, 150),
181 3,
182 {DesktopRect::MakeLTRB(150, 50, 250, 100),
183 DesktopRect::MakeLTRB(100, 100, 250, 150),
184 DesktopRect::MakeLTRB(100, 150, 200, 200)}},
185 {DesktopRect::MakeLTRB(100, 100, 200, 200),
186 DesktopRect::MakeLTRB(0, 120, 150, 180),
187 3,
188 {DesktopRect::MakeLTRB(100, 100, 200, 120),
189 DesktopRect::MakeLTRB(0, 120, 200, 180),
190 DesktopRect::MakeLTRB(100, 180, 200, 200)}},
191 {DesktopRect::MakeLTRB(100, 100, 200, 200),
192 DesktopRect::MakeLTRB(120, 0, 180, 150),
193 2,
194 {DesktopRect::MakeLTRB(120, 0, 180, 100),
195 DesktopRect::MakeLTRB(100, 100, 200, 200)}},
196 {DesktopRect::MakeLTRB(100, 0, 200, 300),
197 DesktopRect::MakeLTRB(0, 100, 300, 200),
198 3,
199 {DesktopRect::MakeLTRB(100, 0, 200, 100),
200 DesktopRect::MakeLTRB(0, 100, 300, 200),
201 DesktopRect::MakeLTRB(100, 200, 200, 300)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000202
Yves Gerey665174f2018-06-19 15:03:05 +0200203 // One rectangle enclosing another.
204 {DesktopRect::MakeLTRB(100, 100, 200, 200),
205 DesktopRect::MakeLTRB(150, 150, 180, 180),
206 1,
207 {DesktopRect::MakeLTRB(100, 100, 200, 200)}},
208 {DesktopRect::MakeLTRB(100, 100, 200, 200),
209 DesktopRect::MakeLTRB(100, 100, 180, 180),
210 1,
211 {DesktopRect::MakeLTRB(100, 100, 200, 200)}},
212 {DesktopRect::MakeLTRB(100, 100, 200, 200),
213 DesktopRect::MakeLTRB(150, 150, 200, 200),
214 1,
215 {DesktopRect::MakeLTRB(100, 100, 200, 200)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000216 };
217
218 for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) {
219 SCOPED_TRACE(i);
220
221 DesktopRegion r;
222
223 r.AddRect(cases[i].input_rect1);
224 r.AddRect(cases[i].input_rect2);
225 CompareRegion(r, cases[i].expected_rects, cases[i].expected_count);
226
227 SCOPED_TRACE("Reverse");
228
229 // Run the same test with rectangles inserted in reverse order.
230 r.Clear();
231 r.AddRect(cases[i].input_rect2);
232 r.AddRect(cases[i].input_rect1);
233 CompareRegion(r, cases[i].expected_rects, cases[i].expected_count);
234 }
235}
236
237// Verify that DesktopRegion::AddRectToRow() works correctly by creating a row
238// of not overlapping rectangles and insert an overlapping rectangle into the
239// row at different positions. Result is verified by building a map of the
240// region in an array and comparing it with the expected values.
241TEST(DesktopRegionTest, SameRow) {
242 const int kMapWidth = 50;
243 const int kLastRectSizes[] = {3, 27};
244
245 DesktopRegion base_region;
Yves Gerey665174f2018-06-19 15:03:05 +0200246 bool base_map[kMapWidth] = {
247 false,
248 };
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000249
250 base_region.AddRect(DesktopRect::MakeXYWH(5, 0, 5, 1));
251 std::fill_n(base_map + 5, 5, true);
252 base_region.AddRect(DesktopRect::MakeXYWH(15, 0, 5, 1));
253 std::fill_n(base_map + 15, 5, true);
254 base_region.AddRect(DesktopRect::MakeXYWH(25, 0, 5, 1));
255 std::fill_n(base_map + 25, 5, true);
256 base_region.AddRect(DesktopRect::MakeXYWH(35, 0, 5, 1));
257 std::fill_n(base_map + 35, 5, true);
258 base_region.AddRect(DesktopRect::MakeXYWH(45, 0, 5, 1));
259 std::fill_n(base_map + 45, 5, true);
260
261 for (size_t i = 0; i < sizeof(kLastRectSizes) / sizeof(kLastRectSizes[0]);
262 i++) {
263 int last_rect_size = kLastRectSizes[i];
264 for (int x = 0; x < kMapWidth - last_rect_size; x++) {
265 SCOPED_TRACE(x);
266
267 DesktopRegion r = base_region;
Yves Gerey665174f2018-06-19 15:03:05 +0200268 r.AddRect(DesktopRect::MakeXYWH(x, 0, last_rect_size, 1));
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000269
270 bool expected_map[kMapWidth];
271 std::copy(base_map, base_map + kMapWidth, expected_map);
272 std::fill_n(expected_map + x, last_rect_size, true);
273
Yves Gerey665174f2018-06-19 15:03:05 +0200274 bool map[kMapWidth] = {
275 false,
276 };
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000277
278 int pos = -1;
279 for (DesktopRegion::Iterator it(r); !it.IsAtEnd(); it.Advance()) {
280 EXPECT_GT(it.rect().left(), pos);
281 pos = it.rect().right();
282 std::fill_n(map + it.rect().left(), it.rect().width(), true);
283 }
284
285 EXPECT_TRUE(std::equal(map, map + kMapWidth, expected_map));
286 }
287 }
288}
289
290TEST(DesktopRegionTest, ComplexRegions) {
291 struct Case {
292 int input_count;
293 DesktopRect input_rects[4];
294 int expected_count;
295 DesktopRect expected_rects[6];
296 } cases[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200297 {3,
298 {
299 DesktopRect::MakeLTRB(100, 100, 200, 200),
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000300 DesktopRect::MakeLTRB(0, 100, 100, 200),
Yves Gerey665174f2018-06-19 15:03:05 +0200301 DesktopRect::MakeLTRB(310, 110, 320, 120),
302 },
303 2,
304 {DesktopRect::MakeLTRB(0, 100, 200, 200),
305 DesktopRect::MakeLTRB(310, 110, 320, 120)}},
306 {3,
307 {DesktopRect::MakeLTRB(100, 100, 200, 200),
308 DesktopRect::MakeLTRB(50, 50, 150, 150),
309 DesktopRect::MakeLTRB(300, 125, 350, 175)},
310 4,
311 {DesktopRect::MakeLTRB(50, 50, 150, 100),
312 DesktopRect::MakeLTRB(50, 100, 200, 150),
313 DesktopRect::MakeLTRB(300, 125, 350, 175),
314 DesktopRect::MakeLTRB(100, 150, 200, 200)}},
315 {4,
316 {DesktopRect::MakeLTRB(0, 0, 30, 30),
317 DesktopRect::MakeLTRB(10, 10, 40, 40),
318 DesktopRect::MakeLTRB(20, 20, 50, 50),
319 DesktopRect::MakeLTRB(50, 0, 65, 15)},
320 6,
321 {DesktopRect::MakeLTRB(0, 0, 30, 10),
322 DesktopRect::MakeLTRB(50, 0, 65, 15),
323 DesktopRect::MakeLTRB(0, 10, 40, 20),
324 DesktopRect::MakeLTRB(0, 20, 50, 30),
325 DesktopRect::MakeLTRB(10, 30, 50, 40),
326 DesktopRect::MakeLTRB(20, 40, 50, 50)}},
327 {3,
328 {DesktopRect::MakeLTRB(10, 10, 40, 20),
329 DesktopRect::MakeLTRB(10, 30, 40, 40),
330 DesktopRect::MakeLTRB(10, 20, 40, 30)},
331 1,
332 {DesktopRect::MakeLTRB(10, 10, 40, 40)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000333 };
334
335 for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) {
336 SCOPED_TRACE(i);
337
338 DesktopRegion r;
339 r.AddRects(cases[i].input_rects, cases[i].input_count);
340 CompareRegion(r, cases[i].expected_rects, cases[i].expected_count);
341
342 // Try inserting rectangles in reverse order.
343 r.Clear();
344 for (int j = cases[i].input_count - 1; j >= 0; --j) {
345 r.AddRect(cases[i].input_rects[j]);
346 }
347 CompareRegion(r, cases[i].expected_rects, cases[i].expected_count);
348 }
349}
350
351TEST(DesktopRegionTest, Equals) {
352 struct Region {
353 int count;
354 DesktopRect rects[4];
355 int id;
356 } regions[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200357 // Same region with one of the rectangles 1 pixel wider/taller.
358 {2,
359 {DesktopRect::MakeLTRB(0, 100, 200, 200),
360 DesktopRect::MakeLTRB(310, 110, 320, 120)},
361 0},
362 {2,
363 {DesktopRect::MakeLTRB(0, 100, 201, 200),
364 DesktopRect::MakeLTRB(310, 110, 320, 120)},
365 1},
366 {2,
367 {DesktopRect::MakeLTRB(0, 100, 200, 201),
368 DesktopRect::MakeLTRB(310, 110, 320, 120)},
369 2},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000370
Yves Gerey665174f2018-06-19 15:03:05 +0200371 // Same region with one of the rectangles shifted horizontally and
372 // vertically.
373 {4,
374 {DesktopRect::MakeLTRB(0, 0, 30, 30),
375 DesktopRect::MakeLTRB(10, 10, 40, 40),
376 DesktopRect::MakeLTRB(20, 20, 50, 50),
377 DesktopRect::MakeLTRB(50, 0, 65, 15)},
378 3},
379 {4,
380 {DesktopRect::MakeLTRB(0, 0, 30, 30),
381 DesktopRect::MakeLTRB(10, 10, 40, 40),
382 DesktopRect::MakeLTRB(20, 20, 50, 50),
383 DesktopRect::MakeLTRB(50, 1, 65, 16)},
384 4},
385 {4,
386 {DesktopRect::MakeLTRB(0, 0, 30, 30),
387 DesktopRect::MakeLTRB(10, 10, 40, 40),
388 DesktopRect::MakeLTRB(20, 20, 50, 50),
389 DesktopRect::MakeLTRB(51, 0, 66, 15)},
390 5},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000391
Yves Gerey665174f2018-06-19 15:03:05 +0200392 // Same region defined by a different set of rectangles - one of the
393 // rectangle is split horizontally into two.
394 {3,
395 {DesktopRect::MakeLTRB(100, 100, 200, 200),
396 DesktopRect::MakeLTRB(50, 50, 150, 150),
397 DesktopRect::MakeLTRB(300, 125, 350, 175)},
398 6},
399 {4,
400 {DesktopRect::MakeLTRB(100, 100, 200, 200),
401 DesktopRect::MakeLTRB(50, 50, 100, 150),
402 DesktopRect::MakeLTRB(100, 50, 150, 150),
403 DesktopRect::MakeLTRB(300, 125, 350, 175)},
404 6},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000405
Yves Gerey665174f2018-06-19 15:03:05 +0200406 // Rectangle region defined by a set of rectangles that merge into one.
407 {3,
408 {DesktopRect::MakeLTRB(10, 10, 40, 20),
409 DesktopRect::MakeLTRB(10, 30, 40, 40),
410 DesktopRect::MakeLTRB(10, 20, 40, 30)},
411 7},
412 {1, {DesktopRect::MakeLTRB(10, 10, 40, 40)}, 7},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000413 };
414 int kTotalRegions = sizeof(regions) / sizeof(Region);
415
416 for (int i = 0; i < kTotalRegions; ++i) {
417 SCOPED_TRACE(i);
418
419 DesktopRegion r1(regions[i].rects, regions[i].count);
420 for (int j = 0; j < kTotalRegions; ++j) {
421 SCOPED_TRACE(j);
422
423 DesktopRegion r2(regions[j].rects, regions[j].count);
424 EXPECT_EQ(regions[i].id == regions[j].id, r1.Equals(r2));
425 }
426 }
427}
428
429TEST(DesktopRegionTest, Translate) {
430 struct Case {
431 int input_count;
432 DesktopRect input_rects[4];
433 int dx;
434 int dy;
435 int expected_count;
436 DesktopRect expected_rects[5];
437 } cases[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200438 {3,
439 {DesktopRect::MakeLTRB(0, 0, 30, 30),
440 DesktopRect::MakeLTRB(10, 10, 40, 40),
441 DesktopRect::MakeLTRB(20, 20, 50, 50)},
442 3,
443 5,
444 5,
445 {DesktopRect::MakeLTRB(3, 5, 33, 15),
446 DesktopRect::MakeLTRB(3, 15, 43, 25),
447 DesktopRect::MakeLTRB(3, 25, 53, 35),
448 DesktopRect::MakeLTRB(13, 35, 53, 45),
449 DesktopRect::MakeLTRB(23, 45, 53, 55)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000450 };
451
452 for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) {
453 SCOPED_TRACE(i);
454
455 DesktopRegion r(cases[i].input_rects, cases[i].input_count);
456 r.Translate(cases[i].dx, cases[i].dy);
457 CompareRegion(r, cases[i].expected_rects, cases[i].expected_count);
458 }
459}
460
461TEST(DesktopRegionTest, Intersect) {
462 struct Case {
463 int input1_count;
464 DesktopRect input1_rects[4];
465 int input2_count;
466 DesktopRect input2_rects[4];
467 int expected_count;
468 DesktopRect expected_rects[5];
469 } cases[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200470 {1,
471 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
472 1,
473 {DesktopRect::MakeLTRB(50, 50, 150, 150)},
474 1,
475 {DesktopRect::MakeLTRB(50, 50, 100, 100)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000476
Yves Gerey665174f2018-06-19 15:03:05 +0200477 {1,
478 {DesktopRect::MakeLTRB(100, 0, 200, 300)},
479 1,
480 {DesktopRect::MakeLTRB(0, 100, 300, 200)},
481 1,
482 {DesktopRect::MakeLTRB(100, 100, 200, 200)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000483
Yves Gerey665174f2018-06-19 15:03:05 +0200484 {1,
485 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
486 2,
487 {DesktopRect::MakeLTRB(50, 10, 150, 30),
488 DesktopRect::MakeLTRB(50, 30, 160, 50)},
489 1,
490 {DesktopRect::MakeLTRB(50, 10, 100, 50)}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000491
Yves Gerey665174f2018-06-19 15:03:05 +0200492 {1,
493 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
494 2,
495 {DesktopRect::MakeLTRB(50, 10, 150, 30),
496 DesktopRect::MakeLTRB(50, 30, 90, 50)},
497 2,
498 {DesktopRect::MakeLTRB(50, 10, 100, 30),
499 DesktopRect::MakeLTRB(50, 30, 90, 50)}},
500 {1,
501 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
502 1,
503 {DesktopRect::MakeLTRB(100, 50, 200, 200)},
504 0,
505 {}},
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000506 };
507
508 for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) {
509 SCOPED_TRACE(i);
510
511 DesktopRegion r1(cases[i].input1_rects, cases[i].input1_count);
512 DesktopRegion r2(cases[i].input2_rects, cases[i].input2_count);
513
514 DesktopRegion r;
515 r.Intersect(r1, r2);
516
517 CompareRegion(r, cases[i].expected_rects, cases[i].expected_count);
518 }
519}
520
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000521TEST(DesktopRegionTest, Subtract) {
522 struct Case {
523 int input1_count;
524 DesktopRect input1_rects[4];
525 int input2_count;
526 DesktopRect input2_rects[4];
527 int expected_count;
528 DesktopRect expected_rects[5];
529 } cases[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200530 // Subtract one rect from another.
531 {1,
532 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
533 1,
534 {DesktopRect::MakeLTRB(50, 50, 150, 150)},
535 2,
536 {DesktopRect::MakeLTRB(0, 0, 100, 50),
537 DesktopRect::MakeLTRB(0, 50, 50, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000538
Yves Gerey665174f2018-06-19 15:03:05 +0200539 {1,
540 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
541 1,
542 {DesktopRect::MakeLTRB(-50, -50, 50, 50)},
543 2,
544 {DesktopRect::MakeLTRB(50, 0, 100, 50),
545 DesktopRect::MakeLTRB(0, 50, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000546
Yves Gerey665174f2018-06-19 15:03:05 +0200547 {1,
548 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
549 1,
550 {DesktopRect::MakeLTRB(-50, 50, 50, 150)},
551 2,
552 {DesktopRect::MakeLTRB(0, 0, 100, 50),
553 DesktopRect::MakeLTRB(50, 50, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000554
Yves Gerey665174f2018-06-19 15:03:05 +0200555 {1,
556 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
557 1,
558 {DesktopRect::MakeLTRB(50, 50, 150, 70)},
559 3,
560 {DesktopRect::MakeLTRB(0, 0, 100, 50),
561 DesktopRect::MakeLTRB(0, 50, 50, 70),
562 DesktopRect::MakeLTRB(0, 70, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000563
Yves Gerey665174f2018-06-19 15:03:05 +0200564 {1,
565 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
566 1,
567 {DesktopRect::MakeLTRB(50, 50, 70, 70)},
568 4,
569 {DesktopRect::MakeLTRB(0, 0, 100, 50),
570 DesktopRect::MakeLTRB(0, 50, 50, 70),
571 DesktopRect::MakeLTRB(70, 50, 100, 70),
572 DesktopRect::MakeLTRB(0, 70, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000573
Yves Gerey665174f2018-06-19 15:03:05 +0200574 // Empty result.
575 {1,
576 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
577 1,
578 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
579 0,
580 {}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000581
Yves Gerey665174f2018-06-19 15:03:05 +0200582 {1,
583 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
584 1,
585 {DesktopRect::MakeLTRB(-10, -10, 110, 110)},
586 0,
587 {}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000588
Yves Gerey665174f2018-06-19 15:03:05 +0200589 {2,
590 {DesktopRect::MakeLTRB(0, 0, 100, 100),
591 DesktopRect::MakeLTRB(50, 50, 150, 150)},
592 2,
593 {DesktopRect::MakeLTRB(0, 0, 100, 100),
594 DesktopRect::MakeLTRB(50, 50, 150, 150)},
595 0,
596 {}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000597
Yves Gerey665174f2018-06-19 15:03:05 +0200598 // One rect out of disjoint set.
599 {3,
600 {DesktopRect::MakeLTRB(0, 0, 10, 10),
601 DesktopRect::MakeLTRB(20, 20, 30, 30),
602 DesktopRect::MakeLTRB(40, 0, 50, 10)},
603 1,
604 {DesktopRect::MakeLTRB(20, 20, 30, 30)},
605 2,
606 {DesktopRect::MakeLTRB(0, 0, 10, 10),
607 DesktopRect::MakeLTRB(40, 0, 50, 10)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000608
Yves Gerey665174f2018-06-19 15:03:05 +0200609 // Row merging.
610 {3,
611 {DesktopRect::MakeLTRB(0, 0, 100, 50),
612 DesktopRect::MakeLTRB(0, 50, 150, 70),
613 DesktopRect::MakeLTRB(0, 70, 100, 100)},
614 1,
615 {DesktopRect::MakeLTRB(100, 50, 150, 70)},
616 1,
617 {DesktopRect::MakeLTRB(0, 0, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000618
Yves Gerey665174f2018-06-19 15:03:05 +0200619 // No-op subtraction.
620 {1,
621 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
622 1,
623 {DesktopRect::MakeLTRB(100, 0, 200, 100)},
624 1,
625 {DesktopRect::MakeLTRB(0, 0, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000626
Yves Gerey665174f2018-06-19 15:03:05 +0200627 {1,
628 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
629 1,
630 {DesktopRect::MakeLTRB(-100, 0, 0, 100)},
631 1,
632 {DesktopRect::MakeLTRB(0, 0, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000633
Yves Gerey665174f2018-06-19 15:03:05 +0200634 {1,
635 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
636 1,
637 {DesktopRect::MakeLTRB(0, 100, 0, 200)},
638 1,
639 {DesktopRect::MakeLTRB(0, 0, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000640
Yves Gerey665174f2018-06-19 15:03:05 +0200641 {1,
642 {DesktopRect::MakeLTRB(0, 0, 100, 100)},
643 1,
644 {DesktopRect::MakeLTRB(0, -100, 100, 0)},
645 1,
646 {DesktopRect::MakeLTRB(0, 0, 100, 100)}},
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000647 };
648
649 for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) {
650 SCOPED_TRACE(i);
651
652 DesktopRegion r1(cases[i].input1_rects, cases[i].input1_count);
653 DesktopRegion r2(cases[i].input2_rects, cases[i].input2_count);
654
655 r1.Subtract(r2);
656
657 CompareRegion(r1, cases[i].expected_rects, cases[i].expected_count);
658 }
659}
660
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000661// Verify that DesktopRegion::SubtractRows() works correctly by creating a row
662// of not overlapping rectangles and subtracting a set of rectangle. Result
663// is verified by building a map of the region in an array and comparing it with
664// the expected values.
665TEST(DesktopRegionTest, SubtractRectOnSameRow) {
666 const int kMapWidth = 50;
667
668 struct SpanSet {
669 int count;
670 struct Range {
Yves Gerey665174f2018-06-19 15:03:05 +0200671 int start;
672 int end;
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000673 } spans[3];
674 } span_sets[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200675 {1, {{0, 3}}},
676 {1, {{0, 5}}},
677 {1, {{0, 7}}},
678 {1, {{0, 12}}},
679 {2, {{0, 3}, {4, 5}, {6, 16}}},
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000680 };
681
682 DesktopRegion base_region;
Yves Gerey665174f2018-06-19 15:03:05 +0200683 bool base_map[kMapWidth] = {
684 false,
685 };
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000686
687 base_region.AddRect(DesktopRect::MakeXYWH(5, 0, 5, 1));
688 std::fill_n(base_map + 5, 5, true);
689 base_region.AddRect(DesktopRect::MakeXYWH(15, 0, 5, 1));
690 std::fill_n(base_map + 15, 5, true);
691 base_region.AddRect(DesktopRect::MakeXYWH(25, 0, 5, 1));
692 std::fill_n(base_map + 25, 5, true);
693 base_region.AddRect(DesktopRect::MakeXYWH(35, 0, 5, 1));
694 std::fill_n(base_map + 35, 5, true);
695 base_region.AddRect(DesktopRect::MakeXYWH(45, 0, 5, 1));
696 std::fill_n(base_map + 45, 5, true);
697
698 for (size_t i = 0; i < sizeof(span_sets) / sizeof(span_sets[0]); i++) {
699 SCOPED_TRACE(i);
700 SpanSet& span_set = span_sets[i];
701 int span_set_end = span_set.spans[span_set.count - 1].end;
702 for (int x = 0; x < kMapWidth - span_set_end; ++x) {
703 SCOPED_TRACE(x);
704
705 DesktopRegion r = base_region;
706
707 bool expected_map[kMapWidth];
708 std::copy(base_map, base_map + kMapWidth, expected_map);
709
710 DesktopRegion region2;
711 for (int span = 0; span < span_set.count; span++) {
712 std::fill_n(x + expected_map + span_set.spans[span].start,
713 span_set.spans[span].end - span_set.spans[span].start,
714 false);
715 region2.AddRect(DesktopRect::MakeLTRB(x + span_set.spans[span].start, 0,
716 x + span_set.spans[span].end, 1));
717 }
718 r.Subtract(region2);
719
Yves Gerey665174f2018-06-19 15:03:05 +0200720 bool map[kMapWidth] = {
721 false,
722 };
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000723
724 int pos = -1;
725 for (DesktopRegion::Iterator it(r); !it.IsAtEnd(); it.Advance()) {
726 EXPECT_GT(it.rect().left(), pos);
727 pos = it.rect().right();
728 std::fill_n(map + it.rect().left(), it.rect().width(), true);
729 }
730
731 EXPECT_TRUE(std::equal(map, map + kMapWidth, expected_map));
732 }
733 }
734}
735
736// Verify that DesktopRegion::Subtract() works correctly by creating a column of
737// not overlapping rectangles and subtracting a set of rectangle on the same
738// column. Result is verified by building a map of the region in an array and
739// comparing it with the expected values.
740TEST(DesktopRegionTest, SubtractRectOnSameCol) {
741 const int kMapHeight = 50;
742
743 struct SpanSet {
744 int count;
745 struct Range {
Yves Gerey665174f2018-06-19 15:03:05 +0200746 int start;
747 int end;
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000748 } spans[3];
749 } span_sets[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200750 {1, {{0, 3}}},
751 {1, {{0, 5}}},
752 {1, {{0, 7}}},
753 {1, {{0, 12}}},
754 {2, {{0, 3}, {4, 5}, {6, 16}}},
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000755 };
756
757 DesktopRegion base_region;
Yves Gerey665174f2018-06-19 15:03:05 +0200758 bool base_map[kMapHeight] = {
759 false,
760 };
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000761
762 base_region.AddRect(DesktopRect::MakeXYWH(0, 5, 1, 5));
763 std::fill_n(base_map + 5, 5, true);
764 base_region.AddRect(DesktopRect::MakeXYWH(0, 15, 1, 5));
765 std::fill_n(base_map + 15, 5, true);
766 base_region.AddRect(DesktopRect::MakeXYWH(0, 25, 1, 5));
767 std::fill_n(base_map + 25, 5, true);
768 base_region.AddRect(DesktopRect::MakeXYWH(0, 35, 1, 5));
769 std::fill_n(base_map + 35, 5, true);
770 base_region.AddRect(DesktopRect::MakeXYWH(0, 45, 1, 5));
771 std::fill_n(base_map + 45, 5, true);
772
773 for (size_t i = 0; i < sizeof(span_sets) / sizeof(span_sets[0]); i++) {
774 SCOPED_TRACE(i);
775 SpanSet& span_set = span_sets[i];
776 int span_set_end = span_set.spans[span_set.count - 1].end;
777 for (int y = 0; y < kMapHeight - span_set_end; ++y) {
778 SCOPED_TRACE(y);
779
780 DesktopRegion r = base_region;
781
782 bool expected_map[kMapHeight];
783 std::copy(base_map, base_map + kMapHeight, expected_map);
784
785 DesktopRegion region2;
786 for (int span = 0; span < span_set.count; span++) {
787 std::fill_n(y + expected_map + span_set.spans[span].start,
788 span_set.spans[span].end - span_set.spans[span].start,
789 false);
790 region2.AddRect(DesktopRect::MakeLTRB(0, y + span_set.spans[span].start,
791 1, y + span_set.spans[span].end));
792 }
793 r.Subtract(region2);
794
Yves Gerey665174f2018-06-19 15:03:05 +0200795 bool map[kMapHeight] = {
796 false,
797 };
sergeyu@chromium.org2edb6422013-09-20 21:29:18 +0000798
799 int pos = -1;
800 for (DesktopRegion::Iterator it(r); !it.IsAtEnd(); it.Advance()) {
801 EXPECT_GT(it.rect().top(), pos);
802 pos = it.rect().bottom();
803 std::fill_n(map + it.rect().top(), it.rect().height(), true);
804 }
805
806 for (int j = 0; j < kMapHeight; j++) {
807 EXPECT_EQ(expected_map[j], map[j]) << "j = " << j;
808 }
809 }
810 }
811}
812
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000813TEST(DesktopRegionTest, DISABLED_Performance) {
814 for (int c = 0; c < 1000; ++c) {
815 DesktopRegion r;
816 for (int i = 0; i < 10; ++i) {
Yves Gerey665174f2018-06-19 15:03:05 +0200817 r.AddRect(
818 DesktopRect::MakeXYWH(RadmonInt(1000), RadmonInt(1000), 200, 200));
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000819 }
820
821 for (int i = 0; i < 1000; ++i) {
Yves Gerey665174f2018-06-19 15:03:05 +0200822 r.AddRect(DesktopRect::MakeXYWH(RadmonInt(1000), RadmonInt(1000),
823 5 + RadmonInt(10) * 5,
824 5 + RadmonInt(10) * 5));
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000825 }
826
827 // Iterate over the rectangles.
828 for (DesktopRegion::Iterator it(r); !it.IsAtEnd(); it.Advance()) {
829 }
830 }
831}
832
833} // namespace webrtc