// 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 "third_party/blink/renderer/core/layout/ng/ng_block_node.h"

#include <memory>

#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/html_marquee_element.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_fieldset.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_set.h"
#include "third_party/blink/renderer/core/layout/min_max_size.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
#include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/shapes/shape_outside_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/text/writing_mode.h"

namespace blink {

namespace {

inline LayoutMultiColumnFlowThread* GetFlowThread(const LayoutBox& box) {
  if (!box.IsLayoutBlockFlow())
    return nullptr;
  return ToLayoutBlockFlow(box).MultiColumnFlowThread();
}

#define WITH_ALGORITHM(ret, func, argdecl, args)                             \
  ret func##WithAlgorithm(NGBlockNode node, const NGConstraintSpace& space,  \
                          const NGBreakToken* break_token, argdecl) {        \
    const auto* token = ToNGBlockBreakToken(break_token);                    \
    const ComputedStyle& style = node.Style();                               \
    if (node.GetLayoutBox()->IsLayoutNGFlexibleBox())                        \
      return NGFlexLayoutAlgorithm(node, space, token).func args;            \
    if (node.GetLayoutBox()->IsLayoutNGFieldset())                           \
      return NGFieldsetLayoutAlgorithm(node, space, token).func args;        \
    /* If there's a legacy layout box, we can only do block fragmentation if \
     * we would have done block fragmentation with the legacy engine.        \
     * Otherwise writing data back into the legacy tree will fail. Look for  \
     * the flow thread. */                                                   \
    if (GetFlowThread(*node.GetLayoutBox())) {                               \
      if (style.IsOverflowPaged())                                           \
        return NGPageLayoutAlgorithm(node, space, token).func args;          \
      if (style.SpecifiesColumns())                                          \
        return NGColumnLayoutAlgorithm(node, space, token).func args;        \
      NOTREACHED();                                                          \
    }                                                                        \
    return NGBlockLayoutAlgorithm(node, space, token).func args;             \
  }

WITH_ALGORITHM(scoped_refptr<NGLayoutResult>, Layout, void*, ())
WITH_ALGORITHM(base::Optional<MinMaxSize>,
               ComputeMinMaxSize,
               MinMaxSizeInput input,
               (input))

#undef WITH_ALGORITHM

bool IsFloatFragment(const NGPhysicalFragment& fragment) {
  const LayoutObject* layout_object = fragment.GetLayoutObject();
  return layout_object && layout_object->IsFloating() && fragment.IsBox();
}

void UpdateLegacyMultiColumnFlowThread(
    NGBlockNode node,
    LayoutMultiColumnFlowThread* flow_thread,
    const NGConstraintSpace& constraint_space,
    const NGPhysicalBoxFragment& fragment) {
  WritingMode writing_mode = constraint_space.GetWritingMode();
  LayoutUnit flow_end;
  LayoutUnit column_block_size;
  bool has_processed_first_child = false;

  // Stitch the columns together.
  for (const auto& child : fragment.Children()) {
    NGFragment child_fragment(writing_mode, *child);
    flow_end += child_fragment.BlockSize();
    // Non-uniform fragmentainer widths not supported by legacy layout.
    DCHECK(!has_processed_first_child ||
           flow_thread->LogicalWidth() == child_fragment.InlineSize());
    if (!has_processed_first_child) {
      // The offset of the flow thread should be the same as that of the first
      // first column.
      flow_thread->SetX(child.Offset().left);
      flow_thread->SetY(child.Offset().top);
      flow_thread->SetLogicalWidth(child_fragment.InlineSize());
      column_block_size = child_fragment.BlockSize();
      has_processed_first_child = true;
    }
  }

  if (LayoutMultiColumnSet* column_set = flow_thread->FirstMultiColumnSet()) {
    NGFragment logical_fragment(writing_mode, fragment);
    auto border_scrollbar_padding =
        CalculateBorderScrollbarPadding(constraint_space, node);

    column_set->SetLogicalLeft(border_scrollbar_padding.inline_start);
    column_set->SetLogicalTop(border_scrollbar_padding.block_start);
    column_set->SetLogicalWidth(logical_fragment.InlineSize() -
                                border_scrollbar_padding.InlineSum());
    column_set->SetLogicalHeight(column_block_size);
    column_set->EndFlow(flow_end);
  }
  // TODO(mstensho): Update all column boxes, not just the first column set
  // (like we do above). This is needed to support column-span:all.

  flow_thread->UpdateFromNG();
  flow_thread->ValidateColumnSets();
  flow_thread->SetLogicalHeight(flow_end);
  flow_thread->UpdateAfterLayout();
  flow_thread->ClearNeedsLayout();
}

NGConstraintSpaceBuilder CreateConstraintSpaceBuilderForMinMax(
    NGBlockNode node,
    NGPhysicalSize icb_size) {
  return NGConstraintSpaceBuilder(node.Style().GetWritingMode(), icb_size)
      .SetTextDirection(node.Style().Direction())
      .SetIsIntermediateLayout(true)
      .SetIsNewFormattingContext(node.CreatesNewFormattingContext())
      .SetFloatsBfcBlockOffset(LayoutUnit());
}

LayoutUnit CalculateAvailableInlineSizeForLegacy(
    const LayoutBox& box,
    const NGConstraintSpace& space) {
  if (box.StyleRef().LogicalWidth().IsPercent()) {
    if (box.ShouldComputeSizeAsReplaced())
      return space.ReplacedPercentageResolutionSize().inline_size;

    return space.PercentageResolutionSize().inline_size;
  }

  return space.AvailableSize().inline_size;
}

LayoutUnit CalculateAvailableBlockSizeForLegacy(
    const LayoutBox& box,
    const NGConstraintSpace& space) {
  if (box.StyleRef().LogicalHeight().IsPercent()) {
    if (box.ShouldComputeSizeAsReplaced())
      return space.ReplacedPercentageResolutionSize().block_size;

    return space.PercentageResolutionSize().block_size;
  }

  return space.AvailableSize().block_size;
}

}  // namespace

scoped_refptr<NGLayoutResult> NGBlockNode::Layout(
    const NGConstraintSpace& constraint_space,
    const NGBreakToken* break_token) {
  // Use the old layout code and synthesize a fragment.
  if (!CanUseNewLayout()) {
    return RunOldLayout(constraint_space);
  }

  LayoutBlockFlow* block_flow =
      box_->IsLayoutNGMixin() ? ToLayoutBlockFlow(box_) : nullptr;
  NGLayoutInputNode first_child = FirstChild();
  scoped_refptr<NGLayoutResult> layout_result;
  if (block_flow) {
    layout_result =
        block_flow->CachedLayoutResult(constraint_space, break_token);
    if (layout_result) {
      // TODO(layoutng): Figure out why these two call can't be inside the
      // !constraint_space.IsIntermediateLayout() block below.
      UpdateShapeOutsideInfoIfNeeded(
          constraint_space.PercentageResolutionSize().inline_size);
      // We may need paint invalidation even if we can reuse layout, as our
      // paint offset/visual rect may have changed due to relative
      // positioning changes. Otherwise we fail fast/css/
      // fast/css/relative-positioned-block-with-inline-ancestor-and-parent
      // -dynamic.html
      // TODO(layoutng): See if we can optimize this. When we natively
      // support relative positioning in NG we can probably remove this,
      box_->SetShouldCheckForPaintInvalidation();

      // We have to re-set the cached result here, because it is used for
      // LayoutNGMixin::CurrentFragment and therefore has to be up-to-date.
      // In particular, that fragment would have an incorrect offset if we
      // don't re-set the result here.
      block_flow->SetCachedLayoutResult(constraint_space, break_token,
                                        *layout_result);
      if (!constraint_space.IsIntermediateLayout() && first_child &&
          first_child.IsInline()) {
        block_flow->UpdatePaintFragmentFromCachedLayoutResult(
            break_token, layout_result->PhysicalFragment(),
            layout_result->Offset());
      }
      return layout_result;
    }
  }

  // This follows the code from LayoutBox::UpdateLogicalWidth
  if (box_->NeedsPreferredWidthsRecalculation() &&
      !box_->PreferredLogicalWidthsDirty()) {
    // Laying out this object means that its containing block is also being
    // laid out. This object is special, in that its min/max widths depend on
    // the ancestry (min/max width calculation should ideally be strictly
    // bottom-up, but that's not always the case), so since the containing
    // block size may have changed, we need to recalculate the min/max widths
    // of this object, and every child that has the same issue, recursively.
    box_->SetPreferredLogicalWidthsDirty(kMarkOnlyThis);
    // Since all this takes place during actual layout, instead of being part
    // of min/max the width calculation machinery, we need to enter said
    // machinery here, to make sure that what was dirtied is actualy
    // recalculated. Leaving things dirty would mean that any subsequent
    // dirtying of descendants would fail.
    box_->ComputePreferredLogicalWidths();
  }

  PrepareForLayout();

  NGBoxStrut old_scrollbars = GetScrollbarSizes();
  layout_result = LayoutWithAlgorithm(*this, constraint_space, break_token,
                                      /* ignored */ nullptr);

  FinishLayout(block_flow, constraint_space, break_token, layout_result);
  if (old_scrollbars != GetScrollbarSizes()) {
    // If our scrollbars have changed, we need to relayout because either:
    // - Our size has changed (if shrinking to fit), or
    // - Space available to our children has changed.
    // This mirrors legacy code in PaintLayerScrollableArea::UpdateAfterLayout.
    // TODO(cbiesinger): It seems that we should also check if
    // PreferredLogicalWidthsDirty() has changed from false to true during
    // layout, so that we correctly size ourselves when shrinking to fit
    // and a child gained a vertical scrollbar. However, no test fails
    // without that check.
    PaintLayerScrollableArea::FreezeScrollbarsScope freeze_scrollbars;
    layout_result = LayoutWithAlgorithm(*this, constraint_space, break_token,
                                        /* ignored */ nullptr);
    FinishLayout(block_flow, constraint_space, break_token, layout_result);
  }

  return layout_result;
}

void NGBlockNode::PrepareForLayout() {
  if (box_->IsLayoutBlock()) {
    LayoutBlock* block = ToLayoutBlock(box_);
    if (block->HasOverflowClip()) {
      DCHECK(block->GetScrollableArea());
      if (block->GetScrollableArea()->ShouldPerformScrollAnchoring())
        block->GetScrollableArea()->GetScrollAnchor()->NotifyBeforeLayout();
    }
  }

  if (IsListItem())
    ToLayoutNGListItem(box_)->UpdateMarkerTextIfNeeded();
}

void NGBlockNode::FinishLayout(LayoutBlockFlow* block_flow,
                               const NGConstraintSpace& constraint_space,
                               const NGBreakToken* break_token,
                               scoped_refptr<NGLayoutResult> layout_result) {
  if (!IsBlockLayoutComplete(constraint_space, *layout_result))
    return;

  DCHECK(layout_result->PhysicalFragment());

  if (block_flow) {
    block_flow->SetCachedLayoutResult(constraint_space, break_token,
                                      *layout_result);
    NGLayoutInputNode first_child = FirstChild();
    bool has_inline_children = first_child && first_child.IsInline();
    if (has_inline_children || box_->IsLayoutNGFieldset()) {
      if (has_inline_children) {
        CopyFragmentDataToLayoutBoxForInlineChildren(
            ToNGPhysicalBoxFragment(*layout_result->PhysicalFragment()),
            layout_result->PhysicalFragment()->Size().width,
            Style().IsFlippedBlocksWritingMode());
      }

      block_flow->SetPaintFragment(break_token,
                                   layout_result->PhysicalFragment(),
                                   layout_result->Offset());
    } else {
      // We still need to clear paint fragments in case it had inline children,
      // and thus had NGPaintFragment.
      block_flow->SetPaintFragment(break_token, nullptr, NGPhysicalOffset());
    }
  }

  CopyFragmentDataToLayoutBox(constraint_space, *layout_result);
}

MinMaxSize NGBlockNode::ComputeMinMaxSize(
    WritingMode container_writing_mode,
    const MinMaxSizeInput& input,
    const NGConstraintSpace* constraint_space) {
  bool is_orthogonal_flow_root =
      !IsParallelWritingMode(container_writing_mode, Style().GetWritingMode());

  MinMaxSize sizes;
  // If we're orthogonal, we have to run layout to compute the sizes. However,
  // if we're outside of layout, we can't do that. This can happen on Mac.
  if ((!CanUseNewLayout() && !is_orthogonal_flow_root) ||
      (is_orthogonal_flow_root && !box_->GetFrameView()->IsInPerformLayout())) {
    return ComputeMinMaxSizeFromLegacy(input.size_type);
  }

  NGPhysicalSize icb_size = constraint_space
                                ? constraint_space->InitialContainingBlockSize()
                                : InitialContainingBlockSize();
  NGConstraintSpace zero_constraint_space =
      CreateConstraintSpaceBuilderForMinMax(*this, icb_size)
          .ToConstraintSpace(Style().GetWritingMode());

  if (!constraint_space) {
    // Using the zero-sized constraint space when measuring for an orthogonal
    // flow root isn't going to give the right result.
    DCHECK(!is_orthogonal_flow_root);

    constraint_space = &zero_constraint_space;
  }

  if (is_orthogonal_flow_root || !CanUseNewLayout()) {
    scoped_refptr<NGLayoutResult> layout_result = Layout(*constraint_space);
    DCHECK_EQ(layout_result->Status(), NGLayoutResult::kSuccess);
    NGBoxFragment fragment(
        container_writing_mode,
        TextDirection::kLtr,  // irrelevant here
        ToNGPhysicalBoxFragment(*layout_result->PhysicalFragment()));
    sizes.min_size = sizes.max_size = fragment.Size().inline_size;
    if (input.size_type == NGMinMaxSizeType::kContentBoxSize) {
      sizes -= fragment.Borders().InlineSum() + fragment.Padding().InlineSum() +
               box_->ScrollbarLogicalWidth();
      DCHECK_GE(sizes.min_size, LayoutUnit());
      DCHECK_GE(sizes.max_size, LayoutUnit());
    }
    return sizes;
  }

  base::Optional<MinMaxSize> maybe_sizes =
      ComputeMinMaxSizeWithAlgorithm(*this, *constraint_space,
                                     /* break token */ nullptr, input);
  if (maybe_sizes.has_value()) {
    if (UNLIKELY(IsHTMLMarqueeElement(box_->GetNode()) &&
                 ToHTMLMarqueeElement(box_->GetNode())->IsHorizontal()))
      maybe_sizes->min_size = LayoutUnit();
    return *maybe_sizes;
  }

  if (!box_->GetFrameView()->IsInPerformLayout()) {
    // We can't synthesize these using Layout() if we're not in PerformLayout.
    // This situation can happen on mac. Fall back to legacy instead.
    return ComputeMinMaxSizeFromLegacy(input.size_type);
  }

  // Have to synthesize this value.
  scoped_refptr<NGLayoutResult> layout_result = Layout(zero_constraint_space);
  NGBoxFragment min_fragment(
      container_writing_mode,
      TextDirection::kLtr,  // irrelevant here
      ToNGPhysicalBoxFragment(*layout_result->PhysicalFragment()));
  sizes.min_size = min_fragment.Size().inline_size;

  // Now, redo with infinite space for max_content
  NGConstraintSpace infinite_constraint_space =
      CreateConstraintSpaceBuilderForMinMax(*this, icb_size)
          .SetAvailableSize({LayoutUnit::Max(), LayoutUnit()})
          .SetPercentageResolutionSize({LayoutUnit(), LayoutUnit()})
          .ToConstraintSpace(Style().GetWritingMode());

  layout_result = Layout(infinite_constraint_space);
  NGBoxFragment max_fragment(
      container_writing_mode,
      TextDirection::kLtr,  // irrelevant here
      ToNGPhysicalBoxFragment(*layout_result->PhysicalFragment()));
  sizes.max_size = max_fragment.Size().inline_size;

  if (input.size_type == NGMinMaxSizeType::kContentBoxSize) {
    sizes -= max_fragment.Borders().InlineSum() +
             max_fragment.Padding().InlineSum() + box_->ScrollbarLogicalWidth();
    DCHECK_GE(sizes.min_size, LayoutUnit());
    DCHECK_GE(sizes.max_size, LayoutUnit());
  }
  return sizes;
}

MinMaxSize NGBlockNode::ComputeMinMaxSizeFromLegacy(
    NGMinMaxSizeType type) const {
  MinMaxSize sizes;
  // ComputeIntrinsicLogicalWidths returns content-box + scrollbar.
  box_->ComputeIntrinsicLogicalWidths(sizes.min_size, sizes.max_size);
  if (type == NGMinMaxSizeType::kContentBoxSize) {
    sizes -= LayoutUnit(box_->ScrollbarLogicalWidth());
    DCHECK_GE(sizes.min_size, LayoutUnit());
    DCHECK_GE(sizes.max_size, LayoutUnit());
  } else {
    sizes += box_->BorderAndPaddingLogicalWidth();
  }
  return sizes;
}

NGBoxStrut NGBlockNode::GetScrollbarSizes() const {
  NGPhysicalBoxStrut sizes;
  const ComputedStyle& style = box_->StyleRef();
  if (!style.IsOverflowVisible()) {
    LayoutUnit vertical = LayoutUnit(box_->VerticalScrollbarWidth());
    LayoutUnit horizontal = LayoutUnit(box_->HorizontalScrollbarHeight());
    sizes.bottom = horizontal;
    if (box_->ShouldPlaceBlockDirectionScrollbarOnLogicalLeft())
      sizes.left = vertical;
    else
      sizes.right = vertical;
  }
  return sizes.ConvertToLogical(style.GetWritingMode(), style.Direction());
}

NGLayoutInputNode NGBlockNode::NextSibling() const {
  LayoutObject* next_sibling = GetLayoutObjectForNextSiblingNode(box_);
  if (next_sibling) {
    DCHECK(!next_sibling->IsInline());
    return NGBlockNode(ToLayoutBox(next_sibling));
  }
  return nullptr;
}

NGLayoutInputNode NGBlockNode::FirstChild() const {
  auto* block = ToLayoutBlock(box_);
  auto* child = GetLayoutObjectForFirstChildNode(block);
  if (!child)
    return nullptr;
  if (AreNGBlockFlowChildrenInline(block))
    return NGInlineNode(ToLayoutBlockFlow(block));
  return NGBlockNode(ToLayoutBox(child));
}

NGBlockNode NGBlockNode::GetRenderedLegend() const {
  if (!IsFieldsetContainer())
    return nullptr;
  return NGBlockNode(LayoutFieldset::FindInFlowLegend(*ToLayoutBlock(box_)));
}

NGBlockNode NGBlockNode::GetFieldsetContent() const {
  if (!IsFieldsetContainer())
    return nullptr;
  auto* child = GetLayoutObjectForFirstChildNode(ToLayoutBlock(box_));
  if (!child)
    return nullptr;
  return NGBlockNode(ToLayoutBox(child));
}

bool NGBlockNode::CanUseNewLayout(const LayoutBox& box) {
  DCHECK(RuntimeEnabledFeatures::LayoutNGEnabled());
  if (box.StyleRef().ForceLegacyLayout())
    return false;

  // When the style has |ForceLegacyLayout|, it's usually not LayoutNGMixin,
  // but anonymous block can be.
  return box.IsLayoutNGMixin() || box.IsLayoutNGFlexibleBox();
}

bool NGBlockNode::CanUseNewLayout() const {
  return CanUseNewLayout(*box_);
}

String NGBlockNode::ToString() const {
  return String::Format("NGBlockNode: '%s'",
                        GetLayoutBox()->DebugName().Ascii().data());
}

void NGBlockNode::CopyFragmentDataToLayoutBox(
    const NGConstraintSpace& constraint_space,
    const NGLayoutResult& layout_result) {
  DCHECK(layout_result.PhysicalFragment());
  if (constraint_space.IsIntermediateLayout())
    return;

  const NGPhysicalBoxFragment& physical_fragment =
      ToNGPhysicalBoxFragment(*layout_result.PhysicalFragment());

  NGBoxFragment fragment(constraint_space.GetWritingMode(),
                         constraint_space.Direction(), physical_fragment);
  NGLogicalSize fragment_logical_size = fragment.Size();
  // For each fragment we process, we'll accumulate the logical height and
  // logical intrinsic content box height. We reset it at the first fragment,
  // and accumulate at each method call for fragments belonging to the same
  // layout object. Logical width will only be set at the first fragment and is
  // expected to remain the same throughout all subsequent fragments, since
  // legacy layout doesn't support non-uniform fragmentainer widths.
  LayoutUnit logical_height;
  LayoutUnit intrinsic_content_logical_height;
  if (IsFirstFragment(constraint_space, physical_fragment)) {
    box_->SetLogicalWidth(fragment_logical_size.inline_size);
  } else {
    DCHECK_EQ(box_->LogicalWidth(), fragment_logical_size.inline_size)
        << "Variable fragment inline size not supported";
    logical_height =
        PreviouslyUsedBlockSpace(constraint_space, physical_fragment);
    // TODO(layout-ng): We should store this on the break token instead of
    // relying on previously-stored data. Our relayout in NGBlockNode::Layout
    // will otherwise lead to wrong data.
    intrinsic_content_logical_height = box_->IntrinsicContentLogicalHeight();
  }
  logical_height += fragment_logical_size.block_size;
  intrinsic_content_logical_height += layout_result.IntrinsicBlockSize();

  NGBoxStrut borders = fragment.Borders();
  NGBoxStrut scrollbars = GetScrollbarSizes();
  NGBoxStrut padding = fragment.Padding();
  NGBoxStrut border_scrollbar_padding = borders + scrollbars + padding;

  if (IsLastFragment(physical_fragment))
    intrinsic_content_logical_height -= border_scrollbar_padding.BlockSum();
  box_->SetLogicalHeight(logical_height);
  box_->SetIntrinsicContentLogicalHeight(intrinsic_content_logical_height);
  // TODO(mstensho): This should always be done by the parent algorithm, since
  // we may have auto margins, which only the parent is able to resolve. Remove
  // the following line when all layout modes do this properly.
  box_->SetMargin(ComputePhysicalMargins(constraint_space, Style()));

  LayoutMultiColumnFlowThread* flow_thread = GetFlowThread(*box_);
  if (flow_thread) {
    PlaceChildrenInFlowThread(constraint_space, physical_fragment);
  } else {
    NGPhysicalOffset offset_from_start;
    if (constraint_space.HasBlockFragmentation()) {
      // Need to include any block space that this container has used in
      // previous fragmentainers. The offset of children will be relative to
      // the container, in flow thread coordinates, i.e. the model where
      // everything is represented as one single strip, rather than being
      // sliced and translated into columns.

      // TODO(mstensho): writing modes
      offset_from_start.top =
          PreviouslyUsedBlockSpace(constraint_space, physical_fragment);
    }
    PlaceChildrenInLayoutBox(constraint_space, physical_fragment,
                             offset_from_start);
  }

  if (box_->IsLayoutBlock() && IsLastFragment(physical_fragment)) {
    LayoutBlock* block = ToLayoutBlock(box_);
    LayoutUnit intrinsic_block_size = layout_result.IntrinsicBlockSize();
    if (constraint_space.HasBlockFragmentation()) {
      intrinsic_block_size +=
          PreviouslyUsedBlockSpace(constraint_space, physical_fragment);
    }
    block->LayoutPositionedObjects(/* relayout_children */ false);

    if (flow_thread) {
      UpdateLegacyMultiColumnFlowThread(*this, flow_thread, constraint_space,
                                        physical_fragment);
    }

    // |ComputeOverflow()| below calls |AddVisualOverflowFromChildren()|, which
    // computes visual overflow from |RootInlineBox| if |ChildrenInline()|
    block->ComputeOverflow(intrinsic_block_size - borders.block_end -
                           scrollbars.block_end);
  }

  box_->UpdateAfterLayout();
  box_->ClearNeedsLayout();

  UpdateShapeOutsideInfoIfNeeded(
      constraint_space.PercentageResolutionSize().inline_size);

  // Overflow computation depends on this being set.
  if (box_->IsLayoutBlockFlow()) {
    LayoutBlockFlow* block_flow = ToLayoutBlockFlow(box_);
    block_flow->UpdateIsSelfCollapsing();
  }
}

void NGBlockNode::PlaceChildrenInLayoutBox(
    const NGConstraintSpace& constraint_space,
    const NGPhysicalBoxFragment& physical_fragment,
    const NGPhysicalOffset& offset_from_start) {
  LayoutBox* rendered_legend = nullptr;
  for (const auto& child_fragment : physical_fragment.Children()) {
    auto* child_object = child_fragment->GetLayoutObject();

    // Skip any line-boxes we have as children, this is handled within
    // NGInlineNode at the moment.
    if (!child_fragment->IsBox() && !child_fragment->IsRenderedLegend())
      continue;

    const auto& box_fragment = *ToNGPhysicalBoxFragment(child_fragment.get());
    if (IsFirstFragment(constraint_space, box_fragment)) {
      if (box_fragment.IsRenderedLegend())
        rendered_legend = ToLayoutBox(box_fragment.GetLayoutObject());
      CopyChildFragmentPosition(box_fragment, child_fragment.Offset(),
                                offset_from_start);
    }
    if (child_object->IsLayoutBlockFlow()) {
      ToLayoutBlockFlow(child_object)->AddVisualOverflowFromFloats();
      ToLayoutBlockFlow(child_object)->AddLayoutOverflowFromFloats();
    }
  }

  if (rendered_legend) {
    // The rendered legend is a child of the the anonymous fieldset content
    // child wrapper object on the legacy side. LayoutNG, on the other hand,
    // generates a fragment for the rendered legend as a direct child of the
    // fieldset container fragment (as a *sibling* preceding the anonymous
    // fieldset content wrapper). Now that we have positioned the anonymous
    // wrapper, we're ready to compensate for this discrepancy. See
    // LayoutNGFieldset for more details.
    LayoutBlock* content_wrapper = rendered_legend->ContainingBlock();
    DCHECK(content_wrapper->IsAnonymous());
    DCHECK(IsHTMLFieldSetElement(content_wrapper->Parent()->GetNode()));
    LayoutPoint location = rendered_legend->Location();
    location -= content_wrapper->Location();
    rendered_legend->SetLocation(location);
  }
}

void NGBlockNode::PlaceChildrenInFlowThread(
    const NGConstraintSpace& constraint_space,
    const NGPhysicalBoxFragment& physical_fragment) {
  LayoutUnit flowthread_offset;
  for (const auto& child : physical_fragment.Children()) {
    // Each anonymous child of a multicol container constitutes one column.
    DCHECK(child->GetLayoutObject() == box_);

    // TODO(mstensho): writing modes
    NGPhysicalOffset offset(LayoutUnit(), flowthread_offset);

    // Position each child node in the first column that they occur, relatively
    // to the block-start of the flow thread.
    const auto* column = ToNGPhysicalBoxFragment(child.get());
    PlaceChildrenInLayoutBox(constraint_space, *column, offset);
    const auto* token = ToNGBlockBreakToken(column->BreakToken());
    flowthread_offset = token->UsedBlockSize();
  }
}

// Copies data back to the legacy layout tree for a given child fragment.
void NGBlockNode::CopyChildFragmentPosition(
    const NGPhysicalFragment& fragment,
    const NGPhysicalOffset fragment_offset,
    const NGPhysicalOffset additional_offset) {
  LayoutBox* layout_box = ToLayoutBox(fragment.GetLayoutObject());
  if (!layout_box)
    return;

  DCHECK(layout_box->Parent()) << "Should be called on children only.";

  // The containing block of |layout_box| on the legacy layout side is normally
  // |box_|, but this is not an invariant. Among other things, it does not apply
  // to list item markers and multicol container children. Multicol containiner
  // children typically have their flow thread (not the multicol container
  // itself) as their containing block, and we need to use the right containing
  // block for inserting floats, flipping for writing modes, etc.
  LayoutBlock* containing_block = layout_box->ContainingBlock();

  // LegacyLayout flips vertical-rl horizontal coordinates before paint.
  // NGLayout flips X location for LegacyLayout compatibility. horizontal_offset
  // will be the offset from the left edge of the container to the left edge of
  // the layout object, except when in vertical-rl: Then it will be the offset
  // from the right edge of the container to the right edge of the layout
  // object.
  LayoutUnit horizontal_offset = fragment_offset.left + additional_offset.left;
  bool has_flipped_x_axis =
      containing_block->StyleRef().IsFlippedBlocksWritingMode();
  if (has_flipped_x_axis) {
    horizontal_offset = containing_block->Size().Width() - horizontal_offset -
                        fragment.Size().width;
  }
  layout_box->SetX(horizontal_offset);
  layout_box->SetY(fragment_offset.top + additional_offset.top);

  // Floats need an associated FloatingObject for painting.
  if (IsFloatFragment(fragment) && containing_block->IsLayoutBlockFlow()) {
    FloatingObject* floating_object =
        ToLayoutBlockFlow(containing_block)->InsertFloatingObject(*layout_box);
    floating_object->SetIsInPlacedTree(false);
    floating_object->SetShouldPaint(!layout_box->HasSelfPaintingLayer());
    LayoutUnit horizontal_margin_edge_offset = horizontal_offset;
    if (has_flipped_x_axis)
      horizontal_margin_edge_offset -= layout_box->MarginRight();
    else
      horizontal_margin_edge_offset -= layout_box->MarginLeft();
    floating_object->SetX(horizontal_margin_edge_offset);
    floating_object->SetY(fragment_offset.top + additional_offset.top -
                          layout_box->MarginTop());
    floating_object->SetIsPlaced(true);
    floating_object->SetIsInPlacedTree(true);
  }
}

// For inline children, NG painters handles fragments directly, but there are
// some cases where we need to copy data to the LayoutObject tree. This function
// handles such cases.
void NGBlockNode::CopyFragmentDataToLayoutBoxForInlineChildren(
    const NGPhysicalContainerFragment& container,
    LayoutUnit initial_container_width,
    bool initial_container_is_flipped,
    NGPhysicalOffset offset) {
  for (const auto& child : container.Children()) {
    if (child->IsContainer()) {
      NGPhysicalOffset child_offset = offset + child.Offset();

      // Replaced elements and inline blocks need Location() set relative to
      // their block container.
      LayoutObject* layout_object = child->GetLayoutObject();
      if (layout_object && layout_object->IsBox()) {
        LayoutBox& layout_box = ToLayoutBox(*layout_object);
        NGPhysicalOffset maybe_flipped_offset = child_offset;
        if (initial_container_is_flipped) {
          maybe_flipped_offset.left = initial_container_width -
                                      child->Size().width -
                                      maybe_flipped_offset.left;
        }
        layout_box.SetLocation(maybe_flipped_offset.ToLayoutPoint());
      }

      // The Location() of inline LayoutObject is relative to the
      // LayoutBlockFlow. If |child| establishes a new block formatting context,
      // it also creates another inline formatting context. Do not copy to its
      // descendants in this case.
      if (!child->IsBlockFormattingContextRoot()) {
        CopyFragmentDataToLayoutBoxForInlineChildren(
            ToNGPhysicalContainerFragment(*child), initial_container_width,
            initial_container_is_flipped, child_offset);
      }
    }
  }
}

bool NGBlockNode::IsInlineLevel() const {
  return GetLayoutBox()->IsInline();
}

bool NGBlockNode::IsAtomicInlineLevel() const {
  // LayoutObject::IsAtomicInlineLevel() returns true for e.g., <img
  // style="display: block">. Check IsInline() as well.
  return GetLayoutBox()->IsAtomicInlineLevel() && GetLayoutBox()->IsInline();
}

bool NGBlockNode::UseLogicalBottomMarginEdgeForInlineBlockBaseline() const {
  LayoutBox* layout_box = GetLayoutBox();
  return layout_box->IsLayoutBlock() &&
         ToLayoutBlock(layout_box)
             ->UseLogicalBottomMarginEdgeForInlineBlockBaseline();
}

scoped_refptr<NGLayoutResult> NGBlockNode::LayoutAtomicInline(
    const NGConstraintSpace& parent_constraint_space,
    FontBaseline baseline_type,
    bool use_first_line_style) {
  NGConstraintSpaceBuilder space_builder(parent_constraint_space);
  space_builder.SetUseFirstLineStyle(use_first_line_style);

  // Request to compute baseline during the layout, except when we know the box
  // would synthesize box-baseline.
  LayoutBox* layout_box = GetLayoutBox();
  if (NGBaseline::ShouldPropagateBaselines(layout_box)) {
    space_builder.AddBaselineRequest(
        {NGBaselineAlgorithmType::kAtomicInline, baseline_type});
  }

  const ComputedStyle& style = Style();
  NGConstraintSpace constraint_space =
      space_builder.SetIsNewFormattingContext(true)
          .SetIsShrinkToFit(Style().LogicalWidth().IsAuto())
          .SetAvailableSize(parent_constraint_space.AvailableSize())
          .SetPercentageResolutionSize(
              parent_constraint_space.PercentageResolutionSize())
          .SetReplacedPercentageResolutionSize(
              parent_constraint_space.ReplacedPercentageResolutionSize())
          .SetTextDirection(style.Direction())
          .ToConstraintSpace(style.GetWritingMode());
  scoped_refptr<NGLayoutResult> result = Layout(constraint_space);
  // TODO(kojii): Investigate why ClearNeedsLayout() isn't called automatically
  // when it's being laid out.
  if (!constraint_space.IsIntermediateLayout())
    layout_box->ClearNeedsLayout();
  return result;
}

scoped_refptr<NGLayoutResult> NGBlockNode::RunOldLayout(
    const NGConstraintSpace& constraint_space) {
  // This is an exit-point from LayoutNG to the legacy engine. This means that
  // we need to be at a formatting context boundary, since NG and legacy don't
  // cooperate on e.g. margin collapsing.
  DCHECK(!box_->IsLayoutBlock() ||
         ToLayoutBlock(box_)->CreatesNewFormattingContext());

  WritingMode writing_mode = Style().GetWritingMode();
  LayoutBlock* block = box_->IsLayoutBlock() ? ToLayoutBlock(box_) : nullptr;
  const NGConstraintSpace* old_space =
      block ? block->CachedConstraintSpace() : nullptr;
  if (!old_space || box_->NeedsLayout() || *old_space != constraint_space) {
    LayoutUnit inline_size =
        CalculateAvailableInlineSizeForLegacy(*box_, constraint_space);
    LayoutUnit block_size =
        CalculateAvailableBlockSizeForLegacy(*box_, constraint_space);

    LayoutObject* containing_block = box_->ContainingBlock();
    bool parallel_writing_mode;
    if (!containing_block) {
      parallel_writing_mode = true;
    } else {
      parallel_writing_mode = IsParallelWritingMode(
          containing_block->StyleRef().GetWritingMode(), writing_mode);
    }
    if (parallel_writing_mode) {
      box_->SetOverrideContainingBlockContentLogicalWidth(inline_size);
      box_->SetOverrideContainingBlockContentLogicalHeight(block_size);
    } else {
      // OverrideContainingBlock should be in containing block writing mode.
      box_->SetOverrideContainingBlockContentLogicalWidth(block_size);
      box_->SetOverrideContainingBlockContentLogicalHeight(inline_size);
    }

    if (constraint_space.IsFixedSizeInline()) {
      box_->SetOverrideLogicalWidth(
          constraint_space.AvailableSize().inline_size);
    }
    if (constraint_space.IsFixedSizeBlock()) {
      box_->SetOverrideLogicalHeight(
          constraint_space.AvailableSize().block_size);
    }
    box_->ComputeAndSetBlockDirectionMargins(box_->ContainingBlock());

    if (box_->NeedsLayout() && box_->IsLayoutNGMixin()) {
      ToLayoutBlockFlow(box_)->LayoutBlockFlow::UpdateBlockLayout(true);
    } else {
      box_->ForceLayout();
    }

    // Reset the containing block size override size, now that we're done with
    // subtree layout. Min/max calculation that depends on the block size of the
    // container (e.g. objects with intrinsic ratio and percentage block size)
    // in a subsequent layout pass might otherwise become wrong.
    box_->ClearOverrideContainingBlockContentSize();
    if (block)
      block->SetCachedConstraintSpace(constraint_space);
  }
  NGLogicalSize box_size(box_->LogicalWidth(), box_->LogicalHeight());
  // TODO(kojii): Implement use_first_line_style.
  NGBoxFragmentBuilder builder(*this, box_->Style(), writing_mode,
                               box_->StyleRef().Direction());
  builder.SetIsOldLayoutRoot();
  builder.SetInlineSize(box_size.inline_size);
  builder.SetBlockSize(box_size.block_size);
  NGBoxStrut borders(box_->BorderStart(), box_->BorderEnd(),
                     box_->BorderBefore(), box_->BorderAfter());
  builder.SetBorders(borders);
  NGBoxStrut padding(box_->PaddingStart(), box_->PaddingEnd(),
                     box_->PaddingBefore(), box_->PaddingAfter());
  builder.SetPadding(padding);

  CopyBaselinesFromOldLayout(constraint_space, &builder);
  UpdateShapeOutsideInfoIfNeeded(
      constraint_space.PercentageResolutionSize().inline_size);
  return builder.ToBoxFragment();
}

void NGBlockNode::CopyBaselinesFromOldLayout(
    const NGConstraintSpace& constraint_space,
    NGBoxFragmentBuilder* builder) {
  const NGConstraintSpace::NGBaselineRequestVector& requests =
      constraint_space.BaselineRequests();
  if (requests.IsEmpty())
    return;

  if (UNLIKELY(constraint_space.GetWritingMode() != Style().GetWritingMode()))
    return;

  for (const auto& request : requests) {
    switch (request.algorithm_type) {
      case NGBaselineAlgorithmType::kAtomicInline: {
        LayoutUnit position =
            AtomicInlineBaselineFromOldLayout(request, constraint_space);
        if (position != -1)
          builder->AddBaseline(request, position);
        break;
      }
      case NGBaselineAlgorithmType::kFirstLine: {
        LayoutUnit position = box_->FirstLineBoxBaseline();
        if (position != -1)
          builder->AddBaseline(request, position);
        break;
      }
    }
  }
}

LayoutUnit NGBlockNode::AtomicInlineBaselineFromOldLayout(
    const NGBaselineRequest& request,
    const NGConstraintSpace& constraint_space) {
  LineDirectionMode line_direction = box_->IsHorizontalWritingMode()
                                         ? LineDirectionMode::kHorizontalLine
                                         : LineDirectionMode::kVerticalLine;

  // If this is an inline box, use |BaselinePosition()|. Some LayoutObject
  // classes override it assuming inline layout calls |BaselinePosition()|.
  if (box_->IsInline()) {
    LayoutUnit position = LayoutUnit(box_->BaselinePosition(
        request.baseline_type, constraint_space.UseFirstLineStyle(),
        line_direction, kPositionOnContainingLine));

    // BaselinePosition() uses margin edge for atomic inlines. Subtract
    // margin-over so that the position is relative to the border box.
    if (box_->IsAtomicInlineLevel())
      position -= box_->MarginOver();

    return position;
  }

  // If this is a block box, use |InlineBlockBaseline()|. When an inline block
  // has block children, their inline block baselines need to be propagated.
  return box_->InlineBlockBaseline(line_direction);
}

// Floats can optionally have a shape area, specifed by "shape-outside". The
// current shape machinery requires setting the size of the float after layout
// in the parents writing mode.
void NGBlockNode::UpdateShapeOutsideInfoIfNeeded(
    LayoutUnit percentage_resolution_inline_size) {
  if (!box_->IsFloating() || !box_->GetShapeOutsideInfo())
    return;

  // TODO(ikilpatrick): Ideally this should be moved to a NGLayoutResult
  // computing the shape area. There may be an issue with the new fragmentation
  // model and computing the correct sizes of shapes.
  ShapeOutsideInfo* shape_outside = box_->GetShapeOutsideInfo();
  LayoutBlock* containing_block = box_->ContainingBlock();
  shape_outside->SetReferenceBoxLogicalSize(
      containing_block->IsHorizontalWritingMode()
          ? box_->Size()
          : box_->Size().TransposedSize());
  shape_outside->SetPercentageResolutionInlineSize(
      percentage_resolution_inline_size);
}

void NGBlockNode::UseOldOutOfFlowPositioning() {
  DCHECK(box_->IsOutOfFlowPositioned());
  box_->ContainingBlock()->InsertPositionedObject(box_);
}

// Save static position for legacy AbsPos layout.
void NGBlockNode::SaveStaticOffsetForLegacy(
    const NGLogicalOffset& offset,
    const LayoutObject* offset_container) {
  DCHECK(box_->IsOutOfFlowPositioned());
  // Only set static position if the current offset container
  // is one that Legacy layout expects static offset from.
  const LayoutObject* parent = box_->Parent();
  if (parent == offset_container ||
      (parent && parent->IsLayoutInline() &&
       parent->ContainingBlock() == offset_container)) {
    DCHECK(box_->Layer());
    box_->Layer()->SetStaticBlockPosition(offset.block_offset);
    box_->Layer()->SetStaticInlinePosition(offset.inline_offset);
  }
}

void NGBlockNode::StoreMargins(const NGConstraintSpace& constraint_space,
                               const NGBoxStrut& margins) {
  if (constraint_space.IsIntermediateLayout())
    return;
  NGPhysicalBoxStrut physical_margins = margins.ConvertToPhysical(
      constraint_space.GetWritingMode(), constraint_space.Direction());
  box_->SetMargin(physical_margins);
}

}  // namespace blink
