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