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

Unified 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, 10 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
index 8b3ba8b0eb83fbdab73bc81f24824a65454df3a9..530cd0ed48efd9c6fd28913a2c70468af3c36f24 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
@@ -26,15 +26,24 @@ namespace {
using testing::ElementsAre;
using testing::Pointee;
-NGConstraintSpace* ConstructConstraintSpace(NGWritingMode writing_mode,
- TextDirection direction,
- NGLogicalSize size,
- bool shrink_to_fit = false) {
+NGConstraintSpace* ConstructConstraintSpace(
+ NGWritingMode writing_mode,
+ TextDirection direction,
+ NGLogicalSize size,
+ bool shrink_to_fit = false,
+ LayoutUnit fragmentainer_space_available = LayoutUnit()) {
+ NGFragmentationType block_fragmentation =
+ fragmentainer_space_available != LayoutUnit()
+ ? NGFragmentationType::kFragmentColumn
+ : NGFragmentationType::kFragmentNone;
+
return NGConstraintSpaceBuilder(writing_mode)
.SetAvailableSize(size)
.SetPercentageResolutionSize(size)
.SetTextDirection(direction)
.SetIsShrinkToFit(shrink_to_fit)
+ .SetFragmentainerSpaceAvailable(fragmentainer_space_available)
+ .SetFragmentationType(block_fragmentation)
.ToConstraintSpace(writing_mode);
}
@@ -2096,5 +2105,425 @@ TEST_F(NGBlockLayoutAlgorithmTest, PositionEmptyBlocksInNewBfc) {
empty_block2->Offset());
}
+// Tests that a block child won't fragment if it doesn't reach the fragmentation
+// line.
+TEST_F(NGBlockLayoutAlgorithmTest, NoFragmentation) {
+ setBodyInnerHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #container {
+ width: 150px;
+ height: 200px;
+ }
+ </style>
+ <div id='container'></div>
+ )HTML");
+
+ LayoutUnit kFragmentainerSpaceAvailable(200);
+
+ NGBlockNode* node = new NGBlockNode(
+ toLayoutBlockFlow(getLayoutObjectByElementId("container")));
+ auto* space = ConstructConstraintSpace(
+ kHorizontalTopBottom, TextDirection::kLtr,
+ NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
+ kFragmentainerSpaceAvailable);
+
+ // We should only have one 150x200 fragment with no fragmentation.
+ RefPtr<const NGPhysicalFragment> fragment =
+ NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment();
+ EXPECT_EQ(LayoutUnit(150), fragment->Width());
Gleb Lanbin 2017/02/24 21:51:28 .nit use fragment->Size() EXPECT_EQ(fragment->Siz
ikilpatrick 2017/02/25 00:57:22 Done.
+ EXPECT_EQ(LayoutUnit(200), fragment->Height());
+ ASSERT_TRUE(fragment->BreakToken()->IsFinished());
+}
+
+// Tests that a block child with fragment if it reaches the fragmentation line.
+TEST_F(NGBlockLayoutAlgorithmTest, SimpleFragmentation) {
+ setBodyInnerHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #container {
+ width: 150px;
+ height: 300px;
+ }
+ </style>
+ <div id='container'></div>
+ )HTML");
+
+ LayoutUnit kFragmentainerSpaceAvailable(200);
+
+ NGBlockNode* node = new NGBlockNode(
+ toLayoutBlockFlow(getLayoutObjectByElementId("container")));
+ auto* space = ConstructConstraintSpace(
+ kHorizontalTopBottom, TextDirection::kLtr,
+ NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
+ kFragmentainerSpaceAvailable);
+
+ RefPtr<const NGPhysicalFragment> fragment =
+ NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment();
+ EXPECT_EQ(LayoutUnit(150), fragment->Width());
+ EXPECT_EQ(LayoutUnit(200), fragment->Height());
+ ASSERT_FALSE(fragment->BreakToken()->IsFinished());
+
+ fragment = NGBlockLayoutAlgorithm(node, space,
+ toNGBlockBreakToken(fragment->BreakToken()))
+ .Layout()
+ ->PhysicalFragment();
+ EXPECT_EQ(LayoutUnit(150), fragment->Width());
+ EXPECT_EQ(LayoutUnit(100), fragment->Height());
+ ASSERT_TRUE(fragment->BreakToken()->IsFinished());
+}
+
+// Tests that children inside the same block formatting context fragment when
+// reaching a fragmentation line.
+TEST_F(NGBlockLayoutAlgorithmTest, InnerChildrenFragmentation) {
+ setBodyInnerHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #container {
+ width: 150px;
+ padding-top: 20px;
+ }
+ #child1 {
+ height: 200px;
+ margin-bottom: 20px;
+ }
+ #child2 {
+ height: 100px;
+ margin-top: 20px;
+ }
+ </style>
+ <div id='container'>
+ <div id='child1'></div>
+ <div id='child2'></div>
+ </div>
+ )HTML");
+
+ LayoutUnit kFragmentainerSpaceAvailable(200);
+
+ NGBlockNode* node = new NGBlockNode(
+ toLayoutBlockFlow(getLayoutObjectByElementId("container")));
+ auto* space = ConstructConstraintSpace(
+ kHorizontalTopBottom, TextDirection::kLtr,
+ NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
+ kFragmentainerSpaceAvailable);
+
+ RefPtr<const NGPhysicalFragment> fragment =
+ NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment();
+ EXPECT_EQ(LayoutUnit(150), fragment->Width());
+ EXPECT_EQ(LayoutUnit(200), fragment->Height());
+ ASSERT_FALSE(fragment->BreakToken()->IsFinished());
+
+ FragmentChildIterator iterator(toNGPhysicalBoxFragment(fragment.get()));
+ const NGPhysicalBoxFragment* child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(150), child->Width());
+ EXPECT_EQ(LayoutUnit(180), child->Height());
+ EXPECT_EQ(LayoutUnit(0), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(20), child->TopOffset());
+
+ EXPECT_FALSE(iterator.NextChild());
+
+ fragment = NGBlockLayoutAlgorithm(node, space,
+ toNGBlockBreakToken(fragment->BreakToken()))
+ .Layout()
+ ->PhysicalFragment();
+ EXPECT_EQ(LayoutUnit(150), fragment->Width());
+ EXPECT_EQ(LayoutUnit(140), fragment->Height());
+ ASSERT_TRUE(fragment->BreakToken()->IsFinished());
+
+ iterator.SetParent(toNGPhysicalBoxFragment(fragment.get()));
+ child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(150), child->Width());
+ EXPECT_EQ(LayoutUnit(20), child->Height());
+ EXPECT_EQ(LayoutUnit(0), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(0), child->TopOffset());
+
+ child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(150), child->Width());
+ EXPECT_EQ(LayoutUnit(100), child->Height());
+ EXPECT_EQ(LayoutUnit(0), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(40), child->TopOffset());
+
+ EXPECT_FALSE(iterator.NextChild());
+}
+
+// Tests that children inside which establish new formatting contexts fragment
+// correctly.
+TEST_F(NGBlockLayoutAlgorithmTest,
+ InnerFormattingContextChildrenFragmentation) {
+ setBodyInnerHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #container {
+ width: 150px;
+ padding-top: 20px;
+ }
+ #child1 {
+ height: 200px;
+ margin-bottom: 20px;
+ contain: paint;
+ }
+ #child2 {
+ height: 100px;
+ margin-top: 20px;
+ contain: paint;
+ }
+ </style>
+ <div id='container'>
+ <div id='child1'></div>
+ <div id='child2'></div>
+ </div>
+ )HTML");
+
+ LayoutUnit kFragmentainerSpaceAvailable(200);
+
+ NGBlockNode* node = new NGBlockNode(
+ toLayoutBlockFlow(getLayoutObjectByElementId("container")));
+ auto* space = ConstructConstraintSpace(
+ kHorizontalTopBottom, TextDirection::kLtr,
+ NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
+ kFragmentainerSpaceAvailable);
+
+ RefPtr<const NGPhysicalFragment> fragment =
+ NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment();
+ EXPECT_EQ(LayoutUnit(150), fragment->Width());
+ EXPECT_EQ(LayoutUnit(200), fragment->Height());
+ ASSERT_FALSE(fragment->BreakToken()->IsFinished());
+
+ FragmentChildIterator iterator(toNGPhysicalBoxFragment(fragment.get()));
+ const NGPhysicalBoxFragment* child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(150), child->Width());
+ EXPECT_EQ(LayoutUnit(180), child->Height());
+ EXPECT_EQ(LayoutUnit(0), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(20), child->TopOffset());
+
+ EXPECT_FALSE(iterator.NextChild());
+
+ fragment = NGBlockLayoutAlgorithm(node, space,
+ toNGBlockBreakToken(fragment->BreakToken()))
+ .Layout()
+ ->PhysicalFragment();
+ EXPECT_EQ(LayoutUnit(150), fragment->Width());
+ EXPECT_EQ(LayoutUnit(140), fragment->Height());
+ ASSERT_TRUE(fragment->BreakToken()->IsFinished());
+
+ iterator.SetParent(toNGPhysicalBoxFragment(fragment.get()));
+ child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(150), child->Width());
+ EXPECT_EQ(LayoutUnit(20), child->Height());
+ EXPECT_EQ(LayoutUnit(0), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(0), child->TopOffset());
+
+ child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(150), child->Width());
+ EXPECT_EQ(LayoutUnit(100), child->Height());
+ EXPECT_EQ(LayoutUnit(0), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(40), child->TopOffset());
+
+ EXPECT_FALSE(iterator.NextChild());
+}
+
+// Tests that children inside which establish new formatting contexts fragment
+// correctly.
+TEST_F(NGBlockLayoutAlgorithmTest, InnerChildrenFragmentationSmallHeight) {
+ setBodyInnerHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #container {
+ width: 150px;
+ padding-top: 20px;
+ height: 50px;
+ }
+ #child1 {
+ height: 200px;
+ margin-bottom: 20px;
+ }
+ #child2 {
+ height: 100px;
+ margin-top: 20px;
+ }
+ </style>
+ <div id='container'>
+ <div id='child1'></div>
+ <div id='child2'></div>
+ </div>
+ )HTML");
+
+ LayoutUnit kFragmentainerSpaceAvailable(200);
+
+ NGBlockNode* node = new NGBlockNode(
+ toLayoutBlockFlow(getLayoutObjectByElementId("container")));
+ auto* space = ConstructConstraintSpace(
+ kHorizontalTopBottom, TextDirection::kLtr,
+ NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
+ kFragmentainerSpaceAvailable);
+
+ RefPtr<const NGPhysicalFragment> fragment =
+ NGBlockLayoutAlgorithm(node, space).Layout()->PhysicalFragment();
+ EXPECT_EQ(LayoutUnit(150), fragment->Width());
+ EXPECT_EQ(LayoutUnit(70), fragment->Height());
+ ASSERT_FALSE(fragment->BreakToken()->IsFinished());
+
+ FragmentChildIterator iterator(toNGPhysicalBoxFragment(fragment.get()));
+ const NGPhysicalBoxFragment* child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(150), child->Width());
+ EXPECT_EQ(LayoutUnit(180), child->Height());
+ EXPECT_EQ(LayoutUnit(0), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(20), child->TopOffset());
+
+ EXPECT_FALSE(iterator.NextChild());
+
+ fragment = NGBlockLayoutAlgorithm(node, space,
+ toNGBlockBreakToken(fragment->BreakToken()))
+ .Layout()
+ ->PhysicalFragment();
+ EXPECT_EQ(LayoutUnit(150), fragment->Width());
+ EXPECT_EQ(LayoutUnit(0), fragment->Height());
+ ASSERT_TRUE(fragment->BreakToken()->IsFinished());
+
+ iterator.SetParent(toNGPhysicalBoxFragment(fragment.get()));
+ child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(150), child->Width());
+ EXPECT_EQ(LayoutUnit(20), child->Height());
+ EXPECT_EQ(LayoutUnit(0), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(0), child->TopOffset());
+
+ child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(150), child->Width());
+ EXPECT_EQ(LayoutUnit(100), child->Height());
+ EXPECT_EQ(LayoutUnit(0), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(40), child->TopOffset());
+
+ EXPECT_FALSE(iterator.NextChild());
+}
+
+/*TEST_F(NGBlockLayoutAlgorithmTest, ParallelFlowFragmentation) {
Gleb Lanbin 2017/02/24 21:51:28 use DISABLED_ prefix and TODO, i.e. DISABLED_Paral
ikilpatrick 2017/02/25 00:57:22 Blah sorry, removed, this was from an older patch,
+ setBodyInnerHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #container {
+ width: 150px;
+ }
+ #float_left {
+ float: left;
+ width: 20px;
+ height: 300px;
+ }
+ #float_right {
+ float: right;
+ width: 50px;
+ height: 500px;
+ }
+ #in_flow {
+ height: 550px;
+ }
+ </style>
+ <div id='container'>
+ <div id='float_left'></div>
+ <div id='float_right'></div>
+ <div id='in_flow'></div>
+ </div>
+ )HTML");
+
+ LayoutUnit kFragmentainerSpaceAvailable(200);
+
+ NGBlockNode* node = new NGBlockNode(toLayoutBlockFlow(
+ document().getElementById("container")->layoutObject()));
+ auto* space = ConstructConstraintSpace(
+ kHorizontalTopBottom, TextDirection::kLtr,
+ NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false,
+ kFragmentainerSpaceAvailable);
+
+ // The first fragment should have ...
+ RefPtr<const NGPhysicalFragment> fragment =
+ NGBlockLayoutAlgorithm(node, space).Layout();
+ EXPECT_EQ(LayoutUnit(150), fragment->Width());
+ EXPECT_EQ(LayoutUnit(200), fragment->Height());
+ ASSERT_FALSE(fragment->BreakToken()->IsFinished());
+
+ FragmentChildIterator iterator(toNGPhysicalBoxFragment(fragment.get()));
+
+ // #float_left child.
+ const NGPhysicalBoxFragment* child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(20), child->Width());
+ EXPECT_EQ(LayoutUnit(200), child->Height());
+ EXPECT_EQ(LayoutUnit(0), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(0), child->TopOffset());
+
+ // #float_right child.
+ child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(50), child->Width());
+ EXPECT_EQ(LayoutUnit(200), child->Height());
+ EXPECT_EQ(LayoutUnit(100), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(0), child->TopOffset());
+
+ // #in_flow child.
+ child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(150), child->Width());
+ EXPECT_EQ(LayoutUnit(200), child->Height());
+ EXPECT_EQ(LayoutUnit(0), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(0), child->TopOffset());
+
+ EXPECT_FALSE(iterator.NextChild());
+
+ fragment = NGBlockLayoutAlgorithm(node, space,
+ toNGBlockBreakToken(fragment->BreakToken()))
+ .Layout();
+ EXPECT_EQ(LayoutUnit(150), fragment->Width());
+ EXPECT_EQ(LayoutUnit(200), fragment->Height());
+ ASSERT_FALSE(fragment->BreakToken()->IsFinished());
+
+ iterator.SetParent(toNGPhysicalBoxFragment(fragment.get()));
+
+ // #float_left child.
+ child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(20), child->Width());
+ EXPECT_EQ(LayoutUnit(100), child->Height());
+ EXPECT_EQ(LayoutUnit(0), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(0), child->TopOffset());
+ EXPECT_TRUE(child->BreakToken()->IsFinished());
+
+ // #float_right child.
+ child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(50), child->Width());
+ EXPECT_EQ(LayoutUnit(200), child->Height());
+ EXPECT_EQ(LayoutUnit(100), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(0), child->TopOffset());
+
+ // #in_flow child.
+ child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(150), child->Width());
+ EXPECT_EQ(LayoutUnit(200), child->Height());
+ EXPECT_EQ(LayoutUnit(0), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(0), child->TopOffset());
+
+ EXPECT_FALSE(iterator.NextChild());
+
+ fragment = NGBlockLayoutAlgorithm(node, space,
+ toNGBlockBreakToken(fragment->BreakToken()))
+ .Layout();
+
+ EXPECT_EQ(LayoutUnit(150), fragment->Width());
+ EXPECT_EQ(LayoutUnit(150), fragment->Height());
+ ASSERT_FALSE(fragment->BreakToken()->IsFinished());
+
+ iterator.SetParent(toNGPhysicalBoxFragment(fragment.get()));
+
+ // #float_right child.
+ child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(50), child->Width());
+ EXPECT_EQ(LayoutUnit(100), child->Height());
+ EXPECT_EQ(LayoutUnit(100), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(0), child->TopOffset());
+
+ // #in_flow child.
+ child = iterator.NextChild();
+ EXPECT_EQ(LayoutUnit(150), child->Width());
+ EXPECT_EQ(LayoutUnit(150), child->Height());
+ EXPECT_EQ(LayoutUnit(0), child->LeftOffset());
+ EXPECT_EQ(LayoutUnit(0), child->TopOffset());
+
+ EXPECT_FALSE(iterator.NextChild());
+}*/
+
} // namespace
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698