Index: third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc |
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 5eabe822376d798483b9851d9c5151e6d1f3b678..a7c9426808dba7a4145d568295033344b7cb030e 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 |
@@ -418,12 +418,21 @@ RefPtr<NGPhysicalFragment> NGBlockLayoutAlgorithm::Layout() { |
// Margins collapsing: |
// Do not collapse margins between parent and its child if there is |
// border/padding between them. |
- if (border_and_padding_.block_start || |
- ConstraintSpace().IsNewFormattingContext()) { |
+ if (border_and_padding_.block_start) { |
curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
- builder_->SetBfcOffset(curr_bfc_offset_); |
+ UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); |
curr_margin_strut_ = NGMarginStrut(); |
} |
+ |
+ // Block that establishes a new BFC knows its BFC offset == {} |
+ // If a new formatting context hits the if branch above then the BFC offset is |
+ // still {} as the margin strut from the constraint space must also be empty. |
+ if (ConstraintSpace().IsNewFormattingContext()) { |
+ UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); |
+ DCHECK_EQ(builder_->BfcOffset().value(), NGLogicalOffset()); |
+ DCHECK_EQ(curr_margin_strut_, NGMarginStrut()); |
+ } |
+ |
curr_bfc_offset_.block_offset += content_size_; |
while (current_child_) { |
@@ -475,7 +484,7 @@ RefPtr<NGPhysicalFragment> NGBlockLayoutAlgorithm::Layout() { |
// Layout our absolute and fixed positioned children. |
NGOutOfFlowLayoutPart(Style(), builder_.get()).Run(); |
- // Non empty blocks always know their position in space: |
+ // Non-empty blocks always know their position in space: |
if (block_size) { |
curr_bfc_offset_.block_offset += curr_margin_strut_.Sum(); |
UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); |
@@ -522,8 +531,6 @@ void NGBlockLayoutAlgorithm::FinishCurrentChildLayout( |
NGBoxFragment fragment(ConstraintSpace().WritingMode(), |
physical_fragment.get()); |
- if (!physical_fragment->UnpositionedFloats().isEmpty()) |
- DCHECK(!builder_->BfcOffset()) << "Parent BFC offset shouldn't be set here"; |
// Pull out unpositioned floats to the current fragment. This may needed if |
// for example the child fragment could not position its floats because it's |
// empty and therefore couldn't determine its position in space. |
@@ -560,6 +567,15 @@ void NGBlockLayoutAlgorithm::FinishCurrentChildLayout( |
// Fragment that knows its offset can be used to set parent's BFC position. |
curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset; |
bfc_offset = curr_bfc_offset_; |
+ } else if (builder_->BfcOffset()) { |
+ // Fragment doesn't know its offset but we can still calculate its BFC |
+ // position because the parent fragment's BFC is known. |
+ // Example: |
+ // BFC Offset is known here because of the padding. |
+ // <div style="padding: 1px"> |
+ // <div id="empty-div" style="margins: 1px"></div> |
+ bfc_offset = curr_bfc_offset_; |
+ bfc_offset.value().block_offset += curr_margin_strut_.Sum(); |
} |
if (bfc_offset) { |
UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get()); |
@@ -577,7 +593,15 @@ void NGBlockLayoutAlgorithm::FinishCurrentChildLayout( |
curr_margin_strut_ = fragment.EndMarginStrut(); |
curr_margin_strut_.Append(curr_child_margins_.block_end); |
- content_size_ = fragment.BlockSize() + logical_offset.block_offset; |
+ // Only modify content_size if BlockSize is not empty. It's needed to prevent |
+ // the situation when logical_offset is included in content_size for empty |
+ // blocks. Example: |
+ // <div style="overflow:hidden"> |
+ // <div style="margin-top: 8px"></div> |
+ // <div style="margin-top: 10px"></div> |
+ // </div> |
+ if (fragment.BlockSize()) |
+ content_size_ = fragment.BlockSize() + logical_offset.block_offset; |
max_inline_size_ = |
std::max(max_inline_size_, fragment.InlineSize() + |
curr_child_margins_.InlineSum() + |
@@ -795,22 +819,22 @@ NGBlockLayoutAlgorithm::CreateConstraintSpaceForCurrentChild() { |
builder_->BfcOffset().value(), &content_size_); |
} |
- // Append the current margin strut with child's block start margin. |
- // Non empty border/padding use cases are handled inside of the child's |
- // layout. |
- curr_margin_strut_.Append(curr_child_margins_.block_start); |
- space_builder_->SetMarginStrut(curr_margin_strut_); |
- |
// Set estimated BFC offset to the next child's constraint space. |
curr_bfc_offset_ = builder_->BfcOffset() ? builder_->BfcOffset().value() |
: ConstraintSpace().BfcOffset(); |
curr_bfc_offset_.block_offset += content_size_; |
curr_bfc_offset_.inline_offset += border_and_padding_.inline_start; |
- // Floats margins are not included in child's CS because they are used to |
- // calculate floating exclusions. |
+ // Floats margins are not included in child's CS because |
+ // 1) Floats do not participate in margins collapsing |
+ // 2) Floats margins are used separately to calculate floating exclusions. |
if (!CurrentChildStyle().isFloating()) { |
curr_bfc_offset_.inline_offset += curr_child_margins_.inline_start; |
+ // Append the current margin strut with child's block start margin. |
+ // Non empty border/padding use cases are handled inside of the child's |
+ // layout. |
+ curr_margin_strut_.Append(curr_child_margins_.block_start); |
+ space_builder_->SetMarginStrut(curr_margin_strut_); |
} |
space_builder_->SetBfcOffset(curr_bfc_offset_); |