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