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