tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestRect.cpp (27937B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 #include <limits>
      7 
      8 #include "gtest/gtest.h"
      9 
     10 #include "gfxTypes.h"
     11 #include "nsRect.h"
     12 #include "nsRectAbsolute.h"
     13 #include "gfxRect.h"
     14 #include "mozilla/gfx/Point.h"
     15 #include "mozilla/gfx/Rect.h"
     16 #include "mozilla/gfx/RectAbsolute.h"
     17 #include "mozilla/WritingModes.h"
     18 #ifdef XP_WIN
     19 #  include <windows.h>
     20 #endif
     21 
     22 using mozilla::CSSCoord;
     23 using mozilla::CSSIntCoord;
     24 using mozilla::CSSIntSize;
     25 using mozilla::ScreenIntCoord;
     26 using mozilla::gfx::IntPoint;
     27 using mozilla::gfx::IntRect;
     28 using mozilla::gfx::IntRectAbsolute;
     29 using mozilla::gfx::Rect;
     30 
     31 static_assert(std::is_constructible_v<CSSIntSize, CSSIntCoord, CSSIntCoord>);
     32 static_assert(
     33    !std::is_constructible_v<CSSIntSize, ScreenIntCoord, ScreenIntCoord>);
     34 static_assert(std::is_constructible_v<CSSIntSize, int, int>);
     35 static_assert(!std::is_constructible_v<CSSIntSize, float, float>);
     36 
     37 static_assert(std::is_same_v<CSSIntCoord, decltype(CSSIntCoord() * 42)>);
     38 static_assert(std::is_same_v<CSSCoord, decltype(CSSCoord() * 42)>);
     39 static_assert(std::is_same_v<CSSCoord, decltype(CSSIntCoord() * 42.f)>);
     40 static_assert(std::is_same_v<CSSCoord, decltype(CSSCoord() * 42.f)>);
     41 
     42 template <class RectType>
     43 static bool TestConstructors() {
     44  // Create a rectangle
     45  RectType rect1(10, 20, 30, 40);
     46 
     47  // Make sure the rectangle was properly initialized
     48  EXPECT_TRUE(rect1.IsEqualRect(10, 20, 30, 40) && rect1.IsEqualXY(10, 20) &&
     49              rect1.IsEqualSize(30, 40))
     50      << "[1] Make sure the rectangle was properly initialized with "
     51         "constructor";
     52 
     53  // Create a second rect using the copy constructor
     54  RectType rect2(rect1);
     55 
     56  // Make sure the rectangle was properly initialized
     57  EXPECT_TRUE(rect2.IsEqualEdges(rect1) &&
     58              rect2.IsEqualXY(rect1.X(), rect1.Y()) &&
     59              rect2.IsEqualSize(rect1.Width(), rect1.Height()))
     60      << "[2] Make sure the rectangle was properly initialized with copy "
     61         "constructor";
     62 
     63  EXPECT_TRUE(!rect1.IsEmpty() && !rect1.IsZeroArea() && rect1.IsFinite() &&
     64              !rect2.IsEmpty() && !rect2.IsZeroArea() && rect2.IsFinite())
     65      << "[3] These rectangles are not empty and are finite";
     66 
     67  rect1.SetRect(1, 2, 30, 40);
     68  EXPECT_TRUE(rect1.X() == 1 && rect1.Y() == 2 && rect1.Width() == 30 &&
     69              rect1.Height() == 40 && rect1.XMost() == 31 &&
     70              rect1.YMost() == 42);
     71 
     72  rect1.SetRectX(11, 50);
     73  EXPECT_TRUE(rect1.X() == 11 && rect1.Y() == 2 && rect1.Width() == 50 &&
     74              rect1.Height() == 40 && rect1.XMost() == 61 &&
     75              rect1.YMost() == 42);
     76 
     77  rect1.SetRectY(22, 60);
     78  EXPECT_TRUE(rect1.X() == 11 && rect1.Y() == 22 && rect1.Width() == 50 &&
     79              rect1.Height() == 60 && rect1.XMost() == 61 &&
     80              rect1.YMost() == 82);
     81 
     82  rect1.SetBox(1, 2, 31, 42);
     83  EXPECT_TRUE(rect1.X() == 1 && rect1.Y() == 2 && rect1.Width() == 30 &&
     84              rect1.Height() == 40 && rect1.XMost() == 31 &&
     85              rect1.YMost() == 42);
     86 
     87  rect1.SetBoxX(11, 61);
     88  EXPECT_TRUE(rect1.X() == 11 && rect1.Y() == 2 && rect1.Width() == 50 &&
     89              rect1.Height() == 40 && rect1.XMost() == 61 &&
     90              rect1.YMost() == 42);
     91 
     92  rect1.SetBoxY(22, 82);
     93  EXPECT_TRUE(rect1.X() == 11 && rect1.Y() == 22 && rect1.Width() == 50 &&
     94              rect1.Height() == 60 && rect1.XMost() == 61 &&
     95              rect1.YMost() == 82);
     96 
     97  rect1.SetRect(1, 2, 30, 40);
     98  EXPECT_TRUE(rect1.X() == 1 && rect1.Y() == 2 && rect1.Width() == 30 &&
     99              rect1.Height() == 40 && rect1.XMost() == 31 &&
    100              rect1.YMost() == 42);
    101 
    102  rect1.MoveByX(10);
    103  EXPECT_TRUE(rect1.X() == 11 && rect1.Y() == 2 && rect1.Width() == 30 &&
    104              rect1.Height() == 40 && rect1.XMost() == 41 &&
    105              rect1.YMost() == 42);
    106 
    107  rect1.MoveByY(20);
    108  EXPECT_TRUE(rect1.X() == 11 && rect1.Y() == 22 && rect1.Width() == 30 &&
    109              rect1.Height() == 40 && rect1.XMost() == 41 &&
    110              rect1.YMost() == 62);
    111 
    112  return true;
    113 }
    114 
    115 template <class RectType>
    116 static bool TestEqualityOperator() {
    117  RectType rect1(10, 20, 30, 40);
    118  RectType rect2(rect1);
    119 
    120  // Test the equality operator
    121  EXPECT_TRUE(rect1 == rect2) << "[1] Test the equality operator";
    122 
    123  EXPECT_FALSE(!rect1.IsEqualInterior(rect2))
    124      << "[2] Test the inequality operator";
    125 
    126  // Make sure that two empty rects are equal
    127  rect1.SetEmpty();
    128  rect2.SetEmpty();
    129  EXPECT_TRUE(rect1 == rect2) << "[3] Make sure that two empty rects are equal";
    130 
    131  return true;
    132 }
    133 
    134 template <class RectType, class UnitType>
    135 static bool TestContainment() {
    136  RectType rect1(10, 10, 50, 50);
    137 
    138  // Test the point containment methods
    139  //
    140 
    141  // Basic test of a point in the middle of the rect
    142  EXPECT_TRUE(rect1.Contains(rect1.Center()) &&
    143              rect1.ContainsX(rect1.Center().x) &&
    144              rect1.ContainsY(rect1.Center().y))
    145      << "[1] Basic test of a point in the middle of the rect";
    146 
    147  // Test against a point at the left/top edges
    148  EXPECT_TRUE(rect1.Contains(rect1.X(), rect1.Y()) &&
    149              rect1.ContainsX(rect1.X()) && rect1.ContainsY(rect1.Y()))
    150      << "[2] Test against a point at the left/top edges";
    151 
    152  // Test against a point at the right/bottom extents
    153  EXPECT_FALSE(rect1.Contains(rect1.XMost(), rect1.YMost()) ||
    154               rect1.ContainsX(rect1.XMost()) || rect1.ContainsY(rect1.YMost()))
    155      << "[3] Test against a point at the right/bottom extents";
    156 
    157  // Test the rect containment methods
    158  //
    159  RectType rect2(rect1);
    160 
    161  // Test against a rect that's the same as rect1
    162  EXPECT_FALSE(!rect1.Contains(rect2))
    163      << "[4] Test against a rect that's the same as rect1";
    164 
    165  // Test against a rect whose left edge (only) is outside of rect1
    166  rect2.MoveByX(-1);
    167  EXPECT_FALSE(rect1.Contains(rect2))
    168      << "[5] Test against a rect whose left edge (only) is outside of rect1";
    169  rect2.MoveByX(1);
    170 
    171  // Test against a rect whose top edge (only) is outside of rect1
    172  rect2.MoveByY(-1);
    173  EXPECT_FALSE(rect1.Contains(rect2))
    174      << "[6] Test against a rect whose top edge (only) is outside of rect1";
    175  rect2.MoveByY(1);
    176 
    177  // Test against a rect whose right edge (only) is outside of rect1
    178  rect2.MoveByX(1);
    179  EXPECT_FALSE(rect1.Contains(rect2))
    180      << "[7] Test against a rect whose right edge (only) is outside of rect1";
    181  rect2.MoveByX(-1);
    182 
    183  // Test against a rect whose bottom edge (only) is outside of rect1
    184  rect2.MoveByY(1);
    185  EXPECT_FALSE(rect1.Contains(rect2))
    186      << "[8] Test against a rect whose bottom edge (only) is outside of rect1";
    187  rect2.MoveByY(-1);
    188 
    189  // Test rects approaching numeric limits can contain rects
    190  RectType rectLarge(10, 10, std::numeric_limits<UnitType>::max(),
    191                     std::numeric_limits<UnitType>::max());
    192  EXPECT_TRUE(rectLarge.Contains(rect2))
    193      << "[9] Test rect at numeric limits against a smaller rect";
    194 
    195  return true;
    196 }
    197 
    198 // Test the method that returns a boolean result but doesn't return a
    199 // a rectangle
    200 template <class RectType>
    201 static bool TestIntersects() {
    202  RectType rect1(10, 10, 50, 50);
    203  RectType rect2(rect1);
    204 
    205  // Test against a rect that's the same as rect1
    206  EXPECT_FALSE(!rect1.Intersects(rect2))
    207      << "[1] Test against a rect that's the same as rect1";
    208 
    209  // Test against a rect that's enclosed by rect1
    210  rect2.Inflate(-1, -1);
    211  EXPECT_FALSE(!rect1.Contains(rect2) || !rect1.Intersects(rect2))
    212      << "[2] Test against a rect that's enclosed by rect1";
    213  rect2.Inflate(1, 1);
    214 
    215  // Make sure inflate and deflate worked correctly
    216  EXPECT_TRUE(rect1.IsEqualInterior(rect2))
    217      << "[3] Make sure inflate and deflate worked correctly";
    218 
    219  // Test against a rect that overlaps the left edge of rect1
    220  rect2.MoveByX(-1);
    221  EXPECT_FALSE(!rect1.Intersects(rect2))
    222      << "[4] Test against a rect that overlaps the left edge of rect1";
    223  rect2.MoveByX(1);
    224 
    225  // Test against a rect that's outside of rect1 on the left
    226  rect2.MoveByX(-rect2.Width());
    227  EXPECT_FALSE(rect1.Intersects(rect2))
    228      << "[5] Test against a rect that's outside of rect1 on the left";
    229  rect2.MoveByX(rect2.Width());
    230 
    231  // Test against a rect that overlaps the top edge of rect1
    232  rect2.MoveByY(-1);
    233  EXPECT_FALSE(!rect1.Intersects(rect2))
    234      << "[6] Test against a rect that overlaps the top edge of rect1";
    235  rect2.MoveByY(1);
    236 
    237  // Test against a rect that's outside of rect1 on the top
    238  rect2.MoveByY(-rect2.Height());
    239  EXPECT_FALSE(rect1.Intersects(rect2))
    240      << "[7] Test against a rect that's outside of rect1 on the top";
    241  rect2.MoveByY(rect2.Height());
    242 
    243  // Test against a rect that overlaps the right edge of rect1
    244  rect2.MoveByX(1);
    245  EXPECT_FALSE(!rect1.Intersects(rect2))
    246      << "[8] Test against a rect that overlaps the right edge of rect1";
    247  rect2.MoveByX(-1);
    248 
    249  // Test against a rect that's outside of rect1 on the right
    250  rect2.MoveByX(rect2.Width());
    251  EXPECT_FALSE(rect1.Intersects(rect2))
    252      << "[9] Test against a rect that's outside of rect1 on the right";
    253  rect2.MoveByX(-rect2.Width());
    254 
    255  // Test against a rect that overlaps the bottom edge of rect1
    256  rect2.MoveByY(1);
    257  EXPECT_FALSE(!rect1.Intersects(rect2))
    258      << "[10] Test against a rect that overlaps the bottom edge of rect1";
    259  rect2.MoveByY(-1);
    260 
    261  // Test against a rect that's outside of rect1 on the bottom
    262  rect2.MoveByY(rect2.Height());
    263  EXPECT_FALSE(rect1.Intersects(rect2))
    264      << "[11] Test against a rect that's outside of rect1 on the bottom";
    265  rect2.MoveByY(-rect2.Height());
    266 
    267  return true;
    268 }
    269 
    270 // Test the method that returns a boolean result and an intersection rect
    271 template <class RectType>
    272 static bool TestIntersection() {
    273  RectType rect1(10, 10, 50, 50);
    274  RectType rect2(rect1);
    275  RectType dest;
    276 
    277  // Test against a rect that's the same as rect1
    278  EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) ||
    279               !(dest.IsEqualInterior(rect1)))
    280      << "[1] Test against a rect that's the same as rect1";
    281 
    282  // Test against a rect that's enclosed by rect1
    283  rect2.Inflate(-1, -1);
    284  EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) ||
    285               !(dest.IsEqualInterior(rect2)))
    286      << "[2] Test against a rect that's enclosed by rect1";
    287  rect2.Inflate(1, 1);
    288 
    289  // Test against a rect that overlaps the left edge of rect1
    290  rect2.MoveByX(-1);
    291  EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) ||
    292               !(dest.IsEqualInterior(RectType(
    293                   rect1.X(), rect1.Y(), rect1.Width() - 1, rect1.Height()))))
    294      << "[3] Test against a rect that overlaps the left edge of rect1";
    295  rect2.MoveByX(1);
    296 
    297  // Test against a rect that's outside of rect1 on the left
    298  rect2.MoveByX(-rect2.Width());
    299  EXPECT_FALSE(dest.IntersectRect(rect1, rect2))
    300      << "[4] Test against a rect that's outside of rect1 on the left";
    301  // Make sure an empty rect is returned
    302  EXPECT_TRUE(dest.IsEmpty() && dest.IsZeroArea())
    303      << "[4] Make sure an empty rect is returned";
    304  EXPECT_TRUE(dest.IsFinite()) << "[4b] Should be finite";
    305  rect2.MoveByX(rect2.Width());
    306 
    307  // Test against a rect that overlaps the top edge of rect1
    308  rect2.MoveByY(-1);
    309  EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) ||
    310               !(dest.IsEqualInterior(RectType(
    311                   rect1.X(), rect1.Y(), rect1.Width(), rect1.Height() - 1))))
    312      << "[5] Test against a rect that overlaps the top edge of rect1";
    313  EXPECT_TRUE(dest.IsFinite()) << "[5b] Should be finite";
    314  rect2.MoveByY(1);
    315 
    316  // Test against a rect that's outside of rect1 on the top
    317  rect2.MoveByY(-rect2.Height());
    318  EXPECT_FALSE(dest.IntersectRect(rect1, rect2))
    319      << "[6] Test against a rect that's outside of rect1 on the top";
    320  // Make sure an empty rect is returned
    321  EXPECT_TRUE(dest.IsEmpty() && dest.IsZeroArea())
    322      << "[6] Make sure an empty rect is returned";
    323  EXPECT_TRUE(dest.IsFinite()) << "[6b] Should be finite";
    324  rect2.MoveByY(rect2.Height());
    325 
    326  // Test against a rect that overlaps the right edge of rect1
    327  rect2.MoveByX(1);
    328  EXPECT_FALSE(
    329      !dest.IntersectRect(rect1, rect2) ||
    330      !(dest.IsEqualInterior(RectType(rect1.X() + 1, rect1.Y(),
    331                                      rect1.Width() - 1, rect1.Height()))))
    332      << "[7] Test against a rect that overlaps the right edge of rect1";
    333  rect2.MoveByX(-1);
    334 
    335  // Test against a rect that's outside of rect1 on the right
    336  rect2.MoveByX(rect2.Width());
    337  EXPECT_FALSE(dest.IntersectRect(rect1, rect2))
    338      << "[8] Test against a rect that's outside of rect1 on the right";
    339  // Make sure an empty rect is returned
    340  EXPECT_TRUE(dest.IsEmpty() && dest.IsZeroArea())
    341      << "[8] Make sure an empty rect is returned";
    342  EXPECT_TRUE(dest.IsFinite()) << "[8b] Should be finite";
    343  rect2.MoveByX(-rect2.Width());
    344 
    345  // Test against a rect that overlaps the bottom edge of rect1
    346  rect2.MoveByY(1);
    347  EXPECT_FALSE(
    348      !dest.IntersectRect(rect1, rect2) ||
    349      !(dest.IsEqualInterior(RectType(rect1.X(), rect1.Y() + 1, rect1.Width(),
    350                                      rect1.Height() - 1))))
    351      << "[9] Test against a rect that overlaps the bottom edge of rect1";
    352  EXPECT_TRUE(dest.IsFinite()) << "[9b] Should be finite";
    353  rect2.MoveByY(-1);
    354 
    355  // Test against a rect that's outside of rect1 on the bottom
    356  rect2.MoveByY(rect2.Height());
    357  EXPECT_FALSE(dest.IntersectRect(rect1, rect2))
    358      << "[10] Test against a rect that's outside of rect1 on the bottom";
    359  // Make sure an empty rect is returned
    360  EXPECT_TRUE(dest.IsEmpty() && dest.IsZeroArea())
    361      << "[10] Make sure an empty rect is returned";
    362  EXPECT_TRUE(dest.IsFinite()) << "[10b] Should be finite";
    363  rect2.MoveByY(-rect2.Height());
    364 
    365  // Test against a rect with zero width or height
    366  rect1.SetRect(100, 100, 100, 100);
    367  rect2.SetRect(150, 100, 0, 100);
    368  EXPECT_TRUE(!dest.IntersectRect(rect1, rect2) && dest.IsEmpty() &&
    369              dest.IsZeroArea())
    370      << "[11] Intersection of rects with zero width or height should be empty";
    371  EXPECT_TRUE(dest.IsFinite()) << "[11b] Should be finite";
    372 
    373  // Tests against a rect with negative width or height
    374  //
    375 
    376  // Test against a rect with negative width
    377  rect1.SetRect(100, 100, 100, 100);
    378  rect2.SetRect(100, 100, -100, 100);
    379  EXPECT_TRUE(!dest.IntersectRect(rect1, rect2) && dest.IsEmpty() &&
    380              dest.IsZeroArea())
    381      << "[12] Intersection of rects with negative width or height should be "
    382         "empty";
    383  EXPECT_TRUE(dest.IsFinite()) << "[12b] Should be finite";
    384 
    385  // Those two rects exactly overlap in some way...
    386  // but we still want to return an empty rect
    387  rect1.SetRect(100, 100, 100, 100);
    388  rect2.SetRect(200, 200, -100, -100);
    389  EXPECT_TRUE(!dest.IntersectRect(rect1, rect2) && dest.IsEmpty() &&
    390              dest.IsZeroArea())
    391      << "[13] Intersection of rects with negative width or height should be "
    392         "empty";
    393  EXPECT_TRUE(dest.IsFinite()) << "[13b] Should be finite";
    394 
    395  // Test against two identical rects with negative height
    396  rect1.SetRect(100, 100, 100, -100);
    397  rect2.SetRect(100, 100, 100, -100);
    398  EXPECT_TRUE(!dest.IntersectRect(rect1, rect2) && dest.IsEmpty() &&
    399              dest.IsZeroArea())
    400      << "[14] Intersection of rects with negative width or height should be "
    401         "empty";
    402  EXPECT_TRUE(dest.IsFinite()) << "[14b] Should be finite";
    403 
    404  return true;
    405 }
    406 
    407 template <class RectType>
    408 static bool TestUnion() {
    409  RectType rect1;
    410  RectType rect2(10, 10, 50, 50);
    411  RectType dest;
    412 
    413  // Check the case where the receiver is an empty rect
    414  rect1.SetEmpty();
    415  dest.UnionRect(rect1, rect2);
    416  EXPECT_TRUE(!dest.IsEmpty() && !dest.IsZeroArea() &&
    417              dest.IsEqualInterior(rect2))
    418      << "[1] Check the case where the receiver is an empty rect";
    419  EXPECT_TRUE(dest.IsFinite()) << "[1b] Should be finite";
    420 
    421  // Check the case where the source rect is an empty rect
    422  rect1 = rect2;
    423  rect2.SetEmpty();
    424  dest.UnionRect(rect1, rect2);
    425  EXPECT_TRUE(!dest.IsEmpty() && !dest.IsZeroArea() &&
    426              dest.IsEqualInterior(rect1))
    427      << "[2] Check the case where the source rect is an empty rect";
    428  EXPECT_TRUE(dest.IsFinite()) << "[2b] Should be finite";
    429 
    430  // Test the case where both rects are empty
    431  rect1.SetEmpty();
    432  rect2.SetEmpty();
    433  dest.UnionRect(rect1, rect2);
    434  EXPECT_TRUE(dest.IsEmpty() && dest.IsZeroArea())
    435      << "[3] Test the case where both rects are empty";
    436  EXPECT_TRUE(dest.IsFinite()) << "[3b] Should be finite";
    437 
    438  // Test union case where the two rects don't overlap at all
    439  rect1.SetRect(10, 10, 50, 50);
    440  rect2.SetRect(100, 100, 50, 50);
    441  dest.UnionRect(rect1, rect2);
    442  EXPECT_TRUE(!dest.IsEmpty() && !dest.IsZeroArea() &&
    443              (dest.IsEqualInterior(RectType(rect1.X(), rect1.Y(),
    444                                             rect2.XMost() - rect1.X(),
    445                                             rect2.YMost() - rect1.Y()))))
    446      << "[4] Test union case where the two rects don't overlap at all";
    447  EXPECT_TRUE(dest.IsFinite()) << "[4b] Should be finite";
    448 
    449  // Test union case where the two rects overlap
    450  rect1.SetRect(30, 30, 50, 50);
    451  rect2.SetRect(10, 10, 50, 50);
    452  dest.UnionRect(rect1, rect2);
    453  EXPECT_TRUE(!dest.IsEmpty() && !dest.IsZeroArea() &&
    454              (dest.IsEqualInterior(RectType(rect2.X(), rect2.Y(),
    455                                             rect1.XMost() - rect2.X(),
    456                                             rect1.YMost() - rect2.Y()))))
    457      << "[5] Test union case where the two rects overlap";
    458  EXPECT_TRUE(dest.IsFinite()) << "[5b] Should be finite";
    459 
    460  return true;
    461 }
    462 
    463 template <class RectType>
    464 static void TestUnionEmptyRects() {
    465  RectType rect1(10, 10, 0, 50);
    466  RectType rect2(5, 5, 40, 0);
    467  EXPECT_TRUE(rect1.IsEmpty() && rect2.IsEmpty());
    468 
    469  RectType dest = rect1.Union(rect2);
    470  EXPECT_TRUE(dest.IsEmpty() && dest.IsEqualEdges(rect2))
    471      << "Test the case where both rects are empty, and the result is the "
    472         "same value passing into Union()";
    473 }
    474 
    475 static bool TestFiniteGfx() {
    476  float posInf = std::numeric_limits<float>::infinity();
    477  float negInf = -std::numeric_limits<float>::infinity();
    478  float justNaN = std::numeric_limits<float>::quiet_NaN();
    479 
    480  gfxFloat values[4] = {5.0, 10.0, 15.0, 20.0};
    481 
    482  // Try the "non-finite" values for x, y, width, height, one at a time
    483  for (int i = 0; i < 4; i += 1) {
    484    values[i] = posInf;
    485    gfxRect rectPosInf(values[0], values[1], values[2], values[3]);
    486    EXPECT_FALSE(rectPosInf.IsFinite())
    487        << "For +inf (" << values[0] << "," << values[1] << "," << values[2]
    488        << "," << values[3] << ")";
    489 
    490    values[i] = negInf;
    491    gfxRect rectNegInf(values[0], values[1], values[2], values[3]);
    492    EXPECT_FALSE(rectNegInf.IsFinite())
    493        << "For -inf (" << values[0] << "," << values[1] << "," << values[2]
    494        << "," << values[3] << ")";
    495 
    496    values[i] = justNaN;
    497    gfxRect rectNaN(values[0], values[1], values[2], values[3]);
    498    EXPECT_FALSE(rectNaN.IsFinite())
    499        << "For NaN (" << values[0] << "," << values[1] << "," << values[2]
    500        << "," << values[3] << ")";
    501 
    502    // Reset to a finite value...
    503    values[i] = 5.0 * i;
    504  }
    505 
    506  return true;
    507 }
    508 
    509 // We want to test nsRect values that are still in range but where
    510 // the implementation is at risk of overflowing
    511 template <class RectType>
    512 static bool TestBug1135677() {
    513  RectType rect1(1073741344, 1073741344, 1073756696, 1073819936);
    514  RectType rect2(1073741820, 1073741820, 14400, 77640);
    515  RectType dest;
    516 
    517  dest = rect1.Intersect(rect2);
    518 
    519  EXPECT_TRUE(dest.IsEqualRect(1073741820, 1073741820, 14400, 77640))
    520      << "[1] Operation should not overflow internally.";
    521 
    522  return true;
    523 }
    524 
    525 template <class RectType>
    526 static bool TestSetWH() {
    527  RectType rect(1, 2, 3, 4);
    528  EXPECT_TRUE(rect.IsEqualRect(1, 2, 3, 4));
    529  rect.SetWidth(13);
    530  EXPECT_TRUE(rect.IsEqualRect(1, 2, 13, 4));
    531  rect.SetHeight(14);
    532  EXPECT_TRUE(rect.IsEqualRect(1, 2, 13, 14));
    533  rect.SizeTo(23, 24);
    534  EXPECT_TRUE(rect.IsEqualRect(1, 2, 23, 24));
    535  return true;
    536 }
    537 
    538 template <class RectType>
    539 static bool TestSwap() {
    540  RectType rect(1, 2, 3, 4);
    541  EXPECT_TRUE(rect.IsEqualRect(1, 2, 3, 4));
    542  rect.Swap();
    543  EXPECT_TRUE(rect.IsEqualRect(2, 1, 4, 3));
    544  return true;
    545 }
    546 
    547 static void TestIntersectionLogicalHelper(nscoord x1, nscoord y1, nscoord w1,
    548                                          nscoord h1, nscoord x2, nscoord y2,
    549                                          nscoord w2, nscoord h2, nscoord xR,
    550                                          nscoord yR, nscoord wR, nscoord hR,
    551                                          bool isNonEmpty) {
    552  nsRect rect1(x1, y1, w1, h1);
    553  nsRect rect2(x2, y2, w2, h2);
    554  nsRect rectDebug;
    555  EXPECT_TRUE(isNonEmpty == rectDebug.IntersectRect(rect1, rect2));
    556  EXPECT_TRUE(rectDebug.IsEqualEdges(nsRect(xR, yR, wR, hR)));
    557 
    558  mozilla::LogicalRect r1(mozilla::WritingMode(), rect1.X(), rect1.Y(),
    559                          rect1.Width(), rect1.Height());
    560  mozilla::LogicalRect r2(mozilla::WritingMode(), rect2.X(), rect2.Y(),
    561                          rect2.Width(), rect2.Height());
    562  EXPECT_TRUE(isNonEmpty == r1.IntersectRect(r1, r2));
    563  EXPECT_TRUE(rectDebug.IsEqualEdges(nsRect(
    564      r1.IStart(mozilla::WritingMode()), r1.BStart(mozilla::WritingMode()),
    565      r1.ISize(mozilla::WritingMode()), r1.BSize(mozilla::WritingMode()))));
    566 
    567  mozilla::LogicalRect r3(mozilla::WritingMode(), rect1.X(), rect1.Y(),
    568                          rect1.Width(), rect1.Height());
    569  mozilla::LogicalRect r4(mozilla::WritingMode(), rect2.X(), rect2.Y(),
    570                          rect2.Width(), rect2.Height());
    571  EXPECT_TRUE(isNonEmpty == r4.IntersectRect(r3, r4));
    572  EXPECT_TRUE(rectDebug.IsEqualEdges(nsRect(
    573      r4.IStart(mozilla::WritingMode()), r4.BStart(mozilla::WritingMode()),
    574      r4.ISize(mozilla::WritingMode()), r4.BSize(mozilla::WritingMode()))));
    575 
    576  mozilla::LogicalRect r5(mozilla::WritingMode(), rect1.X(), rect1.Y(),
    577                          rect1.Width(), rect1.Height());
    578  mozilla::LogicalRect r6(mozilla::WritingMode(), rect2.X(), rect2.Y(),
    579                          rect2.Width(), rect2.Height());
    580  mozilla::LogicalRect r7(mozilla::WritingMode(), 0, 0, 1, 1);
    581  EXPECT_TRUE(isNonEmpty == r7.IntersectRect(r5, r6));
    582  EXPECT_TRUE(rectDebug.IsEqualEdges(nsRect(
    583      r7.IStart(mozilla::WritingMode()), r7.BStart(mozilla::WritingMode()),
    584      r7.ISize(mozilla::WritingMode()), r7.BSize(mozilla::WritingMode()))));
    585 }
    586 
    587 static void TestIntersectionLogical(nscoord x1, nscoord y1, nscoord w1,
    588                                    nscoord h1, nscoord x2, nscoord y2,
    589                                    nscoord w2, nscoord h2, nscoord xR,
    590                                    nscoord yR, nscoord wR, nscoord hR,
    591                                    bool isNonEmpty) {
    592  TestIntersectionLogicalHelper(x1, y1, w1, h1, x2, y2, w2, h2, xR, yR, wR, hR,
    593                                isNonEmpty);
    594  TestIntersectionLogicalHelper(x2, y2, w2, h2, x1, y1, w1, h1, xR, yR, wR, hR,
    595                                isNonEmpty);
    596 }
    597 
    598 TEST(Gfx, Logical)
    599 {
    600  TestIntersectionLogical(578, 0, 2650, 1152, 1036, 0, 2312, 1, 1036, 0, 2192,
    601                          1, true);
    602  TestIntersectionLogical(0, 0, 1000, 1000, 500, 500, 1000, 1000, 500, 500, 500,
    603                          500, true);
    604  TestIntersectionLogical(100, 200, 300, 400, 50, 250, 100, 100, 100, 250, 50,
    605                          100, true);
    606  TestIntersectionLogical(0, 100, 200, 300, 300, 100, 100, 300, 300, 100, 0, 0,
    607                          false);
    608 }
    609 
    610 TEST(Gfx, nsRect)
    611 {
    612  TestConstructors<nsRect>();
    613  TestEqualityOperator<nsRect>();
    614  TestContainment<nsRect, nscoord>();
    615  TestIntersects<nsRect>();
    616  TestIntersection<nsRect>();
    617  TestUnion<nsRect>();
    618  TestUnionEmptyRects<nsRect>();
    619  TestBug1135677<nsRect>();
    620  TestSetWH<nsRect>();
    621  TestSwap<nsRect>();
    622 }
    623 
    624 TEST(Gfx, nsIntRect)
    625 {
    626  TestConstructors<nsIntRect>();
    627  TestEqualityOperator<nsIntRect>();
    628  TestContainment<nsIntRect, int32_t>();
    629  TestIntersects<nsIntRect>();
    630  TestIntersection<nsIntRect>();
    631  TestUnion<nsIntRect>();
    632  TestUnionEmptyRects<nsIntRect>();
    633  TestBug1135677<nsIntRect>();
    634  TestSetWH<nsIntRect>();
    635  TestSwap<nsIntRect>();
    636 }
    637 
    638 TEST(Gfx, gfxRect)
    639 {
    640  TestConstructors<gfxRect>();
    641  // Skip TestEqualityOperator<gfxRect>(); as gfxRect::operator== is private
    642  TestContainment<gfxRect, double>();
    643  TestIntersects<gfxRect>();
    644  TestIntersection<gfxRect>();
    645  TestUnion<gfxRect>();
    646  TestUnionEmptyRects<gfxRect>();
    647  TestBug1135677<gfxRect>();
    648  TestFiniteGfx();
    649  TestSetWH<gfxRect>();
    650  TestSwap<gfxRect>();
    651 }
    652 
    653 TEST(Gfx, nsRectAbsolute)
    654 {
    655  TestUnionEmptyRects<nsRectAbsolute>();
    656 }
    657 
    658 TEST(Gfx, IntRectAbsolute)
    659 {
    660  TestUnionEmptyRects<IntRectAbsolute>();
    661 }
    662 
    663 static void TestMoveInsideAndClamp(IntRect aSrc, IntRect aTarget,
    664                                   IntRect aExpected) {
    665  // Test the implementation in BaseRect (x/y/width/height representation)
    666  IntRect result = aSrc.MoveInsideAndClamp(aTarget);
    667  EXPECT_TRUE(result.IsEqualEdges(aExpected))
    668      << "Source " << aSrc << " Target " << aTarget << " Expected " << aExpected
    669      << " Actual " << result;
    670 
    671  // Also test the implementation in RectAbsolute (left/top/right/bottom
    672  // representation)
    673  IntRectAbsolute absSrc = IntRectAbsolute::FromRect(aSrc);
    674  IntRectAbsolute absTarget = IntRectAbsolute::FromRect(aTarget);
    675  IntRectAbsolute absExpected = IntRectAbsolute::FromRect(aExpected);
    676 
    677  IntRectAbsolute absResult = absSrc.MoveInsideAndClamp(absTarget);
    678  EXPECT_TRUE(absResult.IsEqualEdges(absExpected))
    679      << "AbsSource " << absSrc << " AbsTarget " << absTarget << " AbsExpected "
    680      << absExpected << " AbsActual " << absResult;
    681 }
    682 
    683 TEST(Gfx, MoveInsideAndClamp)
    684 {
    685  TestMoveInsideAndClamp(IntRect(0, 0, 10, 10), IntRect(1, -1, 10, 10),
    686                         IntRect(1, -1, 10, 10));
    687  TestMoveInsideAndClamp(IntRect(0, 0, 10, 10), IntRect(-1, -1, 12, 5),
    688                         IntRect(0, -1, 10, 5));
    689  TestMoveInsideAndClamp(IntRect(0, 0, 10, 10), IntRect(10, 11, 10, 0),
    690                         IntRect(10, 11, 10, 0));
    691  TestMoveInsideAndClamp(IntRect(0, 0, 10, 10), IntRect(-10, -1, 10, 0),
    692                         IntRect(-10, -1, 10, 0));
    693  TestMoveInsideAndClamp(IntRect(0, 0, 0, 0), IntRect(10, -10, 10, 10),
    694                         IntRect(10, 0, 0, 0));
    695 }
    696 
    697 TEST(Gfx, ClampPoint)
    698 {
    699  /* Various bounds */
    700  IntRect Square(0, 0, 10, 10);
    701  EXPECT_EQ(Square.ClampPoint(IntPoint(-5, -5)), IntPoint(0, 0));
    702  EXPECT_EQ(Square.ClampPoint(IntPoint(-5, 5)), IntPoint(0, 5));
    703  EXPECT_EQ(Square.ClampPoint(IntPoint(-5, 15)), IntPoint(0, 10));
    704 
    705  EXPECT_EQ(Square.ClampPoint(IntPoint(5, -5)), IntPoint(5, 0));
    706  EXPECT_EQ(Square.ClampPoint(IntPoint(5, 5)), IntPoint(5, 5));
    707  EXPECT_EQ(Square.ClampPoint(IntPoint(5, 15)), IntPoint(5, 10));
    708 
    709  EXPECT_EQ(Square.ClampPoint(IntPoint(15, -5)), IntPoint(10, 0));
    710  EXPECT_EQ(Square.ClampPoint(IntPoint(15, 5)), IntPoint(10, 5));
    711  EXPECT_EQ(Square.ClampPoint(IntPoint(15, 15)), IntPoint(10, 10));
    712 
    713  /* Special case of empty rect */
    714  IntRect Empty(0, 0, -1, -1);
    715  EXPECT_TRUE(Empty.IsEmpty());
    716  EXPECT_EQ(Empty.ClampPoint(IntPoint(-1, -1)), IntPoint(0, 0));
    717  EXPECT_EQ(Empty.ClampPoint(IntPoint(-1, 1)), IntPoint(0, 0));
    718  EXPECT_EQ(Empty.ClampPoint(IntPoint(1, -1)), IntPoint(0, 0));
    719  EXPECT_EQ(Empty.ClampPoint(IntPoint(1, 1)), IntPoint(0, 0));
    720 }
    721 
    722 TEST(Gfx, SafeMoveBy)
    723 {
    724  IntRect intRect(0, 0, 10, 10);
    725  intRect.SafeMoveByX(10);
    726  intRect.SafeMoveByY(10);
    727  EXPECT_EQ(intRect, IntRect(10, 10, 10, 10));
    728 
    729  intRect = IntRect(0, 0, 10, 10);
    730  intRect.SafeMoveByX(-10);
    731  intRect.SafeMoveByY(-10);
    732  EXPECT_EQ(intRect, IntRect(-10, -10, 10, 10));
    733 
    734  Rect rect(0, 0, 10, 10);
    735  rect.SafeMoveByX(10);
    736  rect.SafeMoveByY(10);
    737  EXPECT_EQ(rect, Rect(10, 10, 10, 10));
    738 
    739  rect = Rect(0, 0, 10, 10);
    740  rect.SafeMoveByX(-10);
    741  rect.SafeMoveByY(-10);
    742  EXPECT_EQ(rect, Rect(-10, -10, 10, 10));
    743 }