// 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/ng_absolute_utils.h"
#include "core/layout/ng/ng_block_break_token.h"
#include "core/layout/ng/ng_block_child_iterator.h"
#include "core/layout/ng/ng_box_fragment.h"
#include "core/layout/ng/ng_constraint_space.h"
#include "core/layout/ng/ng_constraint_space_builder.h"
#include "core/layout/ng/ng_fragment.h"
#include "core/layout/ng/ng_fragment_builder.h"
#include "core/layout/ng/ng_inline_node.h"
#include "core/layout/ng/ng_layout_opportunity_iterator.h"
#include "core/layout/ng/ng_length_utils.h"
#include "core/layout/ng/ng_line_builder.h"
#include "core/layout/ng/ng_out_of_flow_layout_part.h"
#include "core/style/ComputedStyle.h"
#include "platform/LengthFunctions.h"
#include "wtf/Optional.h"

namespace blink {
namespace {

// Whether child's constraint space should shrink to its intrinsic width.
// This is needed for buttons, select, input, floats and orthogonal children.
// See LayoutBox::sizesLogicalWidthToFitContent for the rationale behind this.
bool ShouldShrinkToFit(const NGConstraintSpace& parent_space,
                       const ComputedStyle& child_style) {
  NGWritingMode child_writing_mode =
      FromPlatformWritingMode(child_style.getWritingMode());
  // Whether the child and the containing block are parallel to each other.
  // Example: vertical-rl and vertical-lr
  bool is_in_parallel_flow =
      IsParallelWritingMode(parent_space.WritingMode(), child_writing_mode);

  return child_style.display() == EDisplay::kInlineBlock ||
         child_style.isFloating() || !is_in_parallel_flow;
}

// Returns max of 2 {@code WTF::Optional} values.
template <typename T>
WTF::Optional<T> OptionalMax(const WTF::Optional<T>& value1,
                             const WTF::Optional<T>& value2) {
  if (value1 && value2) {
    return std::max(value1.value(), value2.value());
  } else if (value1) {
    return value1;
  }
  return value2;
}

WTF::Optional<LayoutUnit> GetClearanceOffset(
    const std::shared_ptr<NGExclusions>& exclusions,
    const ComputedStyle& style) {
  const NGExclusion* right_exclusion = exclusions->last_right_float;
  const NGExclusion* left_exclusion = exclusions->last_left_float;

  WTF::Optional<LayoutUnit> left_offset;
  if (left_exclusion) {
    left_offset = left_exclusion->rect.BlockEndOffset();
  }
  WTF::Optional<LayoutUnit> right_offset;
  if (right_exclusion) {
    right_offset = right_exclusion->rect.BlockEndOffset();
  }

  switch (style.clear()) {
    case EClear::kNone:
      return WTF::nullopt;  // nothing to do here.
    case EClear::kLeft:
      return left_offset;
    case EClear::kRight:
      return right_offset;
    case EClear::kBoth:
      return OptionalMax<LayoutUnit>(left_offset, right_offset);
    default:
      ASSERT_NOT_REACHED();
  }
  return WTF::nullopt;
}

// Creates an exclusion from the fragment that will be placed in the provided
// layout opportunity.
NGExclusion CreateExclusion(const NGFragment& fragment,
                            const NGLayoutOpportunity& opportunity,
                            const LayoutUnit float_offset,
                            const NGBoxStrut& margins,
                            NGExclusion::Type exclusion_type) {
  NGExclusion exclusion;
  exclusion.type = exclusion_type;
  NGLogicalRect& rect = exclusion.rect;
  rect.offset = opportunity.offset;
  rect.offset.inline_offset += float_offset;

  rect.size.inline_size = fragment.InlineSize() + margins.InlineSum();
  rect.size.block_size = fragment.BlockSize() + margins.BlockSum();
  return exclusion;
}

// Adjusts the provided offset to the top edge alignment rule.
// Top edge alignment rule: the outer top of a floating box may not be higher
// than the outer top of any block or floated box generated by an element
// earlier in the source document.
NGLogicalOffset AdjustToTopEdgeAlignmentRule(const NGConstraintSpace& space,
                                             const NGLogicalOffset& offset) {
  NGLogicalOffset adjusted_offset = offset;
  LayoutUnit& adjusted_block_offset = adjusted_offset.block_offset;
  if (space.Exclusions()->last_left_float)
    adjusted_block_offset =
        std::max(adjusted_block_offset,
                 space.Exclusions()->last_left_float->rect.BlockStartOffset());
  if (space.Exclusions()->last_right_float)
    adjusted_block_offset =
        std::max(adjusted_block_offset,
                 space.Exclusions()->last_right_float->rect.BlockStartOffset());
  return adjusted_offset;
}

// Finds a layout opportunity for the fragment.
// It iterates over all layout opportunities in the constraint space and returns
// the first layout opportunity that is wider than the fragment or returns the
// last one which is always the widest.
//
// @param space Constraint space that is used to find layout opportunity for
//              the fragment.
// @param fragment Fragment that needs to be placed.
// @param origin_point {@code space}'s offset relative to the space that
//                     establishes a new formatting context that we're currently
//                     in and where all our exclusions reside.
// @param margins Margins of the fragment.
// @return Layout opportunity for the fragment.
const NGLayoutOpportunity FindLayoutOpportunityForFragment(
    const NGConstraintSpace* space,
    const NGFragment& fragment,
    const NGLogicalOffset& origin_point,
    const NGBoxStrut& margins) {
  NGLogicalOffset adjusted_origin_point =
      AdjustToTopEdgeAlignmentRule(*space, origin_point);

  NGLayoutOpportunityIterator opportunity_iter(space, adjusted_origin_point);
  NGLayoutOpportunity opportunity;
  NGLayoutOpportunity opportunity_candidate = opportunity_iter.Next();

  while (!opportunity_candidate.IsEmpty()) {
    opportunity = opportunity_candidate;
    // Checking opportunity's block size is not necessary as a float cannot be
    // positioned on top of another float inside of the same constraint space.
    auto fragment_inline_size = fragment.InlineSize() + margins.InlineSum();
    if (opportunity.size.inline_size >= fragment_inline_size)
      break;

    opportunity_candidate = opportunity_iter.Next();
  }
  return opportunity;
}

// Calculates the logical offset for opportunity.
NGLogicalOffset CalculateLogicalOffsetForOpportunity(
    const NGLayoutOpportunity& opportunity,
    const LayoutUnit float_offset,
    const NGLogicalOffset& from_offset,
    NGFloatingObject* floating_object) {
  DCHECK(floating_object);
  auto margins = floating_object->margins;
  // Adjust to child's margin.
  LayoutUnit inline_offset = margins.inline_start;
  LayoutUnit block_offset = margins.block_start;

  // Offset from the opportunity's block/inline start.
  inline_offset += opportunity.offset.inline_offset;
  block_offset += opportunity.offset.block_offset;

  // Adjust to float: right offset if needed.
  inline_offset += float_offset;

  block_offset -= from_offset.block_offset;
  inline_offset -= from_offset.inline_offset;

  return NGLogicalOffset(inline_offset, block_offset);
}

// Calculates the relative position from {@code from_offset} of the
// floating object that is requested to be positioned from {@code origin_point}.
NGLogicalOffset PositionFloat(const NGLogicalOffset& origin_point,
                              const NGLogicalOffset& from_offset,
                              NGFloatingObject* floating_object,
                              NGConstraintSpace* new_parent_space) {
  DCHECK(floating_object);
  const auto* float_space = floating_object->space.get();
  DCHECK(floating_object->fragment) << "Fragment cannot be null here";

  // TODO(ikilpatrick): The writing mode switching here looks wrong.
  NGBoxFragment float_fragment(
      float_space->WritingMode(),
      toNGPhysicalBoxFragment(floating_object->fragment.get()));

  // Find a layout opportunity that will fit our float.
  const NGLayoutOpportunity opportunity = FindLayoutOpportunityForFragment(
      float_space, float_fragment, origin_point, floating_object->margins);
  DCHECK(!opportunity.IsEmpty()) << "Opportunity is empty but it shouldn't be";

  // Calculate the float offset if needed.
  LayoutUnit float_offset;
  if (floating_object->exclusion_type == NGExclusion::kFloatRight) {
    LayoutUnit float_margin_box_inline_size =
        float_fragment.InlineSize() + floating_object->margins.InlineSum();
    float_offset = opportunity.size.inline_size - float_margin_box_inline_size;
  }

  // Add the float as an exclusion.
  const NGExclusion exclusion = CreateExclusion(
      float_fragment, opportunity, float_offset, floating_object->margins,
      floating_object->exclusion_type);
  new_parent_space->AddExclusion(exclusion);

  return CalculateLogicalOffsetForOpportunity(opportunity, float_offset,
                                              from_offset, floating_object);
}

// Updates the Floating Object's left offset from the provided parent_space
// and {@code floating_object}'s space and margins.
void UpdateFloatingObjectLeftOffset(const NGConstraintSpace& new_parent_space,
                                    const NGLogicalOffset& float_logical_offset,
                                    NGFloatingObject* floating_object) {
  DCHECK(floating_object);
  // TODO(glebl): We should use physical offset here.
  floating_object->left_offset =
      floating_object->original_parent_space->BfcOffset().inline_offset -
      new_parent_space.BfcOffset().inline_offset +
      float_logical_offset.inline_offset;
}

// Positions pending floats stored on the fragment builder starting from
// {@code origin_point_block_offset}.
void PositionPendingFloats(const LayoutUnit origin_point_block_offset,
                           NGConstraintSpace* new_parent_space,
                           NGFragmentBuilder* builder) {
  DCHECK(builder->BfcOffset()) << "Parent BFC offset should be known here";
  LayoutUnit bfc_block_offset = builder->BfcOffset().value().block_offset;

  for (auto& floating_object : builder->UnpositionedFloats()) {
    const auto* float_space = floating_object->space.get();
    const NGConstraintSpace* original_parent_space =
        floating_object->original_parent_space.get();

    NGLogicalOffset origin_point = {float_space->BfcOffset().inline_offset,
                                    origin_point_block_offset};
    NGLogicalOffset from_offset = {
        original_parent_space->BfcOffset().inline_offset, bfc_block_offset};

    NGLogicalOffset float_fragment_offset = PositionFloat(
        origin_point, from_offset, floating_object.get(), new_parent_space);
    builder->AddFloatingObject(floating_object, float_fragment_offset);
    UpdateFloatingObjectLeftOffset(*new_parent_space, float_fragment_offset,
                                   floating_object.get());
  }
  builder->MutableUnpositionedFloats().clear();
}

// Whether an in-flow block-level child creates a new formatting context.
//
// This will *NOT* check the following cases:
//  - The child is out-of-flow, e.g. floating or abs-pos.
//  - The child is a inline-level, e.g. "display: inline-block".
//  - The child establishes a new formatting context, but should be a child of
//    another layout algorithm, e.g. "display: table-caption" or flex-item.
bool IsNewFormattingContextForInFlowBlockLevelChild(
    const NGConstraintSpace& space,
    const ComputedStyle& style) {
  // TODO(layout-dev): This doesn't capture a few cases which can't be computed
  // directly from style yet:
  //  - The child is a <fieldset>.
  //  - "column-span: all" is set on the child (requires knowledge that we are
  //    in a multi-col formatting context).
  //    (https://drafts.csswg.org/css-multicol-1/#valdef-column-span-all)

  if (style.specifiesColumns() || style.containsPaint() ||
      style.containsLayout())
    return true;

  if (!style.isOverflowVisible())
    return true;

  EDisplay display = style.display();
  if (display == EDisplay::kGrid || display == EDisplay::kFlex ||
      display == EDisplay::kWebkitBox)
    return true;

  if (space.WritingMode() != FromPlatformWritingMode(style.getWritingMode()))
    return true;

  return false;
}

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

NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(
    NGBlockNode* node,
    NGConstraintSpace* constraint_space,
    NGBlockBreakToken* break_token)
    : node_(node),
      constraint_space_(constraint_space),
      break_token_(break_token),
      builder_(NGPhysicalFragment::kFragmentBox, node),
      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->Type() == NGLayoutInputNode::kLegacyInline) {
      // 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 = toNGInlineNode(node)->ComputeMinMaxContentSize();
    } else {
      Optional<MinMaxContentSize> child_minmax;
      NGBlockNode* block_child = toNGBlockNode(node);
      if (NeedMinMaxContentSizeForContentContribution(block_child->Style())) {
        child_minmax = block_child->ComputeMinMaxContentSize();
      }

      child_sizes = ComputeMinAndMaxContentContribution(block_child->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) {
  LayoutUnit inline_offset =
      border_and_padding_.inline_start + curr_child_margins_.inline_start;
  LayoutUnit block_offset = content_size_;
  if (known_fragment_offset) {
    block_offset = known_fragment_offset.value().block_offset -
                   builder_.BfcOffset().value().block_offset;
  }
  return {inline_offset, block_offset};
}

void NGBlockLayoutAlgorithm::UpdateFragmentBfcOffset(
    const NGLogicalOffset& offset) {
  if (!builder_.BfcOffset()) {
    NGLogicalOffset bfc_offset = offset;
    if (ConstraintSpace().ClearanceOffset()) {
      bfc_offset.block_offset = std::max(
          ConstraintSpace().ClearanceOffset().value(), offset.block_offset);
    }
    builder_.SetBfcOffset(bfc_offset);
  }
}

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

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

  LayoutUnit inline_size =
      ComputeInlineSizeForFragment(ConstraintSpace(), Style(), sizes);
  LayoutUnit adjusted_inline_size =
      inline_size - border_and_padding_.InlineSum();
  // TODO(layout-ng): For quirks mode, should we pass blockSize instead of
  // -1?
  LayoutUnit block_size =
      ComputeBlockSizeForFragment(ConstraintSpace(), Style(), NGSizeIndefinite);
  LayoutUnit adjusted_block_size(block_size);
  // 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.
  if (adjusted_block_size != NGSizeIndefinite)
    adjusted_block_size -= border_and_padding_.BlockSum();

  space_builder_
      .SetAvailableSize(
          NGLogicalSize(adjusted_inline_size, adjusted_block_size))
      .SetPercentageResolutionSize(
          NGLogicalSize(adjusted_inline_size, adjusted_block_size));

  builder_.SetDirection(constraint_space_->Direction());
  builder_.SetWritingMode(constraint_space_->WritingMode());
  builder_.SetInlineSize(inline_size).SetBlockSize(block_size);

  NGBlockChildIterator child_iterator(node_->FirstChild(), break_token_);
  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_ = break_token_ ? 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();
    UpdateFragmentBfcOffset(curr_bfc_offset_);
    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_);
    DCHECK_EQ(builder_.BfcOffset().value(), NGLogicalOffset());
    DCHECK_EQ(curr_margin_strut_, NGMarginStrut());
  }

  curr_bfc_offset_.block_offset += content_size_;

  while (child) {
    if (child->Type() == NGLayoutInputNode::kLegacyBlock) {
      NGBlockNode* current_block_child = toNGBlockNode(child);
      EPosition position = current_block_child->Style().position();
      if (position == EPosition::kAbsolute || position == EPosition::kFixed) {
        builder_.AddOutOfFlowChildCandidate(current_block_child,
                                            GetChildSpaceOffset());
        NGBlockChildIterator::Entry entry = child_iterator.NextChild();
        child = entry.node;
        child_break_token = entry.token;
        continue;
      }
    }

    PrepareChildLayout(child);
    RefPtr<NGConstraintSpace> child_space =
        CreateConstraintSpaceForChild(child);
    RefPtr<NGLayoutResult> layout_result =
        child->Layout(child_space.get(), child_break_token);

    FinishChildLayout(child, child_space.get(), layout_result);

    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.
  block_size =
      ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_);
  builder_.SetBlockSize(block_size);

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

  // 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_);
    PositionPendingFloats(curr_bfc_offset_.block_offset,
                          MutableConstraintSpace(), &builder_);
  }

  // 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();
  }
  builder_.SetEndMarginStrut(curr_margin_strut_);

  builder_.SetInlineOverflow(max_inline_size_).SetBlockOverflow(content_size_);

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

  return builder_.ToBoxFragment();
}

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

  // Margins collapsing:
  // - An inline node doesn't have any margins to collapse with, so always
  //   can determine its position in space.
  if (child->Type() == NGLayoutInputNode::kLegacyInline) {
    curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
    UpdateFragmentBfcOffset(curr_bfc_offset_);
    PositionPendingFloats(curr_bfc_offset_.block_offset,
                          MutableConstraintSpace(), &builder_);
    curr_margin_strut_ = {};
    curr_child_margins_ = {};
    return;
  }

  NGBlockNode* block_child = toNGBlockNode(child);
  const ComputedStyle& child_style = block_child->Style();

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

  // Clearance:
  // - *Always* collapse margins and update *container*'s BFC offset.
  // - Position all pending floats since the fragment's BFC offset is known.
  if (child_style.clear() != EClear::kNone) {
    curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
    UpdateFragmentBfcOffset(curr_bfc_offset_);
    // Only collapse margins if it's an adjoining block with clearance.
    if (!content_size_) {
      curr_margin_strut_ = {};
      curr_child_margins_.block_start = LayoutUnit();
    }
    PositionPendingFloats(curr_bfc_offset_.block_offset,
                          MutableConstraintSpace(), &builder_);
  }

  // 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 space because:
  // 1) Floats do not participate in margins collapsing.
  // 2) Floats margins are used separately to calculate floating exclusions.
  if (!child_style.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);
  }
}

void NGBlockLayoutAlgorithm::FinishChildLayout(
    NGLayoutInputNode* child,
    NGConstraintSpace* child_space,
    RefPtr<NGLayoutResult> layout_result) {
  NGBoxFragment fragment(
      ConstraintSpace().WritingMode(),
      toNGPhysicalBoxFragment(layout_result->PhysicalFragment().get()));

  // 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.
  builder_.MutableUnpositionedFloats().appendVector(
      layout_result->UnpositionedFloats());

  if (child->Type() == NGLayoutInputNode::kLegacyBlock &&
      toNGBlockNode(child)->Style().isFloating()) {
    RefPtr<NGFloatingObject> floating_object = NGFloatingObject::Create(
        child_space, constraint_space_, toNGBlockNode(child)->Style(),
        curr_child_margins_, layout_result->PhysicalFragment().get());
    builder_.AddUnpositionedFloat(floating_object);
    // No need to postpone the positioning if we know the correct offset.
    if (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, MutableConstraintSpace(),
                            &builder_);
    }
    return;
  }

  // Determine the fragment's position in the parent space either by using
  // content_size_ or known fragment's BFC offset.
  WTF::Optional<NGLogicalOffset> bfc_offset;
  if (child_space->IsNewFormattingContext()) {
    // TODO(ikilpatrick): We may need to place ourself within the BFC
    // before a new formatting context child is laid out. (Not after layout as
    // is done here).
    curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
    bfc_offset = curr_bfc_offset_;
  } else if (fragment.BfcOffset()) {
    // 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_);
    PositionPendingFloats(curr_bfc_offset_.block_offset,
                          MutableConstraintSpace(), &builder_);
  }
  NGLogicalOffset logical_offset = CalculateLogicalOffset(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());

  builder_.AddChild(layout_result, logical_offset);
}

void NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
  LayoutUnit used_block_size =
      break_token_ ? break_token_->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.";

  DCHECK(builder_.BfcOffset()) << "We must have our BfcOffset by this point "
                                  "to determine the space left in the flow.";
  LayoutUnit space_left = ConstraintSpace().FragmentainerSpaceAvailable() -
                          builder_.BfcOffset().value().block_offset;
  DCHECK_GE(space_left, LayoutUnit());

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

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

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

NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins(
    NGBlockNode* child,
    const NGConstraintSpace& space) {
  DCHECK(child);
  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_style.isFloating()) {
    ApplyAutoMargins(space, child_style, child_inline_size, &margins);
  }
  return margins;
}

RefPtr<NGConstraintSpace> NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
    NGLayoutInputNode* child) {
  DCHECK(child);

  if (child->Type() == NGLayoutInputNode::kLegacyInline) {
    // TODO(kojii): Setup space_builder_ appropriately for inline child.
    space_builder_.SetBfcOffset(curr_bfc_offset_);
    return space_builder_.ToConstraintSpace(
        FromPlatformWritingMode(Style().getWritingMode()));
  }

  const ComputedStyle& child_style = toNGBlockNode(child)->Style();

  bool is_new_bfc = IsNewFormattingContextForInFlowBlockLevelChild(
      ConstraintSpace(), child_style);
  space_builder_.SetIsNewFormattingContext(is_new_bfc)
      .SetBfcOffset(curr_bfc_offset_)
      .SetClearanceOffset(
          GetClearanceOffset(constraint_space_->Exclusions(), child_style))
      .SetIsShrinkToFit(ShouldShrinkToFit(ConstraintSpace(), child_style))
      .SetTextDirection(child_style.direction());

  // 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_style.isFloating() ? NGMarginStrut()
                                                         : curr_margin_strut_);

  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) {
      DCHECK(builder_.BfcOffset());
      space_available -= curr_bfc_offset_.block_offset;
    }
  }
  space_builder_.SetFragmentainerSpaceAvailable(space_available);

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