| /* |
| * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "modules/desktop_capture/desktop_region.h" |
| |
| #include <algorithm> |
| |
| #include "test/gtest.h" |
| |
| namespace webrtc { |
| |
| namespace { |
| |
| int RadmonInt(int max) { |
| return (rand() / 256) % max; |
| } |
| |
| void CompareRegion(const DesktopRegion& region, |
| const DesktopRect rects[], int rects_size) { |
| DesktopRegion::Iterator it(region); |
| for (int i = 0; i < rects_size; ++i) { |
| SCOPED_TRACE(i); |
| ASSERT_FALSE(it.IsAtEnd()); |
| EXPECT_TRUE(it.rect().equals(rects[i])) |
| << it.rect().left() << "-" << it.rect().right() << "." |
| << it.rect().top() << "-" << it.rect().bottom() << " " |
| << rects[i].left() << "-" << rects[i].right() << "." |
| << rects[i].top() << "-" << rects[i].bottom(); |
| it.Advance(); |
| } |
| EXPECT_TRUE(it.IsAtEnd()); |
| } |
| |
| } // namespace |
| |
| // Verify that regions are empty when created. |
| TEST(DesktopRegionTest, Empty) { |
| DesktopRegion r; |
| CompareRegion(r, NULL, 0); |
| } |
| |
| // Verify that empty rectangles are ignored. |
| TEST(DesktopRegionTest, AddEmpty) { |
| DesktopRegion r; |
| DesktopRect rect = DesktopRect::MakeXYWH(1, 2, 0, 0); |
| r.AddRect(rect); |
| CompareRegion(r, NULL, 0); |
| } |
| |
| // Verify that regions with a single rectangles are handled properly. |
| TEST(DesktopRegionTest, SingleRect) { |
| DesktopRegion r; |
| DesktopRect rect = DesktopRect::MakeXYWH(1, 2, 3, 4); |
| r.AddRect(rect); |
| CompareRegion(r, &rect, 1); |
| } |
| |
| // Verify that non-overlapping rectangles are not merged. |
| TEST(DesktopRegionTest, NonOverlappingRects) { |
| struct Case { |
| int count; |
| DesktopRect rects[4]; |
| } cases[] = { |
| { 1, { DesktopRect::MakeXYWH(10, 10, 10, 10) } }, |
| { 2, { DesktopRect::MakeXYWH(10, 10, 10, 10), |
| DesktopRect::MakeXYWH(30, 10, 10, 15) } }, |
| { 2, { DesktopRect::MakeXYWH(10, 10, 10, 10), |
| DesktopRect::MakeXYWH(10, 30, 10, 5) } }, |
| { 3, { DesktopRect::MakeXYWH(10, 10, 10, 9), |
| DesktopRect::MakeXYWH(30, 10, 15, 10), |
| DesktopRect::MakeXYWH(10, 30, 8, 10) } }, |
| { 4, { DesktopRect::MakeXYWH(0, 0, 30, 10), |
| DesktopRect::MakeXYWH(40, 0, 10, 30), |
| DesktopRect::MakeXYWH(0, 20, 10, 30), |
| DesktopRect::MakeXYWH(20, 40, 30, 10) } }, |
| { 4, { DesktopRect::MakeXYWH(0, 0, 10, 100), |
| DesktopRect::MakeXYWH(20, 10, 30, 10), |
| DesktopRect::MakeXYWH(20, 30, 30, 10), |
| DesktopRect::MakeXYWH(20, 50, 30, 10) } }, |
| }; |
| |
| for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) { |
| SCOPED_TRACE(i); |
| |
| DesktopRegion r; |
| |
| for (int j = 0; j < cases[i].count; ++j) { |
| r.AddRect(cases[i].rects[j]); |
| } |
| CompareRegion(r, cases[i].rects, cases[i].count); |
| |
| SCOPED_TRACE("Reverse"); |
| |
| // Try inserting rects in reverse order. |
| r.Clear(); |
| for (int j = cases[i].count - 1; j >= 0; --j) { |
| r.AddRect(cases[i].rects[j]); |
| } |
| CompareRegion(r, cases[i].rects, cases[i].count); |
| } |
| } |
| |
| TEST(DesktopRegionTest, TwoRects) { |
| struct Case { |
| DesktopRect input_rect1; |
| DesktopRect input_rect2; |
| int expected_count; |
| DesktopRect expected_rects[3]; |
| } cases[] = { |
| // Touching rectangles that merge into one. |
| { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(0, 100, 100, 200), |
| 1, { DesktopRect::MakeLTRB(0, 100, 200, 200) } }, |
| { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(100, 0, 200, 100), |
| 1, { DesktopRect::MakeLTRB(100, 0, 200, 200) } }, |
| |
| // Rectangles touching on the vertical edge. |
| { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(0, 150, 100, 250), |
| 3, { DesktopRect::MakeLTRB(100, 100, 200, 150), |
| DesktopRect::MakeLTRB(0, 150, 200, 200), |
| DesktopRect::MakeLTRB(0, 200, 100, 250) } }, |
| { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(0, 50, 100, 150), |
| 3, { DesktopRect::MakeLTRB(0, 50, 100, 100), |
| DesktopRect::MakeLTRB(0, 100, 200, 150), |
| DesktopRect::MakeLTRB(100, 150, 200, 200) } }, |
| { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(0, 120, 100, 180), |
| 3, { DesktopRect::MakeLTRB(100, 100, 200, 120), |
| DesktopRect::MakeLTRB(0, 120, 200, 180), |
| DesktopRect::MakeLTRB(100, 180, 200, 200) } }, |
| |
| // Rectangles touching on the horizontal edge. |
| { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(150, 0, 250, 100), |
| 2, { DesktopRect::MakeLTRB(150, 0, 250, 100), |
| DesktopRect::MakeLTRB(100, 100, 200, 200) } }, |
| { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(50, 0, 150, 100), |
| 2, { DesktopRect::MakeLTRB(50, 0, 150, 100), |
| DesktopRect::MakeLTRB(100, 100, 200, 200) } }, |
| { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(120, 0, 180, 100), |
| 2, { DesktopRect::MakeLTRB(120, 0, 180, 100), |
| DesktopRect::MakeLTRB(100, 100, 200, 200) } }, |
| |
| // Overlapping rectangles. |
| { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(50, 50, 150, 150), |
| 3, { DesktopRect::MakeLTRB(50, 50, 150, 100), |
| DesktopRect::MakeLTRB(50, 100, 200, 150), |
| DesktopRect::MakeLTRB(100, 150, 200, 200) } }, |
| { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(150, 50, 250, 150), |
| 3, { DesktopRect::MakeLTRB(150, 50, 250, 100), |
| DesktopRect::MakeLTRB(100, 100, 250, 150), |
| DesktopRect::MakeLTRB(100, 150, 200, 200) } }, |
| { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(0, 120, 150, 180), |
| 3, { DesktopRect::MakeLTRB(100, 100, 200, 120), |
| DesktopRect::MakeLTRB(0, 120, 200, 180), |
| DesktopRect::MakeLTRB(100, 180, 200, 200) } }, |
| { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(120, 0, 180, 150), |
| 2, { DesktopRect::MakeLTRB(120, 0, 180, 100), |
| DesktopRect::MakeLTRB(100, 100, 200, 200) } }, |
| { DesktopRect::MakeLTRB(100, 0, 200, 300), |
| DesktopRect::MakeLTRB(0, 100, 300, 200), |
| 3, { DesktopRect::MakeLTRB(100, 0, 200, 100), |
| DesktopRect::MakeLTRB(0, 100, 300, 200), |
| DesktopRect::MakeLTRB(100, 200, 200, 300)} }, |
| |
| // One rectangle enclosing another. |
| { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(150, 150, 180, 180), |
| 1, { DesktopRect::MakeLTRB(100, 100, 200, 200) } }, |
| { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(100, 100, 180, 180), |
| 1, { DesktopRect::MakeLTRB(100, 100, 200, 200) } }, |
| { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(150, 150, 200, 200), |
| 1, { DesktopRect::MakeLTRB(100, 100, 200, 200) } }, |
| }; |
| |
| for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) { |
| SCOPED_TRACE(i); |
| |
| DesktopRegion r; |
| |
| r.AddRect(cases[i].input_rect1); |
| r.AddRect(cases[i].input_rect2); |
| CompareRegion(r, cases[i].expected_rects, cases[i].expected_count); |
| |
| SCOPED_TRACE("Reverse"); |
| |
| // Run the same test with rectangles inserted in reverse order. |
| r.Clear(); |
| r.AddRect(cases[i].input_rect2); |
| r.AddRect(cases[i].input_rect1); |
| CompareRegion(r, cases[i].expected_rects, cases[i].expected_count); |
| } |
| } |
| |
| // Verify that DesktopRegion::AddRectToRow() works correctly by creating a row |
| // of not overlapping rectangles and insert an overlapping rectangle into the |
| // row at different positions. Result is verified by building a map of the |
| // region in an array and comparing it with the expected values. |
| TEST(DesktopRegionTest, SameRow) { |
| const int kMapWidth = 50; |
| const int kLastRectSizes[] = {3, 27}; |
| |
| DesktopRegion base_region; |
| bool base_map[kMapWidth] = { false, }; |
| |
| base_region.AddRect(DesktopRect::MakeXYWH(5, 0, 5, 1)); |
| std::fill_n(base_map + 5, 5, true); |
| base_region.AddRect(DesktopRect::MakeXYWH(15, 0, 5, 1)); |
| std::fill_n(base_map + 15, 5, true); |
| base_region.AddRect(DesktopRect::MakeXYWH(25, 0, 5, 1)); |
| std::fill_n(base_map + 25, 5, true); |
| base_region.AddRect(DesktopRect::MakeXYWH(35, 0, 5, 1)); |
| std::fill_n(base_map + 35, 5, true); |
| base_region.AddRect(DesktopRect::MakeXYWH(45, 0, 5, 1)); |
| std::fill_n(base_map + 45, 5, true); |
| |
| for (size_t i = 0; i < sizeof(kLastRectSizes) / sizeof(kLastRectSizes[0]); |
| i++) { |
| int last_rect_size = kLastRectSizes[i]; |
| for (int x = 0; x < kMapWidth - last_rect_size; x++) { |
| SCOPED_TRACE(x); |
| |
| DesktopRegion r = base_region; |
| r.AddRect(DesktopRect::MakeXYWH(x, 0, last_rect_size, 1)); |
| |
| bool expected_map[kMapWidth]; |
| std::copy(base_map, base_map + kMapWidth, expected_map); |
| std::fill_n(expected_map + x, last_rect_size, true); |
| |
| bool map[kMapWidth] = { false, }; |
| |
| int pos = -1; |
| for (DesktopRegion::Iterator it(r); !it.IsAtEnd(); it.Advance()) { |
| EXPECT_GT(it.rect().left(), pos); |
| pos = it.rect().right(); |
| std::fill_n(map + it.rect().left(), it.rect().width(), true); |
| } |
| |
| EXPECT_TRUE(std::equal(map, map + kMapWidth, expected_map)); |
| } |
| } |
| } |
| |
| TEST(DesktopRegionTest, ComplexRegions) { |
| struct Case { |
| int input_count; |
| DesktopRect input_rects[4]; |
| int expected_count; |
| DesktopRect expected_rects[6]; |
| } cases[] = { |
| { 3, { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(0, 100, 100, 200), |
| DesktopRect::MakeLTRB(310, 110, 320, 120), }, |
| 2, { DesktopRect::MakeLTRB(0, 100, 200, 200), |
| DesktopRect::MakeLTRB(310, 110, 320, 120) } }, |
| { 3, { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(50, 50, 150, 150), |
| DesktopRect::MakeLTRB(300, 125, 350, 175) }, |
| 4, { DesktopRect::MakeLTRB(50, 50, 150, 100), |
| DesktopRect::MakeLTRB(50, 100, 200, 150), |
| DesktopRect::MakeLTRB(300, 125, 350, 175), |
| DesktopRect::MakeLTRB(100, 150, 200, 200) } }, |
| { 4, { DesktopRect::MakeLTRB(0, 0, 30, 30), |
| DesktopRect::MakeLTRB(10, 10, 40, 40), |
| DesktopRect::MakeLTRB(20, 20, 50, 50), |
| DesktopRect::MakeLTRB(50, 0, 65, 15) }, |
| 6, { DesktopRect::MakeLTRB(0, 0, 30, 10), |
| DesktopRect::MakeLTRB(50, 0, 65, 15), |
| DesktopRect::MakeLTRB(0, 10, 40, 20), |
| DesktopRect::MakeLTRB(0, 20, 50, 30), |
| DesktopRect::MakeLTRB(10, 30, 50, 40), |
| DesktopRect::MakeLTRB(20, 40, 50, 50) } }, |
| { 3, { DesktopRect::MakeLTRB(10, 10, 40, 20), |
| DesktopRect::MakeLTRB(10, 30, 40, 40), |
| DesktopRect::MakeLTRB(10, 20, 40, 30) }, |
| 1, { DesktopRect::MakeLTRB(10, 10, 40, 40) } }, |
| }; |
| |
| for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) { |
| SCOPED_TRACE(i); |
| |
| DesktopRegion r; |
| r.AddRects(cases[i].input_rects, cases[i].input_count); |
| CompareRegion(r, cases[i].expected_rects, cases[i].expected_count); |
| |
| // Try inserting rectangles in reverse order. |
| r.Clear(); |
| for (int j = cases[i].input_count - 1; j >= 0; --j) { |
| r.AddRect(cases[i].input_rects[j]); |
| } |
| CompareRegion(r, cases[i].expected_rects, cases[i].expected_count); |
| } |
| } |
| |
| TEST(DesktopRegionTest, Equals) { |
| struct Region { |
| int count; |
| DesktopRect rects[4]; |
| int id; |
| } regions[] = { |
| // Same region with one of the rectangles 1 pixel wider/taller. |
| { 2, { DesktopRect::MakeLTRB(0, 100, 200, 200), |
| DesktopRect::MakeLTRB(310, 110, 320, 120) }, 0 }, |
| { 2, { DesktopRect::MakeLTRB(0, 100, 201, 200), |
| DesktopRect::MakeLTRB(310, 110, 320, 120) }, 1 }, |
| { 2, { DesktopRect::MakeLTRB(0, 100, 200, 201), |
| DesktopRect::MakeLTRB(310, 110, 320, 120) }, 2 }, |
| |
| // Same region with one of the rectangles shifted horizontally and |
| // vertically. |
| { 4, { DesktopRect::MakeLTRB(0, 0, 30, 30), |
| DesktopRect::MakeLTRB(10, 10, 40, 40), |
| DesktopRect::MakeLTRB(20, 20, 50, 50), |
| DesktopRect::MakeLTRB(50, 0, 65, 15) }, 3 }, |
| { 4, { DesktopRect::MakeLTRB(0, 0, 30, 30), |
| DesktopRect::MakeLTRB(10, 10, 40, 40), |
| DesktopRect::MakeLTRB(20, 20, 50, 50), |
| DesktopRect::MakeLTRB(50, 1, 65, 16) }, 4 }, |
| { 4, { DesktopRect::MakeLTRB(0, 0, 30, 30), |
| DesktopRect::MakeLTRB(10, 10, 40, 40), |
| DesktopRect::MakeLTRB(20, 20, 50, 50), |
| DesktopRect::MakeLTRB(51, 0, 66, 15) }, 5 }, |
| |
| // Same region defined by a different set of rectangles - one of the |
| // rectangle is split horizontally into two. |
| { 3, { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(50, 50, 150, 150), |
| DesktopRect::MakeLTRB(300, 125, 350, 175) }, 6 }, |
| { 4, { DesktopRect::MakeLTRB(100, 100, 200, 200), |
| DesktopRect::MakeLTRB(50, 50, 100, 150), |
| DesktopRect::MakeLTRB(100, 50, 150, 150), |
| DesktopRect::MakeLTRB(300, 125, 350, 175) }, 6 }, |
| |
| // Rectangle region defined by a set of rectangles that merge into one. |
| { 3, { DesktopRect::MakeLTRB(10, 10, 40, 20), |
| DesktopRect::MakeLTRB(10, 30, 40, 40), |
| DesktopRect::MakeLTRB(10, 20, 40, 30) }, 7 }, |
| { 1, { DesktopRect::MakeLTRB(10, 10, 40, 40) }, 7 }, |
| }; |
| int kTotalRegions = sizeof(regions) / sizeof(Region); |
| |
| for (int i = 0; i < kTotalRegions; ++i) { |
| SCOPED_TRACE(i); |
| |
| DesktopRegion r1(regions[i].rects, regions[i].count); |
| for (int j = 0; j < kTotalRegions; ++j) { |
| SCOPED_TRACE(j); |
| |
| DesktopRegion r2(regions[j].rects, regions[j].count); |
| EXPECT_EQ(regions[i].id == regions[j].id, r1.Equals(r2)); |
| } |
| } |
| } |
| |
| TEST(DesktopRegionTest, Translate) { |
| struct Case { |
| int input_count; |
| DesktopRect input_rects[4]; |
| int dx; |
| int dy; |
| int expected_count; |
| DesktopRect expected_rects[5]; |
| } cases[] = { |
| { 3, { DesktopRect::MakeLTRB(0, 0, 30, 30), |
| DesktopRect::MakeLTRB(10, 10, 40, 40), |
| DesktopRect::MakeLTRB(20, 20, 50, 50) }, |
| 3, 5, |
| 5, { DesktopRect::MakeLTRB(3, 5, 33, 15), |
| DesktopRect::MakeLTRB(3, 15, 43, 25), |
| DesktopRect::MakeLTRB(3, 25, 53, 35), |
| DesktopRect::MakeLTRB(13, 35, 53, 45), |
| DesktopRect::MakeLTRB(23, 45, 53, 55) } }, |
| }; |
| |
| for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) { |
| SCOPED_TRACE(i); |
| |
| DesktopRegion r(cases[i].input_rects, cases[i].input_count); |
| r.Translate(cases[i].dx, cases[i].dy); |
| CompareRegion(r, cases[i].expected_rects, cases[i].expected_count); |
| } |
| } |
| |
| TEST(DesktopRegionTest, Intersect) { |
| struct Case { |
| int input1_count; |
| DesktopRect input1_rects[4]; |
| int input2_count; |
| DesktopRect input2_rects[4]; |
| int expected_count; |
| DesktopRect expected_rects[5]; |
| } cases[] = { |
| { 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 1, { DesktopRect::MakeLTRB(50, 50, 150, 150) }, |
| 1, { DesktopRect::MakeLTRB(50, 50, 100, 100) } }, |
| |
| { 1, { DesktopRect::MakeLTRB(100, 0, 200, 300) }, |
| 1, { DesktopRect::MakeLTRB(0, 100, 300, 200) }, |
| 1, { DesktopRect::MakeLTRB(100, 100, 200, 200) } }, |
| |
| { 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 2, { DesktopRect::MakeLTRB(50, 10, 150, 30), |
| DesktopRect::MakeLTRB(50, 30, 160, 50) }, |
| 1, { DesktopRect::MakeLTRB(50, 10, 100, 50) } }, |
| |
| { 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 2, { DesktopRect::MakeLTRB(50, 10, 150, 30), |
| DesktopRect::MakeLTRB(50, 30, 90, 50) }, |
| 2, { DesktopRect::MakeLTRB(50, 10, 100, 30), |
| DesktopRect::MakeLTRB(50, 30, 90, 50) } }, |
| { 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 1, { DesktopRect::MakeLTRB(100, 50, 200, 200) }, |
| 0, {} }, |
| }; |
| |
| for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) { |
| SCOPED_TRACE(i); |
| |
| DesktopRegion r1(cases[i].input1_rects, cases[i].input1_count); |
| DesktopRegion r2(cases[i].input2_rects, cases[i].input2_count); |
| |
| DesktopRegion r; |
| r.Intersect(r1, r2); |
| |
| CompareRegion(r, cases[i].expected_rects, cases[i].expected_count); |
| } |
| } |
| |
| TEST(DesktopRegionTest, Subtract) { |
| struct Case { |
| int input1_count; |
| DesktopRect input1_rects[4]; |
| int input2_count; |
| DesktopRect input2_rects[4]; |
| int expected_count; |
| DesktopRect expected_rects[5]; |
| } cases[] = { |
| // Subtract one rect from another. |
| { 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 1, { DesktopRect::MakeLTRB(50, 50, 150, 150) }, |
| 2, { DesktopRect::MakeLTRB(0, 0, 100, 50), |
| DesktopRect::MakeLTRB(0, 50, 50, 100) } }, |
| |
| { 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 1, { DesktopRect::MakeLTRB(-50, -50, 50, 50) }, |
| 2, { DesktopRect::MakeLTRB(50, 0, 100, 50), |
| DesktopRect::MakeLTRB(0, 50, 100, 100) } }, |
| |
| { 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 1, { DesktopRect::MakeLTRB(-50, 50, 50, 150) }, |
| 2, { DesktopRect::MakeLTRB(0, 0, 100, 50), |
| DesktopRect::MakeLTRB(50, 50, 100, 100) } }, |
| |
| { 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 1, { DesktopRect::MakeLTRB(50, 50, 150, 70) }, |
| 3, { DesktopRect::MakeLTRB(0, 0, 100, 50), |
| DesktopRect::MakeLTRB(0, 50, 50, 70), |
| DesktopRect::MakeLTRB(0, 70, 100, 100) } }, |
| |
| { 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 1, { DesktopRect::MakeLTRB(50, 50, 70, 70) }, |
| 4, { DesktopRect::MakeLTRB(0, 0, 100, 50), |
| DesktopRect::MakeLTRB(0, 50, 50, 70), |
| DesktopRect::MakeLTRB(70, 50, 100, 70), |
| DesktopRect::MakeLTRB(0, 70, 100, 100) } }, |
| |
| // Empty result. |
| { 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 0, {} }, |
| |
| { 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 1, { DesktopRect::MakeLTRB(-10, -10, 110, 110) }, |
| 0, {} }, |
| |
| { 2, { DesktopRect::MakeLTRB(0, 0, 100, 100), |
| DesktopRect::MakeLTRB(50, 50, 150, 150) }, |
| 2, { DesktopRect::MakeLTRB(0, 0, 100, 100), |
| DesktopRect::MakeLTRB(50, 50, 150, 150) }, |
| 0, {} }, |
| |
| // One rect out of disjoint set. |
| { 3, { DesktopRect::MakeLTRB(0, 0, 10, 10), |
| DesktopRect::MakeLTRB(20, 20, 30, 30), |
| DesktopRect::MakeLTRB(40, 0, 50, 10) }, |
| 1, { DesktopRect::MakeLTRB(20, 20, 30, 30) }, |
| 2, { DesktopRect::MakeLTRB(0, 0, 10, 10), |
| DesktopRect::MakeLTRB(40, 0, 50, 10) } }, |
| |
| // Row merging. |
| { 3, { DesktopRect::MakeLTRB(0, 0, 100, 50), |
| DesktopRect::MakeLTRB(0, 50, 150, 70), |
| DesktopRect::MakeLTRB(0, 70, 100, 100) }, |
| 1, { DesktopRect::MakeLTRB(100, 50, 150, 70) }, |
| 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) } }, |
| |
| // No-op subtraction. |
| { 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 1, { DesktopRect::MakeLTRB(100, 0, 200, 100) }, |
| 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) } }, |
| |
| { 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 1, { DesktopRect::MakeLTRB(-100, 0, 0, 100) }, |
| 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) } }, |
| |
| { 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 1, { DesktopRect::MakeLTRB(0, 100, 0, 200) }, |
| 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) } }, |
| |
| { 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) }, |
| 1, { DesktopRect::MakeLTRB(0, -100, 100, 0) }, |
| 1, { DesktopRect::MakeLTRB(0, 0, 100, 100) } }, |
| }; |
| |
| for (size_t i = 0; i < (sizeof(cases) / sizeof(Case)); ++i) { |
| SCOPED_TRACE(i); |
| |
| DesktopRegion r1(cases[i].input1_rects, cases[i].input1_count); |
| DesktopRegion r2(cases[i].input2_rects, cases[i].input2_count); |
| |
| r1.Subtract(r2); |
| |
| CompareRegion(r1, cases[i].expected_rects, cases[i].expected_count); |
| } |
| } |
| |
| // Verify that DesktopRegion::SubtractRows() works correctly by creating a row |
| // of not overlapping rectangles and subtracting a set of rectangle. Result |
| // is verified by building a map of the region in an array and comparing it with |
| // the expected values. |
| TEST(DesktopRegionTest, SubtractRectOnSameRow) { |
| const int kMapWidth = 50; |
| |
| struct SpanSet { |
| int count; |
| struct Range { |
| int start; |
| int end; |
| } spans[3]; |
| } span_sets[] = { |
| {1, { {0, 3} } }, |
| {1, { {0, 5} } }, |
| {1, { {0, 7} } }, |
| {1, { {0, 12} } }, |
| {2, { {0, 3}, {4, 5}, {6, 16} } }, |
| }; |
| |
| DesktopRegion base_region; |
| bool base_map[kMapWidth] = { false, }; |
| |
| base_region.AddRect(DesktopRect::MakeXYWH(5, 0, 5, 1)); |
| std::fill_n(base_map + 5, 5, true); |
| base_region.AddRect(DesktopRect::MakeXYWH(15, 0, 5, 1)); |
| std::fill_n(base_map + 15, 5, true); |
| base_region.AddRect(DesktopRect::MakeXYWH(25, 0, 5, 1)); |
| std::fill_n(base_map + 25, 5, true); |
| base_region.AddRect(DesktopRect::MakeXYWH(35, 0, 5, 1)); |
| std::fill_n(base_map + 35, 5, true); |
| base_region.AddRect(DesktopRect::MakeXYWH(45, 0, 5, 1)); |
| std::fill_n(base_map + 45, 5, true); |
| |
| for (size_t i = 0; i < sizeof(span_sets) / sizeof(span_sets[0]); i++) { |
| SCOPED_TRACE(i); |
| SpanSet& span_set = span_sets[i]; |
| int span_set_end = span_set.spans[span_set.count - 1].end; |
| for (int x = 0; x < kMapWidth - span_set_end; ++x) { |
| SCOPED_TRACE(x); |
| |
| DesktopRegion r = base_region; |
| |
| bool expected_map[kMapWidth]; |
| std::copy(base_map, base_map + kMapWidth, expected_map); |
| |
| DesktopRegion region2; |
| for (int span = 0; span < span_set.count; span++) { |
| std::fill_n(x + expected_map + span_set.spans[span].start, |
| span_set.spans[span].end - span_set.spans[span].start, |
| false); |
| region2.AddRect(DesktopRect::MakeLTRB(x + span_set.spans[span].start, 0, |
| x + span_set.spans[span].end, 1)); |
| } |
| r.Subtract(region2); |
| |
| bool map[kMapWidth] = { false, }; |
| |
| int pos = -1; |
| for (DesktopRegion::Iterator it(r); !it.IsAtEnd(); it.Advance()) { |
| EXPECT_GT(it.rect().left(), pos); |
| pos = it.rect().right(); |
| std::fill_n(map + it.rect().left(), it.rect().width(), true); |
| } |
| |
| EXPECT_TRUE(std::equal(map, map + kMapWidth, expected_map)); |
| } |
| } |
| } |
| |
| // Verify that DesktopRegion::Subtract() works correctly by creating a column of |
| // not overlapping rectangles and subtracting a set of rectangle on the same |
| // column. Result is verified by building a map of the region in an array and |
| // comparing it with the expected values. |
| TEST(DesktopRegionTest, SubtractRectOnSameCol) { |
| const int kMapHeight = 50; |
| |
| struct SpanSet { |
| int count; |
| struct Range { |
| int start; |
| int end; |
| } spans[3]; |
| } span_sets[] = { |
| {1, { {0, 3} } }, |
| {1, { {0, 5} } }, |
| {1, { {0, 7} } }, |
| {1, { {0, 12} } }, |
| {2, { {0, 3}, {4, 5}, {6, 16} } }, |
| }; |
| |
| DesktopRegion base_region; |
| bool base_map[kMapHeight] = { false, }; |
| |
| base_region.AddRect(DesktopRect::MakeXYWH(0, 5, 1, 5)); |
| std::fill_n(base_map + 5, 5, true); |
| base_region.AddRect(DesktopRect::MakeXYWH(0, 15, 1, 5)); |
| std::fill_n(base_map + 15, 5, true); |
| base_region.AddRect(DesktopRect::MakeXYWH(0, 25, 1, 5)); |
| std::fill_n(base_map + 25, 5, true); |
| base_region.AddRect(DesktopRect::MakeXYWH(0, 35, 1, 5)); |
| std::fill_n(base_map + 35, 5, true); |
| base_region.AddRect(DesktopRect::MakeXYWH(0, 45, 1, 5)); |
| std::fill_n(base_map + 45, 5, true); |
| |
| for (size_t i = 0; i < sizeof(span_sets) / sizeof(span_sets[0]); i++) { |
| SCOPED_TRACE(i); |
| SpanSet& span_set = span_sets[i]; |
| int span_set_end = span_set.spans[span_set.count - 1].end; |
| for (int y = 0; y < kMapHeight - span_set_end; ++y) { |
| SCOPED_TRACE(y); |
| |
| DesktopRegion r = base_region; |
| |
| bool expected_map[kMapHeight]; |
| std::copy(base_map, base_map + kMapHeight, expected_map); |
| |
| DesktopRegion region2; |
| for (int span = 0; span < span_set.count; span++) { |
| std::fill_n(y + expected_map + span_set.spans[span].start, |
| span_set.spans[span].end - span_set.spans[span].start, |
| false); |
| region2.AddRect(DesktopRect::MakeLTRB(0, y + span_set.spans[span].start, |
| 1, y + span_set.spans[span].end)); |
| } |
| r.Subtract(region2); |
| |
| bool map[kMapHeight] = { false, }; |
| |
| int pos = -1; |
| for (DesktopRegion::Iterator it(r); !it.IsAtEnd(); it.Advance()) { |
| EXPECT_GT(it.rect().top(), pos); |
| pos = it.rect().bottom(); |
| std::fill_n(map + it.rect().top(), it.rect().height(), true); |
| } |
| |
| for (int j = 0; j < kMapHeight; j++) { |
| EXPECT_EQ(expected_map[j], map[j]) << "j = " << j; |
| } |
| } |
| } |
| } |
| |
| |
| TEST(DesktopRegionTest, DISABLED_Performance) { |
| for (int c = 0; c < 1000; ++c) { |
| DesktopRegion r; |
| for (int i = 0; i < 10; ++i) { |
| r.AddRect(DesktopRect::MakeXYWH( |
| RadmonInt(1000), RadmonInt(1000), 200, 200)); |
| } |
| |
| for (int i = 0; i < 1000; ++i) { |
| r.AddRect(DesktopRect::MakeXYWH( |
| RadmonInt(1000), RadmonInt(1000), |
| 5 + RadmonInt(10) * 5, 5 + RadmonInt(10) * 5)); |
| } |
| |
| // Iterate over the rectangles. |
| for (DesktopRegion::Iterator it(r); !it.IsAtEnd(); it.Advance()) { |
| } |
| } |
| } |
| |
| } // namespace webrtc |