tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }