5 #include "gtest/gtest.h"
14 TEST(RectTest, RectEmptyDeclaration) {
17 EXPECT_EQ(rect.
GetLeft(), 0.0f);
18 EXPECT_EQ(rect.
GetTop(), 0.0f);
21 EXPECT_EQ(rect.
GetX(), 0.0f);
22 EXPECT_EQ(rect.
GetY(), 0.0f);
29 TEST(RectTest, IRectEmptyDeclaration) {
33 EXPECT_EQ(rect.
GetTop(), 0);
36 EXPECT_EQ(rect.
GetX(), 0);
37 EXPECT_EQ(rect.
GetY(), 0);
44 TEST(RectTest, RectDefaultConstructor) {
47 EXPECT_EQ(rect.
GetLeft(), 0.0f);
48 EXPECT_EQ(rect.
GetTop(), 0.0f);
51 EXPECT_EQ(rect.
GetX(), 0.0f);
52 EXPECT_EQ(rect.
GetY(), 0.0f);
59 TEST(RectTest, IRectDefaultConstructor) {
63 EXPECT_EQ(rect.
GetTop(), 0);
66 EXPECT_EQ(rect.
GetX(), 0);
67 EXPECT_EQ(rect.
GetY(), 0);
73 TEST(RectTest, RectSimpleLTRB) {
77 EXPECT_EQ(rect.
GetLeft(), 5.125f);
78 EXPECT_EQ(rect.
GetTop(), 10.25f);
81 EXPECT_EQ(rect.
GetX(), 5.125f);
82 EXPECT_EQ(rect.
GetY(), 10.25f);
89 TEST(RectTest, IRectSimpleLTRB) {
93 EXPECT_EQ(rect.
GetTop(), 10);
96 EXPECT_EQ(rect.
GetX(), 5);
97 EXPECT_EQ(rect.
GetY(), 10);
103 TEST(RectTest, RectSimpleXYWH) {
107 EXPECT_EQ(rect.
GetLeft(), 5.125f);
108 EXPECT_EQ(rect.
GetTop(), 10.25f);
109 EXPECT_EQ(rect.
GetRight(), 20.625f);
111 EXPECT_EQ(rect.
GetX(), 5.125f);
112 EXPECT_EQ(rect.
GetY(), 10.25f);
119 TEST(RectTest, IRectSimpleXYWH) {
123 EXPECT_EQ(rect.
GetTop(), 10);
126 EXPECT_EQ(rect.
GetX(), 5);
127 EXPECT_EQ(rect.
GetY(), 10);
137 EXPECT_EQ(rect.
GetLeft(), 0.0f);
138 EXPECT_EQ(rect.
GetTop(), 0.0f);
141 EXPECT_EQ(rect.
GetX(), 0.0f);
142 EXPECT_EQ(rect.
GetY(), 0.0f);
149 TEST(RectTest, IRectSimpleWH) {
154 EXPECT_EQ(rect.
GetTop(), 0);
157 EXPECT_EQ(rect.
GetX(), 0);
158 EXPECT_EQ(rect.
GetY(), 0);
164 TEST(RectTest, RectFromIRect) {
169 EXPECT_EQ(rect.
GetTop(), 20);
178 TEST(RectTest, RectMakeCircleBounds) {
182 EXPECT_EQ(rect.
GetLeft(), 80.0f);
184 EXPECT_EQ(rect.
GetTop(), 180.0f);
188 TEST(RectTest, RectMakeCircleBoundsNegativeRadius) {
192 EXPECT_EQ(rect.
GetLeft(), 120.0f);
194 EXPECT_EQ(rect.
GetTop(), 220.0f);
198 TEST(RectTest, IRectMakeCircleBounds) {
204 EXPECT_EQ(rect.
GetTop(), 180);
208 TEST(RectTest, IRectMakeCircleBoundsNegativeRadius) {
212 EXPECT_EQ(rect.
GetLeft(), 120);
214 EXPECT_EQ(rect.
GetTop(), 220);
218 TEST(RectTest, RectMakeEllipseBoundsSize) {
223 EXPECT_EQ(rect.
GetLeft(), 80.0f);
225 EXPECT_EQ(rect.
GetTop(), 170.0f);
229 TEST(RectTest, RectMakeEllipseBoundsNegativeSize) {
234 EXPECT_EQ(rect.
GetLeft(), 120.0f);
236 EXPECT_EQ(rect.
GetTop(), 230.0f);
240 TEST(RectTest, RectMakeEllipseBoundsPoint) {
245 EXPECT_EQ(rect.
GetLeft(), 80.0f);
247 EXPECT_EQ(rect.
GetTop(), 170.0f);
251 TEST(RectTest, RectMakeEllipseBoundsNegativePoint) {
256 EXPECT_EQ(rect.
GetLeft(), 120.0f);
258 EXPECT_EQ(rect.
GetTop(), 230.0f);
262 TEST(RectTest, IRectMakeEllipseBoundsSize) {
268 EXPECT_EQ(rect.
GetTop(), 170);
272 TEST(RectTest, IRectMakeEllipseBoundsNegativeSize) {
276 EXPECT_EQ(rect.
GetLeft(), 120);
278 EXPECT_EQ(rect.
GetTop(), 230);
282 TEST(RectTest, IRectMakeEllipseBoundsPoint) {
288 EXPECT_EQ(rect.
GetTop(), 170);
292 TEST(RectTest, IRectMakeEllipseBoundsNegativePoint) {
296 EXPECT_EQ(rect.
GetLeft(), 120);
298 EXPECT_EQ(rect.
GetTop(), 230);
302 TEST(RectTest, RectOverflowXYWH) {
303 auto min = std::numeric_limits<Scalar>::lowest();
304 auto max = std::numeric_limits<Scalar>::max();
305 auto inf = std::numeric_limits<Scalar>::infinity();
323 EXPECT_EQ(rect.
GetLeft(), 5.0f);
324 EXPECT_EQ(rect.
GetTop(), 10.0f);
327 EXPECT_EQ(rect.
GetX(), 5.0f);
328 EXPECT_EQ(rect.
GetY(), 10.0f);
338 EXPECT_EQ(rect.
GetLeft(), max);
339 EXPECT_EQ(rect.
GetTop(), 10.0f);
342 EXPECT_EQ(rect.
GetX(), max);
343 EXPECT_EQ(rect.
GetY(), 10.0f);
353 EXPECT_EQ(rect.
GetLeft(), 5.0f);
354 EXPECT_EQ(rect.
GetTop(), 10.0f);
357 EXPECT_EQ(rect.
GetX(), 5.0f);
358 EXPECT_EQ(rect.
GetY(), 10.0f);
368 EXPECT_EQ(rect.
GetLeft(), 5.0f);
369 EXPECT_EQ(rect.
GetTop(), max);
372 EXPECT_EQ(rect.
GetX(), 5.0f);
373 EXPECT_EQ(rect.
GetY(), max);
383 EXPECT_EQ(rect.
GetLeft(), 5.0f);
384 EXPECT_EQ(rect.
GetTop(), 10.0f);
387 EXPECT_EQ(rect.
GetX(), 5.0f);
388 EXPECT_EQ(rect.
GetY(), 10.0f);
398 EXPECT_EQ(rect.
GetLeft(), min);
399 EXPECT_EQ(rect.
GetTop(), 10.0f);
402 EXPECT_EQ(rect.
GetX(), min);
403 EXPECT_EQ(rect.
GetY(), 10.0f);
413 EXPECT_EQ(rect.
GetLeft(), 5.0f);
414 EXPECT_EQ(rect.
GetTop(), 10.0f);
417 EXPECT_EQ(rect.
GetX(), 5.0f);
418 EXPECT_EQ(rect.
GetY(), 10.0f);
428 EXPECT_EQ(rect.
GetLeft(), 5.0f);
429 EXPECT_EQ(rect.
GetTop(), min);
432 EXPECT_EQ(rect.
GetX(), 5.0f);
433 EXPECT_EQ(rect.
GetY(), min);
441 TEST(RectTest, IRectOverflowXYWH) {
442 auto min = std::numeric_limits<int64_t>::min();
443 auto max = std::numeric_limits<int64_t>::max();
454 EXPECT_EQ(rect.
GetLeft(), max - 5);
455 EXPECT_EQ(rect.
GetTop(), 10);
458 EXPECT_EQ(rect.
GetX(), max - 5);
459 EXPECT_EQ(rect.
GetY(), 10);
468 EXPECT_EQ(rect.
GetLeft(), min + 5);
469 EXPECT_EQ(rect.
GetTop(), 10);
472 EXPECT_EQ(rect.
GetX(), min + 5);
473 EXPECT_EQ(rect.
GetY(), 10);
483 EXPECT_EQ(rect.
GetTop(), max - 10);
486 EXPECT_EQ(rect.
GetX(), 5);
487 EXPECT_EQ(rect.
GetY(), max - 10);
497 EXPECT_EQ(rect.
GetTop(), min + 10);
500 EXPECT_EQ(rect.
GetX(), 5);
501 EXPECT_EQ(rect.
GetY(), min + 10);
508 TEST(RectTest, RectOverflowLTRB) {
509 auto min = std::numeric_limits<Scalar>::lowest();
510 auto max = std::numeric_limits<Scalar>::max();
511 auto inf = std::numeric_limits<Scalar>::infinity();
529 EXPECT_EQ(rect.
GetLeft(), -5.0f);
530 EXPECT_EQ(rect.
GetTop(), 10.0f);
533 EXPECT_EQ(rect.
GetX(), -5.0f);
534 EXPECT_EQ(rect.
GetY(), 10.0f);
544 EXPECT_EQ(rect.
GetLeft(), min + 5.0f);
545 EXPECT_EQ(rect.
GetTop(), 10.0f);
546 EXPECT_EQ(rect.
GetRight(), max - 5.0f);
548 EXPECT_EQ(rect.
GetX(), min + 5.0f);
549 EXPECT_EQ(rect.
GetY(), 10.0f);
559 EXPECT_EQ(rect.
GetLeft(), 5.0f);
560 EXPECT_EQ(rect.
GetTop(), -10.0f);
563 EXPECT_EQ(rect.
GetX(), 5.0f);
564 EXPECT_EQ(rect.
GetY(), -10.0f);
574 EXPECT_EQ(rect.
GetLeft(), 5.0f);
575 EXPECT_EQ(rect.
GetTop(), min + 10.0f);
577 EXPECT_EQ(rect.
GetBottom(), max - 15.0f);
578 EXPECT_EQ(rect.
GetX(), 5.0f);
579 EXPECT_EQ(rect.
GetY(), min + 10.0f);
589 EXPECT_EQ(rect.
GetLeft(), 5.0f);
590 EXPECT_EQ(rect.
GetTop(), 10.0f);
593 EXPECT_EQ(rect.
GetX(), 5.0f);
594 EXPECT_EQ(rect.
GetY(), 10.0f);
604 EXPECT_EQ(rect.
GetLeft(), max - 5.0f);
605 EXPECT_EQ(rect.
GetTop(), 10.0f);
606 EXPECT_EQ(rect.
GetRight(), min + 10.0f);
608 EXPECT_EQ(rect.
GetX(), max - 5.0f);
609 EXPECT_EQ(rect.
GetY(), 10.0f);
619 EXPECT_EQ(rect.
GetLeft(), 5.0f);
620 EXPECT_EQ(rect.
GetTop(), 10.0f);
623 EXPECT_EQ(rect.
GetX(), 5.0f);
624 EXPECT_EQ(rect.
GetY(), 10.0f);
634 EXPECT_EQ(rect.
GetLeft(), 5.0f);
635 EXPECT_EQ(rect.
GetTop(), max - 5.0f);
637 EXPECT_EQ(rect.
GetBottom(), min + 10.0f);
638 EXPECT_EQ(rect.
GetX(), 5.0f);
639 EXPECT_EQ(rect.
GetY(), max - 5.0f);
647 TEST(RectTest, IRectOverflowLTRB) {
648 auto min = std::numeric_limits<int64_t>::min();
649 auto max = std::numeric_limits<int64_t>::max();
660 EXPECT_EQ(rect.
GetLeft(), -10);
661 EXPECT_EQ(rect.
GetTop(), 10);
662 EXPECT_EQ(rect.
GetRight(), max - 5);
664 EXPECT_EQ(rect.
GetX(), -10);
665 EXPECT_EQ(rect.
GetY(), 10);
675 EXPECT_EQ(rect.
GetTop(), 10);
676 EXPECT_EQ(rect.
GetRight(), min + 5);
678 EXPECT_EQ(rect.
GetX(), 10);
679 EXPECT_EQ(rect.
GetY(), 10);
689 EXPECT_EQ(rect.
GetTop(), -10);
692 EXPECT_EQ(rect.
GetX(), 5);
693 EXPECT_EQ(rect.
GetY(), -10);
703 EXPECT_EQ(rect.
GetTop(), 10);
706 EXPECT_EQ(rect.
GetX(), 5);
707 EXPECT_EQ(rect.
GetY(), 10);
733 EXPECT_EQ(r, expected);
740 EXPECT_EQ(r, expected);
744 TEST(RectTest, RectMakeMaximum) {
746 auto inf = std::numeric_limits<Scalar>::infinity();
747 auto min = std::numeric_limits<Scalar>::lowest();
748 auto max = std::numeric_limits<Scalar>::max();
750 EXPECT_EQ(rect.
GetLeft(), min);
751 EXPECT_EQ(rect.
GetTop(), min);
754 EXPECT_EQ(rect.
GetX(), min);
755 EXPECT_EQ(rect.
GetY(), min);
762 TEST(RectTest, IRectMakeMaximum) {
764 auto min = std::numeric_limits<int64_t>::min();
765 auto max = std::numeric_limits<int64_t>::max();
767 EXPECT_EQ(rect.
GetLeft(), min);
768 EXPECT_EQ(rect.
GetTop(), min);
771 EXPECT_EQ(rect.
GetX(), min);
772 EXPECT_EQ(rect.
GetY(), min);
785 TEST(RectTest, IRectFromIRect) {
797 EXPECT_EQ(rect, copy);
798 EXPECT_EQ(copy.
GetLeft(), 5.125f);
799 EXPECT_EQ(copy.
GetTop(), 10.25f);
800 EXPECT_EQ(copy.
GetRight(), 20.625f);
802 EXPECT_EQ(copy.
GetX(), 5.125f);
803 EXPECT_EQ(copy.
GetY(), 10.25f);
814 EXPECT_EQ(rect, copy);
816 EXPECT_EQ(copy.
GetTop(), 10);
819 EXPECT_EQ(copy.
GetX(), 5);
820 EXPECT_EQ(copy.
GetY(), 10);
826 TEST(RectTest, RectOriginSizeXYWHGetters) {
831 EXPECT_EQ(r.
GetX(), 10);
832 EXPECT_EQ(r.
GetY(), 20);
835 auto expected_array = std::array<Scalar, 4>{10, 20, 50, 40};
836 EXPECT_EQ(r.
GetXYWH(), expected_array);
843 EXPECT_EQ(r.
GetX(), 10);
844 EXPECT_EQ(r.
GetY(), 20);
847 auto expected_array = std::array<Scalar, 4>{10, 20, 40, 20};
848 EXPECT_EQ(r.
GetXYWH(), expected_array);
852 TEST(RectTest, IRectOriginSizeXYWHGetters) {
857 EXPECT_EQ(r.
GetX(), 10);
858 EXPECT_EQ(r.
GetY(), 20);
861 auto expected_array = std::array<int64_t, 4>{10, 20, 50, 40};
862 EXPECT_EQ(r.
GetXYWH(), expected_array);
869 EXPECT_EQ(r.
GetX(), 10);
870 EXPECT_EQ(r.
GetY(), 20);
873 auto expected_array = std::array<int64_t, 4>{10, 20, 40, 20};
874 EXPECT_EQ(r.
GetXYWH(), expected_array);
878 TEST(RectTest, RectRoundOutEmpty) {
886 TEST(RectTest, RectRoundOutSimple) {
894 TEST(RectTest, RectRoundOutToIRectHuge) {
895 auto test = [](
int corners) {
896 EXPECT_TRUE(corners >= 0 && corners <= 0xf);
898 int64_t il, it, ir, ib;
903 if ((corners & (1 << 0)) != 0) {
905 il = std::numeric_limits<int64_t>::min();
907 if ((corners & (1 << 1)) != 0) {
909 it = std::numeric_limits<int64_t>::min();
911 if ((corners & (1 << 2)) != 0) {
913 ir = std::numeric_limits<int64_t>::max();
915 if ((corners & (1 << 3)) != 0) {
917 ib = std::numeric_limits<int64_t>::max();
922 EXPECT_EQ(irect.
GetLeft(), il) << corners;
923 EXPECT_EQ(irect.
GetTop(), it) << corners;
924 EXPECT_EQ(irect.
GetRight(), ir) << corners;
925 EXPECT_EQ(irect.
GetBottom(), ib) << corners;
928 for (
int corners = 0; corners <= 15; corners++) {
933 TEST(RectTest, RectDoesNotIntersectEmpty) {
937 const std::string& label) {
939 << label <<
" with Top/Bottom swapped";
941 << label <<
" with Left/Right swapped";
943 << label <<
" with all sides swapped";
946 test(20, 20, 30, 30,
"Above and Left");
947 test(70, 20, 80, 30,
"Above");
948 test(120, 20, 130, 30,
"Above and Right");
949 test(120, 70, 130, 80,
"Right");
950 test(120, 120, 130, 130,
"Below and Right");
951 test(70, 120, 80, 130,
"Below");
952 test(20, 120, 30, 130,
"Below and Left");
953 test(20, 70, 30, 80,
"Left");
955 test(70, 70, 80, 80,
"Inside");
957 test(40, 70, 60, 80,
"Straddling Left");
958 test(70, 40, 80, 60,
"Straddling Top");
959 test(90, 70, 110, 80,
"Straddling Right");
960 test(70, 90, 80, 110,
"Straddling Bottom");
963 TEST(RectTest, IRectDoesNotIntersectEmpty) {
966 auto test = [&rect](int64_t l, int64_t t, int64_t r, int64_t
b,
967 const std::string& label) {
969 << label <<
" with Top/Bottom swapped";
971 << label <<
" with Left/Right swapped";
973 << label <<
" with all sides swapped";
976 test(20, 20, 30, 30,
"Above and Left");
977 test(70, 20, 80, 30,
"Above");
978 test(120, 20, 130, 30,
"Above and Right");
979 test(120, 70, 130, 80,
"Right");
980 test(120, 120, 130, 130,
"Below and Right");
981 test(70, 120, 80, 130,
"Below");
982 test(20, 120, 30, 130,
"Below and Left");
983 test(20, 70, 30, 80,
"Left");
985 test(70, 70, 80, 80,
"Inside");
987 test(40, 70, 60, 80,
"Straddling Left");
988 test(70, 40, 80, 60,
"Straddling Top");
989 test(90, 70, 110, 80,
"Straddling Right");
990 test(70, 90, 80, 110,
"Straddling Bottom");
993 TEST(RectTest, EmptyRectDoesNotIntersect) {
997 const std::string& label) {
999 << label <<
" with Top/Bottom swapped";
1001 << label <<
" with Left/Right swapped";
1003 << label <<
" with all sides swapped";
1006 test(20, 20, 30, 30,
"Above and Left");
1007 test(70, 20, 80, 30,
"Above");
1008 test(120, 20, 130, 30,
"Above and Right");
1009 test(120, 70, 130, 80,
"Right");
1010 test(120, 120, 130, 130,
"Below and Right");
1011 test(70, 120, 80, 130,
"Below");
1012 test(20, 120, 30, 130,
"Below and Left");
1013 test(20, 70, 30, 80,
"Left");
1015 test(70, 70, 80, 80,
"Inside");
1017 test(40, 70, 60, 80,
"Straddling Left");
1018 test(70, 40, 80, 60,
"Straddling Top");
1019 test(90, 70, 110, 80,
"Straddling Right");
1020 test(70, 90, 80, 110,
"Straddling Bottom");
1023 TEST(RectTest, EmptyIRectDoesNotIntersect) {
1026 auto test = [&rect](int64_t l, int64_t t, int64_t r, int64_t
b,
1027 const std::string& label) {
1029 << label <<
" with Top/Bottom swapped";
1031 << label <<
" with Left/Right swapped";
1033 << label <<
" with all sides swapped";
1036 test(20, 20, 30, 30,
"Above and Left");
1037 test(70, 20, 80, 30,
"Above");
1038 test(120, 20, 130, 30,
"Above and Right");
1039 test(120, 70, 130, 80,
"Right");
1040 test(120, 120, 130, 130,
"Below and Right");
1041 test(70, 120, 80, 130,
"Below");
1042 test(20, 120, 30, 130,
"Below and Left");
1043 test(20, 70, 30, 80,
"Left");
1045 test(70, 70, 80, 80,
"Inside");
1047 test(40, 70, 60, 80,
"Straddling Left");
1048 test(70, 40, 80, 60,
"Straddling Top");
1049 test(90, 70, 110, 80,
"Straddling Right");
1050 test(70, 90, 80, 110,
"Straddling Bottom");
1056 rect.
GetY() * scale,
1061 << rect <<
" * " << scale;
1063 << rect <<
" * " << scale;
1065 << rect <<
" * " << scale;
1067 << rect <<
" * " << scale;
1072 rect.
GetY() * scale_y,
1077 << rect <<
" * " << scale_x <<
", " << scale_y;
1079 << rect <<
" * " << scale_x <<
", " << scale_y;
1081 << rect <<
" * " << scale_x <<
", " << scale_y;
1083 test1(rect, scale_x);
1084 test1(rect, scale_y);
1099 auto test1 = [](
IRect rect, int64_t scale) {
1101 rect.
GetY() * scale,
1105 EXPECT_EQ(rect.
Scale(scale), expected)
1106 << rect <<
" * " << scale;
1107 EXPECT_EQ(rect.
Scale(scale, scale), expected)
1108 << rect <<
" * " << scale;
1109 EXPECT_EQ(rect.
Scale(
IPoint(scale, scale)), expected)
1110 << rect <<
" * " << scale;
1111 EXPECT_EQ(rect.
Scale(
ISize(scale, scale)), expected)
1112 << rect <<
" * " << scale;
1115 auto test2 = [&test1](
IRect rect, int64_t scale_x, int64_t scale_y) {
1117 rect.
GetY() * scale_y,
1121 EXPECT_EQ(rect.
Scale(scale_x, scale_y), expected)
1122 << rect <<
" * " << scale_x <<
", " << scale_y;
1123 EXPECT_EQ(rect.
Scale(
IPoint(scale_x, scale_y)), expected)
1124 << rect <<
" * " << scale_x <<
", " << scale_y;
1125 EXPECT_EQ(rect.
Scale(
ISize(scale_x, scale_y)), expected)
1126 << rect <<
" * " << scale_x <<
", " << scale_y;
1128 test1(rect, scale_x);
1129 test1(rect, scale_y);
1158 TEST(RectTest, RectGetNormalizingTransform) {
1164 EXPECT_EQ(r.GetNormalizingTransform(),
1173 auto m = r.GetNormalizingTransform();
1182 EXPECT_EQ(m *
Point(350, 600),
Point(0.5, 0.5));
1185 EXPECT_EQ(m *
Point(200, 300),
Point(-1, -1));
1186 EXPECT_EQ(m *
Point(500, 300),
Point(2, -1));
1188 EXPECT_EQ(m *
Point(200, 900),
Point(-1, 2));
1197 EXPECT_EQ(
Rect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
1198 EXPECT_EQ(
Rect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
1199 EXPECT_EQ(
Rect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
1202 EXPECT_EQ(
Rect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
1203 EXPECT_EQ(
Rect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
1204 EXPECT_EQ(
Rect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
1211 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
1212 auto inf = std::numeric_limits<Scalar>::infinity();
1215 EXPECT_EQ(
Rect::MakeXYWH(10, 10, nan, 10).GetNormalizingTransform(), z);
1216 EXPECT_EQ(
Rect::MakeXYWH(10, 10, 10, nan).GetNormalizingTransform(), z);
1217 EXPECT_EQ(
Rect::MakeXYWH(10, 10, nan, nan).GetNormalizingTransform(), z);
1220 EXPECT_EQ(
Rect::MakeXYWH(10, 10, inf, 10).GetNormalizingTransform(), z);
1221 EXPECT_EQ(
Rect::MakeXYWH(10, 10, 10, inf).GetNormalizingTransform(), z);
1222 EXPECT_EQ(
Rect::MakeXYWH(10, 10, inf, inf).GetNormalizingTransform(), z);
1225 EXPECT_EQ(
Rect::MakeXYWH(10, 10, -inf, 10).GetNormalizingTransform(), z);
1226 EXPECT_EQ(
Rect::MakeXYWH(10, 10, 10, -inf).GetNormalizingTransform(), z);
1227 EXPECT_EQ(
Rect::MakeXYWH(10, 10, -inf, -inf).GetNormalizingTransform(), z);
1230 EXPECT_EQ(
Rect::MakeXYWH(nan, 10, 10, 10).GetNormalizingTransform(), z);
1231 EXPECT_EQ(
Rect::MakeXYWH(10, nan, 10, 10).GetNormalizingTransform(), z);
1232 EXPECT_EQ(
Rect::MakeXYWH(nan, nan, 10, 10).GetNormalizingTransform(), z);
1235 EXPECT_EQ(
Rect::MakeXYWH(inf, 10, 10, 10).GetNormalizingTransform(), z);
1236 EXPECT_EQ(
Rect::MakeXYWH(10, inf, 10, 10).GetNormalizingTransform(), z);
1237 EXPECT_EQ(
Rect::MakeXYWH(inf, inf, 10, 10).GetNormalizingTransform(), z);
1240 EXPECT_EQ(
Rect::MakeXYWH(-inf, 10, 10, 10).GetNormalizingTransform(), z);
1241 EXPECT_EQ(
Rect::MakeXYWH(10, -inf, 10, 10).GetNormalizingTransform(), z);
1242 EXPECT_EQ(
Rect::MakeXYWH(-inf, -inf, 10, 10).GetNormalizingTransform(), z);
1246 TEST(RectTest, IRectGetNormalizingTransform) {
1252 EXPECT_EQ(r.GetNormalizingTransform(),
1261 auto m = r.GetNormalizingTransform();
1270 EXPECT_EQ(m *
Point(350, 600),
Point(0.5, 0.5));
1273 EXPECT_EQ(m *
Point(200, 300),
Point(-1, -1));
1274 EXPECT_EQ(m *
Point(500, 300),
Point(2, -1));
1276 EXPECT_EQ(m *
Point(200, 900),
Point(-1, 2));
1285 EXPECT_EQ(
IRect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
1286 EXPECT_EQ(
IRect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
1287 EXPECT_EQ(
IRect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
1290 EXPECT_EQ(
IRect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
1291 EXPECT_EQ(
IRect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
1292 EXPECT_EQ(
IRect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
1297 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
1337 TEST(RectTest, MakePointBoundsQuad) {
1345 EXPECT_TRUE(bounds.has_value());
1346 if (bounds.has_value()) {
1382 EXPECT_EQ(rect.Expand(10, 10),
Rect::MakeLTRB(90, 90, 210, 210));
1383 EXPECT_EQ(rect.Expand(10, -10),
Rect::MakeLTRB(90, 110, 210, 190));
1384 EXPECT_EQ(rect.Expand(-10, 10),
Rect::MakeLTRB(110, 90, 190, 210));
1385 EXPECT_EQ(rect.Expand(-10, -10),
Rect::MakeLTRB(110, 110, 190, 190));
1388 EXPECT_EQ(rect.Expand(10, 20, 30, 40),
Rect::MakeLTRB(90, 80, 230, 240));
1389 EXPECT_EQ(rect.Expand(-10, 20, 30, 40),
Rect::MakeLTRB(110, 80, 230, 240));
1390 EXPECT_EQ(rect.Expand(10, -20, 30, 40),
Rect::MakeLTRB(90, 120, 230, 240));
1391 EXPECT_EQ(rect.Expand(10, 20, -30, 40),
Rect::MakeLTRB(90, 80, 170, 240));
1392 EXPECT_EQ(rect.Expand(10, 20, 30, -40),
Rect::MakeLTRB(90, 80, 230, 160));
1418 EXPECT_EQ(rect.Expand(-10, -10),
IRect::MakeLTRB(110, 110, 190, 190));
1421 EXPECT_EQ(rect.Expand(10, 20, 30, 40),
IRect::MakeLTRB(90, 80, 230, 240));
1422 EXPECT_EQ(rect.Expand(-10, 20, 30, 40),
IRect::MakeLTRB(110, 80, 230, 240));
1423 EXPECT_EQ(rect.Expand(10, -20, 30, 40),
IRect::MakeLTRB(90, 120, 230, 240));
1424 EXPECT_EQ(rect.Expand(10, 20, -30, 40),
IRect::MakeLTRB(90, 80, 170, 240));
1425 EXPECT_EQ(rect.Expand(10, 20, 30, -40),
IRect::MakeLTRB(90, 80, 230, 160));
1440 TEST(RectTest, RectExpandToMinTransformedSizeNullForScaledToZero) {
1443 EXPECT_EQ(rect.ExpandToMinTransformedSize({1.0f, 1.0f},
transform),
1447 TEST(RectTest, RectExpandToMinTransformedSizeReturnsUnmodifiedWhenLargeEnough) {
1455 RectExpandToMinTransformedSizeReturnsUnmodifiedWhenLargeEnoughWithFractionalSize) {
1462 TEST(RectTest, RectExpandToMinTransformedSizeRectWithIdentityTransform) {
1471 ASSERT_TRUE(expanded.has_value());
1472 if (expanded.has_value()) {
1473 EXPECT_EQ(expanded.value().GetSize(), size);
1480 ASSERT_TRUE(expanded.has_value());
1481 if (expanded.has_value()) {
1482 EXPECT_EQ(expanded.value().GetSize(),
Size(4.0f, 2.0f));
1489 ASSERT_TRUE(expanded.has_value());
1490 if (expanded.has_value()) {
1491 EXPECT_EQ(expanded.value().GetSize(),
Size(2.0f, 4.0f));
1498 ASSERT_TRUE(expanded.has_value());
1499 if (expanded.has_value()) {
1500 EXPECT_EQ(expanded.value().GetSize(),
Size(3.0f, 4.0f));
1505 TEST(RectTest, RectExpandToMinTransformedSizeRectWithScalingTransform) {
1517 ASSERT_TRUE(expanded.has_value());
1518 if (expanded.has_value()) {
1519 EXPECT_EQ(expanded.value().GetSize(), size);
1527 ASSERT_TRUE(expanded.has_value());
1528 if (expanded.has_value()) {
1529 EXPECT_EQ(expanded.value().GetSize(),
Size(2.5f, 2.0f));
1537 ASSERT_TRUE(expanded.has_value());
1538 if (expanded.has_value()) {
1539 EXPECT_EQ(expanded.value().GetSize(),
Size(2.0f, 3.0));
1546 ASSERT_TRUE(expanded.has_value());
1547 if (expanded.has_value()) {
1548 EXPECT_EQ(expanded.value().GetSize(),
Size(2.5f, 3.0f));
1553 TEST(RectTest, ContainsFloatingPoint) {
1555 Rect::MakeXYWH(472.599945f, 440.999969f, 1102.80005f, 654.000061f);
1557 EXPECT_TRUE(rect1.Contains(rect2));
1560 TEST(RectTest, FloatContainsInteger) {
1562 Rect::MakeLTRB(472.599945f, 440.999969f, 1574.80005f, 1094.000000f);
1572 template <
typename R>
1574 return R::MakeLTRB(rect.GetRight(), rect.GetTop(),
1575 rect.GetLeft(), rect.GetBottom());
1578 template <
typename R>
1580 return R::MakeLTRB(rect.GetLeft(), rect.GetBottom(),
1581 rect.GetRight(), rect.GetTop());
1584 template <
typename R>
1590 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1591 FML_DCHECK(index >= 0 && index <= 15);
1592 Scalar l = ((index & (1 << 0)) != 0) ? nan : rect.
GetLeft();
1593 Scalar t = ((index & (1 << 1)) != 0) ? nan : rect.
GetTop();
1600 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1601 FML_DCHECK(index >= 0 && index <= 3);
1602 Scalar x = ((index & (1 << 0)) != 0) ? nan : point.
x;
1603 Scalar y = ((index & (1 << 1)) != 0) ? nan : point.
y;
1608 auto check_nans = [](
const Rect& a,
const Rect&
b,
const std::string& label) {
1609 ASSERT_TRUE(a.
IsFinite()) << label;
1610 ASSERT_TRUE(
b.IsFinite()) << label;
1613 for (
int i = 1; i < 16; i++) {
1615 EXPECT_EQ(
swap_nan(a, i).Union(
b),
b) << label <<
", index = " << i;
1617 EXPECT_EQ(a.
Union(
swap_nan(
b, i)), a) << label <<
", index = " << i;
1619 for (
int j = 1; j < 16; j++) {
1621 << label <<
", indices = " << i <<
", " << j;
1626 auto check_empty_flips = [](
const Rect& a,
const Rect&
b,
1627 const std::string& label) {
1637 EXPECT_EQ(
flip_lr(a).Union(
b),
b) << label;
1638 EXPECT_EQ(
flip_tb(a).Union(
b),
b) << label;
1647 auto test = [&check_nans, &check_empty_flips](
const Rect& a,
const Rect&
b,
1648 const Rect& result) {
1649 ASSERT_FALSE(a.
IsEmpty()) << a;
1652 std::stringstream stream;
1653 stream << a <<
" union " <<
b;
1654 auto label = stream.str();
1656 EXPECT_EQ(a.
Union(
b), result) << label;
1657 EXPECT_EQ(
b.Union(a), result) << label;
1658 check_empty_flips(a,
b, label);
1659 check_nans(a,
b, label);
1666 test(a,
b, expected);
1673 test(a,
b, expected);
1680 test(a,
b, expected);
1687 test(a,
b, expected);
1694 test(a,
b, expected);
1704 EXPECT_FALSE(
Rect::Union(std::nullopt, std::nullopt).has_value());
1705 EXPECT_EQ(
Rect::Union(std::nullopt, std::nullopt), std::nullopt);
1707 auto test1 = [](
const Rect& r) {
1712 EXPECT_TRUE(
Rect::Union(std::optional(r), std::nullopt).has_value());
1719 EXPECT_TRUE(
Rect::Union(std::nullopt, std::optional(r)).has_value());
1727 auto test2 = [](
const Rect& a,
const Rect&
b,
const Rect& u) {
1728 ASSERT_EQ(a.
Union(
b), u);
1737 EXPECT_TRUE(
Rect::Union(std::optional(a), std::optional(
b)).has_value());
1747 auto check_empty_flips = [](
const IRect& a,
const IRect&
b,
1748 const std::string& label) {
1758 EXPECT_EQ(
flip_lr(a).Union(
b),
b) << label;
1759 EXPECT_EQ(
flip_tb(a).Union(
b),
b) << label;
1768 auto test = [&check_empty_flips](
const IRect& a,
const IRect&
b,
1769 const IRect& result) {
1770 ASSERT_FALSE(a.
IsEmpty()) << a;
1773 std::stringstream stream;
1774 stream << a <<
" union " <<
b;
1775 auto label = stream.str();
1777 EXPECT_EQ(a.
Union(
b), result) << label;
1778 EXPECT_EQ(
b.Union(a), result) << label;
1779 check_empty_flips(a,
b, label);
1786 test(a,
b, expected);
1793 test(a,
b, expected);
1800 test(a,
b, expected);
1807 test(a,
b, expected);
1814 test(a,
b, expected);
1824 EXPECT_FALSE(
IRect::Union(std::nullopt, std::nullopt).has_value());
1825 EXPECT_EQ(
IRect::Union(std::nullopt, std::nullopt), std::nullopt);
1827 auto test1 = [](
const IRect& r) {
1832 EXPECT_TRUE(
IRect::Union(std::optional(r), std::nullopt).has_value());
1839 EXPECT_TRUE(
IRect::Union(std::nullopt, std::optional(r)).has_value());
1848 ASSERT_EQ(a.
Union(
b), u);
1857 EXPECT_TRUE(
IRect::Union(std::optional(a), std::optional(
b)).has_value());
1867 auto check_nans = [](
const Rect& a,
const Rect&
b,
const std::string& label) {
1868 ASSERT_TRUE(a.
IsFinite()) << label;
1869 ASSERT_TRUE(
b.IsFinite()) << label;
1871 for (
int i = 1; i < 16; i++) {
1873 EXPECT_FALSE(
swap_nan(a, i).Intersection(
b).has_value())
1874 << label <<
", index = " << i;
1877 << label <<
", index = " << i;
1879 for (
int j = 1; j < 16; j++) {
1881 << label <<
", indices = " << i <<
", " << j;
1886 auto check_empty_flips = [](
const Rect& a,
const Rect&
b,
1887 const std::string& label) {
1900 EXPECT_FALSE(
flip_lr(a).Intersection(
b).has_value()) << label;
1901 EXPECT_TRUE(
flip_lr(a).IntersectionOrEmpty(
b).IsEmpty()) << label;
1902 EXPECT_FALSE(
flip_tb(a).Intersection(
b).has_value()) << label;
1903 EXPECT_TRUE(
flip_tb(a).IntersectionOrEmpty(
b).IsEmpty()) << label;
1904 EXPECT_FALSE(
flip_lrtb(a).Intersection(
b).has_value()) << label;
1905 EXPECT_TRUE(
flip_lrtb(a).IntersectionOrEmpty(
b).IsEmpty()) << label;
1908 EXPECT_FALSE(
flip_lr(a).Intersection(
flip_lr(
b)).has_value()) << label;
1909 EXPECT_TRUE(
flip_lr(a).IntersectionOrEmpty(
flip_lr(
b)).IsEmpty()) << label;
1910 EXPECT_FALSE(
flip_tb(a).Intersection(
flip_tb(
b)).has_value()) << label;
1911 EXPECT_TRUE(
flip_tb(a).IntersectionOrEmpty(
flip_tb(
b)).IsEmpty()) << label;
1917 auto test_non_empty = [&check_nans, &check_empty_flips](
1919 ASSERT_FALSE(a.
IsEmpty()) << a;
1922 std::stringstream stream;
1923 stream << a <<
" union " <<
b;
1924 auto label = stream.str();
1927 EXPECT_TRUE(
b.Intersection(a).has_value()) << label;
1929 EXPECT_EQ(
b.Intersection(a), result) << label;
1930 check_empty_flips(a,
b, label);
1931 check_nans(a,
b, label);
1934 auto test_empty = [&check_nans, &check_empty_flips](
const Rect& a,
1936 ASSERT_FALSE(a.
IsEmpty()) << a;
1939 std::stringstream stream;
1940 stream << a <<
" union " <<
b;
1941 auto label = stream.str();
1945 EXPECT_FALSE(
b.Intersection(a).has_value()) << label;
1946 EXPECT_TRUE(
b.IntersectionOrEmpty(a).IsEmpty()) << label;
1947 check_empty_flips(a,
b, label);
1948 check_nans(a,
b, label);
1970 test_non_empty(a,
b, expected);
1984 test_non_empty(a,
b,
b);
1995 TEST(RectTest, OptRectIntersection) {
2004 auto test1 = [](
const Rect& r) {
2026 auto test2 = [](
const Rect& a,
const Rect&
b,
const Rect& i) {
2049 TEST(RectTest, IRectIntersection) {
2050 auto check_empty_flips = [](
const IRect& a,
const IRect&
b,
2051 const std::string& label) {
2061 EXPECT_FALSE(
flip_lr(a).Intersection(
b).has_value()) << label;
2062 EXPECT_FALSE(
flip_tb(a).Intersection(
b).has_value()) << label;
2063 EXPECT_FALSE(
flip_lrtb(a).Intersection(
b).has_value()) << label;
2066 EXPECT_FALSE(
flip_lr(a).Intersection(
flip_lr(
b)).has_value()) << label;
2067 EXPECT_FALSE(
flip_tb(a).Intersection(
flip_tb(
b)).has_value()) << label;
2071 auto test_non_empty = [&check_empty_flips](
const IRect& a,
const IRect&
b,
2072 const IRect& result) {
2073 ASSERT_FALSE(a.
IsEmpty()) << a;
2076 std::stringstream stream;
2077 stream << a <<
" union " <<
b;
2078 auto label = stream.str();
2081 EXPECT_TRUE(
b.Intersection(a).has_value()) << label;
2083 EXPECT_EQ(
b.Intersection(a), result) << label;
2084 check_empty_flips(a,
b, label);
2087 auto test_empty = [&check_empty_flips](
const IRect& a,
const IRect&
b) {
2088 ASSERT_FALSE(a.
IsEmpty()) << a;
2091 std::stringstream stream;
2092 stream << a <<
" union " <<
b;
2093 auto label = stream.str();
2096 EXPECT_FALSE(
b.Intersection(a).has_value()) << label;
2097 check_empty_flips(a,
b, label);
2119 test_non_empty(a,
b, expected);
2133 test_non_empty(a,
b,
b);
2144 TEST(RectTest, OptIRectIntersection) {
2153 auto test1 = [](
const IRect& r) {
2200 TEST(RectTest, RectIntersectsWithRect) {
2201 auto check_nans = [](
const Rect& a,
const Rect&
b,
const std::string& label) {
2202 ASSERT_TRUE(a.
IsFinite()) << label;
2203 ASSERT_TRUE(
b.IsFinite()) << label;
2205 for (
int i = 1; i < 16; i++) {
2207 EXPECT_FALSE(
swap_nan(a, i).IntersectsWithRect(
b))
2208 << label <<
", index = " << i;
2211 << label <<
", index = " << i;
2213 for (
int j = 1; j < 16; j++) {
2215 << label <<
", indices = " << i <<
", " << j;
2220 auto check_empty_flips = [](
const Rect& a,
const Rect&
b,
2221 const std::string& label) {
2231 EXPECT_FALSE(
flip_lr(a).IntersectsWithRect(
b)) << label;
2232 EXPECT_FALSE(
flip_tb(a).IntersectsWithRect(
b)) << label;
2233 EXPECT_FALSE(
flip_lrtb(a).IntersectsWithRect(
b)) << label;
2241 auto test_non_empty = [&check_nans, &check_empty_flips](
const Rect& a,
2243 ASSERT_FALSE(a.
IsEmpty()) << a;
2246 std::stringstream stream;
2247 stream << a <<
" union " <<
b;
2248 auto label = stream.str();
2251 EXPECT_TRUE(
b.IntersectsWithRect(a)) << label;
2252 check_empty_flips(a,
b, label);
2253 check_nans(a,
b, label);
2256 auto test_empty = [&check_nans, &check_empty_flips](
const Rect& a,
2258 ASSERT_FALSE(a.
IsEmpty()) << a;
2261 std::stringstream stream;
2262 stream << a <<
" union " <<
b;
2263 auto label = stream.str();
2266 EXPECT_FALSE(
b.IntersectsWithRect(a)) << label;
2267 check_empty_flips(a,
b, label);
2268 check_nans(a,
b, label);
2289 test_non_empty(a,
b);
2303 test_non_empty(a,
b);
2310 test_non_empty(a,
b);
2314 TEST(RectTest, IRectIntersectsWithRect) {
2315 auto check_empty_flips = [](
const IRect& a,
const IRect&
b,
2316 const std::string& label) {
2326 EXPECT_FALSE(
flip_lr(a).IntersectsWithRect(
b)) << label;
2327 EXPECT_FALSE(
flip_tb(a).IntersectsWithRect(
b)) << label;
2328 EXPECT_FALSE(
flip_lrtb(a).IntersectsWithRect(
b)) << label;
2336 auto test_non_empty = [&check_empty_flips](
const IRect& a,
const IRect&
b) {
2337 ASSERT_FALSE(a.
IsEmpty()) << a;
2340 std::stringstream stream;
2341 stream << a <<
" union " <<
b;
2342 auto label = stream.str();
2345 EXPECT_TRUE(
b.IntersectsWithRect(a)) << label;
2346 check_empty_flips(a,
b, label);
2349 auto test_empty = [&check_empty_flips](
const IRect& a,
const IRect&
b) {
2350 ASSERT_FALSE(a.
IsEmpty()) << a;
2353 std::stringstream stream;
2354 stream << a <<
" union " <<
b;
2355 auto label = stream.str();
2358 EXPECT_FALSE(
b.IntersectsWithRect(a)) << label;
2359 check_empty_flips(a,
b, label);
2380 test_non_empty(a,
b);
2394 test_non_empty(a,
b);
2401 test_non_empty(a,
b);
2405 TEST(RectTest, RectContainsPoint) {
2406 auto check_nans = [](
const Rect& rect,
const Point& point,
2407 const std::string& label) {
2408 ASSERT_TRUE(rect.
IsFinite()) << label;
2409 ASSERT_TRUE(point.IsFinite()) << label;
2411 for (
int i = 1; i < 16; i++) {
2412 EXPECT_FALSE(
swap_nan(rect, i).Contains(point))
2413 << label <<
", index = " << i;
2414 for (
int j = 1; j < 4; j++) {
2416 << label <<
", indices = " << i <<
", " << j;
2421 auto check_empty_flips = [](
const Rect& rect,
const Point& point,
2422 const std::string& label) {
2425 EXPECT_FALSE(
flip_lr(rect).Contains(point)) << label;
2426 EXPECT_FALSE(
flip_tb(rect).Contains(point)) << label;
2427 EXPECT_FALSE(
flip_lrtb(rect).Contains(point)) << label;
2430 auto test_inside = [&check_nans, &check_empty_flips](
const Rect& rect,
2431 const Point& point) {
2432 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2434 std::stringstream stream;
2435 stream << rect <<
" contains " << point;
2436 auto label = stream.str();
2438 EXPECT_TRUE(rect.
Contains(point)) << label;
2439 check_empty_flips(rect, point, label);
2440 check_nans(rect, point, label);
2443 auto test_outside = [&check_nans, &check_empty_flips](
const Rect& rect,
2444 const Point& point) {
2445 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2447 std::stringstream stream;
2448 stream << rect <<
" contains " << point;
2449 auto label = stream.str();
2451 EXPECT_FALSE(rect.
Contains(point)) << label;
2452 check_empty_flips(rect, point, label);
2453 check_nans(rect, point, label);
2459 auto p =
Point(100, 100);
2466 auto p =
Point(200, 200);
2472 auto p =
Point(99, 99);
2478 auto p =
Point(199, 199);
2485 auto p =
Point(199, 199);
2491 TEST(RectTest, IRectContainsIPoint) {
2492 auto check_empty_flips = [](
const IRect& rect,
const IPoint& point,
2493 const std::string& label) {
2496 EXPECT_FALSE(
flip_lr(rect).Contains(point)) << label;
2497 EXPECT_FALSE(
flip_tb(rect).Contains(point)) << label;
2498 EXPECT_FALSE(
flip_lrtb(rect).Contains(point)) << label;
2501 auto test_inside = [&check_empty_flips](
const IRect& rect,
2503 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2505 std::stringstream stream;
2506 stream << rect <<
" contains " << point;
2507 auto label = stream.str();
2509 EXPECT_TRUE(rect.
Contains(point)) << label;
2510 check_empty_flips(rect, point, label);
2513 auto test_outside = [&check_empty_flips](
const IRect& rect,
2515 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2517 std::stringstream stream;
2518 stream << rect <<
" contains " << point;
2519 auto label = stream.str();
2521 EXPECT_FALSE(rect.
Contains(point)) << label;
2522 check_empty_flips(rect, point, label);
2528 auto p =
IPoint(100, 100);
2535 auto p =
IPoint(200, 200);
2547 auto p =
IPoint(199, 199);
2554 auto p =
IPoint(199, 199);
2560 TEST(RectTest, RectContainsInclusivePoint) {
2561 auto check_nans = [](
const Rect& rect,
const Point& point,
2562 const std::string& label) {
2563 ASSERT_TRUE(rect.
IsFinite()) << label;
2564 ASSERT_TRUE(point.IsFinite()) << label;
2566 for (
int i = 1; i < 16; i++) {
2567 EXPECT_FALSE(
swap_nan(rect, i).ContainsInclusive(point))
2568 << label <<
", index = " << i;
2569 for (
int j = 1; j < 4; j++) {
2571 << label <<
", indices = " << i <<
", " << j;
2576 auto check_empty_flips = [](
const Rect& rect,
const Point& point,
2577 const std::string& label) {
2580 EXPECT_FALSE(
flip_lr(rect).ContainsInclusive(point)) << label;
2581 EXPECT_FALSE(
flip_tb(rect).ContainsInclusive(point)) << label;
2582 EXPECT_FALSE(
flip_lrtb(rect).ContainsInclusive(point)) << label;
2585 auto test_inside = [&check_nans, &check_empty_flips](
const Rect& rect,
2586 const Point& point) {
2587 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2589 std::stringstream stream;
2590 stream << rect <<
" contains " << point;
2591 auto label = stream.str();
2594 check_empty_flips(rect, point, label);
2595 check_nans(rect, point, label);
2598 auto test_outside = [&check_nans, &check_empty_flips](
const Rect& rect,
2599 const Point& point) {
2600 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2602 std::stringstream stream;
2603 stream << rect <<
" contains " << point;
2604 auto label = stream.str();
2607 check_empty_flips(rect, point, label);
2608 check_nans(rect, point, label);
2614 auto p =
Point(100, 100);
2621 auto p =
Point(200, 200);
2634 auto p =
Point(99, 99);
2640 auto p =
Point(199, 199);
2647 auto p =
Point(199, 199);
2653 TEST(RectTest, IRectContainsInclusiveIPoint) {
2654 auto check_empty_flips = [](
const IRect& rect,
const IPoint& point,
2655 const std::string& label) {
2658 EXPECT_FALSE(
flip_lr(rect).ContainsInclusive(point)) << label;
2659 EXPECT_FALSE(
flip_tb(rect).ContainsInclusive(point)) << label;
2660 EXPECT_FALSE(
flip_lrtb(rect).ContainsInclusive(point)) << label;
2663 auto test_inside = [&check_empty_flips](
const IRect& rect,
2665 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2667 std::stringstream stream;
2668 stream << rect <<
" contains " << point;
2669 auto label = stream.str();
2672 check_empty_flips(rect, point, label);
2675 auto test_outside = [&check_empty_flips](
const IRect& rect,
2677 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2679 std::stringstream stream;
2680 stream << rect <<
" contains " << point;
2681 auto label = stream.str();
2684 check_empty_flips(rect, point, label);
2690 auto p =
IPoint(100, 100);
2697 auto p =
IPoint(200, 200);
2704 auto p =
IPoint(201, 201);
2716 auto p =
IPoint(199, 199);
2723 auto p =
IPoint(199, 199);
2730 auto check_nans = [](
const Rect& a,
const Rect&
b,
const std::string& label) {
2731 ASSERT_TRUE(a.
IsFinite()) << label;
2732 ASSERT_TRUE(
b.IsFinite()) << label;
2735 for (
int i = 1; i < 16; i++) {
2737 EXPECT_FALSE(
swap_nan(a, i).Contains(
b)) << label <<
", index = " << i;
2741 for (
int j = 1; j < 16; j++) {
2743 << label <<
", indices = " << i <<
", " << j;
2748 auto check_empty_flips = [](
const Rect& a,
const Rect&
b,
2749 const std::string& label) {
2752 ASSERT_FALSE(
b.GetLeft() >
b.GetRight() ||
b.GetTop() >
b.GetBottom());
2760 EXPECT_FALSE(
flip_lr(a).Contains(
b)) << label;
2761 EXPECT_FALSE(
flip_tb(a).Contains(
b)) << label;
2762 EXPECT_FALSE(
flip_lrtb(a).Contains(
b)) << label;
2770 auto test_inside = [&check_nans, &check_empty_flips](
const Rect& a,
2772 ASSERT_FALSE(a.
IsEmpty()) << a;
2774 ASSERT_FALSE(
b.GetLeft() >
b.GetRight() ||
b.GetTop() >
b.GetBottom());
2776 std::stringstream stream;
2777 stream << a <<
" contains " <<
b;
2778 auto label = stream.str();
2781 check_empty_flips(a,
b, label);
2782 check_nans(a,
b, label);
2785 auto test_not_inside = [&check_nans, &check_empty_flips](
const Rect& a,
2787 ASSERT_FALSE(a.
IsEmpty()) << a;
2790 ASSERT_FALSE(
b.IsEmpty()) <<
b;
2792 std::stringstream stream;
2793 stream << a <<
" contains " <<
b;
2794 auto label = stream.str();
2797 check_empty_flips(a,
b, label);
2798 check_nans(a,
b, label);
2822 test_not_inside(a,
b);
2828 test_not_inside(a,
b);
2834 test_not_inside(a,
b);
2844 TEST(RectTest, IRectContainsIRect) {
2845 auto check_empty_flips = [](
const IRect& a,
const IRect&
b,
2846 const std::string& label) {
2849 ASSERT_FALSE(
b.GetLeft() >
b.GetRight() ||
b.GetTop() >
b.GetBottom());
2857 EXPECT_FALSE(
flip_lr(a).Contains(
b)) << label;
2858 EXPECT_FALSE(
flip_tb(a).Contains(
b)) << label;
2859 EXPECT_FALSE(
flip_lrtb(a).Contains(
b)) << label;
2867 auto test_inside = [&check_empty_flips](
const IRect& a,
const IRect&
b) {
2868 ASSERT_FALSE(a.
IsEmpty()) << a;
2870 ASSERT_FALSE(
b.GetLeft() >
b.GetRight() ||
b.GetTop() >
b.GetBottom());
2872 std::stringstream stream;
2873 stream << a <<
" contains " <<
b;
2874 auto label = stream.str();
2877 check_empty_flips(a,
b, label);
2880 auto test_not_inside = [&check_empty_flips](
const IRect& a,
const IRect&
b) {
2881 ASSERT_FALSE(a.
IsEmpty()) << a;
2884 ASSERT_FALSE(
b.IsEmpty()) <<
b;
2886 std::stringstream stream;
2887 stream << a <<
" contains " <<
b;
2888 auto label = stream.str();
2891 check_empty_flips(a,
b, label);
2915 test_not_inside(a,
b);
2921 test_not_inside(a,
b);
2927 test_not_inside(a,
b);
2940 auto check_nans = [&cull_rect](
const Rect& diff_rect,
2941 const std::string& label) {
2942 EXPECT_TRUE(cull_rect.
IsFinite()) << label;
2943 EXPECT_TRUE(diff_rect.
IsFinite()) << label;
2945 for (
int i = 1; i < 16; i++) {
2947 EXPECT_FALSE(
swap_nan(cull_rect, i).Cutout(diff_rect).has_value())
2948 << label <<
", index " << i;
2949 EXPECT_EQ(
swap_nan(cull_rect, i).CutoutOrEmpty(diff_rect),
Rect())
2950 << label <<
", index " << i;
2953 EXPECT_TRUE(cull_rect.
Cutout(
swap_nan(diff_rect, i)).has_value())
2954 << label <<
", index " << i;
2956 << label <<
", index " << i;
2958 for (
int j = 1; j < 16; j++) {
2962 << label <<
", indices " << i <<
", " << j;
2965 << label <<
", indices " << i <<
", " << j;
2970 auto check_empty_flips = [&cull_rect](
const Rect& diff_rect,
2971 const std::string& label) {
2972 EXPECT_FALSE(cull_rect.
IsEmpty()) << label;
2973 EXPECT_FALSE(diff_rect.
IsEmpty()) << label;
2977 EXPECT_TRUE(cull_rect.
Cutout(
flip_lr(diff_rect)).has_value()) << label;
2978 EXPECT_EQ(cull_rect.
Cutout(
flip_lr(diff_rect)), cull_rect) << label;
2979 EXPECT_TRUE(cull_rect.
Cutout(
flip_tb(diff_rect)).has_value()) << label;
2980 EXPECT_EQ(cull_rect.
Cutout(
flip_tb(diff_rect)), cull_rect) << label;
2981 EXPECT_TRUE(cull_rect.
Cutout(
flip_lrtb(diff_rect)).has_value()) << label;
2982 EXPECT_EQ(cull_rect.
Cutout(
flip_lrtb(diff_rect)), cull_rect) << label;
2986 EXPECT_FALSE(
flip_lr(cull_rect).Cutout(diff_rect).has_value()) << label;
2987 EXPECT_EQ(
flip_lr(cull_rect).CutoutOrEmpty(diff_rect),
Rect()) << label;
2988 EXPECT_FALSE(
flip_tb(cull_rect).Cutout(diff_rect).has_value()) << label;
2989 EXPECT_EQ(
flip_tb(cull_rect).CutoutOrEmpty(diff_rect),
Rect()) << label;
2990 EXPECT_FALSE(
flip_lrtb(cull_rect).Cutout(diff_rect).has_value()) << label;
2991 EXPECT_EQ(
flip_lrtb(cull_rect).CutoutOrEmpty(diff_rect),
Rect()) << label;
2995 EXPECT_FALSE(
flip_lr(cull_rect).Cutout(
flip_lr(diff_rect)).has_value())
2999 EXPECT_FALSE(
flip_tb(cull_rect).Cutout(
flip_tb(diff_rect)).has_value())
3009 auto non_reducing = [&cull_rect, &check_empty_flips, &check_nans](
3010 const Rect& diff_rect,
const std::string& label) {
3011 EXPECT_EQ(cull_rect.
Cutout(diff_rect), cull_rect) << label;
3012 EXPECT_EQ(cull_rect.
CutoutOrEmpty(diff_rect), cull_rect) << label;
3013 check_empty_flips(diff_rect, label);
3014 check_nans(diff_rect, label);
3017 auto reducing = [&cull_rect, &check_empty_flips, &check_nans](
3018 const Rect& diff_rect,
const Rect& result_rect,
3019 const std::string& label) {
3020 EXPECT_TRUE(!result_rect.IsEmpty());
3021 EXPECT_EQ(cull_rect.
Cutout(diff_rect), result_rect) << label;
3022 EXPECT_EQ(cull_rect.
CutoutOrEmpty(diff_rect), result_rect) << label;
3023 check_empty_flips(diff_rect, label);
3024 check_nans(diff_rect, label);
3027 auto emptying = [&cull_rect, &check_empty_flips, &check_nans](
3028 const Rect& diff_rect,
const std::string& label) {
3029 EXPECT_FALSE(cull_rect.
Cutout(diff_rect).has_value()) << label;
3031 check_empty_flips(diff_rect, label);
3032 check_nans(diff_rect, label);
3036 non_reducing(
Rect::MakeLTRB(10, 10, 20, 20),
"outside UL corner");
3038 non_reducing(
Rect::MakeLTRB(40, 10, 50, 20),
"outside UR corner");
3040 non_reducing(
Rect::MakeLTRB(40, 40, 50, 50),
"outside LR corner");
3042 non_reducing(
Rect::MakeLTRB(10, 40, 20, 50),
"outside LR corner");
3046 non_reducing(
Rect::MakeLTRB(15, 15, 25, 25),
"covering UL corner");
3047 non_reducing(
Rect::MakeLTRB(35, 15, 45, 25),
"covering UR corner");
3048 non_reducing(
Rect::MakeLTRB(35, 35, 45, 45),
"covering LR corner");
3049 non_reducing(
Rect::MakeLTRB(15, 35, 25, 45),
"covering LL corner");
3052 non_reducing(
Rect::MakeLTRB(20, 15, 39, 25),
"Top edge left-biased");
3053 non_reducing(
Rect::MakeLTRB(21, 15, 40, 25),
"Top edge, right biased");
3054 non_reducing(
Rect::MakeLTRB(35, 20, 45, 39),
"Right edge, top-biased");
3055 non_reducing(
Rect::MakeLTRB(35, 21, 45, 40),
"Right edge, bottom-biased");
3056 non_reducing(
Rect::MakeLTRB(20, 35, 39, 45),
"Bottom edge, left-biased");
3057 non_reducing(
Rect::MakeLTRB(21, 35, 40, 45),
"Bottom edge, right-biased");
3058 non_reducing(
Rect::MakeLTRB(15, 20, 25, 39),
"Left edge, top-biased");
3059 non_reducing(
Rect::MakeLTRB(15, 21, 25, 40),
"Left edge, bottom-biased");
3062 non_reducing(
Rect::MakeLTRB(25, 15, 35, 45),
"Vertical interior slice");
3063 non_reducing(
Rect::MakeLTRB(15, 25, 45, 35),
"Horizontal interior slice");
3074 "Slice off bottom");
3080 non_reducing(
Rect::MakeLTRB(21, 21, 39, 39),
"Contained, non-covering");
3083 emptying(cull_rect,
"Perfectly covering");
3092 auto check_empty_flips = [&cull_rect](
const IRect& diff_rect,
3093 const std::string& label) {
3094 EXPECT_FALSE(diff_rect.
IsEmpty());
3095 EXPECT_FALSE(cull_rect.
IsEmpty());
3099 EXPECT_TRUE(cull_rect.
Cutout(
flip_lr(diff_rect)).has_value()) << label;
3100 EXPECT_EQ(cull_rect.
Cutout(
flip_lr(diff_rect)), cull_rect) << label;
3101 EXPECT_TRUE(cull_rect.
Cutout(
flip_tb(diff_rect)).has_value()) << label;
3102 EXPECT_EQ(cull_rect.
Cutout(
flip_tb(diff_rect)), cull_rect) << label;
3103 EXPECT_TRUE(cull_rect.
Cutout(
flip_lrtb(diff_rect)).has_value()) << label;
3104 EXPECT_EQ(cull_rect.
Cutout(
flip_lrtb(diff_rect)), cull_rect) << label;
3108 EXPECT_FALSE(
flip_lr(cull_rect).Cutout(diff_rect).has_value()) << label;
3109 EXPECT_EQ(
flip_lr(cull_rect).CutoutOrEmpty(diff_rect),
IRect()) << label;
3110 EXPECT_FALSE(
flip_tb(cull_rect).Cutout(diff_rect).has_value()) << label;
3111 EXPECT_EQ(
flip_tb(cull_rect).CutoutOrEmpty(diff_rect),
IRect()) << label;
3112 EXPECT_FALSE(
flip_lrtb(cull_rect).Cutout(diff_rect).has_value()) << label;
3113 EXPECT_EQ(
flip_lrtb(cull_rect).CutoutOrEmpty(diff_rect),
IRect()) << label;
3117 EXPECT_FALSE(
flip_lr(cull_rect).Cutout(
flip_lr(diff_rect)).has_value())
3121 EXPECT_FALSE(
flip_tb(cull_rect).Cutout(
flip_tb(diff_rect)).has_value())
3131 auto non_reducing = [&cull_rect, &check_empty_flips](
3132 const IRect& diff_rect,
const std::string& label) {
3133 EXPECT_EQ(cull_rect.
Cutout(diff_rect), cull_rect) << label;
3134 EXPECT_EQ(cull_rect.
CutoutOrEmpty(diff_rect), cull_rect) << label;
3135 check_empty_flips(diff_rect, label);
3138 auto reducing = [&cull_rect, &check_empty_flips](
const IRect& diff_rect,
3139 const IRect& result_rect,
3140 const std::string& label) {
3141 EXPECT_TRUE(!result_rect.IsEmpty());
3142 EXPECT_EQ(cull_rect.
Cutout(diff_rect), result_rect) << label;
3143 EXPECT_EQ(cull_rect.
CutoutOrEmpty(diff_rect), result_rect) << label;
3144 check_empty_flips(diff_rect, label);
3147 auto emptying = [&cull_rect, &check_empty_flips](
const IRect& diff_rect,
3148 const std::string& label) {
3149 EXPECT_FALSE(cull_rect.
Cutout(diff_rect).has_value()) << label;
3151 check_empty_flips(diff_rect, label);
3171 non_reducing(
IRect::MakeLTRB(20, 15, 39, 25),
"Top edge left-biased");
3172 non_reducing(
IRect::MakeLTRB(21, 15, 40, 25),
"Top edge, right biased");
3173 non_reducing(
IRect::MakeLTRB(35, 20, 45, 39),
"Right edge, top-biased");
3174 non_reducing(
IRect::MakeLTRB(35, 21, 45, 40),
"Right edge, bottom-biased");
3175 non_reducing(
IRect::MakeLTRB(20, 35, 39, 45),
"Bottom edge, left-biased");
3176 non_reducing(
IRect::MakeLTRB(21, 35, 40, 45),
"Bottom edge, right-biased");
3177 non_reducing(
IRect::MakeLTRB(15, 20, 25, 39),
"Left edge, top-biased");
3178 non_reducing(
IRect::MakeLTRB(15, 21, 25, 40),
"Left edge, bottom-biased");
3181 non_reducing(
IRect::MakeLTRB(25, 15, 35, 45),
"Vertical interior slice");
3182 non_reducing(
IRect::MakeLTRB(15, 25, 45, 35),
"Horizontal interior slice");
3193 "Slice off bottom");
3199 non_reducing(
IRect::MakeLTRB(21, 21, 39, 39),
"Contained, non-covering");
3202 emptying(cull_rect,
"Perfectly covering");
3221 EXPECT_EQ(
points[0],
Point(std::numeric_limits<float>::lowest(),
3222 std::numeric_limits<float>::lowest()));
3223 EXPECT_EQ(
points[1],
Point(std::numeric_limits<float>::max(),
3224 std::numeric_limits<float>::lowest()));
3225 EXPECT_EQ(
points[2],
Point(std::numeric_limits<float>::lowest(),
3226 std::numeric_limits<float>::max()));
3227 EXPECT_EQ(
points[3],
Point(std::numeric_limits<float>::max(),
3228 std::numeric_limits<float>::max()));
3239 TEST(RectTest, RectGetTransformedPoints) {
3248 TEST(RectTest, RectMakePointBounds) {
3250 std::vector<Point>
points{{1, 5}, {4, -1}, {0, 6}};
3253 EXPECT_TRUE(r.has_value());
3254 if (r.has_value()) {
3259 std::vector<Point>
points;
3261 EXPECT_FALSE(r.has_value());
3282 EXPECT_EQ(r.GetLeft(), 1);
3283 EXPECT_EQ(r.GetTop(), 2);
3284 EXPECT_EQ(r.GetRight(), 3);
3285 EXPECT_EQ(r.GetBottom(), 4);
3296 auto actual = r.Project(r);
3365 TEST(RectTest, TransformAndClipBoundsNoCornersClipped) {
3369 2.0f, 0.0f, 0.0f, 0.0f,
3370 0.0f, 4.0f, 0.0f, 0.0f,
3371 0.0f, 0.0f, 1.0f, 0.0f,
3372 0.0f, 0.0f, 0.0f, 8.0f
3379 EXPECT_EQ(matrix.TransformHomogenous(src.
GetLeftTop()),
3380 Vector3(200.0f, 400.0f, 8.0f));
3381 EXPECT_EQ(matrix.TransformHomogenous(src.
GetRightTop()),
3382 Vector3(400.0f, 400.0f, 8.0f));
3384 Vector3(200.0f, 800.0f, 8.0f));
3386 Vector3(400.0f, 800.0f, 8.0f));
3393 TEST(RectTest, TransformAndClipBoundsOneCornerClipped) {
3397 2.0f, 0.0f, 0.0f, -0.01f,
3398 0.0f, 2.0f, 0.0f, -0.006f,
3399 0.0f, 0.0f, 1.0f, 0.0f,
3400 0.0f, 0.0f, 0.0f, 3.0f
3412 Vector3(200.0f, 200.0f, 1.4f));
3416 Vector3(400.0f, 200.0f, 0.4f));
3420 Vector3(200.0f, 400.0f, 0.8f));
3424 Vector3(400.0f, 400.0f, -0.2f));
3450 TEST(RectTest, TransformAndClipBoundsTwoCornersClipped) {
3454 2.0f, 0.0f, 0.0f, -.015f,
3455 0.0f, 2.0f, 0.0f, -.006f,
3456 0.0f, 0.0f, 1.0f, 0.0f,
3457 0.0f, 0.0f, 0.0f, 3.0f
3469 Vector3(200.0f, 200.0f, 0.9f));
3473 Vector3(400.0f, 200.0f, -0.6f));
3483 Vector3(200.0f, 400.0f, 0.3f));
3487 Vector3(400.0f, 400.0f, -1.2f));
3508 TEST(RectTest, TransformAndClipBoundsThreeCornersClipped) {
3512 2.0f, 0.0f, 0.0f, -.02f,
3513 0.0f, 2.0f, 0.0f, -.006f,
3514 0.0f, 0.0f, 1.0f, 0.0f,
3515 0.0f, 0.0f, 0.0f, 3.0f
3527 Vector3(200.0f, 200.0f, 0.4f));
3531 Vector3(400.0f, 200.0f, -1.6f));
3541 Vector3(200.0f, 400.0f, -0.2f));
3551 Vector3(400.0f, 400.0f, -2.2f));
3567 TEST(RectTest, TransformAndClipBoundsAllFourCornersClipped) {
3571 2.0f, 0.0f, 0.0f, -.025f,
3572 0.0f, 2.0f, 0.0f, -.006f,
3573 0.0f, 0.0f, 1.0f, 0.0f,
3574 0.0f, 0.0f, 0.0f, 3.0f
3589 Vector3(200.0f, 200.0f, -0.1f));
3591 Vector3(400.0f, 200.0f, -2.6f));
3593 Vector3(200.0f, 400.0f, -0.7f));
3595 Vector3(400.0f, 400.0f, -3.2f));
inline ::testing::AssertionResult RectNear(impeller::Rect a, impeller::Rect b)
#define EXPECT_VECTOR3_NEAR(a, b)
#define EXPECT_RECT_NEAR(a, b)
#define EXPECT_POINT_NEAR(a, b)
TEST(AllocationSizeTest, CanCreateTypedAllocations)
static constexpr R flip_tb(R rect)
static constexpr Rect swap_nan(const Rect &rect, int index)
static constexpr R flip_lrtb(R rect)
static constexpr R flip_lr(R rect)
constexpr float kEhCloseEnough
std::array< Point, 4 > Quad
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeTranslation(const Vector3 &t)
static constexpr Matrix MakeColumn(Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
static constexpr Matrix MakeScale(const Vector3 &s)
constexpr auto GetBottom() const
constexpr Type GetY() const
Returns the Y coordinate of the upper left corner, equivalent to |GetOrigin().y|.
constexpr bool ContainsInclusive(const TPoint< Type > &p) const
Returns true iff the provided point |p| is inside the closed-range interior of this rectangle.
constexpr auto GetTop() const
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
constexpr TPoint< Type > GetOrigin() const
Returns the upper left corner of the rectangle as specified by the left/top or x/y values when it was...
constexpr std::optional< TRect< T > > ExpandToMinTransformedSize(TSize< T > min_transformed_size, const Matrix &transform) const
Returns a rectangle with edges expanded to satisfy a minimum size in a 2D-transformed coordinate spac...
constexpr std::optional< TRect > Intersection(const TRect &o) const
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
constexpr static TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
constexpr bool Contains(const TPoint< Type > &p) const
Returns true iff the provided point |p| is inside the half-open interior of this rectangle.
constexpr static TRect MakeCircleBounds(const TPoint< Type > ¢er, Type radius)
constexpr TRect Union(const TRect &o) const
constexpr std::array< TPoint< T >, 4 > GetPoints() const
Get the points that represent the 4 corners of this rectangle in a Z order that is compatible with tr...
constexpr bool IntersectsWithRect(const TRect &o) const
constexpr auto GetLeft() const
constexpr TRect CutoutOrEmpty(const TRect &o) const
constexpr static TRect MakeWH(Type width, Type height)
constexpr static std::optional< TRect > MakePointBounds(const U &value)
constexpr TSize< Type > GetSize() const
Returns the size of the rectangle which may be negative in either width or height and may have been c...
Round(const TRect< U > &r)
RoundOut(const TRect< U > &r)
constexpr TRect GetPositive() const
Get a version of this rectangle that has a non-negative size.
constexpr Type GetX() const
Returns the X coordinate of the upper left corner, equivalent to |GetOrigin().x|.
constexpr auto GetRight() const
IsFinite() const
Returns true if all of the fields of this floating point rectangle are finite.
constexpr TRect Scale(Type scale) const
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
constexpr TPoint< T > GetLeftBottom() const
constexpr std::array< TPoint< T >, 4 > GetTransformedPoints(const Matrix &transform) const
constexpr TRect TransformAndClipBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle, clipped against the near clippin...
constexpr TPoint< T > GetRightTop() const
constexpr static TRect MakeSize(const TSize< U > &size)
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
constexpr TPoint< T > GetRightBottom() const
constexpr static std::enable_if_t< std::is_floating_point_v< FT >, TRect > Make(const TRect< U > &rect)
constexpr TRect IntersectionOrEmpty(const TRect &o) const
constexpr std::optional< TRect< T > > Cutout(const TRect &o) const
Returns the new boundary rectangle that would result from this rectangle being cut out by the specifi...
constexpr TPoint< T > GetLeftTop() const
constexpr static TRect MakeEllipseBounds(const TPoint< Type > ¢er, const TSize< Type > &radii)
constexpr std::array< T, 4 > GetXYWH() const
Get the x, y coordinates of the origin and the width and height of the rectangle in an array.
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
constexpr static TRect MakeMaximum()
std::vector< Point > points