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