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