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

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

Issue 2641253002: Rewrite LayoutNG margin collapsing/floats unit tests (Closed)
Patch Set: git rebase-update + more tests Created 3 years, 11 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
« no previous file with comments | « no previous file | third_party/WebKit/Source/core/layout/ng/ng_units.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 d5189a57786737bd962e48ae20bd62b8a8b97a9b..f2e63e3cacd548e44e460084218d904f687e7ee0 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
@@ -4,20 +4,28 @@
#include "core/layout/ng/ng_block_layout_algorithm.h"
+#include "core/dom/NodeComputedStyle.h"
+#include "core/dom/TagCollection.h"
+#include "core/layout/ng/layout_ng_block_flow.h"
#include "core/layout/ng/ng_block_node.h"
#include "core/layout/ng/ng_constraint_space.h"
#include "core/layout/ng/ng_constraint_space_builder.h"
+#include "core/layout/ng/ng_floating_object.h"
#include "core/layout/ng/ng_length_utils.h"
+#include "core/layout/LayoutTestHelper.h"
#include "core/layout/ng/ng_physical_box_fragment.h"
#include "core/layout/ng/ng_physical_fragment.h"
#include "core/layout/ng/ng_units.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "core/style/ComputedStyle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
namespace {
+using testing::ElementsAre;
+using testing::Pointee;
+
NGConstraintSpace* ConstructConstraintSpace(NGWritingMode writing_mode,
TextDirection direction,
NGLogicalSize size,
@@ -56,6 +64,17 @@ class NGBlockLayoutAlgorithmTest
return toNGPhysicalBoxFragment(fragment);
}
+ std::pair<NGPhysicalBoxFragment*, NGConstraintSpace*>
+ RunBlockLayoutAlgorithmForElement(Element* element) {
+ LayoutNGBlockFlow* block_flow =
+ toLayoutNGBlockFlow(element->layoutObject());
+ NGConstraintSpace* space =
+ NGConstraintSpace::CreateFromLayoutObject(*block_flow);
+ NGPhysicalBoxFragment* fragment = RunBlockLayoutAlgorithm(
+ space, new NGBlockNode(element->layoutObject()->slowFirstChild()));
+ return std::make_pair(fragment, space);
+ }
+
MinAndMaxContentSizes RunComputeMinAndMax(NGBlockNode* first_child) {
// The constraint space is not used for min/max computation, but we need
// it to create the algorithm.
@@ -167,237 +186,349 @@ TEST_F(NGBlockLayoutAlgorithmTest, LayoutBlockChildrenWithWritingMode) {
// Verifies the collapsing margins case for the next pair:
// - top margin of a box and top margin of its first in-flow child.
-//
-// Test case's HTML representation:
-// <div style="margin-top: 20px; height: 50px;"> <!-- DIV1 -->
-// <div style="margin-top: 10px"></div> <!-- DIV2 -->
-// </div>
-//
-// Expected:
-// - Empty margin strut of the fragment that establishes new formatting context
-// - Margins are collapsed resulting a single margin 20px = max(20px, 10px)
-// - The top offset of DIV2 == 20px
-TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase1) {
- const int kHeight = 50;
- const int kDiv1MarginTop = 20;
- const int kDiv2MarginTop = 10;
-
- // DIV1
- RefPtr<ComputedStyle> div1_style = ComputedStyle::create();
- div1_style->setHeight(Length(kHeight, Fixed));
- div1_style->setMarginTop(Length(kDiv1MarginTop, Fixed));
- NGBlockNode* div1 = new NGBlockNode(div1_style.get());
-
- // DIV2
- RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
- div2_style->setMarginTop(Length(kDiv2MarginTop, Fixed));
- NGBlockNode* div2 = new NGBlockNode(div2_style.get());
-
- div1->SetFirstChild(div2);
-
- auto* space =
- NGConstraintSpaceBuilder(kHorizontalTopBottom)
- .SetAvailableSize(NGLogicalSize(LayoutUnit(100), NGSizeIndefinite))
- .SetPercentageResolutionSize(
- NGLogicalSize(LayoutUnit(100), NGSizeIndefinite))
- .SetTextDirection(TextDirection::kLtr)
- .SetIsNewFormattingContext(true)
- .ToConstraintSpace();
- NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1);
-
- EXPECT_TRUE(frag->MarginStrut().IsEmpty());
- ASSERT_EQ(frag->Children().size(), 1UL);
- const NGPhysicalBoxFragment* div2_fragment =
- static_cast<const NGPhysicalBoxFragment*>(frag->Children()[0].get());
- EXPECT_EQ(NGDeprecatedMarginStrut({LayoutUnit(kDiv2MarginTop)}),
- div2_fragment->MarginStrut());
- EXPECT_EQ(kDiv1MarginTop, div2_fragment->TopOffset());
+// Verifies that floats are positioned at the top of the first child that can
+// determine its position after margins collapsed.
+// TODO(glebl): Enable with new the float/margins collapsing algorithm.
+TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_CollapsingMarginsCase1WithFloats) {
+ setBodyInnerHTML(
+ "<style>"
+ " #container {"
+ " height: 200px;"
+ " width: 200px;"
+ " margin-top: 10px;"
+ " padding: 0 7px;"
+ " background-color: red;"
+ " }"
+ " #first-child {"
+ " margin-top: 20px;"
+ " height: 10px;"
+ " background-color: blue;"
+ " }"
+ " #float-child-left {"
+ " float: left;"
+ " height: 10px;"
+ " width: 10px;"
+ " padding: 10px;"
+ " margin: 10px;"
+ " background-color: green;"
+ " }"
+ " #float-child-right {"
+ " float: right;"
+ " height: 30px;"
+ " width: 30px;"
+ " background-color: pink;"
+ " }"
+ "</style>"
+ "<div id='container'>"
+ " <div id='float-child-left'></div>"
+ " <div id='float-child-right'></div>"
+ " <div id='first-child'></div>"
+ "</div>");
+
+ // ** Run LayoutNG algorithm **
+ NGConstraintSpace* space;
+ NGPhysicalBoxFragment* fragment;
+ std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement(
+ document().getElementsByTagName("html")->item(0));
+ ASSERT_EQ(fragment->Children().size(), 1UL);
+ auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]);
+ // 20 = max(first child's margin top, containers's margin top)
+ int body_top_offset = 20;
+ EXPECT_THAT(LayoutUnit(body_top_offset), body_fragment->TopOffset());
+ // 8 = body's margin
+ int body_left_offset = 8;
+ EXPECT_THAT(LayoutUnit(body_left_offset), body_fragment->LeftOffset());
+ ASSERT_EQ(1UL, body_fragment->Children().size());
+ auto* container_fragment =
+ toNGPhysicalBoxFragment(body_fragment->Children()[0]);
+ // 0 = collapsed with body's margin
+ EXPECT_THAT(LayoutUnit(0), container_fragment->TopOffset());
+ ASSERT_EQ(1UL, container_fragment->Children().size());
+ auto* first_child_fragment =
+ toNGPhysicalBoxFragment(container_fragment->Children()[0]);
+ // 0 = collapsed with container's margin
+ EXPECT_THAT(LayoutUnit(0), first_child_fragment->TopOffset());
+
+ // ** Verify layout tree **
+ Element* first_child = document().getElementById("first-child");
+ int first_child_block_offset = body_top_offset;
+ EXPECT_EQ(first_child_block_offset, first_child->offsetTop());
+
+ // The left float to be positioned at first-child's top.
ikilpatrick 2017/01/24 22:05:37 So I was more pushing back on the wording here, it
Gleb Lanbin 2017/01/24 22:30:43 Done.
+ Element* float_child_left = document().getElementById("float-child-left");
+ // first_child_block_offset + 10(float-child-left's margin)
+ int float_child_left_block_offset = first_child_block_offset + 10;
+ EXPECT_EQ(float_child_left_block_offset, float_child_left->offsetTop());
+
+ // The right float to be positioned at first-child's top.
ikilpatrick 2017/01/24 22:05:37 and here.
Gleb Lanbin 2017/01/24 22:30:43 Done.
+ Element* float_child_right = document().getElementById("float-child-right");
+ // Should be equal to first_child_block_offset
+ int float_child_right_block_offset = first_child_block_offset;
+ EXPECT_EQ(float_child_right_block_offset, float_child_right->offsetTop());
+
+ // ** Verify exclusions **
+ // float-child-left's height(10) + padding(2x10) + margin(2x10) = 50px
+ NGLogicalSize exclusion1_size = {LayoutUnit(50), LayoutUnit(50)};
+ // float-child-left's inline offset
+ // 15 = body's margin(8) + container's inline padding(7)
+ NGLogicalOffset exclusion1_offset = {LayoutUnit(15),
+ LayoutUnit(first_child_block_offset)};
+ NGLogicalRect exclusion1_rect = {exclusion1_offset, exclusion1_size};
+ NGExclusion expected_exclusion1 = {exclusion1_rect, NGExclusion::kFloatLeft};
+
+ NGLogicalSize exclusion2_size = {LayoutUnit(30), LayoutUnit(30)};
+ // float-child-right's inline offset
+ // right_float_offset = 200 container's width - right float width 30 = 170
+ // 185 = body's margin(8) + right_float_offset(170) + container's padding(7)
+ NGLogicalOffset exclusion2_offset = {LayoutUnit(185),
+ LayoutUnit(first_child_block_offset)};
+ NGLogicalRect exclusion2_rect = {exclusion2_offset, exclusion2_size};
+ NGExclusion expected_exclusion2 = {exclusion2_rect, NGExclusion::kFloatRight};
+
+ EXPECT_THAT(space->Exclusions()->storage,
+ (ElementsAre(Pointee(expected_exclusion1),
+ Pointee(expected_exclusion2))));
}
// Verifies the collapsing margins case for the next pair:
// - bottom margin of box and top margin of its next in-flow following sibling.
-//
-// Test case's HTML representation:
-// <div style="margin-bottom: 20px; height: 50px;"> <!-- DIV1 -->
-// <div style="margin-bottom: -15px"></div> <!-- DIV2 -->
-// <div></div> <!-- DIV3 -->
-// </div>
-// <div></div> <!-- DIV4 -->
-// <div style="margin-top: 10px; height: 50px;"> <!-- DIV5 -->
-// <div></div> <!-- DIV6 -->
-// <div style="margin-top: -30px"></div> <!-- DIV7 -->
-// </div>
-//
-// Expected:
-// Margins are collapsed resulting an overlap
-// -10px = max(20px, 10px) - max(abs(-15px), abs(-30px))
-// between DIV2 and DIV3. Zero-height blocks are ignored.
-TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase2) {
- const int kHeight = 50;
- const int kDiv1MarginBottom = 20;
- const int kDiv2MarginBottom = -15;
- const int kDiv5MarginTop = 10;
- const int kDiv7MarginTop = -30;
- const int kExpectedCollapsedMargin = -10;
-
- // DIV1
- RefPtr<ComputedStyle> div1_style = ComputedStyle::create();
- div1_style->setHeight(Length(kHeight, Fixed));
- div1_style->setMarginBottom(Length(kDiv1MarginBottom, Fixed));
- NGBlockNode* div1 = new NGBlockNode(div1_style.get());
-
- // DIV2
- RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
- div2_style->setMarginBottom(Length(kDiv2MarginBottom, Fixed));
- NGBlockNode* div2 = new NGBlockNode(div2_style.get());
-
- // Empty DIVs: DIV3, DIV4, DIV6
- NGBlockNode* div3 = new NGBlockNode(ComputedStyle::create().get());
- NGBlockNode* div4 = new NGBlockNode(ComputedStyle::create().get());
- NGBlockNode* div6 = new NGBlockNode(ComputedStyle::create().get());
-
- // DIV5
- RefPtr<ComputedStyle> div5_style = ComputedStyle::create();
- div5_style->setHeight(Length(kHeight, Fixed));
- div5_style->setMarginTop(Length(kDiv5MarginTop, Fixed));
- NGBlockNode* div5 = new NGBlockNode(div5_style.get());
-
- // DIV7
- RefPtr<ComputedStyle> div7_style = ComputedStyle::create();
- div7_style->setMarginTop(Length(kDiv7MarginTop, Fixed));
- NGBlockNode* div7 = new NGBlockNode(div7_style.get());
-
- div1->SetFirstChild(div2);
- div2->SetNextSibling(div3);
- div1->SetNextSibling(div4);
- div4->SetNextSibling(div5);
- div5->SetFirstChild(div6);
- div6->SetNextSibling(div7);
-
- auto* space = ConstructConstraintSpace(
- kHorizontalTopBottom, TextDirection::kLtr,
- NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
- NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1);
-
- ASSERT_EQ(frag->Children().size(), 3UL);
-
- // DIV1
- const NGPhysicalFragment* child = frag->Children()[0];
- EXPECT_EQ(kHeight, child->Height());
- EXPECT_EQ(0, child->TopOffset());
-
- // DIV5
- child = frag->Children()[2];
- EXPECT_EQ(kHeight, child->Height());
- EXPECT_EQ(kHeight + kExpectedCollapsedMargin, child->TopOffset());
+// - top and bottom margins of a box that does not establish a new block
+// formatting context and that has zero computed 'min-height', zero or 'auto'
+// computed 'height', and no in-flow children
+// TODO(glebl): Enable with new the float/margins collapsing algorithm.
+TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_CollapsingMarginsCase2WithFloats) {
+ setBodyInnerHTML(
+ "<style>"
+ "#first-child {"
+ " background-color: red;"
+ " height: 50px;"
+ " margin-bottom: 20px;"
+ "}"
+ "#float-between-empties {"
+ " background-color: green;"
+ " float: left;"
+ " height: 30px;"
+ " width: 30px;"
+ "}"
+ "#float-between-nonempties {"
+ " background-color: lightgreen;"
+ " float: left;"
+ " height: 40px;"
+ " width: 40px;"
+ "}"
+ "#float-top-align {"
+ " background-color: seagreen;"
+ " float: left;"
+ " height: 50px;"
+ " width: 50px;"
+ "}"
+ "#second-child {"
+ " background-color: blue;"
+ " height: 50px;"
+ " margin-top: 10px;"
+ "}"
+ "</style>"
+ "<div id='first-child'>"
+ " <div id='empty1' style='margin-bottom: -15px'></div>"
+ " <div id='float-between-empties'></div>"
+ " <div id='empty2'></div>"
+ "</div>"
+ "<div id='float-between-nonempties'></div>"
+ "<div id='second-child'>"
+ " <div id='float-top-align'></div>"
+ " <div id='empty3'></div>"
+ " <div id='empty4' style='margin-top: -30px'></div>"
+ "</div>"
+ "<div id='empty5'></div>");
+
+ // ** Run LayoutNG algorithm **
+ NGConstraintSpace* space;
+ NGPhysicalBoxFragment* fragment;
+ std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement(
+ document().getElementsByTagName("html")->item(0));
+
+ auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]);
+ // -7 = empty1's margin(-15) + body's margin(8)
+ int body_top_offset = -7;
+ EXPECT_THAT(LayoutUnit(body_top_offset), body_fragment->TopOffset());
+ int body_left_offset = 8;
+ EXPECT_THAT(LayoutUnit(body_top_offset), body_fragment->TopOffset());
+ ASSERT_EQ(3UL, body_fragment->Children().size());
+
+ auto* first_child_fragment =
+ toNGPhysicalBoxFragment(body_fragment->Children()[0]);
+ EXPECT_THAT(LayoutUnit(), first_child_fragment->TopOffset());
+
+ auto* second_child_fragment =
+ toNGPhysicalBoxFragment(body_fragment->Children()[1]);
+ // 40 = first_child's height(50) - margin's collapsing result(10)
+ int second_child_block_offset = 40;
+ EXPECT_THAT(LayoutUnit(second_child_block_offset),
+ second_child_fragment->TopOffset());
+
+ auto* empty5_fragment = toNGPhysicalBoxFragment(body_fragment->Children()[2]);
+ // 90 = first_child's height(50) + collapsed margins(-10) +
+ // second child's height(50)
+ int empty5_fragment_block_offset = 90;
+ EXPECT_THAT(LayoutUnit(empty5_fragment_block_offset),
+ empty5_fragment->TopOffset());
+
+ ASSERT_EQ(3UL, body_fragment->PositionedFloats().size());
+ auto float_nonempties_fragment =
+ body_fragment->PositionedFloats().at(1)->fragment;
+ // 70 = first_child's height(50) + first child's margin-bottom(20)
+ EXPECT_THAT(LayoutUnit(70), float_nonempties_fragment->TopOffset());
+ EXPECT_THAT(LayoutUnit(0), float_nonempties_fragment->LeftOffset());
+
+ // ** Verify layout tree **
+ Element* first_child = document().getElementById("first-child");
+ // -7 = body_top_offset
+ EXPECT_EQ(body_top_offset, first_child->offsetTop());
+
+ NGLogicalSize float_empties_exclusion_size = {LayoutUnit(30), LayoutUnit(30)};
+ NGLogicalOffset float_empties_exclusion_offset = {
+ LayoutUnit(body_left_offset), LayoutUnit(body_top_offset)};
+ NGLogicalRect float_empties_exclusion_rect = {float_empties_exclusion_offset,
+ float_empties_exclusion_size};
+ NGExclusion float_empties_exclusion = {float_empties_exclusion_rect,
+ NGExclusion::kFloatLeft};
+
+ NGLogicalSize float_nonempties_exclusion_size = {LayoutUnit(40),
+ LayoutUnit(40)};
+ // 63 = first_child_margin_strut(20) + first-child's height(50) +
+ // body_top_offset(-7)
+ NGLogicalOffset float_nonempties_exclusion_offset = {
+ LayoutUnit(body_left_offset), LayoutUnit(63)};
+ NGLogicalRect float_nonempties_exclusion_rect = {
+ float_nonempties_exclusion_offset, float_nonempties_exclusion_size};
+ NGExclusion float_nonempties_exclusion = {float_nonempties_exclusion_rect,
+ NGExclusion::kFloatLeft};
+
+ NGLogicalSize float_top_align_exclusion_size = {LayoutUnit(50),
+ LayoutUnit(50)};
+ // 63 = float_nonempties_exclusion_offset because of the top edge alignment
+ // rule.
+ // 48 = body's margin + float_nonempties_exclusion_size
+ NGLogicalOffset float_top_align_exclusion_offset = {LayoutUnit(48),
+ LayoutUnit(63)};
+ NGLogicalRect float_top_align_exclusion_rect = {
+ float_top_align_exclusion_offset, float_top_align_exclusion_size};
+ NGExclusion float_top_align_exclusion = {float_top_align_exclusion_rect,
+ NGExclusion::kFloatLeft};
+
+ EXPECT_THAT(space->Exclusions()->storage,
+ (ElementsAre(Pointee(float_empties_exclusion),
+ Pointee(float_nonempties_exclusion),
+ Pointee(float_top_align_exclusion))));
}
// Verifies the collapsing margins case for the next pair:
// - bottom margin of a last in-flow child and bottom margin of its parent if
// the parent has 'auto' computed height
-//
-// Test case's HTML representation:
-// <div style="margin-bottom: 20px; height: 50px;"> <!-- DIV1 -->
-// <div style="margin-bottom: 200px; height: 50px;"/> <!-- DIV2 -->
-// </div>
-//
-// Expected:
-// 1) Margins are collapsed with the result = std::max(20, 200)
-// if DIV1.height == auto
-// 2) Margins are NOT collapsed if DIV1.height != auto
-TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase3) {
- const int kHeight = 50;
- const int kDiv1MarginBottom = 20;
- const int kDiv2MarginBottom = 200;
-
- // DIV1
- RefPtr<ComputedStyle> div1_style = ComputedStyle::create();
- div1_style->setMarginBottom(Length(kDiv1MarginBottom, Fixed));
- NGBlockNode* div1 = new NGBlockNode(div1_style.get());
-
- // DIV2
- RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
- div2_style->setHeight(Length(kHeight, Fixed));
- div2_style->setMarginBottom(Length(kDiv2MarginBottom, Fixed));
- NGBlockNode* div2 = new NGBlockNode(div2_style.get());
-
- div1->SetFirstChild(div2);
-
- auto* space = ConstructConstraintSpace(
- kHorizontalTopBottom, TextDirection::kLtr,
- NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
- NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1);
-
- // Verify that margins are collapsed.
- EXPECT_EQ(
- NGDeprecatedMarginStrut({LayoutUnit(0), LayoutUnit(kDiv2MarginBottom)}),
- frag->MarginStrut());
-
- // Verify that margins are NOT collapsed.
- div1_style->setHeight(Length(kHeight, Fixed));
- frag = RunBlockLayoutAlgorithm(space, div1);
- EXPECT_EQ(
- NGDeprecatedMarginStrut({LayoutUnit(0), LayoutUnit(kDiv1MarginBottom)}),
- frag->MarginStrut());
+// TODO(glebl): Enable with new the float/margins collapsing algorithm.
+TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_CollapsingMarginsCase3) {
+ setBodyInnerHTML(
+ "<style>"
+ " #container {"
+ " margin-bottom: 20px;"
+ " }"
+ " #child {"
+ " margin-bottom: 200px;"
+ " height: 50px;"
+ " }"
+ "</style>"
+ "<div id='container'>"
+ " <div id='child'></div>"
+ "</div>");
+
+ const NGPhysicalBoxFragment* body_fragment;
+ const NGPhysicalBoxFragment* container_fragment;
+ const NGPhysicalBoxFragment* child_fragment;
+ const NGPhysicalBoxFragment* fragment;
+ auto run_test = [&](const Length& container_height) {
+ Element* container = document().getElementById("container");
+ container->mutableComputedStyle()->setHeight(container_height);
+ std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement(
+ document().getElementsByTagName("html")->item(0));
+ ASSERT_EQ(1UL, fragment->Children().size());
+ body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]);
+ container_fragment = toNGPhysicalBoxFragment(body_fragment->Children()[0]);
+ ASSERT_EQ(1UL, container_fragment->Children().size());
+ child_fragment = toNGPhysicalBoxFragment(container_fragment->Children()[0]);
+ };
+
+ // height == auto
+ run_test(Length(Auto));
+ // Margins are collapsed with the result 200 = std::max(20, 200)
+ // The fragment size 258 == body's margin 8 + child's height 50 + 200
+ EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(258)), fragment->Size());
+ // EXPECT_EQ(NGMarginStrut({LayoutUnit(200)}),
+ // container_fragment->EndMarginStrut());
+
+ // height == fixed
+ run_test(Length(50, Fixed));
+ // Margins are not collapsed, so fragment still has margins == 20.
+ // The fragment size 78 == body's margin 8 + child's height 50 + 20
+ // EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(78)),
+ // fragment->Size());
+ // EXPECT_EQ(NGMarginStrut(), container_fragment->EndMarginStrut());
}
// Verifies that 2 adjoining margins are not collapsed if there is padding or
// border that separates them.
-//
-// Test case's HTML representation:
-// <div style="margin: 30px 0px; padding: 20px 0px;"> <!-- DIV1 -->
-// <div style="margin: 200px 0px; height: 50px;"/> <!-- DIV2 -->
-// </div>
-//
-// Expected:
-// Margins do NOT collapse if there is an interfering padding or border.
-TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase4) {
- const int kHeight = 50;
- const int kDiv1Margin = 30;
- const int kDiv1Padding = 20;
- const int kDiv2Margin = 200;
-
- // DIV1
- RefPtr<ComputedStyle> div1_style = ComputedStyle::create();
- div1_style->setMarginTop(Length(kDiv1Margin, Fixed));
- div1_style->setMarginBottom(Length(kDiv1Margin, Fixed));
- div1_style->setPaddingTop(Length(kDiv1Padding, Fixed));
- div1_style->setPaddingBottom(Length(kDiv1Padding, Fixed));
- NGBlockNode* div1 = new NGBlockNode(div1_style.get());
-
- // DIV2
- RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
- div2_style->setHeight(Length(kHeight, Fixed));
- div2_style->setMarginTop(Length(kDiv2Margin, Fixed));
- div2_style->setMarginBottom(Length(kDiv2Margin, Fixed));
- NGBlockNode* div2 = new NGBlockNode(div2_style.get());
-
- div1->SetFirstChild(div2);
-
- auto* space = ConstructConstraintSpace(
- kHorizontalTopBottom, TextDirection::kLtr,
- NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
- NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1);
-
- // Verify that margins do NOT collapse.
- frag = RunBlockLayoutAlgorithm(space, div1);
- EXPECT_EQ(NGDeprecatedMarginStrut(
- {LayoutUnit(kDiv1Margin), LayoutUnit(kDiv1Margin)}),
- frag->MarginStrut());
- ASSERT_EQ(frag->Children().size(), 1UL);
-
- EXPECT_EQ(NGDeprecatedMarginStrut(
- {LayoutUnit(kDiv2Margin), LayoutUnit(kDiv2Margin)}),
- static_cast<const NGPhysicalBoxFragment*>(frag->Children()[0].get())
- ->MarginStrut());
-
- // Reset padding and verify that margins DO collapse.
- div1_style->setPaddingTop(Length(0, Fixed));
- div1_style->setPaddingBottom(Length(0, Fixed));
- frag = RunBlockLayoutAlgorithm(space, div1);
- EXPECT_EQ(NGDeprecatedMarginStrut(
- {LayoutUnit(kDiv2Margin), LayoutUnit(kDiv2Margin)}),
- frag->MarginStrut());
+// TODO(glebl): Enable with new the float/margins collapsing algorithm.
+TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_CollapsingMarginsCase4) {
+ setBodyInnerHTML(
+ "<style>"
+ " #container {"
+ " margin: 30px 0px;"
+ " width: 200px;"
+ " }"
+ " #child {"
+ " margin: 200px 0px;"
+ " height: 50px;"
+ " background-color: blue;"
+ " }"
+ "</style>"
+ "<div id='container'>"
+ " <div id='child'></div>"
+ "</div>");
+
+ const NGPhysicalBoxFragment* body_fragment;
+ const NGPhysicalBoxFragment* container_fragment;
+ const NGPhysicalBoxFragment* child_fragment;
+ const NGPhysicalBoxFragment* fragment;
+ auto run_test = [&](const Length& container_padding_top) {
+ Element* container = document().getElementById("container");
+ container->mutableComputedStyle()->setPaddingTop(container_padding_top);
+ std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement(
+ document().getElementsByTagName("html")->item(0));
+ ASSERT_EQ(1UL, fragment->Children().size());
+ body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]);
+ container_fragment = toNGPhysicalBoxFragment(body_fragment->Children()[0]);
+ ASSERT_EQ(1UL, container_fragment->Children().size());
+ child_fragment = toNGPhysicalBoxFragment(container_fragment->Children()[0]);
+ };
+
+ // with padding
+ run_test(Length(20, Fixed));
+ // 500 = child's height 50 + 2xmargin 400 + paddint-top 20 +
+ // container's margin 30
+ EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(500)), fragment->Size());
+ // 30 = max(body's margin 8, container margin 30)
+ EXPECT_EQ(LayoutUnit(30), body_fragment->TopOffset());
+ // 220 = container's padding top 20 + child's margin
+ EXPECT_EQ(LayoutUnit(220), child_fragment->TopOffset());
+
+ // without padding
+ run_test(Length(0, Fixed));
+ // 450 = 2xmax(body's margin 8, container's margin 30, child's margin 200) +
+ // child's height 50
+ EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(450)), fragment->Size());
+ // 200 = (body's margin 8, container's margin 30, child's margin 200)
+ EXPECT_EQ(LayoutUnit(200), body_fragment->TopOffset());
+ // 0 = collapsed margins
+ EXPECT_EQ(LayoutUnit(0), child_fragment->TopOffset());
}
// Verifies that margins of 2 adjoining blocks with different writing modes
@@ -632,175 +763,404 @@ TEST_F(NGBlockLayoutAlgorithmTest, AutoMargin) {
EXPECT_EQ(LayoutUnit(0), child->TopOffset());
}
-// Verifies that 3 Left/Right float fragments and one regular block fragment
-// are correctly positioned by the algorithm.
-//
-// Test case's HTML representation:
-// <div id="parent" style="width: 200px; height: 200px;">
-// <div style="float:left; width: 30px; height: 30px;
-// margin-top: 10px;"/> <!-- DIV1 -->
-// <div style="width: 30px; height: 30px;"/> <!-- DIV2 -->
-// <div style="float:right; width: 50px; height: 50px;"/> <!-- DIV3 -->
-// <div style="float:left; width: 120px; height: 120px;
-// margin-left: 30px;"/> <!-- DIV4 -->
-// </div>
-//
-// Expected:
-// - Left float(DIV1) is positioned at the left.
-// - Regular block (DIV2) is positioned behind DIV1.
-// - Right float(DIV3) is positioned at the right below DIV2
-// - Left float(DIV4) is positioned at the left below DIV3.
-TEST_F(NGBlockLayoutAlgorithmTest, PositionFloatFragments) {
- const int kParentLeftPadding = 10;
- const int kDiv1TopMargin = 10;
- const int kParentSize = 200;
- const int kDiv1Size = 30;
- const int kDiv2Size = 30;
- const int kDiv3Size = 50;
- const int kDiv4Size = kParentSize - kDiv3Size;
- const int kDiv4LeftMargin = kDiv1Size;
-
- style_->setHeight(Length(kParentSize, Fixed));
- style_->setWidth(Length(kParentSize, Fixed));
- style_->setPaddingLeft(Length(kParentLeftPadding, Fixed));
-
- // DIV1
- RefPtr<ComputedStyle> div1_style = ComputedStyle::create();
- div1_style->setWidth(Length(kDiv1Size, Fixed));
- div1_style->setHeight(Length(kDiv1Size, Fixed));
- div1_style->setFloating(EFloat::kLeft);
- div1_style->setMarginTop(Length(kDiv1TopMargin, Fixed));
- NGBlockNode* div1 = new NGBlockNode(div1_style.get());
-
- // DIV2
- RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
- div2_style->setWidth(Length(kDiv2Size, Fixed));
- div2_style->setHeight(Length(kDiv2Size, Fixed));
- NGBlockNode* div2 = new NGBlockNode(div2_style.get());
-
- // DIV3
- RefPtr<ComputedStyle> div3_style = ComputedStyle::create();
- div3_style->setWidth(Length(kDiv3Size, Fixed));
- div3_style->setHeight(Length(kDiv3Size, Fixed));
- div3_style->setFloating(EFloat::kRight);
- NGBlockNode* div3 = new NGBlockNode(div3_style.get());
-
- // DIV4
- RefPtr<ComputedStyle> div4_style = ComputedStyle::create();
- div4_style->setWidth(Length(kDiv4Size, Fixed));
- div4_style->setHeight(Length(kDiv4Size, Fixed));
- div4_style->setMarginLeft(Length(kDiv4LeftMargin, Fixed));
- div4_style->setFloating(EFloat::kLeft);
- NGBlockNode* div4 = new NGBlockNode(div4_style.get());
-
- div1->SetNextSibling(div2);
- div2->SetNextSibling(div3);
- div3->SetNextSibling(div4);
-
- auto* space = ConstructConstraintSpace(
- kHorizontalTopBottom, TextDirection::kLtr,
- NGLogicalSize(LayoutUnit(kParentSize), LayoutUnit(kParentSize)));
- NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1);
- ASSERT_EQ(frag->Children().size(), 4UL);
-
- // DIV1
- const NGPhysicalFragment* child1 = frag->Children()[0];
- EXPECT_EQ(kDiv1TopMargin, child1->TopOffset());
- EXPECT_EQ(kParentLeftPadding, child1->LeftOffset());
-
- // DIV2
- const NGPhysicalFragment* child2 = frag->Children()[1];
- EXPECT_EQ(0, child2->TopOffset());
- EXPECT_EQ(kParentLeftPadding, child2->LeftOffset());
+// Verifies that floats can be correctly positioned if they are inside of nested
+// empty blocks.
+// TODO(glebl): Enable with new the float/margins collapsing algorithm.
+TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_PositionFloatInsideEmptyBlocks) {
+ setBodyInnerHTML(
+ "<!DOCTYPE html>"
+ "<style>"
+ " #container {"
+ " height: 200px;"
+ " width: 200px;"
+ " }"
+ " #empty1 {"
+ " margin: 20px;"
+ " padding: 0 20px;"
+ " }"
+ " #empty2 {"
+ " margin: 15px;"
+ " padding: 0 15px;"
+ " }"
+ " #float {"
+ " float: left;"
+ " height: 5px;"
+ " width: 5px;"
+ " padding: 10px;"
+ " margin: 10px;"
+ " background-color: green;"
+ " }"
+ "</style>"
+ "<div id='container'>"
+ " <div id='empty1'>"
+ " <div id='empty2'>"
+ " <div id='float'></div>"
+ " </div>"
+ " </div>"
+ "</div>");
+
+ // ** Run LayoutNG algorithm **
+ NGConstraintSpace* space;
+ NGPhysicalBoxFragment* fragment;
+ std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement(
+ document().getElementsByTagName("html")->item(0));
+
+ auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]);
+ // 20 = std::max(empty1's margin, empty2's margin, body's margin)
+ int body_top_offset = 20;
+ EXPECT_THAT(LayoutUnit(body_top_offset), body_fragment->TopOffset());
+ ASSERT_EQ(1UL, body_fragment->Children().size());
+ auto* container_fragment =
+ toNGPhysicalBoxFragment(body_fragment->Children()[0]);
+ ASSERT_EQ(1UL, container_fragment->Children().size());
+
+ auto* empty1_fragment =
+ toNGPhysicalBoxFragment(container_fragment->Children()[0]);
+ // 0, vertical margins got collapsed
+ EXPECT_THAT(LayoutUnit(), empty1_fragment->TopOffset());
+ // 20 empty1's margin
+ int empty1_inline_offset = 20;
+ EXPECT_THAT(LayoutUnit(empty1_inline_offset), empty1_fragment->LeftOffset());
+ ASSERT_EQ(empty1_fragment->Children().size(), 1UL);
+
+ auto* empty2_fragment =
+ toNGPhysicalBoxFragment(empty1_fragment->Children()[0]);
+ // 0, vertical margins got collapsed
+ EXPECT_THAT(LayoutUnit(), empty2_fragment->TopOffset());
+ // 35 = empty1's padding(20) + empty2's padding(15)
+ int empty2_inline_offset = 35;
+ EXPECT_THAT(LayoutUnit(empty2_inline_offset), empty2_fragment->LeftOffset());
+
+ ASSERT_EQ(1UL, body_fragment->PositionedFloats().size());
+ auto float_fragment = body_fragment->PositionedFloats().at(0)->fragment;
+ // 10 = float's padding
+ EXPECT_THAT(LayoutUnit(10), float_fragment->TopOffset());
+ // 25 = empty2's padding(15) + float's padding(10)
+ int float_inline_offset = 25;
+ EXPECT_THAT(float_fragment->LeftOffset(), LayoutUnit(float_inline_offset));
+
+ // ** Verify layout tree **
+ Element* left_float = document().getElementById("float");
+ // 88 = body's margin(8) +
+ // empty1's padding and margin + empty2's padding and margins + float's
+ // padding
+ EXPECT_THAT(left_float->offsetLeft(), 88);
+ // 30 = body_top_offset(collapsed margins result) + float's padding
+ EXPECT_THAT(body_top_offset + 10, left_float->offsetTop());
+
+ // ** Legacy Floating objects **
+ Element* body = document().getElementsByTagName("body")->item(0);
+ auto& floating_objects =
+ const_cast<FloatingObjects*>(
+ toLayoutBlockFlow(body->layoutObject())->floatingObjects())
+ ->mutableSet();
+ ASSERT_EQ(1UL, floating_objects.size());
+ auto floating_object = floating_objects.takeFirst();
+ ASSERT_TRUE(floating_object->isPlaced());
+ // 80 = float_inline_offset(25) + accumulative offset of empty blocks(35 + 20)
+ EXPECT_THAT(LayoutUnit(80), floating_object->x());
+ // 10 = float's padding
+ EXPECT_THAT(LayoutUnit(10), floating_object->y());
+}
- // DIV3
- const NGPhysicalFragment* child3 = frag->Children()[2];
- EXPECT_EQ(kDiv2Size, child3->TopOffset());
- EXPECT_EQ(kParentLeftPadding + kParentSize - kDiv3Size, child3->LeftOffset());
-
- // DIV4
- const NGPhysicalFragment* child4 = frag->Children()[3];
- EXPECT_EQ(kDiv2Size + kDiv3Size, child4->TopOffset());
- EXPECT_EQ(kParentLeftPadding + kDiv4LeftMargin, child4->LeftOffset());
+// Verifies that left/right floating and regular blocks can be positioned
+// correctly by the algorithm.
+// TODO(glebl): Enable with new the float/margins collapsing algorithm.
+TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_PositionFloatFragments) {
+ setBodyInnerHTML(
+ "<style>"
+ " #container {"
+ " height: 200px;"
+ " width: 200px;"
+ " }"
+ " #left-float {"
+ " background-color: red;"
+ " float:left;"
+ " height: 30px;"
+ " width: 30px;"
+ " }"
+ " #left-wide-float {"
+ " background-color: greenyellow;"
+ " float:left;"
+ " height: 30px;"
+ " width: 180px;"
+ " }"
+ " #regular {"
+ " width: 40px;"
+ " height: 40px;"
+ " background-color: green;"
+ " }"
+ " #right-float {"
+ " background-color: cyan;"
+ " float:right;"
+ " width: 50px;"
+ " height: 50px;"
+ " }"
+ " #left-float-with-margin {"
+ " background-color: black;"
+ " float:left;"
+ " height: 120px;"
+ " margin: 10px;"
+ " width: 120px;"
+ " }"
+ "</style>"
+ "<div id='container'>"
+ " <div id='left-float'></div>"
+ " <div id='left-wide-float'></div>"
+ " <div id='regular'></div>"
+ " <div id='right-float'></div>"
+ " <div id='left-float-with-margin'></div>"
+ "</div>");
+
+ // ** Run LayoutNG algorithm **
+ NGConstraintSpace* space;
+ NGPhysicalBoxFragment* fragment;
+ std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement(
+ document().getElementsByTagName("html")->item(0));
+
+ // ** Verify LayoutNG fragments and the list of positioned floats **
+ EXPECT_THAT(LayoutUnit(), fragment->TopOffset());
+ ASSERT_EQ(1UL, fragment->Children().size());
+ auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]);
+ EXPECT_THAT(LayoutUnit(8), body_fragment->TopOffset());
+ auto* container_fragment =
+ toNGPhysicalBoxFragment(body_fragment->Children()[0]);
+ ASSERT_EQ(1UL, container_fragment->Children().size());
+ ASSERT_EQ(4UL, container_fragment->PositionedFloats().size());
+
+ // ** Verify layout tree **
+ Element* left_float = document().getElementById("left-float");
+ // 8 = body's margin-top
+ int left_float_block_offset = 8;
+ EXPECT_EQ(left_float_block_offset, left_float->offsetTop());
+ auto left_float_fragment =
+ container_fragment->PositionedFloats().at(0)->fragment;
+ EXPECT_THAT(LayoutUnit(), left_float_fragment->TopOffset());
+
+ Element* left_wide_float = document().getElementById("left-wide-float");
+ // left-wide-float is positioned right below left-float as it's too wide.
+ // 38 = left_float_block_offset +
+ // left-float's height 30
+ int left_wide_float_block_offset = 38;
+ EXPECT_EQ(left_wide_float_block_offset, left_wide_float->offsetTop());
+ auto left_wide_float_fragment =
+ container_fragment->PositionedFloats().at(1)->fragment;
+ // 30 = left-float's height.
+ EXPECT_THAT(LayoutUnit(30), left_wide_float_fragment->TopOffset());
+
+ Element* regular = document().getElementById("regular");
+ // regular_block_offset = body's margin-top 8
+ int regular_block_offset = 8;
+ EXPECT_EQ(regular_block_offset, regular->offsetTop());
+ auto* regular_block_fragment =
+ toNGPhysicalBoxFragment(container_fragment->Children()[0]);
+ EXPECT_THAT(LayoutUnit(), regular_block_fragment->TopOffset());
+
+ Element* right_float = document().getElementById("right-float");
+ // 158 = body's margin-left 8 + container's width 200 - right_float's width 50
+ int right_float_inline_offset = 158;
+ // it's positioned right after our left_wide_float
+ // 68 = left_wide_float_block_offset 38 + left-wide-float's height 30
+ int right_float_block_offset = left_wide_float_block_offset + 30;
+ EXPECT_EQ(right_float_inline_offset, right_float->offsetLeft());
+ EXPECT_EQ(right_float_block_offset, right_float->offsetTop());
+ auto right_float_fragment =
+ container_fragment->PositionedFloats().at(2)->fragment;
+ // 60 = right_float_block_offset(68) - body's margin(8)
+ EXPECT_THAT(LayoutUnit(right_float_block_offset - 8),
+ right_float_fragment->TopOffset());
+ // 150 = right_float_inline_offset(158) - body's margin(8)
+ EXPECT_THAT(LayoutUnit(right_float_inline_offset - 8),
+ right_float_fragment->LeftOffset());
+
+ Element* left_float_with_margin =
+ document().getElementById("left-float-with-margin");
+ // 18 = body's margin(8) + left-float-with-margin's margin(10)
+ int left_float_with_margin_inline_offset = 18;
+ EXPECT_EQ(left_float_with_margin_inline_offset,
+ left_float_with_margin->offsetLeft());
+ // 78 = left_wide_float_block_offset 38 + left-wide-float's height 30 +
+ // left-float-with-margin's margin(10)
+ int left_float_with_margin_block_offset = 78;
+ EXPECT_EQ(left_float_with_margin_block_offset,
+ left_float_with_margin->offsetTop());
+ auto left_float_with_margin_fragment =
+ container_fragment->PositionedFloats().at(3)->fragment;
+ // 70 = left_float_with_margin_block_offset(78) - body's margin(8)
+ EXPECT_THAT(LayoutUnit(left_float_with_margin_block_offset - 8),
+ left_float_with_margin_fragment->TopOffset());
+ // 10 = left_float_with_margin_inline_offset(18) - body's margin(8)
+ EXPECT_THAT(LayoutUnit(left_float_with_margin_inline_offset - 8),
+ left_float_with_margin_fragment->LeftOffset());
+
+ // ** Verify exclusions **
+ NGLogicalSize left_float_exclusion_size = {LayoutUnit(30), LayoutUnit(30)};
+ // this should be equal to body's margin(8)
+ NGLogicalOffset left_float_exclusion_offset = {LayoutUnit(8), LayoutUnit(8)};
+ NGLogicalRect left_float_exclusion_rect = {left_float_exclusion_offset,
+ left_float_exclusion_size};
+ NGExclusion left_float_exclusion = {left_float_exclusion_rect,
+ NGExclusion::kFloatLeft};
+
+ NGLogicalSize left_wide_exclusion_size = {LayoutUnit(180), LayoutUnit(30)};
+ NGLogicalOffset left_wide_exclusion_offset = {
+ LayoutUnit(8), LayoutUnit(left_wide_float_block_offset)};
+ NGLogicalRect left_wide_exclusion_rect = {left_wide_exclusion_offset,
+ left_wide_exclusion_size};
+ NGExclusion left_wide_exclusion = {left_wide_exclusion_rect,
+ NGExclusion::kFloatLeft};
+
+ NGLogicalSize right_float_exclusion_size = {LayoutUnit(50), LayoutUnit(50)};
+ NGLogicalOffset right_float_exclusion_offset = {
+ LayoutUnit(right_float_inline_offset),
+ LayoutUnit(right_float_block_offset)};
+ NGLogicalRect right_float_exclusion_rect = {right_float_exclusion_offset,
+ right_float_exclusion_size};
+ NGExclusion right_float_exclusion = {right_float_exclusion_rect,
+ NGExclusion::kFloatRight};
+
+ // left-float-with-margin's size(120) + margin(2x10)
+ NGLogicalSize left_float_with_margin_exclusion_size = {LayoutUnit(140),
+ LayoutUnit(140)};
+ // Exclusion starts from the right_float_block_offset position.
+ NGLogicalOffset left_float_with_margin_exclusion_offset = {
+ LayoutUnit(8), LayoutUnit(right_float_block_offset)};
+ NGLogicalRect left_float_with_margin_exclusion_rect = {
+ left_float_with_margin_exclusion_offset,
+ left_float_with_margin_exclusion_size};
+ NGExclusion left_float_with_margin_exclusion = {
+ left_float_with_margin_exclusion_rect, NGExclusion::kFloatLeft};
+
+ EXPECT_THAT(
+ space->Exclusions()->storage,
+ (ElementsAre(Pointee(left_float_exclusion), Pointee(left_wide_exclusion),
+ Pointee(right_float_exclusion),
+ Pointee(left_float_with_margin_exclusion))));
}
// Verifies that NG block layout algorithm respects "clear" CSS property.
-//
-// Test case's HTML representation:
-// <div id="parent" style="width: 200px; height: 200px;">
-// <div style="float: left; width: 30px; height: 30px;"/> <!-- DIV1 -->
-// <div style="float: right; width: 40px; height: 40px;
-// clear: left;"/> <!-- DIV2 -->
-// <div style="clear: ...; width: 50px; height: 50px;"/> <!-- DIV3 -->
-// </div>
-//
-// Expected:
-// - DIV2 is positioned below DIV1 because it has clear: left;
-// - DIV3 is positioned below DIV1 if clear: left;
-// - DIV3 is positioned below DIV2 if clear: right;
-// - DIV3 is positioned below DIV2 if clear: both;
-TEST_F(NGBlockLayoutAlgorithmTest, PositionFragmentsWithClear) {
- const int kParentSize = 200;
- const int kDiv1Size = 30;
- const int kDiv2Size = 40;
- const int kDiv3Size = 50;
-
- style_->setHeight(Length(kParentSize, Fixed));
- style_->setWidth(Length(kParentSize, Fixed));
-
- // DIV1
- RefPtr<ComputedStyle> div1_style = ComputedStyle::create();
- div1_style->setWidth(Length(kDiv1Size, Fixed));
- div1_style->setHeight(Length(kDiv1Size, Fixed));
- div1_style->setFloating(EFloat::kLeft);
- NGBlockNode* div1 = new NGBlockNode(div1_style.get());
-
- // DIV2
- RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
- div2_style->setWidth(Length(kDiv2Size, Fixed));
- div2_style->setHeight(Length(kDiv2Size, Fixed));
- div2_style->setClear(EClear::ClearLeft);
- div2_style->setFloating(EFloat::kRight);
- NGBlockNode* div2 = new NGBlockNode(div2_style.get());
-
- // DIV3
- RefPtr<ComputedStyle> div3_style = ComputedStyle::create();
- div3_style->setWidth(Length(kDiv3Size, Fixed));
- div3_style->setHeight(Length(kDiv3Size, Fixed));
- NGBlockNode* div3 = new NGBlockNode(div3_style.get());
-
- div1->SetNextSibling(div2);
- div2->SetNextSibling(div3);
-
- // clear: left;
- div3_style->setClear(EClear::ClearLeft);
- auto* space = ConstructConstraintSpace(
- kHorizontalTopBottom, TextDirection::kLtr,
- NGLogicalSize(LayoutUnit(kParentSize), LayoutUnit(kParentSize)));
- NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1);
- const NGPhysicalFragment* child3 = frag->Children()[2];
- EXPECT_EQ(kDiv1Size, child3->TopOffset());
-
- // clear: right;
- div3_style->setClear(EClear::ClearRight);
- space = ConstructConstraintSpace(
- kHorizontalTopBottom, TextDirection::kLtr,
- NGLogicalSize(LayoutUnit(kParentSize), LayoutUnit(kParentSize)));
- frag = RunBlockLayoutAlgorithm(space, div1);
- child3 = frag->Children()[2];
- EXPECT_EQ(kDiv1Size + kDiv2Size, child3->TopOffset());
-
- // clear: both;
- div3_style->setClear(EClear::ClearBoth);
- space = ConstructConstraintSpace(
- kHorizontalTopBottom, TextDirection::kLtr,
- NGLogicalSize(LayoutUnit(kParentSize), LayoutUnit(kParentSize)));
- frag = RunBlockLayoutAlgorithm(space, div1);
- space = ConstructConstraintSpace(
- kHorizontalTopBottom, TextDirection::kLtr,
- NGLogicalSize(LayoutUnit(kParentSize), LayoutUnit(kParentSize)));
- child3 = frag->Children()[2];
- EXPECT_EQ(kDiv1Size + kDiv2Size, child3->TopOffset());
+// TODO(glebl): Enable with new the float/margins collapsing algorithm.
+TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_PositionFragmentsWithClear) {
+ setBodyInnerHTML(
+ "<style>"
+ " #container {"
+ " height: 200px;"
+ " width: 200px;"
+ " }"
+ " #float-left {"
+ " background-color: red;"
+ " float: left;"
+ " height: 30px;"
+ " width: 30px;"
+ " }"
+ " #float-right {"
+ " background-color: blue;"
+ " float: right;"
+ " height: 170px;"
+ " width: 40px;"
+ " }"
+ " #clearance {"
+ " background-color: yellow;"
+ " height: 60px;"
+ " width: 60px;"
+ " margin: 20px;"
+ " }"
+ " #block {"
+ " margin: 40px;"
+ " background-color: black;"
+ " height: 60px;"
+ " width: 60px;"
+ " }"
+ " #adjoining-clearance {"
+ " background-color: green;"
+ " clear: left;"
+ " height: 20px;"
+ " width: 20px;"
+ " margin: 30px;"
+ " }"
+ "</style>"
+ "<div id='container'>"
+ " <div id='float-left'></div>"
+ " <div id='float-right'></div>"
+ " <div id='clearance'></div>"
+ " <div id='block'></div>"
+ " <div id='adjoining-clearance'></div>"
+ "</div>");
+
+ const NGPhysicalBoxFragment* clerance_fragment;
+ const NGPhysicalBoxFragment* body_fragment;
+ const NGPhysicalBoxFragment* container_fragment;
+ const NGPhysicalBoxFragment* block_fragment;
+ const NGPhysicalBoxFragment* adjoining_clearance_fragment;
+ auto run_with_clearance = [&](EClear clear_value) {
+ NGPhysicalBoxFragment* fragment;
+ Element* el_with_clear = document().getElementById("clearance");
+ el_with_clear->mutableComputedStyle()->setClear(clear_value);
+ std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement(
+ document().getElementsByTagName("html")->item(0));
+ ASSERT_EQ(1UL, fragment->Children().size());
+ body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]);
+ container_fragment = toNGPhysicalBoxFragment(body_fragment->Children()[0]);
+ ASSERT_EQ(3UL, container_fragment->Children().size());
+ clerance_fragment =
+ toNGPhysicalBoxFragment(container_fragment->Children()[0]);
+ block_fragment = toNGPhysicalBoxFragment(container_fragment->Children()[1]);
+ adjoining_clearance_fragment =
+ toNGPhysicalBoxFragment(container_fragment->Children()[2]);
+ };
+
+ // clear: none
+ run_with_clearance(EClear::ClearNone);
+ // 20 = std::max(body's margin 8, clearance's margins 20)
+ EXPECT_EQ(LayoutUnit(20), body_fragment->TopOffset());
+ EXPECT_EQ(LayoutUnit(0), container_fragment->TopOffset());
+ // 0 = collapsed margins
+ EXPECT_EQ(LayoutUnit(0), clerance_fragment->TopOffset());
+ // 100 = clearance's height 60 +
+ // std::max(clearance's margins 20, block's margins 40)
+ EXPECT_EQ(LayoutUnit(100), block_fragment->TopOffset());
+ // 200 = 100 + block's height 60 + max(adjoining_clearance's margins 30,
+ // block's margins 40)
+ EXPECT_EQ(LayoutUnit(200), adjoining_clearance_fragment->TopOffset());
+
+ // clear: right
+ run_with_clearance(EClear::ClearRight);
+ // 8 = body's margin. This doesn't collapse its margins with 'clearance' block
+ // as it's not an adjoining block to body.
+ EXPECT_EQ(LayoutUnit(8), body_fragment->TopOffset());
+ EXPECT_EQ(LayoutUnit(0), container_fragment->TopOffset());
+ // 170 = float-right's height
+ EXPECT_EQ(LayoutUnit(170), clerance_fragment->TopOffset());
+ // 270 = float-right's height + clearance's height 60 +
+ // max(clearance's margin 20, block margin 40)
+ EXPECT_EQ(LayoutUnit(270), block_fragment->TopOffset());
+ // 370 = block's offset 270 + block's height 60 +
+ // std::max(block's margin 40, adjoining_clearance's margin 30)
+ EXPECT_EQ(LayoutUnit(370), adjoining_clearance_fragment->TopOffset());
+
+ // clear: left
+ run_with_clearance(EClear::ClearLeft);
+ // 8 = body's margin. This doesn't collapse its margins with 'clearance' block
+ // as it's not an adjoining block to body.
+ EXPECT_EQ(LayoutUnit(8), body_fragment->TopOffset());
+ EXPECT_EQ(LayoutUnit(0), container_fragment->TopOffset());
+ // 30 = float_left's height
+ EXPECT_EQ(LayoutUnit(30), clerance_fragment->TopOffset());
+ // 130 = float_left's height + clearance's height 60 +
+ // max(clearance's margin 20, block margin 40)
+ EXPECT_EQ(LayoutUnit(130), block_fragment->TopOffset());
+ // 230 = block's offset 130 + block's height 60 +
+ // std::max(block's margin 40, adjoining_clearance's margin 30)
+ EXPECT_EQ(LayoutUnit(230), adjoining_clearance_fragment->TopOffset());
+
+ // clear: both
+ // same as clear: right
+ run_with_clearance(EClear::ClearBoth);
+ EXPECT_EQ(LayoutUnit(8), body_fragment->TopOffset());
+ EXPECT_EQ(LayoutUnit(0), container_fragment->TopOffset());
+ EXPECT_EQ(LayoutUnit(170), clerance_fragment->TopOffset());
+ EXPECT_EQ(LayoutUnit(270), block_fragment->TopOffset());
+ EXPECT_EQ(LayoutUnit(370), adjoining_clearance_fragment->TopOffset());
}
// Verifies that we compute the right min and max-content size.
« no previous file with comments | « no previous file | third_party/WebKit/Source/core/layout/ng/ng_units.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698