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 
8 
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) {
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) {
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) {
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
TEST(AllocationSizeTest, CanCreateTypedAllocations)
float Scalar
Definition: scalar.h:18
constexpr float kEhCloseEnough
Definition: constants.h:56
TSize< Scalar > Size
Definition: size.h:171
constexpr float kSqrt2
Definition: constants.h:47
constexpr bool IsFinite() const
Definition: round_rect.h:46
constexpr const RoundingRadii & GetRadii() const
Definition: round_rect.h:44
static RoundRect MakeRectRadii(const Rect &rect, const RoundingRadii &radii)
Definition: round_rect.cc:9
constexpr static RoundRect MakeRectRadius(const Rect &rect, Scalar radius)
Definition: round_rect.h:26
constexpr bool IsEmpty() const
Definition: round_rect.h:54
constexpr bool IsRect() const
Definition: round_rect.h:56
constexpr static RoundRect MakeOval(const Rect &rect)
Definition: round_rect.h:22
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
constexpr static RoundRect MakeRect(const Rect &rect)
Definition: round_rect.h:18
constexpr RoundRect Shift(Scalar dx, Scalar dy) const
Returns a new round rectangle translated by the given offset.
Definition: round_rect.h:78
constexpr const Rect & GetBounds() const
Definition: round_rect.h:43
constexpr bool IsOval() const
Definition: round_rect.h:60
constexpr static RoundRect MakeRectXY(const Rect &rect, Scalar x_radius, Scalar y_radius)
Definition: round_rect.h:30
constexpr bool AreAllCornersEmpty() const
constexpr static RoundingRadii MakeRadii(Size radii)
constexpr bool IsFinite() const
constexpr bool AreAllCornersSame(Scalar tolerance=kEhCloseEnough) const
constexpr static RoundingRadii MakeRadius(Scalar radius)
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
constexpr auto GetBottom() const
Definition: rect.h:361
constexpr auto GetTop() const
Definition: rect.h:357
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
Definition: rect.h:301
constexpr auto GetLeft() const
Definition: rect.h:355
constexpr auto GetRight() const
Definition: rect.h:359
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
Type height
Definition: size.h:29
Type width
Definition: size.h:28