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