/src/mozilla-central/gfx/tests/gtest/TestRegion.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include <algorithm> |
8 | | |
9 | | #include "gtest/gtest.h" |
10 | | #include "nsRegion.h" |
11 | | #include "RegionBuilder.h" |
12 | | #include "mozilla/gfx/TiledRegion.h" |
13 | | #include "mozilla/UniquePtr.h" |
14 | | |
15 | | using namespace std; |
16 | | using namespace mozilla::gfx; |
17 | | |
18 | | //#define REGION_RANDOM_STRESS_TESTS |
19 | | |
20 | | class TestLargestRegion { |
21 | | public: |
22 | 0 | static void TestSingleRect(nsRect r) { |
23 | 0 | nsRegion region(r); |
24 | 0 | EXPECT_TRUE(region.GetLargestRectangle().IsEqualInterior(r)); |
25 | 0 | } |
26 | | // Construct a rectangle, remove part of it, then check the remainder |
27 | 0 | static void TestNonRectangular() { |
28 | 0 | nsRegion r(nsRect(0, 0, 30, 30)); |
29 | 0 |
|
30 | 0 | const int nTests = 19; |
31 | 0 | struct { |
32 | 0 | nsRect rect; |
33 | 0 | int64_t expectedArea; |
34 | 0 | } tests[nTests] = { |
35 | 0 | // Remove a 20x10 chunk from the square |
36 | 0 | { nsRect(0, 0, 20, 10), 600 }, |
37 | 0 | { nsRect(10, 0, 20, 10), 600 }, |
38 | 0 | { nsRect(10, 20, 20, 10), 600 }, |
39 | 0 | { nsRect(0, 20, 20, 10), 600 }, |
40 | 0 | // Remove a 10x20 chunk from the square |
41 | 0 | { nsRect(0, 0, 10, 20), 600 }, |
42 | 0 | { nsRect(20, 0, 10, 20), 600 }, |
43 | 0 | { nsRect(20, 10, 10, 20), 600 }, |
44 | 0 | { nsRect(0, 10, 10, 20), 600 }, |
45 | 0 | // Remove the center 10x10 |
46 | 0 | { nsRect(10, 10, 10, 10), 300 }, |
47 | 0 | // Remove the middle column |
48 | 0 | { nsRect(10, 0, 10, 30), 300 }, |
49 | 0 | // Remove the middle row |
50 | 0 | { nsRect(0, 10, 30, 10), 300 }, |
51 | 0 | // Remove the corners 10x10 |
52 | 0 | { nsRect(0, 0, 10, 10), 600 }, |
53 | 0 | { nsRect(20, 20, 10, 10), 600 }, |
54 | 0 | { nsRect(20, 0, 10, 10), 600 }, |
55 | 0 | { nsRect(0, 20, 10, 10), 600 }, |
56 | 0 | // Remove the corners 20x20 |
57 | 0 | { nsRect(0, 0, 20, 20), 300 }, |
58 | 0 | { nsRect(10, 10, 20, 20), 300 }, |
59 | 0 | { nsRect(10, 0, 20, 20), 300 }, |
60 | 0 | { nsRect(0, 10, 20, 20), 300 } |
61 | 0 | }; |
62 | 0 |
|
63 | 0 | for (int32_t i = 0; i < nTests; i++) { |
64 | 0 | nsRegion r2; |
65 | 0 | r2.Sub(r, tests[i].rect); |
66 | 0 |
|
67 | 0 | EXPECT_TRUE(r2.IsComplex()) << "nsRegion code got unexpectedly smarter!"; |
68 | 0 |
|
69 | 0 | nsRect largest = r2.GetLargestRectangle(); |
70 | 0 | EXPECT_TRUE(largest.Width() * largest.Height() == tests[i].expectedArea) << |
71 | 0 | "Did not successfully find largest rectangle in non-rectangular region on iteration " << i; |
72 | 0 | } |
73 | 0 |
|
74 | 0 | } |
75 | 0 | static void TwoRectTest() { |
76 | 0 | nsRegion r(nsRect(0, 0, 100, 100)); |
77 | 0 | const int nTests = 4; |
78 | 0 | struct { |
79 | 0 | nsRect rect1, rect2; |
80 | 0 | int64_t expectedArea; |
81 | 0 | } tests[nTests] = { |
82 | 0 | { nsRect(0, 0, 75, 40), nsRect(0, 60, 75, 40), 2500 }, |
83 | 0 | { nsRect(25, 0, 75, 40), nsRect(25, 60, 75, 40), 2500 }, |
84 | 0 | { nsRect(25, 0, 75, 40), nsRect(0, 60, 75, 40), 2000 }, |
85 | 0 | { nsRect(0, 0, 75, 40), nsRect(25, 60, 75, 40), 2000 }, |
86 | 0 | }; |
87 | 0 | for (int32_t i = 0; i < nTests; i++) { |
88 | 0 | nsRegion r2; |
89 | 0 |
|
90 | 0 | r2.Sub(r, tests[i].rect1); |
91 | 0 | r2.Sub(r2, tests[i].rect2); |
92 | 0 |
|
93 | 0 | EXPECT_TRUE(r2.IsComplex()) << "nsRegion code got unexpectedly smarter!"; |
94 | 0 |
|
95 | 0 | nsRect largest = r2.GetLargestRectangle(); |
96 | 0 | EXPECT_TRUE(largest.Width() * largest.Height() == tests[i].expectedArea) << |
97 | 0 | "Did not successfully find largest rectangle in two-rect-subtract region on iteration " << i; |
98 | 0 | } |
99 | 0 | } |
100 | 0 | static void TestContainsSpecifiedRect() { |
101 | 0 | nsRegion r(nsRect(0, 0, 100, 100)); |
102 | 0 | r.Or(r, nsRect(0, 300, 50, 50)); |
103 | 0 | EXPECT_TRUE(r.GetLargestRectangle(nsRect(0, 300, 10, 10)).IsEqualInterior(nsRect(0, 300, 50, 50))) << |
104 | 0 | "Chose wrong rectangle"; |
105 | 0 | } |
106 | 0 | static void TestContainsSpecifiedOverflowingRect() { |
107 | 0 | nsRegion r(nsRect(0, 0, 100, 100)); |
108 | 0 | r.Or(r, nsRect(0, 300, 50, 50)); |
109 | 0 | EXPECT_TRUE(r.GetLargestRectangle(nsRect(0, 290, 10, 20)).IsEqualInterior(nsRect(0, 300, 50, 50))) << |
110 | 0 | "Chose wrong rectangle"; |
111 | 0 | } |
112 | | }; |
113 | | |
114 | 0 | TEST(Gfx, RegionSingleRect) { |
115 | 0 | TestLargestRegion::TestSingleRect(nsRect(0, 52, 720, 480)); |
116 | 0 | TestLargestRegion::TestSingleRect(nsRect(-20, 40, 50, 20)); |
117 | 0 | TestLargestRegion::TestSingleRect(nsRect(-20, 40, 10, 8)); |
118 | 0 | TestLargestRegion::TestSingleRect(nsRect(-20, -40, 10, 8)); |
119 | 0 | TestLargestRegion::TestSingleRect(nsRect(-10, -10, 20, 20)); |
120 | 0 | } |
121 | | |
122 | 0 | TEST(Gfx, RegionNonRectangular) { |
123 | 0 | TestLargestRegion::TestNonRectangular(); |
124 | 0 | } |
125 | | |
126 | 0 | TEST(Gfx, RegionTwoRectTest) { |
127 | 0 | TestLargestRegion::TwoRectTest(); |
128 | 0 | } |
129 | | |
130 | 0 | TEST(Gfx, RegionContainsSpecifiedRect) { |
131 | 0 | TestLargestRegion::TestContainsSpecifiedRect(); |
132 | 0 | } |
133 | | |
134 | 0 | TEST(Gfx, RegionTestContainsSpecifiedOverflowingRect) { |
135 | 0 | TestLargestRegion::TestContainsSpecifiedOverflowingRect(); |
136 | 0 | } |
137 | | |
138 | 0 | TEST(Gfx, RegionScaleToInside) { |
139 | 0 | { // no rectangles |
140 | 0 | nsRegion r; |
141 | 0 |
|
142 | 0 | nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60); |
143 | 0 | nsIntRegion result; |
144 | 0 |
|
145 | 0 | EXPECT_TRUE(result.IsEqual(scaled)) << |
146 | 0 | "scaled result incorrect"; |
147 | 0 | } |
148 | 0 |
|
149 | 0 | { // one rectangle |
150 | 0 | nsRegion r(nsRect(0,44760,19096,264)); |
151 | 0 |
|
152 | 0 | nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60); |
153 | 0 | nsIntRegion result(mozilla::gfx::IntRect(0,746,318,4)); |
154 | 0 |
|
155 | 0 | EXPECT_TRUE(result.IsEqual(scaled)) << |
156 | 0 | "scaled result incorrect"; |
157 | 0 | } |
158 | 0 |
|
159 | 0 |
|
160 | 0 | { // the first rectangle gets adjusted |
161 | 0 | nsRegion r(nsRect(0,44760,19096,264)); |
162 | 0 | r.Or(r, nsRect(0,45024,19360,1056)); |
163 | 0 |
|
164 | 0 | nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60); |
165 | 0 | nsIntRegion result(mozilla::gfx::IntRect(0,746,318,5)); |
166 | 0 | result.Or(result, mozilla::gfx::IntRect(0,751,322,17)); |
167 | 0 |
|
168 | 0 | EXPECT_TRUE(result.IsEqual(scaled)) << |
169 | 0 | "scaled result incorrect"; |
170 | 0 | } |
171 | 0 |
|
172 | 0 | { // the second rectangle gets adjusted |
173 | 0 | nsRegion r(nsRect(0,44760,19360,264)); |
174 | 0 | r.Or(r, nsRect(0,45024,19096,1056)); |
175 | 0 |
|
176 | 0 | nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60); |
177 | 0 | nsIntRegion result(mozilla::gfx::IntRect(0,746,322,4)); |
178 | 0 | result.Or(result, mozilla::gfx::IntRect(0,750,318,18)); |
179 | 0 |
|
180 | 0 | EXPECT_TRUE(result.IsEqual(scaled)) << |
181 | 0 | "scaled result incorrect"; |
182 | 0 | } |
183 | 0 |
|
184 | 0 | } |
185 | | |
186 | | TEST(Gfx, RegionIsEqual) |
187 | 0 | { |
188 | 0 | { |
189 | 0 | nsRegion r(nsRect(0, 0, 50, 50)); |
190 | 0 | EXPECT_FALSE(nsRegion().IsEqual(r)); |
191 | 0 | } |
192 | 0 | { |
193 | 0 | nsRegion r1(nsRect(0, 0, 50, 50)); |
194 | 0 | nsRegion r2(nsRect(0, 0, 50, 50)); |
195 | 0 | EXPECT_TRUE(r1.IsEqual(r2)); |
196 | 0 | } |
197 | 0 | { |
198 | 0 | nsRegion r1(nsRect(0, 0, 50, 50)); |
199 | 0 | nsRegion r2(nsRect(0, 0, 60, 50)); |
200 | 0 | EXPECT_FALSE(r1.IsEqual(r2)); |
201 | 0 | } |
202 | 0 | { |
203 | 0 | nsRegion r1(nsRect(0, 0, 50, 50)); |
204 | 0 | r1.OrWith(nsRect(0, 60, 50, 50)); |
205 | 0 | nsRegion r2(nsRect(0, 0, 50, 50)); |
206 | 0 | r2.OrWith(nsRect(0, 60, 50, 50)); |
207 | 0 | EXPECT_TRUE(r1.IsEqual(r2)); |
208 | 0 | } |
209 | 0 | { |
210 | 0 | nsRegion r1(nsRect(0, 0, 50, 50)); |
211 | 0 | r1.OrWith(nsRect(0, 60, 50, 50)); |
212 | 0 | nsRegion r2(nsRect(0, 0, 50, 50)); |
213 | 0 | r2.OrWith(nsRect(0, 70, 50, 50)); |
214 | 0 | EXPECT_FALSE(r1.IsEqual(r2)); |
215 | 0 | } |
216 | 0 | { |
217 | 0 | nsRegion r1(nsRect(0, 0, 50, 50)); |
218 | 0 | r1.OrWith(nsRect(0, 60, 50, 50)); |
219 | 0 | r1.OrWith(nsRect(100, 60, 50, 50)); |
220 | 0 | nsRegion r2(nsRect(0, 0, 50, 50)); |
221 | 0 | r2.OrWith(nsRect(0, 60, 50, 50)); |
222 | 0 | EXPECT_FALSE(r1.IsEqual(r2)); |
223 | 0 | } |
224 | 0 | } |
225 | | |
226 | 0 | TEST(Gfx, RegionOrWith) { |
227 | 0 | PR_Sleep(PR_SecondsToInterval(10)); |
228 | 0 | { |
229 | 0 | nsRegion r(nsRect(11840, 11840, 4640, -10880)); |
230 | 0 | r.OrWith(nsRect(160, 160, 7720, 880)); |
231 | 0 | } |
232 | 0 | { |
233 | 0 | nsRegion r(nsRect(79, 31, 75, 12)); |
234 | 0 | r.OrWith(nsRect(22, 43, 132, 5)); |
235 | 0 | r.OrWith(nsRect(22, 48, 125, 3)); |
236 | 0 | r.OrWith(nsRect(22, 51, 96, 20)); |
237 | 0 | r.OrWith(nsRect(34, 71, 1, 14)); |
238 | 0 | r.OrWith(nsRect(26, 85, 53, 1)); |
239 | 0 | r.OrWith(nsRect(26, 86, 53, 4)); |
240 | 0 | r.OrWith(nsRect(96, 86, 30, 4)); |
241 | 0 | r.OrWith(nsRect(34, 90, 1, 2)); |
242 | 0 | r.OrWith(nsRect(96, 90, 30, 2)); |
243 | 0 | r.OrWith(nsRect(34, 92, 1, 3)); |
244 | 0 | r.OrWith(nsRect(49, 92, 34, 3)); |
245 | 0 | r.OrWith(nsRect(96, 92, 30, 3)); |
246 | 0 | r.OrWith(nsRect(34, 95, 1, 17)); |
247 | 0 | r.OrWith(nsRect(49, 95, 77, 17)); |
248 | 0 | r.OrWith(nsRect(34, 112, 1, 12)); |
249 | 0 | r.OrWith(nsRect(75, 112, 51, 12)); |
250 | 0 | r.OrWith(nsRect(34, 124, 1, 10)); |
251 | 0 | r.OrWith(nsRect(75, 124, 44, 10)); |
252 | 0 | r.OrWith(nsRect(34, 134, 1, 19)); |
253 | 0 | r.OrWith(nsRect(22, 17, 96, 27)); |
254 | 0 | } |
255 | 0 | { |
256 | 0 | nsRegion r(nsRect(0, 8, 257, 32)); |
257 | 0 | r.OrWith(nsRect(3702, 8, 138, 32)); |
258 | 0 | r.OrWith(nsRect(0, 40, 225, 1)); |
259 | 0 | r.OrWith(nsRect(3702, 40, 138, 1)); |
260 | 0 | r.OrWith(nsRect(0, 41, 101, 40)); |
261 | 0 | r.OrWith(nsRect(69, 41, 32, 40)); |
262 | 0 | } |
263 | 0 | { |
264 | 0 | nsRegion r(nsRect(79, 56, 8, 32)); |
265 | 0 | r.OrWith(nsRect(5, 94, 23, 81)); |
266 | 0 | r.OrWith(nsRect(56, 29, 91, 81)); |
267 | 0 | } |
268 | 0 | { |
269 | 0 | nsRegion r(nsRect(0, 82, 3840, 2046)); |
270 | 0 | r.OrWith(nsRect(0, 0, 3840, 82)); |
271 | 0 | } |
272 | 0 | { |
273 | 0 | nsRegion r(nsRect(2, 5, 600, 28)); |
274 | 0 | r.OrWith(nsRect(2, 82, 600, 19)); |
275 | 0 | r.OrWith(nsRect(2, 33, 600, 49)); |
276 | 0 | } |
277 | 0 | { |
278 | 0 | nsRegion r(nsRect(3823, 0, 17, 17)); |
279 | 0 | r.OrWith(nsRect(3823, 2029, 17, 17)); |
280 | 0 | r.OrWith(nsRect(3823, 0, 17, 2046)); |
281 | 0 | } |
282 | 0 | { |
283 | 0 | nsRegion r(nsRect(1036, 4, 32, 21)); |
284 | 0 | r.OrWith(nsRect(1070, 4, 66, 21)); |
285 | 0 | r.OrWith(nsRect(40, 5, 0, 33)); |
286 | 0 | } |
287 | 0 | { |
288 | 0 | nsRegion r(nsRect(0, 0, 1024, 1152)); |
289 | 0 | r.OrWith(nsRect(-335802, -1073741824, 1318851, 1860043520)); |
290 | 0 | } |
291 | 0 | { |
292 | 0 | nsRegion r(nsRect(0, 0, 800, 1000)); |
293 | 0 | r.OrWith(nsRect(0, 0, 536870912, 1073741824)); |
294 | 0 | } |
295 | 0 | { |
296 | 0 | nsRegion r(nsRect(53, 2, 52, 3)); |
297 | 0 | r.OrWith(nsRect(45, 5, 60, 16)); |
298 | 0 | r.OrWith(nsRect(16, 21, 8, 1)); |
299 | 0 | r.OrWith(nsRect(45, 21, 12, 1)); |
300 | 0 | r.OrWith(nsRect(16, 22, 8, 5)); |
301 | 0 | r.OrWith(nsRect(33, 22, 52, 5)); |
302 | 0 | r.OrWith(nsRect(16, 27, 8, 7)); |
303 | 0 | r.OrWith(nsRect(33, 27, 66, 7)); |
304 | 0 | r.OrWith(nsRect(0, 34, 99, 1)); |
305 | 0 | r.OrWith(nsRect(0, 35, 159, 27)); |
306 | 0 | r.OrWith(nsRect(0, 62, 122, 3)); |
307 | 0 | r.OrWith(nsRect(0, 65, 85, 11)); |
308 | 0 | r.OrWith(nsRect(91, 65, 97, 11)); |
309 | 0 | r.OrWith(nsRect(11, 76, 74, 2)); |
310 | 0 | r.OrWith(nsRect(91, 76, 97, 2)); |
311 | 0 | r.OrWith(nsRect(11, 78, 74, 12)); |
312 | 0 | r.OrWith(nsRect(11, 90, 13, 3)); |
313 | 0 | r.OrWith(nsRect(33, 90, 108, 3)); |
314 | 0 | r.OrWith(nsRect(16, 93, 8, 22)); |
315 | 0 | r.OrWith(nsRect(33, 93, 108, 22)); |
316 | 0 | r.OrWith(nsRect(16, 115, 8, 1)); |
317 | 0 | r.OrWith(nsRect(58, 115, 83, 1)); |
318 | 0 | r.OrWith(nsRect(58, 116, 83, 25)); |
319 | 0 | r.OrWith(nsRect(59, 37, 88, 92)); |
320 | 0 | } |
321 | | #ifdef REGION_RANDOM_STRESS_TESTS |
322 | | const uint32_t TestIterations = 100000; |
323 | | const uint32_t RectsPerTest = 100; |
324 | | |
325 | | nsRect rects[RectsPerTest]; |
326 | | |
327 | | for (uint32_t i = 0; i < TestIterations; i++) { |
328 | | nsRegion r; |
329 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
330 | | rects[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
331 | | } |
332 | | r.SetEmpty(); |
333 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
334 | | r.OrWith(rects[n]); |
335 | | } |
336 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
337 | | EXPECT_TRUE(r.Contains(rects[n])); |
338 | | } |
339 | | } |
340 | | #endif |
341 | | } |
342 | | |
343 | 0 | TEST(Gfx, RegionSubWith) { |
344 | 0 | { |
345 | 0 | nsRegion r1(nsRect(0, 0, 100, 50)); |
346 | 0 | r1.OrWith(nsRect(50, 50, 50, 50)); |
347 | 0 | nsRegion r2(nsRect(0, 0, 100, 50)); |
348 | 0 | r2.OrWith(nsRect(50, 50, 50, 50)); |
349 | 0 | r1.SubWith(r2); |
350 | 0 | EXPECT_FALSE(r1.Contains(1, 1)); |
351 | 0 | } |
352 | 0 | { |
353 | 0 | nsRegion r1(nsRect(0, 0, 800, 1000)); |
354 | 0 | nsRegion r2(nsRect(8, 108, 22, 20)); |
355 | 0 | r2.OrWith(nsRect(91, 138, 17, 18)); |
356 | 0 | r1.SubWith(r2); |
357 | 0 | EXPECT_TRUE(r1.Contains(400, 130)); |
358 | 0 | } |
359 | 0 | { |
360 | 0 | nsRegion r1(nsRect(392, 2, 28, 7)); |
361 | 0 | r1.OrWith(nsRect(115, 9, 305, 16)); |
362 | 0 | r1.OrWith(nsRect(392, 25, 28, 5)); |
363 | 0 | r1.OrWith(nsRect(0, 32, 1280, 41)); |
364 | 0 | nsRegion r2(nsRect(0, 0, 1280, 9)); |
365 | 0 | r2.OrWith(nsRect(0, 9, 115, 16)); |
366 | 0 | r2.OrWith(nsRect(331, 9, 949, 16)); |
367 | 0 | r2.OrWith(nsRect(0, 25, 1280, 7)); |
368 | 0 | r2.OrWith(nsRect(331, 32, 124, 1)); |
369 | 0 | r1.SubWith(r2); |
370 | 0 | EXPECT_FALSE(r1.Contains(350, 15)); |
371 | 0 | } |
372 | 0 | { |
373 | 0 | nsRegion r1(nsRect(552, 0, 2, 2)); |
374 | 0 | r1.OrWith(nsRect(362, 2, 222, 28)); |
375 | 0 | r1.OrWith(nsRect(552, 30, 2, 2)); |
376 | 0 | r1.OrWith(nsRect(0, 32, 1280, 41)); |
377 | 0 | nsRegion r2(nsRect(512, 0, 146, 9)); |
378 | 0 | r2.OrWith(nsRect(340, 9, 318, 16)); |
379 | 0 | r2.OrWith(nsRect(512, 25, 146, 8)); |
380 | 0 | r1.SubWith(r2); |
381 | 0 | EXPECT_FALSE(r1.Contains(350, 15)); |
382 | 0 | } |
383 | 0 | { |
384 | 0 | nsRegion r(nsRect(0, 0, 229380, 6780)); |
385 | 0 | r.OrWith(nsRect(76800, 6780, 76800, 4440)); |
386 | 0 | r.OrWith(nsRect(76800, 11220, 44082, 1800)); |
387 | 0 | r.OrWith(nsRect(122682, 11220, 30918, 1800)); |
388 | 0 | r.OrWith(nsRect(76800, 13020, 76800, 2340)); |
389 | 0 | r.OrWith(nsRect(85020, 15360, 59340, 75520)); |
390 | 0 | r.OrWith(nsRect(85020, 90880, 38622, 11332)); |
391 | 0 | r.OrWith(nsRect(143789, 90880, 571, 11332)); |
392 | 0 | r.OrWith(nsRect(85020, 102212, 59340, 960)); |
393 | 0 | r.OrWith(nsRect(85020, 103172, 38622, 1560)); |
394 | 0 | r.OrWith(nsRect(143789, 103172, 571, 1560)); |
395 | 0 | r.OrWith(nsRect(85020, 104732, 59340, 12292)); |
396 | 0 | r.OrWith(nsRect(85020, 117024, 38622, 1560)); |
397 | 0 | r.OrWith(nsRect(143789, 117024, 571, 1560)); |
398 | 0 | r.OrWith(nsRect(85020, 118584, 59340, 11976)); |
399 | 0 | r.SubWith(nsRect(123642, 89320, 20147, 1560)); |
400 | 0 | } |
401 | 0 | { |
402 | 0 | nsRegion r(nsRect(0, 0, 9480, 12900)); |
403 | 0 | r.OrWith(nsRect(0, 12900, 8460, 1020)); |
404 | 0 | r.SubWith(nsRect(8460, 0, 1020, 12900)); |
405 | 0 | } |
406 | 0 | { |
407 | 0 | nsRegion r1(nsRect(99, 1, 51, 2)); |
408 | 0 | r1.OrWith(nsRect(85, 3, 65, 1)); |
409 | 0 | r1.OrWith(nsRect(10, 4, 66, 5)); |
410 | 0 | r1.OrWith(nsRect(85, 4, 37, 5)); |
411 | 0 | r1.OrWith(nsRect(10, 9, 112, 3)); |
412 | 0 | r1.OrWith(nsRect(1, 12, 121, 1)); |
413 | 0 | r1.OrWith(nsRect(1, 13, 139, 3)); |
414 | 0 | r1.OrWith(nsRect(0, 16, 140, 3)); |
415 | 0 | r1.OrWith(nsRect(0, 19, 146, 3)); |
416 | 0 | r1.OrWith(nsRect(0, 22, 149, 2)); |
417 | 0 | r1.OrWith(nsRect(0, 24, 154, 2)); |
418 | 0 | r1.OrWith(nsRect(0, 26, 160, 23)); |
419 | 0 | r1.OrWith(nsRect(0, 49, 162, 31)); |
420 | 0 | r1.OrWith(nsRect(0, 80, 171, 19)); |
421 | 0 | r1.OrWith(nsRect(0, 99, 173, 11)); |
422 | 0 | r1.OrWith(nsRect(2, 110, 171, 6)); |
423 | 0 | r1.OrWith(nsRect(6, 116, 165, 5)); |
424 | 0 | r1.OrWith(nsRect(8, 121, 163, 1)); |
425 | 0 | r1.OrWith(nsRect(13, 122, 158, 11)); |
426 | 0 | r1.OrWith(nsRect(14, 133, 157, 23)); |
427 | 0 | r1.OrWith(nsRect(29, 156, 142, 10)); |
428 | 0 | r1.OrWith(nsRect(37, 166, 134, 6)); |
429 | 0 | r1.OrWith(nsRect(55, 172, 4, 4)); |
430 | 0 | r1.OrWith(nsRect(83, 172, 88, 4)); |
431 | 0 | r1.OrWith(nsRect(55, 176, 4, 2)); |
432 | 0 | r1.OrWith(nsRect(89, 176, 6, 2)); |
433 | 0 | r1.OrWith(nsRect(89, 178, 6, 4)); |
434 | 0 | nsRegion r2(nsRect(63, 11, 39, 11)); |
435 | 0 | r2.OrWith(nsRect(63, 22, 99, 16)); |
436 | 0 | r2.OrWith(nsRect(37, 38, 125, 61)); |
437 | 0 | r2.OrWith(nsRect(45, 99, 117, 8)); |
438 | 0 | r2.OrWith(nsRect(47, 107, 115, 7)); |
439 | 0 | r2.OrWith(nsRect(47, 114, 66, 1)); |
440 | 0 | r2.OrWith(nsRect(49, 115, 64, 2)); |
441 | 0 | r2.OrWith(nsRect(49, 117, 54, 30)); |
442 | 0 | r1.SubWith(r2); |
443 | 0 | } |
444 | 0 | { |
445 | 0 | nsRegion r1(nsRect(95, 2, 47, 1)); |
446 | 0 | r1.OrWith(nsRect(62, 3, 80, 2)); |
447 | 0 | r1.OrWith(nsRect(1, 5, 18, 3)); |
448 | 0 | r1.OrWith(nsRect(48, 5, 94, 3)); |
449 | 0 | r1.OrWith(nsRect(1, 8, 18, 3)); |
450 | 0 | r1.OrWith(nsRect(23, 8, 119, 3)); |
451 | 0 | r1.OrWith(nsRect(1, 11, 172, 9)); |
452 | 0 | r1.OrWith(nsRect(1, 20, 18, 8)); |
453 | 0 | r1.OrWith(nsRect(20, 20, 153, 8)); |
454 | 0 | r1.OrWith(nsRect(1, 28, 172, 13)); |
455 | 0 | r1.OrWith(nsRect(1, 41, 164, 1)); |
456 | 0 | r1.OrWith(nsRect(1, 42, 168, 1)); |
457 | 0 | r1.OrWith(nsRect(0, 43, 169, 15)); |
458 | 0 | r1.OrWith(nsRect(1, 58, 168, 26)); |
459 | 0 | r1.OrWith(nsRect(1, 84, 162, 2)); |
460 | 0 | r1.OrWith(nsRect(1, 86, 165, 23)); |
461 | 0 | r1.OrWith(nsRect(1, 109, 162, 23)); |
462 | 0 | r1.OrWith(nsRect(1, 132, 152, 4)); |
463 | 0 | r1.OrWith(nsRect(1, 136, 150, 12)); |
464 | 0 | r1.OrWith(nsRect(12, 148, 139, 4)); |
465 | 0 | r1.OrWith(nsRect(12, 152, 113, 2)); |
466 | 0 | r1.OrWith(nsRect(14, 154, 31, 3)); |
467 | 0 | r1.OrWith(nsRect(82, 154, 43, 3)); |
468 | 0 | r1.OrWith(nsRect(17, 157, 13, 19)); |
469 | 0 | r1.OrWith(nsRect(82, 157, 43, 19)); |
470 | 0 | r1.OrWith(nsRect(17, 176, 13, 16)); |
471 | 0 | nsRegion r2(nsRect(97, 9, 6, 10)); |
472 | 0 | r2.OrWith(nsRect(71, 19, 32, 2)); |
473 | 0 | r2.OrWith(nsRect(20, 21, 83, 2)); |
474 | 0 | r2.OrWith(nsRect(2, 23, 101, 9)); |
475 | 0 | r2.OrWith(nsRect(2, 32, 98, 1)); |
476 | 0 | r2.OrWith(nsRect(2, 33, 104, 5)); |
477 | 0 | r2.OrWith(nsRect(2, 38, 118, 2)); |
478 | 0 | r2.OrWith(nsRect(15, 40, 9, 11)); |
479 | 0 | r2.OrWith(nsRect(36, 40, 84, 11)); |
480 | 0 | r2.OrWith(nsRect(4, 51, 116, 33)); |
481 | 0 | r2.OrWith(nsRect(4, 84, 159, 8)); |
482 | 0 | r2.OrWith(nsRect(4, 92, 116, 13)); |
483 | 0 | r2.OrWith(nsRect(15, 105, 9, 7)); |
484 | 0 | r2.OrWith(nsRect(36, 105, 84, 7)); |
485 | 0 | r2.OrWith(nsRect(36, 112, 84, 22)); |
486 | 0 | r2.OrWith(nsRect(71, 134, 39, 46)); |
487 | 0 | r1.SubWith(r2); |
488 | 0 | } |
489 | | #ifdef REGION_RANDOM_STRESS_TESTS |
490 | | const uint32_t TestIterations = 100000; |
491 | | const uint32_t RectsPerTest = 100; |
492 | | const uint32_t SubRectsPerTest = 10; |
493 | | |
494 | | nsRect rects[RectsPerTest]; |
495 | | nsRect subRects[SubRectsPerTest]; |
496 | | |
497 | | for (uint32_t i = 0; i < TestIterations; i++) { |
498 | | nsRegion r; |
499 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
500 | | rects[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
501 | | } |
502 | | r.SetEmpty(); |
503 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
504 | | r.OrWith(rects[n]); |
505 | | } |
506 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
507 | | EXPECT_TRUE(r.Contains(rects[n])); |
508 | | } |
509 | | for (uint32_t n = 0; n < SubRectsPerTest; n++) { |
510 | | subRects[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
511 | | } |
512 | | for (uint32_t n = 0; n < SubRectsPerTest; n++) { |
513 | | r.SubWith(subRects[n]); |
514 | | } |
515 | | for (uint32_t n = 0; n < SubRectsPerTest; n++) { |
516 | | EXPECT_FALSE(r.Contains(subRects[n].x, subRects[n].y)); |
517 | | EXPECT_FALSE(r.Contains(subRects[n].x, subRects[n].YMost() - 1)); |
518 | | EXPECT_FALSE(r.Contains(subRects[n].XMost() - 1, subRects[n].YMost() - 1)); |
519 | | EXPECT_FALSE(r.Contains(subRects[n].XMost() - 1, subRects[n].Y())); |
520 | | } |
521 | | } |
522 | | for (uint32_t i = 0; i < TestIterations; i++) { |
523 | | nsRegion r; |
524 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
525 | | rects[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
526 | | } |
527 | | r.SetEmpty(); |
528 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
529 | | r.OrWith(rects[n]); |
530 | | } |
531 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
532 | | EXPECT_TRUE(r.Contains(rects[n])); |
533 | | } |
534 | | for (uint32_t n = 0; n < SubRectsPerTest; n++) { |
535 | | subRects[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
536 | | } |
537 | | nsRegion r2; |
538 | | for (uint32_t n = 0; n < SubRectsPerTest; n++) { |
539 | | r2.OrWith(subRects[n]); |
540 | | } |
541 | | r.SubWith(r2); |
542 | | |
543 | | for (uint32_t n = 0; n < SubRectsPerTest; n++) { |
544 | | EXPECT_FALSE(r.Contains(subRects[n].x, subRects[n].y)); |
545 | | EXPECT_FALSE(r.Contains(subRects[n].x, subRects[n].YMost() - 1)); |
546 | | EXPECT_FALSE(r.Contains(subRects[n].XMost() - 1, subRects[n].YMost() - 1)); |
547 | | EXPECT_FALSE(r.Contains(subRects[n].XMost() - 1, subRects[n].Y())); |
548 | | } |
549 | | } |
550 | | for (uint32_t i = 0; i < TestIterations; i++) { |
551 | | nsRegion r(nsRect(-1, -1, 202, 202)); |
552 | | for (uint32_t n = 0; n < SubRectsPerTest; n++) { |
553 | | subRects[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
554 | | r.SubWith(subRects[n]); |
555 | | } |
556 | | for (uint32_t n = 0; n < SubRectsPerTest; n++) { |
557 | | EXPECT_FALSE(r.Contains(subRects[n].x, subRects[n].y)); |
558 | | EXPECT_FALSE(r.Contains(subRects[n].x, subRects[n].YMost() - 1)); |
559 | | EXPECT_FALSE(r.Contains(subRects[n].XMost() - 1, subRects[n].YMost() - 1)); |
560 | | EXPECT_FALSE(r.Contains(subRects[n].XMost() - 1, subRects[n].Y())); |
561 | | } |
562 | | EXPECT_TRUE(r.Contains(-1, -1)); |
563 | | EXPECT_TRUE(r.Contains(-1, 200)); |
564 | | EXPECT_TRUE(r.Contains(200, -1)); |
565 | | EXPECT_TRUE(r.Contains(200, 200)); |
566 | | } |
567 | | for (uint32_t i = 0; i < TestIterations; i++) { |
568 | | nsRegion r(nsRect(-1, -1, 202, 202)); |
569 | | nsRegion r2; |
570 | | for (uint32_t n = 0; n < SubRectsPerTest; n++) { |
571 | | subRects[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
572 | | r2.OrWith(subRects[n]); |
573 | | } |
574 | | r.SubWith(r2); |
575 | | for (uint32_t n = 0; n < SubRectsPerTest; n++) { |
576 | | EXPECT_FALSE(r.Contains(subRects[n].x, subRects[n].y)); |
577 | | EXPECT_FALSE(r.Contains(subRects[n].x, subRects[n].YMost() - 1)); |
578 | | EXPECT_FALSE(r.Contains(subRects[n].XMost() - 1, subRects[n].YMost() - 1)); |
579 | | EXPECT_FALSE(r.Contains(subRects[n].XMost() - 1, subRects[n].Y())); |
580 | | } |
581 | | EXPECT_TRUE(r.Contains(-1, -1)); |
582 | | EXPECT_TRUE(r.Contains(-1, 200)); |
583 | | EXPECT_TRUE(r.Contains(200, -1)); |
584 | | EXPECT_TRUE(r.Contains(200, 200)); |
585 | | } |
586 | | #endif |
587 | | } |
588 | 0 | TEST(Gfx, RegionSub) { |
589 | 0 | { |
590 | 0 | nsRegion r1(nsRect(0, 0, 100, 50)); |
591 | 0 | r1.OrWith(nsRect(50, 50, 50, 50)); |
592 | 0 | nsRegion r2(nsRect(0, 0, 100, 50)); |
593 | 0 | r2.OrWith(nsRect(50, 50, 50, 50)); |
594 | 0 | nsRegion r3; |
595 | 0 | r3.Sub(r1, r2); |
596 | 0 | EXPECT_FALSE(r3.Contains(1, 1)); |
597 | 0 | } |
598 | 0 | { |
599 | 0 | nsRegion r1(nsRect(0, 0, 800, 1000)); |
600 | 0 | nsRegion r2(nsRect(8, 108, 22, 20)); |
601 | 0 | r2.OrWith(nsRect(91, 138, 17, 18)); |
602 | 0 | nsRegion r3; |
603 | 0 | r3.Sub(r1, r2); |
604 | 0 | EXPECT_TRUE(r3.Contains(400, 130)); |
605 | 0 | } |
606 | 0 | { |
607 | 0 | nsRegion r1(nsRect(392, 2, 28, 7)); |
608 | 0 | r1.OrWith(nsRect(115, 9, 305, 16)); |
609 | 0 | r1.OrWith(nsRect(392, 25, 28, 5)); |
610 | 0 | r1.OrWith(nsRect(0, 32, 1280, 41)); |
611 | 0 | nsRegion r2(nsRect(0, 0, 1280, 9)); |
612 | 0 | r2.OrWith(nsRect(0, 9, 115, 16)); |
613 | 0 | r2.OrWith(nsRect(331, 9, 949, 16)); |
614 | 0 | r2.OrWith(nsRect(0, 25, 1280, 7)); |
615 | 0 | r2.OrWith(nsRect(331, 32, 124, 1)); |
616 | 0 | nsRegion r3; |
617 | 0 | r3.Sub(r1, r2); |
618 | 0 | EXPECT_FALSE(r3.Contains(350, 15)); |
619 | 0 | } |
620 | 0 | { |
621 | 0 | nsRegion r1(nsRect(552, 0, 2, 2)); |
622 | 0 | r1.OrWith(nsRect(362, 2, 222, 28)); |
623 | 0 | r1.OrWith(nsRect(552, 30, 2, 2)); |
624 | 0 | r1.OrWith(nsRect(0, 32, 1280, 41)); |
625 | 0 | nsRegion r2(nsRect(512, 0, 146, 9)); |
626 | 0 | r2.OrWith(nsRect(340, 9, 318, 16)); |
627 | 0 | r2.OrWith(nsRect(512, 25, 146, 8)); |
628 | 0 | nsRegion r3; |
629 | 0 | r3.Sub(r1, r2); |
630 | 0 | EXPECT_FALSE(r3.Contains(350, 15)); |
631 | 0 | } |
632 | 0 | { |
633 | 0 | nsRegion r1(nsRect(0, 0, 1265, 1024)); |
634 | 0 | nsRegion r2(nsRect(1265, 0, 15, 685)); |
635 | 0 | r2.OrWith(nsRect(0, 714, 1280, 221)); |
636 | 0 | nsRegion r3; |
637 | 0 | r3.Sub(r1, r2); |
638 | 0 | } |
639 | 0 | { |
640 | 0 | nsRegion r1(nsRect(6, 0, 64, 1)); |
641 | 0 | r1.OrWith(nsRect(6, 1, 67, 1)); |
642 | 0 | r1.OrWith(nsRect(6, 2, 67, 2)); |
643 | 0 | r1.OrWith(nsRect(79, 2, 67, 2)); |
644 | 0 | r1.OrWith(nsRect(6, 4, 67, 1)); |
645 | 0 | r1.OrWith(nsRect(79, 4, 98, 1)); |
646 | 0 | r1.OrWith(nsRect(6, 5, 171, 18)); |
647 | 0 | r1.OrWith(nsRect(1, 23, 176, 3)); |
648 | 0 | r1.OrWith(nsRect(1, 26, 178, 5)); |
649 | 0 | r1.OrWith(nsRect(1, 31, 176, 9)); |
650 | 0 | r1.OrWith(nsRect(0, 40, 177, 57)); |
651 | 0 | r1.OrWith(nsRect(0, 97, 176, 33)); |
652 | 0 | r1.OrWith(nsRect(0, 130, 12, 17)); |
653 | 0 | r1.OrWith(nsRect(15, 130, 161, 17)); |
654 | 0 | r1.OrWith(nsRect(0, 147, 12, 5)); |
655 | 0 | r1.OrWith(nsRect(15, 147, 111, 5)); |
656 | 0 | r1.OrWith(nsRect(0, 152, 12, 7)); |
657 | 0 | r1.OrWith(nsRect(17, 152, 109, 7)); |
658 | 0 | r1.OrWith(nsRect(0, 159, 12, 2)); |
659 | 0 | r1.OrWith(nsRect(17, 159, 98, 2)); |
660 | 0 | r1.OrWith(nsRect(17, 161, 98, 9)); |
661 | 0 | r1.OrWith(nsRect(27, 170, 63, 21)); |
662 | 0 | nsRegion r2(nsRect(9, 9, 37, 17)); |
663 | 0 | r2.OrWith(nsRect(92, 9, 26, 17)); |
664 | 0 | r2.OrWith(nsRect(9, 26, 37, 9)); |
665 | 0 | r2.OrWith(nsRect(84, 26, 65, 9)); |
666 | 0 | r2.OrWith(nsRect(9, 35, 37, 2)); |
667 | 0 | r2.OrWith(nsRect(51, 35, 98, 2)); |
668 | 0 | r2.OrWith(nsRect(51, 37, 98, 11)); |
669 | 0 | r2.OrWith(nsRect(51, 48, 78, 4)); |
670 | 0 | r2.OrWith(nsRect(87, 52, 42, 7)); |
671 | 0 | r2.OrWith(nsRect(19, 59, 12, 5)); |
672 | 0 | r2.OrWith(nsRect(87, 59, 42, 5)); |
673 | 0 | r2.OrWith(nsRect(19, 64, 12, 9)); |
674 | 0 | r2.OrWith(nsRect(32, 64, 97, 9)); |
675 | 0 | r2.OrWith(nsRect(19, 73, 12, 2)); |
676 | 0 | r2.OrWith(nsRect(32, 73, 104, 2)); |
677 | 0 | r2.OrWith(nsRect(19, 75, 117, 5)); |
678 | 0 | r2.OrWith(nsRect(18, 80, 118, 5)); |
679 | 0 | r2.OrWith(nsRect(18, 85, 111, 38)); |
680 | 0 | r2.OrWith(nsRect(87, 123, 42, 11)); |
681 | 0 | nsRegion r3; |
682 | 0 | r3.Sub(r1, r2); |
683 | 0 | } |
684 | 0 | { |
685 | 0 | nsRegion r1(nsRect(27, 0, 39, 1)); |
686 | 0 | r1.OrWith(nsRect(86, 0, 22, 1)); |
687 | 0 | r1.OrWith(nsRect(27, 1, 43, 1)); |
688 | 0 | r1.OrWith(nsRect(86, 1, 22, 1)); |
689 | 0 | r1.OrWith(nsRect(27, 2, 43, 1)); |
690 | 0 | r1.OrWith(nsRect(86, 2, 75, 1)); |
691 | 0 | r1.OrWith(nsRect(12, 3, 58, 1)); |
692 | 0 | r1.OrWith(nsRect(86, 3, 75, 1)); |
693 | 0 | r1.OrWith(nsRect(12, 4, 149, 5)); |
694 | 0 | r1.OrWith(nsRect(0, 9, 161, 9)); |
695 | 0 | r1.OrWith(nsRect(0, 18, 167, 17)); |
696 | 0 | r1.OrWith(nsRect(0, 35, 171, 5)); |
697 | 0 | r1.OrWith(nsRect(0, 40, 189, 28)); |
698 | 0 | r1.OrWith(nsRect(0, 68, 171, 16)); |
699 | 0 | r1.OrWith(nsRect(4, 84, 167, 5)); |
700 | 0 | r1.OrWith(nsRect(4, 89, 177, 9)); |
701 | 0 | r1.OrWith(nsRect(1, 98, 180, 59)); |
702 | 0 | r1.OrWith(nsRect(4, 157, 177, 1)); |
703 | 0 | r1.OrWith(nsRect(4, 158, 139, 15)); |
704 | 0 | r1.OrWith(nsRect(17, 173, 126, 2)); |
705 | 0 | r1.OrWith(nsRect(20, 175, 123, 2)); |
706 | 0 | r1.OrWith(nsRect(20, 177, 118, 6)); |
707 | 0 | r1.OrWith(nsRect(20, 183, 84, 2)); |
708 | 0 | nsRegion r2(nsRect(64, 2, 30, 6)); |
709 | 0 | r2.OrWith(nsRect(26, 11, 41, 17)); |
710 | 0 | r2.OrWith(nsRect(19, 28, 48, 23)); |
711 | 0 | r2.OrWith(nsRect(19, 51, 76, 8)); |
712 | 0 | r2.OrWith(nsRect(4, 59, 91, 31)); |
713 | 0 | r2.OrWith(nsRect(19, 90, 76, 29)); |
714 | 0 | r2.OrWith(nsRect(33, 119, 62, 25)); |
715 | 0 | r2.OrWith(nsRect(33, 144, 4, 21)); |
716 | 0 | nsRegion r3; |
717 | 0 | r3.Sub(r1, r2); |
718 | 0 | } |
719 | | #ifdef REGION_RANDOM_STRESS_TESTS |
720 | | const uint32_t TestIterations = 100000; |
721 | | const uint32_t RectsPerTest = 100; |
722 | | const uint32_t SubRectsPerTest = 10; |
723 | | |
724 | | nsRect rects[RectsPerTest]; |
725 | | nsRect subRects[SubRectsPerTest]; |
726 | | |
727 | | for (uint32_t i = 0; i < TestIterations; i++) { |
728 | | nsRegion r; |
729 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
730 | | rects[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
731 | | } |
732 | | r.SetEmpty(); |
733 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
734 | | r.OrWith(rects[n]); |
735 | | } |
736 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
737 | | EXPECT_TRUE(r.Contains(rects[n])); |
738 | | } |
739 | | for (uint32_t n = 0; n < SubRectsPerTest; n++) { |
740 | | subRects[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
741 | | } |
742 | | nsRegion r2; |
743 | | for (uint32_t n = 0; n < SubRectsPerTest; n++) { |
744 | | r2.OrWith(subRects[n]); |
745 | | } |
746 | | nsRegion r3; |
747 | | r3.Sub(r, r2); |
748 | | |
749 | | for (uint32_t n = 0; n < SubRectsPerTest; n++) { |
750 | | EXPECT_FALSE(r3.Contains(subRects[n].x, subRects[n].y)); |
751 | | EXPECT_FALSE(r3.Contains(subRects[n].x, subRects[n].YMost() - 1)); |
752 | | EXPECT_FALSE(r3.Contains(subRects[n].XMost() - 1, subRects[n].YMost() - 1)); |
753 | | EXPECT_FALSE(r3.Contains(subRects[n].XMost() - 1, subRects[n].Y())); |
754 | | } |
755 | | } |
756 | | for (uint32_t i = 0; i < TestIterations; i++) { |
757 | | nsRegion r(nsRect(-1, -1, 202, 202)); |
758 | | nsRegion r2; |
759 | | for (uint32_t n = 0; n < SubRectsPerTest; n++) { |
760 | | subRects[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
761 | | r2.OrWith(subRects[n]); |
762 | | } |
763 | | nsRegion r3; |
764 | | r3.Sub(r, r2); |
765 | | for (uint32_t n = 0; n < SubRectsPerTest; n++) { |
766 | | EXPECT_FALSE(r3.Contains(subRects[n].x, subRects[n].y)); |
767 | | EXPECT_FALSE(r3.Contains(subRects[n].x, subRects[n].YMost() - 1)); |
768 | | EXPECT_FALSE(r3.Contains(subRects[n].XMost() - 1, subRects[n].YMost() - 1)); |
769 | | EXPECT_FALSE(r3.Contains(subRects[n].XMost() - 1, subRects[n].Y())); |
770 | | } |
771 | | EXPECT_TRUE(r3.Contains(-1, -1)); |
772 | | EXPECT_TRUE(r3.Contains(-1, 200)); |
773 | | EXPECT_TRUE(r3.Contains(200, -1)); |
774 | | EXPECT_TRUE(r3.Contains(200, 200)); |
775 | | } |
776 | | #endif |
777 | | } |
778 | | |
779 | 0 | TEST(Gfx, RegionAndWith) { |
780 | 0 | { |
781 | 0 | nsRegion r(nsRect(20, 0, 20, 20)); |
782 | 0 | r.OrWith(nsRect(0, 20, 40, 20)); |
783 | 0 | r.AndWith(nsRect(0, 0, 5, 5)); |
784 | 0 | EXPECT_FALSE(r.Contains(1, 1)); |
785 | 0 | } |
786 | 0 | { |
787 | 0 | nsRegion r1(nsRect(512, 1792, 256, 256)); |
788 | 0 | nsRegion r2(nsRect(17, 1860, 239, 35)); |
789 | 0 | r2.OrWith(nsRect(17, 1895, 239, 7)); |
790 | 0 | r2.OrWith(nsRect(768, 1895, 154, 7)); |
791 | 0 | r2.OrWith(nsRect(17, 1902, 905, 483)); |
792 | 0 | r1.AndWith(r2); |
793 | 0 | } |
794 | | #ifdef REGION_RANDOM_STRESS_TESTS |
795 | | const uint32_t TestIterations = 100000; |
796 | | const uint32_t RectsPerTest = 50; |
797 | | const uint32_t pointsTested = 100; |
798 | | |
799 | | { |
800 | | nsRect rectsSet1[RectsPerTest]; |
801 | | nsRect rectsSet2[RectsPerTest]; |
802 | | |
803 | | for (uint32_t i = 0; i < TestIterations; i++) { |
804 | | nsRegion r1; |
805 | | nsRegion r2; |
806 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
807 | | rectsSet1[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
808 | | rectsSet2[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
809 | | r1.OrWith(rectsSet1[n]); |
810 | | r2.OrWith(rectsSet1[n]); |
811 | | } |
812 | | |
813 | | nsRegion r3 = r1; |
814 | | r3.AndWith(r2); |
815 | | |
816 | | for (uint32_t n = 0; n < pointsTested; n++) { |
817 | | nsPoint p(rand() % 200, rand() % 200); |
818 | | if (r1.Contains(p.x, p.y) && r2.Contains(p.x, p.y)) { |
819 | | EXPECT_TRUE(r3.Contains(p.x, p.y)); |
820 | | } else { |
821 | | EXPECT_FALSE(r3.Contains(p.x, p.y)); |
822 | | } |
823 | | } |
824 | | } |
825 | | } |
826 | | |
827 | | { |
828 | | nsRect rectsSet[RectsPerTest]; |
829 | | nsRect testRect; |
830 | | for (uint32_t i = 0; i < TestIterations; i++) { |
831 | | nsRegion r; |
832 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
833 | | rectsSet[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
834 | | } |
835 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
836 | | r.OrWith(rectsSet[n]); |
837 | | } |
838 | | testRect.SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
839 | | |
840 | | nsRegion r2 = r; |
841 | | r2.AndWith(testRect); |
842 | | |
843 | | for (uint32_t n = 0; n < pointsTested; n++) { |
844 | | nsPoint p(rand() % 200, rand() % 200); |
845 | | if (r.Contains(p.x, p.y) && testRect.Contains(p.x, p.y)) { |
846 | | EXPECT_TRUE(r2.Contains(p.x, p.y)); |
847 | | } else { |
848 | | EXPECT_FALSE(r2.Contains(p.x, p.y)); |
849 | | } |
850 | | } |
851 | | } |
852 | | } |
853 | | #endif |
854 | | } |
855 | | |
856 | 0 | TEST(Gfx, RegionAnd) { |
857 | 0 | { |
858 | 0 | nsRegion r(nsRect(20, 0, 20, 20)); |
859 | 0 | r.OrWith(nsRect(0, 20, 40, 20)); |
860 | 0 | nsRegion r2; |
861 | 0 | r2.And(r, nsRect(0, 0, 5, 5)); |
862 | 0 | EXPECT_FALSE(r.Contains(1, 1)); |
863 | 0 | } |
864 | 0 | { |
865 | 0 | nsRegion r(nsRect(51, 2, 57, 5)); |
866 | 0 | r.OrWith(nsRect(36, 7, 72, 4)); |
867 | 0 | r.OrWith(nsRect(36, 11, 25, 1)); |
868 | 0 | r.OrWith(nsRect(69, 12, 6, 4)); |
869 | 0 | r.OrWith(nsRect(37, 16, 54, 2)); |
870 | 0 | r.OrWith(nsRect(37, 18, 82, 2)); |
871 | 0 | r.OrWith(nsRect(10, 20, 109, 3)); |
872 | 0 | r.OrWith(nsRect(1, 23, 136, 21)); |
873 | 0 | r.OrWith(nsRect(1, 44, 148, 2)); |
874 | 0 | r.OrWith(nsRect(1, 46, 176, 31)); |
875 | 0 | r.OrWith(nsRect(6, 77, 171, 1)); |
876 | 0 | r.OrWith(nsRect(5, 78, 172, 30)); |
877 | 0 | r.OrWith(nsRect(5, 108, 165, 45)); |
878 | 0 | r.OrWith(nsRect(5, 153, 61, 5)); |
879 | 0 | r.OrWith(nsRect(72, 153, 98, 5)); |
880 | 0 | r.OrWith(nsRect(38, 158, 25, 4)); |
881 | 0 | r.OrWith(nsRect(72, 158, 98, 4)); |
882 | 0 | r.OrWith(nsRect(58, 162, 5, 8)); |
883 | 0 | r.OrWith(nsRect(72, 162, 98, 8)); |
884 | 0 | r.OrWith(nsRect(72, 170, 98, 5)); |
885 | 0 | nsRegion r2; |
886 | 0 | r.And(r2, nsRect(18, 78, 53, 45)); |
887 | 0 | } |
888 | | #ifdef REGION_RANDOM_STRESS_TESTS |
889 | | const uint32_t TestIterations = 100000; |
890 | | const uint32_t RectsPerTest = 50; |
891 | | const uint32_t pointsTested = 100; |
892 | | |
893 | | { |
894 | | nsRect rectsSet1[RectsPerTest]; |
895 | | nsRect rectsSet2[RectsPerTest]; |
896 | | |
897 | | for (uint32_t i = 0; i < TestIterations; i++) { |
898 | | nsRegion r1; |
899 | | nsRegion r2; |
900 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
901 | | rectsSet1[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
902 | | rectsSet2[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
903 | | r1.OrWith(rectsSet1[n]); |
904 | | r2.OrWith(rectsSet1[n]); |
905 | | } |
906 | | |
907 | | nsRegion r3; |
908 | | r3.And(r1, r2); |
909 | | |
910 | | for (uint32_t n = 0; n < pointsTested; n++) { |
911 | | nsPoint p(rand() % 200, rand() % 200); |
912 | | if (r1.Contains(p.x, p.y) && r2.Contains(p.x, p.y)) { |
913 | | EXPECT_TRUE(r3.Contains(p.x, p.y)); |
914 | | } else { |
915 | | EXPECT_FALSE(r3.Contains(p.x, p.y)); |
916 | | } |
917 | | } |
918 | | } |
919 | | } |
920 | | |
921 | | { |
922 | | nsRect rectsSet[RectsPerTest]; |
923 | | nsRect testRect; |
924 | | for (uint32_t i = 0; i < TestIterations; i++) { |
925 | | nsRegion r; |
926 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
927 | | rectsSet[n].SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
928 | | } |
929 | | for (uint32_t n = 0; n < RectsPerTest; n++) { |
930 | | r.OrWith(rectsSet[n]); |
931 | | } |
932 | | testRect.SetRect(rand() % 100, rand() % 100, rand() % 99 + 1, rand() % 99 + 1); |
933 | | |
934 | | nsRegion r2; |
935 | | r2.And(r, testRect); |
936 | | |
937 | | for (uint32_t n = 0; n < pointsTested; n++) { |
938 | | nsPoint p(rand() % 200, rand() % 200); |
939 | | if (r.Contains(p.x, p.y) && testRect.Contains(p.x, p.y)) { |
940 | | EXPECT_TRUE(r2.Contains(p.x, p.y)); |
941 | | } else { |
942 | | EXPECT_FALSE(r2.Contains(p.x, p.y)); |
943 | | } |
944 | | } |
945 | | } |
946 | | } |
947 | | #endif |
948 | | } |
949 | | |
950 | 0 | TEST(Gfx, RegionSimplify) { |
951 | 0 | { // ensure simplify works on a single rect |
952 | 0 | nsRegion r(nsRect(0,100,200,100)); |
953 | 0 |
|
954 | 0 | r.SimplifyOutwardByArea(100*100); |
955 | 0 |
|
956 | 0 | nsRegion result(nsRect(0,100,200,100)); |
957 | 0 |
|
958 | 0 | EXPECT_TRUE(r.IsEqual(result)) << |
959 | 0 | "regions not the same"; |
960 | 0 | } |
961 | 0 |
|
962 | 0 | { // the rectangles will be merged |
963 | 0 | nsRegion r(nsRect(0,100,200,100)); |
964 | 0 | r.Or(r, nsRect(0,200,300,200)); |
965 | 0 |
|
966 | 0 | r.SimplifyOutwardByArea(100*100); |
967 | 0 |
|
968 | 0 | nsRegion result(nsRect(0,100,300,300)); |
969 | 0 |
|
970 | 0 | EXPECT_TRUE(r.IsEqual(result)) << |
971 | 0 | "regions not merged"; |
972 | 0 | } |
973 | 0 |
|
974 | 0 | { // two rectangle on the first span |
975 | 0 | // one on the second |
976 | 0 | nsRegion r(nsRect(0,100,200,100)); |
977 | 0 | r.Or(r, nsRect(0,200,300,200)); |
978 | 0 | r.Or(r, nsRect(250,100,50,100)); |
979 | 0 |
|
980 | 0 | EXPECT_TRUE(r.GetNumRects() == 3) << |
981 | 0 | "wrong number of rects"; |
982 | 0 |
|
983 | 0 | r.SimplifyOutwardByArea(100*100); |
984 | 0 |
|
985 | 0 | nsRegion result(nsRect(0,100,300,300)); |
986 | 0 |
|
987 | 0 | EXPECT_TRUE(r.IsEqual(result)) << |
988 | 0 | "regions not merged"; |
989 | 0 | } |
990 | 0 |
|
991 | 0 | { // the rectangles will be merged |
992 | 0 | nsRegion r(nsRect(0,100,200,100)); |
993 | 0 | r.Or(r, nsRect(0,200,300,200)); |
994 | 0 | r.Or(r, nsRect(250,100,50,100)); |
995 | 0 | r.Sub(r, nsRect(200,200,40,200)); |
996 | 0 |
|
997 | 0 | EXPECT_TRUE(r.GetNumRects() == 4) << |
998 | 0 | "wrong number of rects"; |
999 | 0 |
|
1000 | 0 | r.SimplifyOutwardByArea(100*100); |
1001 | 0 |
|
1002 | 0 | nsRegion result(nsRect(0,100,300,300)); |
1003 | 0 | result.Sub(result, nsRect(200,100,40,300)); |
1004 | 0 |
|
1005 | 0 | EXPECT_TRUE(r.IsEqual(result)) << |
1006 | 0 | "regions not merged"; |
1007 | 0 | } |
1008 | 0 |
|
1009 | 0 | { // three spans of rectangles |
1010 | 0 | nsRegion r(nsRect(0,100,200,100)); |
1011 | 0 | r.Or(r, nsRect(0,200,300,200)); |
1012 | 0 | r.Or(r, nsRect(250,100,50,50)); |
1013 | 0 | r.Sub(r, nsRect(200,200,40,200)); |
1014 | 0 |
|
1015 | 0 | r.SimplifyOutwardByArea(100*100); |
1016 | 0 |
|
1017 | 0 | nsRegion result(nsRect(0,100,300,300)); |
1018 | 0 | result.Sub(result, nsRect(200,100,40,300)); |
1019 | 0 |
|
1020 | 0 | EXPECT_TRUE(r.IsEqual(result)) << |
1021 | 0 | "regions not merged"; |
1022 | 0 | } |
1023 | 0 |
|
1024 | 0 | { // three spans of rectangles and an unmerged rectangle |
1025 | 0 | nsRegion r(nsRect(0,100,200,100)); |
1026 | 0 | r.Or(r, nsRect(0,200,300,200)); |
1027 | 0 | r.Or(r, nsRect(250,100,50,50)); |
1028 | 0 | r.Sub(r, nsRect(200,200,40,200)); |
1029 | 0 | r.Or(r, nsRect(250,900,150,50)); |
1030 | 0 |
|
1031 | 0 | r.SimplifyOutwardByArea(100*100); |
1032 | 0 |
|
1033 | 0 | nsRegion result(nsRect(0,100,300,300)); |
1034 | 0 | result.Sub(result, nsRect(200,100,40,300)); |
1035 | 0 | result.Or(result, nsRect(250,900,150,50)); |
1036 | 0 |
|
1037 | 0 | EXPECT_TRUE(r.IsEqual(result)) << |
1038 | 0 | "regions not merged"; |
1039 | 0 | } |
1040 | 0 |
|
1041 | 0 | { // unmerged regions |
1042 | 0 | nsRegion r(nsRect(0,100,200,100)); |
1043 | 0 | r.Or(r, nsRect(0,200,300,200)); |
1044 | 0 |
|
1045 | 0 | r.SimplifyOutwardByArea(100); |
1046 | 0 |
|
1047 | 0 | nsRegion result(nsRect(0,100,200,100)); |
1048 | 0 | result.Or(result, nsRect(0,200,300,200)); |
1049 | 0 |
|
1050 | 0 | EXPECT_TRUE(r.IsEqual(result)) << |
1051 | 0 | "regions not merged"; |
1052 | 0 | } |
1053 | 0 |
|
1054 | 0 | { // empty region |
1055 | 0 | // just make sure this doesn't crash. |
1056 | 0 | nsRegion r; |
1057 | 0 | r.SimplifyOutwardByArea(100); |
1058 | 0 | } |
1059 | 0 | } |
1060 | | |
1061 | | TEST(Gfx, RegionContains) |
1062 | 0 | { |
1063 | 0 | { // ensure Contains works on a simple region |
1064 | 0 | nsRegion r(nsRect(0, 0, 100, 100)); |
1065 | 0 |
|
1066 | 0 | EXPECT_TRUE(r.Contains(0, 0)); |
1067 | 0 | EXPECT_TRUE(r.Contains(0, 99)); |
1068 | 0 | EXPECT_TRUE(r.Contains(99, 0)); |
1069 | 0 | EXPECT_TRUE(r.Contains(99, 99)); |
1070 | 0 |
|
1071 | 0 | EXPECT_FALSE(r.Contains(-1, 50)); |
1072 | 0 | EXPECT_FALSE(r.Contains(100, 50)); |
1073 | 0 | EXPECT_FALSE(r.Contains(50, -1)); |
1074 | 0 | EXPECT_FALSE(r.Contains(50, 100)); |
1075 | 0 |
|
1076 | 0 | EXPECT_TRUE(r.Contains(nsRect(0, 0, 100, 100))); |
1077 | 0 | EXPECT_TRUE(r.Contains(nsRect(99, 99, 1, 1))); |
1078 | 0 |
|
1079 | 0 | EXPECT_FALSE(r.Contains(nsRect(100, 100, 1, 1))); |
1080 | 0 | EXPECT_FALSE(r.Contains(nsRect(100, 100, 0, 0))); |
1081 | 0 | } |
1082 | 0 |
|
1083 | 0 | { // empty regions contain nothing |
1084 | 0 | nsRegion r(nsRect(100, 100, 0, 0)); |
1085 | 0 |
|
1086 | 0 | EXPECT_FALSE(r.Contains(0, 0)); |
1087 | 0 | EXPECT_FALSE(r.Contains(100, 100)); |
1088 | 0 | EXPECT_FALSE(r.Contains(nsRect(100, 100, 0, 0))); |
1089 | 0 | EXPECT_FALSE(r.Contains(nsRect(100, 100, 1, 1))); |
1090 | 0 | } |
1091 | 0 |
|
1092 | 0 | { // complex region contain tests |
1093 | 0 | // The region looks like this, with two squares that overlap. |
1094 | 0 | // (hard to do accurately with ASCII art) |
1095 | 0 | // +------+ |
1096 | 0 | // | | |
1097 | 0 | // | +--+ |
1098 | 0 | // | | |
1099 | 0 | // +--+ | |
1100 | 0 | // | | |
1101 | 0 | // +------+ |
1102 | 0 | nsRegion r(nsRect(0, 0, 100, 100)); |
1103 | 0 | r.OrWith(nsRect(50, 50, 100, 100)); |
1104 | 0 |
|
1105 | 0 | EXPECT_TRUE(r.Contains(0, 0)); |
1106 | 0 | EXPECT_TRUE(r.Contains(99, 99)); |
1107 | 0 | EXPECT_TRUE(r.Contains(50, 100)); |
1108 | 0 | EXPECT_TRUE(r.Contains(100, 50)); |
1109 | 0 | EXPECT_TRUE(r.Contains(149, 149)); |
1110 | 0 |
|
1111 | 0 | EXPECT_FALSE(r.Contains(49, 100)); |
1112 | 0 | EXPECT_FALSE(r.Contains(100, 49)); |
1113 | 0 | EXPECT_FALSE(r.Contains(150, 150)); |
1114 | 0 |
|
1115 | 0 | EXPECT_TRUE(r.Contains(nsRect(100, 100, 1, 1))); |
1116 | 0 | EXPECT_FALSE(r.Contains(nsRect(49, 99, 2, 2))); |
1117 | 0 | } |
1118 | 0 |
|
1119 | 0 | { // region with a hole |
1120 | 0 | nsRegion r(nsRect(0, 0, 100, 100)); |
1121 | 0 | r.SubOut(nsRect(40, 40, 10, 10)); |
1122 | 0 |
|
1123 | 0 | EXPECT_TRUE(r.Contains(0, 0)); |
1124 | 0 | EXPECT_TRUE(r.Contains(39, 39)); |
1125 | 0 | EXPECT_FALSE(r.Contains(40, 40)); |
1126 | 0 | EXPECT_FALSE(r.Contains(49, 49)); |
1127 | 0 | EXPECT_TRUE(r.Contains(50, 50)); |
1128 | 0 |
|
1129 | 0 | EXPECT_FALSE(r.Contains(nsRect(40, 40, 10, 10))); |
1130 | 0 | EXPECT_FALSE(r.Contains(nsRect(39, 39, 2, 2))); |
1131 | 0 | } |
1132 | 0 | } |
1133 | | |
1134 | 0 | #define DILATE_VALUE 0x88 |
1135 | 0 | #define REGION_VALUE 0xff |
1136 | | |
1137 | | struct RegionBitmap { |
1138 | 0 | RegionBitmap(unsigned char *bitmap, int width, int height) : bitmap(bitmap), width(width), height(height) {} |
1139 | | |
1140 | 0 | void clear() { |
1141 | 0 | for (int y = 0; y < height; y++) { |
1142 | 0 | for (int x = 0; x < width; x++) { |
1143 | 0 | bitmap[x + y * width] = 0; |
1144 | 0 | } |
1145 | 0 | } |
1146 | 0 | } |
1147 | | |
1148 | 0 | void set(nsRegion ®ion) { |
1149 | 0 | clear(); |
1150 | 0 | for (auto iter = region.RectIter(); !iter.Done(); iter.Next()) { |
1151 | 0 | const nsRect& r = iter.Get(); |
1152 | 0 | for (int y = r.Y(); y < r.YMost(); y++) { |
1153 | 0 | for (int x = r.X(); x < r.XMost(); x++) { |
1154 | 0 | bitmap[x + y * width] = REGION_VALUE; |
1155 | 0 | } |
1156 | 0 | } |
1157 | 0 | } |
1158 | 0 | } |
1159 | | |
1160 | 0 | void dilate() { |
1161 | 0 | for (int y = 0; y < height; y++) { |
1162 | 0 | for (int x = 0; x < width; x++) { |
1163 | 0 | if (bitmap[x + y * width] == REGION_VALUE) { |
1164 | 0 | for (int yn = max(y - 1, 0); yn <= min(y + 1, height - 1); yn++) { |
1165 | 0 | for (int xn = max(x - 1, 0); xn <= min(x + 1, width - 1); xn++) { |
1166 | 0 | if (bitmap[xn + yn * width] == 0) |
1167 | 0 | bitmap[xn + yn * width] = DILATE_VALUE; |
1168 | 0 | } |
1169 | 0 | } |
1170 | 0 | } |
1171 | 0 | } |
1172 | 0 | } |
1173 | 0 | } |
1174 | 0 | void compare(RegionBitmap &reference) { |
1175 | 0 | for (int y = 0; y < height; y++) { |
1176 | 0 | for (int x = 0; x < width; x++) { |
1177 | 0 | EXPECT_EQ(bitmap[x + y * width], reference.bitmap[x + y * width]); |
1178 | 0 | } |
1179 | 0 | } |
1180 | 0 | } |
1181 | | |
1182 | | unsigned char *bitmap; |
1183 | | int width; |
1184 | | int height; |
1185 | | }; |
1186 | | |
1187 | | void VisitEdge(void *closure, VisitSide side, int x1, int y1, int x2, int y2) |
1188 | 0 | { |
1189 | 0 | EXPECT_GE(x2, x1); |
1190 | 0 | RegionBitmap *visitor = static_cast<RegionBitmap*>(closure); |
1191 | 0 | unsigned char *bitmap = visitor->bitmap; |
1192 | 0 | const int width = visitor->width; |
1193 | 0 |
|
1194 | 0 | if (side == VisitSide::TOP) { |
1195 | 0 | while (x1 != x2) { |
1196 | 0 | bitmap[x1 + (y1 - 1) * width] = DILATE_VALUE; |
1197 | 0 | x1++; |
1198 | 0 | } |
1199 | 0 | } else if (side == VisitSide::BOTTOM) { |
1200 | 0 | while (x1 != x2) { |
1201 | 0 | bitmap[x1 + y1 * width] = DILATE_VALUE; |
1202 | 0 | x1++; |
1203 | 0 | } |
1204 | 0 | } else if (side == VisitSide::LEFT) { |
1205 | 0 | while (y1 != y2) { |
1206 | 0 | bitmap[x1 - 1 + y1 *width] = DILATE_VALUE; |
1207 | 0 | y1++; |
1208 | 0 | } |
1209 | 0 | } else if (side == VisitSide::RIGHT) { |
1210 | 0 | while (y1 != y2) { |
1211 | 0 | bitmap[x1 + y1 * width] = DILATE_VALUE; |
1212 | 0 | y1++; |
1213 | 0 | } |
1214 | 0 | } |
1215 | 0 | } |
1216 | | |
1217 | | void TestVisit(nsRegion &r) |
1218 | 0 | { |
1219 | 0 | auto reference = mozilla::MakeUnique<unsigned char[]>(600 * 600); |
1220 | 0 | auto result = mozilla::MakeUnique<unsigned char[]>(600 * 600); |
1221 | 0 | RegionBitmap ref(reference.get(), 600, 600); |
1222 | 0 | RegionBitmap res(result.get(), 600, 600); |
1223 | 0 |
|
1224 | 0 | ref.set(r); |
1225 | 0 | ref.dilate(); |
1226 | 0 |
|
1227 | 0 | res.set(r); |
1228 | 0 | r.VisitEdges(VisitEdge, &res); |
1229 | 0 | res.compare(ref); |
1230 | 0 | } |
1231 | | |
1232 | 0 | TEST(Gfx, RegionVisitEdges) { |
1233 | 0 | { // visit edges |
1234 | 0 | nsRegion r(nsRect(20, 20, 100, 100)); |
1235 | 0 | r.Or(r, nsRect(20, 120, 200, 100)); |
1236 | 0 | TestVisit(r); |
1237 | 0 | } |
1238 | 0 |
|
1239 | 0 | { // two rects side by side - 1 pixel inbetween |
1240 | 0 | nsRegion r(nsRect(20, 20, 100, 100)); |
1241 | 0 | r.Or(r, nsRect(121, 20, 100, 100)); |
1242 | 0 | TestVisit(r); |
1243 | 0 | } |
1244 | 0 |
|
1245 | 0 | { // two rects side by side - 2 pixels inbetween |
1246 | 0 | nsRegion r(nsRect(20, 20, 100, 100)); |
1247 | 0 | r.Or(r, nsRect(122, 20, 100, 100)); |
1248 | 0 | TestVisit(r); |
1249 | 0 | } |
1250 | 0 |
|
1251 | 0 | { |
1252 | 0 | // only corner of the rects are touching |
1253 | 0 | nsRegion r(nsRect(20, 20, 100, 100)); |
1254 | 0 | r.Or(r, nsRect(120, 120, 100, 100)); |
1255 | 0 |
|
1256 | 0 | TestVisit(r); |
1257 | 0 | } |
1258 | 0 |
|
1259 | 0 | { |
1260 | 0 | // corners are 1 pixel away |
1261 | 0 | nsRegion r(nsRect(20, 20, 100, 100)); |
1262 | 0 | r.Or(r, nsRect(121, 120, 100, 100)); |
1263 | 0 |
|
1264 | 0 | TestVisit(r); |
1265 | 0 | } |
1266 | 0 |
|
1267 | 0 | { |
1268 | 0 | // vertically separated |
1269 | 0 | nsRegion r(nsRect(20, 20, 100, 100)); |
1270 | 0 | r.Or(r, nsRect(120, 125, 100, 100)); |
1271 | 0 |
|
1272 | 0 | TestVisit(r); |
1273 | 0 | } |
1274 | 0 |
|
1275 | 0 | { |
1276 | 0 | // not touching |
1277 | 0 | nsRegion r(nsRect(20, 20, 100, 100)); |
1278 | 0 | r.Or(r, nsRect(130, 120, 100, 100)); |
1279 | 0 | r.Or(r, nsRect(240, 20, 100, 100)); |
1280 | 0 |
|
1281 | 0 | TestVisit(r); |
1282 | 0 | } |
1283 | 0 |
|
1284 | 0 | { // rect with a hole in it |
1285 | 0 | nsRegion r(nsRect(20, 20, 100, 100)); |
1286 | 0 | r.Sub(r, nsRect(40, 40, 10, 10)); |
1287 | 0 |
|
1288 | 0 | TestVisit(r); |
1289 | 0 | } |
1290 | 0 | { |
1291 | 0 | // left overs |
1292 | 0 | nsRegion r(nsRect(20, 20, 10, 10)); |
1293 | 0 | r.Or(r, nsRect(50, 20, 10, 10)); |
1294 | 0 | r.Or(r, nsRect(90, 20, 10, 10)); |
1295 | 0 | r.Or(r, nsRect(24, 30, 10, 10)); |
1296 | 0 | r.Or(r, nsRect(20, 40, 15, 10)); |
1297 | 0 | r.Or(r, nsRect(50, 40, 15, 10)); |
1298 | 0 | r.Or(r, nsRect(90, 40, 15, 10)); |
1299 | 0 |
|
1300 | 0 | TestVisit(r); |
1301 | 0 | } |
1302 | 0 |
|
1303 | 0 | { |
1304 | 0 | // vertically separated |
1305 | 0 | nsRegion r(nsRect(20, 20, 100, 100)); |
1306 | 0 | r.Or(r, nsRect(120, 125, 100, 100)); |
1307 | 0 |
|
1308 | 0 | TestVisit(r); |
1309 | 0 | } |
1310 | 0 |
|
1311 | 0 | { |
1312 | 0 | // two upper rects followed by a lower one |
1313 | 0 | // on the same line |
1314 | 0 | nsRegion r(nsRect(5, 5, 50, 50)); |
1315 | 0 | r.Or(r, nsRect(100, 5, 50, 50)); |
1316 | 0 | r.Or(r, nsRect(200, 50, 50, 50)); |
1317 | 0 |
|
1318 | 0 | TestVisit(r); |
1319 | 0 | } |
1320 | 0 |
|
1321 | 0 | { |
1322 | 0 | // bug 1130978. |
1323 | 0 | nsRegion r(nsRect(4, 1, 61, 49)); |
1324 | 0 | r.Or(r, nsRect(115, 1, 99, 49)); |
1325 | 0 | r.Or(r, nsRect(115, 49, 99, 1)); |
1326 | 0 | r.Or(r, nsRect(12, 50, 11, 5)); |
1327 | 0 | r.Or(r, nsRect(25, 50, 28, 5)); |
1328 | 0 | r.Or(r, nsRect(115, 50, 99, 5)); |
1329 | 0 | r.Or(r, nsRect(115, 55, 99, 12)); |
1330 | 0 |
|
1331 | 0 | TestVisit(r); |
1332 | 0 | } |
1333 | 0 | } |
1334 | | |
1335 | | // The TiledRegion tests use nsIntRect / IntRegion because nsRect doesn't have |
1336 | | // InflateToMultiple which is required by TiledRegion. |
1337 | 0 | TEST(Gfx, TiledRegionNoSimplification2Rects) { |
1338 | 0 | // Add two rectangles, both rectangles are completely inside |
1339 | 0 | // different tiles. |
1340 | 0 | nsIntRegion region; |
1341 | 0 | region.OrWith(nsIntRect(50, 50, 50, 50)); |
1342 | 0 | region.OrWith(nsIntRect(300, 50, 50, 50)); |
1343 | 0 |
|
1344 | 0 | TiledIntRegion tiledRegion; |
1345 | 0 | tiledRegion.Add(nsIntRect(50, 50, 50, 50)); |
1346 | 0 | tiledRegion.Add(nsIntRect(300, 50, 50, 50)); |
1347 | 0 |
|
1348 | 0 | // No simplification should have happened. |
1349 | 0 | EXPECT_TRUE(region.IsEqual(tiledRegion.GetRegion())); |
1350 | 0 | } |
1351 | | |
1352 | 0 | TEST(Gfx, TiledRegionNoSimplification1Region) { |
1353 | 0 | // Add two rectangles, both rectangles are completely inside |
1354 | 0 | // different tiles. |
1355 | 0 | nsIntRegion region; |
1356 | 0 | region.OrWith(nsIntRect(50, 50, 50, 50)); |
1357 | 0 | region.OrWith(nsIntRect(300, 50, 50, 50)); |
1358 | 0 |
|
1359 | 0 | TiledIntRegion tiledRegion; |
1360 | 0 | tiledRegion.Add(region); |
1361 | 0 |
|
1362 | 0 | // No simplification should have happened. |
1363 | 0 | EXPECT_TRUE(region.IsEqual(tiledRegion.GetRegion())); |
1364 | 0 | } |
1365 | | |
1366 | 0 | TEST(Gfx, TiledRegionWithSimplification3Rects) { |
1367 | 0 | // Add three rectangles. The first two rectangles are completely inside |
1368 | 0 | // different tiles, but the third rectangle intersects both tiles. |
1369 | 0 | TiledIntRegion tiledRegion; |
1370 | 0 | tiledRegion.Add(nsIntRect(50, 50, 50, 50)); |
1371 | 0 | tiledRegion.Add(nsIntRect(300, 50, 50, 50)); |
1372 | 0 | tiledRegion.Add(nsIntRect(250, 70, 10, 10)); |
1373 | 0 |
|
1374 | 0 | // Both tiles should have simplified their rectangles, and those two |
1375 | 0 | // rectangles are adjacent to each other, so they just build up one rect. |
1376 | 0 | EXPECT_TRUE(tiledRegion.GetRegion().IsEqual(nsIntRect(50, 50, 300, 50))); |
1377 | 0 | } |
1378 | | |
1379 | 0 | TEST(Gfx, TiledRegionWithSimplification1Region) { |
1380 | 0 | // Add three rectangles. The first two rectangles are completely inside |
1381 | 0 | // different tiles, but the third rectangle intersects both tiles. |
1382 | 0 | nsIntRegion region; |
1383 | 0 | region.OrWith(nsIntRect(50, 50, 50, 50)); |
1384 | 0 | region.OrWith(nsIntRect(300, 50, 50, 50)); |
1385 | 0 | region.OrWith(nsIntRect(250, 70, 10, 10)); |
1386 | 0 |
|
1387 | 0 | TiledIntRegion tiledRegion; |
1388 | 0 | tiledRegion.Add(region); |
1389 | 0 |
|
1390 | 0 | // Both tiles should have simplified their rectangles, and those two |
1391 | 0 | // rectangles are adjacent to each other, so they just build up one rect. |
1392 | 0 | EXPECT_TRUE(tiledRegion.GetRegion().IsEqual(nsIntRect(50, 50, 300, 50))); |
1393 | 0 | } |
1394 | | |
1395 | 0 | TEST(Gfx, TiledRegionContains) { |
1396 | 0 | // Add three rectangles. The first two rectangles are completely inside |
1397 | 0 | // different tiles, but the third rectangle intersects both tiles. |
1398 | 0 | TiledIntRegion tiledRegion; |
1399 | 0 | tiledRegion.Add(nsIntRect(50, 50, 50, 50)); |
1400 | 0 | tiledRegion.Add(nsIntRect(300, 50, 50, 50)); |
1401 | 0 | tiledRegion.Add(nsIntRect(250, 70, 10, 10)); |
1402 | 0 |
|
1403 | 0 | // Both tiles should have simplified their rectangles, and those two |
1404 | 0 | // rectangles are adjacent to each other, so they just build up one rect. |
1405 | 0 | EXPECT_TRUE(tiledRegion.Contains(nsIntRect(50, 50, 300, 50))); |
1406 | 0 | EXPECT_TRUE(tiledRegion.Contains(nsIntRect(50, 50, 50, 50))); |
1407 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(50, 50, 301, 50))); |
1408 | 0 | } |
1409 | | |
1410 | 0 | TEST(Gfx, TiledRegionIntersects) { |
1411 | 0 | // Add three rectangles. The first two rectangles are completely inside |
1412 | 0 | // different tiles, but the third rectangle intersects both tiles. |
1413 | 0 | TiledIntRegion tiledRegion; |
1414 | 0 | tiledRegion.Add(nsIntRect(50, 50, 50, 50)); |
1415 | 0 | tiledRegion.Add(nsIntRect(300, 50, 50, 50)); |
1416 | 0 | tiledRegion.Add(nsIntRect(250, 70, 10, 10)); |
1417 | 0 |
|
1418 | 0 | // Both tiles should have simplified their rectangles, and those two |
1419 | 0 | // rectangles are adjacent to each other, so they just build up one rect. |
1420 | 0 | EXPECT_TRUE(tiledRegion.Intersects(nsIntRect(50, 50, 300, 50))); |
1421 | 0 | EXPECT_TRUE(tiledRegion.Intersects(nsIntRect(200, 10, 10, 50))); |
1422 | 0 | EXPECT_TRUE(tiledRegion.Intersects(nsIntRect(50, 50, 301, 50))); |
1423 | 0 | EXPECT_FALSE(tiledRegion.Intersects(nsIntRect(0, 0, 50, 500))); |
1424 | 0 | } |
1425 | | |
1426 | 0 | TEST(Gfx, TiledRegionBoundaryConditions1) { |
1427 | 0 | TiledIntRegion tiledRegion; |
1428 | 0 | // This one works fine |
1429 | 0 | tiledRegion.Add(nsIntRegion(nsIntRect(INT_MIN, INT_MIN, 1, 1))); |
1430 | 0 | EXPECT_TRUE(tiledRegion.Contains(nsIntRect(INT_MIN, INT_MIN, 1, 1))); |
1431 | 0 |
|
1432 | 0 | // This causes the tiledRegion.mBounds to overflow, so it is ignored |
1433 | 0 | tiledRegion.Add(nsIntRegion(nsIntRect(INT_MAX - 1, INT_MAX - 1, 1, 1))); |
1434 | 0 |
|
1435 | 0 | // Verify that the tiledRegion contains only things we expect |
1436 | 0 | EXPECT_TRUE(tiledRegion.Contains(nsIntRect(INT_MIN, INT_MIN, 1, 1))); |
1437 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(INT_MAX - 1, INT_MAX - 1, 1, 1))); |
1438 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(0, 0, 1, 1))); |
1439 | 0 | } |
1440 | | |
1441 | 0 | TEST(Gfx, TiledRegionBoundaryConditions2) { |
1442 | 0 | TiledIntRegion tiledRegion; |
1443 | 0 | // This one works fine |
1444 | 0 | tiledRegion.Add(nsIntRegion(nsIntRect(INT_MAX - 1, INT_MIN, 1, 1))); |
1445 | 0 | EXPECT_TRUE(tiledRegion.Contains(nsIntRect(INT_MAX - 1, INT_MIN, 1, 1))); |
1446 | 0 |
|
1447 | 0 | // As with TiledRegionBoundaryConditions1, this overflows, so it is ignored |
1448 | 0 | tiledRegion.Add(nsIntRegion(nsIntRect(INT_MIN, INT_MAX - 1, 1, 1))); |
1449 | 0 | EXPECT_TRUE(tiledRegion.Contains(nsIntRect(INT_MAX - 1, INT_MIN, 1, 1))); |
1450 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(INT_MIN, INT_MAX - 1, 1, 1))); |
1451 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(0, 0, 1, 1))); |
1452 | 0 | } |
1453 | | |
1454 | 0 | TEST(Gfx, TiledRegionBigRects) { |
1455 | 0 | TiledIntRegion tiledRegion; |
1456 | 0 | // Super wide region, forces simplification into bounds mode |
1457 | 0 | tiledRegion.Add(nsIntRegion(nsIntRect(INT_MIN, INT_MIN, INT_MAX, 100))); |
1458 | 0 | EXPECT_TRUE(tiledRegion.Contains(nsIntRect(INT_MIN, INT_MIN, 1, 1))); |
1459 | 0 | EXPECT_TRUE(tiledRegion.Contains(nsIntRect(-2, INT_MIN + 99, 1, 1))); |
1460 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(-2, INT_MIN + 100, 1, 1))); |
1461 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(-1, INT_MIN + 99, 1, 1))); |
1462 | 0 |
|
1463 | 0 | // Add another rect, verify that simplification caused the entire bounds |
1464 | 0 | // to expand by a lot more. |
1465 | 0 | tiledRegion.Add(nsIntRegion(nsIntRect(INT_MIN, INT_MIN + 200, 1, 1))); |
1466 | 0 | EXPECT_TRUE(tiledRegion.Contains(nsIntRect(-2, INT_MIN + 100, 1, 1))); |
1467 | 0 | EXPECT_TRUE(tiledRegion.Contains(nsIntRect(-2, INT_MIN + 200, 1, 1))); |
1468 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(-2, INT_MIN + 201, 1, 1))); |
1469 | 0 | } |
1470 | | |
1471 | 0 | TEST(Gfx, TiledRegionBoundaryOverflow) { |
1472 | 0 | TiledIntRegion tiledRegion; |
1473 | 0 | tiledRegion.Add(nsIntRegion(nsIntRect(100, 100, 1, 1))); |
1474 | 0 | EXPECT_TRUE(tiledRegion.Contains(nsIntRect(100, 100, 1, 1))); |
1475 | 0 |
|
1476 | 0 | // The next region is invalid, so it gets ignored |
1477 | 0 | tiledRegion.Add(nsIntRegion(nsIntRect(INT_MAX, INT_MAX, 1, 1))); |
1478 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(INT_MAX, INT_MAX, 1, 1))); |
1479 | 0 |
|
1480 | 0 | // Try that again as a rect, it will also get ignored |
1481 | 0 | tiledRegion.Add(nsIntRect(INT_MAX, INT_MAX, 1, 1)); |
1482 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(INT_MAX, INT_MAX, 1, 1))); |
1483 | 0 |
|
1484 | 0 | // Try with a bigger overflowing rect |
1485 | 0 | tiledRegion.Add(nsIntRect(INT_MAX, INT_MAX, 500, 500)); |
1486 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(INT_MIN, INT_MIN, 10, 10))); |
1487 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(INT_MAX, INT_MAX, 100, 100))); |
1488 | 0 |
|
1489 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(0, 0, 1, 1))); |
1490 | 0 | } |
1491 | | |
1492 | 0 | TEST(Gfx, TiledRegionNegativeRect) { |
1493 | 0 | TiledIntRegion tiledRegion; |
1494 | 0 | // The next region is invalid, so it gets ignored |
1495 | 0 | tiledRegion.Add(nsIntRegion(nsIntRect(0, 0, -500, -500))); |
1496 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(-50, -50, 1, 1))); |
1497 | 0 | // Rects with negative widths/heights are treated as empty and ignored |
1498 | 0 | tiledRegion.Add(nsIntRect(0, 0, -500, -500)); |
1499 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(-1, -1, 1, 1))); |
1500 | 0 | EXPECT_FALSE(tiledRegion.Contains(nsIntRect(0, 0, 1, 1))); |
1501 | 0 | // Empty rects are always contained |
1502 | 0 | EXPECT_TRUE(tiledRegion.Contains(nsIntRect(0, 0, -1, -1))); |
1503 | 0 | EXPECT_TRUE(tiledRegion.Contains(nsIntRect(100, 100, -1, -1))); |
1504 | 0 | } |