|
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 |
|
8 #include "nsRect.h" |
|
9 #include "gfxRect.h" |
|
10 #ifdef XP_WIN |
|
11 #include <windows.h> |
|
12 #endif |
|
13 |
|
14 template <class RectType> |
|
15 static bool |
|
16 TestConstructors() |
|
17 { |
|
18 // Create a rectangle |
|
19 RectType rect1(10, 20, 30, 40); |
|
20 |
|
21 // Make sure the rectangle was properly initialized |
|
22 EXPECT_TRUE(rect1.x == 10 && rect1.y == 20 && |
|
23 rect1.width == 30 && rect1.height == 40) << |
|
24 "[1] Make sure the rectangle was properly initialized with constructor"; |
|
25 |
|
26 // Create a second rect using the copy constructor |
|
27 RectType rect2(rect1); |
|
28 |
|
29 // Make sure the rectangle was properly initialized |
|
30 EXPECT_TRUE(rect2.x == rect1.x && rect2.y == rect2.y && |
|
31 rect2.width == rect2.width && rect2.height == rect2.height) << |
|
32 "[2] Make sure the rectangle was properly initialized with copy constructor"; |
|
33 |
|
34 |
|
35 EXPECT_TRUE(!rect1.IsEmpty() && rect1.IsFinite() && |
|
36 !rect2.IsEmpty() && rect2.IsFinite()) << |
|
37 "[3] These rectangles are not empty and are finite"; |
|
38 |
|
39 return true; |
|
40 } |
|
41 |
|
42 template <class RectType> |
|
43 static bool |
|
44 TestEqualityOperator() |
|
45 { |
|
46 RectType rect1(10, 20, 30, 40); |
|
47 RectType rect2(rect1); |
|
48 |
|
49 // Test the equality operator |
|
50 EXPECT_TRUE(rect1 == rect2) << |
|
51 "[1] Test the equality operator"; |
|
52 |
|
53 EXPECT_FALSE(!rect1.IsEqualInterior(rect2)) << |
|
54 "[2] Test the inequality operator"; |
|
55 |
|
56 // Make sure that two empty rects are equal |
|
57 rect1.SetEmpty(); |
|
58 rect2.SetEmpty(); |
|
59 EXPECT_TRUE(rect1 == rect2) << |
|
60 "[3] Make sure that two empty rects are equal"; |
|
61 |
|
62 return true; |
|
63 } |
|
64 |
|
65 template <class RectType> |
|
66 static bool |
|
67 TestContainment() |
|
68 { |
|
69 RectType rect1(10, 10, 50, 50); |
|
70 |
|
71 // Test the point containment methods |
|
72 // |
|
73 |
|
74 // Basic test of a point in the middle of the rect |
|
75 EXPECT_FALSE(!rect1.Contains(rect1.x + rect1.width/2, rect1.y + rect1.height/2)) << |
|
76 "[1] Basic test of a point in the middle of the rect"; |
|
77 |
|
78 // Test against a point at the left/top edges |
|
79 EXPECT_FALSE(!rect1.Contains(rect1.x, rect1.y)) << |
|
80 "[2] Test against a point at the left/top edges"; |
|
81 |
|
82 // Test against a point at the right/bottom extents |
|
83 EXPECT_FALSE(rect1.Contains(rect1.XMost(), rect1.YMost())) << |
|
84 "[3] Test against a point at the right/bottom extents"; |
|
85 |
|
86 // Test the rect containment methods |
|
87 // |
|
88 RectType rect2(rect1); |
|
89 |
|
90 // Test against a rect that's the same as rect1 |
|
91 EXPECT_FALSE(!rect1.Contains(rect2)) << |
|
92 "[4] Test against a rect that's the same as rect1"; |
|
93 |
|
94 // Test against a rect whose left edge (only) is outside of rect1 |
|
95 rect2.x--; |
|
96 EXPECT_FALSE(rect1.Contains(rect2)) << |
|
97 "[5] Test against a rect whose left edge (only) is outside of rect1"; |
|
98 rect2.x++; |
|
99 |
|
100 // Test against a rect whose top edge (only) is outside of rect1 |
|
101 rect2.y--; |
|
102 EXPECT_FALSE(rect1.Contains(rect2)) << |
|
103 "[6] Test against a rect whose top edge (only) is outside of rect1"; |
|
104 rect2.y++; |
|
105 |
|
106 // Test against a rect whose right edge (only) is outside of rect1 |
|
107 rect2.x++; |
|
108 EXPECT_FALSE(rect1.Contains(rect2)) << |
|
109 "[7] Test against a rect whose right edge (only) is outside of rect1"; |
|
110 rect2.x--; |
|
111 |
|
112 // Test against a rect whose bottom edge (only) is outside of rect1 |
|
113 rect2.y++; |
|
114 EXPECT_FALSE(rect1.Contains(rect2)) << |
|
115 "[8] Test against a rect whose bottom edge (only) is outside of rect1"; |
|
116 rect2.y--; |
|
117 |
|
118 return true; |
|
119 } |
|
120 |
|
121 // Test the method that returns a boolean result but doesn't return a |
|
122 // a rectangle |
|
123 template <class RectType> |
|
124 static bool |
|
125 TestIntersects() |
|
126 { |
|
127 RectType rect1(10, 10, 50, 50); |
|
128 RectType rect2(rect1); |
|
129 |
|
130 // Test against a rect that's the same as rect1 |
|
131 EXPECT_FALSE(!rect1.Intersects(rect2)) << |
|
132 "[1] Test against a rect that's the same as rect1"; |
|
133 |
|
134 // Test against a rect that's enclosed by rect1 |
|
135 rect2.Inflate(-1, -1); |
|
136 EXPECT_FALSE(!rect1.Contains(rect2) || !rect1.Intersects(rect2)) << |
|
137 "[2] Test against a rect that's enclosed by rect1"; |
|
138 rect2.Inflate(1, 1); |
|
139 |
|
140 // Make sure inflate and deflate worked correctly |
|
141 EXPECT_TRUE(rect1.IsEqualInterior(rect2)) << |
|
142 "[3] Make sure inflate and deflate worked correctly"; |
|
143 |
|
144 // Test against a rect that overlaps the left edge of rect1 |
|
145 rect2.x--; |
|
146 EXPECT_FALSE(!rect1.Intersects(rect2)) << |
|
147 "[4] Test against a rect that overlaps the left edge of rect1"; |
|
148 rect2.x++; |
|
149 |
|
150 // Test against a rect that's outside of rect1 on the left |
|
151 rect2.x -= rect2.width; |
|
152 EXPECT_FALSE(rect1.Intersects(rect2)) << |
|
153 "[5] Test against a rect that's outside of rect1 on the left"; |
|
154 rect2.x += rect2.width; |
|
155 |
|
156 // Test against a rect that overlaps the top edge of rect1 |
|
157 rect2.y--; |
|
158 EXPECT_FALSE(!rect1.Intersects(rect2)) << |
|
159 "[6] Test against a rect that overlaps the top edge of rect1"; |
|
160 rect2.y++; |
|
161 |
|
162 // Test against a rect that's outside of rect1 on the top |
|
163 rect2.y -= rect2.height; |
|
164 EXPECT_FALSE(rect1.Intersects(rect2)) << |
|
165 "[7] Test against a rect that's outside of rect1 on the top"; |
|
166 rect2.y += rect2.height; |
|
167 |
|
168 // Test against a rect that overlaps the right edge of rect1 |
|
169 rect2.x++; |
|
170 EXPECT_FALSE(!rect1.Intersects(rect2)) << |
|
171 "[8] Test against a rect that overlaps the right edge of rect1"; |
|
172 rect2.x--; |
|
173 |
|
174 // Test against a rect that's outside of rect1 on the right |
|
175 rect2.x += rect2.width; |
|
176 EXPECT_FALSE(rect1.Intersects(rect2)) << |
|
177 "[9] Test against a rect that's outside of rect1 on the right"; |
|
178 rect2.x -= rect2.width; |
|
179 |
|
180 // Test against a rect that overlaps the bottom edge of rect1 |
|
181 rect2.y++; |
|
182 EXPECT_FALSE(!rect1.Intersects(rect2)) << |
|
183 "[10] Test against a rect that overlaps the bottom edge of rect1"; |
|
184 rect2.y--; |
|
185 |
|
186 // Test against a rect that's outside of rect1 on the bottom |
|
187 rect2.y += rect2.height; |
|
188 EXPECT_FALSE(rect1.Intersects(rect2)) << |
|
189 "[11] Test against a rect that's outside of rect1 on the bottom"; |
|
190 rect2.y -= rect2.height; |
|
191 |
|
192 return true; |
|
193 } |
|
194 |
|
195 // Test the method that returns a boolean result and an intersection rect |
|
196 template <class RectType> |
|
197 static bool |
|
198 TestIntersection() |
|
199 { |
|
200 RectType rect1(10, 10, 50, 50); |
|
201 RectType rect2(rect1); |
|
202 RectType dest; |
|
203 |
|
204 // Test against a rect that's the same as rect1 |
|
205 EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || !(dest.IsEqualInterior(rect1))) << |
|
206 "[1] Test against a rect that's the same as rect1"; |
|
207 |
|
208 // Test against a rect that's enclosed by rect1 |
|
209 rect2.Inflate(-1, -1); |
|
210 EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || !(dest.IsEqualInterior(rect2))) << |
|
211 "[2] Test against a rect that's enclosed by rect1"; |
|
212 rect2.Inflate(1, 1); |
|
213 |
|
214 // Test against a rect that overlaps the left edge of rect1 |
|
215 rect2.x--; |
|
216 EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || |
|
217 !(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect1.width - 1, rect1.height)))) << |
|
218 "[3] Test against a rect that overlaps the left edge of rect1"; |
|
219 rect2.x++; |
|
220 |
|
221 // Test against a rect that's outside of rect1 on the left |
|
222 rect2.x -= rect2.width; |
|
223 EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << |
|
224 "[4] Test against a rect that's outside of rect1 on the left"; |
|
225 // Make sure an empty rect is returned |
|
226 EXPECT_FALSE(!dest.IsEmpty()) << |
|
227 "[4] Make sure an empty rect is returned"; |
|
228 EXPECT_TRUE(dest.IsFinite()) << "[4b] Should be finite"; |
|
229 rect2.x += rect2.width; |
|
230 |
|
231 // Test against a rect that overlaps the top edge of rect1 |
|
232 rect2.y--; |
|
233 EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || |
|
234 !(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect1.width, rect1.height - 1)))) << |
|
235 "[5] Test against a rect that overlaps the top edge of rect1"; |
|
236 EXPECT_TRUE(dest.IsFinite()) << "[5b] Should be finite"; |
|
237 rect2.y++; |
|
238 |
|
239 // Test against a rect that's outside of rect1 on the top |
|
240 rect2.y -= rect2.height; |
|
241 EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << |
|
242 "[6] Test against a rect that's outside of rect1 on the top"; |
|
243 // Make sure an empty rect is returned |
|
244 EXPECT_FALSE(!dest.IsEmpty()) << |
|
245 "[6] Make sure an empty rect is returned"; |
|
246 EXPECT_TRUE(dest.IsFinite()) << "[6b] Should be finite"; |
|
247 rect2.y += rect2.height; |
|
248 |
|
249 // Test against a rect that overlaps the right edge of rect1 |
|
250 rect2.x++; |
|
251 EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || |
|
252 !(dest.IsEqualInterior(RectType(rect1.x + 1, rect1.y, rect1.width - 1, rect1.height)))) << |
|
253 "[7] Test against a rect that overlaps the right edge of rect1"; |
|
254 rect2.x--; |
|
255 |
|
256 // Test against a rect that's outside of rect1 on the right |
|
257 rect2.x += rect2.width; |
|
258 EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << |
|
259 "[8] Test against a rect that's outside of rect1 on the right"; |
|
260 // Make sure an empty rect is returned |
|
261 EXPECT_FALSE(!dest.IsEmpty()) << |
|
262 "[8] Make sure an empty rect is returned"; |
|
263 EXPECT_TRUE(dest.IsFinite()) << "[8b] Should be finite"; |
|
264 rect2.x -= rect2.width; |
|
265 |
|
266 // Test against a rect that overlaps the bottom edge of rect1 |
|
267 rect2.y++; |
|
268 EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || |
|
269 !(dest.IsEqualInterior(RectType(rect1.x, rect1.y + 1, rect1.width, rect1.height - 1)))) << |
|
270 "[9] Test against a rect that overlaps the bottom edge of rect1"; |
|
271 EXPECT_TRUE(dest.IsFinite()) << "[9b] Should be finite"; |
|
272 rect2.y--; |
|
273 |
|
274 // Test against a rect that's outside of rect1 on the bottom |
|
275 rect2.y += rect2.height; |
|
276 EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << |
|
277 "[10] Test against a rect that's outside of rect1 on the bottom"; |
|
278 // Make sure an empty rect is returned |
|
279 EXPECT_FALSE(!dest.IsEmpty()) << |
|
280 "[10] Make sure an empty rect is returned"; |
|
281 EXPECT_TRUE(dest.IsFinite()) << "[10b] Should be finite"; |
|
282 rect2.y -= rect2.height; |
|
283 |
|
284 // Test against a rect with zero width or height |
|
285 rect1.SetRect(100, 100, 100, 100); |
|
286 rect2.SetRect(150, 100, 0, 100); |
|
287 EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << |
|
288 "[11] Intersection of rects with zero width or height should be empty"; |
|
289 EXPECT_TRUE(dest.IsFinite()) << "[11b] Should be finite"; |
|
290 |
|
291 // Tests against a rect with negative width or height |
|
292 // |
|
293 |
|
294 // Test against a rect with negative width |
|
295 rect1.SetRect(100, 100, 100, 100); |
|
296 rect2.SetRect(100, 100, -100, 100); |
|
297 EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << |
|
298 "[12] Intersection of rects with negative width or height should be empty"; |
|
299 EXPECT_TRUE(dest.IsFinite()) << "[12b] Should be finite"; |
|
300 |
|
301 // Those two rects exactly overlap in some way... |
|
302 // but we still want to return an empty rect |
|
303 rect1.SetRect(100, 100, 100, 100); |
|
304 rect2.SetRect(200, 200, -100, -100); |
|
305 EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << |
|
306 "[13] Intersection of rects with negative width or height should be empty"; |
|
307 EXPECT_TRUE(dest.IsFinite()) << "[13b] Should be finite"; |
|
308 |
|
309 // Test against two identical rects with negative height |
|
310 rect1.SetRect(100, 100, 100, -100); |
|
311 rect2.SetRect(100, 100, 100, -100); |
|
312 EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << |
|
313 "[14] Intersection of rects with negative width or height should be empty"; |
|
314 EXPECT_TRUE(dest.IsFinite()) << "[14b] Should be finite"; |
|
315 |
|
316 return true; |
|
317 } |
|
318 |
|
319 template <class RectType> |
|
320 static bool |
|
321 TestUnion() |
|
322 { |
|
323 RectType rect1; |
|
324 RectType rect2(10, 10, 50, 50); |
|
325 RectType dest; |
|
326 |
|
327 // Check the case where the receiver is an empty rect |
|
328 rect1.SetEmpty(); |
|
329 dest.UnionRect(rect1, rect2); |
|
330 EXPECT_FALSE(dest.IsEmpty() || !dest.IsEqualInterior(rect2)) << |
|
331 "[1] Check the case where the receiver is an empty rect"; |
|
332 EXPECT_TRUE(dest.IsFinite()) << "[1b] Should be finite"; |
|
333 |
|
334 // Check the case where the source rect is an empty rect |
|
335 rect1 = rect2; |
|
336 rect2.SetEmpty(); |
|
337 dest.UnionRect(rect1, rect2); |
|
338 EXPECT_FALSE(dest.IsEmpty() || !dest.IsEqualInterior(rect1)) << |
|
339 "[2] Check the case where the source rect is an empty rect"; |
|
340 EXPECT_TRUE(dest.IsFinite()) << "[2b] Should be finite"; |
|
341 |
|
342 // Test the case where both rects are empty |
|
343 rect1.SetEmpty(); |
|
344 rect2.SetEmpty(); |
|
345 dest.UnionRect(rect1, rect2); |
|
346 EXPECT_FALSE(!dest.IsEmpty()) << |
|
347 "[3] Test the case where both rects are empty"; |
|
348 EXPECT_TRUE(dest.IsFinite()) << "[3b] Should be finite"; |
|
349 |
|
350 // Test union case where the two rects don't overlap at all |
|
351 rect1.SetRect(10, 10, 50, 50); |
|
352 rect2.SetRect(100, 100, 50, 50); |
|
353 dest.UnionRect(rect1, rect2); |
|
354 EXPECT_FALSE(dest.IsEmpty() || |
|
355 !(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect2.XMost() - rect1.x, rect2.YMost() - rect1.y)))) << |
|
356 "[4] Test union case where the two rects don't overlap at all"; |
|
357 EXPECT_TRUE(dest.IsFinite()) << "[4b] Should be finite"; |
|
358 |
|
359 // Test union case where the two rects overlap |
|
360 rect1.SetRect(30, 30, 50, 50); |
|
361 rect2.SetRect(10, 10, 50, 50); |
|
362 dest.UnionRect(rect1, rect2); |
|
363 EXPECT_FALSE(dest.IsEmpty() || |
|
364 !(dest.IsEqualInterior(RectType(rect2.x, rect2.y, rect1.XMost() - rect2.x, rect1.YMost() - rect2.y)))) << |
|
365 "[5] Test union case where the two rects overlap"; |
|
366 EXPECT_TRUE(dest.IsFinite()) << "[5b] Should be finite"; |
|
367 |
|
368 return true; |
|
369 } |
|
370 |
|
371 static bool |
|
372 TestFiniteGfx() |
|
373 { |
|
374 // Doesn't appear that __builtin_inf() and __builtin_nan() are available on |
|
375 // all compilers, so go the old fashioned way for inf and nan. |
|
376 float posInf = 1.0/0.0; |
|
377 float negInf = -1.0/0.0; |
|
378 float justNaN = 0.0/0.0; |
|
379 |
|
380 gfxFloat values[4] = {5.0, 10.0, 15.0, 20.0}; |
|
381 |
|
382 // Try the "non-finite" values for x, y, width, height, one at a time |
|
383 for (int i=0; i<4; i+=1) { |
|
384 values[i] = posInf; |
|
385 gfxRect rectPosInf(values[0], values[1], values[2], values[3]); |
|
386 EXPECT_FALSE(rectPosInf.IsFinite()) << "For +inf (" << values[0] << "," << values[1] << "," << values[2] << "," << values[3] << ")"; |
|
387 |
|
388 values[i] = negInf; |
|
389 gfxRect rectNegInf(values[0], values[1], values[2], values[3]); |
|
390 EXPECT_FALSE(rectNegInf.IsFinite()) << "For -inf (" << values[0] << "," << values[1] << "," << values[2] << "," << values[3] << ")"; |
|
391 |
|
392 values[i] = justNaN; |
|
393 gfxRect rectNaN(values[0], values[1], values[2], values[3]); |
|
394 EXPECT_FALSE(rectNaN.IsFinite()) << "For NaN (" << values[0] << "," << values[1] << "," << values[2] << "," << values[3] << ")"; |
|
395 |
|
396 // Reset to a finite value... |
|
397 values[i] = 5.0*i; |
|
398 } |
|
399 |
|
400 return true; |
|
401 } |
|
402 |
|
403 TEST(Gfx, nsRect) { |
|
404 TestConstructors<nsRect>(); |
|
405 TestEqualityOperator<nsRect>(); |
|
406 TestContainment<nsRect>(); |
|
407 TestIntersects<nsRect>(); |
|
408 TestIntersection<nsRect>(); |
|
409 TestUnion<nsRect>(); |
|
410 } |
|
411 |
|
412 TEST(Gfx, nsIntRect) { |
|
413 TestConstructors<nsIntRect>(); |
|
414 TestEqualityOperator<nsIntRect>(); |
|
415 TestContainment<nsIntRect>(); |
|
416 TestIntersects<nsIntRect>(); |
|
417 TestIntersection<nsIntRect>(); |
|
418 TestUnion<nsIntRect>(); |
|
419 } |
|
420 |
|
421 TEST(Gfx, gfxRect) { |
|
422 TestConstructors<gfxRect>(); |
|
423 // Skip TestEqualityOperator<gfxRect>(); as gfxRect::operator== is private |
|
424 TestContainment<gfxRect>(); |
|
425 TestIntersects<gfxRect>(); |
|
426 TestIntersection<gfxRect>(); |
|
427 TestUnion<gfxRect>(); |
|
428 TestFiniteGfx(); |
|
429 } |