gfx/tests/gtest/TestRect.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial