Home | History | Annotate | Download | only in geometry
      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