• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stddef.h>
8 
9 #include "base/macros.h"
10 #include "build/build_config.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/gfx/geometry/rect.h"
13 #include "ui/gfx/geometry/rect_conversions.h"
14 #include "ui/gfx/test/gfx_util.h"
15 
16 #if defined(OS_WIN)
17 #include <windows.h>
18 #endif
19 
20 namespace gfx {
21 
TEST(RectTest,Contains)22 TEST(RectTest, Contains) {
23   static const struct ContainsCase {
24     int rect_x;
25     int rect_y;
26     int rect_width;
27     int rect_height;
28     int point_x;
29     int point_y;
30     bool contained;
31   } contains_cases[] = {
32     {0, 0, 10, 10, 0, 0, true},
33     {0, 0, 10, 10, 5, 5, true},
34     {0, 0, 10, 10, 9, 9, true},
35     {0, 0, 10, 10, 5, 10, false},
36     {0, 0, 10, 10, 10, 5, false},
37     {0, 0, 10, 10, -1, -1, false},
38     {0, 0, 10, 10, 50, 50, false},
39   #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
40     {0, 0, -10, -10, 0, 0, false},
41   #endif
42   };
43   for (size_t i = 0; i < arraysize(contains_cases); ++i) {
44     const ContainsCase& value = contains_cases[i];
45     Rect rect(value.rect_x, value.rect_y, value.rect_width, value.rect_height);
46     EXPECT_EQ(value.contained, rect.Contains(value.point_x, value.point_y));
47   }
48 }
49 
TEST(RectTest,Intersects)50 TEST(RectTest, Intersects) {
51   static const struct {
52     int x1;  // rect 1
53     int y1;
54     int w1;
55     int h1;
56     int x2;  // rect 2
57     int y2;
58     int w2;
59     int h2;
60     bool intersects;
61   } tests[] = {
62     { 0, 0, 0, 0, 0, 0, 0, 0, false },
63     { 0, 0, 0, 0, -10, -10, 20, 20, false },
64     { -10, 0, 0, 20, 0, -10, 20, 0, false },
65     { 0, 0, 10, 10, 0, 0, 10, 10, true },
66     { 0, 0, 10, 10, 10, 10, 10, 10, false },
67     { 10, 10, 10, 10, 0, 0, 10, 10, false },
68     { 10, 10, 10, 10, 5, 5, 10, 10, true },
69     { 10, 10, 10, 10, 15, 15, 10, 10, true },
70     { 10, 10, 10, 10, 20, 15, 10, 10, false },
71     { 10, 10, 10, 10, 21, 15, 10, 10, false }
72   };
73   for (size_t i = 0; i < arraysize(tests); ++i) {
74     Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
75     Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
76     EXPECT_EQ(tests[i].intersects, r1.Intersects(r2));
77     EXPECT_EQ(tests[i].intersects, r2.Intersects(r1));
78   }
79 }
80 
TEST(RectTest,Intersect)81 TEST(RectTest, Intersect) {
82   static const struct {
83     int x1;  // rect 1
84     int y1;
85     int w1;
86     int h1;
87     int x2;  // rect 2
88     int y2;
89     int w2;
90     int h2;
91     int x3;  // rect 3: the union of rects 1 and 2
92     int y3;
93     int w3;
94     int h3;
95   } tests[] = {
96     { 0, 0, 0, 0,   // zeros
97       0, 0, 0, 0,
98       0, 0, 0, 0 },
99     { 0, 0, 4, 4,   // equal
100       0, 0, 4, 4,
101       0, 0, 4, 4 },
102     { 0, 0, 4, 4,   // neighboring
103       4, 4, 4, 4,
104       0, 0, 0, 0 },
105     { 0, 0, 4, 4,   // overlapping corners
106       2, 2, 4, 4,
107       2, 2, 2, 2 },
108     { 0, 0, 4, 4,   // T junction
109       3, 1, 4, 2,
110       3, 1, 1, 2 },
111     { 3, 0, 2, 2,   // gap
112       0, 0, 2, 2,
113       0, 0, 0, 0 }
114   };
115   for (size_t i = 0; i < arraysize(tests); ++i) {
116     Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
117     Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
118     Rect r3(tests[i].x3, tests[i].y3, tests[i].w3, tests[i].h3);
119     Rect ir = IntersectRects(r1, r2);
120     EXPECT_EQ(r3.x(), ir.x());
121     EXPECT_EQ(r3.y(), ir.y());
122     EXPECT_EQ(r3.width(), ir.width());
123     EXPECT_EQ(r3.height(), ir.height());
124   }
125 }
126 
TEST(RectTest,Union)127 TEST(RectTest, Union) {
128   static const struct Test {
129     int x1;  // rect 1
130     int y1;
131     int w1;
132     int h1;
133     int x2;  // rect 2
134     int y2;
135     int w2;
136     int h2;
137     int x3;  // rect 3: the union of rects 1 and 2
138     int y3;
139     int w3;
140     int h3;
141   } tests[] = {
142     { 0, 0, 0, 0,
143       0, 0, 0, 0,
144       0, 0, 0, 0 },
145     { 0, 0, 4, 4,
146       0, 0, 4, 4,
147       0, 0, 4, 4 },
148     { 0, 0, 4, 4,
149       4, 4, 4, 4,
150       0, 0, 8, 8 },
151     { 0, 0, 4, 4,
152       0, 5, 4, 4,
153       0, 0, 4, 9 },
154     { 0, 0, 2, 2,
155       3, 3, 2, 2,
156       0, 0, 5, 5 },
157     { 3, 3, 2, 2,   // reverse r1 and r2 from previous test
158       0, 0, 2, 2,
159       0, 0, 5, 5 },
160     { 0, 0, 0, 0,   // union with empty rect
161       2, 2, 2, 2,
162       2, 2, 2, 2 }
163   };
164   for (size_t i = 0; i < arraysize(tests); ++i) {
165     Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
166     Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
167     Rect r3(tests[i].x3, tests[i].y3, tests[i].w3, tests[i].h3);
168     Rect u = UnionRects(r1, r2);
169     EXPECT_EQ(r3.x(), u.x());
170     EXPECT_EQ(r3.y(), u.y());
171     EXPECT_EQ(r3.width(), u.width());
172     EXPECT_EQ(r3.height(), u.height());
173   }
174 }
175 
TEST(RectTest,Equals)176 TEST(RectTest, Equals) {
177   ASSERT_TRUE(Rect(0, 0, 0, 0) == Rect(0, 0, 0, 0));
178   ASSERT_TRUE(Rect(1, 2, 3, 4) == Rect(1, 2, 3, 4));
179   ASSERT_FALSE(Rect(0, 0, 0, 0) == Rect(0, 0, 0, 1));
180   ASSERT_FALSE(Rect(0, 0, 0, 0) == Rect(0, 0, 1, 0));
181   ASSERT_FALSE(Rect(0, 0, 0, 0) == Rect(0, 1, 0, 0));
182   ASSERT_FALSE(Rect(0, 0, 0, 0) == Rect(1, 0, 0, 0));
183 }
184 
TEST(RectTest,AdjustToFit)185 TEST(RectTest, AdjustToFit) {
186   static const struct Test {
187     int x1;  // source
188     int y1;
189     int w1;
190     int h1;
191     int x2;  // target
192     int y2;
193     int w2;
194     int h2;
195     int x3;  // rect 3: results of invoking AdjustToFit
196     int y3;
197     int w3;
198     int h3;
199   } tests[] = {
200     { 0, 0, 2, 2,
201       0, 0, 2, 2,
202       0, 0, 2, 2 },
203     { 2, 2, 3, 3,
204       0, 0, 4, 4,
205       1, 1, 3, 3 },
206     { -1, -1, 5, 5,
207       0, 0, 4, 4,
208       0, 0, 4, 4 },
209     { 2, 2, 4, 4,
210       0, 0, 3, 3,
211       0, 0, 3, 3 },
212     { 2, 2, 1, 1,
213       0, 0, 3, 3,
214       2, 2, 1, 1 }
215   };
216   for (size_t i = 0; i < arraysize(tests); ++i) {
217     Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
218     Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
219     Rect r3(tests[i].x3, tests[i].y3, tests[i].w3, tests[i].h3);
220     Rect u = r1;
221     u.AdjustToFit(r2);
222     EXPECT_EQ(r3.x(), u.x());
223     EXPECT_EQ(r3.y(), u.y());
224     EXPECT_EQ(r3.width(), u.width());
225     EXPECT_EQ(r3.height(), u.height());
226   }
227 }
228 
TEST(RectTest,Subtract)229 TEST(RectTest, Subtract) {
230   Rect result;
231 
232   // Matching
233   result = Rect(10, 10, 20, 20);
234   result.Subtract(Rect(10, 10, 20, 20));
235   EXPECT_EQ(Rect(0, 0, 0, 0), result);
236 
237   // Contains
238   result = Rect(10, 10, 20, 20);
239   result.Subtract(Rect(5, 5, 30, 30));
240   EXPECT_EQ(Rect(0, 0, 0, 0), result);
241 
242   // No intersection
243   result = Rect(10, 10, 20, 20);
244   result.Subtract(Rect(30, 30, 30, 30));
245   EXPECT_EQ(Rect(10, 10, 20, 20), result);
246 
247   // Not a complete intersection in either direction
248   result = Rect(10, 10, 20, 20);
249   result.Subtract(Rect(15, 15, 20, 20));
250   EXPECT_EQ(Rect(10, 10, 20, 20), result);
251 
252   // Complete intersection in the x-direction, top edge is fully covered.
253   result = Rect(10, 10, 20, 20);
254   result.Subtract(Rect(10, 15, 20, 20));
255   EXPECT_EQ(Rect(10, 10, 20, 5), result);
256 
257   // Complete intersection in the x-direction, top edge is fully covered.
258   result = Rect(10, 10, 20, 20);
259   result.Subtract(Rect(5, 15, 30, 20));
260   EXPECT_EQ(Rect(10, 10, 20, 5), result);
261 
262   // Complete intersection in the x-direction, bottom edge is fully covered.
263   result = Rect(10, 10, 20, 20);
264   result.Subtract(Rect(5, 5, 30, 20));
265   EXPECT_EQ(Rect(10, 25, 20, 5), result);
266 
267   // Complete intersection in the x-direction, none of the edges is fully
268   // covered.
269   result = Rect(10, 10, 20, 20);
270   result.Subtract(Rect(5, 15, 30, 1));
271   EXPECT_EQ(Rect(10, 10, 20, 20), result);
272 
273   // Complete intersection in the y-direction, left edge is fully covered.
274   result = Rect(10, 10, 20, 20);
275   result.Subtract(Rect(10, 10, 10, 30));
276   EXPECT_EQ(Rect(20, 10, 10, 20), result);
277 
278   // Complete intersection in the y-direction, left edge is fully covered.
279   result = Rect(10, 10, 20, 20);
280   result.Subtract(Rect(5, 5, 20, 30));
281   EXPECT_EQ(Rect(25, 10, 5, 20), result);
282 
283   // Complete intersection in the y-direction, right edge is fully covered.
284   result = Rect(10, 10, 20, 20);
285   result.Subtract(Rect(20, 5, 20, 30));
286   EXPECT_EQ(Rect(10, 10, 10, 20), result);
287 
288   // Complete intersection in the y-direction, none of the edges is fully
289   // covered.
290   result = Rect(10, 10, 20, 20);
291   result.Subtract(Rect(15, 5, 1, 30));
292   EXPECT_EQ(Rect(10, 10, 20, 20), result);
293 }
294 
TEST(RectTest,IsEmpty)295 TEST(RectTest, IsEmpty) {
296   EXPECT_TRUE(Rect(0, 0, 0, 0).IsEmpty());
297   EXPECT_TRUE(Rect(0, 0, 0, 0).size().IsEmpty());
298   EXPECT_TRUE(Rect(0, 0, 10, 0).IsEmpty());
299   EXPECT_TRUE(Rect(0, 0, 10, 0).size().IsEmpty());
300   EXPECT_TRUE(Rect(0, 0, 0, 10).IsEmpty());
301   EXPECT_TRUE(Rect(0, 0, 0, 10).size().IsEmpty());
302   EXPECT_FALSE(Rect(0, 0, 10, 10).IsEmpty());
303   EXPECT_FALSE(Rect(0, 0, 10, 10).size().IsEmpty());
304 }
305 
TEST(RectTest,SplitVertically)306 TEST(RectTest, SplitVertically) {
307   Rect left_half, right_half;
308 
309   // Splitting when origin is (0, 0).
310   Rect(0, 0, 20, 20).SplitVertically(&left_half, &right_half);
311   EXPECT_TRUE(left_half == Rect(0, 0, 10, 20));
312   EXPECT_TRUE(right_half == Rect(10, 0, 10, 20));
313 
314   // Splitting when origin is arbitrary.
315   Rect(10, 10, 20, 10).SplitVertically(&left_half, &right_half);
316   EXPECT_TRUE(left_half == Rect(10, 10, 10, 10));
317   EXPECT_TRUE(right_half == Rect(20, 10, 10, 10));
318 
319   // Splitting a rectangle of zero width.
320   Rect(10, 10, 0, 10).SplitVertically(&left_half, &right_half);
321   EXPECT_TRUE(left_half == Rect(10, 10, 0, 10));
322   EXPECT_TRUE(right_half == Rect(10, 10, 0, 10));
323 
324   // Splitting a rectangle of odd width.
325   Rect(10, 10, 5, 10).SplitVertically(&left_half, &right_half);
326   EXPECT_TRUE(left_half == Rect(10, 10, 2, 10));
327   EXPECT_TRUE(right_half == Rect(12, 10, 3, 10));
328 }
329 
TEST(RectTest,CenterPoint)330 TEST(RectTest, CenterPoint) {
331   Point center;
332 
333   // When origin is (0, 0).
334   center = Rect(0, 0, 20, 20).CenterPoint();
335   EXPECT_TRUE(center == Point(10, 10));
336 
337   // When origin is even.
338   center = Rect(10, 10, 20, 20).CenterPoint();
339   EXPECT_TRUE(center == Point(20, 20));
340 
341   // When origin is odd.
342   center = Rect(11, 11, 20, 20).CenterPoint();
343   EXPECT_TRUE(center == Point(21, 21));
344 
345   // When 0 width or height.
346   center = Rect(10, 10, 0, 20).CenterPoint();
347   EXPECT_TRUE(center == Point(10, 20));
348   center = Rect(10, 10, 20, 0).CenterPoint();
349   EXPECT_TRUE(center == Point(20, 10));
350 
351   // When an odd size.
352   center = Rect(10, 10, 21, 21).CenterPoint();
353   EXPECT_TRUE(center == Point(20, 20));
354 
355   // When an odd size and position.
356   center = Rect(11, 11, 21, 21).CenterPoint();
357   EXPECT_TRUE(center == Point(21, 21));
358 }
359 
TEST(RectTest,CenterPointF)360 TEST(RectTest, CenterPointF) {
361   PointF center;
362 
363   // When origin is (0, 0).
364   center = RectF(0, 0, 20, 20).CenterPoint();
365   EXPECT_TRUE(center == PointF(10, 10));
366 
367   // When origin is even.
368   center = RectF(10, 10, 20, 20).CenterPoint();
369   EXPECT_TRUE(center == PointF(20, 20));
370 
371   // When origin is odd.
372   center = RectF(11, 11, 20, 20).CenterPoint();
373   EXPECT_TRUE(center == PointF(21, 21));
374 
375   // When 0 width or height.
376   center = RectF(10, 10, 0, 20).CenterPoint();
377   EXPECT_TRUE(center == PointF(10, 20));
378   center = RectF(10, 10, 20, 0).CenterPoint();
379   EXPECT_TRUE(center == PointF(20, 10));
380 
381   // When an odd size.
382   center = RectF(10, 10, 21, 21).CenterPoint();
383   EXPECT_TRUE(center == PointF(20.5f, 20.5f));
384 
385   // When an odd size and position.
386   center = RectF(11, 11, 21, 21).CenterPoint();
387   EXPECT_TRUE(center == PointF(21.5f, 21.5f));
388 }
389 
TEST(RectTest,SharesEdgeWith)390 TEST(RectTest, SharesEdgeWith) {
391   Rect r(2, 3, 4, 5);
392 
393   // Must be non-overlapping
394   EXPECT_FALSE(r.SharesEdgeWith(r));
395 
396   Rect just_above(2, 1, 4, 2);
397   Rect just_below(2, 8, 4, 2);
398   Rect just_left(0, 3, 2, 5);
399   Rect just_right(6, 3, 2, 5);
400 
401   EXPECT_TRUE(r.SharesEdgeWith(just_above));
402   EXPECT_TRUE(r.SharesEdgeWith(just_below));
403   EXPECT_TRUE(r.SharesEdgeWith(just_left));
404   EXPECT_TRUE(r.SharesEdgeWith(just_right));
405 
406   // Wrong placement
407   Rect same_height_no_edge(0, 0, 1, 5);
408   Rect same_width_no_edge(0, 0, 4, 1);
409 
410   EXPECT_FALSE(r.SharesEdgeWith(same_height_no_edge));
411   EXPECT_FALSE(r.SharesEdgeWith(same_width_no_edge));
412 
413   Rect just_above_no_edge(2, 1, 5, 2);  // too wide
414   Rect just_below_no_edge(2, 8, 3, 2);  // too narrow
415   Rect just_left_no_edge(0, 3, 2, 6);   // too tall
416   Rect just_right_no_edge(6, 3, 2, 4);  // too short
417 
418   EXPECT_FALSE(r.SharesEdgeWith(just_above_no_edge));
419   EXPECT_FALSE(r.SharesEdgeWith(just_below_no_edge));
420   EXPECT_FALSE(r.SharesEdgeWith(just_left_no_edge));
421   EXPECT_FALSE(r.SharesEdgeWith(just_right_no_edge));
422 }
423 
424 // Similar to EXPECT_FLOAT_EQ, but lets NaN equal NaN
425 #define EXPECT_FLOAT_AND_NAN_EQ(a, b) \
426   { if (a == a || b == b) { EXPECT_FLOAT_EQ(a, b); } }
427 
TEST(RectTest,ScaleRect)428 TEST(RectTest, ScaleRect) {
429   static const struct Test {
430     int x1;  // source
431     int y1;
432     int w1;
433     int h1;
434     float scale;
435     float x2;  // target
436     float y2;
437     float w2;
438     float h2;
439   } tests[] = {
440     { 3, 3, 3, 3,
441       1.5f,
442       4.5f, 4.5f, 4.5f, 4.5f },
443     { 3, 3, 3, 3,
444       0.0f,
445       0.0f, 0.0f, 0.0f, 0.0f },
446     { 3, 3, 3, 3,
447       std::numeric_limits<float>::quiet_NaN(),
448       std::numeric_limits<float>::quiet_NaN(),
449       std::numeric_limits<float>::quiet_NaN(),
450       std::numeric_limits<float>::quiet_NaN(),
451       std::numeric_limits<float>::quiet_NaN() },
452     { 3, 3, 3, 3,
453       std::numeric_limits<float>::max(),
454       std::numeric_limits<float>::max(),
455       std::numeric_limits<float>::max(),
456       std::numeric_limits<float>::max(),
457       std::numeric_limits<float>::max() }
458   };
459 
460   for (size_t i = 0; i < arraysize(tests); ++i) {
461     RectF r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
462     RectF r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
463 
464     RectF scaled = ScaleRect(r1, tests[i].scale);
465     EXPECT_FLOAT_AND_NAN_EQ(r2.x(), scaled.x());
466     EXPECT_FLOAT_AND_NAN_EQ(r2.y(), scaled.y());
467     EXPECT_FLOAT_AND_NAN_EQ(r2.width(), scaled.width());
468     EXPECT_FLOAT_AND_NAN_EQ(r2.height(), scaled.height());
469   }
470 }
471 
TEST(RectTest,ToEnclosedRect)472 TEST(RectTest, ToEnclosedRect) {
473   static const int max_int = std::numeric_limits<int>::max();
474   static const int min_int = std::numeric_limits<int>::min();
475   static const float max_float = std::numeric_limits<float>::max();
476   static const float max_int_f = static_cast<float>(max_int);
477   static const float min_int_f = static_cast<float>(min_int);
478 
479   static const struct Test {
480     struct {
481       float x;
482       float y;
483       float width;
484       float height;
485     } in;
486     struct {
487       int x;
488       int y;
489       int width;
490       int height;
491     } expected;
492   } tests[] = {
493       {{0.0f, 0.0f, 0.0f, 0.0f}, {0, 0, 0, 0}},
494       {{-1.5f, -1.5f, 3.0f, 3.0f}, {-1, -1, 2, 2}},
495       {{-1.5f, -1.5f, 3.5f, 3.5f}, {-1, -1, 3, 3}},
496       {{max_float, max_float, 2.0f, 2.0f}, {max_int, max_int, 0, 0}},
497       {{0.0f, 0.0f, max_float, max_float}, {0, 0, max_int, max_int}},
498       {{20000.5f, 20000.5f, 0.5f, 0.5f}, {20001, 20001, 0, 0}},
499       {{max_int_f, max_int_f, max_int_f, max_int_f}, {max_int, max_int, 0, 0}}};
500 
501   for (size_t i = 0; i < arraysize(tests); ++i) {
502     RectF source(tests[i].in.x, tests[i].in.y, tests[i].in.width,
503                  tests[i].in.height);
504     Rect enclosed = ToEnclosedRect(source);
505 
506     EXPECT_EQ(tests[i].expected.x, enclosed.x());
507     EXPECT_EQ(tests[i].expected.y, enclosed.y());
508     EXPECT_EQ(tests[i].expected.width, enclosed.width());
509     EXPECT_EQ(tests[i].expected.height, enclosed.height());
510   }
511 
512   {
513     RectF source(min_int_f, min_int_f, max_int_f * 3.f, max_int_f * 3.f);
514     Rect enclosed = ToEnclosedRect(source);
515 
516     // That rect can't be represented, but it should be big.
517     EXPECT_EQ(max_int, enclosed.width());
518     EXPECT_EQ(max_int, enclosed.height());
519     // It should include some axis near the global origin.
520     EXPECT_GT(1, enclosed.x());
521     EXPECT_GT(1, enclosed.y());
522     // And it should not cause computation issues for itself.
523     EXPECT_LT(0, enclosed.right());
524     EXPECT_LT(0, enclosed.bottom());
525   }
526 }
527 
TEST(RectTest,ToEnclosingRect)528 TEST(RectTest, ToEnclosingRect) {
529   static const int max_int = std::numeric_limits<int>::max();
530   static const int min_int = std::numeric_limits<int>::min();
531   static const float max_float = std::numeric_limits<float>::max();
532   static const float epsilon_float = std::numeric_limits<float>::epsilon();
533   static const float max_int_f = static_cast<float>(max_int);
534   static const float min_int_f = static_cast<float>(min_int);
535   static const struct Test {
536     struct {
537       float x;
538       float y;
539       float width;
540       float height;
541     } in;
542     struct {
543       int x;
544       int y;
545       int width;
546       int height;
547     } expected;
548   } tests[] = {
549       {{0.0f, 0.0f, 0.0f, 0.0f}, {0, 0, 0, 0}},
550       {{5.5f, 5.5f, 0.0f, 0.0f}, {5, 5, 0, 0}},
551       {{3.5f, 2.5f, epsilon_float, -0.0f}, {3, 2, 0, 0}},
552       {{3.5f, 2.5f, 0.f, 0.001f}, {3, 2, 0, 1}},
553       {{-1.5f, -1.5f, 3.0f, 3.0f}, {-2, -2, 4, 4}},
554       {{-1.5f, -1.5f, 3.5f, 3.5f}, {-2, -2, 4, 4}},
555       {{max_float, max_float, 2.0f, 2.0f}, {max_int, max_int, 0, 0}},
556       {{0.0f, 0.0f, max_float, max_float}, {0, 0, max_int, max_int}},
557       {{20000.5f, 20000.5f, 0.5f, 0.5f}, {20000, 20000, 1, 1}},
558       {{max_int_f, max_int_f, max_int_f, max_int_f}, {max_int, max_int, 0, 0}},
559       {{-0.5f, -0.5f, 22777712.f, 1.f}, {-1, -1, 22777713, 2}}};
560 
561   for (size_t i = 0; i < arraysize(tests); ++i) {
562     RectF source(tests[i].in.x, tests[i].in.y, tests[i].in.width,
563                  tests[i].in.height);
564 
565     Rect enclosing = ToEnclosingRect(source);
566     EXPECT_EQ(tests[i].expected.x, enclosing.x());
567     EXPECT_EQ(tests[i].expected.y, enclosing.y());
568     EXPECT_EQ(tests[i].expected.width, enclosing.width());
569     EXPECT_EQ(tests[i].expected.height, enclosing.height());
570   }
571 
572   {
573     RectF source(min_int_f, min_int_f, max_int_f * 3.f, max_int_f * 3.f);
574     Rect enclosing = ToEnclosingRect(source);
575 
576     // That rect can't be represented, but it should be big.
577     EXPECT_EQ(max_int, enclosing.width());
578     EXPECT_EQ(max_int, enclosing.height());
579     // It should include some axis near the global origin.
580     EXPECT_GT(1, enclosing.x());
581     EXPECT_GT(1, enclosing.y());
582     // And it should cause computation issues for itself.
583     EXPECT_LT(0, enclosing.right());
584     EXPECT_LT(0, enclosing.bottom());
585   }
586 }
587 
TEST(RectTest,ToNearestRect)588 TEST(RectTest, ToNearestRect) {
589   Rect rect;
590   EXPECT_EQ(rect, ToNearestRect(RectF(rect)));
591 
592   rect = Rect(-1, -1, 3, 3);
593   EXPECT_EQ(rect, ToNearestRect(RectF(rect)));
594 
595   RectF rectf(-1.00001f, -0.999999f, 3.0000001f, 2.999999f);
596   EXPECT_EQ(rect, ToNearestRect(rectf));
597 }
598 
TEST(RectTest,ToFlooredRect)599 TEST(RectTest, ToFlooredRect) {
600   static const struct Test {
601     float x1; // source
602     float y1;
603     float w1;
604     float h1;
605     int x2; // target
606     int y2;
607     int w2;
608     int h2;
609   } tests [] = {
610     { 0.0f, 0.0f, 0.0f, 0.0f,
611       0, 0, 0, 0 },
612     { -1.5f, -1.5f, 3.0f, 3.0f,
613       -2, -2, 3, 3 },
614     { -1.5f, -1.5f, 3.5f, 3.5f,
615       -2, -2, 3, 3 },
616     { 20000.5f, 20000.5f, 0.5f, 0.5f,
617       20000, 20000, 0, 0 },
618   };
619 
620   for (size_t i = 0; i < arraysize(tests); ++i) {
621     RectF r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
622     Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
623 
624     Rect floored = ToFlooredRectDeprecated(r1);
625     EXPECT_FLOAT_EQ(r2.x(), floored.x());
626     EXPECT_FLOAT_EQ(r2.y(), floored.y());
627     EXPECT_FLOAT_EQ(r2.width(), floored.width());
628     EXPECT_FLOAT_EQ(r2.height(), floored.height());
629   }
630 }
631 
TEST(RectTest,ScaleToEnclosedRect)632 TEST(RectTest, ScaleToEnclosedRect) {
633   static const struct Test {
634     Rect input_rect;
635     float input_scale;
636     Rect expected_rect;
637   } tests[] = {
638     {
639       Rect(),
640       5.f,
641       Rect(),
642     }, {
643       Rect(1, 1, 1, 1),
644       5.f,
645       Rect(5, 5, 5, 5),
646     }, {
647       Rect(-1, -1, 0, 0),
648       5.f,
649       Rect(-5, -5, 0, 0),
650     }, {
651       Rect(1, -1, 0, 1),
652       5.f,
653       Rect(5, -5, 0, 5),
654     }, {
655       Rect(-1, 1, 1, 0),
656       5.f,
657       Rect(-5, 5, 5, 0),
658     }, {
659       Rect(1, 2, 3, 4),
660       1.5f,
661       Rect(2, 3, 4, 6),
662     }, {
663       Rect(-1, -2, 0, 0),
664       1.5f,
665       Rect(-1, -3, 0, 0),
666     }
667   };
668 
669   for (size_t i = 0; i < arraysize(tests); ++i) {
670     Rect result = ScaleToEnclosedRect(tests[i].input_rect,
671                                       tests[i].input_scale);
672     EXPECT_EQ(tests[i].expected_rect, result);
673   }
674 }
675 
TEST(RectTest,ScaleToEnclosingRect)676 TEST(RectTest, ScaleToEnclosingRect) {
677   static const struct Test {
678     Rect input_rect;
679     float input_scale;
680     Rect expected_rect;
681   } tests[] = {
682     {
683       Rect(),
684       5.f,
685       Rect(),
686     }, {
687       Rect(1, 1, 1, 1),
688       5.f,
689       Rect(5, 5, 5, 5),
690     }, {
691       Rect(-1, -1, 0, 0),
692       5.f,
693       Rect(-5, -5, 0, 0),
694     }, {
695       Rect(1, -1, 0, 1),
696       5.f,
697       Rect(5, -5, 0, 5),
698     }, {
699       Rect(-1, 1, 1, 0),
700       5.f,
701       Rect(-5, 5, 5, 0),
702     }, {
703       Rect(1, 2, 3, 4),
704       1.5f,
705       Rect(1, 3, 5, 6),
706     }, {
707       Rect(-1, -2, 0, 0),
708       1.5f,
709       Rect(-2, -3, 0, 0),
710     }
711   };
712 
713   for (size_t i = 0; i < arraysize(tests); ++i) {
714     Rect result =
715         ScaleToEnclosingRect(tests[i].input_rect, tests[i].input_scale);
716     EXPECT_EQ(tests[i].expected_rect, result);
717     Rect result_safe =
718         ScaleToEnclosingRectSafe(tests[i].input_rect, tests[i].input_scale);
719     EXPECT_EQ(tests[i].expected_rect, result_safe);
720   }
721 }
722 
723 #if defined(OS_WIN)
TEST(RectTest,ConstructAndAssign)724 TEST(RectTest, ConstructAndAssign) {
725   const RECT rect_1 = { 0, 0, 10, 10 };
726   const RECT rect_2 = { 0, 0, -10, -10 };
727   Rect test1(rect_1);
728   Rect test2(rect_2);
729 }
730 #endif
731 
TEST(RectTest,ToRectF)732 TEST(RectTest, ToRectF) {
733   // Check that explicit conversion from integer to float compiles.
734   Rect a(10, 20, 30, 40);
735   RectF b(10, 20, 30, 40);
736 
737   RectF c = RectF(a);
738   EXPECT_EQ(b, c);
739 }
740 
TEST(RectTest,BoundingRect)741 TEST(RectTest, BoundingRect) {
742   struct {
743     Point a;
744     Point b;
745     Rect expected;
746   } int_tests[] = {
747     // If point B dominates A, then A should be the origin.
748     { Point(4, 6), Point(4, 6), Rect(4, 6, 0, 0) },
749     { Point(4, 6), Point(8, 6), Rect(4, 6, 4, 0) },
750     { Point(4, 6), Point(4, 9), Rect(4, 6, 0, 3) },
751     { Point(4, 6), Point(8, 9), Rect(4, 6, 4, 3) },
752     // If point A dominates B, then B should be the origin.
753     { Point(4, 6), Point(4, 6), Rect(4, 6, 0, 0) },
754     { Point(8, 6), Point(4, 6), Rect(4, 6, 4, 0) },
755     { Point(4, 9), Point(4, 6), Rect(4, 6, 0, 3) },
756     { Point(8, 9), Point(4, 6), Rect(4, 6, 4, 3) },
757     // If neither point dominates, then the origin is a combination of the two.
758     { Point(4, 6), Point(6, 4), Rect(4, 4, 2, 2) },
759     { Point(-4, -6), Point(-6, -4), Rect(-6, -6, 2, 2) },
760     { Point(-4, 6), Point(6, -4), Rect(-4, -4, 10, 10) },
761   };
762 
763   for (size_t i = 0; i < arraysize(int_tests); ++i) {
764     Rect actual = BoundingRect(int_tests[i].a, int_tests[i].b);
765     EXPECT_EQ(int_tests[i].expected, actual);
766   }
767 
768   struct {
769     PointF a;
770     PointF b;
771     RectF expected;
772   } float_tests[] = {
773     // If point B dominates A, then A should be the origin.
774     { PointF(4.2f, 6.8f), PointF(4.2f, 6.8f),
775       RectF(4.2f, 6.8f, 0, 0) },
776     { PointF(4.2f, 6.8f), PointF(8.5f, 6.8f),
777       RectF(4.2f, 6.8f, 4.3f, 0) },
778     { PointF(4.2f, 6.8f), PointF(4.2f, 9.3f),
779       RectF(4.2f, 6.8f, 0, 2.5f) },
780     { PointF(4.2f, 6.8f), PointF(8.5f, 9.3f),
781       RectF(4.2f, 6.8f, 4.3f, 2.5f) },
782     // If point A dominates B, then B should be the origin.
783     { PointF(4.2f, 6.8f), PointF(4.2f, 6.8f),
784       RectF(4.2f, 6.8f, 0, 0) },
785     { PointF(8.5f, 6.8f), PointF(4.2f, 6.8f),
786       RectF(4.2f, 6.8f, 4.3f, 0) },
787     { PointF(4.2f, 9.3f), PointF(4.2f, 6.8f),
788       RectF(4.2f, 6.8f, 0, 2.5f) },
789     { PointF(8.5f, 9.3f), PointF(4.2f, 6.8f),
790       RectF(4.2f, 6.8f, 4.3f, 2.5f) },
791     // If neither point dominates, then the origin is a combination of the two.
792     { PointF(4.2f, 6.8f), PointF(6.8f, 4.2f),
793       RectF(4.2f, 4.2f, 2.6f, 2.6f) },
794     { PointF(-4.2f, -6.8f), PointF(-6.8f, -4.2f),
795       RectF(-6.8f, -6.8f, 2.6f, 2.6f) },
796     { PointF(-4.2f, 6.8f), PointF(6.8f, -4.2f),
797       RectF(-4.2f, -4.2f, 11.0f, 11.0f) }
798   };
799 
800   for (size_t i = 0; i < arraysize(float_tests); ++i) {
801     RectF actual = BoundingRect(float_tests[i].a, float_tests[i].b);
802     EXPECT_RECTF_EQ(float_tests[i].expected, actual);
803   }
804 }
805 
TEST(RectTest,IsExpressibleAsRect)806 TEST(RectTest, IsExpressibleAsRect) {
807   EXPECT_TRUE(RectF().IsExpressibleAsRect());
808 
809   float min = std::numeric_limits<int>::min();
810   float max = std::numeric_limits<int>::max();
811   float infinity = std::numeric_limits<float>::infinity();
812 
813   EXPECT_TRUE(RectF(
814       min + 200, min + 200, max - 200, max - 200).IsExpressibleAsRect());
815   EXPECT_FALSE(RectF(
816       min - 200, min + 200, max + 200, max + 200).IsExpressibleAsRect());
817   EXPECT_FALSE(RectF(
818       min + 200 , min - 200, max + 200, max + 200).IsExpressibleAsRect());
819   EXPECT_FALSE(RectF(
820       min + 200, min + 200, max + 200, max - 200).IsExpressibleAsRect());
821   EXPECT_FALSE(RectF(
822       min + 200, min + 200, max - 200, max + 200).IsExpressibleAsRect());
823 
824   EXPECT_TRUE(RectF(0, 0, max - 200, max - 200).IsExpressibleAsRect());
825   EXPECT_FALSE(RectF(200, 0, max + 200, max - 200).IsExpressibleAsRect());
826   EXPECT_FALSE(RectF(0, 200, max - 200, max + 200).IsExpressibleAsRect());
827   EXPECT_FALSE(RectF(0, 0, max + 200, max - 200).IsExpressibleAsRect());
828   EXPECT_FALSE(RectF(0, 0, max - 200, max + 200).IsExpressibleAsRect());
829 
830   EXPECT_FALSE(RectF(infinity, 0, 1, 1).IsExpressibleAsRect());
831   EXPECT_FALSE(RectF(0, infinity, 1, 1).IsExpressibleAsRect());
832   EXPECT_FALSE(RectF(0, 0, infinity, 1).IsExpressibleAsRect());
833   EXPECT_FALSE(RectF(0, 0, 1, infinity).IsExpressibleAsRect());
834 }
835 
TEST(RectTest,Offset)836 TEST(RectTest, Offset) {
837   Rect i(1, 2, 3, 4);
838 
839   EXPECT_EQ(Rect(2, 1, 3, 4), (i + Vector2d(1, -1)));
840   EXPECT_EQ(Rect(2, 1, 3, 4), (Vector2d(1, -1) + i));
841   i += Vector2d(1, -1);
842   EXPECT_EQ(Rect(2, 1, 3, 4), i);
843   EXPECT_EQ(Rect(1, 2, 3, 4), (i - Vector2d(1, -1)));
844   i -= Vector2d(1, -1);
845   EXPECT_EQ(Rect(1, 2, 3, 4), i);
846 
847   RectF f(1.1f, 2.2f, 3.3f, 4.4f);
848   EXPECT_EQ(RectF(2.2f, 1.1f, 3.3f, 4.4f), (f + Vector2dF(1.1f, -1.1f)));
849   EXPECT_EQ(RectF(2.2f, 1.1f, 3.3f, 4.4f), (Vector2dF(1.1f, -1.1f) + f));
850   f += Vector2dF(1.1f, -1.1f);
851   EXPECT_EQ(RectF(2.2f, 1.1f, 3.3f, 4.4f), f);
852   EXPECT_EQ(RectF(1.1f, 2.2f, 3.3f, 4.4f), (f - Vector2dF(1.1f, -1.1f)));
853   f -= Vector2dF(1.1f, -1.1f);
854   EXPECT_EQ(RectF(1.1f, 2.2f, 3.3f, 4.4f), f);
855 }
856 
TEST(RectTest,Corners)857 TEST(RectTest, Corners) {
858   Rect i(1, 2, 3, 4);
859   RectF f(1.1f, 2.1f, 3.1f, 4.1f);
860 
861   EXPECT_EQ(Point(1, 2), i.origin());
862   EXPECT_EQ(Point(4, 2), i.top_right());
863   EXPECT_EQ(Point(1, 6), i.bottom_left());
864   EXPECT_EQ(Point(4, 6), i.bottom_right());
865 
866   EXPECT_EQ(PointF(1.1f, 2.1f), f.origin());
867   EXPECT_EQ(PointF(4.2f, 2.1f), f.top_right());
868   EXPECT_EQ(PointF(1.1f, 6.2f), f.bottom_left());
869   EXPECT_EQ(PointF(4.2f, 6.2f), f.bottom_right());
870 }
871 
TEST(RectTest,ManhattanDistanceToPoint)872 TEST(RectTest, ManhattanDistanceToPoint) {
873   Rect i(1, 2, 3, 4);
874   EXPECT_EQ(0, i.ManhattanDistanceToPoint(Point(1, 2)));
875   EXPECT_EQ(0, i.ManhattanDistanceToPoint(Point(4, 6)));
876   EXPECT_EQ(0, i.ManhattanDistanceToPoint(Point(2, 4)));
877   EXPECT_EQ(3, i.ManhattanDistanceToPoint(Point(0, 0)));
878   EXPECT_EQ(2, i.ManhattanDistanceToPoint(Point(2, 0)));
879   EXPECT_EQ(3, i.ManhattanDistanceToPoint(Point(5, 0)));
880   EXPECT_EQ(1, i.ManhattanDistanceToPoint(Point(5, 4)));
881   EXPECT_EQ(3, i.ManhattanDistanceToPoint(Point(5, 8)));
882   EXPECT_EQ(2, i.ManhattanDistanceToPoint(Point(3, 8)));
883   EXPECT_EQ(2, i.ManhattanDistanceToPoint(Point(0, 7)));
884   EXPECT_EQ(1, i.ManhattanDistanceToPoint(Point(0, 3)));
885 
886   RectF f(1.1f, 2.1f, 3.1f, 4.1f);
887   EXPECT_FLOAT_EQ(0.f, f.ManhattanDistanceToPoint(PointF(1.1f, 2.1f)));
888   EXPECT_FLOAT_EQ(0.f, f.ManhattanDistanceToPoint(PointF(4.2f, 6.f)));
889   EXPECT_FLOAT_EQ(0.f, f.ManhattanDistanceToPoint(PointF(2.f, 4.f)));
890   EXPECT_FLOAT_EQ(3.2f, f.ManhattanDistanceToPoint(PointF(0.f, 0.f)));
891   EXPECT_FLOAT_EQ(2.1f, f.ManhattanDistanceToPoint(PointF(2.f, 0.f)));
892   EXPECT_FLOAT_EQ(2.9f, f.ManhattanDistanceToPoint(PointF(5.f, 0.f)));
893   EXPECT_FLOAT_EQ(.8f, f.ManhattanDistanceToPoint(PointF(5.f, 4.f)));
894   EXPECT_FLOAT_EQ(2.6f, f.ManhattanDistanceToPoint(PointF(5.f, 8.f)));
895   EXPECT_FLOAT_EQ(1.8f, f.ManhattanDistanceToPoint(PointF(3.f, 8.f)));
896   EXPECT_FLOAT_EQ(1.9f, f.ManhattanDistanceToPoint(PointF(0.f, 7.f)));
897   EXPECT_FLOAT_EQ(1.1f, f.ManhattanDistanceToPoint(PointF(0.f, 3.f)));
898 }
899 
TEST(RectTest,ManhattanInternalDistance)900 TEST(RectTest, ManhattanInternalDistance) {
901   Rect i(0, 0, 400, 400);
902   EXPECT_EQ(0, i.ManhattanInternalDistance(gfx::Rect(-1, 0, 2, 1)));
903   EXPECT_EQ(1, i.ManhattanInternalDistance(gfx::Rect(400, 0, 1, 400)));
904   EXPECT_EQ(2, i.ManhattanInternalDistance(gfx::Rect(-100, -100, 100, 100)));
905   EXPECT_EQ(2, i.ManhattanInternalDistance(gfx::Rect(-101, 100, 100, 100)));
906   EXPECT_EQ(4, i.ManhattanInternalDistance(gfx::Rect(-101, -101, 100, 100)));
907   EXPECT_EQ(435, i.ManhattanInternalDistance(gfx::Rect(630, 603, 100, 100)));
908 
909   RectF f(0.0f, 0.0f, 400.0f, 400.0f);
910   static const float kEpsilon = std::numeric_limits<float>::epsilon();
911 
912   EXPECT_FLOAT_EQ(
913       0.0f, f.ManhattanInternalDistance(gfx::RectF(-1.0f, 0.0f, 2.0f, 1.0f)));
914   EXPECT_FLOAT_EQ(
915       kEpsilon,
916       f.ManhattanInternalDistance(gfx::RectF(400.0f, 0.0f, 1.0f, 400.0f)));
917   EXPECT_FLOAT_EQ(2.0f * kEpsilon,
918                   f.ManhattanInternalDistance(
919                       gfx::RectF(-100.0f, -100.0f, 100.0f, 100.0f)));
920   EXPECT_FLOAT_EQ(
921       1.0f + kEpsilon,
922       f.ManhattanInternalDistance(gfx::RectF(-101.0f, 100.0f, 100.0f, 100.0f)));
923   EXPECT_FLOAT_EQ(2.0f + 2.0f * kEpsilon,
924                   f.ManhattanInternalDistance(
925                       gfx::RectF(-101.0f, -101.0f, 100.0f, 100.0f)));
926   EXPECT_FLOAT_EQ(
927       433.0f + 2.0f * kEpsilon,
928       f.ManhattanInternalDistance(gfx::RectF(630.0f, 603.0f, 100.0f, 100.0f)));
929 
930   EXPECT_FLOAT_EQ(
931       0.0f, f.ManhattanInternalDistance(gfx::RectF(-1.0f, 0.0f, 1.1f, 1.0f)));
932   EXPECT_FLOAT_EQ(
933       0.1f + kEpsilon,
934       f.ManhattanInternalDistance(gfx::RectF(-1.5f, 0.0f, 1.4f, 1.0f)));
935   EXPECT_FLOAT_EQ(
936       kEpsilon,
937       f.ManhattanInternalDistance(gfx::RectF(-1.5f, 0.0f, 1.5f, 1.0f)));
938 }
939 
TEST(RectTest,IntegerOverflow)940 TEST(RectTest, IntegerOverflow) {
941   int limit = std::numeric_limits<int>::max();
942   int min_limit = std::numeric_limits<int>::min();
943   int expected = 10;
944   int large_number = limit - expected;
945 
946   Rect height_overflow(0, large_number, 100, 100);
947   EXPECT_EQ(large_number, height_overflow.y());
948   EXPECT_EQ(expected, height_overflow.height());
949 
950   Rect width_overflow(large_number, 0, 100, 100);
951   EXPECT_EQ(large_number, width_overflow.x());
952   EXPECT_EQ(expected, width_overflow.width());
953 
954   Rect size_height_overflow(Point(0, large_number), Size(100, 100));
955   EXPECT_EQ(large_number, size_height_overflow.y());
956   EXPECT_EQ(expected, size_height_overflow.height());
957 
958   Rect size_width_overflow(Point(large_number, 0), Size(100, 100));
959   EXPECT_EQ(large_number, size_width_overflow.x());
960   EXPECT_EQ(expected, size_width_overflow.width());
961 
962   Rect set_height_overflow(0, large_number, 100, 5);
963   EXPECT_EQ(5, set_height_overflow.height());
964   set_height_overflow.set_height(100);
965   EXPECT_EQ(expected, set_height_overflow.height());
966 
967   Rect set_y_overflow(100, 100, 100, 100);
968   EXPECT_EQ(100, set_y_overflow.height());
969   set_y_overflow.set_y(large_number);
970   EXPECT_EQ(expected, set_y_overflow.height());
971 
972   Rect set_width_overflow(large_number, 0, 5, 100);
973   EXPECT_EQ(5, set_width_overflow.width());
974   set_width_overflow.set_width(100);
975   EXPECT_EQ(expected, set_width_overflow.width());
976 
977   Rect set_x_overflow(100, 100, 100, 100);
978   EXPECT_EQ(100, set_x_overflow.width());
979   set_x_overflow.set_x(large_number);
980   EXPECT_EQ(expected, set_x_overflow.width());
981 
982   Point large_offset(large_number, large_number);
983   Size size(100, 100);
984   Size expected_size(10, 10);
985 
986   Rect set_origin_overflow(100, 100, 100, 100);
987   EXPECT_EQ(size, set_origin_overflow.size());
988   set_origin_overflow.set_origin(large_offset);
989   EXPECT_EQ(large_offset, set_origin_overflow.origin());
990   EXPECT_EQ(expected_size, set_origin_overflow.size());
991 
992   Rect set_size_overflow(large_number, large_number, 5, 5);
993   EXPECT_EQ(Size(5, 5), set_size_overflow.size());
994   set_size_overflow.set_size(size);
995   EXPECT_EQ(large_offset, set_size_overflow.origin());
996   EXPECT_EQ(expected_size, set_size_overflow.size());
997 
998   Rect set_rect_overflow;
999   set_rect_overflow.SetRect(large_number, large_number, 100, 100);
1000   EXPECT_EQ(large_offset, set_rect_overflow.origin());
1001   EXPECT_EQ(expected_size, set_rect_overflow.size());
1002 
1003   // Insetting an empty rect, but the total inset (left + right) could overflow.
1004   Rect inset_overflow;
1005   inset_overflow.Inset(large_number, large_number, 100, 100);
1006   EXPECT_EQ(large_offset, inset_overflow.origin());
1007   EXPECT_EQ(gfx::Size(), inset_overflow.size());
1008 
1009   // Insetting where the total inset (width - left - right) could overflow.
1010   // Also, this insetting by the min limit in all directions cannot
1011   // represent width() without overflow, so that will also clamp.
1012   Rect inset_overflow2;
1013   inset_overflow2.Inset(min_limit, min_limit, min_limit, min_limit);
1014   EXPECT_EQ(inset_overflow2, gfx::Rect(min_limit, min_limit, limit, limit));
1015 
1016   // Insetting where the width shouldn't change, but if the insets operations
1017   // clamped in the wrong order, e.g. ((width - left) - right) vs (width - (left
1018   // + right)) then this will not work properly.  This is the proper order,
1019   // as if left + right overflows, the width cannot be decreased by more than
1020   // max int anyway.  Additionally, if left + right underflows, it cannot be
1021   // increased by more then max int.
1022   Rect inset_overflow3(0, 0, limit, limit);
1023   inset_overflow3.Inset(-100, -100, 100, 100);
1024   EXPECT_EQ(inset_overflow3, gfx::Rect(-100, -100, limit, limit));
1025 
1026   Rect inset_overflow4(-1000, -1000, limit, limit);
1027   inset_overflow4.Inset(100, 100, -100, -100);
1028   EXPECT_EQ(inset_overflow4, gfx::Rect(-900, -900, limit, limit));
1029 
1030   Rect offset_overflow(0, 0, 100, 100);
1031   offset_overflow.Offset(large_number, large_number);
1032   EXPECT_EQ(large_offset, offset_overflow.origin());
1033   EXPECT_EQ(expected_size, offset_overflow.size());
1034 
1035   Rect operator_overflow(0, 0, 100, 100);
1036   operator_overflow += Vector2d(large_number, large_number);
1037   EXPECT_EQ(large_offset, operator_overflow.origin());
1038   EXPECT_EQ(expected_size, operator_overflow.size());
1039 
1040   Rect origin_maxint(limit, limit, limit, limit);
1041   EXPECT_EQ(origin_maxint, Rect(gfx::Point(limit, limit), gfx::Size()));
1042 
1043   // Expect a rect at the origin and a rect whose right/bottom is maxint
1044   // create a rect that extends from 0..maxint in both extents.
1045   {
1046     Rect origin_small(0, 0, 100, 100);
1047     Rect big_clamped(50, 50, limit, limit);
1048     EXPECT_EQ(big_clamped.right(), limit);
1049 
1050     Rect unioned = UnionRects(origin_small, big_clamped);
1051     Rect rect_limit(0, 0, limit, limit);
1052     EXPECT_EQ(unioned, rect_limit);
1053   }
1054 
1055   // Expect a rect that would overflow width (but not right) to be clamped
1056   // and to have maxint extents after unioning.
1057   {
1058     Rect small(-500, -400, 100, 100);
1059     Rect big(-400, -500, limit, limit);
1060     // Technically, this should be limit + 100 width, but will clamp to maxint.
1061     EXPECT_EQ(UnionRects(small, big), Rect(-500, -500, limit, limit));
1062   }
1063 
1064   // Expect a rect that would overflow right *and* width to be clamped.
1065   {
1066     Rect clamped(500, 500, limit, limit);
1067     Rect positive_origin(100, 100, 500, 500);
1068 
1069     // Ideally, this should be (100, 100, limit + 400, limit + 400).
1070     // However, width overflows and would be clamped to limit, but right
1071     // overflows too and so will be clamped to limit - 100.
1072     Rect expected(100, 100, limit - 100, limit - 100);
1073     EXPECT_EQ(UnionRects(clamped, positive_origin), expected);
1074   }
1075 
1076   // Unioning a left=minint rect with a right=maxint rect.
1077   // We can't represent both ends of the spectrum in the same rect.
1078   // Make sure we keep the most useful area.
1079   {
1080     int part_limit = min_limit / 3;
1081     Rect left_minint(min_limit, min_limit, 1, 1);
1082     Rect right_maxint(limit - 1, limit - 1, limit, limit);
1083     Rect expected(part_limit, part_limit, 2 * part_limit, 2 * part_limit);
1084     Rect result = UnionRects(left_minint, right_maxint);
1085 
1086     // The result should be maximally big.
1087     EXPECT_EQ(limit, result.height());
1088     EXPECT_EQ(limit, result.width());
1089 
1090     // The result should include the area near the origin.
1091     EXPECT_GT(-part_limit, result.x());
1092     EXPECT_LT(part_limit, result.right());
1093     EXPECT_GT(-part_limit, result.y());
1094     EXPECT_LT(part_limit, result.bottom());
1095 
1096     // More succinctly, but harder to read in the results.
1097     EXPECT_TRUE(UnionRects(left_minint, right_maxint).Contains(expected));
1098   }
1099 }
1100 
TEST(RectTest,ScaleToEnclosingRectSafe)1101 TEST(RectTest, ScaleToEnclosingRectSafe) {
1102   const int max_int = std::numeric_limits<int>::max();
1103   const int min_int = std::numeric_limits<int>::min();
1104 
1105   Rect xy_underflow(-100000, -123456, 10, 20);
1106   EXPECT_EQ(ScaleToEnclosingRectSafe(xy_underflow, 100000, 100000),
1107             Rect(min_int, min_int, 1000000, 2000000));
1108 
1109   // A location overflow means that width/right and bottom/top also
1110   // overflow so need to be clamped.
1111   Rect xy_overflow(100000, 123456, 10, 20);
1112   EXPECT_EQ(ScaleToEnclosingRectSafe(xy_overflow, 100000, 100000),
1113             Rect(max_int, max_int, 0, 0));
1114 
1115   // In practice all rects are clamped to 0 width / 0 height so
1116   // negative sizes don't matter, but try this for the sake of testing.
1117   Rect size_underflow(-1, -2, 100000, 100000);
1118   EXPECT_EQ(ScaleToEnclosingRectSafe(size_underflow, -100000, -100000),
1119             Rect(100000, 200000, 0, 0));
1120 
1121   Rect size_overflow(-1, -2, 123456, 234567);
1122   EXPECT_EQ(ScaleToEnclosingRectSafe(size_overflow, 100000, 100000),
1123             Rect(-100000, -200000, max_int, max_int));
1124   // Verify width/right gets clamped properly too if x/y positive.
1125   Rect size_overflow2(1, 2, 123456, 234567);
1126   EXPECT_EQ(ScaleToEnclosingRectSafe(size_overflow2, 100000, 100000),
1127             Rect(100000, 200000, max_int - 100000, max_int - 200000));
1128 
1129   Rect max_rect(max_int, max_int, max_int, max_int);
1130   EXPECT_EQ(ScaleToEnclosingRectSafe(max_rect, max_int, max_int),
1131             Rect(max_int, max_int, 0, 0));
1132 
1133   Rect min_rect(min_int, min_int, max_int, max_int);
1134   // Min rect can't be scaled up any further in any dimension.
1135   EXPECT_EQ(ScaleToEnclosingRectSafe(min_rect, 2, 3.5), min_rect);
1136   EXPECT_EQ(ScaleToEnclosingRectSafe(min_rect, max_int, max_int), min_rect);
1137   // Min rect scaled by min is an empty rect at (max, max)
1138   EXPECT_EQ(ScaleToEnclosingRectSafe(min_rect, min_int, min_int), max_rect);
1139 }
1140 
1141 }  // namespace gfx
1142