Coverage Report

Created: 2018-09-25 14:53

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