Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc

Issue 2714803002: [LayoutNG] Allow block-flow layout to be fragmented using new approach. (Closed)
Patch Set: spelling. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 2119 matching lines...) Expand 10 before | Expand all | Expand 10 after
2167 // Verify #clears-right block 2176 // Verify #clears-right block
2168 ASSERT_EQ(2UL, container_clear_fragment->Children().size()); 2177 ASSERT_EQ(2UL, container_clear_fragment->Children().size());
2169 auto* clears_right_fragment = 2178 auto* clears_right_fragment =
2170 toNGPhysicalBoxFragment(container_clear_fragment->Children()[1].get()); 2179 toNGPhysicalBoxFragment(container_clear_fragment->Children()[1].get());
2171 // 20 = right-float's block end offset (130 + 80) - 2180 // 20 = right-float's block end offset (130 + 80) -
2172 // container_clear->offsetTop() 190 2181 // container_clear->offsetTop() 190
2173 EXPECT_THAT(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)), 2182 EXPECT_THAT(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)),
2174 clears_right_fragment->Offset()); 2183 clears_right_fragment->Offset());
2175 } 2184 }
2176 2185
2186 // Tests that a block won't fragment if it doesn't reach the fragmentation line.
2187 TEST_F(NGBlockLayoutAlgorithmTest, NoFragmentation) {
2188 setBodyInnerHTML(R"HTML(
2189 <!DOCTYPE html>
2190 <style>
2191 #container {
2192 width: 150px;
2193 height: 200px;
2194 }
2195 </style>
2196 <div id='container'></div>
2197 )HTML");
2198
2199 LayoutUnit kFragmentainerSpaceAvailable(200);
2200
2201 NGBlockNode* node = new NGBlockNode(
2202 toLayoutBlockFlow(getLayoutObjectByElementId("container")));
2203 auto* space = ConstructConstraintSpace(
2204 kHorizontalTopBottom, TextDirection::kLtr,
2205 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
2206 kFragmentainerSpaceAvailable);
2207
2208 // We should only have one 150x200 fragment with no fragmentation.
2209 RefPtr<const NGPhysicalFragment> fragment =
2210 NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment();
2211 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(200)), fragment->Size());
2212 ASSERT_TRUE(fragment->BreakToken()->IsFinished());
2213 }
2214
2215 // Tests that a block will fragment if it reaches the fragmentation line.
2216 TEST_F(NGBlockLayoutAlgorithmTest, SimpleFragmentation) {
2217 setBodyInnerHTML(R"HTML(
2218 <!DOCTYPE html>
2219 <style>
2220 #container {
2221 width: 150px;
2222 height: 300px;
2223 }
2224 </style>
2225 <div id='container'></div>
2226 )HTML");
2227
2228 LayoutUnit kFragmentainerSpaceAvailable(200);
2229
2230 NGBlockNode* node = new NGBlockNode(
2231 toLayoutBlockFlow(getLayoutObjectByElementId("container")));
2232 auto* space = ConstructConstraintSpace(
2233 kHorizontalTopBottom, TextDirection::kLtr,
2234 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
2235 kFragmentainerSpaceAvailable);
2236
2237 RefPtr<const NGPhysicalFragment> fragment =
2238 NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment();
2239 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(200)), fragment->Size());
2240 ASSERT_FALSE(fragment->BreakToken()->IsFinished());
2241
2242 fragment = NGBlockLayoutAlgorithm(node, space,
2243 toNGBlockBreakToken(fragment->BreakToken()))
2244 .Layout()
2245 ->PhysicalFragment();
2246 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(100)), fragment->Size());
2247 ASSERT_TRUE(fragment->BreakToken()->IsFinished());
2248 }
2249
2250 // Tests that children inside the same block formatting context fragment when
2251 // reaching a fragmentation line.
2252 TEST_F(NGBlockLayoutAlgorithmTest, InnerChildrenFragmentation) {
2253 setBodyInnerHTML(R"HTML(
2254 <!DOCTYPE html>
2255 <style>
2256 #container {
2257 width: 150px;
2258 padding-top: 20px;
2259 }
2260 #child1 {
2261 height: 200px;
2262 margin-bottom: 20px;
2263 }
2264 #child2 {
2265 height: 100px;
2266 margin-top: 20px;
2267 }
2268 </style>
2269 <div id='container'>
2270 <div id='child1'></div>
2271 <div id='child2'></div>
2272 </div>
2273 )HTML");
2274
2275 LayoutUnit kFragmentainerSpaceAvailable(200);
2276
2277 NGBlockNode* node = new NGBlockNode(
2278 toLayoutBlockFlow(getLayoutObjectByElementId("container")));
2279 auto* space = ConstructConstraintSpace(
2280 kHorizontalTopBottom, TextDirection::kLtr,
2281 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
2282 kFragmentainerSpaceAvailable);
2283
2284 RefPtr<const NGPhysicalFragment> fragment =
2285 NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment();
2286 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(200)), fragment->Size());
2287 ASSERT_FALSE(fragment->BreakToken()->IsFinished());
2288
2289 FragmentChildIterator iterator(toNGPhysicalBoxFragment(fragment.get()));
2290 const NGPhysicalBoxFragment* child = iterator.NextChild();
2291 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(180)), child->Size());
2292 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)), child->Offset());
2293
2294 EXPECT_FALSE(iterator.NextChild());
2295
2296 fragment = NGBlockLayoutAlgorithm(node, space,
2297 toNGBlockBreakToken(fragment->BreakToken()))
2298 .Layout()
2299 ->PhysicalFragment();
2300 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(140)), fragment->Size());
2301 ASSERT_TRUE(fragment->BreakToken()->IsFinished());
2302
2303 iterator.SetParent(toNGPhysicalBoxFragment(fragment.get()));
2304 child = iterator.NextChild();
2305 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(20)), child->Size());
2306 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(0)), child->Offset());
2307
2308 child = iterator.NextChild();
2309 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(100)), child->Size());
2310 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(40)), child->Offset());
2311
2312 EXPECT_FALSE(iterator.NextChild());
2313 }
2314
2315 // Tests that children which establish new formatting contexts fragment
2316 // correctly.
2317 TEST_F(NGBlockLayoutAlgorithmTest,
2318 InnerFormattingContextChildrenFragmentation) {
2319 setBodyInnerHTML(R"HTML(
2320 <!DOCTYPE html>
2321 <style>
2322 #container {
2323 width: 150px;
2324 padding-top: 20px;
2325 }
2326 #child1 {
2327 height: 200px;
2328 margin-bottom: 20px;
2329 contain: paint;
2330 }
2331 #child2 {
2332 height: 100px;
2333 margin-top: 20px;
2334 contain: paint;
2335 }
2336 </style>
2337 <div id='container'>
2338 <div id='child1'></div>
2339 <div id='child2'></div>
2340 </div>
2341 )HTML");
2342
2343 LayoutUnit kFragmentainerSpaceAvailable(200);
2344
2345 NGBlockNode* node = new NGBlockNode(
2346 toLayoutBlockFlow(getLayoutObjectByElementId("container")));
2347 auto* space = ConstructConstraintSpace(
2348 kHorizontalTopBottom, TextDirection::kLtr,
2349 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
2350 kFragmentainerSpaceAvailable);
2351
2352 RefPtr<const NGPhysicalFragment> fragment =
2353 NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment();
2354 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(200)), fragment->Size());
2355 ASSERT_FALSE(fragment->BreakToken()->IsFinished());
2356
2357 FragmentChildIterator iterator(toNGPhysicalBoxFragment(fragment.get()));
2358 const NGPhysicalBoxFragment* child = iterator.NextChild();
2359 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(180)), child->Size());
2360 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)), child->Offset());
2361
2362 EXPECT_FALSE(iterator.NextChild());
2363
2364 fragment = NGBlockLayoutAlgorithm(node, space,
2365 toNGBlockBreakToken(fragment->BreakToken()))
2366 .Layout()
2367 ->PhysicalFragment();
2368 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(140)), fragment->Size());
2369 ASSERT_TRUE(fragment->BreakToken()->IsFinished());
2370
2371 iterator.SetParent(toNGPhysicalBoxFragment(fragment.get()));
2372 child = iterator.NextChild();
2373 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(20)), child->Size());
2374 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(0)), child->Offset());
2375
2376 child = iterator.NextChild();
2377 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(100)), child->Size());
2378 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(40)), child->Offset());
2379
2380 EXPECT_FALSE(iterator.NextChild());
2381 }
2382
2383 // Tests that children inside a block container will fragment if the container
2384 // doesn't reach the fragmentation line.
2385 TEST_F(NGBlockLayoutAlgorithmTest, InnerChildrenFragmentationSmallHeight) {
2386 setBodyInnerHTML(R"HTML(
2387 <!DOCTYPE html>
2388 <style>
2389 #container {
2390 width: 150px;
2391 padding-top: 20px;
2392 height: 50px;
2393 }
2394 #child1 {
2395 height: 200px;
2396 margin-bottom: 20px;
2397 }
2398 #child2 {
2399 height: 100px;
2400 margin-top: 20px;
2401 }
2402 </style>
2403 <div id='container'>
2404 <div id='child1'></div>
2405 <div id='child2'></div>
2406 </div>
2407 )HTML");
2408
2409 LayoutUnit kFragmentainerSpaceAvailable(200);
2410
2411 NGBlockNode* node = new NGBlockNode(
2412 toLayoutBlockFlow(getLayoutObjectByElementId("container")));
2413 auto* space = ConstructConstraintSpace(
2414 kHorizontalTopBottom, TextDirection::kLtr,
2415 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
2416 kFragmentainerSpaceAvailable);
2417
2418 RefPtr<const NGPhysicalFragment> fragment =
2419 NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment();
2420 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(70)), fragment->Size());
2421 ASSERT_FALSE(fragment->BreakToken()->IsFinished());
2422
2423 FragmentChildIterator iterator(toNGPhysicalBoxFragment(fragment.get()));
2424 const NGPhysicalBoxFragment* child = iterator.NextChild();
2425 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(180)), child->Size());
2426 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)), child->Offset());
2427
2428 EXPECT_FALSE(iterator.NextChild());
2429
2430 fragment = NGBlockLayoutAlgorithm(node, space,
2431 toNGBlockBreakToken(fragment->BreakToken()))
2432 .Layout()
2433 ->PhysicalFragment();
2434 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(0)), fragment->Size());
2435 ASSERT_TRUE(fragment->BreakToken()->IsFinished());
2436
2437 iterator.SetParent(toNGPhysicalBoxFragment(fragment.get()));
2438 child = iterator.NextChild();
2439 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(20)), child->Size());
2440 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(0)), child->Offset());
2441
2442 child = iterator.NextChild();
2443 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(100)), child->Size());
2444 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(40)), child->Offset());
2445
2446 EXPECT_FALSE(iterator.NextChild());
2447 }
2448
2177 } // namespace 2449 } // namespace
2178 } // namespace blink 2450 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698