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/dom/NodeComputedStyle.h" | 7 #include "core/dom/NodeComputedStyle.h" |
8 #include "core/dom/TagCollection.h" | 8 #include "core/dom/TagCollection.h" |
9 #include "core/layout/ng/layout_ng_block_flow.h" | 9 #include "core/layout/ng/layout_ng_block_flow.h" |
10 #include "core/layout/ng/ng_block_node.h" | 10 #include "core/layout/ng/ng_block_node.h" |
11 #include "core/layout/ng/ng_constraint_space.h" | 11 #include "core/layout/ng/ng_constraint_space.h" |
12 #include "core/layout/ng/ng_constraint_space_builder.h" | 12 #include "core/layout/ng/ng_constraint_space_builder.h" |
13 #include "core/layout/ng/ng_floating_object.h" | 13 #include "core/layout/ng/ng_floating_object.h" |
14 #include "core/layout/ng/ng_length_utils.h" | 14 #include "core/layout/ng/ng_length_utils.h" |
15 #include "core/layout/LayoutTestHelper.h" | 15 #include "core/layout/LayoutTestHelper.h" |
16 #include "core/layout/ng/ng_physical_box_fragment.h" | 16 #include "core/layout/ng/ng_physical_box_fragment.h" |
17 #include "core/layout/ng/ng_physical_fragment.h" | 17 #include "core/layout/ng/ng_physical_fragment.h" |
18 #include "core/layout/ng/ng_units.h" | 18 #include "core/layout/ng/ng_units.h" |
19 #include "core/style/ComputedStyle.h" | 19 #include "core/style/ComputedStyle.h" |
20 #include "testing/gmock/include/gmock/gmock.h" | 20 #include "testing/gmock/include/gmock/gmock.h" |
21 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
22 | 22 |
23 namespace blink { | 23 namespace blink { |
24 namespace { | 24 namespace { |
25 | 25 |
26 using testing::ElementsAre; | 26 using testing::ElementsAre; |
27 using testing::Pointee; | 27 using testing::Pointee; |
28 | 28 |
29 NGConstraintSpace* ConstructConstraintSpace(NGWritingMode writing_mode, | 29 NGConstraintSpace* ConstructConstraintSpace( |
30 TextDirection direction, | 30 NGWritingMode writing_mode, |
31 NGLogicalSize size, | 31 TextDirection direction, |
32 bool shrink_to_fit = false) { | 32 NGLogicalSize size, |
33 bool shrink_to_fit = false, | |
34 LayoutUnit fragmentainer_space_available = LayoutUnit()) { | |
35 NGFragmentationType block_fragmentation = | |
36 fragmentainer_space_available != LayoutUnit() | |
37 ? NGFragmentationType::kFragmentColumn | |
38 : NGFragmentationType::kFragmentNone; | |
39 | |
33 return NGConstraintSpaceBuilder(writing_mode) | 40 return NGConstraintSpaceBuilder(writing_mode) |
34 .SetAvailableSize(size) | 41 .SetAvailableSize(size) |
35 .SetPercentageResolutionSize(size) | 42 .SetPercentageResolutionSize(size) |
36 .SetTextDirection(direction) | 43 .SetTextDirection(direction) |
37 .SetIsShrinkToFit(shrink_to_fit) | 44 .SetIsShrinkToFit(shrink_to_fit) |
45 .SetFragmentainerSpaceAvailable(fragmentainer_space_available) | |
46 .SetFragmentationType(block_fragmentation) | |
38 .ToConstraintSpace(writing_mode); | 47 .ToConstraintSpace(writing_mode); |
39 } | 48 } |
40 | 49 |
41 typedef bool TestParamLayoutNG; | 50 typedef bool TestParamLayoutNG; |
42 class NGBlockLayoutAlgorithmTest | 51 class NGBlockLayoutAlgorithmTest |
43 : public ::testing::WithParamInterface<TestParamLayoutNG>, | 52 : public ::testing::WithParamInterface<TestParamLayoutNG>, |
44 public RenderingTest { | 53 public RenderingTest { |
45 public: | 54 public: |
46 NGBlockLayoutAlgorithmTest() { | 55 NGBlockLayoutAlgorithmTest() { |
47 RuntimeEnabledFeatures::setLayoutNGEnabled(true); | 56 RuntimeEnabledFeatures::setLayoutNGEnabled(true); |
(...skipping 2041 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2089 EXPECT_THAT(NGPhysicalOffset(LayoutUnit(8), LayoutUnit(8)), | 2098 EXPECT_THAT(NGPhysicalOffset(LayoutUnit(8), LayoutUnit(8)), |
2090 empty_block1->Offset()); | 2099 empty_block1->Offset()); |
2091 | 2100 |
2092 auto* empty_block2 = | 2101 auto* empty_block2 = |
2093 toNGPhysicalBoxFragment(container_fragment->Children()[1].get()); | 2102 toNGPhysicalBoxFragment(container_fragment->Children()[1].get()); |
2094 // empty-block2's margin == 50 | 2103 // empty-block2's margin == 50 |
2095 EXPECT_THAT(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(50)), | 2104 EXPECT_THAT(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(50)), |
2096 empty_block2->Offset()); | 2105 empty_block2->Offset()); |
2097 } | 2106 } |
2098 | 2107 |
2108 // Tests that a block child won't fragment if it doesn't reach the fragmentation | |
2109 // line. | |
2110 TEST_F(NGBlockLayoutAlgorithmTest, NoFragmentation) { | |
2111 setBodyInnerHTML(R"HTML( | |
2112 <!DOCTYPE html> | |
2113 <style> | |
2114 #container { | |
2115 width: 150px; | |
2116 height: 200px; | |
2117 } | |
2118 </style> | |
2119 <div id='container'></div> | |
2120 )HTML"); | |
2121 | |
2122 LayoutUnit kFragmentainerSpaceAvailable(200); | |
2123 | |
2124 NGBlockNode* node = new NGBlockNode( | |
2125 toLayoutBlockFlow(getLayoutObjectByElementId("container"))); | |
2126 auto* space = ConstructConstraintSpace( | |
2127 kHorizontalTopBottom, TextDirection::kLtr, | |
2128 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false, | |
2129 kFragmentainerSpaceAvailable); | |
2130 | |
2131 // We should only have one 150x200 fragment with no fragmentation. | |
2132 RefPtr<const NGPhysicalFragment> fragment = | |
2133 NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment(); | |
2134 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(200)), fragment->Size()); | |
2135 ASSERT_TRUE(fragment->BreakToken()->IsFinished()); | |
2136 } | |
2137 | |
2138 // Tests that a block child with fragment if it reaches the fragmentation line. | |
mstensho (USE GERRIT)
2017/02/27 13:44:36
I don't think I can parse this sentence, but I thi
ikilpatrick
2017/02/27 18:50:09
s/with/will :P
| |
2139 TEST_F(NGBlockLayoutAlgorithmTest, SimpleFragmentation) { | |
2140 setBodyInnerHTML(R"HTML( | |
2141 <!DOCTYPE html> | |
2142 <style> | |
2143 #container { | |
2144 width: 150px; | |
2145 height: 300px; | |
2146 } | |
2147 </style> | |
2148 <div id='container'></div> | |
2149 )HTML"); | |
2150 | |
2151 LayoutUnit kFragmentainerSpaceAvailable(200); | |
2152 | |
2153 NGBlockNode* node = new NGBlockNode( | |
2154 toLayoutBlockFlow(getLayoutObjectByElementId("container"))); | |
2155 auto* space = ConstructConstraintSpace( | |
2156 kHorizontalTopBottom, TextDirection::kLtr, | |
2157 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false, | |
2158 kFragmentainerSpaceAvailable); | |
2159 | |
2160 RefPtr<const NGPhysicalFragment> fragment = | |
2161 NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment(); | |
2162 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(200)), fragment->Size()); | |
2163 ASSERT_FALSE(fragment->BreakToken()->IsFinished()); | |
2164 | |
2165 fragment = NGBlockLayoutAlgorithm(node, space, | |
2166 toNGBlockBreakToken(fragment->BreakToken())) | |
2167 .Layout() | |
2168 ->PhysicalFragment(); | |
2169 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(100)), fragment->Size()); | |
2170 ASSERT_TRUE(fragment->BreakToken()->IsFinished()); | |
2171 } | |
2172 | |
2173 // Tests that children inside the same block formatting context fragment when | |
2174 // reaching a fragmentation line. | |
2175 TEST_F(NGBlockLayoutAlgorithmTest, InnerChildrenFragmentation) { | |
2176 setBodyInnerHTML(R"HTML( | |
2177 <!DOCTYPE html> | |
2178 <style> | |
2179 #container { | |
2180 width: 150px; | |
2181 padding-top: 20px; | |
2182 } | |
2183 #child1 { | |
2184 height: 200px; | |
2185 margin-bottom: 20px; | |
2186 } | |
2187 #child2 { | |
2188 height: 100px; | |
2189 margin-top: 20px; | |
2190 } | |
2191 </style> | |
2192 <div id='container'> | |
2193 <div id='child1'></div> | |
2194 <div id='child2'></div> | |
2195 </div> | |
2196 )HTML"); | |
2197 | |
2198 LayoutUnit kFragmentainerSpaceAvailable(200); | |
2199 | |
2200 NGBlockNode* node = new NGBlockNode( | |
2201 toLayoutBlockFlow(getLayoutObjectByElementId("container"))); | |
2202 auto* space = ConstructConstraintSpace( | |
2203 kHorizontalTopBottom, TextDirection::kLtr, | |
2204 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false, | |
2205 kFragmentainerSpaceAvailable); | |
2206 | |
2207 RefPtr<const NGPhysicalFragment> fragment = | |
2208 NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment(); | |
2209 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(200)), fragment->Size()); | |
2210 ASSERT_FALSE(fragment->BreakToken()->IsFinished()); | |
2211 | |
2212 FragmentChildIterator iterator(toNGPhysicalBoxFragment(fragment.get())); | |
2213 const NGPhysicalBoxFragment* child = iterator.NextChild(); | |
2214 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(180)), child->Size()); | |
2215 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)), child->Offset()); | |
2216 | |
2217 EXPECT_FALSE(iterator.NextChild()); | |
2218 | |
2219 fragment = NGBlockLayoutAlgorithm(node, space, | |
2220 toNGBlockBreakToken(fragment->BreakToken())) | |
2221 .Layout() | |
2222 ->PhysicalFragment(); | |
2223 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(140)), fragment->Size()); | |
2224 ASSERT_TRUE(fragment->BreakToken()->IsFinished()); | |
2225 | |
2226 iterator.SetParent(toNGPhysicalBoxFragment(fragment.get())); | |
2227 child = iterator.NextChild(); | |
2228 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(20)), child->Size()); | |
2229 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(0)), child->Offset()); | |
2230 | |
2231 child = iterator.NextChild(); | |
2232 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(100)), child->Size()); | |
2233 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(40)), child->Offset()); | |
2234 | |
2235 EXPECT_FALSE(iterator.NextChild()); | |
2236 } | |
2237 | |
2238 // Tests that children inside which establish new formatting contexts fragment | |
2239 // correctly. | |
2240 TEST_F(NGBlockLayoutAlgorithmTest, | |
2241 InnerFormattingContextChildrenFragmentation) { | |
2242 setBodyInnerHTML(R"HTML( | |
2243 <!DOCTYPE html> | |
2244 <style> | |
2245 #container { | |
2246 width: 150px; | |
2247 padding-top: 20px; | |
2248 } | |
2249 #child1 { | |
2250 height: 200px; | |
2251 margin-bottom: 20px; | |
2252 contain: paint; | |
2253 } | |
2254 #child2 { | |
2255 height: 100px; | |
2256 margin-top: 20px; | |
2257 contain: paint; | |
2258 } | |
2259 </style> | |
2260 <div id='container'> | |
2261 <div id='child1'></div> | |
2262 <div id='child2'></div> | |
2263 </div> | |
2264 )HTML"); | |
2265 | |
2266 LayoutUnit kFragmentainerSpaceAvailable(200); | |
2267 | |
2268 NGBlockNode* node = new NGBlockNode( | |
2269 toLayoutBlockFlow(getLayoutObjectByElementId("container"))); | |
2270 auto* space = ConstructConstraintSpace( | |
2271 kHorizontalTopBottom, TextDirection::kLtr, | |
2272 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false, | |
2273 kFragmentainerSpaceAvailable); | |
2274 | |
2275 RefPtr<const NGPhysicalFragment> fragment = | |
2276 NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment(); | |
2277 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(200)), fragment->Size()); | |
2278 ASSERT_FALSE(fragment->BreakToken()->IsFinished()); | |
2279 | |
2280 FragmentChildIterator iterator(toNGPhysicalBoxFragment(fragment.get())); | |
2281 const NGPhysicalBoxFragment* child = iterator.NextChild(); | |
2282 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(180)), child->Size()); | |
2283 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)), child->Offset()); | |
2284 | |
2285 EXPECT_FALSE(iterator.NextChild()); | |
2286 | |
2287 fragment = NGBlockLayoutAlgorithm(node, space, | |
2288 toNGBlockBreakToken(fragment->BreakToken())) | |
2289 .Layout() | |
2290 ->PhysicalFragment(); | |
2291 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(140)), fragment->Size()); | |
2292 ASSERT_TRUE(fragment->BreakToken()->IsFinished()); | |
2293 | |
2294 iterator.SetParent(toNGPhysicalBoxFragment(fragment.get())); | |
2295 child = iterator.NextChild(); | |
2296 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(20)), child->Size()); | |
2297 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(0)), child->Offset()); | |
2298 | |
2299 child = iterator.NextChild(); | |
2300 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(100)), child->Size()); | |
2301 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(40)), child->Offset()); | |
2302 | |
2303 EXPECT_FALSE(iterator.NextChild()); | |
2304 } | |
2305 | |
2306 // Tests that children inside which establish new formatting contexts fragment | |
mstensho (USE GERRIT)
2017/02/27 13:44:36
Comment is the same as the one before the previous
ikilpatrick
2017/02/27 18:50:09
Done.
| |
2307 // correctly. | |
2308 TEST_F(NGBlockLayoutAlgorithmTest, InnerChildrenFragmentationSmallHeight) { | |
2309 setBodyInnerHTML(R"HTML( | |
2310 <!DOCTYPE html> | |
2311 <style> | |
2312 #container { | |
2313 width: 150px; | |
2314 padding-top: 20px; | |
2315 height: 50px; | |
2316 } | |
2317 #child1 { | |
2318 height: 200px; | |
2319 margin-bottom: 20px; | |
2320 } | |
2321 #child2 { | |
2322 height: 100px; | |
2323 margin-top: 20px; | |
2324 } | |
2325 </style> | |
2326 <div id='container'> | |
2327 <div id='child1'></div> | |
2328 <div id='child2'></div> | |
2329 </div> | |
2330 )HTML"); | |
2331 | |
2332 LayoutUnit kFragmentainerSpaceAvailable(200); | |
2333 | |
2334 NGBlockNode* node = new NGBlockNode( | |
2335 toLayoutBlockFlow(getLayoutObjectByElementId("container"))); | |
2336 auto* space = ConstructConstraintSpace( | |
2337 kHorizontalTopBottom, TextDirection::kLtr, | |
2338 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false, | |
2339 kFragmentainerSpaceAvailable); | |
2340 | |
2341 RefPtr<const NGPhysicalFragment> fragment = | |
2342 NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment(); | |
2343 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(70)), fragment->Size()); | |
2344 ASSERT_FALSE(fragment->BreakToken()->IsFinished()); | |
2345 | |
2346 FragmentChildIterator iterator(toNGPhysicalBoxFragment(fragment.get())); | |
2347 const NGPhysicalBoxFragment* child = iterator.NextChild(); | |
2348 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(180)), child->Size()); | |
2349 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)), child->Offset()); | |
2350 | |
2351 EXPECT_FALSE(iterator.NextChild()); | |
2352 | |
2353 fragment = NGBlockLayoutAlgorithm(node, space, | |
2354 toNGBlockBreakToken(fragment->BreakToken())) | |
2355 .Layout() | |
2356 ->PhysicalFragment(); | |
2357 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(0)), fragment->Size()); | |
2358 ASSERT_TRUE(fragment->BreakToken()->IsFinished()); | |
2359 | |
2360 iterator.SetParent(toNGPhysicalBoxFragment(fragment.get())); | |
2361 child = iterator.NextChild(); | |
2362 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(20)), child->Size()); | |
2363 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(0)), child->Offset()); | |
2364 | |
2365 child = iterator.NextChild(); | |
2366 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(100)), child->Size()); | |
2367 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(40)), child->Offset()); | |
2368 | |
2369 EXPECT_FALSE(iterator.NextChild()); | |
2370 } | |
2371 | |
2099 } // namespace | 2372 } // namespace |
2100 } // namespace blink | 2373 } // namespace blink |
OLD | NEW |