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

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: rebase. 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/LayoutTestHelper.h"
9 #include "core/layout/ng/layout_ng_block_flow.h" 10 #include "core/layout/ng/layout_ng_block_flow.h"
11 #include "core/layout/ng/ng_block_break_token.h"
10 #include "core/layout/ng/ng_block_node.h" 12 #include "core/layout/ng/ng_block_node.h"
11 #include "core/layout/ng/ng_constraint_space.h" 13 #include "core/layout/ng/ng_constraint_space.h"
12 #include "core/layout/ng/ng_constraint_space_builder.h" 14 #include "core/layout/ng/ng_constraint_space_builder.h"
13 #include "core/layout/ng/ng_floating_object.h" 15 #include "core/layout/ng/ng_floating_object.h"
14 #include "core/layout/ng/ng_length_utils.h" 16 #include "core/layout/ng/ng_length_utils.h"
15 #include "core/layout/LayoutTestHelper.h"
16 #include "core/layout/ng/ng_physical_box_fragment.h" 17 #include "core/layout/ng/ng_physical_box_fragment.h"
17 #include "core/layout/ng/ng_physical_fragment.h" 18 #include "core/layout/ng/ng_physical_fragment.h"
18 #include "core/layout/ng/ng_units.h" 19 #include "core/layout/ng/ng_units.h"
19 #include "core/style/ComputedStyle.h" 20 #include "core/style/ComputedStyle.h"
20 #include "testing/gmock/include/gmock/gmock.h" 21 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h" 22 #include "testing/gtest/include/gtest/gtest.h"
22 23
23 namespace blink { 24 namespace blink {
24 namespace { 25 namespace {
25 26
26 using testing::ElementsAre; 27 using testing::ElementsAre;
27 using testing::Pointee; 28 using testing::Pointee;
28 29
29 NGConstraintSpace* ConstructConstraintSpace(NGWritingMode writing_mode, 30 NGConstraintSpace* ConstructConstraintSpace(
30 TextDirection direction, 31 NGWritingMode writing_mode,
31 NGLogicalSize size, 32 TextDirection direction,
32 bool shrink_to_fit = false) { 33 NGLogicalSize size,
34 bool shrink_to_fit = false,
35 LayoutUnit fragmentainer_space_available = LayoutUnit()) {
36 NGFragmentationType block_fragmentation =
37 fragmentainer_space_available != LayoutUnit()
38 ? NGFragmentationType::kFragmentColumn
39 : NGFragmentationType::kFragmentNone;
40
33 return NGConstraintSpaceBuilder(writing_mode) 41 return NGConstraintSpaceBuilder(writing_mode)
34 .SetAvailableSize(size) 42 .SetAvailableSize(size)
35 .SetPercentageResolutionSize(size) 43 .SetPercentageResolutionSize(size)
36 .SetTextDirection(direction) 44 .SetTextDirection(direction)
37 .SetIsShrinkToFit(shrink_to_fit) 45 .SetIsShrinkToFit(shrink_to_fit)
46 .SetFragmentainerSpaceAvailable(fragmentainer_space_available)
47 .SetFragmentationType(block_fragmentation)
38 .ToConstraintSpace(writing_mode); 48 .ToConstraintSpace(writing_mode);
39 } 49 }
40 50
41 typedef bool TestParamLayoutNG; 51 typedef bool TestParamLayoutNG;
42 class NGBlockLayoutAlgorithmTest 52 class NGBlockLayoutAlgorithmTest
43 : public ::testing::WithParamInterface<TestParamLayoutNG>, 53 : public ::testing::WithParamInterface<TestParamLayoutNG>,
44 public RenderingTest { 54 public RenderingTest {
45 public: 55 public:
46 NGBlockLayoutAlgorithmTest() { 56 NGBlockLayoutAlgorithmTest() {
47 RuntimeEnabledFeatures::setLayoutNGEnabled(true); 57 RuntimeEnabledFeatures::setLayoutNGEnabled(true);
(...skipping 2152 matching lines...) Expand 10 before | Expand all | Expand 10 after
2200 // Verify #clears-right block 2210 // Verify #clears-right block
2201 ASSERT_EQ(2UL, container_clear_fragment->Children().size()); 2211 ASSERT_EQ(2UL, container_clear_fragment->Children().size());
2202 auto* clears_right_fragment = 2212 auto* clears_right_fragment =
2203 toNGPhysicalBoxFragment(container_clear_fragment->Children()[1].get()); 2213 toNGPhysicalBoxFragment(container_clear_fragment->Children()[1].get());
2204 // 20 = right-float's block end offset (130 + 80) - 2214 // 20 = right-float's block end offset (130 + 80) -
2205 // container_clear->offsetTop() 190 2215 // container_clear->offsetTop() 190
2206 EXPECT_THAT(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)), 2216 EXPECT_THAT(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)),
2207 clears_right_fragment->Offset()); 2217 clears_right_fragment->Offset());
2208 } 2218 }
2209 2219
2220 // Tests that a block won't fragment if it doesn't reach the fragmentation line.
2221 TEST_F(NGBlockLayoutAlgorithmTest, NoFragmentation) {
2222 setBodyInnerHTML(R"HTML(
2223 <!DOCTYPE html>
2224 <style>
2225 #container {
2226 width: 150px;
2227 height: 200px;
2228 }
2229 </style>
2230 <div id='container'></div>
2231 )HTML");
2232
2233 LayoutUnit kFragmentainerSpaceAvailable(200);
2234
2235 NGBlockNode* node = new NGBlockNode(
2236 toLayoutBlockFlow(getLayoutObjectByElementId("container")));
2237 auto* space = ConstructConstraintSpace(
2238 kHorizontalTopBottom, TextDirection::kLtr,
2239 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
2240 kFragmentainerSpaceAvailable);
2241
2242 // We should only have one 150x200 fragment with no fragmentation.
2243 RefPtr<const NGPhysicalFragment> fragment =
2244 NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment();
2245 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(200)), fragment->Size());
2246 ASSERT_TRUE(fragment->BreakToken()->IsFinished());
2247 }
2248
2249 // Tests that a block will fragment if it reaches the fragmentation line.
2250 TEST_F(NGBlockLayoutAlgorithmTest, SimpleFragmentation) {
2251 setBodyInnerHTML(R"HTML(
2252 <!DOCTYPE html>
2253 <style>
2254 #container {
2255 width: 150px;
2256 height: 300px;
2257 }
2258 </style>
2259 <div id='container'></div>
2260 )HTML");
2261
2262 LayoutUnit kFragmentainerSpaceAvailable(200);
2263
2264 NGBlockNode* node = new NGBlockNode(
2265 toLayoutBlockFlow(getLayoutObjectByElementId("container")));
2266 auto* space = ConstructConstraintSpace(
2267 kHorizontalTopBottom, TextDirection::kLtr,
2268 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
2269 kFragmentainerSpaceAvailable);
2270
2271 RefPtr<const NGPhysicalFragment> fragment =
2272 NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment();
2273 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(200)), fragment->Size());
2274 ASSERT_FALSE(fragment->BreakToken()->IsFinished());
2275
2276 fragment = NGBlockLayoutAlgorithm(node, space,
2277 toNGBlockBreakToken(fragment->BreakToken()))
2278 .Layout()
2279 ->PhysicalFragment();
2280 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(100)), fragment->Size());
2281 ASSERT_TRUE(fragment->BreakToken()->IsFinished());
2282 }
2283
2284 // Tests that children inside the same block formatting context fragment when
2285 // reaching a fragmentation line.
2286 TEST_F(NGBlockLayoutAlgorithmTest, InnerChildrenFragmentation) {
2287 setBodyInnerHTML(R"HTML(
2288 <!DOCTYPE html>
2289 <style>
2290 #container {
2291 width: 150px;
2292 padding-top: 20px;
2293 }
2294 #child1 {
2295 height: 200px;
2296 margin-bottom: 20px;
2297 }
2298 #child2 {
2299 height: 100px;
2300 margin-top: 20px;
2301 }
2302 </style>
2303 <div id='container'>
2304 <div id='child1'></div>
2305 <div id='child2'></div>
2306 </div>
2307 )HTML");
2308
2309 LayoutUnit kFragmentainerSpaceAvailable(200);
2310
2311 NGBlockNode* node = new NGBlockNode(
2312 toLayoutBlockFlow(getLayoutObjectByElementId("container")));
2313 auto* space = ConstructConstraintSpace(
2314 kHorizontalTopBottom, TextDirection::kLtr,
2315 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
2316 kFragmentainerSpaceAvailable);
2317
2318 RefPtr<const NGPhysicalFragment> fragment =
2319 NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment();
2320 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(200)), fragment->Size());
2321 ASSERT_FALSE(fragment->BreakToken()->IsFinished());
2322
2323 FragmentChildIterator iterator(toNGPhysicalBoxFragment(fragment.get()));
2324 const NGPhysicalBoxFragment* child = iterator.NextChild();
2325 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(180)), child->Size());
2326 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)), child->Offset());
2327
2328 EXPECT_FALSE(iterator.NextChild());
2329
2330 fragment = NGBlockLayoutAlgorithm(node, space,
2331 toNGBlockBreakToken(fragment->BreakToken()))
2332 .Layout()
2333 ->PhysicalFragment();
2334 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(140)), fragment->Size());
2335 ASSERT_TRUE(fragment->BreakToken()->IsFinished());
2336
2337 iterator.SetParent(toNGPhysicalBoxFragment(fragment.get()));
2338 child = iterator.NextChild();
2339 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(20)), child->Size());
2340 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(0)), child->Offset());
2341
2342 child = iterator.NextChild();
2343 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(100)), child->Size());
2344 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(40)), child->Offset());
2345
2346 EXPECT_FALSE(iterator.NextChild());
2347 }
2348
2349 // Tests that children which establish new formatting contexts fragment
2350 // correctly.
2351 TEST_F(NGBlockLayoutAlgorithmTest,
2352 InnerFormattingContextChildrenFragmentation) {
2353 setBodyInnerHTML(R"HTML(
2354 <!DOCTYPE html>
2355 <style>
2356 #container {
2357 width: 150px;
2358 padding-top: 20px;
2359 }
2360 #child1 {
2361 height: 200px;
2362 margin-bottom: 20px;
2363 contain: paint;
2364 }
2365 #child2 {
2366 height: 100px;
2367 margin-top: 20px;
2368 contain: paint;
2369 }
2370 </style>
2371 <div id='container'>
2372 <div id='child1'></div>
2373 <div id='child2'></div>
2374 </div>
2375 )HTML");
2376
2377 LayoutUnit kFragmentainerSpaceAvailable(200);
2378
2379 NGBlockNode* node = new NGBlockNode(
2380 toLayoutBlockFlow(getLayoutObjectByElementId("container")));
2381 auto* space = ConstructConstraintSpace(
2382 kHorizontalTopBottom, TextDirection::kLtr,
2383 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
2384 kFragmentainerSpaceAvailable);
2385
2386 RefPtr<const NGPhysicalFragment> fragment =
2387 NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment();
2388 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(200)), fragment->Size());
2389 ASSERT_FALSE(fragment->BreakToken()->IsFinished());
2390
2391 FragmentChildIterator iterator(toNGPhysicalBoxFragment(fragment.get()));
2392 const NGPhysicalBoxFragment* child = iterator.NextChild();
2393 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(180)), child->Size());
2394 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)), child->Offset());
2395
2396 EXPECT_FALSE(iterator.NextChild());
2397
2398 fragment = NGBlockLayoutAlgorithm(node, space,
2399 toNGBlockBreakToken(fragment->BreakToken()))
2400 .Layout()
2401 ->PhysicalFragment();
2402 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(140)), fragment->Size());
2403 ASSERT_TRUE(fragment->BreakToken()->IsFinished());
2404
2405 iterator.SetParent(toNGPhysicalBoxFragment(fragment.get()));
2406 child = iterator.NextChild();
2407 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(20)), child->Size());
2408 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(0)), child->Offset());
2409
2410 child = iterator.NextChild();
2411 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(100)), child->Size());
2412 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(40)), child->Offset());
2413
2414 EXPECT_FALSE(iterator.NextChild());
2415 }
2416
2417 // Tests that children inside a block container will fragment if the container
2418 // doesn't reach the fragmentation line.
2419 TEST_F(NGBlockLayoutAlgorithmTest, InnerChildrenFragmentationSmallHeight) {
2420 setBodyInnerHTML(R"HTML(
2421 <!DOCTYPE html>
2422 <style>
2423 #container {
2424 width: 150px;
2425 padding-top: 20px;
2426 height: 50px;
2427 }
2428 #child1 {
2429 height: 200px;
2430 margin-bottom: 20px;
2431 }
2432 #child2 {
2433 height: 100px;
2434 margin-top: 20px;
2435 }
2436 </style>
2437 <div id='container'>
2438 <div id='child1'></div>
2439 <div id='child2'></div>
2440 </div>
2441 )HTML");
2442
2443 LayoutUnit kFragmentainerSpaceAvailable(200);
2444
2445 NGBlockNode* node = new NGBlockNode(
2446 toLayoutBlockFlow(getLayoutObjectByElementId("container")));
2447 auto* space = ConstructConstraintSpace(
2448 kHorizontalTopBottom, TextDirection::kLtr,
2449 NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
2450 kFragmentainerSpaceAvailable);
2451
2452 RefPtr<const NGPhysicalFragment> fragment =
2453 NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment();
2454 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(70)), fragment->Size());
2455 ASSERT_FALSE(fragment->BreakToken()->IsFinished());
2456
2457 FragmentChildIterator iterator(toNGPhysicalBoxFragment(fragment.get()));
2458 const NGPhysicalBoxFragment* child = iterator.NextChild();
2459 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(180)), child->Size());
2460 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(20)), child->Offset());
2461
2462 EXPECT_FALSE(iterator.NextChild());
2463
2464 fragment = NGBlockLayoutAlgorithm(node, space,
2465 toNGBlockBreakToken(fragment->BreakToken()))
2466 .Layout()
2467 ->PhysicalFragment();
2468 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(0)), fragment->Size());
2469 ASSERT_TRUE(fragment->BreakToken()->IsFinished());
2470
2471 iterator.SetParent(toNGPhysicalBoxFragment(fragment.get()));
2472 child = iterator.NextChild();
2473 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(20)), child->Size());
2474 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(0)), child->Offset());
2475
2476 child = iterator.NextChild();
2477 EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(100)), child->Size());
2478 EXPECT_EQ(NGPhysicalOffset(LayoutUnit(0), LayoutUnit(40)), child->Offset());
2479
2480 EXPECT_FALSE(iterator.NextChild());
2481 }
2482
2210 } // namespace 2483 } // namespace
2211 } // namespace blink 2484 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698