| 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 261d588dd69b4e9f05a23a9aac076f517da9d217..03f669188987dd95f3c0b65479814b192a655156 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
|
| @@ -67,14 +67,31 @@ bool IsOutOfSpace(const NGConstraintSpace& space, LayoutUnit content_size) {
|
|
|
| } // namespace
|
|
|
| +// This struct is used for communicating to a child the position of the
|
| +// previous inflow child.
|
| +struct NGPreviousInflowPosition {
|
| + LayoutUnit bfc_block_offset;
|
| + LayoutUnit logical_block_offset;
|
| + NGMarginStrut margin_strut;
|
| +};
|
| +
|
| +// This strut holds information for the current inflow child. The data is not
|
| +// useful outside of handling this single inflow child.
|
| +struct NGInflowChildData {
|
| + NGLogicalOffset bfc_offset_estimate;
|
| + NGMarginStrut margin_strut;
|
| + NGBoxStrut margins;
|
| +};
|
| +
|
| void MaybeUpdateFragmentBfcOffset(const NGConstraintSpace& space,
|
| - const NGLogicalOffset& offset,
|
| + LayoutUnit bfc_block_offset,
|
| NGFragmentBuilder* builder) {
|
| DCHECK(builder);
|
| if (!builder->BfcOffset()) {
|
| - NGLogicalOffset mutable_offset(offset);
|
| - AdjustToClearance(space.ClearanceOffset(), &mutable_offset);
|
| - builder->SetBfcOffset(mutable_offset);
|
| + NGLogicalOffset bfc_offset = {space.BfcOffset().inline_offset,
|
| + bfc_block_offset};
|
| + AdjustToClearance(space.ClearanceOffset(), &bfc_offset);
|
| + builder->SetBfcOffset(bfc_offset);
|
| }
|
| }
|
|
|
| @@ -150,11 +167,13 @@ Optional<MinMaxContentSize> NGBlockLayoutAlgorithm::ComputeMinMaxContentSize()
|
| }
|
|
|
| NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset(
|
| + const NGBoxStrut& child_margins,
|
| const WTF::Optional<NGLogicalOffset>& known_fragment_offset) {
|
| if (known_fragment_offset)
|
| return known_fragment_offset.value() - ContainerBfcOffset();
|
| LayoutUnit inline_offset =
|
| - border_and_padding_.inline_start + curr_child_margins_.inline_start;
|
| + border_and_padding_.inline_start + child_margins.inline_start;
|
| + // TODO(ikilpatrick): Using the content_size_ here looks suspicious - check.
|
| return {inline_offset, content_size_};
|
| }
|
|
|
| @@ -199,17 +218,20 @@ RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
|
| // within a previous fragment.
|
| content_size_ = BreakToken() ? LayoutUnit() : border_and_padding_.block_start;
|
|
|
| - curr_margin_strut_ = ConstraintSpace().MarginStrut();
|
| - curr_bfc_offset_ = ConstraintSpace().BfcOffset();
|
| + NGMarginStrut input_margin_strut = ConstraintSpace().MarginStrut();
|
| + LayoutUnit input_bfc_block_offset =
|
| + ConstraintSpace().BfcOffset().block_offset;
|
|
|
| // Margins collapsing:
|
| // Do not collapse margins between parent and its child if there is
|
| // border/padding between them.
|
| if (border_and_padding_.block_start) {
|
| - curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
|
| - MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
|
| + input_bfc_block_offset += input_margin_strut.Sum();
|
| + MaybeUpdateFragmentBfcOffset(ConstraintSpace(), input_bfc_block_offset,
|
| &container_builder_);
|
| - curr_margin_strut_ = NGMarginStrut();
|
| + // We reset the block offset here as it may have been effected by clearance.
|
| + input_bfc_block_offset = ContainerBfcOffset().block_offset;
|
| + input_margin_strut = NGMarginStrut();
|
| }
|
|
|
| // If a new formatting context hits the margin collapsing if-branch above
|
| @@ -218,29 +240,34 @@ RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
|
| // If we are resuming layout from a break token the same rule applies. Margin
|
| // struts cannot pass through break tokens.
|
| if (ConstraintSpace().IsNewFormattingContext() || BreakToken()) {
|
| - MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
|
| + MaybeUpdateFragmentBfcOffset(ConstraintSpace(), input_bfc_block_offset,
|
| &container_builder_);
|
| - DCHECK_EQ(curr_margin_strut_, NGMarginStrut());
|
| + DCHECK_EQ(input_margin_strut, NGMarginStrut());
|
| DCHECK_EQ(container_builder_.BfcOffset().value(), NGLogicalOffset());
|
| - curr_bfc_offset_ = {};
|
| }
|
|
|
| - curr_bfc_offset_.block_offset += content_size_;
|
| + input_bfc_block_offset += content_size_;
|
| +
|
| + NGPreviousInflowPosition previous_inflow_position = {
|
| + input_bfc_block_offset, content_size_, input_margin_strut};
|
|
|
| while (child) {
|
| if (child->IsOutOfFlowPositioned()) {
|
| DCHECK(!child_break_token);
|
| - HandleOutOfFlowPositioned(ToNGBlockNode(child));
|
| + HandleOutOfFlowPositioned(previous_inflow_position, ToNGBlockNode(child));
|
| } else if (child->IsFloating()) {
|
| - HandleFloating(ToNGBlockNode(child),
|
| + HandleFloating(previous_inflow_position, ToNGBlockNode(child),
|
| ToNGBlockBreakToken(child_break_token));
|
| } else {
|
| - NGLogicalOffset child_bfc_offset = PrepareChildLayout(child);
|
| + NGInflowChildData child_data =
|
| + PrepareChildLayout(previous_inflow_position, child);
|
| RefPtr<NGConstraintSpace> child_space =
|
| - CreateConstraintSpaceForChild(child_bfc_offset, *child);
|
| + CreateConstraintSpaceForChild(*child, child_data);
|
| RefPtr<NGLayoutResult> layout_result =
|
| child->Layout(child_space.Get(), child_break_token);
|
| - FinishChildLayout(*child_space, child, layout_result.Get());
|
| + previous_inflow_position =
|
| + FinishChildLayout(*child_space, previous_inflow_position, child_data,
|
| + child, layout_result.Get());
|
| }
|
|
|
| entry = child_iterator.NextChild();
|
| @@ -251,6 +278,9 @@ RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
|
| break;
|
| }
|
|
|
| + NGMarginStrut end_margin_strut = previous_inflow_position.margin_strut;
|
| + LayoutUnit end_bfc_block_offset = previous_inflow_position.bfc_block_offset;
|
| +
|
| // Margins collapsing:
|
| // Bottom margins of an in-flow block box doesn't collapse with its last
|
| // in-flow block-level child's bottom margin if the box has bottom
|
| @@ -258,8 +288,8 @@ RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
|
| content_size_ += border_and_padding_.block_end;
|
| if (border_and_padding_.block_end ||
|
| ConstraintSpace().IsNewFormattingContext()) {
|
| - content_size_ += curr_margin_strut_.Sum();
|
| - curr_margin_strut_ = NGMarginStrut();
|
| + content_size_ += end_margin_strut.Sum();
|
| + end_margin_strut = NGMarginStrut();
|
| }
|
|
|
| // Recompute the block-axis size now that we know our content size.
|
| @@ -273,10 +303,10 @@ RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
|
| // Non-empty blocks always know their position in space.
|
| // TODO(ikilpatrick): This check for a break token seems error prone.
|
| if (size.block_size || BreakToken()) {
|
| - curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
|
| - MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
|
| + end_bfc_block_offset += end_margin_strut.Sum();
|
| + MaybeUpdateFragmentBfcOffset(ConstraintSpace(), end_bfc_block_offset,
|
| &container_builder_);
|
| - PositionPendingFloats(curr_bfc_offset_.block_offset, &container_builder_,
|
| + PositionPendingFloats(end_bfc_block_offset, &container_builder_,
|
| MutableConstraintSpace());
|
| }
|
|
|
| @@ -285,9 +315,9 @@ RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
|
| // of its parent if the parent has height != auto()
|
| if (!Style().LogicalHeight().IsAuto()) {
|
| // TODO(glebl): handle minLogicalHeight, maxLogicalHeight.
|
| - curr_margin_strut_ = NGMarginStrut();
|
| + end_margin_strut = NGMarginStrut();
|
| }
|
| - container_builder_.SetEndMarginStrut(curr_margin_strut_);
|
| + container_builder_.SetEndMarginStrut(end_margin_strut);
|
|
|
| container_builder_.SetOverflowSize(
|
| NGLogicalSize(max_inline_size_, content_size_));
|
| @@ -302,33 +332,32 @@ RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
|
| return container_builder_.ToBoxFragment();
|
| }
|
|
|
| -void NGBlockLayoutAlgorithm::HandleOutOfFlowPositioned(NGBlockNode* child) {
|
| - NGLogicalOffset offset = {border_and_padding_.inline_start, content_size_};
|
| +void NGBlockLayoutAlgorithm::HandleOutOfFlowPositioned(
|
| + const NGPreviousInflowPosition& previous_inflow_position,
|
| + NGBlockNode* child) {
|
| + NGLogicalOffset offset = {border_and_padding_.inline_start,
|
| + previous_inflow_position.logical_block_offset};
|
|
|
| // 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();
|
| + offset.block_offset += previous_inflow_position.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_;
|
| -
|
| +void NGBlockLayoutAlgorithm::HandleFloating(
|
| + const NGPreviousInflowPosition& previous_inflow_position,
|
| + NGBlockNode* child,
|
| + NGBlockBreakToken* token) {
|
| // Calculate margins in the BFC's writing mode.
|
| - curr_child_margins_ = CalculateMargins(child);
|
| + NGBoxStrut 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);
|
| + constraint_space_->BfcOffset(), margins, child, token);
|
| container_builder_.AddUnpositionedFloat(unpositioned_float);
|
|
|
| // If there is a break token for a float we must be resuming layout, we must
|
| @@ -337,29 +366,28 @@ void NGBlockLayoutAlgorithm::HandleFloating(NGBlockNode* child,
|
|
|
| // 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_,
|
| + LayoutUnit origin_block_offset =
|
| + previous_inflow_position.bfc_block_offset +
|
| + previous_inflow_position.margin_strut.Sum();
|
| + PositionPendingFloats(origin_block_offset, &container_builder_,
|
| MutableConstraintSpace());
|
| }
|
| }
|
|
|
| -NGLogicalOffset NGBlockLayoutAlgorithm::PrepareChildLayout(
|
| +NGInflowChildData NGBlockLayoutAlgorithm::PrepareChildLayout(
|
| + const NGPreviousInflowPosition& previous_inflow_position,
|
| 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();
|
| - curr_bfc_offset_.block_offset += content_size_;
|
| + LayoutUnit bfc_block_offset = previous_inflow_position.bfc_block_offset;
|
|
|
| // Calculate margins in parent's writing mode.
|
| - curr_child_margins_ = CalculateMargins(child);
|
| + NGBoxStrut margins = CalculateMargins(child);
|
| + NGMarginStrut margin_strut = previous_inflow_position.margin_strut;
|
|
|
| bool should_position_pending_floats =
|
| !IsNewFormattingContextForBlockLevelChild(Style(), *child) &&
|
| @@ -371,45 +399,50 @@ NGLogicalOffset NGBlockLayoutAlgorithm::PrepareChildLayout(
|
| // be positioned before layout. This also resolves the fragment's bfc offset.
|
| if (should_position_pending_floats) {
|
| LayoutUnit origin_point_block_offset =
|
| - curr_bfc_offset_.block_offset + curr_margin_strut_.Sum();
|
| - MaybeUpdateFragmentBfcOffset(
|
| - ConstraintSpace(),
|
| - {curr_bfc_offset_.inline_offset, origin_point_block_offset},
|
| - &container_builder_);
|
| + bfc_block_offset + margin_strut.Sum();
|
| + MaybeUpdateFragmentBfcOffset(ConstraintSpace(), origin_point_block_offset,
|
| + &container_builder_);
|
| + // TODO(ikilpatrick): Check if origin_point_block_offset is correct -
|
| + // MaybeUpdateFragmentBfcOffset might have changed it due to clearance.
|
| PositionPendingFloats(origin_point_block_offset, &container_builder_,
|
| MutableConstraintSpace());
|
| }
|
|
|
| - NGLogicalOffset child_bfc_offset = curr_bfc_offset_;
|
| - child_bfc_offset.inline_offset +=
|
| - {border_and_padding_.inline_start + curr_child_margins_.inline_start};
|
| + NGLogicalOffset child_bfc_offset = {
|
| + ConstraintSpace().BfcOffset().inline_offset +
|
| + border_and_padding_.inline_start + margins.inline_start,
|
| + bfc_block_offset};
|
| +
|
| + bool is_new_fc = IsNewFormattingContextForBlockLevelChild(Style(), *child);
|
|
|
| // 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);
|
| + if (!is_new_fc)
|
| + margin_strut.Append(margins.block_start);
|
|
|
| // TODO(crbug.com/716930): We should also collapse margins below once we
|
| // remove LayoutInline splitting.
|
|
|
| // Should collapse margins if our child is a legacy block.
|
| - if (IsLegacyBlock(*child)) {
|
| - curr_bfc_offset_ +=
|
| - {border_and_padding_.inline_start + curr_child_margins_.inline_start,
|
| - curr_margin_strut_.Sum()};
|
| - MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
|
| - &container_builder_);
|
| - PositionPendingFloats(curr_bfc_offset_.block_offset, &container_builder_,
|
| + // TODO(ikilpatrick): I think this can be removed.
|
| + if (IsLegacyBlock(*child) && !is_new_fc) {
|
| + child_bfc_offset.block_offset += margin_strut.Sum();
|
| + MaybeUpdateFragmentBfcOffset(
|
| + ConstraintSpace(), child_bfc_offset.block_offset, &container_builder_);
|
| + // TODO(ikilpatrick): Check if child_bfc_offset.block_offset is correct -
|
| + // MaybeUpdateFragmentBfcOffset might have changed it due to clearance.
|
| + PositionPendingFloats(child_bfc_offset.block_offset, &container_builder_,
|
| MutableConstraintSpace());
|
| - curr_margin_strut_ = {};
|
| + margin_strut = {};
|
| }
|
| - child_bfc_offset.block_offset = curr_bfc_offset_.block_offset;
|
| - return child_bfc_offset;
|
| + return {child_bfc_offset, margin_strut, margins};
|
| }
|
|
|
| -void NGBlockLayoutAlgorithm::FinishChildLayout(
|
| +NGPreviousInflowPosition NGBlockLayoutAlgorithm::FinishChildLayout(
|
| const NGConstraintSpace& child_space,
|
| + const NGPreviousInflowPosition& previous_inflow_position,
|
| + const NGInflowChildData& child_data,
|
| const NGLayoutInputNode* child,
|
| NGLayoutResult* layout_result) {
|
| // Pull out unpositioned floats to the current fragment. This may needed if
|
| @@ -425,97 +458,134 @@ void NGBlockLayoutAlgorithm::FinishChildLayout(
|
| // Determine the fragment's position in the parent space.
|
| WTF::Optional<NGLogicalOffset> child_bfc_offset;
|
| if (child_space.IsNewFormattingContext())
|
| - child_bfc_offset = PositionNewFc(fragment, child_space);
|
| + child_bfc_offset = PositionNewFc(*child, previous_inflow_position, fragment,
|
| + child_data, child_space);
|
| else if (fragment.BfcOffset())
|
| child_bfc_offset = PositionWithBfcOffset(fragment);
|
| else if (IsLegacyBlock(*child))
|
| - child_bfc_offset = PositionLegacy(child_space);
|
| + child_bfc_offset = PositionLegacy(child_space, child_data);
|
| else if (container_builder_.BfcOffset())
|
| - child_bfc_offset = PositionWithParentBfc(child_space, fragment);
|
| + child_bfc_offset = PositionWithParentBfc(child_space, child_data, fragment);
|
|
|
| - NGLogicalOffset logical_offset = CalculateLogicalOffset(child_bfc_offset);
|
| + NGLogicalOffset logical_offset =
|
| + CalculateLogicalOffset(child_data.margins, child_bfc_offset);
|
|
|
| - // Update margin strut.
|
| - curr_margin_strut_ = fragment.EndMarginStrut();
|
| - curr_margin_strut_.Append(curr_child_margins_.block_end);
|
| + NGMarginStrut margin_strut = fragment.EndMarginStrut();
|
| + margin_strut.Append(child_data.margins.block_end);
|
|
|
| - // 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:
|
| + // Only modify content_size_ if the fragment's BlockSize is not empty. This is
|
| + // 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() +
|
| - border_and_padding_.InlineSum());
|
| + content_size_ = std::max(
|
| + content_size_, logical_offset.block_offset + fragment.BlockSize());
|
| + max_inline_size_ = std::max(
|
| + max_inline_size_, fragment.InlineSize() + child_data.margins.InlineSum() +
|
| + border_and_padding_.InlineSum());
|
|
|
| container_builder_.AddChild(layout_result, logical_offset);
|
| +
|
| + // Determine the child's end BFC block offset for the next child to use.
|
| + LayoutUnit child_end_bfc_block_offset;
|
| + if (child_bfc_offset) {
|
| + // TODO(crbug.com/716930): I think the fragment.BfcOffset() condition here
|
| + // can be removed once we've removed inline splitting.
|
| + if (fragment.BlockSize() || fragment.BfcOffset()) {
|
| + child_end_bfc_block_offset =
|
| + child_bfc_offset.value().block_offset + fragment.BlockSize();
|
| + } else {
|
| + DCHECK_EQ(LayoutUnit(), fragment.BlockSize());
|
| + child_end_bfc_block_offset = previous_inflow_position.bfc_block_offset;
|
| + }
|
| + } else {
|
| + child_end_bfc_block_offset = ConstraintSpace().BfcOffset().block_offset;
|
| + }
|
| +
|
| + return {child_end_bfc_block_offset,
|
| + logical_offset.block_offset + fragment.BlockSize(), margin_strut};
|
| }
|
|
|
| NGLogicalOffset NGBlockLayoutAlgorithm::PositionNewFc(
|
| + const NGLayoutInputNode& child,
|
| + const NGPreviousInflowPosition& previous_inflow_position,
|
| const NGBoxFragment& fragment,
|
| + const NGInflowChildData& child_data,
|
| const NGConstraintSpace& child_space) {
|
| + const ComputedStyle& child_style = child.Style();
|
| +
|
| + LayoutUnit child_bfc_offset_estimate =
|
| + child_data.bfc_offset_estimate.block_offset;
|
| +
|
| // 1. Position all pending floats to a temporary space.
|
| RefPtr<NGConstraintSpace> tmp_space =
|
| NGConstraintSpaceBuilder(&child_space)
|
| .SetIsNewFormattingContext(false)
|
| .ToConstraintSpace(child_space.WritingMode());
|
| - PositionFloats(curr_bfc_offset_.block_offset, curr_bfc_offset_.block_offset,
|
| - curr_bfc_offset_.block_offset,
|
| + PositionFloats(child_bfc_offset_estimate, child_bfc_offset_estimate,
|
| + child_bfc_offset_estimate,
|
| container_builder_.UnpositionedFloats(), tmp_space.Get());
|
|
|
| - NGLogicalOffset origin_offset = curr_bfc_offset_;
|
| - origin_offset.inline_offset += border_and_padding_.inline_start;
|
| + NGLogicalOffset origin_offset = {ConstraintSpace().BfcOffset().inline_offset +
|
| + border_and_padding_.inline_start,
|
| + child_bfc_offset_estimate};
|
| + AdjustToClearance(
|
| + GetClearanceOffset(ConstraintSpace().Exclusions(), child_style.Clear()),
|
| + &origin_offset);
|
|
|
| // 2. Find an estimated layout opportunity for our fragment.
|
| NGLayoutOpportunity opportunity = FindLayoutOpportunityForFragment(
|
| tmp_space->Exclusions().get(), child_space.AvailableSize(), origin_offset,
|
| - curr_child_margins_, fragment.Size());
|
| + child_data.margins, fragment.Size());
|
| +
|
| + NGMarginStrut margin_strut = previous_inflow_position.margin_strut;
|
|
|
| // 3. If the found opportunity lies on the same line with our estimated
|
| // child's BFC offset then merge fragment's margins with the current
|
| // MarginStrut.
|
| - if (opportunity.offset.block_offset == curr_bfc_offset_.block_offset)
|
| - curr_margin_strut_.Append(curr_child_margins_.block_start);
|
| - curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
|
| - curr_margin_strut_ = {};
|
| + if (opportunity.offset.block_offset == child_bfc_offset_estimate)
|
| + margin_strut.Append(child_data.margins.block_start);
|
| + child_bfc_offset_estimate += margin_strut.Sum();
|
|
|
| // 4. The child's BFC block offset is known here.
|
| - MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
|
| + MaybeUpdateFragmentBfcOffset(ConstraintSpace(), child_bfc_offset_estimate,
|
| &container_builder_);
|
| - PositionPendingFloats(curr_bfc_offset_.block_offset, &container_builder_,
|
| + PositionPendingFloats(child_bfc_offset_estimate, &container_builder_,
|
| MutableConstraintSpace());
|
|
|
| - origin_offset = curr_bfc_offset_;
|
| - origin_offset.inline_offset += border_and_padding_.inline_start;
|
| + origin_offset = {ConstraintSpace().BfcOffset().inline_offset +
|
| + border_and_padding_.inline_start,
|
| + child_bfc_offset_estimate};
|
| + AdjustToClearance(
|
| + GetClearanceOffset(ConstraintSpace().Exclusions(), child_style.Clear()),
|
| + &origin_offset);
|
|
|
| // 5. Find the final layout opportunity for the fragment after all pending
|
| // floats are positioned at the correct BFC block's offset.
|
| opportunity = FindLayoutOpportunityForFragment(
|
| MutableConstraintSpace()->Exclusions().get(), child_space.AvailableSize(),
|
| - origin_offset, curr_child_margins_, fragment.Size());
|
| + origin_offset, child_data.margins, fragment.Size());
|
|
|
| - curr_bfc_offset_ = opportunity.offset;
|
| - return curr_bfc_offset_;
|
| + return opportunity.offset;
|
| }
|
|
|
| NGLogicalOffset NGBlockLayoutAlgorithm::PositionWithBfcOffset(
|
| const NGBoxFragment& fragment) {
|
| DCHECK(fragment.BfcOffset());
|
| - curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset;
|
| - MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
|
| + LayoutUnit bfc_block_offset = fragment.BfcOffset().value().block_offset;
|
| + MaybeUpdateFragmentBfcOffset(ConstraintSpace(), bfc_block_offset,
|
| &container_builder_);
|
| - PositionPendingFloats(curr_bfc_offset_.block_offset, &container_builder_,
|
| + PositionPendingFloats(bfc_block_offset, &container_builder_,
|
| MutableConstraintSpace());
|
| return fragment.BfcOffset().value();
|
| }
|
|
|
| NGLogicalOffset NGBlockLayoutAlgorithm::PositionWithParentBfc(
|
| const NGConstraintSpace& space,
|
| + const NGInflowChildData& child_data,
|
| const NGBoxFragment& fragment) {
|
| // The child must be an in-flow zero-block-size fragment, use its end margin
|
| // strut for positioning.
|
| @@ -523,22 +593,28 @@ NGLogicalOffset NGBlockLayoutAlgorithm::PositionWithParentBfc(
|
| DCHECK_EQ(fragment.BlockSize(), LayoutUnit());
|
|
|
| NGMarginStrut margin_strut = fragment.EndMarginStrut();
|
| - margin_strut.Append(curr_child_margins_.block_end);
|
| -
|
| - curr_bfc_offset_ +=
|
| - {border_and_padding_.inline_start + curr_child_margins_.inline_start,
|
| - margin_strut.Sum()};
|
| - AdjustToClearance(space.ClearanceOffset(), &curr_bfc_offset_);
|
| - PositionPendingFloatsFromOffset(
|
| - curr_bfc_offset_.block_offset, curr_bfc_offset_.block_offset,
|
| - &container_builder_, MutableConstraintSpace());
|
| - return curr_bfc_offset_;
|
| + margin_strut.Append(child_data.margins.block_end);
|
| +
|
| + NGLogicalOffset bfc_offset = {
|
| + ConstraintSpace().BfcOffset().inline_offset +
|
| + border_and_padding_.inline_start + child_data.margins.inline_start,
|
| + child_data.bfc_offset_estimate.block_offset + margin_strut.Sum()};
|
| + AdjustToClearance(space.ClearanceOffset(), &bfc_offset);
|
| + PositionPendingFloatsFromOffset(bfc_offset.block_offset,
|
| + bfc_offset.block_offset, &container_builder_,
|
| + MutableConstraintSpace());
|
| + return bfc_offset;
|
| }
|
|
|
| NGLogicalOffset NGBlockLayoutAlgorithm::PositionLegacy(
|
| - const NGConstraintSpace& child_space) {
|
| - AdjustToClearance(child_space.ClearanceOffset(), &curr_bfc_offset_);
|
| - return curr_bfc_offset_;
|
| + const NGConstraintSpace& child_space,
|
| + const NGInflowChildData& child_data) {
|
| + NGLogicalOffset bfc_offset = {ConstraintSpace().BfcOffset().inline_offset +
|
| + border_and_padding_.inline_start +
|
| + child_data.margins.inline_start,
|
| + child_data.bfc_offset_estimate.block_offset};
|
| + AdjustToClearance(child_space.ClearanceOffset(), &bfc_offset);
|
| + return bfc_offset;
|
| }
|
|
|
| void NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
|
| @@ -609,8 +685,8 @@ NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins(NGLayoutInputNode* child) {
|
| }
|
|
|
| RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
|
| - const NGLogicalOffset& child_bfc_offset,
|
| - const NGLayoutInputNode& child) {
|
| + const NGLayoutInputNode& child,
|
| + const NGInflowChildData& child_data) {
|
| NGConstraintSpaceBuilder space_builder(MutableConstraintSpace());
|
| space_builder.SetAvailableSize(child_available_size_)
|
| .SetPercentageResolutionSize(child_percentage_size_);
|
| @@ -618,8 +694,8 @@ RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
|
| const ComputedStyle& child_style = child.Style();
|
| bool is_new_bfc = IsNewFormattingContextForBlockLevelChild(Style(), child);
|
| space_builder.SetIsNewFormattingContext(is_new_bfc)
|
| - .SetBfcOffset(child_bfc_offset)
|
| - .SetMarginStrut(curr_margin_strut_);
|
| + .SetBfcOffset(child_data.bfc_offset_estimate)
|
| + .SetMarginStrut(child_data.margin_strut);
|
|
|
| if (!is_new_bfc) {
|
| space_builder.SetUnpositionedFloats(
|
| @@ -646,7 +722,7 @@ RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
|
| // position in the formatting context, and are able to adjust the
|
| // fragmentation line.
|
| if (is_new_bfc) {
|
| - space_available -= child_bfc_offset.block_offset;
|
| + space_available -= child_data.bfc_offset_estimate.block_offset;
|
| }
|
| }
|
| space_builder.SetFragmentainerSpaceAvailable(space_available);
|
|
|