1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <limits> 6 7 #include "base/basictypes.h" 8 #include "testing/gtest/include/gtest/gtest.h" 9 #include "ui/gfx/geometry/rect.h" 10 #include "ui/gfx/geometry/rect_conversions.h" 11 12 #if defined(OS_WIN) 13 #include <windows.h> 14 #endif 15 16 namespace gfx { 17 18 TEST(RectTest, Contains) { 19 static const struct ContainsCase { 20 int rect_x; 21 int rect_y; 22 int rect_width; 23 int rect_height; 24 int point_x; 25 int point_y; 26 bool contained; 27 } contains_cases[] = { 28 {0, 0, 10, 10, 0, 0, true}, 29 {0, 0, 10, 10, 5, 5, true}, 30 {0, 0, 10, 10, 9, 9, true}, 31 {0, 0, 10, 10, 5, 10, false}, 32 {0, 0, 10, 10, 10, 5, false}, 33 {0, 0, 10, 10, -1, -1, false}, 34 {0, 0, 10, 10, 50, 50, false}, 35 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) 36 {0, 0, -10, -10, 0, 0, false}, 37 #endif 38 }; 39 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(contains_cases); ++i) { 40 const ContainsCase& value = contains_cases[i]; 41 Rect rect(value.rect_x, value.rect_y, value.rect_width, value.rect_height); 42 EXPECT_EQ(value.contained, rect.Contains(value.point_x, value.point_y)); 43 } 44 } 45 46 TEST(RectTest, Intersects) { 47 static const struct { 48 int x1; // rect 1 49 int y1; 50 int w1; 51 int h1; 52 int x2; // rect 2 53 int y2; 54 int w2; 55 int h2; 56 bool intersects; 57 } tests[] = { 58 { 0, 0, 0, 0, 0, 0, 0, 0, false }, 59 { 0, 0, 0, 0, -10, -10, 20, 20, false }, 60 { -10, 0, 0, 20, 0, -10, 20, 0, false }, 61 { 0, 0, 10, 10, 0, 0, 10, 10, true }, 62 { 0, 0, 10, 10, 10, 10, 10, 10, false }, 63 { 10, 10, 10, 10, 0, 0, 10, 10, false }, 64 { 10, 10, 10, 10, 5, 5, 10, 10, true }, 65 { 10, 10, 10, 10, 15, 15, 10, 10, true }, 66 { 10, 10, 10, 10, 20, 15, 10, 10, false }, 67 { 10, 10, 10, 10, 21, 15, 10, 10, false } 68 }; 69 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 70 Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1); 71 Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2); 72 EXPECT_EQ(tests[i].intersects, r1.Intersects(r2)); 73 EXPECT_EQ(tests[i].intersects, r2.Intersects(r1)); 74 } 75 } 76 77 TEST(RectTest, Intersect) { 78 static const struct { 79 int x1; // rect 1 80 int y1; 81 int w1; 82 int h1; 83 int x2; // rect 2 84 int y2; 85 int w2; 86 int h2; 87 int x3; // rect 3: the union of rects 1 and 2 88 int y3; 89 int w3; 90 int h3; 91 } tests[] = { 92 { 0, 0, 0, 0, // zeros 93 0, 0, 0, 0, 94 0, 0, 0, 0 }, 95 { 0, 0, 4, 4, // equal 96 0, 0, 4, 4, 97 0, 0, 4, 4 }, 98 { 0, 0, 4, 4, // neighboring 99 4, 4, 4, 4, 100 0, 0, 0, 0 }, 101 { 0, 0, 4, 4, // overlapping corners 102 2, 2, 4, 4, 103 2, 2, 2, 2 }, 104 { 0, 0, 4, 4, // T junction 105 3, 1, 4, 2, 106 3, 1, 1, 2 }, 107 { 3, 0, 2, 2, // gap 108 0, 0, 2, 2, 109 0, 0, 0, 0 } 110 }; 111 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 112 Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1); 113 Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2); 114 Rect r3(tests[i].x3, tests[i].y3, tests[i].w3, tests[i].h3); 115 Rect ir = IntersectRects(r1, r2); 116 EXPECT_EQ(r3.x(), ir.x()); 117 EXPECT_EQ(r3.y(), ir.y()); 118 EXPECT_EQ(r3.width(), ir.width()); 119 EXPECT_EQ(r3.height(), ir.height()); 120 } 121 } 122 123 TEST(RectTest, Union) { 124 static const struct Test { 125 int x1; // rect 1 126 int y1; 127 int w1; 128 int h1; 129 int x2; // rect 2 130 int y2; 131 int w2; 132 int h2; 133 int x3; // rect 3: the union of rects 1 and 2 134 int y3; 135 int w3; 136 int h3; 137 } tests[] = { 138 { 0, 0, 0, 0, 139 0, 0, 0, 0, 140 0, 0, 0, 0 }, 141 { 0, 0, 4, 4, 142 0, 0, 4, 4, 143 0, 0, 4, 4 }, 144 { 0, 0, 4, 4, 145 4, 4, 4, 4, 146 0, 0, 8, 8 }, 147 { 0, 0, 4, 4, 148 0, 5, 4, 4, 149 0, 0, 4, 9 }, 150 { 0, 0, 2, 2, 151 3, 3, 2, 2, 152 0, 0, 5, 5 }, 153 { 3, 3, 2, 2, // reverse r1 and r2 from previous test 154 0, 0, 2, 2, 155 0, 0, 5, 5 }, 156 { 0, 0, 0, 0, // union with empty rect 157 2, 2, 2, 2, 158 2, 2, 2, 2 } 159 }; 160 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 161 Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1); 162 Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2); 163 Rect r3(tests[i].x3, tests[i].y3, tests[i].w3, tests[i].h3); 164 Rect u = UnionRects(r1, r2); 165 EXPECT_EQ(r3.x(), u.x()); 166 EXPECT_EQ(r3.y(), u.y()); 167 EXPECT_EQ(r3.width(), u.width()); 168 EXPECT_EQ(r3.height(), u.height()); 169 } 170 } 171 172 TEST(RectTest, Equals) { 173 ASSERT_TRUE(Rect(0, 0, 0, 0) == Rect(0, 0, 0, 0)); 174 ASSERT_TRUE(Rect(1, 2, 3, 4) == Rect(1, 2, 3, 4)); 175 ASSERT_FALSE(Rect(0, 0, 0, 0) == Rect(0, 0, 0, 1)); 176 ASSERT_FALSE(Rect(0, 0, 0, 0) == Rect(0, 0, 1, 0)); 177 ASSERT_FALSE(Rect(0, 0, 0, 0) == Rect(0, 1, 0, 0)); 178 ASSERT_FALSE(Rect(0, 0, 0, 0) == Rect(1, 0, 0, 0)); 179 } 180 181 TEST(RectTest, AdjustToFit) { 182 static const struct Test { 183 int x1; // source 184 int y1; 185 int w1; 186 int h1; 187 int x2; // target 188 int y2; 189 int w2; 190 int h2; 191 int x3; // rect 3: results of invoking AdjustToFit 192 int y3; 193 int w3; 194 int h3; 195 } tests[] = { 196 { 0, 0, 2, 2, 197 0, 0, 2, 2, 198 0, 0, 2, 2 }, 199 { 2, 2, 3, 3, 200 0, 0, 4, 4, 201 1, 1, 3, 3 }, 202 { -1, -1, 5, 5, 203 0, 0, 4, 4, 204 0, 0, 4, 4 }, 205 { 2, 2, 4, 4, 206 0, 0, 3, 3, 207 0, 0, 3, 3 }, 208 { 2, 2, 1, 1, 209 0, 0, 3, 3, 210 2, 2, 1, 1 } 211 }; 212 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 213 Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1); 214 Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2); 215 Rect r3(tests[i].x3, tests[i].y3, tests[i].w3, tests[i].h3); 216 Rect u = r1; 217 u.AdjustToFit(r2); 218 EXPECT_EQ(r3.x(), u.x()); 219 EXPECT_EQ(r3.y(), u.y()); 220 EXPECT_EQ(r3.width(), u.width()); 221 EXPECT_EQ(r3.height(), u.height()); 222 } 223 } 224 225 TEST(RectTest, Subtract) { 226 Rect result; 227 228 // Matching 229 result = Rect(10, 10, 20, 20); 230 result.Subtract(Rect(10, 10, 20, 20)); 231 EXPECT_EQ(Rect(0, 0, 0, 0).ToString(), result.ToString()); 232 233 // Contains 234 result = Rect(10, 10, 20, 20); 235 result.Subtract(Rect(5, 5, 30, 30)); 236 EXPECT_EQ(Rect(0, 0, 0, 0).ToString(), result.ToString()); 237 238 // No intersection 239 result = Rect(10, 10, 20, 20); 240 result.Subtract(Rect(30, 30, 30, 30)); 241 EXPECT_EQ(Rect(10, 10, 20, 20).ToString(), result.ToString()); 242 243 // Not a complete intersection in either direction 244 result = Rect(10, 10, 20, 20); 245 result.Subtract(Rect(15, 15, 20, 20)); 246 EXPECT_EQ(Rect(10, 10, 20, 20).ToString(), result.ToString()); 247 248 // Complete intersection in the x-direction, top edge is fully covered. 249 result = Rect(10, 10, 20, 20); 250 result.Subtract(Rect(10, 15, 20, 20)); 251 EXPECT_EQ(Rect(10, 10, 20, 5).ToString(), result.ToString()); 252 253 // Complete intersection in the x-direction, top edge is fully covered. 254 result = Rect(10, 10, 20, 20); 255 result.Subtract(Rect(5, 15, 30, 20)); 256 EXPECT_EQ(Rect(10, 10, 20, 5).ToString(), result.ToString()); 257 258 // Complete intersection in the x-direction, bottom edge is fully covered. 259 result = Rect(10, 10, 20, 20); 260 result.Subtract(Rect(5, 5, 30, 20)); 261 EXPECT_EQ(Rect(10, 25, 20, 5).ToString(), result.ToString()); 262 263 // Complete intersection in the x-direction, none of the edges is fully 264 // covered. 265 result = Rect(10, 10, 20, 20); 266 result.Subtract(Rect(5, 15, 30, 1)); 267 EXPECT_EQ(Rect(10, 10, 20, 20).ToString(), result.ToString()); 268 269 // Complete intersection in the y-direction, left edge is fully covered. 270 result = Rect(10, 10, 20, 20); 271 result.Subtract(Rect(10, 10, 10, 30)); 272 EXPECT_EQ(Rect(20, 10, 10, 20).ToString(), result.ToString()); 273 274 // Complete intersection in the y-direction, left edge is fully covered. 275 result = Rect(10, 10, 20, 20); 276 result.Subtract(Rect(5, 5, 20, 30)); 277 EXPECT_EQ(Rect(25, 10, 5, 20).ToString(), result.ToString()); 278 279 // Complete intersection in the y-direction, right edge is fully covered. 280 result = Rect(10, 10, 20, 20); 281 result.Subtract(Rect(20, 5, 20, 30)); 282 EXPECT_EQ(Rect(10, 10, 10, 20).ToString(), result.ToString()); 283 284 // Complete intersection in the y-direction, none of the edges is fully 285 // covered. 286 result = Rect(10, 10, 20, 20); 287 result.Subtract(Rect(15, 5, 1, 30)); 288 EXPECT_EQ(Rect(10, 10, 20, 20).ToString(), result.ToString()); 289 } 290 291 TEST(RectTest, IsEmpty) { 292 EXPECT_TRUE(Rect(0, 0, 0, 0).IsEmpty()); 293 EXPECT_TRUE(Rect(0, 0, 0, 0).size().IsEmpty()); 294 EXPECT_TRUE(Rect(0, 0, 10, 0).IsEmpty()); 295 EXPECT_TRUE(Rect(0, 0, 10, 0).size().IsEmpty()); 296 EXPECT_TRUE(Rect(0, 0, 0, 10).IsEmpty()); 297 EXPECT_TRUE(Rect(0, 0, 0, 10).size().IsEmpty()); 298 EXPECT_FALSE(Rect(0, 0, 10, 10).IsEmpty()); 299 EXPECT_FALSE(Rect(0, 0, 10, 10).size().IsEmpty()); 300 } 301 302 TEST(RectTest, SplitVertically) { 303 Rect left_half, right_half; 304 305 // Splitting when origin is (0, 0). 306 Rect(0, 0, 20, 20).SplitVertically(&left_half, &right_half); 307 EXPECT_TRUE(left_half == Rect(0, 0, 10, 20)); 308 EXPECT_TRUE(right_half == Rect(10, 0, 10, 20)); 309 310 // Splitting when origin is arbitrary. 311 Rect(10, 10, 20, 10).SplitVertically(&left_half, &right_half); 312 EXPECT_TRUE(left_half == Rect(10, 10, 10, 10)); 313 EXPECT_TRUE(right_half == Rect(20, 10, 10, 10)); 314 315 // Splitting a rectangle of zero width. 316 Rect(10, 10, 0, 10).SplitVertically(&left_half, &right_half); 317 EXPECT_TRUE(left_half == Rect(10, 10, 0, 10)); 318 EXPECT_TRUE(right_half == Rect(10, 10, 0, 10)); 319 320 // Splitting a rectangle of odd width. 321 Rect(10, 10, 5, 10).SplitVertically(&left_half, &right_half); 322 EXPECT_TRUE(left_half == Rect(10, 10, 2, 10)); 323 EXPECT_TRUE(right_half == Rect(12, 10, 3, 10)); 324 } 325 326 TEST(RectTest, CenterPoint) { 327 Point center; 328 329 // When origin is (0, 0). 330 center = Rect(0, 0, 20, 20).CenterPoint(); 331 EXPECT_TRUE(center == Point(10, 10)); 332 333 // When origin is even. 334 center = Rect(10, 10, 20, 20).CenterPoint(); 335 EXPECT_TRUE(center == Point(20, 20)); 336 337 // When origin is odd. 338 center = Rect(11, 11, 20, 20).CenterPoint(); 339 EXPECT_TRUE(center == Point(21, 21)); 340 341 // When 0 width or height. 342 center = Rect(10, 10, 0, 20).CenterPoint(); 343 EXPECT_TRUE(center == Point(10, 20)); 344 center = Rect(10, 10, 20, 0).CenterPoint(); 345 EXPECT_TRUE(center == Point(20, 10)); 346 347 // When an odd size. 348 center = Rect(10, 10, 21, 21).CenterPoint(); 349 EXPECT_TRUE(center == Point(20, 20)); 350 351 // When an odd size and position. 352 center = Rect(11, 11, 21, 21).CenterPoint(); 353 EXPECT_TRUE(center == Point(21, 21)); 354 } 355 356 TEST(RectTest, CenterPointF) { 357 PointF center; 358 359 // When origin is (0, 0). 360 center = RectF(0, 0, 20, 20).CenterPoint(); 361 EXPECT_TRUE(center == PointF(10, 10)); 362 363 // When origin is even. 364 center = RectF(10, 10, 20, 20).CenterPoint(); 365 EXPECT_TRUE(center == PointF(20, 20)); 366 367 // When origin is odd. 368 center = RectF(11, 11, 20, 20).CenterPoint(); 369 EXPECT_TRUE(center == PointF(21, 21)); 370 371 // When 0 width or height. 372 center = RectF(10, 10, 0, 20).CenterPoint(); 373 EXPECT_TRUE(center == PointF(10, 20)); 374 center = RectF(10, 10, 20, 0).CenterPoint(); 375 EXPECT_TRUE(center == PointF(20, 10)); 376 377 // When an odd size. 378 center = RectF(10, 10, 21, 21).CenterPoint(); 379 EXPECT_TRUE(center == PointF(20.5f, 20.5f)); 380 381 // When an odd size and position. 382 center = RectF(11, 11, 21, 21).CenterPoint(); 383 EXPECT_TRUE(center == PointF(21.5f, 21.5f)); 384 } 385 386 TEST(RectTest, SharesEdgeWith) { 387 Rect r(2, 3, 4, 5); 388 389 // Must be non-overlapping 390 EXPECT_FALSE(r.SharesEdgeWith(r)); 391 392 Rect just_above(2, 1, 4, 2); 393 Rect just_below(2, 8, 4, 2); 394 Rect just_left(0, 3, 2, 5); 395 Rect just_right(6, 3, 2, 5); 396 397 EXPECT_TRUE(r.SharesEdgeWith(just_above)); 398 EXPECT_TRUE(r.SharesEdgeWith(just_below)); 399 EXPECT_TRUE(r.SharesEdgeWith(just_left)); 400 EXPECT_TRUE(r.SharesEdgeWith(just_right)); 401 402 // Wrong placement 403 Rect same_height_no_edge(0, 0, 1, 5); 404 Rect same_width_no_edge(0, 0, 4, 1); 405 406 EXPECT_FALSE(r.SharesEdgeWith(same_height_no_edge)); 407 EXPECT_FALSE(r.SharesEdgeWith(same_width_no_edge)); 408 409 Rect just_above_no_edge(2, 1, 5, 2); // too wide 410 Rect just_below_no_edge(2, 8, 3, 2); // too narrow 411 Rect just_left_no_edge(0, 3, 2, 6); // too tall 412 Rect just_right_no_edge(6, 3, 2, 4); // too short 413 414 EXPECT_FALSE(r.SharesEdgeWith(just_above_no_edge)); 415 EXPECT_FALSE(r.SharesEdgeWith(just_below_no_edge)); 416 EXPECT_FALSE(r.SharesEdgeWith(just_left_no_edge)); 417 EXPECT_FALSE(r.SharesEdgeWith(just_right_no_edge)); 418 } 419 420 // Similar to EXPECT_FLOAT_EQ, but lets NaN equal NaN 421 #define EXPECT_FLOAT_AND_NAN_EQ(a, b) \ 422 { if (a == a || b == b) { EXPECT_FLOAT_EQ(a, b); } } 423 424 TEST(RectTest, ScaleRect) { 425 static const struct Test { 426 int x1; // source 427 int y1; 428 int w1; 429 int h1; 430 float scale; 431 float x2; // target 432 float y2; 433 float w2; 434 float h2; 435 } tests[] = { 436 { 3, 3, 3, 3, 437 1.5f, 438 4.5f, 4.5f, 4.5f, 4.5f }, 439 { 3, 3, 3, 3, 440 0.0f, 441 0.0f, 0.0f, 0.0f, 0.0f }, 442 { 3, 3, 3, 3, 443 std::numeric_limits<float>::quiet_NaN(), 444 std::numeric_limits<float>::quiet_NaN(), 445 std::numeric_limits<float>::quiet_NaN(), 446 std::numeric_limits<float>::quiet_NaN(), 447 std::numeric_limits<float>::quiet_NaN() }, 448 { 3, 3, 3, 3, 449 std::numeric_limits<float>::max(), 450 std::numeric_limits<float>::max(), 451 std::numeric_limits<float>::max(), 452 std::numeric_limits<float>::max(), 453 std::numeric_limits<float>::max() } 454 }; 455 456 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 457 Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1); 458 RectF r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2); 459 460 RectF scaled = ScaleRect(r1, tests[i].scale); 461 EXPECT_FLOAT_AND_NAN_EQ(r2.x(), scaled.x()); 462 EXPECT_FLOAT_AND_NAN_EQ(r2.y(), scaled.y()); 463 EXPECT_FLOAT_AND_NAN_EQ(r2.width(), scaled.width()); 464 EXPECT_FLOAT_AND_NAN_EQ(r2.height(), scaled.height()); 465 } 466 } 467 468 TEST(RectTest, ToEnclosedRect) { 469 static const struct Test { 470 float x1; // source 471 float y1; 472 float w1; 473 float h1; 474 int x2; // target 475 int y2; 476 int w2; 477 int h2; 478 } tests [] = { 479 { 0.0f, 0.0f, 0.0f, 0.0f, 480 0, 0, 0, 0 }, 481 { -1.5f, -1.5f, 3.0f, 3.0f, 482 -1, -1, 2, 2 }, 483 { -1.5f, -1.5f, 3.5f, 3.5f, 484 -1, -1, 3, 3 }, 485 { std::numeric_limits<float>::max(), 486 std::numeric_limits<float>::max(), 487 2.0f, 2.0f, 488 std::numeric_limits<int>::max(), 489 std::numeric_limits<int>::max(), 490 0, 0 }, 491 { 0.0f, 0.0f, 492 std::numeric_limits<float>::max(), 493 std::numeric_limits<float>::max(), 494 0, 0, 495 std::numeric_limits<int>::max(), 496 std::numeric_limits<int>::max() }, 497 { 20000.5f, 20000.5f, 0.5f, 0.5f, 498 20001, 20001, 0, 0 }, 499 { std::numeric_limits<float>::quiet_NaN(), 500 std::numeric_limits<float>::quiet_NaN(), 501 std::numeric_limits<float>::quiet_NaN(), 502 std::numeric_limits<float>::quiet_NaN(), 503 0, 0, 0, 0 } 504 }; 505 506 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 507 RectF r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1); 508 Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2); 509 510 Rect enclosed = ToEnclosedRect(r1); 511 EXPECT_FLOAT_AND_NAN_EQ(r2.x(), enclosed.x()); 512 EXPECT_FLOAT_AND_NAN_EQ(r2.y(), enclosed.y()); 513 EXPECT_FLOAT_AND_NAN_EQ(r2.width(), enclosed.width()); 514 EXPECT_FLOAT_AND_NAN_EQ(r2.height(), enclosed.height()); 515 } 516 } 517 518 TEST(RectTest, ToEnclosingRect) { 519 static const struct Test { 520 float x1; // source 521 float y1; 522 float w1; 523 float h1; 524 int x2; // target 525 int y2; 526 int w2; 527 int h2; 528 } tests [] = { 529 { 0.0f, 0.0f, 0.0f, 0.0f, 530 0, 0, 0, 0 }, 531 { 5.5f, 5.5f, 0.0f, 0.0f, 532 5, 5, 0, 0 }, 533 { -1.5f, -1.5f, 3.0f, 3.0f, 534 -2, -2, 4, 4 }, 535 { -1.5f, -1.5f, 3.5f, 3.5f, 536 -2, -2, 4, 4 }, 537 { std::numeric_limits<float>::max(), 538 std::numeric_limits<float>::max(), 539 2.0f, 2.0f, 540 std::numeric_limits<int>::max(), 541 std::numeric_limits<int>::max(), 542 0, 0 }, 543 { 0.0f, 0.0f, 544 std::numeric_limits<float>::max(), 545 std::numeric_limits<float>::max(), 546 0, 0, 547 std::numeric_limits<int>::max(), 548 std::numeric_limits<int>::max() }, 549 { 20000.5f, 20000.5f, 0.5f, 0.5f, 550 20000, 20000, 1, 1 }, 551 { std::numeric_limits<float>::quiet_NaN(), 552 std::numeric_limits<float>::quiet_NaN(), 553 std::numeric_limits<float>::quiet_NaN(), 554 std::numeric_limits<float>::quiet_NaN(), 555 0, 0, 0, 0 } 556 }; 557 558 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 559 RectF r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1); 560 Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2); 561 562 Rect enclosed = ToEnclosingRect(r1); 563 EXPECT_FLOAT_AND_NAN_EQ(r2.x(), enclosed.x()); 564 EXPECT_FLOAT_AND_NAN_EQ(r2.y(), enclosed.y()); 565 EXPECT_FLOAT_AND_NAN_EQ(r2.width(), enclosed.width()); 566 EXPECT_FLOAT_AND_NAN_EQ(r2.height(), enclosed.height()); 567 } 568 } 569 570 TEST(RectTest, ToNearestRect) { 571 Rect rect; 572 EXPECT_EQ(rect.ToString(), ToNearestRect(RectF(rect)).ToString()); 573 574 rect = Rect(-1, -1, 3, 3); 575 EXPECT_EQ(rect.ToString(), ToNearestRect(RectF(rect)).ToString()); 576 577 RectF rectf(-1.00001f, -0.999999f, 3.0000001f, 2.999999f); 578 EXPECT_EQ(rect.ToString(), ToNearestRect(rectf).ToString()); 579 } 580 581 TEST(RectTest, ToFlooredRect) { 582 static const struct Test { 583 float x1; // source 584 float y1; 585 float w1; 586 float h1; 587 int x2; // target 588 int y2; 589 int w2; 590 int h2; 591 } tests [] = { 592 { 0.0f, 0.0f, 0.0f, 0.0f, 593 0, 0, 0, 0 }, 594 { -1.5f, -1.5f, 3.0f, 3.0f, 595 -2, -2, 3, 3 }, 596 { -1.5f, -1.5f, 3.5f, 3.5f, 597 -2, -2, 3, 3 }, 598 { 20000.5f, 20000.5f, 0.5f, 0.5f, 599 20000, 20000, 0, 0 }, 600 }; 601 602 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 603 RectF r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1); 604 Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2); 605 606 Rect floored = ToFlooredRectDeprecated(r1); 607 EXPECT_FLOAT_EQ(r2.x(), floored.x()); 608 EXPECT_FLOAT_EQ(r2.y(), floored.y()); 609 EXPECT_FLOAT_EQ(r2.width(), floored.width()); 610 EXPECT_FLOAT_EQ(r2.height(), floored.height()); 611 } 612 } 613 614 TEST(RectTest, ScaleToEnclosedRect) { 615 static const struct Test { 616 Rect input_rect; 617 float input_scale; 618 Rect expected_rect; 619 } tests[] = { 620 { 621 Rect(), 622 5.f, 623 Rect(), 624 }, { 625 Rect(1, 1, 1, 1), 626 5.f, 627 Rect(5, 5, 5, 5), 628 }, { 629 Rect(-1, -1, 0, 0), 630 5.f, 631 Rect(-5, -5, 0, 0), 632 }, { 633 Rect(1, -1, 0, 1), 634 5.f, 635 Rect(5, -5, 0, 5), 636 }, { 637 Rect(-1, 1, 1, 0), 638 5.f, 639 Rect(-5, 5, 5, 0), 640 }, { 641 Rect(1, 2, 3, 4), 642 1.5f, 643 Rect(2, 3, 4, 6), 644 }, { 645 Rect(-1, -2, 0, 0), 646 1.5f, 647 Rect(-1, -3, 0, 0), 648 } 649 }; 650 651 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 652 Rect result = ScaleToEnclosedRect(tests[i].input_rect, 653 tests[i].input_scale); 654 EXPECT_EQ(tests[i].expected_rect.ToString(), result.ToString()); 655 } 656 } 657 658 TEST(RectTest, ScaleToEnclosingRect) { 659 static const struct Test { 660 Rect input_rect; 661 float input_scale; 662 Rect expected_rect; 663 } tests[] = { 664 { 665 Rect(), 666 5.f, 667 Rect(), 668 }, { 669 Rect(1, 1, 1, 1), 670 5.f, 671 Rect(5, 5, 5, 5), 672 }, { 673 Rect(-1, -1, 0, 0), 674 5.f, 675 Rect(-5, -5, 0, 0), 676 }, { 677 Rect(1, -1, 0, 1), 678 5.f, 679 Rect(5, -5, 0, 5), 680 }, { 681 Rect(-1, 1, 1, 0), 682 5.f, 683 Rect(-5, 5, 5, 0), 684 }, { 685 Rect(1, 2, 3, 4), 686 1.5f, 687 Rect(1, 3, 5, 6), 688 }, { 689 Rect(-1, -2, 0, 0), 690 1.5f, 691 Rect(-2, -3, 0, 0), 692 } 693 }; 694 695 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 696 Rect result = ScaleToEnclosingRect(tests[i].input_rect, 697 tests[i].input_scale); 698 EXPECT_EQ(tests[i].expected_rect.ToString(), result.ToString()); 699 } 700 } 701 702 #if defined(OS_WIN) 703 TEST(RectTest, ConstructAndAssign) { 704 const RECT rect_1 = { 0, 0, 10, 10 }; 705 const RECT rect_2 = { 0, 0, -10, -10 }; 706 Rect test1(rect_1); 707 Rect test2(rect_2); 708 } 709 #endif 710 711 TEST(RectTest, ToRectF) { 712 // Check that implicit conversion from integer to float compiles. 713 Rect a(10, 20, 30, 40); 714 RectF b(10, 20, 30, 40); 715 716 RectF intersect = IntersectRects(a, b); 717 EXPECT_EQ(b.ToString(), intersect.ToString()); 718 719 EXPECT_EQ(a, b); 720 EXPECT_EQ(b, a); 721 } 722 723 TEST(RectTest, BoundingRect) { 724 struct { 725 Point a; 726 Point b; 727 Rect expected; 728 } int_tests[] = { 729 // If point B dominates A, then A should be the origin. 730 { Point(4, 6), Point(4, 6), Rect(4, 6, 0, 0) }, 731 { Point(4, 6), Point(8, 6), Rect(4, 6, 4, 0) }, 732 { Point(4, 6), Point(4, 9), Rect(4, 6, 0, 3) }, 733 { Point(4, 6), Point(8, 9), Rect(4, 6, 4, 3) }, 734 // If point A dominates B, then B should be the origin. 735 { Point(4, 6), Point(4, 6), Rect(4, 6, 0, 0) }, 736 { Point(8, 6), Point(4, 6), Rect(4, 6, 4, 0) }, 737 { Point(4, 9), Point(4, 6), Rect(4, 6, 0, 3) }, 738 { Point(8, 9), Point(4, 6), Rect(4, 6, 4, 3) }, 739 // If neither point dominates, then the origin is a combination of the two. 740 { Point(4, 6), Point(6, 4), Rect(4, 4, 2, 2) }, 741 { Point(-4, -6), Point(-6, -4), Rect(-6, -6, 2, 2) }, 742 { Point(-4, 6), Point(6, -4), Rect(-4, -4, 10, 10) }, 743 }; 744 745 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(int_tests); ++i) { 746 Rect actual = BoundingRect(int_tests[i].a, int_tests[i].b); 747 EXPECT_EQ(int_tests[i].expected.ToString(), actual.ToString()); 748 } 749 750 struct { 751 PointF a; 752 PointF b; 753 RectF expected; 754 } float_tests[] = { 755 // If point B dominates A, then A should be the origin. 756 { PointF(4.2f, 6.8f), PointF(4.2f, 6.8f), 757 RectF(4.2f, 6.8f, 0, 0) }, 758 { PointF(4.2f, 6.8f), PointF(8.5f, 6.8f), 759 RectF(4.2f, 6.8f, 4.3f, 0) }, 760 { PointF(4.2f, 6.8f), PointF(4.2f, 9.3f), 761 RectF(4.2f, 6.8f, 0, 2.5f) }, 762 { PointF(4.2f, 6.8f), PointF(8.5f, 9.3f), 763 RectF(4.2f, 6.8f, 4.3f, 2.5f) }, 764 // If point A dominates B, then B should be the origin. 765 { PointF(4.2f, 6.8f), PointF(4.2f, 6.8f), 766 RectF(4.2f, 6.8f, 0, 0) }, 767 { PointF(8.5f, 6.8f), PointF(4.2f, 6.8f), 768 RectF(4.2f, 6.8f, 4.3f, 0) }, 769 { PointF(4.2f, 9.3f), PointF(4.2f, 6.8f), 770 RectF(4.2f, 6.8f, 0, 2.5f) }, 771 { PointF(8.5f, 9.3f), PointF(4.2f, 6.8f), 772 RectF(4.2f, 6.8f, 4.3f, 2.5f) }, 773 // If neither point dominates, then the origin is a combination of the two. 774 { PointF(4.2f, 6.8f), PointF(6.8f, 4.2f), 775 RectF(4.2f, 4.2f, 2.6f, 2.6f) }, 776 { PointF(-4.2f, -6.8f), PointF(-6.8f, -4.2f), 777 RectF(-6.8f, -6.8f, 2.6f, 2.6f) }, 778 { PointF(-4.2f, 6.8f), PointF(6.8f, -4.2f), 779 RectF(-4.2f, -4.2f, 11.0f, 11.0f) } 780 }; 781 782 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(float_tests); ++i) { 783 RectF actual = BoundingRect(float_tests[i].a, float_tests[i].b); 784 EXPECT_EQ(float_tests[i].expected.ToString(), actual.ToString()); 785 } 786 } 787 788 TEST(RectTest, IsExpressibleAsRect) { 789 EXPECT_TRUE(RectF().IsExpressibleAsRect()); 790 791 float min = std::numeric_limits<int>::min(); 792 float max = std::numeric_limits<int>::max(); 793 float infinity = std::numeric_limits<float>::infinity(); 794 795 EXPECT_TRUE(RectF( 796 min + 200, min + 200, max - 200, max - 200).IsExpressibleAsRect()); 797 EXPECT_FALSE(RectF( 798 min - 200, min + 200, max + 200, max + 200).IsExpressibleAsRect()); 799 EXPECT_FALSE(RectF( 800 min + 200 , min - 200, max + 200, max + 200).IsExpressibleAsRect()); 801 EXPECT_FALSE(RectF( 802 min + 200, min + 200, max + 200, max - 200).IsExpressibleAsRect()); 803 EXPECT_FALSE(RectF( 804 min + 200, min + 200, max - 200, max + 200).IsExpressibleAsRect()); 805 806 EXPECT_TRUE(RectF(0, 0, max - 200, max - 200).IsExpressibleAsRect()); 807 EXPECT_FALSE(RectF(200, 0, max + 200, max - 200).IsExpressibleAsRect()); 808 EXPECT_FALSE(RectF(0, 200, max - 200, max + 200).IsExpressibleAsRect()); 809 EXPECT_FALSE(RectF(0, 0, max + 200, max - 200).IsExpressibleAsRect()); 810 EXPECT_FALSE(RectF(0, 0, max - 200, max + 200).IsExpressibleAsRect()); 811 812 EXPECT_FALSE(RectF(infinity, 0, 1, 1).IsExpressibleAsRect()); 813 EXPECT_FALSE(RectF(0, infinity, 1, 1).IsExpressibleAsRect()); 814 EXPECT_FALSE(RectF(0, 0, infinity, 1).IsExpressibleAsRect()); 815 EXPECT_FALSE(RectF(0, 0, 1, infinity).IsExpressibleAsRect()); 816 } 817 818 TEST(RectTest, Offset) { 819 Rect i(1, 2, 3, 4); 820 821 EXPECT_EQ(Rect(2, 1, 3, 4).ToString(), (i + Vector2d(1, -1)).ToString()); 822 EXPECT_EQ(Rect(2, 1, 3, 4).ToString(), (Vector2d(1, -1) + i).ToString()); 823 i += Vector2d(1, -1); 824 EXPECT_EQ(Rect(2, 1, 3, 4).ToString(), i.ToString()); 825 EXPECT_EQ(Rect(1, 2, 3, 4).ToString(), (i - Vector2d(1, -1)).ToString()); 826 i -= Vector2d(1, -1); 827 EXPECT_EQ(Rect(1, 2, 3, 4).ToString(), i.ToString()); 828 829 RectF f(1.1f, 2.2f, 3.3f, 4.4f); 830 EXPECT_EQ(RectF(2.2f, 1.1f, 3.3f, 4.4f).ToString(), 831 (f + Vector2dF(1.1f, -1.1f)).ToString()); 832 EXPECT_EQ(RectF(2.2f, 1.1f, 3.3f, 4.4f).ToString(), 833 (Vector2dF(1.1f, -1.1f) + f).ToString()); 834 f += Vector2dF(1.1f, -1.1f); 835 EXPECT_EQ(RectF(2.2f, 1.1f, 3.3f, 4.4f).ToString(), f.ToString()); 836 EXPECT_EQ(RectF(1.1f, 2.2f, 3.3f, 4.4f).ToString(), 837 (f - Vector2dF(1.1f, -1.1f)).ToString()); 838 f -= Vector2dF(1.1f, -1.1f); 839 EXPECT_EQ(RectF(1.1f, 2.2f, 3.3f, 4.4f).ToString(), f.ToString()); 840 } 841 842 TEST(RectTest, Corners) { 843 Rect i(1, 2, 3, 4); 844 RectF f(1.1f, 2.1f, 3.1f, 4.1f); 845 846 EXPECT_EQ(Point(1, 2).ToString(), i.origin().ToString()); 847 EXPECT_EQ(Point(4, 2).ToString(), i.top_right().ToString()); 848 EXPECT_EQ(Point(1, 6).ToString(), i.bottom_left().ToString()); 849 EXPECT_EQ(Point(4, 6).ToString(), i.bottom_right().ToString()); 850 851 EXPECT_EQ(PointF(1.1f, 2.1f).ToString(), f.origin().ToString()); 852 EXPECT_EQ(PointF(4.2f, 2.1f).ToString(), f.top_right().ToString()); 853 EXPECT_EQ(PointF(1.1f, 6.2f).ToString(), f.bottom_left().ToString()); 854 EXPECT_EQ(PointF(4.2f, 6.2f).ToString(), f.bottom_right().ToString()); 855 } 856 857 TEST(RectTest, ManhattanDistanceToPoint) { 858 Rect i(1, 2, 3, 4); 859 EXPECT_EQ(0, i.ManhattanDistanceToPoint(Point(1, 2))); 860 EXPECT_EQ(0, i.ManhattanDistanceToPoint(Point(4, 6))); 861 EXPECT_EQ(0, i.ManhattanDistanceToPoint(Point(2, 4))); 862 EXPECT_EQ(3, i.ManhattanDistanceToPoint(Point(0, 0))); 863 EXPECT_EQ(2, i.ManhattanDistanceToPoint(Point(2, 0))); 864 EXPECT_EQ(3, i.ManhattanDistanceToPoint(Point(5, 0))); 865 EXPECT_EQ(1, i.ManhattanDistanceToPoint(Point(5, 4))); 866 EXPECT_EQ(3, i.ManhattanDistanceToPoint(Point(5, 8))); 867 EXPECT_EQ(2, i.ManhattanDistanceToPoint(Point(3, 8))); 868 EXPECT_EQ(2, i.ManhattanDistanceToPoint(Point(0, 7))); 869 EXPECT_EQ(1, i.ManhattanDistanceToPoint(Point(0, 3))); 870 871 RectF f(1.1f, 2.1f, 3.1f, 4.1f); 872 EXPECT_FLOAT_EQ(0.f, f.ManhattanDistanceToPoint(PointF(1.1f, 2.1f))); 873 EXPECT_FLOAT_EQ(0.f, f.ManhattanDistanceToPoint(PointF(4.2f, 6.f))); 874 EXPECT_FLOAT_EQ(0.f, f.ManhattanDistanceToPoint(PointF(2.f, 4.f))); 875 EXPECT_FLOAT_EQ(3.2f, f.ManhattanDistanceToPoint(PointF(0.f, 0.f))); 876 EXPECT_FLOAT_EQ(2.1f, f.ManhattanDistanceToPoint(PointF(2.f, 0.f))); 877 EXPECT_FLOAT_EQ(2.9f, f.ManhattanDistanceToPoint(PointF(5.f, 0.f))); 878 EXPECT_FLOAT_EQ(.8f, f.ManhattanDistanceToPoint(PointF(5.f, 4.f))); 879 EXPECT_FLOAT_EQ(2.6f, f.ManhattanDistanceToPoint(PointF(5.f, 8.f))); 880 EXPECT_FLOAT_EQ(1.8f, f.ManhattanDistanceToPoint(PointF(3.f, 8.f))); 881 EXPECT_FLOAT_EQ(1.9f, f.ManhattanDistanceToPoint(PointF(0.f, 7.f))); 882 EXPECT_FLOAT_EQ(1.1f, f.ManhattanDistanceToPoint(PointF(0.f, 3.f))); 883 } 884 885 TEST(RectTest, ManhattanInternalDistance) { 886 Rect i(0, 0, 400, 400); 887 EXPECT_EQ(0, i.ManhattanInternalDistance(gfx::Rect(-1, 0, 2, 1))); 888 EXPECT_EQ(1, i.ManhattanInternalDistance(gfx::Rect(400, 0, 1, 400))); 889 EXPECT_EQ(2, i.ManhattanInternalDistance(gfx::Rect(-100, -100, 100, 100))); 890 EXPECT_EQ(2, i.ManhattanInternalDistance(gfx::Rect(-101, 100, 100, 100))); 891 EXPECT_EQ(4, i.ManhattanInternalDistance(gfx::Rect(-101, -101, 100, 100))); 892 EXPECT_EQ(435, i.ManhattanInternalDistance(gfx::Rect(630, 603, 100, 100))); 893 894 RectF f(0.0f, 0.0f, 400.0f, 400.0f); 895 static const float kEpsilon = std::numeric_limits<float>::epsilon(); 896 897 EXPECT_FLOAT_EQ( 898 0.0f, f.ManhattanInternalDistance(gfx::RectF(-1.0f, 0.0f, 2.0f, 1.0f))); 899 EXPECT_FLOAT_EQ( 900 kEpsilon, 901 f.ManhattanInternalDistance(gfx::RectF(400.0f, 0.0f, 1.0f, 400.0f))); 902 EXPECT_FLOAT_EQ(2.0f * kEpsilon, 903 f.ManhattanInternalDistance( 904 gfx::RectF(-100.0f, -100.0f, 100.0f, 100.0f))); 905 EXPECT_FLOAT_EQ( 906 1.0f + kEpsilon, 907 f.ManhattanInternalDistance(gfx::RectF(-101.0f, 100.0f, 100.0f, 100.0f))); 908 EXPECT_FLOAT_EQ(2.0f + 2.0f * kEpsilon, 909 f.ManhattanInternalDistance( 910 gfx::RectF(-101.0f, -101.0f, 100.0f, 100.0f))); 911 EXPECT_FLOAT_EQ( 912 433.0f + 2.0f * kEpsilon, 913 f.ManhattanInternalDistance(gfx::RectF(630.0f, 603.0f, 100.0f, 100.0f))); 914 915 EXPECT_FLOAT_EQ( 916 0.0f, f.ManhattanInternalDistance(gfx::RectF(-1.0f, 0.0f, 1.1f, 1.0f))); 917 EXPECT_FLOAT_EQ( 918 0.1f + kEpsilon, 919 f.ManhattanInternalDistance(gfx::RectF(-1.5f, 0.0f, 1.4f, 1.0f))); 920 EXPECT_FLOAT_EQ( 921 kEpsilon, 922 f.ManhattanInternalDistance(gfx::RectF(-1.5f, 0.0f, 1.5f, 1.0f))); 923 } 924 925 } // namespace gfx 926