|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "gtest/gtest.h" |
|
7 #include "nsRegion.h" |
|
8 |
|
9 class TestLargestRegion { |
|
10 public: |
|
11 static void TestSingleRect(nsRect r) { |
|
12 nsRegion region(r); |
|
13 EXPECT_TRUE(region.GetLargestRectangle().IsEqualInterior(r)); |
|
14 } |
|
15 // Construct a rectangle, remove part of it, then check the remainder |
|
16 static void TestNonRectangular() { |
|
17 nsRegion r(nsRect(0, 0, 30, 30)); |
|
18 |
|
19 const int nTests = 19; |
|
20 struct { |
|
21 nsRect rect; |
|
22 int64_t expectedArea; |
|
23 } tests[nTests] = { |
|
24 // Remove a 20x10 chunk from the square |
|
25 { nsRect(0, 0, 20, 10), 600 }, |
|
26 { nsRect(10, 0, 20, 10), 600 }, |
|
27 { nsRect(10, 20, 20, 10), 600 }, |
|
28 { nsRect(0, 20, 20, 10), 600 }, |
|
29 // Remove a 10x20 chunk from the square |
|
30 { nsRect(0, 0, 10, 20), 600 }, |
|
31 { nsRect(20, 0, 10, 20), 600 }, |
|
32 { nsRect(20, 10, 10, 20), 600 }, |
|
33 { nsRect(0, 10, 10, 20), 600 }, |
|
34 // Remove the center 10x10 |
|
35 { nsRect(10, 10, 10, 10), 300 }, |
|
36 // Remove the middle column |
|
37 { nsRect(10, 0, 10, 30), 300 }, |
|
38 // Remove the middle row |
|
39 { nsRect(0, 10, 30, 10), 300 }, |
|
40 // Remove the corners 10x10 |
|
41 { nsRect(0, 0, 10, 10), 600 }, |
|
42 { nsRect(20, 20, 10, 10), 600 }, |
|
43 { nsRect(20, 0, 10, 10), 600 }, |
|
44 { nsRect(0, 20, 10, 10), 600 }, |
|
45 // Remove the corners 20x20 |
|
46 { nsRect(0, 0, 20, 20), 300 }, |
|
47 { nsRect(10, 10, 20, 20), 300 }, |
|
48 { nsRect(10, 0, 20, 20), 300 }, |
|
49 { nsRect(0, 10, 20, 20), 300 } |
|
50 }; |
|
51 |
|
52 for (int32_t i = 0; i < nTests; i++) { |
|
53 nsRegion r2; |
|
54 r2.Sub(r, tests[i].rect); |
|
55 |
|
56 EXPECT_TRUE(r2.IsComplex()) << "nsRegion code got unexpectedly smarter!"; |
|
57 |
|
58 nsRect largest = r2.GetLargestRectangle(); |
|
59 EXPECT_TRUE(largest.width * largest.height == tests[i].expectedArea) << |
|
60 "Did not successfully find largest rectangle in non-rectangular region on iteration " << i; |
|
61 } |
|
62 |
|
63 } |
|
64 static void TwoRectTest() { |
|
65 nsRegion r(nsRect(0, 0, 100, 100)); |
|
66 const int nTests = 4; |
|
67 struct { |
|
68 nsRect rect1, rect2; |
|
69 int64_t expectedArea; |
|
70 } tests[nTests] = { |
|
71 { nsRect(0, 0, 75, 40), nsRect(0, 60, 75, 40), 2500 }, |
|
72 { nsRect(25, 0, 75, 40), nsRect(25, 60, 75, 40), 2500 }, |
|
73 { nsRect(25, 0, 75, 40), nsRect(0, 60, 75, 40), 2000 }, |
|
74 { nsRect(0, 0, 75, 40), nsRect(25, 60, 75, 40), 2000 }, |
|
75 }; |
|
76 for (int32_t i = 0; i < nTests; i++) { |
|
77 nsRegion r2; |
|
78 |
|
79 r2.Sub(r, tests[i].rect1); |
|
80 r2.Sub(r2, tests[i].rect2); |
|
81 |
|
82 EXPECT_TRUE(r2.IsComplex()) << "nsRegion code got unexpectedly smarter!"; |
|
83 |
|
84 nsRect largest = r2.GetLargestRectangle(); |
|
85 EXPECT_TRUE(largest.width * largest.height == tests[i].expectedArea) << |
|
86 "Did not successfully find largest rectangle in two-rect-subtract region on iteration " << i; |
|
87 } |
|
88 } |
|
89 static void TestContainsSpecifiedRect() { |
|
90 nsRegion r(nsRect(0, 0, 100, 100)); |
|
91 r.Or(r, nsRect(0, 300, 50, 50)); |
|
92 EXPECT_TRUE(r.GetLargestRectangle(nsRect(0, 300, 10, 10)).IsEqualInterior(nsRect(0, 300, 50, 50))) << |
|
93 "Chose wrong rectangle"; |
|
94 } |
|
95 static void TestContainsSpecifiedOverflowingRect() { |
|
96 nsRegion r(nsRect(0, 0, 100, 100)); |
|
97 r.Or(r, nsRect(0, 300, 50, 50)); |
|
98 EXPECT_TRUE(r.GetLargestRectangle(nsRect(0, 290, 10, 20)).IsEqualInterior(nsRect(0, 300, 50, 50))) << |
|
99 "Chose wrong rectangle"; |
|
100 } |
|
101 }; |
|
102 |
|
103 TEST(Gfx, RegionSingleRect) { |
|
104 TestLargestRegion::TestSingleRect(nsRect(0, 52, 720, 480)); |
|
105 TestLargestRegion::TestSingleRect(nsRect(-20, 40, 50, 20)); |
|
106 TestLargestRegion::TestSingleRect(nsRect(-20, 40, 10, 8)); |
|
107 TestLargestRegion::TestSingleRect(nsRect(-20, -40, 10, 8)); |
|
108 TestLargestRegion::TestSingleRect(nsRect(-10, -10, 20, 20)); |
|
109 } |
|
110 |
|
111 TEST(Gfx, RegionNonRectangular) { |
|
112 TestLargestRegion::TestNonRectangular(); |
|
113 } |
|
114 |
|
115 TEST(Gfx, RegionTwoRectTest) { |
|
116 TestLargestRegion::TwoRectTest(); |
|
117 } |
|
118 |
|
119 TEST(Gfx, RegionContainsSpecifiedRect) { |
|
120 TestLargestRegion::TestContainsSpecifiedRect(); |
|
121 } |
|
122 |
|
123 TEST(Gfx, RegionTestContainsSpecifiedOverflowingRect) { |
|
124 TestLargestRegion::TestContainsSpecifiedOverflowingRect(); |
|
125 } |
|
126 |
|
127 TEST(Gfx, RegionScaleToInside) { |
|
128 { // no rectangles |
|
129 nsRegion r; |
|
130 |
|
131 nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60); |
|
132 nsIntRegion result; |
|
133 |
|
134 EXPECT_TRUE(result.IsEqual(scaled)) << |
|
135 "scaled result incorrect"; |
|
136 } |
|
137 |
|
138 { // one rectangle |
|
139 nsRegion r(nsRect(0,44760,19096,264)); |
|
140 |
|
141 nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60); |
|
142 nsIntRegion result(nsIntRect(0,746,318,4)); |
|
143 |
|
144 EXPECT_TRUE(result.IsEqual(scaled)) << |
|
145 "scaled result incorrect"; |
|
146 } |
|
147 |
|
148 |
|
149 { // the first rectangle gets adjusted |
|
150 nsRegion r(nsRect(0,44760,19096,264)); |
|
151 r.Or(r, nsRect(0,45024,19360,1056)); |
|
152 |
|
153 nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60); |
|
154 nsIntRegion result(nsIntRect(0,746,318,5)); |
|
155 result.Or(result, nsIntRect(0,751,322,17)); |
|
156 |
|
157 EXPECT_TRUE(result.IsEqual(scaled)) << |
|
158 "scaled result incorrect"; |
|
159 } |
|
160 |
|
161 { // the second rectangle gets adjusted |
|
162 nsRegion r(nsRect(0,44760,19360,264)); |
|
163 r.Or(r, nsRect(0,45024,19096,1056)); |
|
164 |
|
165 nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60); |
|
166 nsIntRegion result(nsIntRect(0,746,322,4)); |
|
167 result.Or(result, nsIntRect(0,750,318,18)); |
|
168 |
|
169 EXPECT_TRUE(result.IsEqual(scaled)) << |
|
170 "scaled result incorrect"; |
|
171 } |
|
172 |
|
173 } |
|
174 |
|
175 TEST(Gfx, RegionSimplify) { |
|
176 { // ensure simplify works on a single rect |
|
177 nsRegion r(nsRect(0,100,200,100)); |
|
178 |
|
179 r.SimplifyOutwardByArea(100*100); |
|
180 |
|
181 nsRegion result(nsRect(0,100,200,100)); |
|
182 |
|
183 EXPECT_TRUE(r.IsEqual(result)) << |
|
184 "regions not the same"; |
|
185 } |
|
186 |
|
187 { // the rectangles will be merged |
|
188 nsRegion r(nsRect(0,100,200,100)); |
|
189 r.Or(r, nsRect(0,200,300,200)); |
|
190 |
|
191 r.SimplifyOutwardByArea(100*100); |
|
192 |
|
193 nsRegion result(nsRect(0,100,300,300)); |
|
194 |
|
195 EXPECT_TRUE(r.IsEqual(result)) << |
|
196 "regions not merged"; |
|
197 } |
|
198 |
|
199 { // two rectangle on the first span |
|
200 // one on the second |
|
201 nsRegion r(nsRect(0,100,200,100)); |
|
202 r.Or(r, nsRect(0,200,300,200)); |
|
203 r.Or(r, nsRect(250,100,50,100)); |
|
204 |
|
205 EXPECT_TRUE(r.GetNumRects() == 3) << |
|
206 "wrong number of rects"; |
|
207 |
|
208 r.SimplifyOutwardByArea(100*100); |
|
209 |
|
210 nsRegion result(nsRect(0,100,300,300)); |
|
211 |
|
212 EXPECT_TRUE(r.IsEqual(result)) << |
|
213 "regions not merged"; |
|
214 } |
|
215 |
|
216 { // the rectangles will be merged |
|
217 nsRegion r(nsRect(0,100,200,100)); |
|
218 r.Or(r, nsRect(0,200,300,200)); |
|
219 r.Or(r, nsRect(250,100,50,100)); |
|
220 r.Sub(r, nsRect(200,200,40,200)); |
|
221 |
|
222 EXPECT_TRUE(r.GetNumRects() == 4) << |
|
223 "wrong number of rects"; |
|
224 |
|
225 r.SimplifyOutwardByArea(100*100); |
|
226 |
|
227 nsRegion result(nsRect(0,100,300,300)); |
|
228 result.Sub(result, nsRect(200,100,40,300)); |
|
229 |
|
230 EXPECT_TRUE(r.IsEqual(result)) << |
|
231 "regions not merged"; |
|
232 } |
|
233 |
|
234 { // three spans of rectangles |
|
235 nsRegion r(nsRect(0,100,200,100)); |
|
236 r.Or(r, nsRect(0,200,300,200)); |
|
237 r.Or(r, nsRect(250,100,50,50)); |
|
238 r.Sub(r, nsRect(200,200,40,200)); |
|
239 |
|
240 r.SimplifyOutwardByArea(100*100); |
|
241 |
|
242 nsRegion result(nsRect(0,100,300,300)); |
|
243 result.Sub(result, nsRect(200,100,40,300)); |
|
244 |
|
245 EXPECT_TRUE(r.IsEqual(result)) << |
|
246 "regions not merged"; |
|
247 } |
|
248 |
|
249 { // three spans of rectangles and an unmerged rectangle |
|
250 nsRegion r(nsRect(0,100,200,100)); |
|
251 r.Or(r, nsRect(0,200,300,200)); |
|
252 r.Or(r, nsRect(250,100,50,50)); |
|
253 r.Sub(r, nsRect(200,200,40,200)); |
|
254 r.Or(r, nsRect(250,900,150,50)); |
|
255 |
|
256 r.SimplifyOutwardByArea(100*100); |
|
257 |
|
258 nsRegion result(nsRect(0,100,300,300)); |
|
259 result.Sub(result, nsRect(200,100,40,300)); |
|
260 result.Or(result, nsRect(250,900,150,50)); |
|
261 |
|
262 EXPECT_TRUE(r.IsEqual(result)) << |
|
263 "regions not merged"; |
|
264 } |
|
265 |
|
266 { // unmerged regions |
|
267 nsRegion r(nsRect(0,100,200,100)); |
|
268 r.Or(r, nsRect(0,200,300,200)); |
|
269 |
|
270 r.SimplifyOutwardByArea(100); |
|
271 |
|
272 nsRegion result(nsRect(0,100,200,100)); |
|
273 result.Or(result, nsRect(0,200,300,200)); |
|
274 |
|
275 EXPECT_TRUE(r.IsEqual(result)) << |
|
276 "regions not merged"; |
|
277 } |
|
278 |
|
279 { // empty region |
|
280 // just make sure this doesn't crash. |
|
281 nsRegion r; |
|
282 r.SimplifyOutwardByArea(100); |
|
283 } |
|
284 |
|
285 } |