| Flutter Impeller |

round_rect_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter 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 "gtest/gtest.h"
6
7 #include "flutter/impeller/geometry/round_rect.h"
8
9 #include "flutter/impeller/geometry/geometry_asserts.h"
10
11 namespace impeller {
12 namespace testing {
13
14 TEST(RoundRectTest, RoundingRadiiEmptyDeclaration) {
15 RoundingRadii radii;
16
17 EXPECT_TRUE(radii.AreAllCornersEmpty());
18 EXPECT_TRUE(radii.AreAllCornersSame());
19 EXPECT_TRUE(radii.IsFinite());
20 EXPECT_EQ(radii.top_left, Size());
21 EXPECT_EQ(radii.top_right, Size());
22 EXPECT_EQ(radii.bottom_left, Size());
23 EXPECT_EQ(radii.bottom_right, Size());
24 EXPECT_EQ(radii.top_left.width, 0.0f);
25 EXPECT_EQ(radii.top_left.height, 0.0f);
26 EXPECT_EQ(radii.top_right.width, 0.0f);
27 EXPECT_EQ(radii.top_right.height, 0.0f);
28 EXPECT_EQ(radii.bottom_left.width, 0.0f);
29 EXPECT_EQ(radii.bottom_left.height, 0.0f);
30 EXPECT_EQ(radii.bottom_right.width, 0.0f);
31 EXPECT_EQ(radii.bottom_right.height, 0.0f);
32 }
33
34 TEST(RoundRectTest, RoundingRadiiDefaultConstructor) {
35 RoundingRadii radii = RoundingRadii();
36
37 EXPECT_TRUE(radii.AreAllCornersEmpty());
38 EXPECT_TRUE(radii.AreAllCornersSame());
39 EXPECT_TRUE(radii.IsFinite());
40 EXPECT_EQ(radii.top_left, Size());
41 EXPECT_EQ(radii.top_right, Size());
42 EXPECT_EQ(radii.bottom_left, Size());
43 EXPECT_EQ(radii.bottom_right, Size());
44 }
45
46 TEST(RoundRectTest, RoundingRadiiScalarConstructor) {
47 RoundingRadii radii = RoundingRadii::MakeRadius(5.0f);
48
49 EXPECT_FALSE(radii.AreAllCornersEmpty());
50 EXPECT_TRUE(radii.AreAllCornersSame());
51 EXPECT_TRUE(radii.IsFinite());
52 EXPECT_EQ(radii.top_left, Size(5.0f, 5.0f));
53 EXPECT_EQ(radii.top_right, Size(5.0f, 5.0f));
54 EXPECT_EQ(radii.bottom_left, Size(5.0f, 5.0f));
55 EXPECT_EQ(radii.bottom_right, Size(5.0f, 5.0f));
56 }
57
58 TEST(RoundRectTest, RoundingRadiiEmptyScalarConstructor) {
59 RoundingRadii radii = RoundingRadii::MakeRadius(-5.0f);
60
61 EXPECT_TRUE(radii.AreAllCornersEmpty());
62 EXPECT_TRUE(radii.AreAllCornersSame());
63 EXPECT_TRUE(radii.IsFinite());
64 EXPECT_EQ(radii.top_left, Size(-5.0f, -5.0f));
65 EXPECT_EQ(radii.top_right, Size(-5.0f, -5.0f));
66 EXPECT_EQ(radii.bottom_left, Size(-5.0f, -5.0f));
67 EXPECT_EQ(radii.bottom_right, Size(-5.0f, -5.0f));
68 }
69
70 TEST(RoundRectTest, RoundingRadiiSizeConstructor) {
71 RoundingRadii radii = RoundingRadii::MakeRadii(Size(5.0f, 6.0f));
72
73 EXPECT_FALSE(radii.AreAllCornersEmpty());
74 EXPECT_TRUE(radii.AreAllCornersSame());
75 EXPECT_TRUE(radii.IsFinite());
76 EXPECT_EQ(radii.top_left, Size(5.0f, 6.0f));
77 EXPECT_EQ(radii.top_right, Size(5.0f, 6.0f));
78 EXPECT_EQ(radii.bottom_left, Size(5.0f, 6.0f));
79 EXPECT_EQ(radii.bottom_right, Size(5.0f, 6.0f));
80 }
81
82 TEST(RoundRectTest, RoundingRadiiEmptySizeConstructor) {
83 {
84 RoundingRadii radii = RoundingRadii::MakeRadii(Size(-5.0f, 6.0f));
85
86 EXPECT_TRUE(radii.AreAllCornersEmpty());
87 EXPECT_TRUE(radii.AreAllCornersSame());
88 EXPECT_TRUE(radii.IsFinite());
89 EXPECT_EQ(radii.top_left, Size(-5.0f, 6.0f));
90 EXPECT_EQ(radii.top_right, Size(-5.0f, 6.0f));
91 EXPECT_EQ(radii.bottom_left, Size(-5.0f, 6.0f));
92 EXPECT_EQ(radii.bottom_right, Size(-5.0f, 6.0f));
93 }
94
95 {
96 RoundingRadii radii = RoundingRadii::MakeRadii(Size(5.0f, -6.0f));
97
98 EXPECT_TRUE(radii.AreAllCornersEmpty());
99 EXPECT_TRUE(radii.AreAllCornersSame());
100 EXPECT_TRUE(radii.IsFinite());
101 EXPECT_EQ(radii.top_left, Size(5.0f, -6.0f));
102 EXPECT_EQ(radii.top_right, Size(5.0f, -6.0f));
103 EXPECT_EQ(radii.bottom_left, Size(5.0f, -6.0f));
104 EXPECT_EQ(radii.bottom_right, Size(5.0f, -6.0f));
105 }
106 }
107
108 TEST(RoundRectTest, RoundingRadiiNamedSizesConstructor) {
109 RoundingRadii radii = {
110 .top_left = Size(5.0f, 5.5f),
111 .top_right = Size(6.0f, 6.5f),
112 .bottom_left = Size(7.0f, 7.5f),
113 .bottom_right = Size(8.0f, 8.5f),
114 };
115
116 EXPECT_FALSE(radii.AreAllCornersEmpty());
117 EXPECT_FALSE(radii.AreAllCornersSame());
118 EXPECT_TRUE(radii.IsFinite());
119 EXPECT_EQ(radii.top_left, Size(5.0f, 5.5f));
120 EXPECT_EQ(radii.top_right, Size(6.0f, 6.5f));
121 EXPECT_EQ(radii.bottom_left, Size(7.0f, 7.5f));
122 EXPECT_EQ(radii.bottom_right, Size(8.0f, 8.5f));
123 }
124
125 TEST(RoundRectTest, RoundingRadiiPartialNamedSizesConstructor) {
126 {
127 RoundingRadii radii = {
128 .top_left = Size(5.0f, 5.5f),
129 };
130
131 EXPECT_FALSE(radii.AreAllCornersEmpty());
132 EXPECT_FALSE(radii.AreAllCornersSame());
133 EXPECT_TRUE(radii.IsFinite());
134 EXPECT_EQ(radii.top_left, Size(5.0f, 5.5f));
135 EXPECT_EQ(radii.top_right, Size());
136 EXPECT_EQ(radii.bottom_left, Size());
137 EXPECT_EQ(radii.bottom_right, Size());
138 }
139
140 {
141 RoundingRadii radii = {
142 .top_right = Size(6.0f, 6.5f),
143 };
144
145 EXPECT_FALSE(radii.AreAllCornersEmpty());
146 EXPECT_FALSE(radii.AreAllCornersSame());
147 EXPECT_TRUE(radii.IsFinite());
148 EXPECT_EQ(radii.top_left, Size());
149 EXPECT_EQ(radii.top_right, Size(6.0f, 6.5f));
150 EXPECT_EQ(radii.bottom_left, Size());
151 EXPECT_EQ(radii.bottom_right, Size());
152 }
153
154 {
155 RoundingRadii radii = {
156 .bottom_left = Size(7.0f, 7.5f),
157 };
158
159 EXPECT_FALSE(radii.AreAllCornersEmpty());
160 EXPECT_FALSE(radii.AreAllCornersSame());
161 EXPECT_TRUE(radii.IsFinite());
162 EXPECT_EQ(radii.top_left, Size());
163 EXPECT_EQ(radii.top_right, Size());
164 EXPECT_EQ(radii.bottom_left, Size(7.0f, 7.5f));
165 EXPECT_EQ(radii.bottom_right, Size());
166 }
167
168 {
169 RoundingRadii radii = {
170 .bottom_right = Size(8.0f, 8.5f),
171 };
172
173 EXPECT_FALSE(radii.AreAllCornersEmpty());
174 EXPECT_FALSE(radii.AreAllCornersSame());
175 EXPECT_TRUE(radii.IsFinite());
176 EXPECT_EQ(radii.top_left, Size());
177 EXPECT_EQ(radii.top_right, Size());
178 EXPECT_EQ(radii.bottom_left, Size());
179 EXPECT_EQ(radii.bottom_right, Size(8.0f, 8.5f));
180 }
181 }
182
183 TEST(RoundRectTest, RoundingRadiiMultiply) {
184 RoundingRadii radii = {
185 .top_left = Size(5.0f, 5.5f),
186 .top_right = Size(6.0f, 6.5f),
187 .bottom_left = Size(7.0f, 7.5f),
188 .bottom_right = Size(8.0f, 8.5f),
189 };
190 RoundingRadii doubled = radii * 2.0f;
191
192 EXPECT_FALSE(doubled.AreAllCornersEmpty());
193 EXPECT_FALSE(doubled.AreAllCornersSame());
194 EXPECT_TRUE(doubled.IsFinite());
195 EXPECT_EQ(doubled.top_left, Size(10.0f, 11.0f));
196 EXPECT_EQ(doubled.top_right, Size(12.0f, 13.0f));
197 EXPECT_EQ(doubled.bottom_left, Size(14.0f, 15.0f));
198 EXPECT_EQ(doubled.bottom_right, Size(16.0f, 17.0f));
199 }
200
201 TEST(RoundRectTest, RoundingRadiiEquals) {
202 RoundingRadii radii = {
203 .top_left = Size(5.0f, 5.5f),
204 .top_right = Size(6.0f, 6.5f),
205 .bottom_left = Size(7.0f, 7.5f),
206 .bottom_right = Size(8.0f, 8.5f),
207 };
208 RoundingRadii other = {
209 .top_left = Size(5.0f, 5.5f),
210 .top_right = Size(6.0f, 6.5f),
211 .bottom_left = Size(7.0f, 7.5f),
212 .bottom_right = Size(8.0f, 8.5f),
213 };
214
215 EXPECT_EQ(radii, other);
216 }
217
218 TEST(RoundRectTest, RoundingRadiiNotEquals) {
219 const RoundingRadii radii = {
220 .top_left = Size(5.0f, 5.5f),
221 .top_right = Size(6.0f, 6.5f),
222 .bottom_left = Size(7.0f, 7.5f),
223 .bottom_right = Size(8.0f, 8.5f),
224 };
225
226 {
227 RoundingRadii different = radii;
228 different.top_left.width = 100.0f;
229 EXPECT_NE(different, radii);
230 }
231 {
232 RoundingRadii different = radii;
233 different.top_left.height = 100.0f;
234 EXPECT_NE(different, radii);
235 }
236 {
237 RoundingRadii different = radii;
238 different.top_right.width = 100.0f;
239 EXPECT_NE(different, radii);
240 }
241 {
242 RoundingRadii different = radii;
243 different.top_right.height = 100.0f;
244 EXPECT_NE(different, radii);
245 }
246 {
247 RoundingRadii different = radii;
248 different.bottom_left.width = 100.0f;
249 EXPECT_NE(different, radii);
250 }
251 {
252 RoundingRadii different = radii;
253 different.bottom_left.height = 100.0f;
254 EXPECT_NE(different, radii);
255 }
256 {
257 RoundingRadii different = radii;
258 different.bottom_right.width = 100.0f;
259 EXPECT_NE(different, radii);
260 }
261 {
262 RoundingRadii different = radii;
263 different.bottom_right.height = 100.0f;
264 EXPECT_NE(different, radii);
265 }
266 }
267
268 TEST(RoundRectTest, RoundingRadiiCornersSameTolerance) {
269 RoundingRadii radii{
270 .top_left = {10, 20},
271 .top_right = {10.01, 20.01},
272 .bottom_left = {9.99, 19.99},
273 .bottom_right = {9.99, 20.01},
274 };
275
276 EXPECT_TRUE(radii.AreAllCornersSame(.02));
277
278 {
279 RoundingRadii different = radii;
280 different.top_left.width = 10.03;
281 EXPECT_FALSE(different.AreAllCornersSame(.02));
282 }
283 {
284 RoundingRadii different = radii;
285 different.top_left.height = 20.03;
286 EXPECT_FALSE(different.AreAllCornersSame(.02));
287 }
288 {
289 RoundingRadii different = radii;
290 different.top_right.width = 10.03;
291 EXPECT_FALSE(different.AreAllCornersSame(.02));
292 }
293 {
294 RoundingRadii different = radii;
295 different.top_right.height = 20.03;
296 EXPECT_FALSE(different.AreAllCornersSame(.02));
297 }
298 {
299 RoundingRadii different = radii;
300 different.bottom_left.width = 9.97;
301 EXPECT_FALSE(different.AreAllCornersSame(.02));
302 }
303 {
304 RoundingRadii different = radii;
305 different.bottom_left.height = 19.97;
306 EXPECT_FALSE(different.AreAllCornersSame(.02));
307 }
308 {
309 RoundingRadii different = radii;
310 different.bottom_right.width = 9.97;
311 EXPECT_FALSE(different.AreAllCornersSame(.02));
312 }
313 {
314 RoundingRadii different = radii;
315 different.bottom_right.height = 20.03;
316 EXPECT_FALSE(different.AreAllCornersSame(.02));
317 }
318 }
319
320 TEST(RoundRectTest, EmptyDeclaration) {
321 RoundRect round_rect;
322
323 EXPECT_TRUE(round_rect.IsEmpty());
324 EXPECT_FALSE(round_rect.IsRect());
325 EXPECT_FALSE(round_rect.IsOval());
326 EXPECT_TRUE(round_rect.IsFinite());
327 EXPECT_TRUE(round_rect.GetBounds().IsEmpty());
328 EXPECT_EQ(round_rect.GetBounds(), Rect());
329 EXPECT_EQ(round_rect.GetBounds().GetLeft(), 0.0f);
330 EXPECT_EQ(round_rect.GetBounds().GetTop(), 0.0f);
331 EXPECT_EQ(round_rect.GetBounds().GetRight(), 0.0f);
332 EXPECT_EQ(round_rect.GetBounds().GetBottom(), 0.0f);
333 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
334 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
335 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
336 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
337 EXPECT_EQ(round_rect.GetRadii().top_left.width, 0.0f);
338 EXPECT_EQ(round_rect.GetRadii().top_left.height, 0.0f);
339 EXPECT_EQ(round_rect.GetRadii().top_right.width, 0.0f);
340 EXPECT_EQ(round_rect.GetRadii().top_right.height, 0.0f);
341 EXPECT_EQ(round_rect.GetRadii().bottom_left.width, 0.0f);
342 EXPECT_EQ(round_rect.GetRadii().bottom_left.height, 0.0f);
343 EXPECT_EQ(round_rect.GetRadii().bottom_right.width, 0.0f);
344 EXPECT_EQ(round_rect.GetRadii().bottom_right.height, 0.0f);
345 }
346
347 TEST(RoundRectTest, DefaultConstructor) {
348 RoundRect round_rect = RoundRect();
349
350 EXPECT_TRUE(round_rect.IsEmpty());
351 EXPECT_FALSE(round_rect.IsRect());
352 EXPECT_FALSE(round_rect.IsOval());
353 EXPECT_TRUE(round_rect.IsFinite());
354 EXPECT_TRUE(round_rect.GetBounds().IsEmpty());
355 EXPECT_EQ(round_rect.GetBounds(), Rect());
356 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
357 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
358 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
359 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
360 }
361
362 TEST(RoundRectTest, EmptyRectConstruction) {
363 RoundRect round_rect =
364 RoundRect::MakeRect(Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
365
366 EXPECT_TRUE(round_rect.IsEmpty());
367 EXPECT_FALSE(round_rect.IsRect());
368 EXPECT_FALSE(round_rect.IsOval());
369 EXPECT_TRUE(round_rect.IsFinite());
370 EXPECT_TRUE(round_rect.GetBounds().IsEmpty());
371 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
372 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
373 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
374 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
375 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
376 }
377
378 TEST(RoundRectTest, RectConstructor) {
379 RoundRect round_rect =
380 RoundRect::MakeRect(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
381
382 EXPECT_FALSE(round_rect.IsEmpty());
383 EXPECT_TRUE(round_rect.IsRect());
384 EXPECT_FALSE(round_rect.IsOval());
385 EXPECT_TRUE(round_rect.IsFinite());
386 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
387 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
388 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
389 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
390 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
391 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
392 }
393
394 TEST(RoundRectTest, InvertedRectConstruction) {
395 RoundRect round_rect =
396 RoundRect::MakeRect(Rect::MakeLTRB(20.0f, 20.0f, 10.0f, 10.0f));
397
398 EXPECT_FALSE(round_rect.IsEmpty());
399 EXPECT_TRUE(round_rect.IsRect());
400 EXPECT_FALSE(round_rect.IsOval());
401 EXPECT_TRUE(round_rect.IsFinite());
402 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
403 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
404 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
405 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
406 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
407 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
408 }
409
410 TEST(RoundRectTest, EmptyOvalConstruction) {
411 RoundRect round_rect = RoundRect::MakeRectXY(
412 Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f), 10.0f, 10.0f);
413
414 EXPECT_TRUE(round_rect.IsEmpty());
415 EXPECT_FALSE(round_rect.IsRect());
416 EXPECT_FALSE(round_rect.IsOval());
417 EXPECT_TRUE(round_rect.IsFinite());
418 EXPECT_TRUE(round_rect.GetBounds().IsEmpty());
419 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
420 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
421 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
422 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
423 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
424 }
425
426 TEST(RoundRectTest, OvalConstructor) {
427 RoundRect round_rect =
428 RoundRect::MakeOval(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
429
430 EXPECT_FALSE(round_rect.IsEmpty());
431 EXPECT_FALSE(round_rect.IsRect());
432 EXPECT_TRUE(round_rect.IsOval());
433 EXPECT_TRUE(round_rect.IsFinite());
434 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
435 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
436 EXPECT_EQ(round_rect.GetRadii().top_left, Size(5.0f, 5.0f));
437 EXPECT_EQ(round_rect.GetRadii().top_right, Size(5.0f, 5.0f));
438 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(5.0f, 5.0f));
439 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(5.0f, 5.0f));
440 }
441
442 TEST(RoundRectTest, InvertedOvalConstruction) {
443 RoundRect round_rect = RoundRect::MakeRectXY(
444 Rect::MakeLTRB(20.0f, 20.0f, 10.0f, 10.0f), 10.0f, 10.0f);
445
446 EXPECT_FALSE(round_rect.IsEmpty());
447 EXPECT_FALSE(round_rect.IsRect());
448 EXPECT_TRUE(round_rect.IsOval());
449 EXPECT_TRUE(round_rect.IsFinite());
450 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
451 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
452 EXPECT_EQ(round_rect.GetRadii().top_left, Size(5.0f, 5.0f));
453 EXPECT_EQ(round_rect.GetRadii().top_right, Size(5.0f, 5.0f));
454 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(5.0f, 5.0f));
455 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(5.0f, 5.0f));
456 }
457
458 TEST(RoundRectTest, RectRadiusConstructor) {
459 RoundRect round_rect = RoundRect::MakeRectRadius(
460 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), 2.0f);
461
462 EXPECT_FALSE(round_rect.IsEmpty());
463 EXPECT_FALSE(round_rect.IsRect());
464 EXPECT_FALSE(round_rect.IsOval());
465 EXPECT_TRUE(round_rect.IsFinite());
466 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
467 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
468 EXPECT_EQ(round_rect.GetRadii().top_left, Size(2.0f, 2.0f));
469 EXPECT_EQ(round_rect.GetRadii().top_right, Size(2.0f, 2.0f));
470 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(2.0f, 2.0f));
471 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(2.0f, 2.0f));
472 }
473
474 TEST(RoundRectTest, RectXYConstructor) {
475 RoundRect round_rect = RoundRect::MakeRectXY(
476 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), 2.0f, 3.0f);
477
478 EXPECT_FALSE(round_rect.IsEmpty());
479 EXPECT_FALSE(round_rect.IsRect());
480 EXPECT_FALSE(round_rect.IsOval());
481 EXPECT_TRUE(round_rect.IsFinite());
482 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
483 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
484 EXPECT_EQ(round_rect.GetRadii().top_left, Size(2.0f, 3.0f));
485 EXPECT_EQ(round_rect.GetRadii().top_right, Size(2.0f, 3.0f));
486 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(2.0f, 3.0f));
487 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(2.0f, 3.0f));
488 }
489
490 TEST(RoundRectTest, RectSizeConstructor) {
491 RoundRect round_rect = RoundRect::MakeRectXY(
492 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), Size(2.0f, 3.0f));
493
494 EXPECT_FALSE(round_rect.IsEmpty());
495 EXPECT_FALSE(round_rect.IsRect());
496 EXPECT_FALSE(round_rect.IsOval());
497 EXPECT_TRUE(round_rect.IsFinite());
498 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
499 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
500 EXPECT_EQ(round_rect.GetRadii().top_left, Size(2.0f, 3.0f));
501 EXPECT_EQ(round_rect.GetRadii().top_right, Size(2.0f, 3.0f));
502 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(2.0f, 3.0f));
503 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(2.0f, 3.0f));
504 }
505
506 TEST(RoundRectTest, RectRadiiConstructor) {
507 RoundRect round_rect =
508 RoundRect::MakeRectRadii(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f),
509 {
510 .top_left = Size(1.0, 1.5),
511 .top_right = Size(2.0, 2.5f),
512 .bottom_left = Size(3.0, 3.5f),
513 .bottom_right = Size(4.0, 4.5f),
514 });
515
516 EXPECT_FALSE(round_rect.IsEmpty());
517 EXPECT_FALSE(round_rect.IsRect());
518 EXPECT_FALSE(round_rect.IsOval());
519 EXPECT_TRUE(round_rect.IsFinite());
520 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
521 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
522 EXPECT_EQ(round_rect.GetRadii().top_left, Size(1.0f, 1.5f));
523 EXPECT_EQ(round_rect.GetRadii().top_right, Size(2.0f, 2.5f));
524 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(3.0f, 3.5f));
525 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(4.0f, 4.5f));
526 }
527
528 TEST(RoundRectTest, RectRadiiOverflowWidthConstructor) {
529 RoundRect round_rect =
530 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 6.0f, 30.0f),
531 {
532 .top_left = Size(1.0f, 2.0f),
533 .top_right = Size(3.0f, 4.0f),
534 .bottom_left = Size(5.0f, 6.0f),
535 .bottom_right = Size(7.0f, 8.0f),
536 });
537 // Largest sum of paired radii widths is the bottom edge which sums to 12
538 // Rect is only 6 wide so all radii are scaled by half
539 // Rect is 30 tall so no scaling should happen due to radii heights
540
541 EXPECT_FALSE(round_rect.IsEmpty());
542 EXPECT_FALSE(round_rect.IsRect());
543 EXPECT_FALSE(round_rect.IsOval());
544 EXPECT_TRUE(round_rect.IsFinite());
545 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
546 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 16.0f, 40.0f));
547 EXPECT_EQ(round_rect.GetRadii().top_left, Size(0.5f, 1.0f));
548 EXPECT_EQ(round_rect.GetRadii().top_right, Size(1.5f, 2.0f));
549 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(2.5f, 3.0f));
550 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(3.5f, 4.0f));
551 }
552
553 TEST(RoundRectTest, RectRadiiOverflowHeightConstructor) {
554 RoundRect round_rect =
555 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 6.0f),
556 {
557 .top_left = Size(1.0f, 2.0f),
558 .top_right = Size(3.0f, 4.0f),
559 .bottom_left = Size(5.0f, 6.0f),
560 .bottom_right = Size(7.0f, 8.0f),
561 });
562 // Largest sum of paired radii heights is the right edge which sums to 12
563 // Rect is only 6 tall so all radii are scaled by half
564 // Rect is 30 wide so no scaling should happen due to radii widths
565
566 EXPECT_FALSE(round_rect.IsEmpty());
567 EXPECT_FALSE(round_rect.IsRect());
568 EXPECT_FALSE(round_rect.IsOval());
569 EXPECT_TRUE(round_rect.IsFinite());
570 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
571 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 40.0f, 16.0f));
572 EXPECT_EQ(round_rect.GetRadii().top_left, Size(0.5f, 1.0f));
573 EXPECT_EQ(round_rect.GetRadii().top_right, Size(1.5f, 2.0f));
574 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(2.5f, 3.0f));
575 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(3.5f, 4.0f));
576 }
577
578 TEST(RoundRectTest, Shift) {
579 RoundRect round_rect =
580 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
581 {
582 .top_left = Size(1.0f, 2.0f),
583 .top_right = Size(3.0f, 4.0f),
584 .bottom_left = Size(5.0f, 6.0f),
585 .bottom_right = Size(7.0f, 8.0f),
586 });
587 RoundRect shifted = round_rect.Shift(5.0, 6.0);
588
589 EXPECT_FALSE(shifted.IsEmpty());
590 EXPECT_FALSE(shifted.IsRect());
591 EXPECT_FALSE(shifted.IsOval());
592 EXPECT_TRUE(shifted.IsFinite());
593 EXPECT_FALSE(shifted.GetBounds().IsEmpty());
594 EXPECT_EQ(shifted.GetBounds(), Rect::MakeLTRB(15.0f, 16.0f, 45.0f, 46.0f));
595 EXPECT_EQ(shifted.GetRadii().top_left, Size(1.0f, 2.0f));
596 EXPECT_EQ(shifted.GetRadii().top_right, Size(3.0f, 4.0f));
597 EXPECT_EQ(shifted.GetRadii().bottom_left, Size(5.0f, 6.0f));
598 EXPECT_EQ(shifted.GetRadii().bottom_right, Size(7.0f, 8.0f));
599
600 EXPECT_EQ(shifted,
601 RoundRect::MakeRectRadii(Rect::MakeXYWH(15.0f, 16.0f, 30.0f, 30.0f),
602 {
603 .top_left = Size(1.0f, 2.0f),
604 .top_right = Size(3.0f, 4.0f),
605 .bottom_left = Size(5.0f, 6.0f),
606 .bottom_right = Size(7.0f, 8.0f),
607 }));
608 }
609
610 TEST(RoundRectTest, ExpandScalar) {
611 RoundRect round_rect =
612 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
613 {
614 .top_left = Size(1.0f, 2.0f),
615 .top_right = Size(3.0f, 4.0f),
616 .bottom_left = Size(5.0f, 6.0f),
617 .bottom_right = Size(7.0f, 8.0f),
618 });
619 RoundRect expanded = round_rect.Expand(5.0);
620
621 EXPECT_FALSE(expanded.IsEmpty());
622 EXPECT_FALSE(expanded.IsRect());
623 EXPECT_FALSE(expanded.IsOval());
624 EXPECT_TRUE(expanded.IsFinite());
625 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
626 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 5.0f, 45.0f, 45.0f));
627 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
628 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
629 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
630 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
631
632 EXPECT_EQ(expanded,
633 RoundRect::MakeRectRadii(Rect::MakeXYWH(5.0f, 5.0f, 40.0f, 40.0f),
634 {
635 .top_left = Size(1.0f, 2.0f),
636 .top_right = Size(3.0f, 4.0f),
637 .bottom_left = Size(5.0f, 6.0f),
638 .bottom_right = Size(7.0f, 8.0f),
639 }));
640 }
641
642 TEST(RoundRectTest, ExpandTwoScalars) {
643 RoundRect round_rect =
644 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
645 {
646 .top_left = Size(1.0f, 2.0f),
647 .top_right = Size(3.0f, 4.0f),
648 .bottom_left = Size(5.0f, 6.0f),
649 .bottom_right = Size(7.0f, 8.0f),
650 });
651 RoundRect expanded = round_rect.Expand(5.0, 6.0);
652
653 EXPECT_FALSE(expanded.IsEmpty());
654 EXPECT_FALSE(expanded.IsRect());
655 EXPECT_FALSE(expanded.IsOval());
656 EXPECT_TRUE(expanded.IsFinite());
657 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
658 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 4.0f, 45.0f, 46.0f));
659 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
660 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
661 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
662 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
663
664 EXPECT_EQ(expanded,
665 RoundRect::MakeRectRadii(Rect::MakeXYWH(5.0f, 4.0f, 40.0f, 42.0f),
666 {
667 .top_left = Size(1.0f, 2.0f),
668 .top_right = Size(3.0f, 4.0f),
669 .bottom_left = Size(5.0f, 6.0f),
670 .bottom_right = Size(7.0f, 8.0f),
671 }));
672 }
673
674 TEST(RoundRectTest, ExpandFourScalars) {
675 RoundRect round_rect =
676 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
677 {
678 .top_left = Size(1.0f, 2.0f),
679 .top_right = Size(3.0f, 4.0f),
680 .bottom_left = Size(5.0f, 6.0f),
681 .bottom_right = Size(7.0f, 8.0f),
682 });
683 RoundRect expanded = round_rect.Expand(5.0, 6.0, 7.0, 8.0);
684
685 EXPECT_FALSE(expanded.IsEmpty());
686 EXPECT_FALSE(expanded.IsRect());
687 EXPECT_FALSE(expanded.IsOval());
688 EXPECT_TRUE(expanded.IsFinite());
689 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
690 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 4.0f, 47.0f, 48.0f));
691 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
692 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
693 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
694 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
695
696 EXPECT_EQ(expanded,
697 RoundRect::MakeRectRadii(Rect::MakeXYWH(5.0f, 4.0f, 42.0f, 44.0f),
698 {
699 .top_left = Size(1.0f, 2.0f),
700 .top_right = Size(3.0f, 4.0f),
701 .bottom_left = Size(5.0f, 6.0f),
702 .bottom_right = Size(7.0f, 8.0f),
703 }));
704 }
705
706 TEST(RoundRectTest, ContractScalar) {
707 RoundRect round_rect =
708 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
709 {
710 .top_left = Size(1.0f, 2.0f),
711 .top_right = Size(3.0f, 4.0f),
712 .bottom_left = Size(5.0f, 6.0f),
713 .bottom_right = Size(7.0f, 8.0f),
714 });
715 RoundRect expanded = round_rect.Expand(-2.0);
716
717 EXPECT_FALSE(expanded.IsEmpty());
718 EXPECT_FALSE(expanded.IsRect());
719 EXPECT_FALSE(expanded.IsOval());
720 EXPECT_TRUE(expanded.IsFinite());
721 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
722 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(12.0f, 12.0f, 38.0f, 38.0f));
723 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
724 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
725 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
726 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
727
728 EXPECT_EQ(expanded,
729 RoundRect::MakeRectRadii(Rect::MakeXYWH(12.0f, 12.0f, 26.0f, 26.0f),
730 {
731 .top_left = Size(1.0f, 2.0f),
732 .top_right = Size(3.0f, 4.0f),
733 .bottom_left = Size(5.0f, 6.0f),
734 .bottom_right = Size(7.0f, 8.0f),
735 }));
736 }
737
738 TEST(RoundRectTest, ContractTwoScalars) {
739 RoundRect round_rect =
740 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
741 {
742 .top_left = Size(1.0f, 2.0f),
743 .top_right = Size(3.0f, 4.0f),
744 .bottom_left = Size(5.0f, 6.0f),
745 .bottom_right = Size(7.0f, 8.0f),
746 });
747 RoundRect expanded = round_rect.Expand(-1.0, -2.0);
748
749 EXPECT_FALSE(expanded.IsEmpty());
750 EXPECT_FALSE(expanded.IsRect());
751 EXPECT_FALSE(expanded.IsOval());
752 EXPECT_TRUE(expanded.IsFinite());
753 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
754 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(11.0f, 12.0f, 39.0f, 38.0f));
755 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
756 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
757 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
758 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
759
760 EXPECT_EQ(expanded,
761 RoundRect::MakeRectRadii(Rect::MakeXYWH(11.0f, 12.0f, 28.0f, 26.0f),
762 {
763 .top_left = Size(1.0f, 2.0f),
764 .top_right = Size(3.0f, 4.0f),
765 .bottom_left = Size(5.0f, 6.0f),
766 .bottom_right = Size(7.0f, 8.0f),
767 }));
768 }
769
770 TEST(RoundRectTest, ContractFourScalars) {
771 RoundRect round_rect =
772 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
773 {
774 .top_left = Size(1.0f, 2.0f),
775 .top_right = Size(3.0f, 4.0f),
776 .bottom_left = Size(5.0f, 6.0f),
777 .bottom_right = Size(7.0f, 8.0f),
778 });
779 RoundRect expanded = round_rect.Expand(-1.0, -1.5, -2.0, -2.5);
780
781 EXPECT_FALSE(expanded.IsEmpty());
782 EXPECT_FALSE(expanded.IsRect());
783 EXPECT_FALSE(expanded.IsOval());
784 EXPECT_TRUE(expanded.IsFinite());
785 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
786 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(11.0f, 11.5f, 38.0f, 37.5f));
787 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
788 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
789 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
790 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
791
792 EXPECT_EQ(expanded,
793 RoundRect::MakeRectRadii(Rect::MakeXYWH(11.0f, 11.5f, 27.0f, 26.0f),
794 {
795 .top_left = Size(1.0f, 2.0f),
796 .top_right = Size(3.0f, 4.0f),
797 .bottom_left = Size(5.0f, 6.0f),
798 .bottom_right = Size(7.0f, 8.0f),
799 }));
800 }
801
802 TEST(RoundRectTest, ContractAndRequireRadiiAdjustment) {
803 RoundRect round_rect =
804 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
805 {
806 .top_left = Size(1.0f, 2.0f),
807 .top_right = Size(3.0f, 4.0f),
808 .bottom_left = Size(5.0f, 6.0f),
809 .bottom_right = Size(7.0f, 8.0f),
810 });
811 RoundRect expanded = round_rect.Expand(-12.0);
812 // Largest sum of paired radii sizes are the bottom and right edges
813 // both of which sum to 12
814 // Rect was 30x30 reduced by 12 on all sides leaving only 6x6, so all
815 // radii are scaled by half to avoid overflowing the contracted rect
816
817 EXPECT_FALSE(expanded.IsEmpty());
818 EXPECT_FALSE(expanded.IsRect());
819 EXPECT_FALSE(expanded.IsOval());
820 EXPECT_TRUE(expanded.IsFinite());
821 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
822 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(22.0f, 22.0f, 28.0f, 28.0f));
823 EXPECT_EQ(expanded.GetRadii().top_left, Size(0.5f, 1.0f));
824 EXPECT_EQ(expanded.GetRadii().top_right, Size(1.5f, 2.0f));
825 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(2.5f, 3.0f));
826 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(3.5f, 4.0f));
827
828 // In this test, the MakeRectRadii constructor will make the same
829 // adjustment to the radii that the Expand method applied.
830 EXPECT_EQ(expanded,
831 RoundRect::MakeRectRadii(Rect::MakeXYWH(22.0f, 22.0f, 6.0f, 6.0f),
832 {
833 .top_left = Size(1.0f, 2.0f),
834 .top_right = Size(3.0f, 4.0f),
835 .bottom_left = Size(5.0f, 6.0f),
836 .bottom_right = Size(7.0f, 8.0f),
837 }));
838
839 // In this test, the arguments to the constructor supply the correctly
840 // adjusted radii (though there is no real way to tell other than
841 // the result is the same).
842 EXPECT_EQ(expanded,
843 RoundRect::MakeRectRadii(Rect::MakeXYWH(22.0f, 22.0f, 6.0f, 6.0f),
844 {
845 .top_left = Size(0.5f, 1.0f),
846 .top_right = Size(1.5f, 2.0f),
847 .bottom_left = Size(2.5f, 3.0f),
848 .bottom_right = Size(3.5f, 4.0f),
849 }));
850 }
851
852 TEST(RoundRectTest, NoCornerRoundRectContains) {
853 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
854 // RRect of bounds with no corners contains corners just barely
855 auto no_corners = RoundRect::MakeRectXY(bounds, 0.0f, 0.0f);
856
857 EXPECT_TRUE(no_corners.Contains({-50, -50}));
858 // Rectangles have half-in, half-out containment so we need
859 // to be careful about testing containment of right/bottom corners.
860 EXPECT_TRUE(no_corners.Contains({-50, 49.99}));
861 EXPECT_TRUE(no_corners.Contains({49.99, -50}));
862 EXPECT_TRUE(no_corners.Contains({49.99, 49.99}));
863 EXPECT_FALSE(no_corners.Contains({-50.01, -50}));
864 EXPECT_FALSE(no_corners.Contains({-50, -50.01}));
865 EXPECT_FALSE(no_corners.Contains({-50.01, 50}));
866 EXPECT_FALSE(no_corners.Contains({-50, 50.01}));
867 EXPECT_FALSE(no_corners.Contains({50.01, -50}));
868 EXPECT_FALSE(no_corners.Contains({50, -50.01}));
869 EXPECT_FALSE(no_corners.Contains({50.01, 50}));
870 EXPECT_FALSE(no_corners.Contains({50, 50.01}));
871 }
872
873 TEST(RoundRectTest, TinyCornerRoundRectContains) {
874 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
875 // RRect of bounds with even the tiniest corners does not contain corners
876 auto tiny_corners = RoundRect::MakeRectXY(bounds, 0.01f, 0.01f);
877
878 EXPECT_FALSE(tiny_corners.Contains({-50, -50}));
879 EXPECT_FALSE(tiny_corners.Contains({-50, 50}));
880 EXPECT_FALSE(tiny_corners.Contains({50, -50}));
881 EXPECT_FALSE(tiny_corners.Contains({50, 50}));
882 }
883
884 TEST(RoundRectTest, UniformCircularRoundRectContains) {
885 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
886 auto expanded_2_r_2 = RoundRect::MakeRectXY(bounds.Expand(2.0), 2.0f, 2.0f);
887
888 // Expanded by 2.0 and then with a corner of 2.0 obviously still
889 // contains the corners
890 EXPECT_TRUE(expanded_2_r_2.Contains({-50, -50}));
891 EXPECT_TRUE(expanded_2_r_2.Contains({-50, 50}));
892 EXPECT_TRUE(expanded_2_r_2.Contains({50, -50}));
893 EXPECT_TRUE(expanded_2_r_2.Contains({50, 50}));
894
895 // Now we try to box in the corner containment to exactly where the
896 // rounded corner of the expanded round rect with radii of 2.0 lies.
897 // The 45-degree diagonal point of a circle of radius 2.0 lies at:
898 //
899 // (2 * sqrt(2) / 2, 2 * sqrt(2) / 2)
900 // (sqrt(2), sqrt(2))
901 //
902 // So we test +/- (50 + sqrt(2) +/- epsilon)
903 const auto coord_out = 50 + kSqrt2 + kEhCloseEnough;
904 const auto coord_in = 50 + kSqrt2 - kEhCloseEnough;
905 // Upper left corner
906 EXPECT_TRUE(expanded_2_r_2.Contains({-coord_in, -coord_in}));
907 EXPECT_FALSE(expanded_2_r_2.Contains({-coord_out, -coord_out}));
908 // Upper right corner
909 EXPECT_TRUE(expanded_2_r_2.Contains({coord_in, -coord_in}));
910 EXPECT_FALSE(expanded_2_r_2.Contains({coord_out, -coord_out}));
911 // Lower left corner
912 EXPECT_TRUE(expanded_2_r_2.Contains({-coord_in, coord_in}));
913 EXPECT_FALSE(expanded_2_r_2.Contains({-coord_out, coord_out}));
914 // Lower right corner
915 EXPECT_TRUE(expanded_2_r_2.Contains({coord_in, coord_in}));
916 EXPECT_FALSE(expanded_2_r_2.Contains({coord_out, coord_out}));
917 }
918
919 TEST(RoundRectTest, UniformEllipticalRoundRectContains) {
920 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
921 auto expanded_2_r_2 = RoundRect::MakeRectXY(bounds.Expand(2.0), 2.0f, 3.0f);
922
923 // Expanded by 2.0 and then with a corner of 2x3 should still
924 // contain the corners
925 EXPECT_TRUE(expanded_2_r_2.Contains({-50, -50}));
926 EXPECT_TRUE(expanded_2_r_2.Contains({-50, 50}));
927 EXPECT_TRUE(expanded_2_r_2.Contains({50, -50}));
928 EXPECT_TRUE(expanded_2_r_2.Contains({50, 50}));
929
930 // Now we try to box in the corner containment to exactly where the
931 // rounded corner of the expanded round rect with radii of 2x3 lies.
932 // The "45-degree diagonal point" of an ellipse of radii 2x3 lies at:
933 //
934 // (2 * sqrt(2) / 2, 3 * sqrt(2) / 2)
935 // (sqrt(2), 3 * sqrt(2) / 2)
936 //
937 // And the center(s) of these corners are at:
938 // (+/-(50 + 2 - 2), +/-(50 + 2 - 3))
939 // = (+/-50, +/-49)
940 const auto x_coord_out = 50 + kSqrt2 + kEhCloseEnough;
941 const auto x_coord_in = 50 + kSqrt2 - kEhCloseEnough;
942 const auto y_coord_out = 49 + 3 * kSqrt2 / 2 + kEhCloseEnough;
943 const auto y_coord_in = 49 + 3 * kSqrt2 / 2 - kEhCloseEnough;
944 // Upper left corner
945 EXPECT_TRUE(expanded_2_r_2.Contains({-x_coord_in, -y_coord_in}));
946 EXPECT_FALSE(expanded_2_r_2.Contains({-x_coord_out, -y_coord_out}));
947 // Upper right corner
948 EXPECT_TRUE(expanded_2_r_2.Contains({x_coord_in, -y_coord_in}));
949 EXPECT_FALSE(expanded_2_r_2.Contains({x_coord_out, -y_coord_out}));
950 // Lower left corner
951 EXPECT_TRUE(expanded_2_r_2.Contains({-x_coord_in, y_coord_in}));
952 EXPECT_FALSE(expanded_2_r_2.Contains({-x_coord_out, y_coord_out}));
953 // Lower right corner
954 EXPECT_TRUE(expanded_2_r_2.Contains({x_coord_in, y_coord_in}));
955 EXPECT_FALSE(expanded_2_r_2.Contains({x_coord_out, y_coord_out}));
956 }
957
958 TEST(RoundRectTest, DifferingCornersRoundRectContains) {
959 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
960 auto round_rect =
961 RoundRect::MakeRectRadii(bounds, {
962 .top_left = Size(2.0, 3.0),
963 .top_right = Size(4.0, 5.0),
964 .bottom_left = Size(6.0, 7.0),
965 .bottom_right = Size(8.0, 9.0),
966 });
967
968 // For a corner with radii {A, B}, the "45 degree point" on the
969 // corner curve will be at an offset of:
970 //
971 // (A * sqrt(2) / 2, B * sqrt(2) / 2)
972 //
973 // And the center(s) of these corners are at:
974 //
975 // (+/-(50 - A), +/-(50 - B))
976 auto coord = [](Scalar radius) {
977 return 50 - radius + radius * kSqrt2 / 2.0f - kEhCloseEnough;
978 };
979 auto coord_in = [&coord](Scalar radius) {
980 return coord(radius) - kEhCloseEnough;
981 };
982 auto coord_out = [&coord](Scalar radius) {
983 // For some reason 1 kEhCloseEnough is not enough to put us outside
984 // in some of the cases, so we use 2x the epsilon.
985 return coord(radius) + 2 * kEhCloseEnough;
986 };
987 // Upper left corner (radii = {2.0, 3.0})
988 EXPECT_TRUE(round_rect.Contains({-coord_in(2.0), -coord_in(3.0)}));
989 EXPECT_FALSE(round_rect.Contains({-coord_out(2.0), -coord_out(3.0)}));
990 // Upper right corner (radii = {4.0, 5.0})
991 EXPECT_TRUE(round_rect.Contains({coord_in(4.0), -coord_in(5.0)}));
992 EXPECT_FALSE(round_rect.Contains({coord_out(4.0), -coord_out(5.0)}));
993 // Lower left corner (radii = {6.0, 7.0})
994 EXPECT_TRUE(round_rect.Contains({-coord_in(6.0), coord_in(7.0)}));
995 EXPECT_FALSE(round_rect.Contains({-coord_out(6.0), coord_out(7.0)}));
996 // Lower right corner (radii = {8.0, 9.0})
997 EXPECT_TRUE(round_rect.Contains({coord_in(8.0), coord_in(9.0)}));
998 EXPECT_FALSE(round_rect.Contains({coord_out(8.0), coord_out(9.0)}));
999 }
1000
1001 } // namespace testing
1002 } // namespace impeller
geometry_asserts.h
impeller::testing::TEST
TEST(AllocationSizeTest, CanCreateTypedAllocations)
Definition: allocation_size_unittests.cc:10
impeller
Definition: allocation.cc:12
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::kEhCloseEnough
constexpr float kEhCloseEnough
Definition: constants.h:56
impeller::Size
TSize< Scalar > Size
Definition: size.h:171
impeller::kSqrt2
constexpr float kSqrt2
Definition: constants.h:47
round_rect.h
impeller::RoundRect
Definition: round_rect.h:15
impeller::RoundRect::IsFinite
constexpr bool IsFinite() const
Definition: round_rect.h:46
impeller::RoundRect::GetRadii
constexpr const RoundingRadii & GetRadii() const
Definition: round_rect.h:44
impeller::RoundRect::MakeRectRadii
static RoundRect MakeRectRadii(const Rect &rect, const RoundingRadii &radii)
Definition: round_rect.cc:9
impeller::RoundRect::MakeRectRadius
constexpr static RoundRect MakeRectRadius(const Rect &rect, Scalar radius)
Definition: round_rect.h:26
impeller::RoundRect::IsEmpty
constexpr bool IsEmpty() const
Definition: round_rect.h:54
impeller::RoundRect::IsRect
constexpr bool IsRect() const
Definition: round_rect.h:56
impeller::RoundRect::MakeOval
constexpr static RoundRect MakeOval(const Rect &rect)
Definition: round_rect.h:22
impeller::RoundRect::Expand
constexpr RoundRect Expand(Scalar left, Scalar top, Scalar right, Scalar bottom) const
Returns a round rectangle with expanded edges. Negative expansion results in shrinking.
Definition: round_rect.h:87
impeller::RoundRect::MakeRect
constexpr static RoundRect MakeRect(const Rect &rect)
Definition: round_rect.h:18
impeller::RoundRect::Shift
constexpr RoundRect Shift(Scalar dx, Scalar dy) const
Returns a new round rectangle translated by the given offset.
Definition: round_rect.h:78
impeller::RoundRect::GetBounds
constexpr const Rect & GetBounds() const
Definition: round_rect.h:43
impeller::RoundRect::IsOval
constexpr bool IsOval() const
Definition: round_rect.h:60
impeller::RoundRect::MakeRectXY
constexpr static RoundRect MakeRectXY(const Rect &rect, Scalar x_radius, Scalar y_radius)
Definition: round_rect.h:30
impeller::RoundingRadii
Definition: rounding_radii.h:14
impeller::RoundingRadii::top_right
Size top_right
Definition: rounding_radii.h:16
impeller::RoundingRadii::bottom_left
Size bottom_left
Definition: rounding_radii.h:17
impeller::RoundingRadii::bottom_right
Size bottom_right
Definition: rounding_radii.h:18
impeller::RoundingRadii::top_left
Size top_left
Definition: rounding_radii.h:15
impeller::RoundingRadii::AreAllCornersEmpty
constexpr bool AreAllCornersEmpty() const
Definition: rounding_radii.h:35
impeller::RoundingRadii::MakeRadii
constexpr static RoundingRadii MakeRadii(Size radii)
Definition: rounding_radii.h:24
impeller::RoundingRadii::IsFinite
constexpr bool IsFinite() const
Definition: rounding_radii.h:28
impeller::RoundingRadii::AreAllCornersSame
constexpr bool AreAllCornersSame(Scalar tolerance=kEhCloseEnough) const
Definition: rounding_radii.h:42
impeller::RoundingRadii::MakeRadius
constexpr static RoundingRadii MakeRadius(Scalar radius)
Definition: rounding_radii.h:20
impeller::TRect< Scalar >
impeller::TRect::Expand
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
Definition: rect.h:622
impeller::TRect::GetBottom
constexpr auto GetBottom() const
Definition: rect.h:361
impeller::TRect::GetTop
constexpr auto GetTop() const
Definition: rect.h:357
impeller::TRect::IsEmpty
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
Definition: rect.h:301
impeller::TRect::GetLeft
constexpr auto GetLeft() const
Definition: rect.h:355
impeller::TRect::GetRight
constexpr auto GetRight() const
Definition: rect.h:359
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
impeller::TSize< Scalar >
impeller::TSize::height
Type height
Definition: size.h:29
impeller::TSize::width
Type width
Definition: size.h:28