Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/layout/ng/ng_block_layout_algorithm.h" | 5 #include "core/layout/ng/ng_block_layout_algorithm.h" |
| 6 | 6 |
| 7 #include "core/layout/ng/ng_block_node.h" | 7 #include "core/layout/ng/ng_block_node.h" |
| 8 #include "core/layout/ng/ng_constraint_space.h" | 8 #include "core/layout/ng/ng_constraint_space.h" |
| 9 #include "core/layout/ng/ng_constraint_space_builder.h" | 9 #include "core/layout/ng/ng_constraint_space_builder.h" |
| 10 #include "core/layout/ng/ng_layout_coordinator.h" | 10 #include "core/layout/ng/ng_layout_coordinator.h" |
| (...skipping 829 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 840 first_child->SetNextSibling(second_child); | 840 first_child->SetNextSibling(second_child); |
| 841 | 841 |
| 842 auto* space = ConstructConstraintSpace( | 842 auto* space = ConstructConstraintSpace( |
| 843 kHorizontalTopBottom, TextDirection::kLtr, | 843 kHorizontalTopBottom, TextDirection::kLtr, |
| 844 NGLogicalSize(LayoutUnit(100), NGSizeIndefinite), true); | 844 NGLogicalSize(LayoutUnit(100), NGSizeIndefinite), true); |
| 845 NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, first_child); | 845 NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, first_child); |
| 846 | 846 |
| 847 EXPECT_EQ(LayoutUnit(30), frag->Width()); | 847 EXPECT_EQ(LayoutUnit(30), frag->Width()); |
| 848 } | 848 } |
| 849 | 849 |
| 850 class FragmentChildIterator | |
|
eae
2017/01/12 23:36:23
This class seem pretty useful, perhaps move out of
mstensho (USE GERRIT)
2017/01/13 14:30:18
Are you suggesting that I move it out to a separat
| |
| 851 : public GarbageCollectedFinalized<FragmentChildIterator> { | |
| 852 public: | |
| 853 FragmentChildIterator() {} | |
| 854 FragmentChildIterator(const NGPhysicalBoxFragment* parent) { | |
| 855 SetParent(parent); | |
| 856 } | |
| 857 void SetParent(const NGPhysicalBoxFragment* parent) { | |
| 858 parent_ = parent; | |
| 859 index_ = 0; | |
| 860 } | |
| 861 | |
| 862 const NGPhysicalBoxFragment* NextChild() { | |
| 863 if (!parent_) | |
| 864 return nullptr; | |
| 865 if (index_ >= parent_->Children().size()) | |
| 866 return nullptr; | |
| 867 while (parent_->Children()[index_]->Type() != | |
| 868 NGPhysicalFragment::kFragmentBox) { | |
| 869 ++index_; | |
| 870 if (index_ >= parent_->Children().size()) | |
| 871 return nullptr; | |
| 872 } | |
| 873 return toNGPhysicalBoxFragment(parent_->Children()[index_++]); | |
| 874 } | |
| 875 | |
| 876 DEFINE_INLINE_TRACE() { visitor->trace(parent_); } | |
| 877 | |
| 878 private: | |
| 879 Member<const NGPhysicalBoxFragment> parent_; | |
| 880 unsigned index_; | |
| 881 }; | |
| 882 | |
| 883 // Test case's HTML representation: | |
| 884 // <div id="parent" style="columns:2; column-fill:auto; column-gap:10px; | |
| 885 // width:210px; height:100px;"> | |
| 886 // </div> | |
| 887 TEST_F(NGBlockLayoutAlgorithmTest, EmptyMulticol) { | |
| 888 // parent | |
| 889 RefPtr<ComputedStyle> parent_style = ComputedStyle::create(); | |
| 890 parent_style->setColumnCount(2); | |
| 891 parent_style->setColumnFill(ColumnFillAuto); | |
| 892 parent_style->setColumnGap(10); | |
| 893 parent_style->setHeight(Length(100, Fixed)); | |
| 894 parent_style->setWidth(Length(210, Fixed)); | |
| 895 NGBlockNode* parent = new NGBlockNode(parent_style.get()); | |
| 896 | |
| 897 auto* space = ConstructConstraintSpace( | |
| 898 kHorizontalTopBottom, TextDirection::kLtr, | |
| 899 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite)); | |
| 900 const auto* fragment = RunBlockLayoutAlgorithm(space, parent); | |
| 901 FragmentChildIterator iterator(fragment); | |
| 902 fragment = iterator.NextChild(); | |
| 903 ASSERT_TRUE(fragment); | |
| 904 EXPECT_EQ(LayoutUnit(210), fragment->Width()); | |
| 905 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 906 EXPECT_FALSE(iterator.NextChild()); | |
| 907 | |
| 908 // There should be nothing inside the multicol container. | |
| 909 EXPECT_FALSE(FragmentChildIterator(fragment).NextChild()); | |
| 910 } | |
| 911 | |
| 912 // Test case's HTML representation: | |
| 913 // <div id="parent" style="columns:2; column-fill:auto; column-gap:10px; | |
| 914 // width:210px; height:100px;"> | |
| 915 // <div id="child"></div> | |
| 916 // </div> | |
| 917 TEST_F(NGBlockLayoutAlgorithmTest, EmptyBlock) { | |
| 918 // parent | |
| 919 RefPtr<ComputedStyle> parent_style = ComputedStyle::create(); | |
| 920 parent_style->setColumnCount(2); | |
| 921 parent_style->setColumnFill(ColumnFillAuto); | |
| 922 parent_style->setColumnGap(10); | |
| 923 parent_style->setHeight(Length(100, Fixed)); | |
| 924 parent_style->setWidth(Length(210, Fixed)); | |
| 925 NGBlockNode* parent = new NGBlockNode(parent_style.get()); | |
| 926 | |
| 927 // child | |
| 928 RefPtr<ComputedStyle> child_style = ComputedStyle::create(); | |
| 929 NGBlockNode* child = new NGBlockNode(child_style.get()); | |
| 930 | |
| 931 parent->SetFirstChild(child); | |
| 932 | |
| 933 auto* space = ConstructConstraintSpace( | |
| 934 kHorizontalTopBottom, TextDirection::kLtr, | |
| 935 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite)); | |
| 936 const auto* fragment = RunBlockLayoutAlgorithm(space, parent); | |
| 937 FragmentChildIterator iterator(fragment); | |
| 938 fragment = iterator.NextChild(); | |
| 939 EXPECT_EQ(LayoutUnit(210), fragment->Width()); | |
| 940 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 941 ASSERT_TRUE(fragment); | |
| 942 EXPECT_FALSE(iterator.NextChild()); | |
| 943 iterator.SetParent(fragment); | |
| 944 | |
| 945 // #child fragment in first column | |
| 946 fragment = iterator.NextChild(); | |
| 947 ASSERT_TRUE(fragment); | |
| 948 EXPECT_EQ(LayoutUnit(), fragment->LeftOffset()); | |
| 949 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 950 EXPECT_EQ(LayoutUnit(100), fragment->Width()); | |
| 951 EXPECT_EQ(LayoutUnit(), fragment->Height()); | |
| 952 EXPECT_EQ(0UL, fragment->Children().size()); | |
| 953 EXPECT_FALSE(iterator.NextChild()); | |
| 954 } | |
| 955 | |
| 956 // Test case's HTML representation: | |
| 957 // <div id="parent" style="columns:2; column-fill:auto; column-gap:10px; | |
| 958 // width:310px; height:100px;"> | |
| 959 // <div id="child" style="width:60%; height:100px;"></div> | |
| 960 // </div> | |
| 961 TEST_F(NGBlockLayoutAlgorithmTest, BlockInOneColumn) { | |
| 962 // parent | |
| 963 RefPtr<ComputedStyle> parent_style = ComputedStyle::create(); | |
| 964 parent_style->setColumnCount(2); | |
| 965 parent_style->setColumnFill(ColumnFillAuto); | |
| 966 parent_style->setColumnGap(10); | |
| 967 parent_style->setHeight(Length(100, Fixed)); | |
| 968 parent_style->setWidth(Length(310, Fixed)); | |
| 969 NGBlockNode* parent = new NGBlockNode(parent_style.get()); | |
| 970 | |
| 971 // child | |
| 972 RefPtr<ComputedStyle> child_style = ComputedStyle::create(); | |
| 973 child_style->setWidth(Length(60, Percent)); | |
| 974 child_style->setHeight(Length(100, Fixed)); | |
| 975 NGBlockNode* child = new NGBlockNode(child_style.get()); | |
| 976 | |
| 977 parent->SetFirstChild(child); | |
| 978 | |
| 979 auto* space = ConstructConstraintSpace( | |
| 980 kHorizontalTopBottom, TextDirection::kLtr, | |
| 981 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite)); | |
| 982 const auto* fragment = RunBlockLayoutAlgorithm(space, parent); | |
| 983 | |
| 984 FragmentChildIterator iterator(fragment); | |
| 985 fragment = iterator.NextChild(); | |
| 986 ASSERT_TRUE(fragment); | |
| 987 EXPECT_EQ(LayoutUnit(310), fragment->Width()); | |
| 988 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 989 EXPECT_FALSE(iterator.NextChild()); | |
| 990 iterator.SetParent(fragment); | |
| 991 | |
| 992 // #child fragment in first column | |
| 993 fragment = iterator.NextChild(); | |
| 994 ASSERT_TRUE(fragment); | |
| 995 EXPECT_EQ(LayoutUnit(), fragment->LeftOffset()); | |
| 996 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 997 EXPECT_EQ(LayoutUnit(90), fragment->Width()); | |
| 998 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 999 EXPECT_EQ(0UL, fragment->Children().size()); | |
| 1000 EXPECT_FALSE(iterator.NextChild()); | |
| 1001 } | |
| 1002 | |
| 1003 // Test case's HTML representation: | |
| 1004 // <div id="parent" style="columns:2; column-fill:auto; column-gap:10px; | |
| 1005 // width:210px; height:100px;"> | |
| 1006 // <div id="child" style="width:75%; height:150px;"></div> | |
| 1007 // </div> | |
| 1008 TEST_F(NGBlockLayoutAlgorithmTest, BlockInTwoColumns) { | |
| 1009 // parent | |
| 1010 RefPtr<ComputedStyle> parent_style = ComputedStyle::create(); | |
| 1011 parent_style->setColumnCount(2); | |
| 1012 parent_style->setColumnFill(ColumnFillAuto); | |
| 1013 parent_style->setColumnGap(10); | |
| 1014 parent_style->setHeight(Length(100, Fixed)); | |
| 1015 parent_style->setWidth(Length(210, Fixed)); | |
| 1016 NGBlockNode* parent = new NGBlockNode(parent_style.get()); | |
| 1017 | |
| 1018 // child | |
| 1019 RefPtr<ComputedStyle> child_style = ComputedStyle::create(); | |
| 1020 child_style->setWidth(Length(75, Percent)); | |
| 1021 child_style->setHeight(Length(150, Fixed)); | |
| 1022 NGBlockNode* child = new NGBlockNode(child_style.get()); | |
| 1023 | |
| 1024 parent->SetFirstChild(child); | |
| 1025 | |
| 1026 auto* space = ConstructConstraintSpace( | |
| 1027 kHorizontalTopBottom, TextDirection::kLtr, | |
| 1028 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite)); | |
| 1029 const auto* fragment = RunBlockLayoutAlgorithm(space, parent); | |
| 1030 | |
| 1031 FragmentChildIterator iterator(fragment); | |
| 1032 fragment = iterator.NextChild(); | |
| 1033 ASSERT_TRUE(fragment); | |
| 1034 EXPECT_EQ(LayoutUnit(210), fragment->Width()); | |
| 1035 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1036 EXPECT_FALSE(iterator.NextChild()); | |
| 1037 | |
| 1038 iterator.SetParent(fragment); | |
| 1039 // #child fragment in first column | |
| 1040 fragment = iterator.NextChild(); | |
| 1041 ASSERT_TRUE(fragment); | |
| 1042 EXPECT_EQ(LayoutUnit(), fragment->LeftOffset()); | |
| 1043 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1044 EXPECT_EQ(LayoutUnit(75), fragment->Width()); | |
| 1045 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1046 EXPECT_EQ(0UL, fragment->Children().size()); | |
| 1047 | |
| 1048 // #child fragment in second column | |
| 1049 fragment = iterator.NextChild(); | |
| 1050 ASSERT_TRUE(fragment); | |
| 1051 EXPECT_EQ(LayoutUnit(110), fragment->LeftOffset()); | |
| 1052 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1053 EXPECT_EQ(LayoutUnit(75), fragment->Width()); | |
| 1054 EXPECT_EQ(LayoutUnit(50), fragment->Height()); | |
| 1055 EXPECT_EQ(0U, fragment->Children().size()); | |
| 1056 EXPECT_FALSE(iterator.NextChild()); | |
| 1057 } | |
| 1058 | |
| 1059 // Test case's HTML representation: | |
| 1060 // <div id="parent" style="columns:3; column-fill:auto; column-gap:10px; | |
| 1061 // width:320px; height:100px;"> | |
| 1062 // <div id="child" style="width:75%; height:250px;"></div> | |
| 1063 // </div> | |
| 1064 TEST_F(NGBlockLayoutAlgorithmTest, BlockInThreeColumns) { | |
| 1065 // parent | |
| 1066 RefPtr<ComputedStyle> parent_style = ComputedStyle::create(); | |
| 1067 parent_style->setColumnCount(3); | |
| 1068 parent_style->setColumnFill(ColumnFillAuto); | |
| 1069 parent_style->setColumnGap(10); | |
| 1070 parent_style->setHeight(Length(100, Fixed)); | |
| 1071 parent_style->setWidth(Length(320, Fixed)); | |
| 1072 NGBlockNode* parent = new NGBlockNode(parent_style.get()); | |
| 1073 | |
| 1074 // child | |
| 1075 RefPtr<ComputedStyle> child_style = ComputedStyle::create(); | |
| 1076 child_style->setWidth(Length(75, Percent)); | |
| 1077 child_style->setHeight(Length(250, Fixed)); | |
| 1078 NGBlockNode* child = new NGBlockNode(child_style.get()); | |
| 1079 | |
| 1080 parent->SetFirstChild(child); | |
| 1081 | |
| 1082 auto* space = ConstructConstraintSpace( | |
| 1083 kHorizontalTopBottom, TextDirection::kLtr, | |
| 1084 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite)); | |
| 1085 const auto* fragment = RunBlockLayoutAlgorithm(space, parent); | |
| 1086 | |
| 1087 FragmentChildIterator iterator(fragment); | |
| 1088 fragment = iterator.NextChild(); | |
| 1089 ASSERT_TRUE(fragment); | |
| 1090 EXPECT_EQ(LayoutUnit(320), fragment->Width()); | |
| 1091 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1092 EXPECT_FALSE(iterator.NextChild()); | |
| 1093 | |
| 1094 iterator.SetParent(fragment); | |
| 1095 // #child fragment in first column | |
| 1096 fragment = iterator.NextChild(); | |
| 1097 ASSERT_TRUE(fragment); | |
| 1098 EXPECT_EQ(LayoutUnit(), fragment->LeftOffset()); | |
| 1099 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1100 EXPECT_EQ(LayoutUnit(75), fragment->Width()); | |
| 1101 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1102 EXPECT_EQ(0UL, fragment->Children().size()); | |
| 1103 | |
| 1104 // #child fragment in second column | |
| 1105 fragment = iterator.NextChild(); | |
| 1106 ASSERT_TRUE(fragment); | |
| 1107 EXPECT_EQ(LayoutUnit(110), fragment->LeftOffset()); | |
| 1108 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1109 EXPECT_EQ(LayoutUnit(75), fragment->Width()); | |
| 1110 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1111 EXPECT_EQ(0U, fragment->Children().size()); | |
| 1112 | |
| 1113 // #child fragment in third column | |
| 1114 fragment = iterator.NextChild(); | |
| 1115 ASSERT_TRUE(fragment); | |
| 1116 EXPECT_EQ(LayoutUnit(220), fragment->LeftOffset()); | |
| 1117 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1118 EXPECT_EQ(LayoutUnit(75), fragment->Width()); | |
| 1119 EXPECT_EQ(LayoutUnit(50), fragment->Height()); | |
| 1120 EXPECT_EQ(0U, fragment->Children().size()); | |
| 1121 EXPECT_FALSE(iterator.NextChild()); | |
| 1122 } | |
| 1123 | |
| 1124 // Test case's HTML representation: | |
| 1125 // <div id="parent" style="columns:2; column-fill:auto; column-gap:10px; | |
| 1126 // width:210px; height:100px;"> | |
| 1127 // <div id="child" style="width:1px; height:250px;"></div> | |
| 1128 // </div> | |
| 1129 TEST_F(NGBlockLayoutAlgorithmTest, ActualColumnCountGreaterThanSpecified) { | |
| 1130 // parent | |
| 1131 RefPtr<ComputedStyle> parent_style = ComputedStyle::create(); | |
| 1132 parent_style->setColumnCount(2); | |
| 1133 parent_style->setColumnFill(ColumnFillAuto); | |
| 1134 parent_style->setColumnGap(10); | |
| 1135 parent_style->setHeight(Length(100, Fixed)); | |
| 1136 parent_style->setWidth(Length(210, Fixed)); | |
| 1137 NGBlockNode* parent = new NGBlockNode(parent_style.get()); | |
| 1138 | |
| 1139 // child | |
| 1140 RefPtr<ComputedStyle> child_style = ComputedStyle::create(); | |
| 1141 child_style->setWidth(Length(1, Fixed)); | |
| 1142 child_style->setHeight(Length(250, Fixed)); | |
| 1143 NGBlockNode* child = new NGBlockNode(child_style.get()); | |
| 1144 | |
| 1145 parent->SetFirstChild(child); | |
| 1146 | |
| 1147 auto* space = ConstructConstraintSpace( | |
| 1148 kHorizontalTopBottom, TextDirection::kLtr, | |
| 1149 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite)); | |
| 1150 const auto* fragment = RunBlockLayoutAlgorithm(space, parent); | |
| 1151 | |
| 1152 FragmentChildIterator iterator(fragment); | |
| 1153 fragment = iterator.NextChild(); | |
| 1154 ASSERT_TRUE(fragment); | |
| 1155 EXPECT_EQ(LayoutUnit(210), fragment->Width()); | |
| 1156 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1157 EXPECT_FALSE(iterator.NextChild()); | |
| 1158 | |
| 1159 iterator.SetParent(fragment); | |
| 1160 // #child fragment in first column | |
| 1161 fragment = iterator.NextChild(); | |
| 1162 ASSERT_TRUE(fragment); | |
| 1163 EXPECT_EQ(LayoutUnit(), fragment->LeftOffset()); | |
| 1164 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1165 EXPECT_EQ(LayoutUnit(1), fragment->Width()); | |
| 1166 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1167 EXPECT_EQ(0UL, fragment->Children().size()); | |
| 1168 | |
| 1169 // #child fragment in second column | |
| 1170 fragment = iterator.NextChild(); | |
| 1171 ASSERT_TRUE(fragment); | |
| 1172 EXPECT_EQ(LayoutUnit(110), fragment->LeftOffset()); | |
| 1173 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1174 EXPECT_EQ(LayoutUnit(1), fragment->Width()); | |
| 1175 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1176 EXPECT_EQ(0U, fragment->Children().size()); | |
| 1177 | |
| 1178 // #child fragment in third column | |
| 1179 fragment = iterator.NextChild(); | |
| 1180 ASSERT_TRUE(fragment); | |
| 1181 EXPECT_EQ(LayoutUnit(220), fragment->LeftOffset()); | |
| 1182 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1183 EXPECT_EQ(LayoutUnit(1), fragment->Width()); | |
| 1184 EXPECT_EQ(LayoutUnit(50), fragment->Height()); | |
| 1185 EXPECT_EQ(0U, fragment->Children().size()); | |
| 1186 EXPECT_FALSE(iterator.NextChild()); | |
| 1187 } | |
| 1188 | |
| 1189 // Test case's HTML representation: | |
| 1190 // <div id="parent" style="columns:3; column-fill:auto; column-gap:10px; | |
| 1191 // width:320px; height:100px;"> | |
| 1192 // <div id="child1" style="width:75%; height:60px;"></div> | |
| 1193 // <div id="child2" style="width:85%; height:60px;"></div> | |
| 1194 // </div> | |
| 1195 TEST_F(NGBlockLayoutAlgorithmTest, TwoBlocksInTwoColumns) { | |
| 1196 // parent | |
| 1197 RefPtr<ComputedStyle> parent_style = ComputedStyle::create(); | |
| 1198 parent_style->setColumnCount(3); | |
| 1199 parent_style->setColumnFill(ColumnFillAuto); | |
| 1200 parent_style->setColumnGap(10); | |
| 1201 parent_style->setHeight(Length(100, Fixed)); | |
| 1202 parent_style->setWidth(Length(320, Fixed)); | |
| 1203 NGBlockNode* parent = new NGBlockNode(parent_style.get()); | |
| 1204 | |
| 1205 // child1 | |
| 1206 RefPtr<ComputedStyle> child1_style = ComputedStyle::create(); | |
| 1207 child1_style->setWidth(Length(75, Percent)); | |
| 1208 child1_style->setHeight(Length(60, Fixed)); | |
| 1209 NGBlockNode* child1 = new NGBlockNode(child1_style.get()); | |
| 1210 | |
| 1211 // child2 | |
| 1212 RefPtr<ComputedStyle> child2_style = ComputedStyle::create(); | |
| 1213 child2_style->setWidth(Length(85, Percent)); | |
| 1214 child2_style->setHeight(Length(60, Fixed)); | |
| 1215 NGBlockNode* child2 = new NGBlockNode(child2_style.get()); | |
| 1216 | |
| 1217 parent->SetFirstChild(child1); | |
| 1218 child1->SetNextSibling(child2); | |
| 1219 | |
| 1220 auto* space = ConstructConstraintSpace( | |
| 1221 kHorizontalTopBottom, TextDirection::kLtr, | |
| 1222 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite)); | |
| 1223 const auto* fragment = RunBlockLayoutAlgorithm(space, parent); | |
| 1224 | |
| 1225 FragmentChildIterator iterator(fragment); | |
| 1226 fragment = iterator.NextChild(); | |
| 1227 ASSERT_TRUE(fragment); | |
| 1228 EXPECT_EQ(LayoutUnit(320), fragment->Width()); | |
| 1229 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1230 EXPECT_FALSE(iterator.NextChild()); | |
| 1231 | |
| 1232 iterator.SetParent(fragment); | |
| 1233 // #child1 fragment in first column | |
| 1234 fragment = iterator.NextChild(); | |
| 1235 ASSERT_TRUE(fragment); | |
| 1236 EXPECT_EQ(LayoutUnit(), fragment->LeftOffset()); | |
| 1237 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1238 EXPECT_EQ(LayoutUnit(75), fragment->Width()); | |
| 1239 EXPECT_EQ(LayoutUnit(60), fragment->Height()); | |
| 1240 EXPECT_EQ(0UL, fragment->Children().size()); | |
| 1241 // #child2 fragment in first column | |
| 1242 fragment = iterator.NextChild(); | |
| 1243 ASSERT_TRUE(fragment); | |
| 1244 EXPECT_EQ(LayoutUnit(), fragment->LeftOffset()); | |
| 1245 EXPECT_EQ(LayoutUnit(60), fragment->TopOffset()); | |
| 1246 EXPECT_EQ(LayoutUnit(85), fragment->Width()); | |
| 1247 EXPECT_EQ(LayoutUnit(40), fragment->Height()); | |
| 1248 EXPECT_EQ(0UL, fragment->Children().size()); | |
| 1249 | |
| 1250 // #child2 fragment in second column | |
| 1251 fragment = iterator.NextChild(); | |
| 1252 ASSERT_TRUE(fragment); | |
| 1253 EXPECT_EQ(LayoutUnit(110), fragment->LeftOffset()); | |
| 1254 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1255 EXPECT_EQ(LayoutUnit(85), fragment->Width()); | |
| 1256 EXPECT_EQ(LayoutUnit(20), fragment->Height()); | |
| 1257 EXPECT_EQ(0U, fragment->Children().size()); | |
| 1258 EXPECT_FALSE(iterator.NextChild()); | |
| 1259 } | |
| 1260 | |
| 1261 // Test case's HTML representation: | |
| 1262 // <div id="parent" style="columns:3; column-fill:auto; column-gap:10px; | |
| 1263 // width:320px; height:100px;"> | |
| 1264 // <div id="child1" style="width:75%; height:60px;"> | |
| 1265 // <div id="grandchild1" style="width:50px; height:120px;"></div> | |
| 1266 // <div id="grandchild2" style="width:40px; height:20px;"></div> | |
| 1267 // </div> | |
| 1268 // <div id="child2" style="width:85%; height:10px;"></div> | |
| 1269 // </div> | |
| 1270 TEST_F(NGBlockLayoutAlgorithmTest, OverflowedBlock) { | |
| 1271 // parent | |
| 1272 RefPtr<ComputedStyle> parent_style = ComputedStyle::create(); | |
| 1273 parent_style->setColumnCount(3); | |
| 1274 parent_style->setColumnFill(ColumnFillAuto); | |
| 1275 parent_style->setColumnGap(10); | |
| 1276 parent_style->setHeight(Length(100, Fixed)); | |
| 1277 parent_style->setWidth(Length(320, Fixed)); | |
| 1278 NGBlockNode* parent = new NGBlockNode(parent_style.get()); | |
| 1279 | |
| 1280 // child1 | |
| 1281 RefPtr<ComputedStyle> child1_style = ComputedStyle::create(); | |
| 1282 child1_style->setWidth(Length(75, Percent)); | |
| 1283 child1_style->setHeight(Length(60, Fixed)); | |
| 1284 NGBlockNode* child1 = new NGBlockNode(child1_style.get()); | |
| 1285 | |
| 1286 // grandchild1 | |
| 1287 RefPtr<ComputedStyle> grandchild1_style = ComputedStyle::create(); | |
| 1288 grandchild1_style->setWidth(Length(50, Fixed)); | |
| 1289 grandchild1_style->setHeight(Length(120, Fixed)); | |
| 1290 NGBlockNode* grandchild1 = new NGBlockNode(grandchild1_style.get()); | |
| 1291 | |
| 1292 // grandchild2 | |
| 1293 RefPtr<ComputedStyle> grandchild2_style = ComputedStyle::create(); | |
| 1294 grandchild2_style->setWidth(Length(40, Fixed)); | |
| 1295 grandchild2_style->setHeight(Length(20, Fixed)); | |
| 1296 NGBlockNode* grandchild2 = new NGBlockNode(grandchild2_style.get()); | |
| 1297 | |
| 1298 // child2 | |
| 1299 RefPtr<ComputedStyle> child2_style = ComputedStyle::create(); | |
| 1300 child2_style->setWidth(Length(85, Percent)); | |
| 1301 child2_style->setHeight(Length(10, Fixed)); | |
| 1302 NGBlockNode* child2 = new NGBlockNode(child2_style.get()); | |
| 1303 | |
| 1304 parent->SetFirstChild(child1); | |
| 1305 child1->SetNextSibling(child2); | |
| 1306 child1->SetFirstChild(grandchild1); | |
| 1307 grandchild1->SetNextSibling(grandchild2); | |
| 1308 | |
| 1309 auto* space = ConstructConstraintSpace( | |
| 1310 kHorizontalTopBottom, TextDirection::kLtr, | |
| 1311 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite)); | |
| 1312 const auto* fragment = RunBlockLayoutAlgorithm(space, parent); | |
| 1313 | |
| 1314 FragmentChildIterator iterator(fragment); | |
| 1315 fragment = iterator.NextChild(); | |
| 1316 ASSERT_TRUE(fragment); | |
| 1317 EXPECT_EQ(LayoutUnit(320), fragment->Width()); | |
| 1318 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1319 EXPECT_FALSE(iterator.NextChild()); | |
| 1320 | |
| 1321 iterator.SetParent(fragment); | |
| 1322 // #child1 fragment in first column | |
| 1323 fragment = iterator.NextChild(); | |
| 1324 ASSERT_TRUE(fragment); | |
| 1325 EXPECT_EQ(LayoutUnit(), fragment->LeftOffset()); | |
| 1326 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1327 EXPECT_EQ(LayoutUnit(75), fragment->Width()); | |
| 1328 EXPECT_EQ(LayoutUnit(60), fragment->Height()); | |
| 1329 FragmentChildIterator grandchild_iterator(fragment); | |
| 1330 // #grandchild1 fragment in first column | |
| 1331 fragment = grandchild_iterator.NextChild(); | |
| 1332 ASSERT_TRUE(fragment); | |
| 1333 EXPECT_EQ(LayoutUnit(), fragment->LeftOffset()); | |
| 1334 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1335 EXPECT_EQ(LayoutUnit(50), fragment->Width()); | |
| 1336 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1337 EXPECT_FALSE(grandchild_iterator.NextChild()); | |
| 1338 // #child2 fragment in first column | |
| 1339 fragment = iterator.NextChild(); | |
| 1340 ASSERT_TRUE(fragment); | |
| 1341 EXPECT_EQ(LayoutUnit(), fragment->LeftOffset()); | |
| 1342 EXPECT_EQ(LayoutUnit(60), fragment->TopOffset()); | |
| 1343 EXPECT_EQ(LayoutUnit(85), fragment->Width()); | |
| 1344 EXPECT_EQ(LayoutUnit(10), fragment->Height()); | |
| 1345 EXPECT_EQ(0UL, fragment->Children().size()); | |
| 1346 | |
| 1347 // #child1 fragment in second column | |
| 1348 fragment = iterator.NextChild(); | |
| 1349 ASSERT_TRUE(fragment); | |
| 1350 EXPECT_EQ(LayoutUnit(110), fragment->LeftOffset()); | |
| 1351 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1352 EXPECT_EQ(LayoutUnit(75), fragment->Width()); | |
| 1353 EXPECT_EQ(LayoutUnit(), fragment->Height()); | |
| 1354 grandchild_iterator.SetParent(fragment); | |
| 1355 // #grandchild1 fragment in second column | |
| 1356 fragment = grandchild_iterator.NextChild(); | |
| 1357 ASSERT_TRUE(fragment); | |
| 1358 EXPECT_EQ(LayoutUnit(), fragment->LeftOffset()); | |
| 1359 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1360 EXPECT_EQ(LayoutUnit(50), fragment->Width()); | |
| 1361 EXPECT_EQ(LayoutUnit(20), fragment->Height()); | |
| 1362 // #grandchild2 fragment in second column | |
| 1363 fragment = grandchild_iterator.NextChild(); | |
| 1364 ASSERT_TRUE(fragment); | |
| 1365 EXPECT_EQ(LayoutUnit(), fragment->LeftOffset()); | |
| 1366 EXPECT_EQ(LayoutUnit(20), fragment->TopOffset()); | |
| 1367 EXPECT_EQ(LayoutUnit(40), fragment->Width()); | |
| 1368 EXPECT_EQ(LayoutUnit(20), fragment->Height()); | |
| 1369 EXPECT_FALSE(grandchild_iterator.NextChild()); | |
| 1370 EXPECT_FALSE(iterator.NextChild()); | |
| 1371 } | |
| 1372 | |
| 1373 // Test case's HTML representation: | |
| 1374 // <div id="parent" style="columns:3; column-fill:auto; column-gap:10px; | |
| 1375 // width:320px; height:100px;"> | |
| 1376 // <div id="child" style="float:left; width:75%; height:100px;"></div> | |
| 1377 // </div> | |
| 1378 TEST_F(NGBlockLayoutAlgorithmTest, FloatInOneColumn) { | |
| 1379 // parent | |
| 1380 RefPtr<ComputedStyle> parent_style = ComputedStyle::create(); | |
| 1381 parent_style->setColumnCount(3); | |
| 1382 parent_style->setColumnFill(ColumnFillAuto); | |
| 1383 parent_style->setColumnGap(10); | |
| 1384 parent_style->setHeight(Length(100, Fixed)); | |
| 1385 parent_style->setWidth(Length(320, Fixed)); | |
| 1386 NGBlockNode* parent = new NGBlockNode(parent_style.get()); | |
| 1387 | |
| 1388 // child | |
| 1389 RefPtr<ComputedStyle> child_style = ComputedStyle::create(); | |
| 1390 child_style->setFloating(EFloat::kLeft); | |
| 1391 child_style->setWidth(Length(75, Percent)); | |
| 1392 child_style->setHeight(Length(100, Fixed)); | |
| 1393 NGBlockNode* child = new NGBlockNode(child_style.get()); | |
| 1394 | |
| 1395 parent->SetFirstChild(child); | |
| 1396 | |
| 1397 auto* space = ConstructConstraintSpace( | |
| 1398 kHorizontalTopBottom, TextDirection::kLtr, | |
| 1399 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite)); | |
| 1400 const auto* fragment = RunBlockLayoutAlgorithm(space, parent); | |
| 1401 | |
| 1402 FragmentChildIterator iterator(fragment); | |
| 1403 fragment = iterator.NextChild(); | |
| 1404 ASSERT_TRUE(fragment); | |
| 1405 EXPECT_EQ(LayoutUnit(320), fragment->Width()); | |
| 1406 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1407 EXPECT_FALSE(iterator.NextChild()); | |
| 1408 | |
| 1409 iterator.SetParent(fragment); | |
| 1410 // #child fragment in first column | |
| 1411 fragment = iterator.NextChild(); | |
| 1412 ASSERT_TRUE(fragment); | |
| 1413 EXPECT_EQ(LayoutUnit(), fragment->LeftOffset()); | |
| 1414 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1415 EXPECT_EQ(LayoutUnit(75), fragment->Width()); | |
| 1416 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1417 EXPECT_EQ(0UL, fragment->Children().size()); | |
| 1418 EXPECT_FALSE(iterator.NextChild()); | |
| 1419 } | |
| 1420 | |
| 1421 // Test case's HTML representation: | |
| 1422 // <div id="parent" style="columns:3; column-fill:auto; column-gap:10px; | |
| 1423 // width:320px; height:100px;"> | |
| 1424 // <div id="child1" style="float:left; width:15%; height:100px;"></div> | |
| 1425 // <div id="child2" style="float:right; width:16%; height:100px;"></div> | |
| 1426 // </div> | |
| 1427 TEST_F(NGBlockLayoutAlgorithmTest, TwoFloatsInOneColumn) { | |
| 1428 // parent | |
| 1429 RefPtr<ComputedStyle> parent_style = ComputedStyle::create(); | |
| 1430 parent_style->setColumnCount(3); | |
| 1431 parent_style->setColumnFill(ColumnFillAuto); | |
| 1432 parent_style->setColumnGap(10); | |
| 1433 parent_style->setHeight(Length(100, Fixed)); | |
| 1434 parent_style->setWidth(Length(320, Fixed)); | |
| 1435 NGBlockNode* parent = new NGBlockNode(parent_style.get()); | |
| 1436 | |
| 1437 // child1 | |
| 1438 RefPtr<ComputedStyle> child1_style = ComputedStyle::create(); | |
| 1439 child1_style->setFloating(EFloat::kLeft); | |
| 1440 child1_style->setWidth(Length(15, Percent)); | |
| 1441 child1_style->setHeight(Length(100, Fixed)); | |
| 1442 NGBlockNode* child1 = new NGBlockNode(child1_style.get()); | |
| 1443 | |
| 1444 // child2 | |
| 1445 RefPtr<ComputedStyle> child2_style = ComputedStyle::create(); | |
| 1446 child2_style->setFloating(EFloat::kRight); | |
| 1447 child2_style->setWidth(Length(16, Percent)); | |
| 1448 child2_style->setHeight(Length(100, Fixed)); | |
| 1449 NGBlockNode* child2 = new NGBlockNode(child2_style.get()); | |
| 1450 | |
| 1451 parent->SetFirstChild(child1); | |
| 1452 child1->SetNextSibling(child2); | |
| 1453 | |
| 1454 auto* space = ConstructConstraintSpace( | |
| 1455 kHorizontalTopBottom, TextDirection::kLtr, | |
| 1456 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite)); | |
| 1457 const auto* fragment = RunBlockLayoutAlgorithm(space, parent); | |
| 1458 | |
| 1459 FragmentChildIterator iterator(fragment); | |
| 1460 fragment = iterator.NextChild(); | |
| 1461 ASSERT_TRUE(fragment); | |
| 1462 EXPECT_EQ(LayoutUnit(320), fragment->Width()); | |
| 1463 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1464 EXPECT_FALSE(iterator.NextChild()); | |
| 1465 | |
| 1466 iterator.SetParent(fragment); | |
| 1467 // #child1 fragment in first column | |
| 1468 fragment = iterator.NextChild(); | |
| 1469 ASSERT_TRUE(fragment); | |
| 1470 EXPECT_EQ(LayoutUnit(), fragment->LeftOffset()); | |
| 1471 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1472 EXPECT_EQ(LayoutUnit(15), fragment->Width()); | |
| 1473 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1474 EXPECT_EQ(0UL, fragment->Children().size()); | |
| 1475 // #child2 fragment in first column | |
| 1476 fragment = iterator.NextChild(); | |
| 1477 ASSERT_TRUE(fragment); | |
| 1478 EXPECT_EQ(LayoutUnit(84), fragment->LeftOffset()); | |
| 1479 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1480 EXPECT_EQ(LayoutUnit(16), fragment->Width()); | |
| 1481 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1482 EXPECT_EQ(0UL, fragment->Children().size()); | |
| 1483 EXPECT_FALSE(iterator.NextChild()); | |
| 1484 } | |
| 1485 | |
| 1486 // Test case's HTML representation: | |
| 1487 // <div id="parent" style="columns:3; column-fill:auto; column-gap:10px; | |
| 1488 // width:320px; height:100px;"> | |
| 1489 // <div id="child1" style="float:left; width:15%; height:150px;"></div> | |
| 1490 // <div id="child2" style="float:right; width:16%; height:150px;"></div> | |
| 1491 // </div> | |
| 1492 TEST_F(NGBlockLayoutAlgorithmTest, TwoFloatsInTwoColumns) { | |
| 1493 // parent | |
| 1494 RefPtr<ComputedStyle> parent_style = ComputedStyle::create(); | |
| 1495 parent_style->setColumnCount(3); | |
| 1496 parent_style->setColumnFill(ColumnFillAuto); | |
| 1497 parent_style->setColumnGap(10); | |
| 1498 parent_style->setHeight(Length(100, Fixed)); | |
| 1499 parent_style->setWidth(Length(320, Fixed)); | |
| 1500 NGBlockNode* parent = new NGBlockNode(parent_style.get()); | |
| 1501 | |
| 1502 // child1 | |
| 1503 RefPtr<ComputedStyle> child1_style = ComputedStyle::create(); | |
| 1504 child1_style->setFloating(EFloat::kLeft); | |
| 1505 child1_style->setWidth(Length(15, Percent)); | |
| 1506 child1_style->setHeight(Length(150, Fixed)); | |
| 1507 NGBlockNode* child1 = new NGBlockNode(child1_style.get()); | |
| 1508 | |
| 1509 // child2 | |
| 1510 RefPtr<ComputedStyle> child2_style = ComputedStyle::create(); | |
| 1511 child2_style->setFloating(EFloat::kRight); | |
| 1512 child2_style->setWidth(Length(16, Percent)); | |
| 1513 child2_style->setHeight(Length(150, Fixed)); | |
| 1514 NGBlockNode* child2 = new NGBlockNode(child2_style.get()); | |
| 1515 | |
| 1516 parent->SetFirstChild(child1); | |
| 1517 child1->SetNextSibling(child2); | |
| 1518 | |
| 1519 auto* space = ConstructConstraintSpace( | |
| 1520 kHorizontalTopBottom, TextDirection::kLtr, | |
| 1521 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite)); | |
| 1522 const auto* fragment = RunBlockLayoutAlgorithm(space, parent); | |
| 1523 | |
| 1524 FragmentChildIterator iterator(fragment); | |
| 1525 fragment = iterator.NextChild(); | |
| 1526 ASSERT_TRUE(fragment); | |
| 1527 EXPECT_EQ(LayoutUnit(320), fragment->Width()); | |
| 1528 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1529 EXPECT_FALSE(iterator.NextChild()); | |
| 1530 | |
| 1531 iterator.SetParent(fragment); | |
| 1532 // #child1 fragment in first column | |
| 1533 fragment = iterator.NextChild(); | |
| 1534 ASSERT_TRUE(fragment); | |
| 1535 EXPECT_EQ(LayoutUnit(), fragment->LeftOffset()); | |
| 1536 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1537 EXPECT_EQ(LayoutUnit(15), fragment->Width()); | |
| 1538 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1539 EXPECT_EQ(0UL, fragment->Children().size()); | |
| 1540 // #child2 fragment in first column | |
| 1541 fragment = iterator.NextChild(); | |
| 1542 ASSERT_TRUE(fragment); | |
| 1543 EXPECT_EQ(LayoutUnit(84), fragment->LeftOffset()); | |
| 1544 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1545 EXPECT_EQ(LayoutUnit(16), fragment->Width()); | |
| 1546 EXPECT_EQ(LayoutUnit(100), fragment->Height()); | |
| 1547 EXPECT_EQ(0UL, fragment->Children().size()); | |
| 1548 | |
| 1549 // #child1 fragment in second column | |
| 1550 fragment = iterator.NextChild(); | |
| 1551 ASSERT_TRUE(fragment); | |
| 1552 EXPECT_EQ(LayoutUnit(110), fragment->LeftOffset()); | |
| 1553 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1554 EXPECT_EQ(LayoutUnit(15), fragment->Width()); | |
| 1555 EXPECT_EQ(LayoutUnit(50), fragment->Height()); | |
| 1556 EXPECT_EQ(0UL, fragment->Children().size()); | |
| 1557 // #child2 fragment in second column | |
| 1558 fragment = iterator.NextChild(); | |
| 1559 ASSERT_TRUE(fragment); | |
| 1560 EXPECT_EQ(LayoutUnit(194), fragment->LeftOffset()); | |
| 1561 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | |
| 1562 EXPECT_EQ(LayoutUnit(16), fragment->Width()); | |
| 1563 EXPECT_EQ(LayoutUnit(50), fragment->Height()); | |
| 1564 EXPECT_EQ(0UL, fragment->Children().size()); | |
| 1565 EXPECT_FALSE(iterator.NextChild()); | |
| 1566 } | |
| 1567 | |
| 850 } // namespace | 1568 } // namespace |
| 851 } // namespace blink | 1569 } // namespace blink |
| OLD | NEW |