// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "core/layout/ng/ng_block_layout_algorithm.h"

#include "core/layout/ng/inline/ng_inline_node.h"
#include "core/layout/ng/ng_absolute_utils.h"
#include "core/layout/ng/ng_block_child_iterator.h"
#include "core/layout/ng/ng_constraint_space.h"
#include "core/layout/ng/ng_constraint_space_builder.h"
#include "core/layout/ng/ng_floats_utils.h"
#include "core/layout/ng/ng_fragment.h"
#include "core/layout/ng/ng_fragment_builder.h"
#include "core/layout/ng/ng_layout_opportunity_iterator.h"
#include "core/layout/ng/ng_length_utils.h"
#include "core/layout/ng/ng_out_of_flow_layout_part.h"
#include "core/layout/ng/ng_space_utils.h"
#include "core/style/ComputedStyle.h"
#include "platform/LengthFunctions.h"
#include "platform/wtf/Optional.h"

namespace blink {
namespace {

// Adjusts {@code offset} to the clearance line.
void AdjustToClearance(const WTF::Optional<LayoutUnit>& clearance_offset,
                       NGLogicalOffset* offset) {
  DCHECK(offset);
  if (clearance_offset) {
    offset->block_offset =
        std::max(clearance_offset.value(), offset->block_offset);
  }
}

// Returns if a child may be affected by its clear property. I.e. it will
// actually clear a float.
bool ClearanceMayAffectLayout(
    const NGConstraintSpace& space,
    const Vector<RefPtr<NGFloatingObject>>& unpositioned_floats,
    const ComputedStyle& child_style) {
  const NGExclusions& exclusions = *space.Exclusions();
  EClear clear = child_style.Clear();
  bool should_clear_left = (clear == EClear::kBoth || clear == EClear::kLeft);
  bool should_clear_right = (clear == EClear::kBoth || clear == EClear::kRight);

  if (exclusions.last_left_float && should_clear_left)
    return true;

  if (exclusions.last_right_float && should_clear_right)
    return true;

  auto should_clear_pred =
      [&](const RefPtr<const NGFloatingObject>& unpositioned_float) {
        return (unpositioned_float->IsLeft() && should_clear_left) ||
               (unpositioned_float->IsRight() && should_clear_right);
      };

  if (std::any_of(unpositioned_floats.begin(), unpositioned_floats.end(),
                  should_clear_pred))
    return true;

  return false;
}

bool IsLegacyBlock(const NGLayoutInputNode& node) {
  return node.IsBlock() && !ToNGBlockNode(node).CanUseNewLayout();
}

// Whether we've run out of space in this flow. If so, there will be no work
// left to do for this block in this fragmentainer.
bool IsOutOfSpace(const NGConstraintSpace& space, LayoutUnit content_size) {
  return space.HasBlockFragmentation() &&
         content_size >= space.FragmentainerSpaceAvailable();
}

}  // namespace

void MaybeUpdateFragmentBfcOffset(const NGConstraintSpace& space,
                                  const NGLogicalOffset& offset,
                                  NGFragmentBuilder* builder) {
  DCHECK(builder);
  if (!builder->BfcOffset()) {
    NGLogicalOffset mutable_offset(offset);
    AdjustToClearance(space.ClearanceOffset(), &mutable_offset);
    builder->SetBfcOffset(mutable_offset);
  }
}

void PositionPendingFloats(LayoutUnit origin_block_offset,
                           NGFragmentBuilder* container_builder,
                           NGConstraintSpace* space) {
  DCHECK(container_builder->BfcOffset())
      << "Parent BFC offset should be known here";
  const auto& floating_objects = container_builder->UnpositionedFloats();
  container_builder->MutablePositionedFloats().AppendVector(PositionFloats(
      origin_block_offset, container_builder->BfcOffset().value().block_offset,
      floating_objects, space));
  container_builder->MutableUnpositionedFloats().clear();
}

NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(NGBlockNode* node,
                                               NGConstraintSpace* space,
                                               NGBlockBreakToken* break_token)
    : NGLayoutAlgorithm(node, space, break_token),
      space_builder_(constraint_space_) {}

Optional<MinMaxContentSize> NGBlockLayoutAlgorithm::ComputeMinMaxContentSize()
    const {
  MinMaxContentSize sizes;

  // Size-contained elements don't consider their contents for intrinsic sizing.
  if (Style().ContainsSize())
    return sizes;

  // TODO: handle floats & orthogonal children.
  for (NGLayoutInputNode* node = Node()->FirstChild(); node;
       node = node->NextSibling()) {
    MinMaxContentSize child_sizes;
    if (node->IsInline()) {
      // From |NGBlockLayoutAlgorithm| perspective, we can handle |NGInlineNode|
      // almost the same as |NGBlockNode|, because an |NGInlineNode| includes
      // all inline nodes following |node| and their descendants, and produces
      // an anonymous box that contains all line boxes.
      // |NextSibling| returns the next block sibling, or nullptr, skipping all
      // following inline siblings and descendants.
      child_sizes = node->ComputeMinMaxContentSize();
    } else {
      Optional<MinMaxContentSize> child_minmax;
      if (NeedMinMaxContentSizeForContentContribution(node->Style())) {
        child_minmax = node->ComputeMinMaxContentSize();
      }

      child_sizes =
          ComputeMinAndMaxContentContribution(node->Style(), child_minmax);
    }

    sizes.min_content = std::max(sizes.min_content, child_sizes.min_content);
    sizes.max_content = std::max(sizes.max_content, child_sizes.max_content);
  }

  sizes.max_content = std::max(sizes.min_content, sizes.max_content);
  return sizes;
}

NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset(
    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;
  return {inline_offset, content_size_};
}

RefPtr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
  WTF::Optional<MinMaxContentSize> min_max_size;
  if (NeedMinMaxContentSize(ConstraintSpace(), Style()))
    min_max_size = ComputeMinMaxContentSize();

  border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) +
                        ComputePadding(ConstraintSpace(), Style());

  // TODO(layout-ng): For quirks mode, should we pass blockSize instead of -1?
  NGLogicalSize size(
      ComputeInlineSizeForFragment(ConstraintSpace(), Style(), min_max_size),
      ComputeBlockSizeForFragment(ConstraintSpace(), Style(),
                                  NGSizeIndefinite));

  // Our calculated block-axis size may be indefinite at this point.
  // If so, just leave the size as NGSizeIndefinite instead of subtracting
  // borders and padding.
  NGLogicalSize adjusted_size(size);
  if (size.block_size == NGSizeIndefinite)
    adjusted_size.inline_size -= border_and_padding_.InlineSum();
  else
    adjusted_size -= border_and_padding_;

  space_builder_.SetAvailableSize(adjusted_size)
      .SetPercentageResolutionSize(adjusted_size);

  container_builder_.SetDirection(constraint_space_->Direction());
  container_builder_.SetWritingMode(constraint_space_->WritingMode());
  container_builder_.SetSize(size);
  container_builder_.MutableUnpositionedFloats() =
      constraint_space_->UnpositionedFloats();

  NGBlockChildIterator child_iterator(Node()->FirstChild(), BreakToken());
  NGBlockChildIterator::Entry entry = child_iterator.NextChild();
  NGLayoutInputNode* child = entry.node;
  NGBreakToken* child_break_token = entry.token;

  // If we are resuming from a break token our start border and padding is
  // within a previous fragment.
  content_size_ = BreakToken() ? LayoutUnit() : border_and_padding_.block_start;

  curr_margin_strut_ = ConstraintSpace().MarginStrut();
  curr_bfc_offset_ = ConstraintSpace().BfcOffset();

  // 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_,
                                 &container_builder_);
    curr_margin_strut_ = NGMarginStrut();
  }

  // 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()) {
    MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
                                 &container_builder_);
    DCHECK_EQ(curr_margin_strut_, NGMarginStrut());
    DCHECK_EQ(container_builder_.BfcOffset().value(), NGLogicalOffset());
    curr_bfc_offset_ = {};
  }

  curr_bfc_offset_.block_offset += content_size_;

  while (child) {
    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);
    RefPtr<NGConstraintSpace> child_space =
        CreateConstraintSpaceForChild(child_bfc_offset, child);
    RefPtr<NGLayoutResult> layout_result =
        child->Layout(child_space.Get(), child_break_token);

    if (child->IsFloating())
      FinishFloatChildLayout(child->Style(), *child_space, layout_result.Get());
    else
      FinishChildLayout(*child_space, child, layout_result.Get());

    entry = child_iterator.NextChild();
    child = entry.node;
    child_break_token = entry.token;

    if (IsOutOfSpace(ConstraintSpace(), content_size_))
      break;
  }

  // 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
  //   border/padding.
  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();
  }

  // Recompute the block-axis size now that we know our content size.
  size.block_size =
      ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_);
  container_builder_.SetBlockSize(size.block_size);

  // Layout our absolute and fixed positioned children.
  NGOutOfFlowLayoutPart(ConstraintSpace(), Style(), &container_builder_).Run();

  // Non-empty blocks always know their position in space:
  if (size.block_size) {
    curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
    MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
                                 &container_builder_);
    PositionPendingFloats(curr_bfc_offset_.block_offset, &container_builder_,
                          MutableConstraintSpace());
  }

  // Margins collapsing:
  //   Do not collapse margins between the last in-flow child and bottom margin
  //   of its parent if the parent has height != auto()
  if (!Style().LogicalHeight().IsAuto()) {
    // TODO(glebl): handle minLogicalHeight, maxLogicalHeight.
    curr_margin_strut_ = NGMarginStrut();
  }
  container_builder_.SetEndMarginStrut(curr_margin_strut_);

  container_builder_.SetOverflowSize(
      NGLogicalSize(max_inline_size_, content_size_));

  if (ConstraintSpace().HasBlockFragmentation())
    FinalizeForFragmentation();

  return container_builder_.ToBoxFragment();
}

NGLogicalOffset NGBlockLayoutAlgorithm::PrepareChildLayout(
    NGLayoutInputNode* child) {
  DCHECK(child);

  curr_bfc_offset_ = container_builder_.BfcOffset()
                         ? container_builder_.BfcOffset().value()
                         : ConstraintSpace().BfcOffset();
  curr_bfc_offset_.block_offset += content_size_;

  // Calculate margins in parent's writing mode.
  curr_child_margins_ = CalculateMargins(
      child, *space_builder_.ToConstraintSpace(
                 FromPlatformWritingMode(Style().GetWritingMode())));

  bool should_position_pending_floats =
      !child->IsFloating() &&
      !IsNewFormattingContextForBlockLevelChild(Style(), *child) &&
      ClearanceMayAffectLayout(ConstraintSpace(),
                               container_builder_.UnpositionedFloats(),
                               child->Style());

  // Children which may clear a float need to force all the pending floats to
  // 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_);
    PositionPendingFloats(origin_point_block_offset, &container_builder_,
                          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);
  }

  // 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_,
                          MutableConstraintSpace());
    curr_margin_strut_ = {};
  }
  child_bfc_offset.block_offset = curr_bfc_offset_.block_offset;
  return child_bfc_offset;
}

void NGBlockLayoutAlgorithm::FinishChildLayout(
    const NGConstraintSpace& child_space,
    const NGLayoutInputNode* child,
    NGLayoutResult* layout_result) {
  // 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.
  container_builder_.MutableUnpositionedFloats().AppendVector(
      layout_result->UnpositionedFloats());

  NGBoxFragment fragment(
      ConstraintSpace().WritingMode(),
      ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get()));

  // 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);
  else if (fragment.BfcOffset())
    child_bfc_offset = PositionWithBfcOffset(fragment);
  else if (IsLegacyBlock(*child))
    child_bfc_offset = PositionLegacy(child_space);
  else if (container_builder_.BfcOffset())
    child_bfc_offset = PositionWithParentBfc(fragment);

  NGLogicalOffset logical_offset = CalculateLogicalOffset(child_bfc_offset);

  // Update margin strut.
  curr_margin_strut_ = fragment.EndMarginStrut();
  curr_margin_strut_.Append(curr_child_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:
  //   <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());

  container_builder_.AddChild(layout_result, logical_offset);
}

NGLogicalOffset NGBlockLayoutAlgorithm::PositionNewFc(
    const NGBoxFragment& fragment,
    const NGConstraintSpace& child_space) {
  // 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,
                 container_builder_.UnpositionedFloats(), tmp_space.Get());

  NGLogicalOffset origin_offset = curr_bfc_offset_;
  origin_offset.inline_offset += border_and_padding_.inline_start;

  // 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);

  // 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_ = {};

  // 4. The child's BFC block offset is known here.
  MaybeUpdateFragmentBfcOffset(ConstraintSpace(), curr_bfc_offset_,
                               &container_builder_);
  PositionPendingFloats(curr_bfc_offset_.block_offset, &container_builder_,
                        MutableConstraintSpace());

  origin_offset = curr_bfc_offset_;
  origin_offset.inline_offset += border_and_padding_.inline_start;

  // 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);

  curr_bfc_offset_ = opportunity.offset;
  return curr_bfc_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_,
                               &container_builder_);
  PositionPendingFloats(curr_bfc_offset_.block_offset, &container_builder_,
                        MutableConstraintSpace());
  return fragment.BfcOffset().value();
}

NGLogicalOffset NGBlockLayoutAlgorithm::PositionWithParentBfc(
    const NGBoxFragment& fragment) {
  // The child must be an in-flow zero-block-size fragment, use its end margin
  // strut for positioning.
  DCHECK(!fragment.BfcOffset());
  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()};
  return curr_bfc_offset_;
}

NGLogicalOffset NGBlockLayoutAlgorithm::PositionLegacy(
    const NGConstraintSpace& child_space) {
  AdjustToClearance(child_space.ClearanceOffset(), &curr_bfc_offset_);
  return curr_bfc_offset_;
}

void NGBlockLayoutAlgorithm::FinishFloatChildLayout(
    const ComputedStyle& child_style,
    const NGConstraintSpace& child_space,
    const NGLayoutResult* layout_result) {
  NGLogicalOffset origin_offset = constraint_space_->BfcOffset();
  origin_offset.inline_offset += border_and_padding_.inline_start;
  RefPtr<NGFloatingObject> floating_object = NGFloatingObject::Create(
      child_style, child_space.WritingMode(), child_space.AvailableSize(),
      origin_offset, constraint_space_->BfcOffset(), curr_child_margins_,
      layout_result->PhysicalFragment().Get());
  container_builder_.AddUnpositionedFloat(floating_object);

  // 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();
  LayoutUnit block_size = ComputeBlockSizeForFragment(
      ConstraintSpace(), Style(), used_block_size + content_size_);

  block_size -= used_block_size;
  DCHECK_GE(block_size, LayoutUnit())
      << "Adding and subtracting the used_block_size shouldn't leave the "
         "block_size for this fragment smaller than zero.";

  LayoutUnit space_left = ConstraintSpace().FragmentainerSpaceAvailable() -
                          ContainerBfcOffset().block_offset;
  DCHECK_GE(space_left, LayoutUnit());

  if (container_builder_.DidBreak()) {
    // One of our children broke. Even if we fit within the remaining space we
    // need to prepare a break token.
    container_builder_.SetUsedBlockSize(std::min(space_left, block_size) +
                                        used_block_size);
    container_builder_.SetBlockSize(std::min(space_left, block_size));
    container_builder_.SetBlockOverflow(space_left);
    return;
  }

  if (block_size > space_left) {
    // Need a break inside this block.
    container_builder_.SetUsedBlockSize(space_left + used_block_size);
    container_builder_.SetBlockSize(space_left);
    container_builder_.SetBlockOverflow(space_left);
    return;
  }

  // The end of the block fits in the current fragmentainer.
  container_builder_.SetBlockSize(block_size);
  container_builder_.SetBlockOverflow(content_size_);
}

NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins(
    NGLayoutInputNode* child,
    const NGConstraintSpace& space) {
  DCHECK(child);
  if (child->IsInline())
    return {};
  const ComputedStyle& child_style = child->Style();

  WTF::Optional<MinMaxContentSize> sizes;
  if (NeedMinMaxContentSize(space, child_style))
    sizes = child->ComputeMinMaxContentSize();

  LayoutUnit child_inline_size =
      ComputeInlineSizeForFragment(space, child_style, sizes);
  NGBoxStrut margins = ComputeMargins(space, child_style, space.WritingMode(),
                                      space.Direction());
  if (!child->IsFloating()) {
    ApplyAutoMargins(space, child_style, child_inline_size, &margins);
  }
  return margins;
}

RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
    const NGLogicalOffset& child_bfc_offset,
    NGLayoutInputNode* child) {
  DCHECK(child);

  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_);

  if (!is_new_bfc) {
    space_builder_.SetUnpositionedFloats(
        container_builder_.MutableUnpositionedFloats());
  }

  if (child->IsInline()) {
    // TODO(kojii): Setup space_builder_ appropriately for inline child.
    space_builder_.SetClearanceOffset(ConstraintSpace().ClearanceOffset());
    return space_builder_.ToConstraintSpace(
        FromPlatformWritingMode(Style().GetWritingMode()));
  }

  space_builder_
      .SetClearanceOffset(
          GetClearanceOffset(constraint_space_->Exclusions(), child_style))
      .SetIsShrinkToFit(ShouldShrinkToFit(Style(), child_style))
      .SetTextDirection(child_style.Direction());

  LayoutUnit space_available;
  if (constraint_space_->HasBlockFragmentation()) {
    space_available = ConstraintSpace().FragmentainerSpaceAvailable();
    // If a block establishes a new formatting context we must know our
    // 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_builder_.SetFragmentainerSpaceAvailable(space_available);

  return space_builder_.ToConstraintSpace(
      FromPlatformWritingMode(child_style.GetWritingMode()));
}
}  // namespace blink
