// 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 PositionPendingFloatsFromOffset(LayoutUnit origin_block_offset,
                                     LayoutUnit from_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, from_block_offset,
                     container_builder->BfcOffset().value().block_offset,
                     floating_objects, space));
  container_builder->MutableUnpositionedFloats().clear();
}

void PositionPendingFloats(LayoutUnit origin_block_offset,
                           NGFragmentBuilder* container_builder,
                           NGConstraintSpace* space) {
  DCHECK(container_builder->BfcOffset())
      << "Parent BFC offset should be known here";
  LayoutUnit from_block_offset =
      container_builder->BfcOffset().value().block_offset;
  PositionPendingFloatsFromOffset(origin_block_offset, from_block_offset,
                                  container_builder, space);
}

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

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

  child_available_size_ = adjusted_size;
  child_percentage_size_ = 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);

  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(child_space, 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,
                 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 NGConstraintSpace& space,
    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()};
  AdjustToClearance(space.ClearanceOffset(), &curr_bfc_offset_);
  PositionPendingFloatsFromOffset(
      curr_bfc_offset_.block_offset, curr_bfc_offset_.block_offset,
      &container_builder_, MutableConstraintSpace());
  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) {
  DCHECK(child);
  if (child->IsInline())
    return {};
  const ComputedStyle& child_style = child->Style();

  RefPtr<NGConstraintSpace> space =
      NGConstraintSpaceBuilder(MutableConstraintSpace())
          .SetAvailableSize(child_available_size_)
          .SetPercentageResolutionSize(child_percentage_size_)
          .ToConstraintSpace(ConstraintSpace().WritingMode());

  NGBoxStrut margins = ComputeMargins(*space, child_style, space->WritingMode(),
                                      space->Direction());

  // TODO(ikilpatrick): Move the auto margins calculation for different writing
  // modes to post-layout.
  if (!child->IsFloating()) {
    WTF::Optional<MinMaxContentSize> sizes;
    if (NeedMinMaxContentSize(*space, child_style))
      sizes = child->ComputeMinMaxContentSize();

    LayoutUnit child_inline_size =
        ComputeInlineSizeForFragment(*space, child_style, sizes);
    ApplyAutoMargins(*space, child_style, child_inline_size, &margins);
  }
  return margins;
}

RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
    const NGLogicalOffset& child_bfc_offset,
    const NGLayoutInputNode& child) {
  NGConstraintSpaceBuilder space_builder(MutableConstraintSpace());
  space_builder.SetAvailableSize(child_available_size_)
      .SetPercentageResolutionSize(child_percentage_size_);

  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
