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, RectOverflowXYWH) {
179 auto min = std::numeric_limits<Scalar>::lowest();
180 auto max = std::numeric_limits<Scalar>::max();
181 auto inf = std::numeric_limits<Scalar>::infinity();
199 EXPECT_EQ(rect.
GetLeft(), 5.0f);
200 EXPECT_EQ(rect.
GetTop(), 10.0f);
203 EXPECT_EQ(rect.
GetX(), 5.0f);
204 EXPECT_EQ(rect.
GetY(), 10.0f);
214 EXPECT_EQ(rect.
GetLeft(), max);
215 EXPECT_EQ(rect.
GetTop(), 10.0f);
218 EXPECT_EQ(rect.
GetX(), max);
219 EXPECT_EQ(rect.
GetY(), 10.0f);
229 EXPECT_EQ(rect.
GetLeft(), 5.0f);
230 EXPECT_EQ(rect.
GetTop(), 10.0f);
233 EXPECT_EQ(rect.
GetX(), 5.0f);
234 EXPECT_EQ(rect.
GetY(), 10.0f);
244 EXPECT_EQ(rect.
GetLeft(), 5.0f);
245 EXPECT_EQ(rect.
GetTop(), max);
248 EXPECT_EQ(rect.
GetX(), 5.0f);
249 EXPECT_EQ(rect.
GetY(), max);
259 EXPECT_EQ(rect.
GetLeft(), 5.0f);
260 EXPECT_EQ(rect.
GetTop(), 10.0f);
263 EXPECT_EQ(rect.
GetX(), 5.0f);
264 EXPECT_EQ(rect.
GetY(), 10.0f);
274 EXPECT_EQ(rect.
GetLeft(), min);
275 EXPECT_EQ(rect.
GetTop(), 10.0f);
278 EXPECT_EQ(rect.
GetX(), min);
279 EXPECT_EQ(rect.
GetY(), 10.0f);
289 EXPECT_EQ(rect.
GetLeft(), 5.0f);
290 EXPECT_EQ(rect.
GetTop(), 10.0f);
293 EXPECT_EQ(rect.
GetX(), 5.0f);
294 EXPECT_EQ(rect.
GetY(), 10.0f);
304 EXPECT_EQ(rect.
GetLeft(), 5.0f);
305 EXPECT_EQ(rect.
GetTop(), min);
308 EXPECT_EQ(rect.
GetX(), 5.0f);
309 EXPECT_EQ(rect.
GetY(), min);
317 TEST(RectTest, IRectOverflowXYWH) {
318 auto min = std::numeric_limits<int64_t>::min();
319 auto max = std::numeric_limits<int64_t>::max();
330 EXPECT_EQ(rect.
GetLeft(), max - 5);
331 EXPECT_EQ(rect.
GetTop(), 10);
334 EXPECT_EQ(rect.
GetX(), max - 5);
335 EXPECT_EQ(rect.
GetY(), 10);
344 EXPECT_EQ(rect.
GetLeft(), min + 5);
345 EXPECT_EQ(rect.
GetTop(), 10);
348 EXPECT_EQ(rect.
GetX(), min + 5);
349 EXPECT_EQ(rect.
GetY(), 10);
359 EXPECT_EQ(rect.
GetTop(), max - 10);
362 EXPECT_EQ(rect.
GetX(), 5);
363 EXPECT_EQ(rect.
GetY(), max - 10);
373 EXPECT_EQ(rect.
GetTop(), min + 10);
376 EXPECT_EQ(rect.
GetX(), 5);
377 EXPECT_EQ(rect.
GetY(), min + 10);
384 TEST(RectTest, RectOverflowLTRB) {
385 auto min = std::numeric_limits<Scalar>::lowest();
386 auto max = std::numeric_limits<Scalar>::max();
387 auto inf = std::numeric_limits<Scalar>::infinity();
405 EXPECT_EQ(rect.
GetLeft(), -5.0f);
406 EXPECT_EQ(rect.
GetTop(), 10.0f);
409 EXPECT_EQ(rect.
GetX(), -5.0f);
410 EXPECT_EQ(rect.
GetY(), 10.0f);
420 EXPECT_EQ(rect.
GetLeft(), min + 5.0f);
421 EXPECT_EQ(rect.
GetTop(), 10.0f);
422 EXPECT_EQ(rect.
GetRight(), max - 5.0f);
424 EXPECT_EQ(rect.
GetX(), min + 5.0f);
425 EXPECT_EQ(rect.
GetY(), 10.0f);
435 EXPECT_EQ(rect.
GetLeft(), 5.0f);
436 EXPECT_EQ(rect.
GetTop(), -10.0f);
439 EXPECT_EQ(rect.
GetX(), 5.0f);
440 EXPECT_EQ(rect.
GetY(), -10.0f);
450 EXPECT_EQ(rect.
GetLeft(), 5.0f);
451 EXPECT_EQ(rect.
GetTop(), min + 10.0f);
453 EXPECT_EQ(rect.
GetBottom(), max - 15.0f);
454 EXPECT_EQ(rect.
GetX(), 5.0f);
455 EXPECT_EQ(rect.
GetY(), min + 10.0f);
465 EXPECT_EQ(rect.
GetLeft(), 5.0f);
466 EXPECT_EQ(rect.
GetTop(), 10.0f);
469 EXPECT_EQ(rect.
GetX(), 5.0f);
470 EXPECT_EQ(rect.
GetY(), 10.0f);
480 EXPECT_EQ(rect.
GetLeft(), max - 5.0f);
481 EXPECT_EQ(rect.
GetTop(), 10.0f);
482 EXPECT_EQ(rect.
GetRight(), min + 10.0f);
484 EXPECT_EQ(rect.
GetX(), max - 5.0f);
485 EXPECT_EQ(rect.
GetY(), 10.0f);
495 EXPECT_EQ(rect.
GetLeft(), 5.0f);
496 EXPECT_EQ(rect.
GetTop(), 10.0f);
499 EXPECT_EQ(rect.
GetX(), 5.0f);
500 EXPECT_EQ(rect.
GetY(), 10.0f);
510 EXPECT_EQ(rect.
GetLeft(), 5.0f);
511 EXPECT_EQ(rect.
GetTop(), max - 5.0f);
513 EXPECT_EQ(rect.
GetBottom(), min + 10.0f);
514 EXPECT_EQ(rect.
GetX(), 5.0f);
515 EXPECT_EQ(rect.
GetY(), max - 5.0f);
523 TEST(RectTest, IRectOverflowLTRB) {
524 auto min = std::numeric_limits<int64_t>::min();
525 auto max = std::numeric_limits<int64_t>::max();
536 EXPECT_EQ(rect.
GetLeft(), -10);
537 EXPECT_EQ(rect.
GetTop(), 10);
538 EXPECT_EQ(rect.
GetRight(), max - 5);
540 EXPECT_EQ(rect.
GetX(), -10);
541 EXPECT_EQ(rect.
GetY(), 10);
551 EXPECT_EQ(rect.
GetTop(), 10);
552 EXPECT_EQ(rect.
GetRight(), min + 5);
554 EXPECT_EQ(rect.
GetX(), 10);
555 EXPECT_EQ(rect.
GetY(), 10);
565 EXPECT_EQ(rect.
GetTop(), -10);
568 EXPECT_EQ(rect.
GetX(), 5);
569 EXPECT_EQ(rect.
GetY(), -10);
579 EXPECT_EQ(rect.
GetTop(), 10);
582 EXPECT_EQ(rect.
GetX(), 5);
583 EXPECT_EQ(rect.
GetY(), 10);
609 EXPECT_EQ(r, expected);
616 EXPECT_EQ(r, expected);
620 TEST(RectTest, RectMakeMaximum) {
622 auto inf = std::numeric_limits<Scalar>::infinity();
623 auto min = std::numeric_limits<Scalar>::lowest();
624 auto max = std::numeric_limits<Scalar>::max();
626 EXPECT_EQ(rect.
GetLeft(), min);
627 EXPECT_EQ(rect.
GetTop(), min);
630 EXPECT_EQ(rect.
GetX(), min);
631 EXPECT_EQ(rect.
GetY(), min);
638 TEST(RectTest, IRectMakeMaximum) {
640 auto min = std::numeric_limits<int64_t>::min();
641 auto max = std::numeric_limits<int64_t>::max();
643 EXPECT_EQ(rect.
GetLeft(), min);
644 EXPECT_EQ(rect.
GetTop(), min);
647 EXPECT_EQ(rect.
GetX(), min);
648 EXPECT_EQ(rect.
GetY(), min);
661 TEST(RectTest, IRectFromIRect) {
673 EXPECT_EQ(rect, copy);
674 EXPECT_EQ(copy.
GetLeft(), 5.125f);
675 EXPECT_EQ(copy.
GetTop(), 10.25f);
676 EXPECT_EQ(copy.
GetRight(), 20.625f);
678 EXPECT_EQ(copy.
GetX(), 5.125f);
679 EXPECT_EQ(copy.
GetY(), 10.25f);
690 EXPECT_EQ(rect, copy);
692 EXPECT_EQ(copy.
GetTop(), 10);
695 EXPECT_EQ(copy.
GetX(), 5);
696 EXPECT_EQ(copy.
GetY(), 10);
702 TEST(RectTest, RectOriginSizeXYWHGetters) {
707 EXPECT_EQ(r.
GetX(), 10);
708 EXPECT_EQ(r.
GetY(), 20);
711 auto expected_array = std::array<Scalar, 4>{10, 20, 50, 40};
712 EXPECT_EQ(r.
GetXYWH(), expected_array);
719 EXPECT_EQ(r.
GetX(), 10);
720 EXPECT_EQ(r.
GetY(), 20);
723 auto expected_array = std::array<Scalar, 4>{10, 20, 40, 20};
724 EXPECT_EQ(r.
GetXYWH(), expected_array);
728 TEST(RectTest, IRectOriginSizeXYWHGetters) {
733 EXPECT_EQ(r.
GetX(), 10);
734 EXPECT_EQ(r.
GetY(), 20);
737 auto expected_array = std::array<int64_t, 4>{10, 20, 50, 40};
738 EXPECT_EQ(r.
GetXYWH(), expected_array);
745 EXPECT_EQ(r.
GetX(), 10);
746 EXPECT_EQ(r.
GetY(), 20);
749 auto expected_array = std::array<int64_t, 4>{10, 20, 40, 20};
750 EXPECT_EQ(r.
GetXYWH(), expected_array);
754 TEST(RectTest, RectRoundOutEmpty) {
762 TEST(RectTest, RectRoundOutSimple) {
770 TEST(RectTest, RectRoundOutToIRectHuge) {
771 auto test = [](
int corners) {
772 EXPECT_TRUE(corners >= 0 && corners <= 0xf);
774 int64_t il, it, ir, ib;
779 if ((corners & (1 << 0)) != 0) {
781 il = std::numeric_limits<int64_t>::min();
783 if ((corners & (1 << 1)) != 0) {
785 it = std::numeric_limits<int64_t>::min();
787 if ((corners & (1 << 2)) != 0) {
789 ir = std::numeric_limits<int64_t>::max();
791 if ((corners & (1 << 3)) != 0) {
793 ib = std::numeric_limits<int64_t>::max();
798 EXPECT_EQ(irect.
GetLeft(), il) << corners;
799 EXPECT_EQ(irect.
GetTop(), it) << corners;
800 EXPECT_EQ(irect.
GetRight(), ir) << corners;
801 EXPECT_EQ(irect.
GetBottom(), ib) << corners;
804 for (
int corners = 0; corners <= 15; corners++) {
809 TEST(RectTest, RectDoesNotIntersectEmpty) {
813 const std::string& label) {
815 << label <<
" with Top/Bottom swapped";
817 << label <<
" with Left/Right swapped";
819 << label <<
" with all sides swapped";
822 test(20, 20, 30, 30,
"Above and Left");
823 test(70, 20, 80, 30,
"Above");
824 test(120, 20, 130, 30,
"Above and Right");
825 test(120, 70, 130, 80,
"Right");
826 test(120, 120, 130, 130,
"Below and Right");
827 test(70, 120, 80, 130,
"Below");
828 test(20, 120, 30, 130,
"Below and Left");
829 test(20, 70, 30, 80,
"Left");
831 test(70, 70, 80, 80,
"Inside");
833 test(40, 70, 60, 80,
"Straddling Left");
834 test(70, 40, 80, 60,
"Straddling Top");
835 test(90, 70, 110, 80,
"Straddling Right");
836 test(70, 90, 80, 110,
"Straddling Bottom");
839 TEST(RectTest, IRectDoesNotIntersectEmpty) {
842 auto test = [&rect](int64_t l, int64_t t, int64_t r, int64_t
b,
843 const std::string& label) {
845 << label <<
" with Top/Bottom swapped";
847 << label <<
" with Left/Right swapped";
849 << label <<
" with all sides swapped";
852 test(20, 20, 30, 30,
"Above and Left");
853 test(70, 20, 80, 30,
"Above");
854 test(120, 20, 130, 30,
"Above and Right");
855 test(120, 70, 130, 80,
"Right");
856 test(120, 120, 130, 130,
"Below and Right");
857 test(70, 120, 80, 130,
"Below");
858 test(20, 120, 30, 130,
"Below and Left");
859 test(20, 70, 30, 80,
"Left");
861 test(70, 70, 80, 80,
"Inside");
863 test(40, 70, 60, 80,
"Straddling Left");
864 test(70, 40, 80, 60,
"Straddling Top");
865 test(90, 70, 110, 80,
"Straddling Right");
866 test(70, 90, 80, 110,
"Straddling Bottom");
869 TEST(RectTest, EmptyRectDoesNotIntersect) {
873 const std::string& label) {
875 << label <<
" with Top/Bottom swapped";
877 << label <<
" with Left/Right swapped";
879 << label <<
" with all sides swapped";
882 test(20, 20, 30, 30,
"Above and Left");
883 test(70, 20, 80, 30,
"Above");
884 test(120, 20, 130, 30,
"Above and Right");
885 test(120, 70, 130, 80,
"Right");
886 test(120, 120, 130, 130,
"Below and Right");
887 test(70, 120, 80, 130,
"Below");
888 test(20, 120, 30, 130,
"Below and Left");
889 test(20, 70, 30, 80,
"Left");
891 test(70, 70, 80, 80,
"Inside");
893 test(40, 70, 60, 80,
"Straddling Left");
894 test(70, 40, 80, 60,
"Straddling Top");
895 test(90, 70, 110, 80,
"Straddling Right");
896 test(70, 90, 80, 110,
"Straddling Bottom");
899 TEST(RectTest, EmptyIRectDoesNotIntersect) {
902 auto test = [&rect](int64_t l, int64_t t, int64_t r, int64_t
b,
903 const std::string& label) {
905 << label <<
" with Top/Bottom swapped";
907 << label <<
" with Left/Right swapped";
909 << label <<
" with all sides swapped";
912 test(20, 20, 30, 30,
"Above and Left");
913 test(70, 20, 80, 30,
"Above");
914 test(120, 20, 130, 30,
"Above and Right");
915 test(120, 70, 130, 80,
"Right");
916 test(120, 120, 130, 130,
"Below and Right");
917 test(70, 120, 80, 130,
"Below");
918 test(20, 120, 30, 130,
"Below and Left");
919 test(20, 70, 30, 80,
"Left");
921 test(70, 70, 80, 80,
"Inside");
923 test(40, 70, 60, 80,
"Straddling Left");
924 test(70, 40, 80, 60,
"Straddling Top");
925 test(90, 70, 110, 80,
"Straddling Right");
926 test(70, 90, 80, 110,
"Straddling Bottom");
937 << rect <<
" * " << scale;
939 << rect <<
" * " << scale;
941 << rect <<
" * " << scale;
943 << rect <<
" * " << scale;
948 rect.
GetY() * scale_y,
953 << rect <<
" * " << scale_x <<
", " << scale_y;
955 << rect <<
" * " << scale_x <<
", " << scale_y;
957 << rect <<
" * " << scale_x <<
", " << scale_y;
959 test1(rect, scale_x);
960 test1(rect, scale_y);
975 auto test1 = [](
IRect rect, int64_t scale) {
981 EXPECT_EQ(rect.
Scale(scale), expected)
982 << rect <<
" * " << scale;
983 EXPECT_EQ(rect.
Scale(scale, scale), expected)
984 << rect <<
" * " << scale;
985 EXPECT_EQ(rect.
Scale(
IPoint(scale, scale)), expected)
986 << rect <<
" * " << scale;
987 EXPECT_EQ(rect.
Scale(
ISize(scale, scale)), expected)
988 << rect <<
" * " << scale;
991 auto test2 = [&test1](
IRect rect, int64_t scale_x, int64_t scale_y) {
993 rect.
GetY() * scale_y,
997 EXPECT_EQ(rect.
Scale(scale_x, scale_y), expected)
998 << rect <<
" * " << scale_x <<
", " << scale_y;
999 EXPECT_EQ(rect.
Scale(
IPoint(scale_x, scale_y)), expected)
1000 << rect <<
" * " << scale_x <<
", " << scale_y;
1001 EXPECT_EQ(rect.
Scale(
ISize(scale_x, scale_y)), expected)
1002 << rect <<
" * " << scale_x <<
", " << scale_y;
1004 test1(rect, scale_x);
1005 test1(rect, scale_y);
1034 TEST(RectTest, RectGetNormalizingTransform) {
1040 EXPECT_EQ(r.GetNormalizingTransform(),
1049 auto m = r.GetNormalizingTransform();
1058 EXPECT_EQ(m *
Point(350, 600),
Point(0.5, 0.5));
1061 EXPECT_EQ(m *
Point(200, 300),
Point(-1, -1));
1062 EXPECT_EQ(m *
Point(500, 300),
Point(2, -1));
1064 EXPECT_EQ(m *
Point(200, 900),
Point(-1, 2));
1073 EXPECT_EQ(
Rect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
1074 EXPECT_EQ(
Rect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
1075 EXPECT_EQ(
Rect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
1078 EXPECT_EQ(
Rect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
1079 EXPECT_EQ(
Rect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
1080 EXPECT_EQ(
Rect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
1087 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
1088 auto inf = std::numeric_limits<Scalar>::infinity();
1091 EXPECT_EQ(
Rect::MakeXYWH(10, 10, nan, 10).GetNormalizingTransform(), z);
1092 EXPECT_EQ(
Rect::MakeXYWH(10, 10, 10, nan).GetNormalizingTransform(), z);
1093 EXPECT_EQ(
Rect::MakeXYWH(10, 10, nan, nan).GetNormalizingTransform(), z);
1096 EXPECT_EQ(
Rect::MakeXYWH(10, 10, inf, 10).GetNormalizingTransform(), z);
1097 EXPECT_EQ(
Rect::MakeXYWH(10, 10, 10, inf).GetNormalizingTransform(), z);
1098 EXPECT_EQ(
Rect::MakeXYWH(10, 10, inf, inf).GetNormalizingTransform(), z);
1101 EXPECT_EQ(
Rect::MakeXYWH(10, 10, -inf, 10).GetNormalizingTransform(), z);
1102 EXPECT_EQ(
Rect::MakeXYWH(10, 10, 10, -inf).GetNormalizingTransform(), z);
1103 EXPECT_EQ(
Rect::MakeXYWH(10, 10, -inf, -inf).GetNormalizingTransform(), z);
1106 EXPECT_EQ(
Rect::MakeXYWH(nan, 10, 10, 10).GetNormalizingTransform(), z);
1107 EXPECT_EQ(
Rect::MakeXYWH(10, nan, 10, 10).GetNormalizingTransform(), z);
1108 EXPECT_EQ(
Rect::MakeXYWH(nan, nan, 10, 10).GetNormalizingTransform(), z);
1111 EXPECT_EQ(
Rect::MakeXYWH(inf, 10, 10, 10).GetNormalizingTransform(), z);
1112 EXPECT_EQ(
Rect::MakeXYWH(10, inf, 10, 10).GetNormalizingTransform(), z);
1113 EXPECT_EQ(
Rect::MakeXYWH(inf, inf, 10, 10).GetNormalizingTransform(), z);
1116 EXPECT_EQ(
Rect::MakeXYWH(-inf, 10, 10, 10).GetNormalizingTransform(), z);
1117 EXPECT_EQ(
Rect::MakeXYWH(10, -inf, 10, 10).GetNormalizingTransform(), z);
1118 EXPECT_EQ(
Rect::MakeXYWH(-inf, -inf, 10, 10).GetNormalizingTransform(), z);
1122 TEST(RectTest, IRectGetNormalizingTransform) {
1128 EXPECT_EQ(r.GetNormalizingTransform(),
1137 auto m = r.GetNormalizingTransform();
1146 EXPECT_EQ(m *
Point(350, 600),
Point(0.5, 0.5));
1149 EXPECT_EQ(m *
Point(200, 300),
Point(-1, -1));
1150 EXPECT_EQ(m *
Point(500, 300),
Point(2, -1));
1152 EXPECT_EQ(m *
Point(200, 900),
Point(-1, 2));
1161 EXPECT_EQ(
IRect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
1162 EXPECT_EQ(
IRect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
1163 EXPECT_EQ(
IRect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
1166 EXPECT_EQ(
IRect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
1167 EXPECT_EQ(
IRect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
1168 EXPECT_EQ(
IRect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
1173 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
1213 TEST(RectTest, MakePointBoundsQuad) {
1221 EXPECT_TRUE(bounds.has_value());
1222 if (bounds.has_value()) {
1258 EXPECT_EQ(rect.Expand(10, 10),
Rect::MakeLTRB(90, 90, 210, 210));
1259 EXPECT_EQ(rect.Expand(10, -10),
Rect::MakeLTRB(90, 110, 210, 190));
1260 EXPECT_EQ(rect.Expand(-10, 10),
Rect::MakeLTRB(110, 90, 190, 210));
1261 EXPECT_EQ(rect.Expand(-10, -10),
Rect::MakeLTRB(110, 110, 190, 190));
1264 EXPECT_EQ(rect.Expand(10, 20, 30, 40),
Rect::MakeLTRB(90, 80, 230, 240));
1265 EXPECT_EQ(rect.Expand(-10, 20, 30, 40),
Rect::MakeLTRB(110, 80, 230, 240));
1266 EXPECT_EQ(rect.Expand(10, -20, 30, 40),
Rect::MakeLTRB(90, 120, 230, 240));
1267 EXPECT_EQ(rect.Expand(10, 20, -30, 40),
Rect::MakeLTRB(90, 80, 170, 240));
1268 EXPECT_EQ(rect.Expand(10, 20, 30, -40),
Rect::MakeLTRB(90, 80, 230, 160));
1294 EXPECT_EQ(rect.Expand(-10, -10),
IRect::MakeLTRB(110, 110, 190, 190));
1297 EXPECT_EQ(rect.Expand(10, 20, 30, 40),
IRect::MakeLTRB(90, 80, 230, 240));
1298 EXPECT_EQ(rect.Expand(-10, 20, 30, 40),
IRect::MakeLTRB(110, 80, 230, 240));
1299 EXPECT_EQ(rect.Expand(10, -20, 30, 40),
IRect::MakeLTRB(90, 120, 230, 240));
1300 EXPECT_EQ(rect.Expand(10, 20, -30, 40),
IRect::MakeLTRB(90, 80, 170, 240));
1301 EXPECT_EQ(rect.Expand(10, 20, 30, -40),
IRect::MakeLTRB(90, 80, 230, 160));
1316 TEST(RectTest, ContainsFloatingPoint) {
1318 Rect::MakeXYWH(472.599945f, 440.999969f, 1102.80005f, 654.000061f);
1320 EXPECT_TRUE(rect1.Contains(rect2));
1323 template <
typename R>
1325 return R::MakeLTRB(rect.GetRight(), rect.GetTop(),
1326 rect.GetLeft(), rect.GetBottom());
1329 template <
typename R>
1331 return R::MakeLTRB(rect.GetLeft(), rect.GetBottom(),
1332 rect.GetRight(), rect.GetTop());
1335 template <
typename R>
1341 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1342 FML_DCHECK(index >= 0 && index <= 15);
1343 Scalar l = ((index & (1 << 0)) != 0) ? nan : rect.
GetLeft();
1344 Scalar t = ((index & (1 << 1)) != 0) ? nan : rect.
GetTop();
1351 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1352 FML_DCHECK(index >= 0 && index <= 3);
1353 Scalar x = ((index & (1 << 0)) != 0) ? nan : point.
x;
1354 Scalar y = ((index & (1 << 1)) != 0) ? nan : point.
y;
1359 auto check_nans = [](
const Rect& a,
const Rect&
b,
const std::string& label) {
1360 ASSERT_TRUE(a.
IsFinite()) << label;
1361 ASSERT_TRUE(
b.IsFinite()) << label;
1364 for (
int i = 1; i < 16; i++) {
1366 EXPECT_EQ(
swap_nan(a, i).Union(
b),
b) << label <<
", index = " << i;
1368 EXPECT_EQ(a.
Union(
swap_nan(
b, i)), a) << label <<
", index = " << i;
1370 for (
int j = 1; j < 16; j++) {
1372 << label <<
", indices = " << i <<
", " << j;
1377 auto check_empty_flips = [](
const Rect& a,
const Rect&
b,
1378 const std::string& label) {
1388 EXPECT_EQ(
flip_lr(a).Union(
b),
b) << label;
1389 EXPECT_EQ(
flip_tb(a).Union(
b),
b) << label;
1398 auto test = [&check_nans, &check_empty_flips](
const Rect& a,
const Rect&
b,
1399 const Rect& result) {
1400 ASSERT_FALSE(a.
IsEmpty()) << a;
1403 std::stringstream stream;
1404 stream << a <<
" union " <<
b;
1405 auto label = stream.str();
1407 EXPECT_EQ(a.
Union(
b), result) << label;
1408 EXPECT_EQ(
b.Union(a), result) << label;
1409 check_empty_flips(a,
b, label);
1410 check_nans(a,
b, label);
1417 test(a,
b, expected);
1424 test(a,
b, expected);
1431 test(a,
b, expected);
1438 test(a,
b, expected);
1445 test(a,
b, expected);
1455 EXPECT_FALSE(
Rect::Union(std::nullopt, std::nullopt).has_value());
1456 EXPECT_EQ(
Rect::Union(std::nullopt, std::nullopt), std::nullopt);
1458 auto test1 = [](
const Rect& r) {
1463 EXPECT_TRUE(
Rect::Union(std::optional(r), std::nullopt).has_value());
1470 EXPECT_TRUE(
Rect::Union(std::nullopt, std::optional(r)).has_value());
1478 auto test2 = [](
const Rect& a,
const Rect&
b,
const Rect& u) {
1479 ASSERT_EQ(a.
Union(
b), u);
1488 EXPECT_TRUE(
Rect::Union(std::optional(a), std::optional(
b)).has_value());
1498 auto check_empty_flips = [](
const IRect& a,
const IRect&
b,
1499 const std::string& label) {
1509 EXPECT_EQ(
flip_lr(a).Union(
b),
b) << label;
1510 EXPECT_EQ(
flip_tb(a).Union(
b),
b) << label;
1519 auto test = [&check_empty_flips](
const IRect& a,
const IRect&
b,
1520 const IRect& result) {
1521 ASSERT_FALSE(a.
IsEmpty()) << a;
1524 std::stringstream stream;
1525 stream << a <<
" union " <<
b;
1526 auto label = stream.str();
1528 EXPECT_EQ(a.
Union(
b), result) << label;
1529 EXPECT_EQ(
b.Union(a), result) << label;
1530 check_empty_flips(a,
b, label);
1537 test(a,
b, expected);
1544 test(a,
b, expected);
1551 test(a,
b, expected);
1558 test(a,
b, expected);
1565 test(a,
b, expected);
1575 EXPECT_FALSE(
IRect::Union(std::nullopt, std::nullopt).has_value());
1576 EXPECT_EQ(
IRect::Union(std::nullopt, std::nullopt), std::nullopt);
1578 auto test1 = [](
const IRect& r) {
1583 EXPECT_TRUE(
IRect::Union(std::optional(r), std::nullopt).has_value());
1590 EXPECT_TRUE(
IRect::Union(std::nullopt, std::optional(r)).has_value());
1599 ASSERT_EQ(a.
Union(
b), u);
1608 EXPECT_TRUE(
IRect::Union(std::optional(a), std::optional(
b)).has_value());
1618 auto check_nans = [](
const Rect& a,
const Rect&
b,
const std::string& label) {
1619 ASSERT_TRUE(a.
IsFinite()) << label;
1620 ASSERT_TRUE(
b.IsFinite()) << label;
1622 for (
int i = 1; i < 16; i++) {
1624 EXPECT_FALSE(
swap_nan(a, i).Intersection(
b).has_value())
1625 << label <<
", index = " << i;
1628 << label <<
", index = " << i;
1630 for (
int j = 1; j < 16; j++) {
1632 << label <<
", indices = " << i <<
", " << j;
1637 auto check_empty_flips = [](
const Rect& a,
const Rect&
b,
1638 const std::string& label) {
1651 EXPECT_FALSE(
flip_lr(a).Intersection(
b).has_value()) << label;
1652 EXPECT_TRUE(
flip_lr(a).IntersectionOrEmpty(
b).IsEmpty()) << label;
1653 EXPECT_FALSE(
flip_tb(a).Intersection(
b).has_value()) << label;
1654 EXPECT_TRUE(
flip_tb(a).IntersectionOrEmpty(
b).IsEmpty()) << label;
1655 EXPECT_FALSE(
flip_lrtb(a).Intersection(
b).has_value()) << label;
1656 EXPECT_TRUE(
flip_lrtb(a).IntersectionOrEmpty(
b).IsEmpty()) << label;
1659 EXPECT_FALSE(
flip_lr(a).Intersection(
flip_lr(
b)).has_value()) << label;
1660 EXPECT_TRUE(
flip_lr(a).IntersectionOrEmpty(
flip_lr(
b)).IsEmpty()) << label;
1661 EXPECT_FALSE(
flip_tb(a).Intersection(
flip_tb(
b)).has_value()) << label;
1662 EXPECT_TRUE(
flip_tb(a).IntersectionOrEmpty(
flip_tb(
b)).IsEmpty()) << label;
1668 auto test_non_empty = [&check_nans, &check_empty_flips](
1670 ASSERT_FALSE(a.
IsEmpty()) << a;
1673 std::stringstream stream;
1674 stream << a <<
" union " <<
b;
1675 auto label = stream.str();
1678 EXPECT_TRUE(
b.Intersection(a).has_value()) << label;
1680 EXPECT_EQ(
b.Intersection(a), result) << label;
1681 check_empty_flips(a,
b, label);
1682 check_nans(a,
b, label);
1685 auto test_empty = [&check_nans, &check_empty_flips](
const Rect& a,
1687 ASSERT_FALSE(a.
IsEmpty()) << a;
1690 std::stringstream stream;
1691 stream << a <<
" union " <<
b;
1692 auto label = stream.str();
1696 EXPECT_FALSE(
b.Intersection(a).has_value()) << label;
1697 EXPECT_TRUE(
b.IntersectionOrEmpty(a).IsEmpty()) << label;
1698 check_empty_flips(a,
b, label);
1699 check_nans(a,
b, label);
1721 test_non_empty(a,
b, expected);
1735 test_non_empty(a,
b,
b);
1746 TEST(RectTest, OptRectIntersection) {
1755 auto test1 = [](
const Rect& r) {
1777 auto test2 = [](
const Rect& a,
const Rect&
b,
const Rect& i) {
1800 TEST(RectTest, IRectIntersection) {
1801 auto check_empty_flips = [](
const IRect& a,
const IRect&
b,
1802 const std::string& label) {
1812 EXPECT_FALSE(
flip_lr(a).Intersection(
b).has_value()) << label;
1813 EXPECT_FALSE(
flip_tb(a).Intersection(
b).has_value()) << label;
1814 EXPECT_FALSE(
flip_lrtb(a).Intersection(
b).has_value()) << label;
1817 EXPECT_FALSE(
flip_lr(a).Intersection(
flip_lr(
b)).has_value()) << label;
1818 EXPECT_FALSE(
flip_tb(a).Intersection(
flip_tb(
b)).has_value()) << label;
1822 auto test_non_empty = [&check_empty_flips](
const IRect& a,
const IRect&
b,
1823 const IRect& result) {
1824 ASSERT_FALSE(a.
IsEmpty()) << a;
1827 std::stringstream stream;
1828 stream << a <<
" union " <<
b;
1829 auto label = stream.str();
1832 EXPECT_TRUE(
b.Intersection(a).has_value()) << label;
1834 EXPECT_EQ(
b.Intersection(a), result) << label;
1835 check_empty_flips(a,
b, label);
1838 auto test_empty = [&check_empty_flips](
const IRect& a,
const IRect&
b) {
1839 ASSERT_FALSE(a.
IsEmpty()) << a;
1842 std::stringstream stream;
1843 stream << a <<
" union " <<
b;
1844 auto label = stream.str();
1847 EXPECT_FALSE(
b.Intersection(a).has_value()) << label;
1848 check_empty_flips(a,
b, label);
1870 test_non_empty(a,
b, expected);
1884 test_non_empty(a,
b,
b);
1895 TEST(RectTest, OptIRectIntersection) {
1904 auto test1 = [](
const IRect& r) {
1951 TEST(RectTest, RectIntersectsWithRect) {
1952 auto check_nans = [](
const Rect& a,
const Rect&
b,
const std::string& label) {
1953 ASSERT_TRUE(a.
IsFinite()) << label;
1954 ASSERT_TRUE(
b.IsFinite()) << label;
1956 for (
int i = 1; i < 16; i++) {
1958 EXPECT_FALSE(
swap_nan(a, i).IntersectsWithRect(
b))
1959 << label <<
", index = " << i;
1962 << label <<
", index = " << i;
1964 for (
int j = 1; j < 16; j++) {
1966 << label <<
", indices = " << i <<
", " << j;
1971 auto check_empty_flips = [](
const Rect& a,
const Rect&
b,
1972 const std::string& label) {
1982 EXPECT_FALSE(
flip_lr(a).IntersectsWithRect(
b)) << label;
1983 EXPECT_FALSE(
flip_tb(a).IntersectsWithRect(
b)) << label;
1984 EXPECT_FALSE(
flip_lrtb(a).IntersectsWithRect(
b)) << label;
1992 auto test_non_empty = [&check_nans, &check_empty_flips](
const Rect& a,
1994 ASSERT_FALSE(a.
IsEmpty()) << a;
1997 std::stringstream stream;
1998 stream << a <<
" union " <<
b;
1999 auto label = stream.str();
2002 EXPECT_TRUE(
b.IntersectsWithRect(a)) << label;
2003 check_empty_flips(a,
b, label);
2004 check_nans(a,
b, label);
2007 auto test_empty = [&check_nans, &check_empty_flips](
const Rect& a,
2009 ASSERT_FALSE(a.
IsEmpty()) << a;
2012 std::stringstream stream;
2013 stream << a <<
" union " <<
b;
2014 auto label = stream.str();
2017 EXPECT_FALSE(
b.IntersectsWithRect(a)) << label;
2018 check_empty_flips(a,
b, label);
2019 check_nans(a,
b, label);
2040 test_non_empty(a,
b);
2054 test_non_empty(a,
b);
2061 test_non_empty(a,
b);
2065 TEST(RectTest, IRectIntersectsWithRect) {
2066 auto check_empty_flips = [](
const IRect& a,
const IRect&
b,
2067 const std::string& label) {
2077 EXPECT_FALSE(
flip_lr(a).IntersectsWithRect(
b)) << label;
2078 EXPECT_FALSE(
flip_tb(a).IntersectsWithRect(
b)) << label;
2079 EXPECT_FALSE(
flip_lrtb(a).IntersectsWithRect(
b)) << label;
2087 auto test_non_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_TRUE(
b.IntersectsWithRect(a)) << label;
2097 check_empty_flips(a,
b, label);
2100 auto test_empty = [&check_empty_flips](
const IRect& a,
const IRect&
b) {
2101 ASSERT_FALSE(a.
IsEmpty()) << a;
2104 std::stringstream stream;
2105 stream << a <<
" union " <<
b;
2106 auto label = stream.str();
2109 EXPECT_FALSE(
b.IntersectsWithRect(a)) << label;
2110 check_empty_flips(a,
b, label);
2131 test_non_empty(a,
b);
2145 test_non_empty(a,
b);
2152 test_non_empty(a,
b);
2156 TEST(RectTest, RectContainsPoint) {
2157 auto check_nans = [](
const Rect& rect,
const Point& point,
2158 const std::string& label) {
2159 ASSERT_TRUE(rect.
IsFinite()) << label;
2160 ASSERT_TRUE(point.IsFinite()) << label;
2162 for (
int i = 1; i < 16; i++) {
2163 EXPECT_FALSE(
swap_nan(rect, i).Contains(point))
2164 << label <<
", index = " << i;
2165 for (
int j = 1; j < 4; j++) {
2167 << label <<
", indices = " << i <<
", " << j;
2172 auto check_empty_flips = [](
const Rect& rect,
const Point& point,
2173 const std::string& label) {
2176 EXPECT_FALSE(
flip_lr(rect).Contains(point)) << label;
2177 EXPECT_FALSE(
flip_tb(rect).Contains(point)) << label;
2178 EXPECT_FALSE(
flip_lrtb(rect).Contains(point)) << label;
2181 auto test_inside = [&check_nans, &check_empty_flips](
const Rect& rect,
2182 const Point& point) {
2183 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2185 std::stringstream stream;
2186 stream << rect <<
" contains " << point;
2187 auto label = stream.str();
2189 EXPECT_TRUE(rect.
Contains(point)) << label;
2190 check_empty_flips(rect, point, label);
2191 check_nans(rect, point, label);
2194 auto test_outside = [&check_nans, &check_empty_flips](
const Rect& rect,
2195 const Point& point) {
2196 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2198 std::stringstream stream;
2199 stream << rect <<
" contains " << point;
2200 auto label = stream.str();
2202 EXPECT_FALSE(rect.
Contains(point)) << label;
2203 check_empty_flips(rect, point, label);
2204 check_nans(rect, point, label);
2210 auto p =
Point(100, 100);
2217 auto p =
Point(200, 200);
2223 auto p =
Point(99, 99);
2229 auto p =
Point(199, 199);
2236 auto p =
Point(199, 199);
2242 TEST(RectTest, IRectContainsIPoint) {
2243 auto check_empty_flips = [](
const IRect& rect,
const IPoint& point,
2244 const std::string& label) {
2247 EXPECT_FALSE(
flip_lr(rect).Contains(point)) << label;
2248 EXPECT_FALSE(
flip_tb(rect).Contains(point)) << label;
2249 EXPECT_FALSE(
flip_lrtb(rect).Contains(point)) << label;
2252 auto test_inside = [&check_empty_flips](
const IRect& rect,
2254 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2256 std::stringstream stream;
2257 stream << rect <<
" contains " << point;
2258 auto label = stream.str();
2260 EXPECT_TRUE(rect.
Contains(point)) << label;
2261 check_empty_flips(rect, point, label);
2264 auto test_outside = [&check_empty_flips](
const IRect& rect,
2266 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2268 std::stringstream stream;
2269 stream << rect <<
" contains " << point;
2270 auto label = stream.str();
2272 EXPECT_FALSE(rect.
Contains(point)) << label;
2273 check_empty_flips(rect, point, label);
2279 auto p =
IPoint(100, 100);
2286 auto p =
IPoint(200, 200);
2298 auto p =
IPoint(199, 199);
2305 auto p =
IPoint(199, 199);
2311 TEST(RectTest, RectContainsInclusivePoint) {
2312 auto check_nans = [](
const Rect& rect,
const Point& point,
2313 const std::string& label) {
2314 ASSERT_TRUE(rect.
IsFinite()) << label;
2315 ASSERT_TRUE(point.IsFinite()) << label;
2317 for (
int i = 1; i < 16; i++) {
2318 EXPECT_FALSE(
swap_nan(rect, i).ContainsInclusive(point))
2319 << label <<
", index = " << i;
2320 for (
int j = 1; j < 4; j++) {
2322 << label <<
", indices = " << i <<
", " << j;
2327 auto check_empty_flips = [](
const Rect& rect,
const Point& point,
2328 const std::string& label) {
2331 EXPECT_FALSE(
flip_lr(rect).ContainsInclusive(point)) << label;
2332 EXPECT_FALSE(
flip_tb(rect).ContainsInclusive(point)) << label;
2333 EXPECT_FALSE(
flip_lrtb(rect).ContainsInclusive(point)) << label;
2336 auto test_inside = [&check_nans, &check_empty_flips](
const Rect& rect,
2337 const Point& point) {
2338 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2340 std::stringstream stream;
2341 stream << rect <<
" contains " << point;
2342 auto label = stream.str();
2345 check_empty_flips(rect, point, label);
2346 check_nans(rect, point, label);
2349 auto test_outside = [&check_nans, &check_empty_flips](
const Rect& rect,
2350 const Point& point) {
2351 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2353 std::stringstream stream;
2354 stream << rect <<
" contains " << point;
2355 auto label = stream.str();
2358 check_empty_flips(rect, point, label);
2359 check_nans(rect, point, label);
2365 auto p =
Point(100, 100);
2372 auto p =
Point(200, 200);
2385 auto p =
Point(99, 99);
2391 auto p =
Point(199, 199);
2398 auto p =
Point(199, 199);
2404 TEST(RectTest, IRectContainsInclusiveIPoint) {
2405 auto check_empty_flips = [](
const IRect& rect,
const IPoint& point,
2406 const std::string& label) {
2409 EXPECT_FALSE(
flip_lr(rect).ContainsInclusive(point)) << label;
2410 EXPECT_FALSE(
flip_tb(rect).ContainsInclusive(point)) << label;
2411 EXPECT_FALSE(
flip_lrtb(rect).ContainsInclusive(point)) << label;
2414 auto test_inside = [&check_empty_flips](
const IRect& rect,
2416 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2418 std::stringstream stream;
2419 stream << rect <<
" contains " << point;
2420 auto label = stream.str();
2423 check_empty_flips(rect, point, label);
2426 auto test_outside = [&check_empty_flips](
const IRect& rect,
2428 ASSERT_FALSE(rect.
IsEmpty()) << rect;
2430 std::stringstream stream;
2431 stream << rect <<
" contains " << point;
2432 auto label = stream.str();
2435 check_empty_flips(rect, point, label);
2441 auto p =
IPoint(100, 100);
2448 auto p =
IPoint(200, 200);
2455 auto p =
IPoint(201, 201);
2467 auto p =
IPoint(199, 199);
2474 auto p =
IPoint(199, 199);
2481 auto check_nans = [](
const Rect& a,
const Rect&
b,
const std::string& label) {
2482 ASSERT_TRUE(a.
IsFinite()) << label;
2483 ASSERT_TRUE(
b.IsFinite()) << label;
2486 for (
int i = 1; i < 16; i++) {
2488 EXPECT_FALSE(
swap_nan(a, i).Contains(
b)) << label <<
", index = " << i;
2492 for (
int j = 1; j < 16; j++) {
2494 << label <<
", indices = " << i <<
", " << j;
2499 auto check_empty_flips = [](
const Rect& a,
const Rect&
b,
2500 const std::string& label) {
2503 ASSERT_FALSE(
b.GetLeft() >
b.GetRight() ||
b.GetTop() >
b.GetBottom());
2511 EXPECT_FALSE(
flip_lr(a).Contains(
b)) << label;
2512 EXPECT_FALSE(
flip_tb(a).Contains(
b)) << label;
2513 EXPECT_FALSE(
flip_lrtb(a).Contains(
b)) << label;
2521 auto test_inside = [&check_nans, &check_empty_flips](
const Rect& a,
2523 ASSERT_FALSE(a.
IsEmpty()) << a;
2525 ASSERT_FALSE(
b.GetLeft() >
b.GetRight() ||
b.GetTop() >
b.GetBottom());
2527 std::stringstream stream;
2528 stream << a <<
" contains " <<
b;
2529 auto label = stream.str();
2532 check_empty_flips(a,
b, label);
2533 check_nans(a,
b, label);
2536 auto test_not_inside = [&check_nans, &check_empty_flips](
const Rect& a,
2538 ASSERT_FALSE(a.
IsEmpty()) << a;
2541 ASSERT_FALSE(
b.IsEmpty()) <<
b;
2543 std::stringstream stream;
2544 stream << a <<
" contains " <<
b;
2545 auto label = stream.str();
2548 check_empty_flips(a,
b, label);
2549 check_nans(a,
b, label);
2573 test_not_inside(a,
b);
2579 test_not_inside(a,
b);
2585 test_not_inside(a,
b);
2595 TEST(RectTest, IRectContainsIRect) {
2596 auto check_empty_flips = [](
const IRect& a,
const IRect&
b,
2597 const std::string& label) {
2600 ASSERT_FALSE(
b.GetLeft() >
b.GetRight() ||
b.GetTop() >
b.GetBottom());
2608 EXPECT_FALSE(
flip_lr(a).Contains(
b)) << label;
2609 EXPECT_FALSE(
flip_tb(a).Contains(
b)) << label;
2610 EXPECT_FALSE(
flip_lrtb(a).Contains(
b)) << label;
2618 auto test_inside = [&check_empty_flips](
const IRect& a,
const IRect&
b) {
2619 ASSERT_FALSE(a.
IsEmpty()) << a;
2621 ASSERT_FALSE(
b.GetLeft() >
b.GetRight() ||
b.GetTop() >
b.GetBottom());
2623 std::stringstream stream;
2624 stream << a <<
" contains " <<
b;
2625 auto label = stream.str();
2628 check_empty_flips(a,
b, label);
2631 auto test_not_inside = [&check_empty_flips](
const IRect& a,
const IRect&
b) {
2632 ASSERT_FALSE(a.
IsEmpty()) << a;
2635 ASSERT_FALSE(
b.IsEmpty()) <<
b;
2637 std::stringstream stream;
2638 stream << a <<
" contains " <<
b;
2639 auto label = stream.str();
2642 check_empty_flips(a,
b, label);
2666 test_not_inside(a,
b);
2672 test_not_inside(a,
b);
2678 test_not_inside(a,
b);
2691 auto check_nans = [&cull_rect](
const Rect& diff_rect,
2692 const std::string& label) {
2693 EXPECT_TRUE(cull_rect.
IsFinite()) << label;
2694 EXPECT_TRUE(diff_rect.
IsFinite()) << label;
2696 for (
int i = 1; i < 16; i++) {
2698 EXPECT_FALSE(
swap_nan(cull_rect, i).Cutout(diff_rect).has_value())
2699 << label <<
", index " << i;
2700 EXPECT_EQ(
swap_nan(cull_rect, i).CutoutOrEmpty(diff_rect),
Rect())
2701 << label <<
", index " << i;
2704 EXPECT_TRUE(cull_rect.
Cutout(
swap_nan(diff_rect, i)).has_value())
2705 << label <<
", index " << i;
2707 << label <<
", index " << i;
2709 for (
int j = 1; j < 16; j++) {
2713 << label <<
", indices " << i <<
", " << j;
2716 << label <<
", indices " << i <<
", " << j;
2721 auto check_empty_flips = [&cull_rect](
const Rect& diff_rect,
2722 const std::string& label) {
2723 EXPECT_FALSE(cull_rect.
IsEmpty()) << label;
2724 EXPECT_FALSE(diff_rect.
IsEmpty()) << label;
2728 EXPECT_TRUE(cull_rect.
Cutout(
flip_lr(diff_rect)).has_value()) << label;
2729 EXPECT_EQ(cull_rect.
Cutout(
flip_lr(diff_rect)), cull_rect) << label;
2730 EXPECT_TRUE(cull_rect.
Cutout(
flip_tb(diff_rect)).has_value()) << label;
2731 EXPECT_EQ(cull_rect.
Cutout(
flip_tb(diff_rect)), cull_rect) << label;
2732 EXPECT_TRUE(cull_rect.
Cutout(
flip_lrtb(diff_rect)).has_value()) << label;
2733 EXPECT_EQ(cull_rect.
Cutout(
flip_lrtb(diff_rect)), cull_rect) << label;
2737 EXPECT_FALSE(
flip_lr(cull_rect).Cutout(diff_rect).has_value()) << label;
2738 EXPECT_EQ(
flip_lr(cull_rect).CutoutOrEmpty(diff_rect),
Rect()) << label;
2739 EXPECT_FALSE(
flip_tb(cull_rect).Cutout(diff_rect).has_value()) << label;
2740 EXPECT_EQ(
flip_tb(cull_rect).CutoutOrEmpty(diff_rect),
Rect()) << label;
2741 EXPECT_FALSE(
flip_lrtb(cull_rect).Cutout(diff_rect).has_value()) << label;
2742 EXPECT_EQ(
flip_lrtb(cull_rect).CutoutOrEmpty(diff_rect),
Rect()) << label;
2746 EXPECT_FALSE(
flip_lr(cull_rect).Cutout(
flip_lr(diff_rect)).has_value())
2750 EXPECT_FALSE(
flip_tb(cull_rect).Cutout(
flip_tb(diff_rect)).has_value())
2760 auto non_reducing = [&cull_rect, &check_empty_flips, &check_nans](
2761 const Rect& diff_rect,
const std::string& label) {
2762 EXPECT_EQ(cull_rect.
Cutout(diff_rect), cull_rect) << label;
2763 EXPECT_EQ(cull_rect.
CutoutOrEmpty(diff_rect), cull_rect) << label;
2764 check_empty_flips(diff_rect, label);
2765 check_nans(diff_rect, label);
2768 auto reducing = [&cull_rect, &check_empty_flips, &check_nans](
2769 const Rect& diff_rect,
const Rect& result_rect,
2770 const std::string& label) {
2771 EXPECT_TRUE(!result_rect.IsEmpty());
2772 EXPECT_EQ(cull_rect.
Cutout(diff_rect), result_rect) << label;
2773 EXPECT_EQ(cull_rect.
CutoutOrEmpty(diff_rect), result_rect) << label;
2774 check_empty_flips(diff_rect, label);
2775 check_nans(diff_rect, label);
2778 auto emptying = [&cull_rect, &check_empty_flips, &check_nans](
2779 const Rect& diff_rect,
const std::string& label) {
2780 EXPECT_FALSE(cull_rect.
Cutout(diff_rect).has_value()) << label;
2782 check_empty_flips(diff_rect, label);
2783 check_nans(diff_rect, label);
2787 non_reducing(
Rect::MakeLTRB(10, 10, 20, 20),
"outside UL corner");
2789 non_reducing(
Rect::MakeLTRB(40, 10, 50, 20),
"outside UR corner");
2791 non_reducing(
Rect::MakeLTRB(40, 40, 50, 50),
"outside LR corner");
2793 non_reducing(
Rect::MakeLTRB(10, 40, 20, 50),
"outside LR corner");
2797 non_reducing(
Rect::MakeLTRB(15, 15, 25, 25),
"covering UL corner");
2798 non_reducing(
Rect::MakeLTRB(35, 15, 45, 25),
"covering UR corner");
2799 non_reducing(
Rect::MakeLTRB(35, 35, 45, 45),
"covering LR corner");
2800 non_reducing(
Rect::MakeLTRB(15, 35, 25, 45),
"covering LL corner");
2803 non_reducing(
Rect::MakeLTRB(20, 15, 39, 25),
"Top edge left-biased");
2804 non_reducing(
Rect::MakeLTRB(21, 15, 40, 25),
"Top edge, right biased");
2805 non_reducing(
Rect::MakeLTRB(35, 20, 45, 39),
"Right edge, top-biased");
2806 non_reducing(
Rect::MakeLTRB(35, 21, 45, 40),
"Right edge, bottom-biased");
2807 non_reducing(
Rect::MakeLTRB(20, 35, 39, 45),
"Bottom edge, left-biased");
2808 non_reducing(
Rect::MakeLTRB(21, 35, 40, 45),
"Bottom edge, right-biased");
2809 non_reducing(
Rect::MakeLTRB(15, 20, 25, 39),
"Left edge, top-biased");
2810 non_reducing(
Rect::MakeLTRB(15, 21, 25, 40),
"Left edge, bottom-biased");
2813 non_reducing(
Rect::MakeLTRB(25, 15, 35, 45),
"Vertical interior slice");
2814 non_reducing(
Rect::MakeLTRB(15, 25, 45, 35),
"Horizontal interior slice");
2825 "Slice off bottom");
2831 non_reducing(
Rect::MakeLTRB(21, 21, 39, 39),
"Contained, non-covering");
2834 emptying(cull_rect,
"Perfectly covering");
2843 auto check_empty_flips = [&cull_rect](
const IRect& diff_rect,
2844 const std::string& label) {
2845 EXPECT_FALSE(diff_rect.
IsEmpty());
2846 EXPECT_FALSE(cull_rect.
IsEmpty());
2850 EXPECT_TRUE(cull_rect.
Cutout(
flip_lr(diff_rect)).has_value()) << label;
2851 EXPECT_EQ(cull_rect.
Cutout(
flip_lr(diff_rect)), cull_rect) << label;
2852 EXPECT_TRUE(cull_rect.
Cutout(
flip_tb(diff_rect)).has_value()) << label;
2853 EXPECT_EQ(cull_rect.
Cutout(
flip_tb(diff_rect)), cull_rect) << label;
2854 EXPECT_TRUE(cull_rect.
Cutout(
flip_lrtb(diff_rect)).has_value()) << label;
2855 EXPECT_EQ(cull_rect.
Cutout(
flip_lrtb(diff_rect)), cull_rect) << label;
2859 EXPECT_FALSE(
flip_lr(cull_rect).Cutout(diff_rect).has_value()) << label;
2860 EXPECT_EQ(
flip_lr(cull_rect).CutoutOrEmpty(diff_rect),
IRect()) << label;
2861 EXPECT_FALSE(
flip_tb(cull_rect).Cutout(diff_rect).has_value()) << label;
2862 EXPECT_EQ(
flip_tb(cull_rect).CutoutOrEmpty(diff_rect),
IRect()) << label;
2863 EXPECT_FALSE(
flip_lrtb(cull_rect).Cutout(diff_rect).has_value()) << label;
2864 EXPECT_EQ(
flip_lrtb(cull_rect).CutoutOrEmpty(diff_rect),
IRect()) << label;
2868 EXPECT_FALSE(
flip_lr(cull_rect).Cutout(
flip_lr(diff_rect)).has_value())
2872 EXPECT_FALSE(
flip_tb(cull_rect).Cutout(
flip_tb(diff_rect)).has_value())
2882 auto non_reducing = [&cull_rect, &check_empty_flips](
2883 const IRect& diff_rect,
const std::string& label) {
2884 EXPECT_EQ(cull_rect.
Cutout(diff_rect), cull_rect) << label;
2885 EXPECT_EQ(cull_rect.
CutoutOrEmpty(diff_rect), cull_rect) << label;
2886 check_empty_flips(diff_rect, label);
2889 auto reducing = [&cull_rect, &check_empty_flips](
const IRect& diff_rect,
2890 const IRect& result_rect,
2891 const std::string& label) {
2892 EXPECT_TRUE(!result_rect.IsEmpty());
2893 EXPECT_EQ(cull_rect.
Cutout(diff_rect), result_rect) << label;
2894 EXPECT_EQ(cull_rect.
CutoutOrEmpty(diff_rect), result_rect) << label;
2895 check_empty_flips(diff_rect, label);
2898 auto emptying = [&cull_rect, &check_empty_flips](
const IRect& diff_rect,
2899 const std::string& label) {
2900 EXPECT_FALSE(cull_rect.
Cutout(diff_rect).has_value()) << label;
2902 check_empty_flips(diff_rect, label);
2922 non_reducing(
IRect::MakeLTRB(20, 15, 39, 25),
"Top edge left-biased");
2923 non_reducing(
IRect::MakeLTRB(21, 15, 40, 25),
"Top edge, right biased");
2924 non_reducing(
IRect::MakeLTRB(35, 20, 45, 39),
"Right edge, top-biased");
2925 non_reducing(
IRect::MakeLTRB(35, 21, 45, 40),
"Right edge, bottom-biased");
2926 non_reducing(
IRect::MakeLTRB(20, 35, 39, 45),
"Bottom edge, left-biased");
2927 non_reducing(
IRect::MakeLTRB(21, 35, 40, 45),
"Bottom edge, right-biased");
2928 non_reducing(
IRect::MakeLTRB(15, 20, 25, 39),
"Left edge, top-biased");
2929 non_reducing(
IRect::MakeLTRB(15, 21, 25, 40),
"Left edge, bottom-biased");
2932 non_reducing(
IRect::MakeLTRB(25, 15, 35, 45),
"Vertical interior slice");
2933 non_reducing(
IRect::MakeLTRB(15, 25, 45, 35),
"Horizontal interior slice");
2944 "Slice off bottom");
2950 non_reducing(
IRect::MakeLTRB(21, 21, 39, 39),
"Contained, non-covering");
2953 emptying(cull_rect,
"Perfectly covering");
2972 EXPECT_EQ(
points[0],
Point(std::numeric_limits<float>::lowest(),
2973 std::numeric_limits<float>::lowest()));
2974 EXPECT_EQ(
points[1],
Point(std::numeric_limits<float>::max(),
2975 std::numeric_limits<float>::lowest()));
2976 EXPECT_EQ(
points[2],
Point(std::numeric_limits<float>::lowest(),
2977 std::numeric_limits<float>::max()));
2978 EXPECT_EQ(
points[3],
Point(std::numeric_limits<float>::max(),
2979 std::numeric_limits<float>::max()));
2990 TEST(RectTest, RectGetTransformedPoints) {
2999 TEST(RectTest, RectMakePointBounds) {
3001 std::vector<Point>
points{{1, 5}, {4, -1}, {0, 6}};
3004 EXPECT_TRUE(r.has_value());
3005 if (r.has_value()) {
3010 std::vector<Point>
points;
3012 EXPECT_FALSE(r.has_value());
3033 EXPECT_EQ(r.GetLeft(), 1);
3034 EXPECT_EQ(r.GetTop(), 2);
3035 EXPECT_EQ(r.GetRight(), 3);
3036 EXPECT_EQ(r.GetBottom(), 4);
3047 auto actual = r.Project(r);
3116 TEST(RectTest, TransformAndClipBounds) {
3121 2.0f, 0.0f, 0.0f, 0.0f,
3122 0.0f, 4.0f, 0.0f, 0.0f,
3123 0.0f, 0.0f, 1.0f, 0.0f,
3124 0.0f, 0.0f, 0.0f, 8.0f
3129 EXPECT_EQ(matrix.TransformHomogenous(src.
GetLeftTop()),
3130 Vector3(200.0f, 400.0f, 8.0f));
3131 EXPECT_EQ(matrix.TransformHomogenous(src.
GetRightTop()),
3132 Vector3(400.0f, 400.0f, 8.0f));
3134 Vector3(200.0f, 800.0f, 8.0f));
3136 Vector3(400.0f, 800.0f, 8.0f));
3147 2.0f, 0.0f, 0.0f, -0.01f,
3148 0.0f, 2.0f, 0.0f, -0.006f,
3149 0.0f, 0.0f, 1.0f, 0.0f,
3150 0.0f, 0.0f, 0.0f, 3.0f
3156 Vector3(200.0f, 200.0f, 1.4f));
3158 Vector3(400.0f, 200.0f, 0.4f));
3160 Vector3(200.0f, 400.0f, 0.8f));
3162 Vector3(400.0f, 400.0f, -0.2f));
3173 2.0f, 0.0f, 0.0f, -.015f,
3174 0.0f, 2.0f, 0.0f, -.006f,
3175 0.0f, 0.0f, 1.0f, 0.0f,
3176 0.0f, 0.0f, 0.0f, 3.0f
3182 Vector3(200.0f, 200.0f, 0.9f));
3184 Vector3(400.0f, 200.0f, -0.6f));
3186 Vector3(200.0f, 400.0f, 0.3f));
3188 Vector3(400.0f, 400.0f, -1.2f));
3199 2.0f, 0.0f, 0.0f, -.02f,
3200 0.0f, 2.0f, 0.0f, -.006f,
3201 0.0f, 0.0f, 1.0f, 0.0f,
3202 0.0f, 0.0f, 0.0f, 3.0f
3208 Vector3(200.0f, 200.0f, 0.4f));
3210 Vector3(400.0f, 200.0f, -1.6f));
3212 Vector3(200.0f, 400.0f, -0.2f));
3214 Vector3(400.0f, 400.0f, -2.2f));
3225 2.0f, 0.0f, 0.0f, -.025f,
3226 0.0f, 2.0f, 0.0f, -.006f,
3227 0.0f, 0.0f, 1.0f, 0.0f,
3228 0.0f, 0.0f, 0.0f, 3.0f
3234 Vector3(200.0f, 200.0f, -0.1f));
3236 Vector3(400.0f, 200.0f, -2.6f));
3238 Vector3(200.0f, 400.0f, -0.7f));
3240 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
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 > 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 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 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