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