• 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 "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 
TEST(RectTest,Contains)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 
TEST(RectTest,Intersects)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 
TEST(RectTest,Intersect)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 
TEST(RectTest,Union)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 
TEST(RectTest,Equals)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 
TEST(RectTest,AdjustToFit)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 
TEST(RectTest,Subtract)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 
TEST(RectTest,IsEmpty)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 
TEST(RectTest,SplitVertically)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 
TEST(RectTest,CenterPoint)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 
TEST(RectTest,CenterPointF)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 
TEST(RectTest,SharesEdgeWith)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 
TEST(RectTest,ScaleRect)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 
TEST(RectTest,ToEnclosedRect)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 
TEST(RectTest,ToEnclosingRect)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 
TEST(RectTest,ToNearestRect)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 
TEST(RectTest,ToFlooredRect)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 
TEST(RectTest,ScaleToEnclosedRect)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 
TEST(RectTest,ScaleToEnclosingRect)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)
TEST(RectTest,ConstructAndAssign)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 
TEST(RectTest,ToRectF)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 
TEST(RectTest,BoundingRect)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 
TEST(RectTest,IsExpressibleAsRect)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 
TEST(RectTest,Offset)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 
TEST(RectTest,Corners)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 
TEST(RectTest,ManhattanDistanceToPoint)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 
TEST(RectTest,ManhattanInternalDistance)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