[LayoutNG] Refactor main-loop of block layout algorithm.
This just simplifies things by having clear paths for each type of child.
There should be no functional changes.
BUG=635619
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_layout_tests_layout_ng
Review-Url: https://codereview.chromium.org/2883353005
Cr-Commit-Position: refs/heads/master@{#473077}
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
index 502f0a72..261d588 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
@@ -228,33 +228,14 @@
curr_bfc_offset_.block_offset += content_size_;
while (child) {
- // TODO(ikilpatrick): Refactor the inside of this loop.
- if (child->IsBlock()) {
- EPosition position = child->Style().GetPosition();
- if (position == EPosition::kAbsolute || position == EPosition::kFixed) {
- NGLogicalOffset offset = {border_and_padding_.inline_start,
- content_size_};
-
- // We only include the margin strut in the OOF static-position if we
- // know we aren't going to be a zero-block-size fragment.
- if (container_builder_.BfcOffset())
- offset.block_offset += curr_margin_strut_.Sum();
-
- container_builder_.AddOutOfFlowChildCandidate(ToNGBlockNode(child),
- offset);
- NGBlockChildIterator::Entry entry = child_iterator.NextChild();
- child = entry.node;
- child_break_token = entry.token;
- continue;
- }
- }
-
- NGLogicalOffset child_bfc_offset = PrepareChildLayout(child);
-
- if (child->IsFloating()) {
- FinishFloatChildLayout(child->Style(), ToNGBlockNode(child),
- ToNGBlockBreakToken(child_break_token));
+ if (child->IsOutOfFlowPositioned()) {
+ DCHECK(!child_break_token);
+ HandleOutOfFlowPositioned(ToNGBlockNode(child));
+ } else if (child->IsFloating()) {
+ HandleFloating(ToNGBlockNode(child),
+ ToNGBlockBreakToken(child_break_token));
} else {
+ NGLogicalOffset child_bfc_offset = PrepareChildLayout(child);
RefPtr<NGConstraintSpace> child_space =
CreateConstraintSpaceForChild(child_bfc_offset, *child);
RefPtr<NGLayoutResult> layout_result =
@@ -321,10 +302,57 @@
return container_builder_.ToBoxFragment();
}
+void NGBlockLayoutAlgorithm::HandleOutOfFlowPositioned(NGBlockNode* child) {
+ NGLogicalOffset offset = {border_and_padding_.inline_start, content_size_};
+
+ // We only include the margin strut in the OOF static-position if we know we
+ // aren't going to be a zero-block-size fragment.
+ if (container_builder_.BfcOffset())
+ offset.block_offset += curr_margin_strut_.Sum();
+
+ container_builder_.AddOutOfFlowChildCandidate(child, offset);
+}
+
+void NGBlockLayoutAlgorithm::HandleFloating(NGBlockNode* child,
+ NGBlockBreakToken* token) {
+ // TODO(ikilpatrick): Pass in BFC offset from previous in-flow child.
+ curr_bfc_offset_ = container_builder_.BfcOffset()
+ ? container_builder_.BfcOffset().value()
+ : ConstraintSpace().BfcOffset();
+ curr_bfc_offset_.block_offset += content_size_;
+
+ // Calculate margins in the BFC's writing mode.
+ curr_child_margins_ = CalculateMargins(child);
+
+ NGLogicalOffset origin_offset = constraint_space_->BfcOffset();
+ origin_offset.inline_offset += border_and_padding_.inline_start;
+ RefPtr<NGUnpositionedFloat> unpositioned_float = NGUnpositionedFloat::Create(
+ child_available_size_, child_percentage_size_, origin_offset,
+ constraint_space_->BfcOffset(), curr_child_margins_, child, token);
+ container_builder_.AddUnpositionedFloat(unpositioned_float);
+
+ // If there is a break token for a float we must be resuming layout, we must
+ // always know our position in the BFC.
+ DCHECK(!token || container_builder_.BfcOffset());
+
+ // No need to postpone the positioning if we know the correct offset.
+ if (container_builder_.BfcOffset()) {
+ NGLogicalOffset origin_point = curr_bfc_offset_;
+ // Adjust origin point to the margins of the last child.
+ // Example: <div style="margin-bottom: 20px"><float></div>
+ // <div style="margin-bottom: 30px"></div>
+ origin_point.block_offset += curr_margin_strut_.Sum();
+ PositionPendingFloats(origin_point.block_offset, &container_builder_,
+ MutableConstraintSpace());
+ }
+}
+
NGLogicalOffset NGBlockLayoutAlgorithm::PrepareChildLayout(
NGLayoutInputNode* child) {
DCHECK(child);
+ DCHECK(!child->IsFloating());
+ // TODO(ikilpatrick): Pass in BFC offset from previous in-flow child.
curr_bfc_offset_ = container_builder_.BfcOffset()
? container_builder_.BfcOffset().value()
: ConstraintSpace().BfcOffset();
@@ -334,7 +362,6 @@
curr_child_margins_ = CalculateMargins(child);
bool should_position_pending_floats =
- !child->IsFloating() &&
!IsNewFormattingContextForBlockLevelChild(Style(), *child) &&
ClearanceMayAffectLayout(ConstraintSpace(),
container_builder_.UnpositionedFloats(),
@@ -353,20 +380,15 @@
MutableConstraintSpace());
}
- bool is_inflow = child->IsInline() || !child->IsFloating();
-
NGLogicalOffset child_bfc_offset = curr_bfc_offset_;
- child_bfc_offset.inline_offset += border_and_padding_.inline_start;
- // Only inflow children (e.g. not floats) are included in the child's margin
- // strut as they do not participate in margin collapsing.
- if (is_inflow) {
- child_bfc_offset.inline_offset += curr_child_margins_.inline_start;
- // Append the current margin strut with child's block start margin.
- // Non empty border/padding, and new FC use cases are handled inside of the
- // child's layout.
- if (!IsNewFormattingContextForBlockLevelChild(Style(), *child))
- curr_margin_strut_.Append(curr_child_margins_.block_start);
- }
+ child_bfc_offset.inline_offset +=
+ {border_and_padding_.inline_start + curr_child_margins_.inline_start};
+
+ // Append the current margin strut with child's block start margin.
+ // Non empty border/padding, and new FC use cases are handled inside of the
+ // child's layout.
+ if (!IsNewFormattingContextForBlockLevelChild(Style(), *child))
+ curr_margin_strut_.Append(curr_child_margins_.block_start);
// TODO(crbug.com/716930): We should also collapse margins below once we
// remove LayoutInline splitting.
@@ -519,33 +541,6 @@
return curr_bfc_offset_;
}
-void NGBlockLayoutAlgorithm::FinishFloatChildLayout(
- const ComputedStyle& child_style,
- NGBlockNode* child,
- NGBlockBreakToken* token) {
- NGLogicalOffset origin_offset = constraint_space_->BfcOffset();
- origin_offset.inline_offset += border_and_padding_.inline_start;
- RefPtr<NGUnpositionedFloat> unpositioned_float = NGUnpositionedFloat::Create(
- child_available_size_, child_percentage_size_, origin_offset,
- constraint_space_->BfcOffset(), curr_child_margins_, child, token);
- container_builder_.AddUnpositionedFloat(unpositioned_float);
-
- // If there is a break token for a float we must be resuming layout, we must
- // always know our position in the BFC.
- DCHECK(!token || container_builder_.BfcOffset());
-
- // No need to postpone the positioning if we know the correct offset.
- if (container_builder_.BfcOffset()) {
- NGLogicalOffset origin_point = curr_bfc_offset_;
- // Adjust origin point to the margins of the last child.
- // Example: <div style="margin-bottom: 20px"><float></div>
- // <div style="margin-bottom: 30px"></div>
- origin_point.block_offset += curr_margin_strut_.Sum();
- PositionPendingFloats(origin_point.block_offset, &container_builder_,
- MutableConstraintSpace());
- }
-}
-
void NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
LayoutUnit used_block_size =
BreakToken() ? BreakToken()->UsedBlockSize() : LayoutUnit();
@@ -623,13 +618,8 @@
const ComputedStyle& child_style = child.Style();
bool is_new_bfc = IsNewFormattingContextForBlockLevelChild(Style(), child);
space_builder.SetIsNewFormattingContext(is_new_bfc)
- .SetBfcOffset(child_bfc_offset);
-
- // Float's margins are not included in child's space because:
- // 1) Floats do not participate in margins collapsing.
- // 2) Floats margins are used separately to calculate floating exclusions.
- space_builder.SetMarginStrut(child.IsFloating() ? NGMarginStrut()
- : curr_margin_strut_);
+ .SetBfcOffset(child_bfc_offset)
+ .SetMarginStrut(curr_margin_strut_);
if (!is_new_bfc) {
space_builder.SetUnpositionedFloats(
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
index 55858b4..9ce63c41 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
@@ -99,9 +99,8 @@
NGLogicalOffset PositionLegacy(const NGConstraintSpace& child_space);
- void FinishFloatChildLayout(const ComputedStyle&,
- NGBlockNode*,
- NGBlockBreakToken*);
+ void HandleOutOfFlowPositioned(NGBlockNode*);
+ void HandleFloating(NGBlockNode*, NGBlockBreakToken*);
// Final adjustments before fragment creation. We need to prevent the
// fragment from crossing fragmentainer boundaries, and rather create a break
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_layout_input_node.h b/third_party/WebKit/Source/core/layout/ng/ng_layout_input_node.h
index 1ca0099..ae697ca 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_layout_input_node.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_layout_input_node.h
@@ -31,6 +31,10 @@
bool IsFloating() const { return IsBlock() && Style().IsFloating(); }
+ bool IsOutOfFlowPositioned() const {
+ return IsBlock() && Style().HasOutOfFlowPosition();
+ }
+
virtual ~NGLayoutInputNode(){};
// Performs layout on this input node, will return the layout result.