/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "core/layout/LayoutBlockFlow.h"

#include <memory>
#include "core/editing/Editor.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/UseCounter.h"
#include "core/html/HTMLDialogElement.h"
#include "core/layout/HitTestLocation.h"
#include "core/layout/LayoutAnalyzer.h"
#include "core/layout/LayoutFlowThread.h"
#include "core/layout/LayoutInline.h"
#include "core/layout/LayoutMultiColumnFlowThread.h"
#include "core/layout/LayoutMultiColumnSpannerPlaceholder.h"
#include "core/layout/LayoutPagedFlowThread.h"
#include "core/layout/LayoutView.h"
#include "core/layout/TextAutosizer.h"
#include "core/layout/line/GlyphOverflow.h"
#include "core/layout/line/InlineIterator.h"
#include "core/layout/line/InlineTextBox.h"
#include "core/layout/line/LineWidth.h"
#include "core/layout/ng/layout_ng_block_flow.h"
#include "core/layout/shapes/ShapeOutsideInfo.h"
#include "core/paint/BlockFlowPaintInvalidator.h"
#include "core/paint/PaintLayer.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/wtf/PtrUtil.h"

namespace blink {

bool LayoutBlockFlow::can_propagate_float_into_sibling_ = false;

struct SameSizeAsLayoutBlockFlow : public LayoutBlock {
  LineBoxList line_boxes;
  void* pointers[2];
};

static_assert(sizeof(LayoutBlockFlow) == sizeof(SameSizeAsLayoutBlockFlow),
              "LayoutBlockFlow should stay small");

struct SameSizeAsMarginInfo {
  uint16_t bitfields;
  LayoutUnit margins[2];
};

static_assert(sizeof(LayoutBlockFlow::MarginValues) == sizeof(LayoutUnit[4]),
              "MarginValues should stay small");

// Caches all our current margin collapsing state.
class MarginInfo {
  // Collapsing flags for whether we can collapse our margins with our
  // children's margins.
  bool can_collapse_with_children_ : 1;
  bool can_collapse_margin_before_with_children_ : 1;
  bool can_collapse_margin_after_with_children_ : 1;
  bool can_collapse_margin_after_with_last_child_ : 1;

  // Whether or not we are a quirky container, i.e., do we collapse away top and
  // bottom margins in our container. Table cells and the body are the common
  // examples. We also have a custom style property for Safari RSS to deal with
  // TypePad blog articles.
  bool quirk_container_ : 1;

  // This flag tracks whether we are still looking at child margins that can all
  // collapse together at the beginning of a block. They may or may not collapse
  // with the top margin of the block (|m_canCollapseTopWithChildren| tells us
  // that), but they will always be collapsing with one another. This variable
  // can remain set to true through multiple iterations as long as we keep
  // encountering self-collapsing blocks.
  bool at_before_side_of_block_ : 1;

  // This flag is set when we know we're examining bottom margins and we know
  // we're at the bottom of the block.
  bool at_after_side_of_block_ : 1;

  // These variables are used to detect quirky margins that we need to collapse
  // away (in table cells
  // and in the body element).
  bool has_margin_before_quirk_ : 1;
  bool has_margin_after_quirk_ : 1;
  bool determined_margin_before_quirk_ : 1;

  bool discard_margin_ : 1;
  bool last_child_is_self_collapsing_block_with_clearance_ : 1;

  // These flags track the previous maximal positive and negative margins.
  LayoutUnit positive_margin_;
  LayoutUnit negative_margin_;

 public:
  MarginInfo(LayoutBlockFlow*,
             LayoutUnit before_border_padding,
             LayoutUnit after_border_padding);

  void SetAtBeforeSideOfBlock(bool b) { at_before_side_of_block_ = b; }
  void SetAtAfterSideOfBlock(bool b) { at_after_side_of_block_ = b; }
  void ClearMargin() {
    positive_margin_ = LayoutUnit();
    negative_margin_ = LayoutUnit();
  }
  void SetHasMarginBeforeQuirk(bool b) { has_margin_before_quirk_ = b; }
  void SetHasMarginAfterQuirk(bool b) { has_margin_after_quirk_ = b; }
  void SetDeterminedMarginBeforeQuirk(bool b) {
    determined_margin_before_quirk_ = b;
  }
  void SetPositiveMargin(LayoutUnit p) {
    DCHECK(!discard_margin_);
    positive_margin_ = p;
  }
  void SetNegativeMargin(LayoutUnit n) {
    DCHECK(!discard_margin_);
    negative_margin_ = n;
  }
  void SetPositiveMarginIfLarger(LayoutUnit p) {
    DCHECK(!discard_margin_);
    if (p > positive_margin_)
      positive_margin_ = p;
  }
  void SetNegativeMarginIfLarger(LayoutUnit n) {
    DCHECK(!discard_margin_);
    if (n > negative_margin_)
      negative_margin_ = n;
  }

  void SetMargin(LayoutUnit p, LayoutUnit n) {
    DCHECK(!discard_margin_);
    positive_margin_ = p;
    negative_margin_ = n;
  }
  void SetCanCollapseMarginAfterWithChildren(bool collapse) {
    can_collapse_margin_after_with_children_ = collapse;
  }
  void SetCanCollapseMarginAfterWithLastChild(bool collapse) {
    can_collapse_margin_after_with_last_child_ = collapse;
  }
  void SetDiscardMargin(bool value) { discard_margin_ = value; }

  bool AtBeforeSideOfBlock() const { return at_before_side_of_block_; }
  bool CanCollapseWithMarginBefore() const {
    return at_before_side_of_block_ &&
           can_collapse_margin_before_with_children_;
  }
  bool CanCollapseWithMarginAfter() const {
    return at_after_side_of_block_ && can_collapse_margin_after_with_children_;
  }
  bool CanCollapseMarginBeforeWithChildren() const {
    return can_collapse_margin_before_with_children_;
  }
  bool CanCollapseMarginAfterWithChildren() const {
    return can_collapse_margin_after_with_children_;
  }
  bool CanCollapseMarginAfterWithLastChild() const {
    return can_collapse_margin_after_with_last_child_;
  }
  bool QuirkContainer() const { return quirk_container_; }
  bool DeterminedMarginBeforeQuirk() const {
    return determined_margin_before_quirk_;
  }
  bool HasMarginBeforeQuirk() const { return has_margin_before_quirk_; }
  bool HasMarginAfterQuirk() const { return has_margin_after_quirk_; }
  LayoutUnit PositiveMargin() const { return positive_margin_; }
  LayoutUnit NegativeMargin() const { return negative_margin_; }
  bool DiscardMargin() const { return discard_margin_; }
  LayoutUnit Margin() const { return positive_margin_ - negative_margin_; }
  void SetLastChildIsSelfCollapsingBlockWithClearance(bool value) {
    last_child_is_self_collapsing_block_with_clearance_ = value;
  }
  bool LastChildIsSelfCollapsingBlockWithClearance() const {
    return last_child_is_self_collapsing_block_with_clearance_;
  }
};

// Some features, such as floats, margin collapsing and fragmentation, require
// some knowledge about things that happened when laying out previous block
// child siblings. Only looking at the object currently being laid out isn't
// always enough.
class BlockChildrenLayoutInfo {
 public:
  BlockChildrenLayoutInfo(LayoutBlockFlow* block_flow,
                          LayoutUnit before_edge,
                          LayoutUnit after_edge)
      : margin_info_(block_flow, before_edge, after_edge),
        previous_break_after_value_(EBreakBetween::kAuto),
        is_at_first_in_flow_child_(true) {}

  // Store multicol layout state before first layout of a block child. The child
  // may contain a column spanner. If we need to re-lay out the block child
  // because our initial logical top estimate was wrong, we need to roll back to
  // how things were before laying out the child.
  void StoreMultiColumnLayoutState(const LayoutFlowThread& flow_thread) {
    multi_column_layout_state_ = flow_thread.GetMultiColumnLayoutState();
  }
  void RollBackToInitialMultiColumnLayoutState(LayoutFlowThread& flow_thread) {
    flow_thread.RestoreMultiColumnLayoutState(multi_column_layout_state_);
  }

  const MarginInfo& GetMarginInfo() const { return margin_info_; }
  MarginInfo& GetMarginInfo() { return margin_info_; }
  LayoutUnit& PreviousFloatLogicalBottom() {
    return previous_float_logical_bottom_;
  }

  EBreakBetween PreviousBreakAfterValue() const {
    return previous_break_after_value_;
  }
  void SetPreviousBreakAfterValue(EBreakBetween value) {
    previous_break_after_value_ = value;
  }

  bool IsAtFirstInFlowChild() const { return is_at_first_in_flow_child_; }
  void ClearIsAtFirstInFlowChild() { is_at_first_in_flow_child_ = false; }

 private:
  MultiColumnLayoutState multi_column_layout_state_;
  MarginInfo margin_info_;
  LayoutUnit previous_float_logical_bottom_;
  EBreakBetween previous_break_after_value_;
  bool is_at_first_in_flow_child_;
};

LayoutBlockFlow::LayoutBlockFlow(ContainerNode* node) : LayoutBlock(node) {
  static_assert(sizeof(MarginInfo) == sizeof(SameSizeAsMarginInfo),
                "MarginInfo should stay small");
  SetChildrenInline(true);
}

LayoutBlockFlow::~LayoutBlockFlow() {}

LayoutBlockFlow* LayoutBlockFlow::CreateAnonymous(Document* document) {
  LayoutBlockFlow* layout_block_flow = RuntimeEnabledFeatures::layoutNGEnabled()
                                           ? new LayoutNGBlockFlow(nullptr)
                                           : new LayoutBlockFlow(nullptr);
  layout_block_flow->SetDocumentForAnonymous(document);
  return layout_block_flow;
}

LayoutObject* LayoutBlockFlow::LayoutSpecialExcludedChild(
    bool relayout_children,
    SubtreeLayoutScope& layout_scope) {
  LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread();
  if (!flow_thread)
    return nullptr;
  SetLogicalTopForChild(*flow_thread, BorderBefore() + PaddingBefore());
  flow_thread->LayoutColumns(layout_scope);
  DetermineLogicalLeftPositionForChild(*flow_thread);
  return flow_thread;
}

bool LayoutBlockFlow::UpdateLogicalWidthAndColumnWidth() {
  bool relayout_children = LayoutBlock::UpdateLogicalWidthAndColumnWidth();
  if (LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread()) {
    if (flow_thread->NeedsNewWidth())
      return true;
  }
  return relayout_children;
}

void LayoutBlockFlow::SetBreakAtLineToAvoidWidow(int line_to_break) {
  DCHECK_GE(line_to_break, 0);
  EnsureRareData();
  DCHECK(!rare_data_->did_break_at_line_to_avoid_widow_);
  rare_data_->line_break_to_avoid_widow_ = line_to_break;
}

void LayoutBlockFlow::SetDidBreakAtLineToAvoidWidow() {
  DCHECK(!ShouldBreakAtLineToAvoidWidow());

  // This function should be called only after a break was applied to avoid
  // widows so assert |m_rareData| exists.
  DCHECK(rare_data_);

  rare_data_->did_break_at_line_to_avoid_widow_ = true;
}

void LayoutBlockFlow::ClearDidBreakAtLineToAvoidWidow() {
  if (!rare_data_)
    return;

  rare_data_->did_break_at_line_to_avoid_widow_ = false;
}

void LayoutBlockFlow::ClearShouldBreakAtLineToAvoidWidow() const {
  DCHECK(ShouldBreakAtLineToAvoidWidow());
  if (!rare_data_)
    return;

  rare_data_->line_break_to_avoid_widow_ = -1;
}

bool LayoutBlockFlow::IsSelfCollapsingBlock() const {
  if (NeedsLayout()) {
    // Sometimes we don't lay out objects in DOM order (column spanners being
    // one such relevant type of object right here). As long as the object in
    // question establishes a new formatting context, that's nothing to worry
    // about, though.
    DCHECK(CreatesNewFormattingContext());
    return false;
  }
  DCHECK_EQ(!is_self_collapsing_, !CheckIfIsSelfCollapsingBlock());
  return is_self_collapsing_;
}

bool LayoutBlockFlow::CheckIfIsSelfCollapsingBlock() const {
  // We are not self-collapsing if we
  // (a) have a non-zero height according to layout (an optimization to avoid
  //     wasting time)
  // (b) have border/padding,
  // (c) have a min-height
  // (d) have specified that one of our margins can't collapse using a CSS
  //     extension
  // (e) establish a new block formatting context.

  // The early exit must be done before we check for clean layout.
  // We should be able to give a quick answer if the box is a relayout boundary.
  // Being a relayout boundary implies a block formatting context, and also
  // our internal layout shouldn't affect our container in any way.
  if (CreatesNewFormattingContext())
    return false;

  // Placeholder elements are not laid out until the dimensions of their parent
  // text control are known, so they don't get layout until their parent has had
  // layout - this is unique in the layout tree and means when we call
  // isSelfCollapsingBlock on them we find that they still need layout.
  DCHECK(!NeedsLayout() || (GetNode() && GetNode()->IsElementNode() &&
                            ToElement(GetNode())->ShadowPseudoId() ==
                                "-webkit-input-placeholder"));

  if (LogicalHeight() > LayoutUnit() || BorderAndPaddingLogicalHeight() ||
      Style()->LogicalMinHeight().IsPositive() ||
      Style()->MarginBeforeCollapse() == kMarginCollapseSeparate ||
      Style()->MarginAfterCollapse() == kMarginCollapseSeparate)
    return false;

  Length logical_height_length = Style()->LogicalHeight();
  bool has_auto_height = logical_height_length.IsAuto();
  if (logical_height_length.IsPercentOrCalc() &&
      !GetDocument().InQuirksMode()) {
    has_auto_height = true;
    for (LayoutBlock* cb = ContainingBlock(); !cb->IsLayoutView();
         cb = cb->ContainingBlock()) {
      if (cb->Style()->LogicalHeight().IsFixed() || cb->IsTableCell())
        has_auto_height = false;
    }
  }

  // If the height is 0 or auto, then whether or not we are a self-collapsing
  // block depends on whether we have content that is all self-collapsing.
  // TODO(alancutter): Make this work correctly for calc lengths.
  if (has_auto_height || ((logical_height_length.IsFixed() ||
                           logical_height_length.IsPercentOrCalc()) &&
                          logical_height_length.IsZero())) {
    // If the block has inline children, see if we generated any line boxes.
    // If we have any line boxes, then we can't be self-collapsing, since we
    // have content.
    if (ChildrenInline())
      return !FirstLineBox();

    // Whether or not we collapse is dependent on whether all our normal flow
    // children are also self-collapsing.
    for (LayoutBox* child = FirstChildBox(); child;
         child = child->NextSiblingBox()) {
      if (child->IsFloatingOrOutOfFlowPositioned() || child->IsColumnSpanAll())
        continue;
      if (!child->IsSelfCollapsingBlock())
        return false;
    }
    return true;
  }
  return false;
}

DISABLE_CFI_PERF
void LayoutBlockFlow::UpdateBlockLayout(bool relayout_children) {
  DCHECK(NeedsLayout());
  DCHECK(IsInlineBlockOrInlineTable() || !IsInline());

  if (!relayout_children && SimplifiedLayout())
    return;

  LayoutAnalyzer::BlockScope analyzer(*this);
  SubtreeLayoutScope layout_scope(*this);

  LayoutUnit previous_height = LogicalHeight();
  LayoutUnit old_left = LogicalLeft();
  bool logical_width_changed = UpdateLogicalWidthAndColumnWidth();
  relayout_children |= logical_width_changed;

  TextAutosizer::LayoutScope text_autosizer_layout_scope(this, &layout_scope);

  bool pagination_state_changed = pagination_state_changed_;
  bool preferred_logical_widths_were_dirty = PreferredLogicalWidthsDirty();

  // Multiple passes might be required for column based layout.
  // The number of passes could be as high as the number of columns.
  LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread();
  do {
    LayoutState state(*this, logical_width_changed);
    if (pagination_state_changed_) {
      // We now need a deep layout to clean up struts after pagination, if we
      // just ceased to be paginated, or, if we just became paginated on the
      // other hand, we now need the deep layout, to insert pagination struts.
      pagination_state_changed_ = false;
      state.SetPaginationStateChanged();
    }

    LayoutChildren(relayout_children, layout_scope);

    if (!preferred_logical_widths_were_dirty && PreferredLogicalWidthsDirty()) {
      // The only thing that should dirty preferred widths at this point is the
      // addition of overflow:auto scrollbars in a descendant. To avoid a
      // potential infinite loop, run layout again with auto scrollbars frozen
      // in their current state.
      PaintLayerScrollableArea::FreezeScrollbarsScope freeze_scrollbars;
      relayout_children |= UpdateLogicalWidthAndColumnWidth();
      LayoutChildren(relayout_children, layout_scope);
    }

    if (flow_thread && flow_thread->ColumnHeightsChanged()) {
      SetChildNeedsLayout(kMarkOnlyThis);
      continue;
    }

    if (ShouldBreakAtLineToAvoidWidow()) {
      SetEverHadLayout();
      continue;
    }
    break;
  } while (true);

  LayoutState state(*this, logical_width_changed);
  if (pagination_state_changed) {
    // We still haven't laid out positioned descendants, and we need to perform
    // a deep layout on those too if pagination state changed.
    state.SetPaginationStateChanged();
  }

  // Remember the automatic logical height we got from laying out the children.
  LayoutUnit unconstrained_height = LogicalHeight();
  LayoutUnit unconstrained_client_after_edge = ClientLogicalBottom();

  // Adjust logical height to satisfy whatever computed style requires.
  UpdateLogicalHeight();

  if (!ChildrenInline())
    AddOverhangingFloatsFromChildren(unconstrained_height);

  if (LogicalHeight() != previous_height || IsDocumentElement())
    relayout_children = true;

  PositionedLayoutBehavior behavior = kDefaultLayout;
  if (old_left != LogicalLeft())
    behavior = kForcedLayoutAfterContainingBlockMoved;
  LayoutPositionedObjects(relayout_children, behavior);

  // Add overflow from children.
  ComputeOverflow(unconstrained_client_after_edge);

  descendants_with_floats_marked_for_layout_ = false;

  UpdateAfterLayout();

  if (isHTMLDialogElement(GetNode()) && IsOutOfFlowPositioned())
    PositionDialog();

  ClearNeedsLayout();
  UpdateIsSelfCollapsing();
}

DISABLE_CFI_PERF
void LayoutBlockFlow::ResetLayout() {
  if (!FirstChild() && !IsAnonymousBlock())
    SetChildrenInline(true);
  SetContainsInlineWithOutlineAndContinuation(false);

  RebuildFloatsFromIntruding();

  // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg,
  // to track our current maximal positive and negative margins. These values
  // are used when we are collapsed with adjacent blocks, so for example, if you
  // have block A and B collapsing together, then you'd take the maximal
  // positive margin from both A and B and subtract it from the maximal negative
  // margin from both A and B to get the true collapsed margin. This algorithm
  // is recursive, so when we finish layout() our block knows its current
  // maximal positive/negative values.
  //
  // Start out by setting our margin values to our current margins. Table cells
  // have no margins, so we don't fill in the values for table cells.
  if (!IsTableCell()) {
    InitMaxMarginValues();
    SetHasMarginBeforeQuirk(Style()->HasMarginBeforeQuirk());
    SetHasMarginAfterQuirk(Style()->HasMarginAfterQuirk());
  }

  if (View()->GetLayoutState()->IsPaginated()) {
    SetPaginationStrutPropagatedFromChild(LayoutUnit());
    SetFirstForcedBreakOffset(LayoutUnit());

    // Start with any applicable computed break-after and break-before values
    // for this object. During child layout, breakBefore will be joined with the
    // breakBefore value of the first in-flow child, and breakAfter will be
    // joined with the breakAfter value of the last in-flow child. This is done
    // in order to honor the requirement that a class A break point [1] may only
    // exists *between* in-flow siblings (i.e. not before the first child and
    // not after the last child).
    //
    // [1] https://drafts.csswg.org/css-break/#possible-breaks
    SetBreakBefore(LayoutBlock::BreakBefore());
    SetBreakAfter(LayoutBlock::BreakAfter());
  }
}

DISABLE_CFI_PERF
void LayoutBlockFlow::LayoutChildren(bool relayout_children,
                                     SubtreeLayoutScope& layout_scope) {
  ResetLayout();

  LayoutUnit before_edge = BorderBefore() + PaddingBefore();
  LayoutUnit after_edge =
      BorderAfter() + PaddingAfter() + ScrollbarLogicalHeight();
  SetLogicalHeight(before_edge);

  if (ChildrenInline())
    LayoutInlineChildren(relayout_children, after_edge);
  else
    LayoutBlockChildren(relayout_children, layout_scope, before_edge,
                        after_edge);

  // Expand our intrinsic height to encompass floats.
  if (LowestFloatLogicalBottom() > (LogicalHeight() - after_edge) &&
      CreatesNewFormattingContext())
    SetLogicalHeight(LowestFloatLogicalBottom() + after_edge);
}

void LayoutBlockFlow::AddOverhangingFloatsFromChildren(
    LayoutUnit unconstrained_height) {
  LayoutBlockFlow* lowest_block = nullptr;
  bool added_overhanging_floats = false;
  // One of our children's floats may have become an overhanging float for us.
  for (LayoutObject* child = LastChild(); child;
       child = child->PreviousSibling()) {
    // TODO(robhogan): We should exclude blocks that create formatting
    // contexts, not just out of flow or floating blocks.
    if (child->IsLayoutBlockFlow() &&
        !child->IsFloatingOrOutOfFlowPositioned()) {
      LayoutBlockFlow* block = ToLayoutBlockFlow(child);
      if (!block->ContainsFloats())
        continue;
      lowest_block = block;
      if (unconstrained_height <= LogicalHeight())
        break;
      LayoutUnit logical_bottom =
          block->LogicalTop() + block->LowestFloatLogicalBottom();
      if (logical_bottom <= LogicalHeight())
        break;
      AddOverhangingFloats(block, false);
      added_overhanging_floats = true;
    }
  }
  // If we have no overhanging floats we still pass a record of the lowest
  // non-overhanging float up the tree so we can enclose it if we are a
  // formatting context and allow siblings to avoid it if they have negative
  // margin and find themselves in its vicinity.
  if (!added_overhanging_floats)
    AddLowestFloatFromChildren(lowest_block);
}

void LayoutBlockFlow::AddLowestFloatFromChildren(LayoutBlockFlow* block) {
  // TODO(robhogan): Make createsNewFormattingContext an ASSERT.
  if (!block || !block->ContainsFloats() ||
      block->CreatesNewFormattingContext())
    return;

  FloatingObject* floating_object =
      block->floating_objects_->LowestFloatingObject();
  if (!floating_object || ContainsFloat(floating_object->GetLayoutObject()))
    return;

  LayoutSize offset(-block->LogicalLeft(), -block->LogicalTop());
  if (!IsHorizontalWritingMode())
    offset = offset.TransposedSize();

  if (!floating_objects_)
    CreateFloatingObjects();
  FloatingObject* new_floating_object = floating_objects_->Add(
      floating_object->CopyToNewContainer(offset, false, true));
  new_floating_object->SetIsLowestNonOverhangingFloatInChild(true);
}

DISABLE_CFI_PERF
void LayoutBlockFlow::DetermineLogicalLeftPositionForChild(LayoutBox& child) {
  LayoutUnit start_position = BorderStart() + PaddingStart();
  LayoutUnit initial_start_position = start_position;
  if (ShouldPlaceBlockDirectionScrollbarOnLogicalLeft())
    start_position -= VerticalScrollbarWidth();
  LayoutUnit total_available_logical_width =
      BorderAndPaddingLogicalWidth() + AvailableLogicalWidth();

  LayoutUnit child_margin_start = MarginStartForChild(child);
  LayoutUnit new_position = start_position + child_margin_start;

  if (child.AvoidsFloats() && ContainsFloats()) {
    LayoutUnit position_to_avoid_floats =
        StartOffsetForLine(LogicalTopForChild(child), kDoNotIndentText,
                           LogicalHeightForChild(child));

    // If the child has an offset from the content edge to avoid floats then use
    // that, otherwise let any negative margin pull it back over the content
    // edge or any positive margin push it out.
    // If the child is being centred then the margin calculated to do that has
    // factored in any offset required to avoid floats, so use it if necessary.
    if (Style()->GetTextAlign() == ETextAlign::kWebkitCenter ||
        child.Style()->MarginStartUsing(Style()).IsAuto())
      new_position =
          std::max(new_position, position_to_avoid_floats + child_margin_start);
    else if (position_to_avoid_floats > initial_start_position)
      new_position = std::max(new_position, position_to_avoid_floats);
  }

  SetLogicalLeftForChild(child, Style()->IsLeftToRightDirection()
                                    ? new_position
                                    : total_available_logical_width -
                                          new_position -
                                          LogicalWidthForChild(child));
}

void LayoutBlockFlow::SetLogicalLeftForChild(LayoutBox& child,
                                             LayoutUnit logical_left) {
  if (IsHorizontalWritingMode()) {
    child.SetX(logical_left);
  } else {
    child.SetY(logical_left);
  }
}

void LayoutBlockFlow::SetLogicalTopForChild(LayoutBox& child,
                                            LayoutUnit logical_top) {
  if (IsHorizontalWritingMode()) {
    child.SetY(logical_top);
  } else {
    child.SetX(logical_top);
  }
}

void LayoutBlockFlow::MarkDescendantsWithFloatsForLayoutIfNeeded(
    LayoutBlockFlow& child,
    LayoutUnit new_logical_top,
    LayoutUnit previous_float_logical_bottom) {
  // TODO(mstensho): rework the code to return early when there is no need for
  // marking, instead of this |markDescendantsWithFloats| flag.
  bool mark_descendants_with_floats = false;
  if (new_logical_top != child.LogicalTop() && !child.AvoidsFloats() &&
      child.ContainsFloats()) {
    mark_descendants_with_floats = true;
  } else if (UNLIKELY(new_logical_top.MightBeSaturated())) {
    // The logical top might be saturated for very large elements. Comparing
    // with the old logical top might then yield a false negative, as adding and
    // removing margins, borders etc. from a saturated number might yield
    // incorrect results. If this is the case, always mark for layout.
    mark_descendants_with_floats = true;
  } else if (!child.AvoidsFloats() || child.ShrinkToAvoidFloats()) {
    // If an element might be affected by the presence of floats, then always
    // mark it for layout.
    LayoutUnit lowest_float =
        std::max(previous_float_logical_bottom, LowestFloatLogicalBottom());
    if (lowest_float > new_logical_top)
      mark_descendants_with_floats = true;
  }

  if (mark_descendants_with_floats)
    child.MarkAllDescendantsWithFloatsForLayout();
}

bool LayoutBlockFlow::PositionAndLayoutOnceIfNeeded(
    LayoutBox& child,
    LayoutUnit new_logical_top,
    BlockChildrenLayoutInfo& layout_info) {
  if (LayoutFlowThread* flow_thread = FlowThreadContainingBlock())
    layout_info.RollBackToInitialMultiColumnLayoutState(*flow_thread);

  if (child.IsLayoutBlockFlow()) {
    LayoutUnit& previous_float_logical_bottom =
        layout_info.PreviousFloatLogicalBottom();
    LayoutBlockFlow& child_block_flow = ToLayoutBlockFlow(child);
    if (child_block_flow.ContainsFloats() || ContainsFloats())
      MarkDescendantsWithFloatsForLayoutIfNeeded(
          child_block_flow, new_logical_top, previous_float_logical_bottom);

    // TODO(mstensho): A writing mode root is one thing, but we should be able
    // to skip anything that establishes a new block formatting context here.
    // Their floats don't affect us.
    if (!child_block_flow.IsWritingModeRoot())
      previous_float_logical_bottom =
          std::max(previous_float_logical_bottom,
                   child_block_flow.LogicalTop() +
                       child_block_flow.LowestFloatLogicalBottom());
  }

  LayoutUnit old_logical_top = LogicalTopForChild(child);
  SetLogicalTopForChild(child, new_logical_top);

  SubtreeLayoutScope layout_scope(child);
  if (!child.NeedsLayout()) {
    if (new_logical_top != old_logical_top && child.ShrinkToAvoidFloats()) {
      // The child's width is affected by adjacent floats. When the child shifts
      // to clear an item, its width can change (because it has more available
      // width).
      layout_scope.SetChildNeedsLayout(&child);
    } else {
      MarkChildForPaginationRelayoutIfNeeded(child, layout_scope);
    }
  }

  bool needed_layout = child.NeedsLayout();
  if (needed_layout)
    child.UpdateLayout();
  if (View()->GetLayoutState()->IsPaginated())
    UpdateFragmentationInfoForChild(child);
  return needed_layout;
}

void LayoutBlockFlow::InsertForcedBreakBeforeChildIfNeeded(
    LayoutBox& child,
    BlockChildrenLayoutInfo& layout_info) {
  if (layout_info.IsAtFirstInFlowChild()) {
    // There's no class A break point before the first child (only *between*
    // siblings), so steal its break value and join it with what we already have
    // here.
    SetBreakBefore(
        JoinFragmentainerBreakValues(BreakBefore(), child.BreakBefore()));
    return;
  }

  // Figure out if a forced break should be inserted in front of the child. If
  // we insert a forced break, the margins on this child may not collapse with
  // those preceding the break.
  EBreakBetween class_a_break_point_value =
      child.ClassABreakPointValue(layout_info.PreviousBreakAfterValue());
  if (IsForcedFragmentainerBreakValue(class_a_break_point_value)) {
    layout_info.GetMarginInfo().ClearMargin();
    LayoutUnit old_logical_top = LogicalHeight();
    LayoutUnit new_logical_top =
        ApplyForcedBreak(old_logical_top, class_a_break_point_value);
    SetLogicalHeight(new_logical_top);
    LayoutUnit pagination_strut = new_logical_top - old_logical_top;
    child.SetPaginationStrut(pagination_strut);
  }
}

void LayoutBlockFlow::LayoutBlockChild(LayoutBox& child,
                                       BlockChildrenLayoutInfo& layout_info) {
  MarginInfo& margin_info = layout_info.GetMarginInfo();
  LayoutBlockFlow* child_layout_block_flow =
      child.IsLayoutBlockFlow() ? ToLayoutBlockFlow(&child) : nullptr;
  LayoutUnit old_pos_margin_before = MaxPositiveMarginBefore();
  LayoutUnit old_neg_margin_before = MaxNegativeMarginBefore();

  // The child is a normal flow object. Compute the margins we will use for
  // collapsing now.
  child.ComputeAndSetBlockDirectionMargins(this);

  // Try to guess our correct logical top position. In most cases this guess
  // will be correct. Only if we're wrong (when we compute the real logical top
  // position) will we have to potentially relayout.
  LayoutUnit estimate_without_pagination;
  LayoutUnit logical_top_estimate = EstimateLogicalTopPosition(
      child, layout_info, estimate_without_pagination);

  LayoutRect old_rect = child.FrameRect();

  if (LayoutFlowThread* flow_thread = FlowThreadContainingBlock())
    layout_info.StoreMultiColumnLayoutState(*flow_thread);

  // Use the estimated block position and lay out the child if needed. After
  // child layout, when we have enough information to perform proper margin
  // collapsing, float clearing and pagination, we may have to reposition and
  // lay out again if the estimate was wrong.
  bool child_needed_layout =
      PositionAndLayoutOnceIfNeeded(child, logical_top_estimate, layout_info);

  // Cache if we are at the top of the block right now.
  bool at_before_side_of_block = margin_info.AtBeforeSideOfBlock();
  bool child_is_self_collapsing = child.IsSelfCollapsingBlock();
  bool child_discard_margin_before = MustDiscardMarginBeforeForChild(child);
  bool child_discard_margin_after = MustDiscardMarginAfterForChild(child);
  bool paginated = View()->GetLayoutState()->IsPaginated();

  // If there should be a forced break before the child, we need to insert it
  // before attempting to collapse margins or apply clearance.
  if (paginated) {
    // We will now insert the strut needed by any forced break. After this
    // operation, we will have calculated the offset where we can apply margin
    // collapsing and clearance. After having applied those things, we'll be at
    // the position where we can honor requirements of unbreakable content,
    // which may extend the strut further.
    child.ResetPaginationStrut();
    InsertForcedBreakBeforeChildIfNeeded(child, layout_info);
  }

  // Now determine the correct ypos based off examination of collapsing margin
  // values.
  LayoutUnit logical_top_before_clear =
      CollapseMargins(child, layout_info, child_is_self_collapsing,
                      child_discard_margin_before, child_discard_margin_after);

  // Now check for clear.
  bool child_discard_margin =
      child_discard_margin_before || child_discard_margin_after;
  LayoutUnit new_logical_top = ClearFloatsIfNeeded(
      child, margin_info, old_pos_margin_before, old_neg_margin_before,
      logical_top_before_clear, child_is_self_collapsing, child_discard_margin);

  // If there's a forced break in front of this child, its final position has
  // already been determined. Otherwise, see if there are other reasons for
  // breaking before it (break-inside:avoid, or not enough space for the first
  // piece of child content to fit in the current fragmentainer), and adjust the
  // position accordingly.
  if (paginated) {
    if (estimate_without_pagination != new_logical_top) {
      // We got a new position due to clearance or margin collapsing. Before we
      // attempt to paginate (which may result in the position changing again),
      // let's try again at the new position (since a new position may result in
      // a new logical height).
      PositionAndLayoutOnceIfNeeded(child, new_logical_top, layout_info);
    }

    // We have now applied forced breaks, margin collapsing and clearance, and
    // we're at the position where we can honor requirements of unbreakable
    // content.
    new_logical_top = AdjustBlockChildForPagination(
        new_logical_top, child, layout_info,
        at_before_side_of_block && logical_top_before_clear == new_logical_top);
  }

  // Clearance, margin collapsing or pagination may have given us a new logical
  // top, in which case we may have to reposition and possibly relayout as well.
  // If we determined during child layout that we need to insert a break to
  // honor widows, we also need to relayout.
  if (new_logical_top != logical_top_estimate || child.NeedsLayout() ||
      (paginated && child_layout_block_flow &&
       child_layout_block_flow->ShouldBreakAtLineToAvoidWidow())) {
    PositionAndLayoutOnceIfNeeded(child, new_logical_top, layout_info);
  }

  // If we previously encountered a self-collapsing sibling of this child that
  // had clearance then we set this bit to ensure we would not collapse the
  // child's margins, and those of any subsequent self-collapsing siblings, with
  // our parent. If this child is not self-collapsing then it can collapse its
  // margins with the parent so reset the bit.
  if (!margin_info.CanCollapseMarginAfterWithLastChild() &&
      !child_is_self_collapsing)
    margin_info.SetCanCollapseMarginAfterWithLastChild(true);

  // We are no longer at the top of the block if we encounter a non-empty child.
  // This has to be done after checking for clear, so that margins can be reset
  // if a clear occurred.
  if (margin_info.AtBeforeSideOfBlock() && !child_is_self_collapsing)
    margin_info.SetAtBeforeSideOfBlock(false);

  // Now place the child in the correct left position
  DetermineLogicalLeftPositionForChild(child);

  LayoutSize child_offset = child.Location() - old_rect.Location();

  // Update our height now that the child has been placed in the correct
  // position.
  SetLogicalHeight(LogicalHeight() + LogicalHeightForChild(child));
  if (MustSeparateMarginAfterForChild(child)) {
    SetLogicalHeight(LogicalHeight() + MarginAfterForChild(child));
    margin_info.ClearMargin();
  }
  // If the child has overhanging floats that intrude into following siblings
  // (or possibly out of this block), then the parent gets notified of the
  // floats now.
  if (child_layout_block_flow)
    AddOverhangingFloats(child_layout_block_flow, !child_needed_layout);

  // If the child moved, we have to invalidate its paint as well as any
  // floating/positioned descendants. An exception is if we need a layout.
  // In this case, we know we're going to invalidate our paint (and the child)
  // anyway.
  if (!SelfNeedsLayout() && (child_offset.Width() || child_offset.Height()) &&
      child.IsLayoutBlockFlow())
    BlockFlowPaintInvalidator(ToLayoutBlockFlow(child))
        .InvalidatePaintForOverhangingFloats();

  if (paginated) {
    // Keep track of the break-after value of the child, so that it can be
    // joined with the break-before value of the next in-flow object at the next
    // class A break point.
    layout_info.SetPreviousBreakAfterValue(child.BreakAfter());

    PaginatedContentWasLaidOut(child.LogicalBottom());

    if (child_layout_block_flow) {
      // If a forced break was inserted inside the child, translate and
      // propagate the offset to this object.
      if (LayoutUnit offset = child_layout_block_flow->FirstForcedBreakOffset())
        SetFirstForcedBreakOffset(offset + new_logical_top);
    }
  }

  if (child.IsLayoutMultiColumnSpannerPlaceholder()) {
    // The actual column-span:all element is positioned by this placeholder
    // child.
    PositionSpannerDescendant(ToLayoutMultiColumnSpannerPlaceholder(child));
  }
}

LayoutUnit LayoutBlockFlow::AdjustBlockChildForPagination(
    LayoutUnit logical_top,
    LayoutBox& child,
    BlockChildrenLayoutInfo& layout_info,
    bool at_before_side_of_block) {
  LayoutBlockFlow* child_block_flow =
      child.IsLayoutBlockFlow() ? ToLayoutBlockFlow(&child) : 0;

  // See if we need a soft (unforced) break in front of this child, and set the
  // pagination strut in that case. An unforced break may come from two sources:
  // 1. The first piece of content inside the child doesn't fit in the current
  //    page or column
  // 2. The child itself has breaking restrictions (break-inside:avoid, replaced
  //    content, etc.) and doesn't fully fit in the current page or column.
  //
  // No matter which source, if we need to insert a strut, it should always take
  // us to the exact top of a page or column further ahead, or be zero.

  // The first piece of content inside the child may have set a strut during
  // layout. Currently, only block flows support strut propagation, but this may
  // (and should) change in the future. See crbug.com/539873
  LayoutUnit strut_from_content =
      child_block_flow ? child_block_flow->PaginationStrutPropagatedFromChild()
                       : LayoutUnit();
  LayoutUnit logical_top_with_content_strut = logical_top + strut_from_content;

  LayoutUnit logical_top_after_unsplittable =
      AdjustForUnsplittableChild(child, logical_top);

  // Pick the largest offset. Tall unsplittable content may take us to a page or
  // column further ahead than the next one.
  LayoutUnit logical_top_after_pagination =
      std::max(logical_top_with_content_strut, logical_top_after_unsplittable);
  LayoutUnit new_logical_top = logical_top;

  // Forced breaks may already have caused a strut, and this needs to be added
  // together with any strut detected here in this method.
  LayoutUnit previous_strut = child.PaginationStrut();

  if (LayoutUnit pagination_strut =
          logical_top_after_pagination - logical_top + previous_strut) {
    DCHECK_GT(pagination_strut, 0);
    // If we're not at the first in-flow child, there's a class A break point
    // before the child. If we *are* at the first in-flow child, but the child
    // isn't flush with the content edge of its container, due to e.g.
    // clearance, there's a class C break point before the child. Otherwise we
    // should propagate the strut to our parent block, and attempt to break
    // there instead. See https://drafts.csswg.org/css-break/#possible-breaks
    bool can_break =
        !layout_info.IsAtFirstInFlowChild() || !at_before_side_of_block;
    if (!can_break && child.GetPaginationBreakability() == kForbidBreaks &&
        !AllowsPaginationStrut()) {
      // The child is monolithic content, e.g. an image. It is truly
      // unsplittable. Breaking inside it would be bad. Since this block doesn't
      // allow pagination struts to be propagated to it, we're left to handle it
      // on our own right here. Break before the child, even if we're currently
      // at the block start (i.e. there's no class A or C break point here).
      can_break = true;
    }
    if (can_break) {
      child.SetPaginationStrut(pagination_strut);
      // |previousStrut| was already baked into the logical top, so don't add
      // it again.
      new_logical_top += pagination_strut - previous_strut;
    } else {
      // No valid break point here. Propagate the strut from the child to this
      // block, but only if the block allows it. If the block doesn't allow it,
      // we'll just ignore the strut and carry on, without breaking. This
      // happens e.g. when a tall break-inside:avoid object with a top margin is
      // the first in-flow child in the fragmentation context.
      if (AllowsPaginationStrut()) {
        pagination_strut += logical_top;
        SetPaginationStrutPropagatedFromChild(pagination_strut);
        if (child_block_flow)
          child_block_flow->SetPaginationStrutPropagatedFromChild(LayoutUnit());
      }
      child.ResetPaginationStrut();
    }
  }

  // Similar to how we apply clearance. Go ahead and boost height() to be the
  // place where we're going to position the child.
  SetLogicalHeight(LogicalHeight() + (new_logical_top - logical_top));

  // Return the final adjusted logical top.
  return new_logical_top;
}

LayoutUnit LayoutBlockFlow::AdjustFloatLogicalTopForPagination(
    LayoutBox& child,
    LayoutUnit logical_top_margin_edge) {
  // The first piece of content inside the child may have set a strut during
  // layout.
  LayoutUnit strut;
  if (child.IsLayoutBlockFlow())
    strut = ToLayoutBlockFlow(child).PaginationStrutPropagatedFromChild();

  LayoutUnit margin_before = MarginBeforeForChild(child);
  if (margin_before > LayoutUnit()) {
    // Avoid breaking inside the top margin of a float.
    if (strut) {
      // If we already had decided to break, just add the margin. The strut so
      // far only accounts for pushing the top border edge to the next
      // fragmentainer. We need to push the margin over as well, because
      // there's no break opportunity between margin and border.
      strut += margin_before;
    } else {
      // Even if we didn't break before the border box to the next
      // fragmentainer, we need to check if we can fit the margin before it.
      if (PageLogicalHeightForOffset(logical_top_margin_edge)) {
        LayoutUnit remaining_space = PageRemainingLogicalHeightForOffset(
            logical_top_margin_edge, kAssociateWithLatterPage);
        if (remaining_space <= margin_before) {
          strut += CalculatePaginationStrutToFitContent(
              logical_top_margin_edge, remaining_space, margin_before);
        }
      }
    }
  }
  if (!strut) {
    // If we are unsplittable and don't fit, move to the next page or column
    // if that helps the situation.
    LayoutUnit new_logical_top_margin_edge =
        AdjustForUnsplittableChild(child, logical_top_margin_edge);
    strut = new_logical_top_margin_edge - logical_top_margin_edge;
  }

  child.SetPaginationStrut(strut);
  return logical_top_margin_edge + strut;
}

static bool ShouldSetStrutOnBlock(const LayoutBlockFlow& block,
                                  const RootInlineBox& line_box,
                                  LayoutUnit line_logical_offset,
                                  int line_index,
                                  LayoutUnit page_logical_height) {
  if (line_box == block.FirstRootBox()) {
    // This is the first line in the block. We can take the whole block with us
    // to the next page or column, rather than keeping a content-less portion of
    // it in the previous one. Only do this if the line is flush with the
    // content edge of the block, though. If it isn't, it means that the line
    // was pushed downwards by preceding floats that didn't fit beside the line,
    // and we don't want to move all that, since it has already been established
    // that it fits nicely where it is. In this case we have a class "C" break
    // point [1] in front of this line.
    //
    // [1] https://drafts.csswg.org/css-break/#possible-breaks
    if (line_logical_offset > block.BorderAndPaddingBefore())
      return false;

    LayoutUnit line_height =
        line_box.LineBottomWithLeading() - line_box.LineTopWithLeading();
    LayoutUnit total_logical_height =
        line_height + line_logical_offset.ClampNegativeToZero();
    // It's rather pointless to break before the block if the current line isn't
    // going to fit in the same column or page, so check that as well.
    if (total_logical_height > page_logical_height)
      return false;
  } else {
    if (line_index > block.Style()->Orphans())
      return false;

    // Not enough orphans here. Push the entire block to the next column / page
    // as an attempt to better satisfy the orphans requirement.
    //
    // Note that we should ideally check if the first line in the block is flush
    // with the content edge of the block here, because if it isn't, we should
    // break at the class "C" break point in front of the first line, rather
    // than before the entire block.
  }
  return block.AllowsPaginationStrut();
}

void LayoutBlockFlow::AdjustLinePositionForPagination(RootInlineBox& line_box,
                                                      LayoutUnit& delta) {
  // TODO(mstensho): Pay attention to line overflow. It should be painted in the
  // same column as the rest of the line, possibly overflowing the column. We
  // currently only allow overflow above the first column. We clip at all other
  // column boundaries, and that's how it has to be for now. The paint we have
  // to do when a column has overflow has to be special.
  // We need to exclude content that paints in a previous column (and content
  // that paints in the following column).
  //
  // FIXME: Another problem with simply moving lines is that the available line
  // width may change (because of floats). Technically if the location we move
  // the line to has a different line width than our old position, then we need
  // to dirty the line and all following lines.
  LayoutUnit logical_offset = line_box.LineTopWithLeading();
  LayoutUnit line_height = line_box.LineBottomWithLeading() - logical_offset;
  logical_offset += delta;
  line_box.SetPaginationStrut(LayoutUnit());
  line_box.SetIsFirstAfterPageBreak(false);
  if (!View()->GetLayoutState()->IsPaginated())
    return;
  LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset);
  if (!page_logical_height)
    return;
  LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset(
      logical_offset, kAssociateWithLatterPage);
  int line_index = LineCount(&line_box);
  if (remaining_logical_height < line_height ||
      (ShouldBreakAtLineToAvoidWidow() &&
       LineBreakToAvoidWidow() == line_index)) {
    LayoutUnit pagination_strut = CalculatePaginationStrutToFitContent(
        logical_offset, remaining_logical_height, line_height);
    LayoutUnit new_logical_offset = logical_offset + pagination_strut;
    // Moving to a different page or column may mean that its height is
    // different.
    page_logical_height = PageLogicalHeightForOffset(new_logical_offset);
    if (line_height > page_logical_height) {
      // Too tall to fit in one page / column. Give up. Don't push to the next
      // page / column.
      // TODO(mstensho): Get rid of this. This is just utter weirdness, but the
      // other browsers also do something slightly similar, although in much
      // more specific cases than we do here, and printing Google Docs depends
      // on it.
      PaginatedContentWasLaidOut(logical_offset + line_height);
      return;
    }

    // We need to insert a break now, either because there's no room for the
    // line in the current column / page, or because we have determined that we
    // need a break to satisfy widow requirements.
    if (ShouldBreakAtLineToAvoidWidow() &&
        LineBreakToAvoidWidow() == line_index) {
      ClearShouldBreakAtLineToAvoidWidow();
      SetDidBreakAtLineToAvoidWidow();
    }
    if (ShouldSetStrutOnBlock(*this, line_box, logical_offset, line_index,
                              page_logical_height)) {
      // Note that when setting the strut on a block, it may be propagated to
      // parent blocks later on, if a block's logical top is flush with that of
      // its parent. We don't want content-less portions (struts) at the
      // beginning of a block before a break, if it can be avoided. After all,
      // that's the reason for setting struts on blocks and not lines in the
      // first place.
      SetPaginationStrutPropagatedFromChild(pagination_strut + logical_offset);
    } else {
      delta += pagination_strut;
      line_box.SetPaginationStrut(pagination_strut);
      line_box.SetIsFirstAfterPageBreak(true);
    }
    PaginatedContentWasLaidOut(new_logical_offset + line_height);
    return;
  }

  LayoutUnit strut_to_propagate;
  if (remaining_logical_height == page_logical_height) {
    // We're at the very top of a page or column.
    if (line_box != FirstRootBox())
      line_box.SetIsFirstAfterPageBreak(true);
    // If this is the first line in the block, and the block has a top border or
    // padding, we may want to set a strut on the block, so that everything ends
    // up in the next column or page. Setting a strut on the block is also
    // important when it comes to satisfying orphan requirements.
    if (ShouldSetStrutOnBlock(*this, line_box, logical_offset, line_index,
                              page_logical_height))
      strut_to_propagate = logical_offset;
  } else if (line_box == FirstRootBox() && AllowsPaginationStrut()) {
    // This is the first line in the block. The block may still start in the
    // previous column or page, and if that's the case, attempt to pull it over
    // to where this line is, so that we don't split the top border or padding.
    LayoutUnit strut =
        remaining_logical_height + logical_offset - page_logical_height;
    if (strut > LayoutUnit()) {
      // The block starts in a previous column or page. Set a strut on the block
      // if there's room for the top border, padding and the line in one column
      // or page.
      if (logical_offset + line_height <= page_logical_height)
        strut_to_propagate = strut;
    }
  }

  // If we found that some preceding content (lines, border and padding) belongs
  // together with this line, we should pull the entire block with us to the
  // fragmentainer we're currently in. We need to avoid this when the block
  // precedes the first fragmentainer, though. We shouldn't fragment content
  // there, but rather let it appear in the overflow area before the first
  // fragmentainer.
  if (strut_to_propagate && OffsetFromLogicalTopOfFirstPage() > LayoutUnit())
    SetPaginationStrutPropagatedFromChild(strut_to_propagate);

  PaginatedContentWasLaidOut(logical_offset + line_height);
}

LayoutUnit LayoutBlockFlow::AdjustForUnsplittableChild(
    LayoutBox& child,
    LayoutUnit logical_offset) const {
  if (child.GetPaginationBreakability() == kAllowAnyBreaks)
    return logical_offset;
  LayoutUnit child_logical_height = LogicalHeightForChild(child);
  // Floats' margins do not collapse with page or column boundaries.
  if (child.IsFloating())
    child_logical_height +=
        MarginBeforeForChild(child) + MarginAfterForChild(child);
  LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset);
  if (!page_logical_height)
    return logical_offset;
  LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset(
      logical_offset, kAssociateWithLatterPage);
  if (remaining_logical_height >= child_logical_height)
    return logical_offset;  // It fits fine where it is. No need to break.
  LayoutUnit pagination_strut = CalculatePaginationStrutToFitContent(
      logical_offset, remaining_logical_height, child_logical_height);
  if (pagination_strut == remaining_logical_height &&
      remaining_logical_height == page_logical_height) {
    // Don't break if we were at the top of a page, and we failed to fit the
    // content completely. No point in leaving a page completely blank.
    return logical_offset;
  }

  if (child.IsLayoutBlockFlow()) {
    // If there's a forced break inside this object, figure out if we can fit
    // everything before that forced break in the current fragmentainer. If it
    // fits, we don't need to insert a break before the child.
    const LayoutBlockFlow& block_child = ToLayoutBlockFlow(child);
    if (LayoutUnit first_break_offset = block_child.FirstForcedBreakOffset()) {
      if (remaining_logical_height >= first_break_offset)
        return logical_offset;
    }
  }

  return logical_offset + pagination_strut;
}

DISABLE_CFI_PERF
void LayoutBlockFlow::RebuildFloatsFromIntruding() {
  if (floating_objects_)
    floating_objects_->SetHorizontalWritingMode(IsHorizontalWritingMode());

  HashSet<LayoutBox*> old_intruding_float_set;
  if (!ChildrenInline() && floating_objects_) {
    const FloatingObjectSet& floating_object_set = floating_objects_->Set();
    FloatingObjectSetIterator end = floating_object_set.end();
    for (FloatingObjectSetIterator it = floating_object_set.begin(); it != end;
         ++it) {
      const FloatingObject& floating_object = *it->get();
      if (!floating_object.IsDescendant())
        old_intruding_float_set.insert(floating_object.GetLayoutObject());
    }
  }

  // Inline blocks are covered by the isAtomicInlineLevel() check in the
  // avoidFloats method.
  if (AvoidsFloats() || IsDocumentElement() || IsLayoutView() ||
      IsFloatingOrOutOfFlowPositioned() || IsTableCell()) {
    if (floating_objects_) {
      floating_objects_->Clear();
    }
    if (!old_intruding_float_set.IsEmpty())
      MarkAllDescendantsWithFloatsForLayout();
    return;
  }

  LayoutBoxToFloatInfoMap float_map;

  if (floating_objects_) {
    if (ChildrenInline())
      floating_objects_->MoveAllToFloatInfoMap(float_map);
    else
      floating_objects_->Clear();
  }

  // We should not process floats if the parent node is not a LayoutBlockFlow.
  // Otherwise, we will add floats in an invalid context. This will cause a
  // crash arising from a bad cast on the parent.
  // See <rdar://problem/8049753>, where float property is applied on a text
  // node in a SVG.
  if (!Parent() || !Parent()->IsLayoutBlockFlow())
    return;

  // Attempt to locate a previous sibling with overhanging floats. We skip any
  // elements that may have shifted to avoid floats, and any objects whose
  // floats cannot interact with objects outside it (i.e. objects that create a
  // new block formatting context).
  LayoutBlockFlow* parent_block_flow = ToLayoutBlockFlow(Parent());
  bool sibling_float_may_intrude = false;
  LayoutObject* prev = PreviousSibling();
  while (prev && (!prev->IsBox() || !prev->IsLayoutBlock() ||
                  ToLayoutBlock(prev)->AvoidsFloats() ||
                  ToLayoutBlock(prev)->CreatesNewFormattingContext())) {
    if (prev->IsFloating())
      sibling_float_may_intrude = true;
    prev = prev->PreviousSibling();
  }

  // First add in floats from the parent. Self-collapsing blocks let their
  // parent track any floats that intrude into them (as opposed to floats they
  // contain themselves) so check for those here too. If margin collapsing has
  // moved us up past the top a previous sibling then we need to check for
  // floats from the parent too.
  bool parent_floats_may_intrude =
      !sibling_float_may_intrude &&
      (!prev || ToLayoutBlockFlow(prev)->IsSelfCollapsingBlock() ||
       ToLayoutBlock(prev)->LogicalTop() > LogicalTop()) &&
      parent_block_flow->LowestFloatLogicalBottom() > LogicalTop();
  if (sibling_float_may_intrude || parent_floats_may_intrude)
    AddIntrudingFloats(parent_block_flow,
                       parent_block_flow->LogicalLeftOffsetForContent(),
                       LogicalTop());

  // Add overhanging floats from the previous LayoutBlockFlow, but only if it
  // has a float that intrudes into our space.
  if (prev) {
    LayoutBlockFlow* previous_block_flow = ToLayoutBlockFlow(prev);
    if (LogicalTop() < previous_block_flow->LogicalTop() +
                           previous_block_flow->LowestFloatLogicalBottom())
      AddIntrudingFloats(previous_block_flow, LayoutUnit(),
                         LogicalTop() - previous_block_flow->LogicalTop());
  }

  if (ChildrenInline()) {
    LayoutUnit change_logical_top = LayoutUnit::Max();
    LayoutUnit change_logical_bottom = LayoutUnit::Min();
    if (floating_objects_) {
      const FloatingObjectSet& floating_object_set = floating_objects_->Set();
      FloatingObjectSetIterator end = floating_object_set.end();
      for (FloatingObjectSetIterator it = floating_object_set.begin();
           it != end; ++it) {
        const FloatingObject& floating_object = *it->get();
        FloatingObject* old_floating_object =
            float_map.at(floating_object.GetLayoutObject());
        LayoutUnit logical_bottom = LogicalBottomForFloat(floating_object);
        if (old_floating_object) {
          LayoutUnit old_logical_bottom =
              LogicalBottomForFloat(*old_floating_object);
          if (LogicalWidthForFloat(floating_object) !=
                  LogicalWidthForFloat(*old_floating_object) ||
              LogicalLeftForFloat(floating_object) !=
                  LogicalLeftForFloat(*old_floating_object)) {
            change_logical_top = LayoutUnit();
            change_logical_bottom =
                std::max(change_logical_bottom,
                         std::max(logical_bottom, old_logical_bottom));
          } else {
            if (logical_bottom != old_logical_bottom) {
              change_logical_top =
                  std::min(change_logical_top,
                           std::min(logical_bottom, old_logical_bottom));
              change_logical_bottom =
                  std::max(change_logical_bottom,
                           std::max(logical_bottom, old_logical_bottom));
            }
            LayoutUnit logical_top = LogicalTopForFloat(floating_object);
            LayoutUnit old_logical_top =
                LogicalTopForFloat(*old_floating_object);
            if (logical_top != old_logical_top) {
              change_logical_top = std::min(
                  change_logical_top, std::min(logical_top, old_logical_top));
              change_logical_bottom =
                  std::max(change_logical_bottom,
                           std::max(logical_top, old_logical_top));
            }
          }

          if (old_floating_object->OriginatingLine() && !SelfNeedsLayout()) {
            DCHECK(old_floating_object->OriginatingLine()
                       ->GetLineLayoutItem()
                       .IsEqual(this));
            old_floating_object->OriginatingLine()->MarkDirty();
          }

          float_map.erase(floating_object.GetLayoutObject());
        } else {
          change_logical_top = LayoutUnit();
          change_logical_bottom =
              std::max(change_logical_bottom, logical_bottom);
        }
      }
    }

    LayoutBoxToFloatInfoMap::iterator end = float_map.end();
    for (LayoutBoxToFloatInfoMap::iterator it = float_map.begin(); it != end;
         ++it) {
      std::unique_ptr<FloatingObject>& floating_object = it->value;
      if (!floating_object->IsDescendant()) {
        change_logical_top = LayoutUnit();
        change_logical_bottom = std::max(
            change_logical_bottom, LogicalBottomForFloat(*floating_object));
      }
    }

    MarkLinesDirtyInBlockRange(change_logical_top, change_logical_bottom);
  } else if (!old_intruding_float_set.IsEmpty()) {
    // If there are previously intruding floats that no longer intrude, then
    // children with floats should also get layout because they might need their
    // floating object lists cleared.
    if (floating_objects_->Set().size() < old_intruding_float_set.size()) {
      MarkAllDescendantsWithFloatsForLayout();
    } else {
      const FloatingObjectSet& floating_object_set = floating_objects_->Set();
      FloatingObjectSetIterator end = floating_object_set.end();
      for (FloatingObjectSetIterator it = floating_object_set.begin();
           it != end && !old_intruding_float_set.IsEmpty(); ++it)
        old_intruding_float_set.erase((*it)->GetLayoutObject());
      if (!old_intruding_float_set.IsEmpty())
        MarkAllDescendantsWithFloatsForLayout();
    }
  }
}

void LayoutBlockFlow::LayoutBlockChildren(bool relayout_children,
                                          SubtreeLayoutScope& layout_scope,
                                          LayoutUnit before_edge,
                                          LayoutUnit after_edge) {
  DirtyForLayoutFromPercentageHeightDescendants(layout_scope);

  BlockChildrenLayoutInfo layout_info(this, before_edge, after_edge);
  MarginInfo& margin_info = layout_info.GetMarginInfo();

  // Fieldsets need to find their legend and position it inside the border of
  // the object.
  // The legend then gets skipped during normal layout. The same is true for
  // ruby text.
  // It doesn't get included in the normal layout process but is instead skipped
  LayoutObject* child_to_exclude =
      LayoutSpecialExcludedChild(relayout_children, layout_scope);

  // TODO(foolip): Speculative CHECKs to crash if any non-LayoutBox
  // children ever appear, the childrenInline() check at the call site
  // should make this impossible. crbug.com/632848
  LayoutObject* first_child = this->FirstChild();
  CHECK(!first_child || first_child->IsBox());
  LayoutBox* next = ToLayoutBox(first_child);
  LayoutBox* last_normal_flow_child = nullptr;

  while (next) {
    LayoutBox* child = next;
    LayoutObject* next_sibling = child->NextSibling();
    CHECK(!next_sibling || next_sibling->IsBox());
    next = ToLayoutBox(next_sibling);

    child->SetMayNeedPaintInvalidation();

    if (child_to_exclude == child)
      continue;  // Skip this child, since it will be positioned by the
                 // specialized subclass (fieldsets and ruby runs).

    UpdateBlockChildDirtyBitsBeforeLayout(relayout_children, *child);

    if (child->IsOutOfFlowPositioned()) {
      child->ContainingBlock()->InsertPositionedObject(child);
      AdjustPositionedBlock(*child, layout_info);
      continue;
    }
    if (child->IsFloating()) {
      InsertFloatingObject(*child);
      AdjustFloatingBlock(margin_info);
      continue;
    }
    if (child->IsColumnSpanAll()) {
      // This is not the containing block of the spanner. The spanner's
      // placeholder will lay it out in due course. For now we just need to
      // consult our flow thread, so that the columns (if any) preceding and
      // following the spanner are laid out correctly. But first we apply the
      // pending margin, so that it's taken into consideration and doesn't end
      // up on the other side of the spanner.
      SetLogicalHeight(LogicalHeight() + margin_info.Margin());
      margin_info.ClearMargin();

      child->SpannerPlaceholder()->FlowThread()->SkipColumnSpanner(
          child, OffsetFromLogicalTopOfFirstPage() + LogicalHeight());
      continue;
    }

    // Lay out the child.
    LayoutBlockChild(*child, layout_info);
    layout_info.ClearIsAtFirstInFlowChild();
    last_normal_flow_child = child;
  }

  // Now do the handling of the bottom of the block, adding in our bottom
  // border/padding and determining the correct collapsed bottom margin
  // information.
  HandleAfterSideOfBlock(last_normal_flow_child, before_edge, after_edge,
                         margin_info);
}

// Our MarginInfo state used when laying out block children.
MarginInfo::MarginInfo(LayoutBlockFlow* block_flow,
                       LayoutUnit before_border_padding,
                       LayoutUnit after_border_padding)
    : can_collapse_margin_after_with_last_child_(true),
      at_before_side_of_block_(true),
      at_after_side_of_block_(false),
      has_margin_before_quirk_(false),
      has_margin_after_quirk_(false),
      determined_margin_before_quirk_(false),
      discard_margin_(false),
      last_child_is_self_collapsing_block_with_clearance_(false) {
  const ComputedStyle& block_style = block_flow->StyleRef();
  DCHECK(block_flow->IsLayoutView() || block_flow->Parent());
  can_collapse_with_children_ = !block_flow->CreatesNewFormattingContext() &&
                                !block_flow->IsLayoutFlowThread() &&
                                !block_flow->IsLayoutView();

  can_collapse_margin_before_with_children_ =
      can_collapse_with_children_ && !before_border_padding &&
      block_style.MarginBeforeCollapse() != kMarginCollapseSeparate;

  // If any height other than auto is specified in CSS, then we don't collapse
  // our bottom margins with our children's margins. To do otherwise would be to
  // risk odd visual effects when the children overflow out of the parent block
  // and yet still collapse with it. We also don't collapse if we have any
  // bottom border/padding.
  can_collapse_margin_after_with_children_ =
      can_collapse_with_children_ && !after_border_padding &&
      (block_style.LogicalHeight().IsAuto() &&
       !block_style.LogicalHeight().Value()) &&
      block_style.MarginAfterCollapse() != kMarginCollapseSeparate;

  quirk_container_ = block_flow->IsTableCell() || block_flow->IsBody();

  discard_margin_ = can_collapse_margin_before_with_children_ &&
                    block_flow->MustDiscardMarginBefore();

  positive_margin_ = (can_collapse_margin_before_with_children_ &&
                      !block_flow->MustDiscardMarginBefore())
                         ? block_flow->MaxPositiveMarginBefore()
                         : LayoutUnit();
  negative_margin_ = (can_collapse_margin_before_with_children_ &&
                      !block_flow->MustDiscardMarginBefore())
                         ? block_flow->MaxNegativeMarginBefore()
                         : LayoutUnit();
}

LayoutBlockFlow::MarginValues LayoutBlockFlow::MarginValuesForChild(
    LayoutBox& child) const {
  LayoutUnit child_before_positive;
  LayoutUnit child_before_negative;
  LayoutUnit child_after_positive;
  LayoutUnit child_after_negative;

  LayoutUnit before_margin;
  LayoutUnit after_margin;

  LayoutBlockFlow* child_layout_block_flow =
      child.IsLayoutBlockFlow() ? ToLayoutBlockFlow(&child) : 0;

  // If the child has the same directionality as we do, then we can just return
  // its margins in the same direction.
  if (!child.IsWritingModeRoot()) {
    if (child_layout_block_flow) {
      child_before_positive =
          child_layout_block_flow->MaxPositiveMarginBefore();
      child_before_negative =
          child_layout_block_flow->MaxNegativeMarginBefore();
      child_after_positive = child_layout_block_flow->MaxPositiveMarginAfter();
      child_after_negative = child_layout_block_flow->MaxNegativeMarginAfter();
    } else {
      before_margin = child.MarginBefore();
      after_margin = child.MarginAfter();
    }
  } else if (child.IsHorizontalWritingMode() == IsHorizontalWritingMode()) {
    // The child has a different directionality. If the child is parallel, then
    // it's just flipped relative to us. We can use the margins for the opposite
    // edges.
    if (child_layout_block_flow) {
      child_before_positive = child_layout_block_flow->MaxPositiveMarginAfter();
      child_before_negative = child_layout_block_flow->MaxNegativeMarginAfter();
      child_after_positive = child_layout_block_flow->MaxPositiveMarginBefore();
      child_after_negative = child_layout_block_flow->MaxNegativeMarginBefore();
    } else {
      before_margin = child.MarginAfter();
      after_margin = child.MarginBefore();
    }
  } else {
    // The child is perpendicular to us, which means its margins don't collapse
    // but are on the "logical left/right" sides of the child box. We can just
    // return the raw margin in this case.
    before_margin = MarginBeforeForChild(child);
    after_margin = MarginAfterForChild(child);
  }

  // Resolve uncollapsing margins into their positive/negative buckets.
  if (before_margin) {
    if (before_margin > 0)
      child_before_positive = before_margin;
    else
      child_before_negative = -before_margin;
  }
  if (after_margin) {
    if (after_margin > 0)
      child_after_positive = after_margin;
    else
      child_after_negative = -after_margin;
  }

  return LayoutBlockFlow::MarginValues(
      child_before_positive, child_before_negative, child_after_positive,
      child_after_negative);
}

LayoutUnit LayoutBlockFlow::AdjustedMarginBeforeForPagination(
    const LayoutBox& child,
    LayoutUnit logical_top_margin_edge,
    LayoutUnit logical_top_border_edge,
    const BlockChildrenLayoutInfo& layout_info) const {
  LayoutUnit effective_margin =
      logical_top_border_edge - logical_top_margin_edge;
  DCHECK(IsPageLogicalHeightKnown());
  if (effective_margin <= LayoutUnit())
    return effective_margin;
  // If margins would pull us past the top of the next fragmentainer, then we
  // need to pull back and let the margins collapse into the fragmentainer
  // boundary. If we're at a fragmentainer boundary, and there's no forced break
  // involved, collapse the margin with the boundary we're at. Otherwise,
  // preserve the margin at the top of the fragmentainer, but collapse it with
  // the next fragmentainer boundary, since no margin should ever live in more
  // than one fragmentainer.
  PageBoundaryRule rule = kAssociateWithLatterPage;
  if (!child.NeedsForcedBreakBefore(layout_info.PreviousBreakAfterValue()) &&
      OffsetFromLogicalTopOfFirstPage() + logical_top_margin_edge >
          LayoutUnit())
    rule = kAssociateWithFormerPage;
  LayoutUnit remaining_space =
      PageRemainingLogicalHeightForOffset(logical_top_margin_edge, rule);
  return std::min(effective_margin, remaining_space);
}

LayoutUnit LayoutBlockFlow::CollapseMargins(
    LayoutBox& child,
    BlockChildrenLayoutInfo& layout_info,
    bool child_is_self_collapsing,
    bool child_discard_margin_before,
    bool child_discard_margin_after) {
  MarginInfo& margin_info = layout_info.GetMarginInfo();

  // The child discards the before margin when the the after margin has discard
  // in the case of a self collapsing block.
  child_discard_margin_before =
      child_discard_margin_before ||
      (child_discard_margin_after && child_is_self_collapsing);

  // Get the four margin values for the child and cache them.
  const LayoutBlockFlow::MarginValues child_margins =
      MarginValuesForChild(child);

  // Get our max pos and neg top margins.
  LayoutUnit pos_top = child_margins.PositiveMarginBefore();
  LayoutUnit neg_top = child_margins.NegativeMarginBefore();

  // For self-collapsing blocks, collapse our bottom margins into our
  // top to get new posTop and negTop values.
  if (child_is_self_collapsing) {
    pos_top = std::max(pos_top, child_margins.PositiveMarginAfter());
    neg_top = std::max(neg_top, child_margins.NegativeMarginAfter());
  }

  // See if the top margin is quirky. We only care if this child has
  // margins that will collapse with us.
  bool top_quirk = HasMarginBeforeQuirk(&child);

  if (margin_info.CanCollapseWithMarginBefore()) {
    if (!child_discard_margin_before && !margin_info.DiscardMargin()) {
      // This child is collapsing with the top of the
      // block. If it has larger margin values, then we need to update
      // our own maximal values.
      if (!GetDocument().InQuirksMode() || !margin_info.QuirkContainer() ||
          !top_quirk)
        SetMaxMarginBeforeValues(std::max(pos_top, MaxPositiveMarginBefore()),
                                 std::max(neg_top, MaxNegativeMarginBefore()));

      // The minute any of the margins involved isn't a quirk, don't
      // collapse it away, even if the margin is smaller (www.webreference.com
      // has an example of this, a <dt> with 0.8em author-specified inside
      // a <dl> inside a <td>.
      if (!margin_info.DeterminedMarginBeforeQuirk() && !top_quirk &&
          (pos_top - neg_top)) {
        SetHasMarginBeforeQuirk(false);
        margin_info.SetDeterminedMarginBeforeQuirk(true);
      }

      if (!margin_info.DeterminedMarginBeforeQuirk() && top_quirk &&
          !MarginBefore()) {
        // We have no top margin and our top child has a quirky margin.
        // We will pick up this quirky margin and pass it through.
        // This deals with the <td><div><p> case.
        // Don't do this for a block that split two inlines though. You do
        // still apply margins in this case.
        SetHasMarginBeforeQuirk(true);
      }
    } else {
      // The before margin of the container will also discard all the margins it
      // is collapsing with.
      SetMustDiscardMarginBefore();
    }
  }

  // Once we find a child with discardMarginBefore all the margins collapsing
  // with us must also discard.
  if (child_discard_margin_before) {
    margin_info.SetDiscardMargin(true);
    margin_info.ClearMargin();
  }

  if (margin_info.QuirkContainer() && margin_info.AtBeforeSideOfBlock() &&
      (pos_top - neg_top))
    margin_info.SetHasMarginBeforeQuirk(top_quirk);

  LayoutUnit before_collapse_logical_top = LogicalHeight();
  LayoutUnit logical_top = before_collapse_logical_top;

  LayoutObject* prev = child.PreviousSibling();
  LayoutBlockFlow* previous_block_flow =
      prev && prev->IsLayoutBlockFlow() ? ToLayoutBlockFlow(prev) : nullptr;
  bool previous_block_flow_can_self_collapse =
      previous_block_flow &&
      !previous_block_flow->IsFloatingOrOutOfFlowPositioned();
  // If the child's previous sibling is a self-collapsing block that cleared a
  // float then its top border edge has been set at the bottom border edge of
  // the float. Since we want to collapse the child's top margin with the self-
  // collapsing block's top and bottom margins we need to adjust our parent's
  // height to match the margin top of the self-collapsing block. If the
  // resulting collapsed margin leaves the child still intruding into the float
  // then we will want to clear it.
  if (!margin_info.CanCollapseWithMarginBefore() &&
      previous_block_flow_can_self_collapse &&
      margin_info.LastChildIsSelfCollapsingBlockWithClearance())
    SetLogicalHeight(
        LogicalHeight() -
        MarginValuesForChild(*previous_block_flow).PositiveMarginBefore());

  if (child_is_self_collapsing) {
    // For a self collapsing block both the before and after margins get
    // discarded. The block doesn't contribute anything to the height of the
    // block. Also, the child's top position equals the logical height of the
    // container.
    if (!child_discard_margin_before && !margin_info.DiscardMargin()) {
      // This child has no height. We need to compute our
      // position before we collapse the child's margins together,
      // so that we can get an accurate position for the zero-height block.
      LayoutUnit collapsed_before_pos = std::max(
          margin_info.PositiveMargin(), child_margins.PositiveMarginBefore());
      LayoutUnit collapsed_before_neg = std::max(
          margin_info.NegativeMargin(), child_margins.NegativeMarginBefore());
      margin_info.SetMargin(collapsed_before_pos, collapsed_before_neg);

      // Now collapse the child's margins together, which means examining our
      // bottom margin values as well.
      margin_info.SetPositiveMarginIfLarger(
          child_margins.PositiveMarginAfter());
      margin_info.SetNegativeMarginIfLarger(
          child_margins.NegativeMarginAfter());

      if (!margin_info.CanCollapseWithMarginBefore()) {
        // We need to make sure that the position of the self-collapsing block
        // is correct, since it could have overflowing content
        // that needs to be positioned correctly (e.g., a block that
        // had a specified height of 0 but that actually had subcontent).
        logical_top =
            LogicalHeight() + collapsed_before_pos - collapsed_before_neg;
      }
    }
  } else {
    if (MustSeparateMarginBeforeForChild(child)) {
      DCHECK(!margin_info.DiscardMargin() ||
             (margin_info.DiscardMargin() && !margin_info.Margin()));
      // If we are at the before side of the block and we collapse, ignore the
      // computed margin and just add the child margin to the container height.
      // This will correctly position the child inside the container.
      LayoutUnit separate_margin = !margin_info.CanCollapseWithMarginBefore()
                                       ? margin_info.Margin()
                                       : LayoutUnit();
      SetLogicalHeight(LogicalHeight() + separate_margin +
                       MarginBeforeForChild(child));
      logical_top = LogicalHeight();
    } else if (!margin_info.DiscardMargin() &&
               (!margin_info.AtBeforeSideOfBlock() ||
                (!margin_info.CanCollapseMarginBeforeWithChildren() &&
                 (!GetDocument().InQuirksMode() ||
                  !margin_info.QuirkContainer() ||
                  !margin_info.HasMarginBeforeQuirk())))) {
      // We're collapsing with a previous sibling's margins and not
      // with the top of the block.
      SetLogicalHeight(LogicalHeight() +
                       std::max(margin_info.PositiveMargin(), pos_top) -
                       std::max(margin_info.NegativeMargin(), neg_top));
      logical_top = LogicalHeight();
    }

    margin_info.SetDiscardMargin(child_discard_margin_after);

    if (!margin_info.DiscardMargin()) {
      margin_info.SetPositiveMargin(child_margins.PositiveMarginAfter());
      margin_info.SetNegativeMargin(child_margins.NegativeMarginAfter());
    } else {
      margin_info.ClearMargin();
    }

    if (margin_info.Margin())
      margin_info.SetHasMarginAfterQuirk(HasMarginAfterQuirk(&child));
  }

  if (View()->GetLayoutState()->IsPaginated() && IsPageLogicalHeightKnown()) {
    LayoutUnit old_logical_top = logical_top;
    LayoutUnit margin = AdjustedMarginBeforeForPagination(
        child, before_collapse_logical_top, logical_top, layout_info);
    logical_top = before_collapse_logical_top + margin;
    SetLogicalHeight(LogicalHeight() + (logical_top - old_logical_top));
  }

  // If |child| has moved up into previous siblings it needs to avoid or clear
  // any floats they contain.
  if (logical_top < before_collapse_logical_top) {
    LayoutUnit old_logical_height = LogicalHeight();
    SetLogicalHeight(logical_top);
    while (previous_block_flow) {
      auto lowest_float = previous_block_flow->LogicalTop() +
                          previous_block_flow->LowestFloatLogicalBottom();
      if (lowest_float > logical_top)
        AddOverhangingFloats(previous_block_flow, false);
      else
        break;
      LayoutObject* prev = previous_block_flow->PreviousSibling();
      if (prev && prev->IsLayoutBlockFlow())
        previous_block_flow = ToLayoutBlockFlow(prev);
      else
        previous_block_flow = nullptr;
    }
    SetLogicalHeight(old_logical_height);
  }

  if (previous_block_flow_can_self_collapse) {
    // If |child|'s previous sibling is or contains a self-collapsing block that
    // cleared a float and margin collapsing resulted in |child| moving up
    // into the margin area of the self-collapsing block then the float it
    // clears is now intruding into |child|. Layout again so that we can look
    // for floats in the parent that overhang |child|'s new logical top.
    bool logical_top_intrudes_into_float =
        logical_top < before_collapse_logical_top;
    if (logical_top_intrudes_into_float && ContainsFloats() &&
        !child.AvoidsFloats() && LowestFloatLogicalBottom() > logical_top)
      child.SetNeedsLayoutAndFullPaintInvalidation(
          LayoutInvalidationReason::kAncestorMarginCollapsing);
  }

  return logical_top;
}

void LayoutBlockFlow::AdjustPositionedBlock(
    LayoutBox& child,
    const BlockChildrenLayoutInfo& layout_info) {
  LayoutUnit logical_top = LogicalHeight();

  // Forced breaks are only specified on in-flow objects, but auto-positioned
  // out-of-flow objects may be affected by a break-after value of the previous
  // in-flow object.
  if (View()->GetLayoutState()->IsPaginated())
    logical_top =
        ApplyForcedBreak(logical_top, layout_info.PreviousBreakAfterValue());

  UpdateStaticInlinePositionForChild(child, logical_top);

  const MarginInfo& margin_info = layout_info.GetMarginInfo();
  if (!margin_info.CanCollapseWithMarginBefore()) {
    // Positioned blocks don't collapse margins, so add the margin provided by
    // the container now. The child's own margin is added later when calculating
    // its logical top.
    LayoutUnit collapsed_before_pos = margin_info.PositiveMargin();
    LayoutUnit collapsed_before_neg = margin_info.NegativeMargin();
    logical_top += collapsed_before_pos - collapsed_before_neg;
  }

  PaintLayer* child_layer = child.Layer();
  if (child_layer->StaticBlockPosition() != logical_top)
    child_layer->SetStaticBlockPosition(logical_top);
}

LayoutUnit LayoutBlockFlow::ClearFloatsIfNeeded(LayoutBox& child,
                                                MarginInfo& margin_info,
                                                LayoutUnit old_top_pos_margin,
                                                LayoutUnit old_top_neg_margin,
                                                LayoutUnit y_pos,
                                                bool child_is_self_collapsing,
                                                bool child_discard_margin) {
  LayoutUnit height_increase = GetClearDelta(&child, y_pos);
  margin_info.SetLastChildIsSelfCollapsingBlockWithClearance(false);

  if (!height_increase)
    return y_pos;

  if (child_is_self_collapsing) {
    margin_info.SetLastChildIsSelfCollapsingBlockWithClearance(true);
    margin_info.SetDiscardMargin(child_discard_margin);

    // For self-collapsing blocks that clear, they can still collapse their
    // margins with following siblings. Reset the current margins to represent
    // the self-collapsing block's margins only.
    // If DISCARD is specified for -webkit-margin-collapse, reset the margin
    // values.
    LayoutBlockFlow::MarginValues child_margins = MarginValuesForChild(child);
    if (!child_discard_margin) {
      margin_info.SetPositiveMargin(
          std::max(child_margins.PositiveMarginBefore(),
                   child_margins.PositiveMarginAfter()));
      margin_info.SetNegativeMargin(
          std::max(child_margins.NegativeMarginBefore(),
                   child_margins.NegativeMarginAfter()));
    } else {
      margin_info.ClearMargin();
    }

    // CSS2.1 states:
    // "If the top and bottom margins of an element with clearance are
    // adjoining, its margins collapse with the adjoining margins of following
    // siblings but that resulting margin does not collapse with the bottom
    // margin of the parent block."
    // So the parent's bottom margin cannot collapse through this block or any
    // subsequent self-collapsing blocks. Set a bit to ensure this happens; it
    // will get reset if we encounter an in-flow sibling that is not
    // self-collapsing.
    margin_info.SetCanCollapseMarginAfterWithLastChild(false);

    // For now set the border-top of |child| flush with the bottom border-edge
    // of the float so it can layout any floating or positioned children of its
    // own at the correct vertical position. If subsequent siblings attempt to
    // collapse with |child|'s margins in |collapseMargins| we will adjust the
    // height of the parent to |child|'s margin top (which if it is positive
    // sits up 'inside' the float it's clearing) so that all three margins can
    // collapse at the correct vertical position.
    // Per CSS2.1 we need to ensure that any negative margin-top clears |child|
    // beyond the bottom border-edge of the float so that the top border edge of
    // the child (i.e. its clearance)  is at a position that satisfies the
    // equation: "the amount of clearance is set so that:
    //   clearance + margin-top = [height of float],
    // i.e., clearance = [height of float] - margin-top".
    SetLogicalHeight(child.LogicalTop() + child_margins.NegativeMarginBefore());
  } else {
    // Increase our height by the amount we had to clear.
    SetLogicalHeight(LogicalHeight() + height_increase);
  }

  if (margin_info.CanCollapseWithMarginBefore()) {
    // We can no longer collapse with the top of the block since a clear
    // occurred. The empty blocks collapse into the cleared block.
    SetMaxMarginBeforeValues(old_top_pos_margin, old_top_neg_margin);
    margin_info.SetAtBeforeSideOfBlock(false);

    // In case the child discarded the before margin of the block we need to
    // reset the mustDiscardMarginBefore flag to the initial value.
    SetMustDiscardMarginBefore(Style()->MarginBeforeCollapse() ==
                               kMarginCollapseDiscard);
  }

  return y_pos + height_increase;
}

void LayoutBlockFlow::SetCollapsedBottomMargin(const MarginInfo& margin_info) {
  if (margin_info.CanCollapseWithMarginAfter() &&
      !margin_info.CanCollapseWithMarginBefore()) {
    // Update the after side margin of the container to discard if the after
    // margin of the last child also discards and we collapse with it.
    // Don't update the max margin values because we won't need them anyway.
    if (margin_info.DiscardMargin()) {
      SetMustDiscardMarginAfter();
      return;
    }

    // Update our max pos/neg bottom margins, since we collapsed our bottom
    // margins with our children.
    SetMaxMarginAfterValues(
        std::max(MaxPositiveMarginAfter(), margin_info.PositiveMargin()),
        std::max(MaxNegativeMarginAfter(), margin_info.NegativeMargin()));

    if (!margin_info.HasMarginAfterQuirk())
      SetHasMarginAfterQuirk(false);

    if (margin_info.HasMarginAfterQuirk() && !MarginAfter()) {
      // We have no bottom margin and our last child has a quirky margin.
      // We will pick up this quirky margin and pass it through.
      // This deals with the <td><div><p> case.
      SetHasMarginAfterQuirk(true);
    }
  }
}

DISABLE_CFI_PERF
void LayoutBlockFlow::MarginBeforeEstimateForChild(
    LayoutBox& child,
    LayoutUnit& positive_margin_before,
    LayoutUnit& negative_margin_before,
    bool& discard_margin_before) const {
  // Give up if in quirks mode and we're a body/table cell and the top margin of
  // the child box is quirky.
  // Give up if the child specified -webkit-margin-collapse: separate that
  // prevents collapsing.
  // FIXME: Use writing mode independent accessor for marginBeforeCollapse.
  if ((GetDocument().InQuirksMode() && HasMarginBeforeQuirk(&child) &&
       (IsTableCell() || IsBody())) ||
      child.Style()->MarginBeforeCollapse() == kMarginCollapseSeparate)
    return;

  // The margins are discarded by a child that specified
  // -webkit-margin-collapse: discard.
  // FIXME: Use writing mode independent accessor for marginBeforeCollapse.
  if (child.Style()->MarginBeforeCollapse() == kMarginCollapseDiscard) {
    positive_margin_before = LayoutUnit();
    negative_margin_before = LayoutUnit();
    discard_margin_before = true;
    return;
  }

  LayoutUnit before_child_margin = MarginBeforeForChild(child);
  positive_margin_before =
      std::max(positive_margin_before, before_child_margin);
  negative_margin_before =
      std::max(negative_margin_before, -before_child_margin);

  if (!child.IsLayoutBlockFlow())
    return;

  LayoutBlockFlow* child_block_flow = ToLayoutBlockFlow(&child);
  if (child_block_flow->ChildrenInline() ||
      child_block_flow->IsWritingModeRoot())
    return;

  MarginInfo child_margin_info(
      child_block_flow,
      child_block_flow->BorderBefore() + child_block_flow->PaddingBefore(),
      child_block_flow->BorderAfter() + child_block_flow->PaddingAfter());
  if (!child_margin_info.CanCollapseMarginBeforeWithChildren())
    return;

  LayoutBox* grandchild_box = child_block_flow->FirstChildBox();
  for (; grandchild_box; grandchild_box = grandchild_box->NextSiblingBox()) {
    if (!grandchild_box->IsFloatingOrOutOfFlowPositioned() &&
        !grandchild_box->IsColumnSpanAll())
      break;
  }

  if (!grandchild_box)
    return;

  // Make sure to update the block margins now for the grandchild box so that
  // we're looking at current values.
  if (grandchild_box->NeedsLayout()) {
    grandchild_box->ComputeAndSetBlockDirectionMargins(this);
    if (grandchild_box->IsLayoutBlock()) {
      LayoutBlock* grandchild_block = ToLayoutBlock(grandchild_box);
      grandchild_block->SetHasMarginBeforeQuirk(
          grandchild_box->Style()->HasMarginBeforeQuirk());
      grandchild_block->SetHasMarginAfterQuirk(
          grandchild_box->Style()->HasMarginAfterQuirk());
    }
  }

  // If we have a 'clear' value but also have a margin we may not actually
  // require clearance to move past any floats. If that's the case we want to be
  // sure we estimate the correct position including margins after any floats
  // rather than use 'clearance' later which could give us the wrong position.
  if (grandchild_box->Style()->Clear() != EClear::kNone &&
      child_block_flow->MarginBeforeForChild(*grandchild_box) == 0)
    return;

  // Collapse the margin of the grandchild box with our own to produce an
  // estimate.
  child_block_flow->MarginBeforeEstimateForChild(
      *grandchild_box, positive_margin_before, negative_margin_before,
      discard_margin_before);
}

LayoutUnit LayoutBlockFlow::EstimateLogicalTopPosition(
    LayoutBox& child,
    const BlockChildrenLayoutInfo& layout_info,
    LayoutUnit& estimate_without_pagination) {
  const MarginInfo& margin_info = layout_info.GetMarginInfo();
  // FIXME: We need to eliminate the estimation of vertical position, because
  // when it's wrong we sometimes trigger a pathological
  // relayout if there are intruding floats.
  LayoutUnit logical_top_estimate = LogicalHeight();
  LayoutUnit positive_margin_before;
  LayoutUnit negative_margin_before;
  bool discard_margin_before = false;
  if (!margin_info.CanCollapseWithMarginBefore()) {
    if (child.SelfNeedsLayout()) {
      // Try to do a basic estimation of how the collapse is going to go.
      MarginBeforeEstimateForChild(child, positive_margin_before,
                                   negative_margin_before,
                                   discard_margin_before);
    } else {
      // Use the cached collapsed margin values from a previous layout. Most of
      // the time they will be right.
      LayoutBlockFlow::MarginValues margin_values = MarginValuesForChild(child);
      positive_margin_before = std::max(positive_margin_before,
                                        margin_values.PositiveMarginBefore());
      negative_margin_before = std::max(negative_margin_before,
                                        margin_values.NegativeMarginBefore());
      discard_margin_before = MustDiscardMarginBeforeForChild(child);
    }

    // Collapse the result with our current margins.
    if (!discard_margin_before)
      logical_top_estimate +=
          std::max(margin_info.PositiveMargin(), positive_margin_before) -
          std::max(margin_info.NegativeMargin(), negative_margin_before);
  }

  LayoutState* layout_state = View()->GetLayoutState();
  if (layout_state->IsPaginated() && IsPageLogicalHeightKnown()) {
    LayoutUnit margin = AdjustedMarginBeforeForPagination(
        child, LogicalHeight(), logical_top_estimate, layout_info);
    logical_top_estimate = LogicalHeight() + margin;
  }

  logical_top_estimate += GetClearDelta(&child, logical_top_estimate);

  estimate_without_pagination = logical_top_estimate;

  if (layout_state->IsPaginated()) {
    if (!layout_info.IsAtFirstInFlowChild()) {
      // Estimate the need for a forced break in front of this child. The final
      // break policy at this class A break point isn't known until we have laid
      // out the children of |child|. There may be forced break-before values
      // set on first-children inside that get propagated up to the child.
      // Just make an estimate with what we know so far.
      EBreakBetween break_value =
          child.ClassABreakPointValue(layout_info.PreviousBreakAfterValue());
      if (IsForcedFragmentainerBreakValue(break_value)) {
        logical_top_estimate = ApplyForcedBreak(LogicalHeight(), break_value);
        // Disregard previous margins, since they will collapse with the
        // fragmentainer boundary, due to the forced break. Only apply margins
        // that have been specified on the child or its descendants.
        if (!discard_margin_before)
          logical_top_estimate +=
              positive_margin_before - negative_margin_before;

        // Clearance may already have taken us past the beginning of the next
        // fragmentainer.
        return std::max(estimate_without_pagination, logical_top_estimate);
      }

      logical_top_estimate =
          AdjustForUnsplittableChild(child, logical_top_estimate);
    }
  }

  return logical_top_estimate;
}

void LayoutBlockFlow::AdjustFloatingBlock(const MarginInfo& margin_info) {
  // The float should be positioned taking into account the bottom margin
  // of the previous flow. We add that margin into the height, get the
  // float positioned properly, and then subtract the margin out of the
  // height again. In the case of self-collapsing blocks, we always just
  // use the top margins, since the self-collapsing block collapsed its
  // own bottom margin into its top margin.
  //
  // Note also that the previous flow may collapse its margin into the top of
  // our block. If this is the case, then we do not add the margin in to our
  // height when computing the position of the float. This condition can be
  // tested for by simply calling canCollapseWithMarginBefore. See
  // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
  // an example of this scenario.
  LayoutUnit logical_top = LogicalHeight();
  if (!margin_info.CanCollapseWithMarginBefore())
    logical_top += margin_info.Margin();
  PlaceNewFloats(logical_top);
}

void LayoutBlockFlow::HandleAfterSideOfBlock(LayoutBox* last_child,
                                             LayoutUnit before_side,
                                             LayoutUnit after_side,
                                             MarginInfo& margin_info) {
  margin_info.SetAtAfterSideOfBlock(true);

  // If our last child was a self-collapsing block with clearance then our
  // logical height is flush with the bottom edge of the float that the child
  // clears. The correct vertical position for the margin-collapsing we want to
  // perform now is at the child's margin-top - so adjust our height to that
  // position.
  if (margin_info.LastChildIsSelfCollapsingBlockWithClearance()) {
    DCHECK(last_child);
    SetLogicalHeight(LogicalHeight() -
                     MarginValuesForChild(*last_child).PositiveMarginBefore());
  }

  if (margin_info.CanCollapseMarginAfterWithChildren() &&
      !margin_info.CanCollapseMarginAfterWithLastChild())
    margin_info.SetCanCollapseMarginAfterWithChildren(false);

  // If we can't collapse with children then go ahead and add in the bottom
  // margin.
  if (!margin_info.DiscardMargin() &&
      (!margin_info.CanCollapseWithMarginAfter() &&
       !margin_info.CanCollapseWithMarginBefore() &&
       (!GetDocument().InQuirksMode() || !margin_info.QuirkContainer() ||
        !margin_info.HasMarginAfterQuirk())))
    SetLogicalHeight(LogicalHeight() + margin_info.Margin());

  // Now add in our bottom border/padding.
  SetLogicalHeight(LogicalHeight() + after_side);

  // Negative margins can cause our height to shrink below our minimal height
  // (border/padding). If this happens, ensure that the computed height is
  // increased to the minimal height.
  SetLogicalHeight(std::max(LogicalHeight(), before_side + after_side));

  // Update our bottom collapsed margin info.
  SetCollapsedBottomMargin(margin_info);

  // There's no class A break point right after the last child, only *between*
  // siblings. So propagate the break-after value, and keep looking for a class
  // A break point (at the next in-flow block-level object), where we'll join
  // this break-after value with the break-before value there.
  if (View()->GetLayoutState()->IsPaginated() && last_child)
    SetBreakAfter(
        JoinFragmentainerBreakValues(BreakAfter(), last_child->BreakAfter()));
}

void LayoutBlockFlow::SetMustDiscardMarginBefore(bool value) {
  if (Style()->MarginBeforeCollapse() == kMarginCollapseDiscard) {
    DCHECK(value);
    return;
  }

  if (!rare_data_ && !value)
    return;

  if (!rare_data_)
    rare_data_ = WTF::MakeUnique<LayoutBlockFlowRareData>(this);

  rare_data_->discard_margin_before_ = value;
}

void LayoutBlockFlow::SetMustDiscardMarginAfter(bool value) {
  if (Style()->MarginAfterCollapse() == kMarginCollapseDiscard) {
    DCHECK(value);
    return;
  }

  if (!rare_data_ && !value)
    return;

  if (!rare_data_)
    rare_data_ = WTF::MakeUnique<LayoutBlockFlowRareData>(this);

  rare_data_->discard_margin_after_ = value;
}

bool LayoutBlockFlow::MustDiscardMarginBefore() const {
  return Style()->MarginBeforeCollapse() == kMarginCollapseDiscard ||
         (rare_data_ && rare_data_->discard_margin_before_);
}

bool LayoutBlockFlow::MustDiscardMarginAfter() const {
  return Style()->MarginAfterCollapse() == kMarginCollapseDiscard ||
         (rare_data_ && rare_data_->discard_margin_after_);
}

bool LayoutBlockFlow::MustDiscardMarginBeforeForChild(
    const LayoutBox& child) const {
  DCHECK(!child.SelfNeedsLayout());
  if (!child.IsWritingModeRoot())
    return child.IsLayoutBlockFlow()
               ? ToLayoutBlockFlow(&child)->MustDiscardMarginBefore()
               : (child.Style()->MarginBeforeCollapse() ==
                  kMarginCollapseDiscard);
  if (child.IsHorizontalWritingMode() == IsHorizontalWritingMode())
    return child.IsLayoutBlockFlow()
               ? ToLayoutBlockFlow(&child)->MustDiscardMarginAfter()
               : (child.Style()->MarginAfterCollapse() ==
                  kMarginCollapseDiscard);

  // FIXME: We return false here because the implementation is not geometrically
  // complete. We have values only for before/after, not start/end.
  // In case the boxes are perpendicular we assume the property is not
  // specified.
  return false;
}

bool LayoutBlockFlow::MustDiscardMarginAfterForChild(
    const LayoutBox& child) const {
  DCHECK(!child.SelfNeedsLayout());
  if (!child.IsWritingModeRoot())
    return child.IsLayoutBlockFlow()
               ? ToLayoutBlockFlow(&child)->MustDiscardMarginAfter()
               : (child.Style()->MarginAfterCollapse() ==
                  kMarginCollapseDiscard);
  if (child.IsHorizontalWritingMode() == IsHorizontalWritingMode())
    return child.IsLayoutBlockFlow()
               ? ToLayoutBlockFlow(&child)->MustDiscardMarginBefore()
               : (child.Style()->MarginBeforeCollapse() ==
                  kMarginCollapseDiscard);

  // FIXME: See |mustDiscardMarginBeforeForChild| above.
  return false;
}

void LayoutBlockFlow::SetMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg) {
  if (!rare_data_) {
    if (pos == LayoutBlockFlowRareData::PositiveMarginBeforeDefault(this) &&
        neg == LayoutBlockFlowRareData::NegativeMarginBeforeDefault(this))
      return;
    rare_data_ = WTF::MakeUnique<LayoutBlockFlowRareData>(this);
  }
  rare_data_->margins_.SetPositiveMarginBefore(pos);
  rare_data_->margins_.SetNegativeMarginBefore(neg);
}

void LayoutBlockFlow::SetMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg) {
  if (!rare_data_) {
    if (pos == LayoutBlockFlowRareData::PositiveMarginAfterDefault(this) &&
        neg == LayoutBlockFlowRareData::NegativeMarginAfterDefault(this))
      return;
    rare_data_ = WTF::MakeUnique<LayoutBlockFlowRareData>(this);
  }
  rare_data_->margins_.SetPositiveMarginAfter(pos);
  rare_data_->margins_.SetNegativeMarginAfter(neg);
}

bool LayoutBlockFlow::MustSeparateMarginBeforeForChild(
    const LayoutBox& child) const {
  DCHECK(!child.SelfNeedsLayout());
  const ComputedStyle& child_style = child.StyleRef();
  if (!child.IsWritingModeRoot())
    return child_style.MarginBeforeCollapse() == kMarginCollapseSeparate;
  if (child.IsHorizontalWritingMode() == IsHorizontalWritingMode())
    return child_style.MarginAfterCollapse() == kMarginCollapseSeparate;

  // FIXME: See |mustDiscardMarginBeforeForChild| above.
  return false;
}

bool LayoutBlockFlow::MustSeparateMarginAfterForChild(
    const LayoutBox& child) const {
  DCHECK(!child.SelfNeedsLayout());
  const ComputedStyle& child_style = child.StyleRef();
  if (!child.IsWritingModeRoot())
    return child_style.MarginAfterCollapse() == kMarginCollapseSeparate;
  if (child.IsHorizontalWritingMode() == IsHorizontalWritingMode())
    return child_style.MarginBeforeCollapse() == kMarginCollapseSeparate;

  // FIXME: See |mustDiscardMarginBeforeForChild| above.
  return false;
}

LayoutUnit LayoutBlockFlow::ApplyForcedBreak(LayoutUnit logical_offset,
                                             EBreakBetween break_value) {
  if (!IsForcedFragmentainerBreakValue(break_value))
    return logical_offset;
  // TODO(mstensho): honor breakValue. There are different types of forced
  // breaks. We currently just assume that we want to break to the top of the
  // next fragmentainer of the fragmentation context we're in. However, we may
  // want to find the next left or right page - even if we're inside a multicol
  // container when printing.
  LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset);
  if (!page_logical_height)
    return logical_offset;  // Page height is still unknown, so we cannot insert
                            // forced breaks.
  LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset(
      logical_offset, kAssociateWithLatterPage);
  if (remaining_logical_height == page_logical_height)
    return logical_offset;  // Don't break if we're already at the block start
                            // of a fragmentainer.

  // If this is the first forced break inside this object, store the
  // location. We need this information later if there's a break-inside:avoid
  // object further up. We need to know if there are any forced breaks inside
  // such objects, in order to determine whether we need to push it to the next
  // fragmentainer or not.
  if (!FirstForcedBreakOffset())
    SetFirstForcedBreakOffset(logical_offset);

  return logical_offset + remaining_logical_height;
}

void LayoutBlockFlow::SetBreakBefore(EBreakBetween break_value) {
  if (break_value != EBreakBetween::kAuto &&
      !IsBreakBetweenControllable(break_value))
    break_value = EBreakBetween::kAuto;
  if (break_value == EBreakBetween::kAuto && !rare_data_)
    return;
  EnsureRareData().break_before_ = static_cast<unsigned>(break_value);
}

void LayoutBlockFlow::SetBreakAfter(EBreakBetween break_value) {
  if (break_value != EBreakBetween::kAuto &&
      !IsBreakBetweenControllable(break_value))
    break_value = EBreakBetween::kAuto;
  if (break_value == EBreakBetween::kAuto && !rare_data_)
    return;
  EnsureRareData().break_after_ = static_cast<unsigned>(break_value);
}

EBreakBetween LayoutBlockFlow::BreakBefore() const {
  return rare_data_ ? static_cast<EBreakBetween>(rare_data_->break_before_)
                    : EBreakBetween::kAuto;
}

EBreakBetween LayoutBlockFlow::BreakAfter() const {
  return rare_data_ ? static_cast<EBreakBetween>(rare_data_->break_after_)
                    : EBreakBetween::kAuto;
}

void LayoutBlockFlow::AddOverflowFromFloats() {
  if (!floating_objects_)
    return;

  const FloatingObjectSet& floating_object_set = floating_objects_->Set();
  FloatingObjectSetIterator end = floating_object_set.end();
  for (FloatingObjectSetIterator it = floating_object_set.begin(); it != end;
       ++it) {
    const FloatingObject& floating_object = *it->get();
    if (floating_object.IsDescendant())
      AddOverflowFromChild(
          *floating_object.GetLayoutObject(),
          LayoutSize(XPositionForFloatIncludingMargin(floating_object),
                     YPositionForFloatIncludingMargin(floating_object)));
  }
}

void LayoutBlockFlow::ComputeOverflow(LayoutUnit old_client_after_edge,
                                      bool recompute_floats) {
  LayoutBlock::ComputeOverflow(old_client_after_edge, recompute_floats);
  if (recompute_floats || CreatesNewFormattingContext() ||
      HasSelfPaintingLayer())
    AddOverflowFromFloats();
}

void LayoutBlockFlow::ComputeSelfHitTestRects(
    Vector<LayoutRect>& rects,
    const LayoutPoint& layer_offset) const {
  LayoutBlock::ComputeSelfHitTestRects(rects, layer_offset);

  if (!HasHorizontalLayoutOverflow() && !HasVerticalLayoutOverflow())
    return;

  for (RootInlineBox* curr = FirstRootBox(); curr; curr = curr->NextRootBox()) {
    LayoutUnit top = std::max<LayoutUnit>(curr->LineTop(), curr->Y());
    LayoutUnit bottom =
        std::min<LayoutUnit>(curr->LineBottom(), curr->Y() + curr->Height());
    LayoutRect rect(layer_offset.X() + curr->X(), layer_offset.Y() + top,
                    curr->Width(), bottom - top);
    // It's common for this rect to be entirely contained in our box, so exclude
    // that simple case.
    if (!rect.IsEmpty() && (rects.IsEmpty() || !rects[0].Contains(rect)))
      rects.push_back(rect);
  }
}

void LayoutBlockFlow::AbsoluteRects(
    Vector<IntRect>& rects,
    const LayoutPoint& accumulated_offset) const {
  if (!IsAnonymousBlockContinuation()) {
    LayoutBlock::AbsoluteRects(rects, accumulated_offset);
    return;
  }
  // For blocks inside inlines, we go ahead and include margins so that we run
  // right up to the inline boxes above and below us (thus getting merged with
  // them to form a single irregular shape).
  // FIXME: This is wrong for vertical writing-modes.
  // https://bugs.webkit.org/show_bug.cgi?id=46781
  LayoutRect rect(accumulated_offset, Size());
  rect.Expand(CollapsedMarginBoxLogicalOutsets());
  rects.push_back(PixelSnappedIntRect(rect));
  Continuation()->AbsoluteRects(
      rects,
      accumulated_offset -
          ToLayoutSize(
              Location() +
              InlineElementContinuation()->ContainingBlock()->Location()));
}

void LayoutBlockFlow::AbsoluteQuads(Vector<FloatQuad>& quads,
                                    MapCoordinatesFlags mode) const {
  if (!IsAnonymousBlockContinuation()) {
    LayoutBlock::AbsoluteQuads(quads, mode);
    return;
  }
  LayoutBoxModelObject::AbsoluteQuads(quads, mode);
}

void LayoutBlockFlow::AbsoluteQuadsForSelf(Vector<FloatQuad>& quads,
                                           MapCoordinatesFlags mode) const {
  // For blocks inside inlines, we go ahead and include margins so that we run
  // right up to the inline boxes above and below us (thus getting merged with
  // them to form a single irregular shape).
  // FIXME: This is wrong for vertical writing-modes.
  // https://bugs.webkit.org/show_bug.cgi?id=46781
  LayoutRect local_rect(LayoutPoint(), Size());
  local_rect.Expand(CollapsedMarginBoxLogicalOutsets());
  quads.push_back(LocalToAbsoluteQuad(FloatRect(local_rect), mode));
}

LayoutObject* LayoutBlockFlow::HoverAncestor() const {
  return IsAnonymousBlockContinuation() ? Continuation()
                                        : LayoutBlock::HoverAncestor();
}

RootInlineBox* LayoutBlockFlow::CreateAndAppendRootInlineBox() {
  RootInlineBox* root_box = CreateRootInlineBox();
  line_boxes_.AppendLineBox(root_box);

  return root_box;
}

void LayoutBlockFlow::DeleteLineBoxTree() {
  if (ContainsFloats())
    floating_objects_->ClearLineBoxTreePointers();

  line_boxes_.DeleteLineBoxTree();
}

int LayoutBlockFlow::LineCount(
    const RootInlineBox* stop_root_inline_box) const {
#ifndef NDEBUG
  DCHECK(!stop_root_inline_box ||
         stop_root_inline_box->Block().DebugPointer() == this);
#endif
  if (!ChildrenInline())
    return 0;

  int count = 0;
  for (const RootInlineBox* box = FirstRootBox(); box;
       box = box->NextRootBox()) {
    count++;
    if (box == stop_root_inline_box)
      break;
  }
  return count;
}

int LayoutBlockFlow::FirstLineBoxBaseline() const {
  // Orthogonal grid items can participante in baseline alignment along column
  // axis.
  if (IsWritingModeRoot() && !IsRubyRun() && !IsGridItem())
    return -1;
  if (!ChildrenInline())
    return LayoutBlock::FirstLineBoxBaseline();
  if (FirstLineBox()) {
    const SimpleFontData* font_data = Style(true)->GetFont().PrimaryFont();
    DCHECK(font_data);
    if (!font_data)
      return -1;
    // fontMetrics 'ascent' is the distance above the baseline to the 'over'
    // edge, which is 'top' for horizontal and 'right' for vertical-lr and
    // vertical-rl. However, firstLineBox()->logicalTop() gives the offset from
    // the 'left' edge for vertical-lr, hence we need to use the Font Metrics
    // 'descent' instead. The result should be handled accordingly by the caller
    // as a 'descent' value, in order to compute properly the max baseline.
    if (StyleRef().IsFlippedLinesWritingMode()) {
      return (FirstLineBox()->LogicalTop() +
              font_data->GetFontMetrics().Descent(
                  FirstRootBox()->BaselineType()))
          .ToInt();
    }
    return (FirstLineBox()->LogicalTop() +
            font_data->GetFontMetrics().Ascent(FirstRootBox()->BaselineType()))
        .ToInt();
  }
  return -1;
}

int LayoutBlockFlow::InlineBlockBaseline(
    LineDirectionMode line_direction) const {
  // CSS2.1 states that the baseline of an 'inline-block' is:
  // the baseline of the last line box in the normal flow, unless it has
  // either no in-flow line boxes or if its 'overflow' property has a computed
  // value other than 'visible', in which case the baseline is the bottom
  // margin edge.
  // We likewise avoid using the last line box in the case of size containment,
  // where the block's contents shouldn't be considered when laying out its
  // ancestors or siblings.

  if ((!Style()->IsOverflowVisible() &&
       !ShouldIgnoreOverflowPropertyForInlineBlockBaseline()) ||
      Style()->ContainsSize()) {
    // We are not calling baselinePosition here because the caller should add
    // the margin-top/margin-right, not us.
    return (line_direction == kHorizontalLine ? Size().Height() + MarginBottom()
                                              : Size().Width() + MarginLeft())
        .ToInt();
  }
  if (IsWritingModeRoot() && !IsRubyRun())
    return -1;
  if (!ChildrenInline())
    return LayoutBlock::InlineBlockBaseline(line_direction);
  if (LastLineBox()) {
    const SimpleFontData* font_data =
        Style(LastLineBox() == FirstLineBox())->GetFont().PrimaryFont();
    DCHECK(font_data);
    if (!font_data)
      return -1;
    // InlineFlowBox::placeBoxesInBlockDirection will flip lines in
    // case of verticalLR mode, so we can assume verticalRL for now.
    if (Style()->IsFlippedLinesWritingMode()) {
      return (LogicalHeight() - LastLineBox()->LogicalBottom() +
              font_data->GetFontMetrics().Ascent(LastRootBox()->BaselineType()))
          .ToInt();
    }
    return (LastLineBox()->LogicalTop() +
            font_data->GetFontMetrics().Ascent(LastRootBox()->BaselineType()))
        .ToInt();
  }
  if (!HasLineIfEmpty())
    return -1;

  const SimpleFontData* font_data = FirstLineStyle()->GetFont().PrimaryFont();
  DCHECK(font_data);
  if (!font_data)
    return -1;

  const FontMetrics& font_metrics = font_data->GetFontMetrics();
  return (font_metrics.Ascent() +
          (LineHeight(true, line_direction, kPositionOfInteriorLineBoxes) -
           font_metrics.Height()) /
              2 +
          (line_direction == kHorizontalLine ? BorderTop() + PaddingTop()
                                             : BorderRight() + PaddingRight()))
      .ToInt();
}

void LayoutBlockFlow::RemoveFloatingObjectsFromDescendants() {
  if (!ContainsFloats())
    return;
  RemoveFloatingObjects();
  SetChildNeedsLayout(kMarkOnlyThis);

  // If our children are inline, then the only boxes which could contain floats
  // are atomic inlines (e.g. inline-block, float etc.) and these create
  // formatting contexts, so can't pick up intruding floats from
  // ancestors/siblings - making them safe to skip.
  if (ChildrenInline())
    return;
  for (LayoutObject* child = FirstChild(); child;
       child = child->NextSibling()) {
    // We don't skip blocks that create formatting contexts as they may have
    // only recently changed style and their float lists may still contain
    // floats from siblings and ancestors.
    if (child->IsLayoutBlockFlow())
      ToLayoutBlockFlow(child)->RemoveFloatingObjectsFromDescendants();
  }
}

void LayoutBlockFlow::MarkAllDescendantsWithFloatsForLayout(
    LayoutBox* float_to_remove,
    bool in_layout) {
  if (!EverHadLayout() && !ContainsFloats())
    return;

  if (descendants_with_floats_marked_for_layout_ && !float_to_remove)
    return;
  descendants_with_floats_marked_for_layout_ |= !float_to_remove;

  MarkingBehavior mark_parents =
      in_layout ? kMarkOnlyThis : kMarkContainerChain;
  SetChildNeedsLayout(mark_parents);

  if (float_to_remove)
    RemoveFloatingObject(float_to_remove);

  // Iterate over our children and mark them as needed. If our children are
  // inline, then the only boxes which could contain floats are atomic inlines
  // (e.g. inline-block, float etc.) and these create formatting contexts, so
  // can't pick up intruding floats from ancestors/siblings - making them safe
  // to skip.
  if (!ChildrenInline()) {
    for (LayoutObject* child = FirstChild(); child;
         child = child->NextSibling()) {
      if ((!float_to_remove && child->IsFloatingOrOutOfFlowPositioned()) ||
          !child->IsLayoutBlock())
        continue;
      if (!child->IsLayoutBlockFlow()) {
        LayoutBlock* child_block = ToLayoutBlock(child);
        if (child_block->ShrinkToAvoidFloats() && child_block->EverHadLayout())
          child_block->SetChildNeedsLayout(mark_parents);
        continue;
      }
      LayoutBlockFlow* child_block_flow = ToLayoutBlockFlow(child);
      if ((float_to_remove ? child_block_flow->ContainsFloat(float_to_remove)
                           : child_block_flow->ContainsFloats()) ||
          child_block_flow->ShrinkToAvoidFloats())
        child_block_flow->MarkAllDescendantsWithFloatsForLayout(float_to_remove,
                                                                in_layout);
    }
  }
}

void LayoutBlockFlow::MarkSiblingsWithFloatsForLayout(
    LayoutBox* float_to_remove) {
  if (!floating_objects_)
    return;

  const FloatingObjectSet& floating_object_set = floating_objects_->Set();
  FloatingObjectSetIterator end = floating_object_set.end();

  for (LayoutObject* next = NextSibling(); next; next = next->NextSibling()) {
    if (!next->IsLayoutBlockFlow() ||
        (!float_to_remove && (next->IsFloatingOrOutOfFlowPositioned() ||
                              ToLayoutBlockFlow(next)->AvoidsFloats())))
      continue;

    LayoutBlockFlow* next_block = ToLayoutBlockFlow(next);
    for (FloatingObjectSetIterator it = floating_object_set.begin(); it != end;
         ++it) {
      LayoutBox* floating_box = (*it)->GetLayoutObject();
      if (float_to_remove && floating_box != float_to_remove)
        continue;
      if (next_block->ContainsFloat(floating_box))
        next_block->MarkAllDescendantsWithFloatsForLayout(floating_box);
    }
  }
}

LayoutUnit LayoutBlockFlow::GetClearDelta(LayoutBox* child,
                                          LayoutUnit logical_top) {
  // There is no need to compute clearance if we have no floats.
  if (!ContainsFloats())
    return LayoutUnit();

  // At least one float is present. We need to perform the clearance
  // computation.
  EClear clear = child->Style()->Clear();
  LayoutUnit logical_bottom = LowestFloatLogicalBottom(clear);

  // We also clear floats if we are too big to sit on the same line as a float
  // (and wish to avoid floats by default).
  LayoutUnit result = clear != EClear::kNone
                          ? (logical_bottom - logical_top).ClampNegativeToZero()
                          : LayoutUnit();
  if (!result && child->AvoidsFloats()) {
    LayoutUnit new_logical_top = logical_top;
    LayoutRect border_box = child->BorderBoxRect();
    LayoutUnit child_logical_width_at_old_logical_top_offset =
        IsHorizontalWritingMode() ? border_box.Width() : border_box.Height();
    while (true) {
      LayoutUnit available_logical_width_at_new_logical_top_offset =
          AvailableLogicalWidthForLine(new_logical_top, kDoNotIndentText,
                                       LogicalHeightForChild(*child));
      if (available_logical_width_at_new_logical_top_offset ==
          AvailableLogicalWidthForContent())
        return new_logical_top - logical_top;

      LogicalExtentComputedValues computed_values;
      child->LogicalExtentAfterUpdatingLogicalWidth(new_logical_top,
                                                    computed_values);
      LayoutUnit child_logical_width_at_new_logical_top_offset =
          computed_values.extent_;

      if (child_logical_width_at_new_logical_top_offset <=
          available_logical_width_at_new_logical_top_offset) {
        // Even though we may not be moving, if the logical width did shrink
        // because of the presence of new floats, then we need to force a
        // relayout as though we shifted. This happens because of the dynamic
        // addition of overhanging floats from previous siblings when negative
        // margins exist on a child (see the addOverhangingFloats call at the
        // end of collapseMargins).
        if (child_logical_width_at_old_logical_top_offset !=
            child_logical_width_at_new_logical_top_offset)
          child->SetChildNeedsLayout(kMarkOnlyThis);
        return new_logical_top - logical_top;
      }

      new_logical_top = NextFloatLogicalBottomBelowForBlock(new_logical_top);
      DCHECK_GE(new_logical_top, logical_top);
      if (new_logical_top < logical_top)
        break;
    }
    NOTREACHED();
  }
  return result;
}

void LayoutBlockFlow::CreateFloatingObjects() {
  floating_objects_ =
      WTF::WrapUnique(new FloatingObjects(this, IsHorizontalWritingMode()));
}

void LayoutBlockFlow::WillBeDestroyed() {
  // Mark as being destroyed to avoid trouble with merges in removeChild().
  being_destroyed_ = true;

  // Make sure to destroy anonymous children first while they are still
  // connected to the rest of the tree, so that they will properly dirty line
  // boxes that they are removed from. Effects that do :before/:after only on
  // hover could crash otherwise.
  Children()->DestroyLeftoverChildren();

  // Destroy our continuation before anything other than anonymous children.
  // The reason we don't destroy it before anonymous children is that they may
  // have continuations of their own that are anonymous children of our
  // continuation.
  LayoutBoxModelObject* continuation = this->Continuation();
  if (continuation) {
    continuation->Destroy();
    SetContinuation(nullptr);
  }

  if (!DocumentBeingDestroyed()) {
    // TODO(mstensho): figure out if we need this. We have no test coverage for
    // it. It looks like all line boxes have been removed at this point.
    if (FirstLineBox()) {
      // If we are an anonymous block, then our line boxes might have children
      // that will outlast this block. In the non-anonymous block case those
      // children will be destroyed by the time we return from this function.
      if (IsAnonymousBlock()) {
        for (InlineFlowBox* box = FirstLineBox(); box;
             box = box->NextLineBox()) {
          while (InlineBox* child_box = box->FirstChild())
            child_box->Remove();
        }
      }
    }
  }

  line_boxes_.DeleteLineBoxes();

  LayoutBlock::WillBeDestroyed();
}

void LayoutBlockFlow::StyleWillChange(StyleDifference diff,
                                      const ComputedStyle& new_style) {
  const ComputedStyle* old_style = Style();
  can_propagate_float_into_sibling_ =
      old_style ? !IsFloatingOrOutOfFlowPositioned() && !AvoidsFloats() : false;
  if (old_style && Parent() && diff.NeedsFullLayout() &&
      old_style->GetPosition() != new_style.GetPosition() && ContainsFloats() &&
      !IsFloating() && !IsOutOfFlowPositioned() &&
      new_style.HasOutOfFlowPosition())
    MarkAllDescendantsWithFloatsForLayout();

  LayoutBlock::StyleWillChange(diff, new_style);
}

DISABLE_CFI_PERF
void LayoutBlockFlow::StyleDidChange(StyleDifference diff,
                                     const ComputedStyle* old_style) {
  bool had_self_painting_layer = HasSelfPaintingLayer();
  LayoutBlock::StyleDidChange(diff, old_style);

  // After our style changed, if we lose our ability to propagate floats into
  // next sibling blocks, then we need to find the top most parent containing
  // that overhanging float and then mark its descendants with floats for layout
  // and clear all floats from its next sibling blocks that exist in our
  // floating objects list. See crbug.com/56299 and crbug.com/62875.
  bool can_propagate_float_into_sibling =
      !IsFloatingOrOutOfFlowPositioned() && !AvoidsFloats();
  bool sibling_float_propagation_changed =
      diff.NeedsFullLayout() && can_propagate_float_into_sibling_ &&
      !can_propagate_float_into_sibling && HasOverhangingFloats();

  // When this object's self-painting layer status changed, we should update
  // FloatingObjects::shouldPaint() flags for descendant overhanging floats in
  // ancestors.
  bool needs_update_ancestor_float_object_should_paint_flags = false;
  if (HasSelfPaintingLayer() != had_self_painting_layer &&
      HasOverhangingFloats()) {
    SetNeedsLayout(LayoutInvalidationReason::kStyleChange);
    if (had_self_painting_layer)
      MarkAllDescendantsWithFloatsForLayout();
    else
      needs_update_ancestor_float_object_should_paint_flags = true;
  }

  if (sibling_float_propagation_changed ||
      needs_update_ancestor_float_object_should_paint_flags) {
    LayoutBlockFlow* parent_block_flow = this;
    const FloatingObjectSet& floating_object_set = floating_objects_->Set();
    FloatingObjectSetIterator end = floating_object_set.end();

    for (LayoutObject* curr = Parent(); curr && !curr->IsLayoutView();
         curr = curr->Parent()) {
      if (curr->IsLayoutBlockFlow()) {
        LayoutBlockFlow* curr_block = ToLayoutBlockFlow(curr);

        if (curr_block->HasOverhangingFloats()) {
          for (FloatingObjectSetIterator it = floating_object_set.begin();
               it != end; ++it) {
            LayoutBox* layout_box = (*it)->GetLayoutObject();
            if (curr_block->HasOverhangingFloat(layout_box)) {
              parent_block_flow = curr_block;
              break;
            }
          }
        }
      }
    }

    parent_block_flow->MarkAllDescendantsWithFloatsForLayout();
    if (sibling_float_propagation_changed)
      parent_block_flow->MarkSiblingsWithFloatsForLayout();
  }

  if (diff.NeedsFullLayout() || !old_style)
    CreateOrDestroyMultiColumnFlowThreadIfNeeded(old_style);
  if (old_style) {
    if (LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread()) {
      if (!Style()->ColumnRuleEquivalent(old_style)) {
        // Column rules are painted by anonymous column set children of the
        // multicol container. We need to notify them.
        flow_thread->ColumnRuleStyleDidChange();
      }
    }
  }
}

void LayoutBlockFlow::UpdateBlockChildDirtyBitsBeforeLayout(
    bool relayout_children,
    LayoutBox& child) {
  if (child.IsLayoutMultiColumnSpannerPlaceholder())
    ToLayoutMultiColumnSpannerPlaceholder(child)
        .MarkForLayoutIfObjectInFlowThreadNeedsLayout();
  LayoutBlock::UpdateBlockChildDirtyBitsBeforeLayout(relayout_children, child);
}

void LayoutBlockFlow::UpdateStaticInlinePositionForChild(
    LayoutBox& child,
    LayoutUnit logical_top,
    IndentTextOrNot indent_text) {
  if (child.Style()->IsOriginalDisplayInlineType())
    SetStaticInlinePositionForChild(
        child, StartAlignedOffsetForLine(logical_top, indent_text));
  else
    SetStaticInlinePositionForChild(child, StartOffsetForContent());
}

void LayoutBlockFlow::SetStaticInlinePositionForChild(
    LayoutBox& child,
    LayoutUnit inline_position) {
  child.Layer()->SetStaticInlinePosition(inline_position);
}

LayoutInline* LayoutBlockFlow::InlineElementContinuation() const {
  LayoutBoxModelObject* continuation = this->Continuation();
  return continuation && continuation->IsInline() ? ToLayoutInline(continuation)
                                                  : nullptr;
}

void LayoutBlockFlow::AddChild(LayoutObject* new_child,
                               LayoutObject* before_child) {
  if (LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread()) {
    if (before_child == flow_thread)
      before_child = flow_thread->FirstChild();
    DCHECK(!before_child || before_child->IsDescendantOf(flow_thread));
    flow_thread->AddChild(new_child, before_child);
    return;
  }

  if (before_child && before_child->Parent() != this) {
    AddChildBeforeDescendant(new_child, before_child);
    return;
  }

  bool made_boxes_non_inline = false;

  // A block has to either have all of its children inline, or all of its
  // children as blocks.
  // So, if our children are currently inline and a block child has to be
  // inserted, we move all our inline children into anonymous block boxes.
  bool child_is_block_level =
      !new_child->IsInline() && !new_child->IsFloatingOrOutOfFlowPositioned();
  if (ChildrenInline()) {
    if (child_is_block_level) {
      // Wrap the inline content in anonymous blocks, to allow for the new block
      // child to be inserted.
      MakeChildrenNonInline(before_child);
      made_boxes_non_inline = true;

      if (before_child && before_child->Parent() != this) {
        before_child = before_child->Parent();
        DCHECK(before_child->IsAnonymousBlock());
        DCHECK_EQ(before_child->Parent(), this);
      }
    }
  } else if (!child_is_block_level) {
    // This block has block children. We may want to put the new child into an
    // anomyous block. Floats and out-of-flow children may live among either
    // block or inline children, so for such children, only put them inside an
    // anonymous block if one already exists. If the child is inline, on the
    // other hand, we *have to* put it inside an anonymous block, so create a
    // new one if there is none for us there already.
    LayoutObject* after_child =
        before_child ? before_child->PreviousSibling() : LastChild();

    if (after_child && after_child->IsAnonymousBlock()) {
      after_child->AddChild(new_child);
      return;
    }

    if (new_child->IsInline()) {
      // No suitable existing anonymous box - create a new one.
      LayoutBlockFlow* new_block = ToLayoutBlockFlow(CreateAnonymousBlock());
      LayoutBox::AddChild(new_block, before_child);
      // Reparent adjacent floating or out-of-flow siblings to the new box.
      new_block->ReparentPrecedingFloatingOrOutOfFlowSiblings();
      new_block->AddChild(new_child);
      new_block->ReparentSubsequentFloatingOrOutOfFlowSiblings();
      return;
    }
  }

  // Skip the LayoutBlock override, since that one deals with anonymous child
  // insertion in a way that isn't sufficient for us, and can only cause trouble
  // at this point.
  LayoutBox::AddChild(new_child, before_child);

  if (made_boxes_non_inline && Parent() && IsAnonymousBlock() &&
      Parent()->IsLayoutBlock()) {
    ToLayoutBlock(Parent())->RemoveLeftoverAnonymousBlock(this);
    // |this| may be dead now.
  }
}

static bool IsMergeableAnonymousBlock(const LayoutBlockFlow* block) {
  return block->IsAnonymousBlock() && !block->Continuation() &&
         !block->BeingDestroyed() && !block->IsRubyRun() &&
         !block->IsRubyBase();
}

void LayoutBlockFlow::RemoveChild(LayoutObject* old_child) {
  // No need to waste time in merging or removing empty anonymous blocks.
  // We can just bail out if our document is getting destroyed.
  if (DocumentBeingDestroyed()) {
    LayoutBox::RemoveChild(old_child);
    return;
  }

  // If this child is a block, and if our previous and next siblings are
  // both anonymous blocks with inline content, then we can go ahead and
  // fold the inline content back together.
  LayoutObject* prev = old_child->PreviousSibling();
  LayoutObject* next = old_child->NextSibling();
  bool merged_anonymous_blocks = false;
  if (prev && next && !old_child->IsInline() &&
      !old_child->VirtualContinuation() && prev->IsLayoutBlockFlow() &&
      next->IsLayoutBlockFlow()) {
    if (ToLayoutBlockFlow(prev)->MergeSiblingContiguousAnonymousBlock(
            ToLayoutBlockFlow(next))) {
      merged_anonymous_blocks = true;
      next = nullptr;
    }
  }

  LayoutBlock::RemoveChild(old_child);

  LayoutObject* child = prev ? prev : next;
  if (child && child->IsLayoutBlockFlow() && !child->PreviousSibling() &&
      !child->NextSibling()) {
    // If the removal has knocked us down to containing only a single anonymous
    // box we can go ahead and pull the content right back up into our
    // box.
    if (merged_anonymous_blocks ||
        IsMergeableAnonymousBlock(ToLayoutBlockFlow(child)))
      CollapseAnonymousBlockChild(ToLayoutBlockFlow(child));
  }

  if (!FirstChild()) {
    // If this was our last child be sure to clear out our line boxes.
    if (ChildrenInline())
      DeleteLineBoxTree();

    // If we are an empty anonymous block in the continuation chain,
    // we need to remove ourself and fix the continuation chain.
    if (!BeingDestroyed() && IsAnonymousBlockContinuation() &&
        !old_child->IsListMarker()) {
      LayoutObject* containing_block_ignoring_anonymous = ContainingBlock();
      while (containing_block_ignoring_anonymous &&
             containing_block_ignoring_anonymous->IsAnonymous())
        containing_block_ignoring_anonymous =
            containing_block_ignoring_anonymous->ContainingBlock();
      for (LayoutObject* curr = this; curr;
           curr =
               curr->PreviousInPreOrder(containing_block_ignoring_anonymous)) {
        if (curr->VirtualContinuation() != this)
          continue;

        // Found our previous continuation. We just need to point it to
        // |this|'s next continuation.
        LayoutBoxModelObject* next_continuation = Continuation();
        if (curr->IsLayoutInline())
          ToLayoutInline(curr)->SetContinuation(next_continuation);
        else if (curr->IsLayoutBlockFlow())
          ToLayoutBlockFlow(curr)->SetContinuation(next_continuation);
        else
          NOTREACHED();

        break;
      }
      SetContinuation(nullptr);
      Destroy();
    }
  } else if (!BeingDestroyed() &&
             !old_child->IsFloatingOrOutOfFlowPositioned() &&
             !old_child->IsAnonymousBlock()) {
    // If the child we're removing means that we can now treat all children as
    // inline without the need for anonymous blocks, then do that.
    MakeChildrenInlineIfPossible();
  }
}

void LayoutBlockFlow::MoveAllChildrenIncludingFloatsTo(
    LayoutBlock* to_block,
    bool full_remove_insert) {
  LayoutBlockFlow* to_block_flow = ToLayoutBlockFlow(to_block);
  MoveAllChildrenTo(to_block_flow, full_remove_insert);

  // When a portion of the layout tree is being detached, anonymous blocks
  // will be combined as their children are deleted. In this process, the
  // anonymous block later in the tree is merged into the one preceding it.
  // It can happen that the later block (this) contains floats that the
  // previous block (toBlockFlow) did not contain, and thus are not in the
  // floating objects list for toBlockFlow. This can result in toBlockFlow
  // containing floats that are not in it's floating objects list, but are in
  // the floating objects lists of siblings and parents. This can cause problems
  // when the float itself is deleted, since the deletion code assumes that if a
  // float is not in it's containing block's floating objects list, it isn't in
  // any floating objects list. In order to preserve this condition (removing it
  // has serious performance implications), we need to copy the floating objects
  // from the old block (this) to the new block (toBlockFlow).
  // The float's metrics will likely all be wrong, but since toBlockFlow is
  // already marked for layout, this will get fixed before anything gets
  // displayed.
  // See bug https://code.google.com/p/chromium/issues/detail?id=230907
  if (floating_objects_) {
    if (!to_block_flow->floating_objects_)
      to_block_flow->CreateFloatingObjects();

    const FloatingObjectSet& from_floating_object_set =
        floating_objects_->Set();
    FloatingObjectSetIterator end = from_floating_object_set.end();

    for (FloatingObjectSetIterator it = from_floating_object_set.begin();
         it != end; ++it) {
      const FloatingObject& floating_object = *it->get();

      // Don't insert the object again if it's already in the list
      if (to_block_flow->ContainsFloat(floating_object.GetLayoutObject()))
        continue;

      to_block_flow->floating_objects_->Add(floating_object.UnsafeClone());
    }
  }
}

void LayoutBlockFlow::ChildBecameFloatingOrOutOfFlow(LayoutBox* child) {
  MakeChildrenInlineIfPossible();

  // Reparent the child to an adjacent anonymous block if one is available.
  LayoutObject* prev = child->PreviousSibling();
  if (prev && prev->IsAnonymousBlock() && prev->IsLayoutBlockFlow()) {
    LayoutBlockFlow* new_container = ToLayoutBlockFlow(prev);
    MoveChildTo(new_container, child, nullptr, false);
    // The anonymous block we've moved to may now be adjacent to former siblings
    // of ours that it can contain also.
    new_container->ReparentSubsequentFloatingOrOutOfFlowSiblings();
    return;
  }
  LayoutObject* next = child->NextSibling();
  if (next && next->IsAnonymousBlock() && next->IsLayoutBlockFlow()) {
    LayoutBlockFlow* new_container = ToLayoutBlockFlow(next);
    MoveChildTo(new_container, child, new_container->FirstChild(), false);
  }
}

void LayoutBlockFlow::CollapseAnonymousBlockChild(LayoutBlockFlow* child) {
  // It's possible that this block's destruction may have been triggered by the
  // child's removal. Just bail if the anonymous child block is already being
  // destroyed. See crbug.com/282088
  if (child->BeingDestroyed())
    return;
  if (child->Continuation())
    return;
  // Ruby elements use anonymous wrappers for ruby runs and ruby bases by
  // design, so we don't remove them.
  if (child->IsRubyRun() || child->IsRubyBase())
    return;
  SetNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(
      LayoutInvalidationReason::kChildAnonymousBlockChanged);

  child->MoveAllChildrenTo(this, child->NextSibling(), child->HasLayer());
  // If we make an object's children inline we are going to frustrate any future
  // attempts to remove floats from its children's float-lists before the next
  // layout happens so clear down all the floatlists now - they will be rebuilt
  // at layout.
  if (child->ChildrenInline())
    RemoveFloatingObjectsFromDescendants();
  SetChildrenInline(child->ChildrenInline());

  Children()->RemoveChildNode(this, child, child->HasLayer());
  child->Destroy();
}

bool LayoutBlockFlow::MergeSiblingContiguousAnonymousBlock(
    LayoutBlockFlow* sibling_that_may_be_deleted) {
  // Note: |this| and |siblingThatMayBeDeleted| may not be adjacent siblings at
  // this point. There may be an object between them which is about to be
  // removed.

  if (!IsMergeableAnonymousBlock(this) ||
      !IsMergeableAnonymousBlock(sibling_that_may_be_deleted))
    return false;

  SetNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(
      LayoutInvalidationReason::kAnonymousBlockChange);

  // If the inlineness of children of the two block don't match, we'd need
  // special code here (but there should be no need for it).
  DCHECK_EQ(sibling_that_may_be_deleted->ChildrenInline(), ChildrenInline());
  // Take all the children out of the |next| block and put them in
  // the |prev| block.
  sibling_that_may_be_deleted->MoveAllChildrenIncludingFloatsTo(
      this, sibling_that_may_be_deleted->HasLayer() || HasLayer());
  // Delete the now-empty block's lines and nuke it.
  sibling_that_may_be_deleted->DeleteLineBoxTree();
  sibling_that_may_be_deleted->Destroy();
  return true;
}

void LayoutBlockFlow::ReparentSubsequentFloatingOrOutOfFlowSiblings() {
  if (!Parent() || !Parent()->IsLayoutBlockFlow())
    return;
  if (BeingDestroyed() || DocumentBeingDestroyed())
    return;
  LayoutBlockFlow* parent_block_flow = ToLayoutBlockFlow(Parent());
  LayoutObject* child = NextSibling();
  while (child && child->IsFloatingOrOutOfFlowPositioned()) {
    LayoutObject* sibling = child->NextSibling();
    parent_block_flow->MoveChildTo(this, child, nullptr, false);
    child = sibling;
  }

  if (LayoutObject* next = NextSibling()) {
    if (next->IsLayoutBlockFlow())
      MergeSiblingContiguousAnonymousBlock(ToLayoutBlockFlow(next));
  }
}

void LayoutBlockFlow::ReparentPrecedingFloatingOrOutOfFlowSiblings() {
  if (!Parent() || !Parent()->IsLayoutBlockFlow())
    return;
  if (BeingDestroyed() || DocumentBeingDestroyed())
    return;
  LayoutBlockFlow* parent_block_flow = ToLayoutBlockFlow(Parent());
  LayoutObject* child = PreviousSibling();
  while (child && child->IsFloatingOrOutOfFlowPositioned()) {
    LayoutObject* sibling = child->PreviousSibling();
    parent_block_flow->MoveChildTo(this, child, FirstChild(), false);
    child = sibling;
  }
}

void LayoutBlockFlow::MakeChildrenInlineIfPossible() {
  // Collapsing away anonymous wrappers isn't relevant for the children of
  // anonymous blocks, unless they are ruby bases.
  if (IsAnonymousBlock() && !IsRubyBase())
    return;

  Vector<LayoutBlockFlow*, 3> blocks_to_remove;
  for (LayoutObject* child = FirstChild(); child;
       child = child->NextSibling()) {
    if (child->IsFloating())
      continue;
    if (child->IsOutOfFlowPositioned())
      continue;

    // There are still block children in the container, so any anonymous
    // wrappers are still needed.
    if (!child->IsAnonymousBlock() || !child->IsLayoutBlockFlow())
      return;
    // If one of the children is being destroyed then it is unsafe to clean up
    // anonymous wrappers as the
    // entire branch may be being destroyed.
    if (ToLayoutBlockFlow(child)->BeingDestroyed())
      return;
    // We can't remove anonymous wrappers if they contain continuations as this
    // means there are block children present.
    if (ToLayoutBlockFlow(child)->Continuation())
      return;
    // We are only interested in removing anonymous wrappers if there are inline
    // siblings underneath them.
    if (!child->ChildrenInline())
      return;
    // Ruby elements use anonymous wrappers for ruby runs and ruby bases by
    // design, so we don't remove them.
    if (child->IsRubyRun() || child->IsRubyBase())
      return;

    blocks_to_remove.push_back(ToLayoutBlockFlow(child));
  }

  // If we make an object's children inline we are going to frustrate any future
  // attempts to remove floats from its children's float-lists before the next
  // layout happens so clear down all the floatlists now - they will be rebuilt
  // at layout.
  RemoveFloatingObjectsFromDescendants();

  for (size_t i = 0; i < blocks_to_remove.size(); i++)
    CollapseAnonymousBlockChild(blocks_to_remove[i]);
  SetChildrenInline(true);
}

static void GetInlineRun(LayoutObject* start,
                         LayoutObject* boundary,
                         LayoutObject*& inline_run_start,
                         LayoutObject*& inline_run_end) {
  // Beginning at |start| we find the largest contiguous run of inlines that
  // we can.  We denote the run with start and end points, |inlineRunStart|
  // and |inlineRunEnd|.  Note that these two values may be the same if
  // we encounter only one inline.
  //
  // We skip any non-inlines we encounter as long as we haven't found any
  // inlines yet.
  //
  // |boundary| indicates a non-inclusive boundary point.  Regardless of whether
  // |boundary| is inline or not, we will not include it in a run with inlines
  // before it. It's as though we encountered a non-inline.

  // Start by skipping as many non-inlines as we can.
  LayoutObject* curr = start;
  bool saw_inline;
  do {
    while (curr &&
           !(curr->IsInline() || curr->IsFloatingOrOutOfFlowPositioned()))
      curr = curr->NextSibling();

    inline_run_start = inline_run_end = curr;

    if (!curr)
      return;  // No more inline children to be found.

    saw_inline = curr->IsInline();

    curr = curr->NextSibling();
    while (curr &&
           (curr->IsInline() || curr->IsFloatingOrOutOfFlowPositioned()) &&
           (curr != boundary)) {
      inline_run_end = curr;
      if (curr->IsInline())
        saw_inline = true;
      curr = curr->NextSibling();
    }
  } while (!saw_inline);
}

void LayoutBlockFlow::MakeChildrenNonInline(LayoutObject* insertion_point) {
  // makeChildrenNonInline takes a block whose children are *all* inline and it
  // makes sure that inline children are coalesced under anonymous blocks.
  // If |insertionPoint| is defined, then it represents the insertion point for
  // the new block child that is causing us to have to wrap all the inlines.
  // This means that we cannot coalesce inlines before |insertionPoint| with
  // inlines following |insertionPoint|, because the new child is going to be
  // inserted in between the inlines, splitting them.
  DCHECK(!IsInline() || IsAtomicInlineLevel());
  DCHECK(!insertion_point || insertion_point->Parent() == this);

  SetChildrenInline(false);

  LayoutObject* child = FirstChild();
  if (!child)
    return;

  DeleteLineBoxTree();

  while (child) {
    LayoutObject* inline_run_start;
    LayoutObject* inline_run_end;
    GetInlineRun(child, insertion_point, inline_run_start, inline_run_end);

    if (!inline_run_start)
      break;

    child = inline_run_end->NextSibling();

    LayoutBlock* block = CreateAnonymousBlock();
    Children()->InsertChildNode(this, block, inline_run_start);
    MoveChildrenTo(block, inline_run_start, child);
  }

#if DCHECK_IS_ON()
  for (LayoutObject* c = FirstChild(); c; c = c->NextSibling())
    DCHECK(!c->IsInline());
#endif

  SetShouldDoFullPaintInvalidation();
}

void LayoutBlockFlow::ChildBecameNonInline(LayoutObject*) {
  MakeChildrenNonInline();
  if (IsAnonymousBlock() && Parent() && Parent()->IsLayoutBlock())
    ToLayoutBlock(Parent())->RemoveLeftoverAnonymousBlock(this);
  // |this| may be dead here
}

void LayoutBlockFlow::ClearFloats(EClear clear) {
  PlaceNewFloats(LogicalHeight());
  // set y position
  LayoutUnit new_y = LowestFloatLogicalBottom(clear);
  if (Size().Height() < new_y)
    SetLogicalHeight(new_y);
}

bool LayoutBlockFlow::ContainsFloat(LayoutBox* layout_box) const {
  return floating_objects_ &&
         floating_objects_->Set().Contains<FloatingObjectHashTranslator>(
             layout_box);
}

void LayoutBlockFlow::RemoveFloatingObjects() {
  if (!floating_objects_)
    return;

  MarkSiblingsWithFloatsForLayout();

  floating_objects_->Clear();
}

LayoutPoint LayoutBlockFlow::FlipFloatForWritingModeForChild(
    const FloatingObject& child,
    const LayoutPoint& point) const {
  if (!Style()->IsFlippedBlocksWritingMode())
    return point;

  // This is similar to LayoutBox::flipForWritingModeForChild. We have to
  // subtract out our left offsets twice, since it's going to get added back in.
  // We hide this complication here so that the calling code looks normal for
  // the unflipped case.
  return LayoutPoint(point.X() + Size().Width() -
                         child.GetLayoutObject()->Size().Width() -
                         2 * XPositionForFloatIncludingMargin(child),
                     point.Y());
}

LayoutUnit LayoutBlockFlow::LogicalLeftOffsetForPositioningFloat(
    LayoutUnit logical_top,
    LayoutUnit fixed_offset,
    LayoutUnit* height_remaining) const {
  LayoutUnit offset = fixed_offset;
  if (floating_objects_ && floating_objects_->HasLeftObjects())
    offset = floating_objects_->LogicalLeftOffsetForPositioningFloat(
        fixed_offset, logical_top, height_remaining);
  return AdjustLogicalLeftOffsetForLine(offset, kDoNotIndentText);
}

LayoutUnit LayoutBlockFlow::LogicalRightOffsetForPositioningFloat(
    LayoutUnit logical_top,
    LayoutUnit fixed_offset,
    LayoutUnit* height_remaining) const {
  LayoutUnit offset = fixed_offset;
  if (floating_objects_ && floating_objects_->HasRightObjects())
    offset = floating_objects_->LogicalRightOffsetForPositioningFloat(
        fixed_offset, logical_top, height_remaining);
  return AdjustLogicalRightOffsetForLine(offset, kDoNotIndentText);
}

LayoutUnit LayoutBlockFlow::AdjustLogicalLeftOffsetForLine(
    LayoutUnit offset_from_floats,
    IndentTextOrNot apply_text_indent) const {
  LayoutUnit left = offset_from_floats;

  if (apply_text_indent == kIndentText && Style()->IsLeftToRightDirection())
    left += TextIndentOffset();

  return left;
}

LayoutUnit LayoutBlockFlow::AdjustLogicalRightOffsetForLine(
    LayoutUnit offset_from_floats,
    IndentTextOrNot apply_text_indent) const {
  LayoutUnit right = offset_from_floats;

  if (apply_text_indent == kIndentText && !Style()->IsLeftToRightDirection())
    right -= TextIndentOffset();

  return right;
}

LayoutPoint LayoutBlockFlow::ComputeLogicalLocationForFloat(
    const FloatingObject& floating_object,
    LayoutUnit logical_top_offset) const {
  LayoutBox* child_box = floating_object.GetLayoutObject();
  LayoutUnit logical_left_offset =
      LogicalLeftOffsetForContent();  // Constant part of left offset.
  LayoutUnit logical_right_offset;    // Constant part of right offset.
  logical_right_offset = LogicalRightOffsetForContent();

  LayoutUnit float_logical_width = std::min(
      LogicalWidthForFloat(floating_object),
      logical_right_offset - logical_left_offset);  // The width we look for.

  LayoutUnit float_logical_left;

  if (child_box->Style()->Floating() == EFloat::kLeft) {
    LayoutUnit height_remaining_left = LayoutUnit(1);
    LayoutUnit height_remaining_right = LayoutUnit(1);
    float_logical_left = LogicalLeftOffsetForPositioningFloat(
        logical_top_offset, logical_left_offset, &height_remaining_left);
    while (LogicalRightOffsetForPositioningFloat(logical_top_offset,
                                                 logical_right_offset,
                                                 &height_remaining_right) -
               float_logical_left <
           float_logical_width) {
      logical_top_offset +=
          std::min<LayoutUnit>(height_remaining_left, height_remaining_right);
      float_logical_left = LogicalLeftOffsetForPositioningFloat(
          logical_top_offset, logical_left_offset, &height_remaining_left);
    }
    float_logical_left =
        std::max(logical_left_offset - BorderAndPaddingLogicalLeft(),
                 float_logical_left);
  } else {
    LayoutUnit height_remaining_left = LayoutUnit(1);
    LayoutUnit height_remaining_right = LayoutUnit(1);
    float_logical_left = LogicalRightOffsetForPositioningFloat(
        logical_top_offset, logical_right_offset, &height_remaining_right);
    while (float_logical_left - LogicalLeftOffsetForPositioningFloat(
                                    logical_top_offset, logical_left_offset,
                                    &height_remaining_left) <
           float_logical_width) {
      logical_top_offset +=
          std::min(height_remaining_left, height_remaining_right);
      float_logical_left = LogicalRightOffsetForPositioningFloat(
          logical_top_offset, logical_right_offset, &height_remaining_right);
    }
    // Use the original width of the float here, since the local variable
    // |floatLogicalWidth| was capped to the available line width. See
    // fast/block/float/clamped-right-float.html.
    float_logical_left -= LogicalWidthForFloat(floating_object);
  }

  return LayoutPoint(float_logical_left, logical_top_offset);
}

FloatingObject* LayoutBlockFlow::InsertFloatingObject(LayoutBox& float_box) {
  DCHECK(float_box.IsFloating());

  // Create the list of special objects if we don't aleady have one
  if (!floating_objects_) {
    CreateFloatingObjects();
  } else {
    // Don't insert the object again if it's already in the list
    const FloatingObjectSet& floating_object_set = floating_objects_->Set();
    FloatingObjectSetIterator it =
        floating_object_set.Find<FloatingObjectHashTranslator>(&float_box);
    if (it != floating_object_set.end())
      return it->get();
  }

  // Create the special object entry & append it to the list

  std::unique_ptr<FloatingObject> new_obj = FloatingObject::Create(&float_box);
  return floating_objects_->Add(std::move(new_obj));
}

void LayoutBlockFlow::RemoveFloatingObject(LayoutBox* float_box) {
  if (floating_objects_) {
    const FloatingObjectSet& floating_object_set = floating_objects_->Set();
    FloatingObjectSetIterator it =
        floating_object_set.Find<FloatingObjectHashTranslator>(float_box);
    if (it != floating_object_set.end()) {
      FloatingObject& floating_object = *it->get();
      if (ChildrenInline()) {
        LayoutUnit logical_top = LogicalTopForFloat(floating_object);
        LayoutUnit logical_bottom = LogicalBottomForFloat(floating_object);

        // Fix for https://bugs.webkit.org/show_bug.cgi?id=54995.
        if (logical_bottom < 0 || logical_bottom < logical_top ||
            logical_top == LayoutUnit::Max()) {
          logical_bottom = LayoutUnit::Max();
        } else {
          // Special-case zero- and less-than-zero-height floats: those don't
          // touch the line that they're on, but it still needs to be dirtied.
          // This is accomplished by pretending they have a height of 1.
          logical_bottom = std::max(logical_bottom, logical_top + 1);
        }
        if (floating_object.OriginatingLine()) {
          if (!SelfNeedsLayout()) {
            DCHECK(
                floating_object.OriginatingLine()->GetLineLayoutItem().IsEqual(
                    this));
            floating_object.OriginatingLine()->MarkDirty();
          }
#if DCHECK_IS_ON()
          floating_object.SetOriginatingLine(nullptr);
#endif
        }
        MarkLinesDirtyInBlockRange(LayoutUnit(), logical_bottom);
      }
      floating_objects_->Remove(&floating_object);
    }
  }
}

void LayoutBlockFlow::RemoveFloatingObjectsBelow(FloatingObject* last_float,
                                                 LayoutUnit logical_offset) {
  if (!ContainsFloats())
    return;

  const FloatingObjectSet& floating_object_set = floating_objects_->Set();
  FloatingObject* curr = floating_object_set.back().get();
  while (curr != last_float &&
         (!curr->IsPlaced() || LogicalTopForFloat(*curr) >= logical_offset)) {
    floating_objects_->Remove(curr);
    if (floating_object_set.IsEmpty())
      break;
    curr = floating_object_set.back().get();
  }
}

bool LayoutBlockFlow::PlaceNewFloats(LayoutUnit logical_top_margin_edge,
                                     LineWidth* width) {
  if (!floating_objects_)
    return false;

  const FloatingObjectSet& floating_object_set = floating_objects_->Set();
  if (floating_object_set.IsEmpty())
    return false;

  // If all floats have already been positioned, then we have no work to do.
  if (floating_object_set.back()->IsPlaced())
    return false;

  // Move backwards through our floating object list until we find a float that
  // has already been positioned. Then we'll be able to move forward,
  // positioning all of the new floats that need it.
  FloatingObjectSetIterator it = floating_object_set.end();
  --it;  // Go to last item.
  FloatingObjectSetIterator begin = floating_object_set.begin();
  FloatingObject* last_placed_floating_object = nullptr;
  while (it != begin) {
    --it;
    if ((*it)->IsPlaced()) {
      last_placed_floating_object = it->get();
      ++it;
      break;
    }
  }

  // The float cannot start above the top position of the last positioned float.
  if (last_placed_floating_object) {
    logical_top_margin_edge =
        std::max(logical_top_margin_edge,
                 LogicalTopForFloat(*last_placed_floating_object));
  }

  FloatingObjectSetIterator end = floating_object_set.end();
  // Now walk through the set of unpositioned floats and place them.
  for (; it != end; ++it) {
    FloatingObject& floating_object = *it->get();
    // The containing block is responsible for positioning floats, so if we have
    // unplaced floats in our list that come from somewhere else, we have a bug.
    DCHECK_EQ(floating_object.GetLayoutObject()->ContainingBlock(), this);

    logical_top_margin_edge =
        PositionAndLayoutFloat(floating_object, logical_top_margin_edge);

    floating_objects_->AddPlacedObject(floating_object);

    if (width)
      width->ShrinkAvailableWidthForNewFloatIfNeeded(floating_object);
  }
  return true;
}

LayoutUnit LayoutBlockFlow::PositionAndLayoutFloat(
    FloatingObject& floating_object,
    LayoutUnit logical_top_margin_edge) {
  // Once a float has been placed, we cannot update its position, or the float
  // interval tree will be out of sync with reality. This may in turn lead to
  // objects being used after they have been deleted.
  CHECK(!floating_object.IsPlaced());

  LayoutBox& child = *floating_object.GetLayoutObject();

  // FIXME Investigate if this can be removed. crbug.com/370006
  child.SetMayNeedPaintInvalidation();

  logical_top_margin_edge =
      std::max(logical_top_margin_edge,
               LowestFloatLogicalBottom(child.Style()->Clear()));

  bool is_paginated = View()->GetLayoutState()->IsPaginated();
  if (is_paginated && !ChildrenInline()) {
    // Forced breaks are inserted at class A break points. Floats may be
    // affected by a break-after value on the previous in-flow sibling.
    if (LayoutBox* previous_in_flow_box = child.PreviousInFlowSiblingBox()) {
      logical_top_margin_edge = ApplyForcedBreak(
          logical_top_margin_edge, previous_in_flow_box->BreakAfter());
    }
  }

  LayoutUnit old_logical_top = child.LogicalTop();
  if (child.NeedsLayout()) {
    if (is_paginated) {
      // Before we can lay out the float, we need to estimate a position for
      // it. In order to do that, we first need to know its block start margin.
      child.ComputeAndSetBlockDirectionMargins(this);
      LayoutUnit margin_before = MarginBeforeForChild(child);

      // We have found the highest possible position for the float, so we'll
      // lay out right there. Later on, we may be pushed further down by
      // adjacent floats which we don't fit beside, or pushed by fragmentation
      // if we need to break before the top margin edge of the float.
      SetLogicalTopForChild(child, logical_top_margin_edge + margin_before);
      child.UpdateLayout();

      // May need to push the float to the next fragmentainer before attempting
      // to place it.
      logical_top_margin_edge =
          AdjustFloatLogicalTopForPagination(child, logical_top_margin_edge);
    } else {
      child.UpdateLayout();
    }
  }

  LayoutUnit margin_start = MarginStartForChild(child);
  LayoutUnit margin_end = MarginEndForChild(child);
  SetLogicalWidthForFloat(
      floating_object, LogicalWidthForChild(child) + margin_start + margin_end);

  // We have determined the logical width of the float. This is enough
  // information to fit it among other floats according to float positioning
  // rules. Note that logical *height* doesn't really matter yet (until we're
  // going to place subsequent floats or other objects that are affected by
  // floats), since no float may be positioned above the outer logical top edge
  // of any other earlier float in the block formatting context.
  LayoutUnit margin_before = MarginBeforeForChild(child);
  LayoutUnit margin_after = MarginAfterForChild(child);
  LayoutPoint float_logical_location =
      ComputeLogicalLocationForFloat(floating_object, logical_top_margin_edge);
  logical_top_margin_edge = float_logical_location.Y();
  SetLogicalTopForChild(child, logical_top_margin_edge + margin_before);

  SubtreeLayoutScope layout_scope(child);

  // A new position may mean that we need to insert, move or remove breaks
  // inside the float. We may also need to lay out if we just ceased to be
  // fragmented, in order to remove pagination struts inside the child.
  MarkChildForPaginationRelayoutIfNeeded(child, layout_scope);
  child.LayoutIfNeeded();

  // If negative margin pushes the child completely out of its old position
  // mark for layout siblings that may have it in its float lists.
  if (child.LogicalBottom() <= old_logical_top) {
    LayoutObject* next = child.NextSibling();
    if (next && next->IsLayoutBlockFlow()) {
      LayoutBlockFlow* nextBlock = ToLayoutBlockFlow(next);
      if (!nextBlock->AvoidsFloats() || nextBlock->ShrinkToAvoidFloats())
        nextBlock->MarkAllDescendantsWithFloatsForLayout();
    }
  }

  if (is_paginated) {
    PaginatedContentWasLaidOut(child.LogicalBottom());

    // We may have to insert a break before the float.
    LayoutUnit new_logical_top_margin_edge =
        AdjustFloatLogicalTopForPagination(child, logical_top_margin_edge);
    if (logical_top_margin_edge != new_logical_top_margin_edge) {
      // We had already found a location for the float, but a soft
      // fragmentainer break then made us push it further down. This may affect
      // the inline position of the float (since we may no longer be beside the
      // same floats anymore). Block position will remain unaffected, though.
      float_logical_location = ComputeLogicalLocationForFloat(
          floating_object, new_logical_top_margin_edge);
      DCHECK_EQ(float_logical_location.Y(), new_logical_top_margin_edge);
      logical_top_margin_edge = new_logical_top_margin_edge;

      SetLogicalTopForChild(child, logical_top_margin_edge + margin_before);

      // Pushing the child to the next fragmentainer most likely means that we
      // need to recalculate pagination struts inside it.
      if (child.IsLayoutBlock())
        child.SetChildNeedsLayout(kMarkOnlyThis);
      child.LayoutIfNeeded();
      PaginatedContentWasLaidOut(child.LogicalBottom());
    }
  }

  LayoutUnit child_logical_left_margin =
      Style()->IsLeftToRightDirection() ? margin_start : margin_end;
  SetLogicalLeftForChild(
      child, float_logical_location.X() + child_logical_left_margin);
  SetLogicalLeftForFloat(floating_object, float_logical_location.X());
  SetLogicalTopForFloat(floating_object, logical_top_margin_edge);
  SetLogicalHeightForFloat(floating_object, LogicalHeightForChild(child) +
                                                margin_before + margin_after);

  if (ShapeOutsideInfo* shape_outside = child.GetShapeOutsideInfo())
    shape_outside->SetReferenceBoxLogicalSize(LogicalSizeForChild(child));

  return logical_top_margin_edge;
}

bool LayoutBlockFlow::HasOverhangingFloat(LayoutBox* layout_box) {
  if (!floating_objects_ || !Parent())
    return false;

  const FloatingObjectSet& floating_object_set = floating_objects_->Set();
  FloatingObjectSetIterator it =
      floating_object_set.Find<FloatingObjectHashTranslator>(layout_box);
  if (it == floating_object_set.end())
    return false;

  return IsOverhangingFloat(**it);
}

void LayoutBlockFlow::AddIntrudingFloats(LayoutBlockFlow* prev,
                                         LayoutUnit logical_left_offset,
                                         LayoutUnit logical_top_offset) {
  DCHECK(!AvoidsFloats());

  // If we create our own block formatting context then our contents don't
  // interact with floats outside it, even those from our parent.
  if (CreatesNewFormattingContext())
    return;

  // If the parent or previous sibling doesn't have any floats to add, don't
  // bother.
  if (!prev->floating_objects_)
    return;

  logical_left_offset += MarginLogicalLeft();

  const FloatingObjectSet& prev_set = prev->floating_objects_->Set();
  FloatingObjectSetIterator prev_end = prev_set.end();
  for (FloatingObjectSetIterator prev_it = prev_set.begin();
       prev_it != prev_end; ++prev_it) {
    FloatingObject& floating_object = *prev_it->get();
    if (LogicalBottomForFloat(floating_object) > logical_top_offset) {
      if (!floating_objects_ ||
          !floating_objects_->Set().Contains(&floating_object)) {
        // We create the floating object list lazily.
        if (!floating_objects_)
          CreateFloatingObjects();

        // Applying the child's margin makes no sense in the case where the
        // child was passed in since this margin was added already through the
        // modification of the |logicalLeftOffset| variable above.
        // |logicalLeftOffset| will equal the margin in this case, so it's
        // already been taken into account. Only apply this code if prev is the
        // parent, since otherwise the left margin will get applied twice.
        LayoutSize offset =
            IsHorizontalWritingMode()
                ? LayoutSize(logical_left_offset - (prev != Parent()
                                                        ? prev->MarginLeft()
                                                        : LayoutUnit()),
                             logical_top_offset)
                : LayoutSize(logical_top_offset,
                             logical_left_offset - (prev != Parent()
                                                        ? prev->MarginTop()
                                                        : LayoutUnit()));

        floating_objects_->Add(floating_object.CopyToNewContainer(offset));
      }
    }
  }
}

void LayoutBlockFlow::AddOverhangingFloats(LayoutBlockFlow* child,
                                           bool make_child_paint_other_floats) {
  // Prevent floats from being added to the canvas by the root element, e.g.,
  // <html>.
  if (!child->ContainsFloats() || child->CreatesNewFormattingContext())
    return;

  LayoutUnit child_logical_top = child->LogicalTop();
  LayoutUnit child_logical_left = child->LogicalLeft();

  // Floats that will remain the child's responsibility to paint should factor
  // into its overflow.
  FloatingObjectSetIterator child_end = child->floating_objects_->Set().end();
  for (FloatingObjectSetIterator child_it =
           child->floating_objects_->Set().begin();
       child_it != child_end; ++child_it) {
    FloatingObject& floating_object = *child_it->get();
    LayoutUnit logical_bottom_for_float =
        std::min(this->LogicalBottomForFloat(floating_object),
                 LayoutUnit::Max() - child_logical_top);
    LayoutUnit logical_bottom = child_logical_top + logical_bottom_for_float;

    if (logical_bottom > LogicalHeight()) {
      // If the object is not in the list, we add it now.
      if (!ContainsFloat(floating_object.GetLayoutObject())) {
        LayoutSize offset =
            IsHorizontalWritingMode()
                ? LayoutSize(-child_logical_left, -child_logical_top)
                : LayoutSize(-child_logical_top, -child_logical_left);
        bool should_paint = false;

        // The nearest enclosing layer always paints the float (so that zindex
        // and stacking behaves properly). We always want to propagate the
        // desire to paint the float as far out as we can, to the outermost
        // block that overlaps the float, stopping only if we hit a
        // self-painting layer boundary.
        if (floating_object.GetLayoutObject()->EnclosingFloatPaintingLayer() ==
                EnclosingFloatPaintingLayer() &&
            !floating_object.IsLowestNonOverhangingFloatInChild()) {
          floating_object.SetShouldPaint(false);
          should_paint = true;
        }
        // We create the floating object list lazily.
        if (!floating_objects_)
          CreateFloatingObjects();

        floating_objects_->Add(
            floating_object.CopyToNewContainer(offset, should_paint, true));
      }
    } else {
      if (make_child_paint_other_floats && !floating_object.ShouldPaint() &&
          !floating_object.GetLayoutObject()->HasSelfPaintingLayer() &&
          !floating_object.IsLowestNonOverhangingFloatInChild() &&
          floating_object.GetLayoutObject()->IsDescendantOf(child) &&
          floating_object.GetLayoutObject()->EnclosingFloatPaintingLayer() ==
              child->EnclosingFloatPaintingLayer()) {
        // The float is not overhanging from this block, so if it is a
        // descendant of the child, the child should paint it (the other case is
        // that it is intruding into the child), unless it has its own layer or
        // enclosing layer.
        // If makeChildPaintOtherFloats is false, it means that the child must
        // already know about all the floats it should paint.
        floating_object.SetShouldPaint(true);
      }

      // Since the float doesn't overhang, it didn't get put into our list. We
      // need to go ahead and add its overflow in to the child now.
      if (floating_object.IsDescendant())
        child->AddOverflowFromChild(
            *floating_object.GetLayoutObject(),
            LayoutSize(XPositionForFloatIncludingMargin(floating_object),
                       YPositionForFloatIncludingMargin(floating_object)));
    }
  }
}

LayoutUnit LayoutBlockFlow::LowestFloatLogicalBottom(EClear clear) const {
  if (clear == EClear::kNone || !floating_objects_)
    return LayoutUnit();

  FloatingObject::Type float_type = clear == EClear::kLeft
                                        ? FloatingObject::kFloatLeft
                                        : clear == EClear::kRight
                                              ? FloatingObject::kFloatRight
                                              : FloatingObject::kFloatLeftRight;
  return floating_objects_->LowestFloatLogicalBottom(float_type);
}

LayoutUnit LayoutBlockFlow::NextFloatLogicalBottomBelow(
    LayoutUnit logical_height) const {
  if (!floating_objects_)
    return logical_height;
  return floating_objects_->FindNextFloatLogicalBottomBelow(logical_height);
}

LayoutUnit LayoutBlockFlow::NextFloatLogicalBottomBelowForBlock(
    LayoutUnit logical_height) const {
  if (!floating_objects_)
    return logical_height;

  return floating_objects_->FindNextFloatLogicalBottomBelowForBlock(
      logical_height);
}

LayoutUnit LayoutBlockFlow::LogicalHeightWithVisibleOverflow() const {
  LayoutUnit logical_height = LayoutBlock::LogicalHeightWithVisibleOverflow();
  return std::max(logical_height, LowestFloatLogicalBottom());
}

Node* LayoutBlockFlow::NodeForHitTest() const {
  // If we are in the margins of block elements that are part of a
  // continuation we're actually still inside the enclosing element
  // that was split. Use the appropriate inner node.
  return IsAnonymousBlockContinuation() ? Continuation()->GetNode() : GetNode();
}

bool LayoutBlockFlow::HitTestChildren(
    HitTestResult& result,
    const HitTestLocation& location_in_container,
    const LayoutPoint& accumulated_offset,
    HitTestAction hit_test_action) {
  LayoutPoint scrolled_offset(HasOverflowClip()
                                  ? accumulated_offset - ScrolledContentOffset()
                                  : accumulated_offset);

  if (hit_test_action == kHitTestFloat &&
      HitTestFloats(result, location_in_container, scrolled_offset))
    return true;

  if (ChildrenInline()) {
    if (line_boxes_.HitTest(LineLayoutBoxModel(this), result,
                            location_in_container, scrolled_offset,
                            hit_test_action)) {
      UpdateHitTestResult(
          result, FlipForWritingMode(ToLayoutPoint(
                      location_in_container.Point() - accumulated_offset)));
      return true;
    }
  } else if (LayoutBlock::HitTestChildren(result, location_in_container,
                                          accumulated_offset,
                                          hit_test_action)) {
    return true;
  }

  return false;
}

bool LayoutBlockFlow::HitTestFloats(
    HitTestResult& result,
    const HitTestLocation& location_in_container,
    const LayoutPoint& accumulated_offset) {
  if (!floating_objects_)
    return false;

  LayoutPoint adjusted_location = accumulated_offset;
  if (IsLayoutView()) {
    ScrollOffset offset = ToLayoutView(this)->GetFrameView()->GetScrollOffset();
    adjusted_location.Move(LayoutSize(offset));
  }

  const FloatingObjectSet& floating_object_set = floating_objects_->Set();
  FloatingObjectSetIterator begin = floating_object_set.begin();
  for (FloatingObjectSetIterator it = floating_object_set.end(); it != begin;) {
    --it;
    const FloatingObject& floating_object = *it->get();
    if (floating_object.ShouldPaint() &&
        // TODO(wangxianzhu): Should this be a DCHECK?
        !floating_object.GetLayoutObject()->HasSelfPaintingLayer()) {
      LayoutUnit x_offset = XPositionForFloatIncludingMargin(floating_object) -
                            floating_object.GetLayoutObject()->Location().X();
      LayoutUnit y_offset = YPositionForFloatIncludingMargin(floating_object) -
                            floating_object.GetLayoutObject()->Location().Y();
      LayoutPoint child_point = FlipFloatForWritingModeForChild(
          floating_object, adjusted_location + LayoutSize(x_offset, y_offset));
      if (floating_object.GetLayoutObject()->HitTest(
              result, location_in_container, child_point)) {
        UpdateHitTestResult(
            result, location_in_container.Point() - ToLayoutSize(child_point));
        return true;
      }
    }
  }

  return false;
}

LayoutSize LayoutBlockFlow::AccumulateInFlowPositionOffsets() const {
  if (!IsAnonymousBlock() || !IsInFlowPositioned())
    return LayoutSize();
  LayoutSize offset;
  for (const LayoutObject* p = InlineElementContinuation();
       p && p->IsLayoutInline(); p = p->Parent()) {
    if (p->IsInFlowPositioned())
      offset += ToLayoutInline(p)->OffsetForInFlowPosition();
  }
  return offset;
}

LayoutUnit LayoutBlockFlow::LogicalLeftFloatOffsetForLine(
    LayoutUnit logical_top,
    LayoutUnit fixed_offset,
    LayoutUnit logical_height) const {
  if (floating_objects_ && floating_objects_->HasLeftObjects())
    return floating_objects_->LogicalLeftOffset(fixed_offset, logical_top,
                                                logical_height);

  return fixed_offset;
}

LayoutUnit LayoutBlockFlow::LogicalRightFloatOffsetForLine(
    LayoutUnit logical_top,
    LayoutUnit fixed_offset,
    LayoutUnit logical_height) const {
  if (floating_objects_ && floating_objects_->HasRightObjects())
    return floating_objects_->LogicalRightOffset(fixed_offset, logical_top,
                                                 logical_height);

  return fixed_offset;
}

void LayoutBlockFlow::UpdateAncestorShouldPaintFloatingObject(
    const LayoutBox& float_box) {
  DCHECK(float_box.IsFloating());
  bool float_box_is_self_painting_layer =
      float_box.HasLayer() && float_box.Layer()->IsSelfPaintingLayer();
  for (LayoutObject* ancestor = float_box.Parent();
       ancestor && ancestor->IsLayoutBlockFlow();
       ancestor = ancestor->Parent()) {
    LayoutBlockFlow* ancestor_block = ToLayoutBlockFlow(ancestor);
    FloatingObjects* ancestor_floating_objects =
        ancestor_block->floating_objects_.get();
    if (!ancestor_floating_objects)
      break;
    FloatingObjectSet::iterator it =
        ancestor_floating_objects->MutableSet()
            .Find<FloatingObjectHashTranslator>(
                const_cast<LayoutBox*>(&float_box));
    if (it == ancestor_floating_objects->MutableSet().end())
      break;

    FloatingObject& floating_object = **it;
    if (!float_box_is_self_painting_layer) {
      // This repeats the logic in addOverhangingFloats() about shouldPaint
      // flag:
      // - The nearest enclosing block in which the float doesn't overhang
      //   paints the float;
      // - Or even if the float overhangs, if the ancestor block has
      //   self-painting layer, it paints the float.
      if (ancestor_block->HasSelfPaintingLayer() ||
          !ancestor_block->IsOverhangingFloat(floating_object)) {
        floating_object.SetShouldPaint(true);
        return;
      }
    } else {
      floating_object.SetShouldPaint(false);
    }
  }
}

bool LayoutBlockFlow::AllowsPaginationStrut() const {
  // The block needs to be contained by a LayoutBlockFlow (and not by e.g. a
  // flexbox, grid, or a table (the latter being the case for table cell or
  // table caption)). The reason for this limitation is simply that
  // LayoutBlockFlow child layout code is the only place where we pick up the
  // struts and handle them. We handle floats and regular in-flow children, and
  // that's all. We could handle this in other layout modes as well (and even
  // for out-of-flow children), but currently we don't.
  // TODO(mstensho): But we *should*.
  if (IsOutOfFlowPositioned())
    return false;
  if (IsLayoutFlowThread()) {
    // Don't let the strut escape the fragmentation context and get lost.
    // TODO(mstensho): If we're in a nested fragmentation context, we should
    // ideally convert and propagate the strut to the outer fragmentation
    // context, so that the inner one is fully pushed to the next outer
    // fragmentainer, instead of taking up unusable space in the previous one.
    // But currently we have no mechanism in place to handle this.
    return false;
  }
  const LayoutBlock* containing_block = this->ContainingBlock();
  if (!containing_block || !containing_block->IsLayoutBlockFlow())
    return false;
  const LayoutBlockFlow* containing_block_flow =
      ToLayoutBlockFlow(containing_block);
  // If children are inline, allow the strut. We are probably a float.
  if (containing_block_flow->ChildrenInline())
    return true;
  for (LayoutBox* sibling = PreviousSiblingBox(); sibling;
       sibling = sibling->PreviousSiblingBox()) {
    // What happens on the other side of a spanner is none of our concern, so
    // stop here. Since there's no in-flow box between the previous spanner and
    // us, there's no class A break point in front of us. We cannot even
    // re-propagate pagination struts to our containing block, since the
    // containing block starts in a different column row.
    if (sibling->IsColumnSpanAll())
      return false;
    // If this isn't the first in-flow object, there's a break opportunity
    // before us, which means that we can allow the strut.
    if (!sibling->IsFloatingOrOutOfFlowPositioned())
      return true;
  }
  // This is a first in-flow child. We'll still allow the strut if it can be
  // re-propagated to our containing block.
  return containing_block_flow->AllowsPaginationStrut();
}

void LayoutBlockFlow::SetPaginationStrutPropagatedFromChild(LayoutUnit strut) {
  strut = std::max(strut, LayoutUnit());
  if (!rare_data_) {
    if (!strut)
      return;
    rare_data_ = WTF::MakeUnique<LayoutBlockFlowRareData>(this);
  }
  rare_data_->pagination_strut_propagated_from_child_ = strut;
}

void LayoutBlockFlow::SetFirstForcedBreakOffset(LayoutUnit block_offset) {
  if (!rare_data_) {
    if (!block_offset)
      return;
    rare_data_ = WTF::MakeUnique<LayoutBlockFlowRareData>(this);
  }
  rare_data_->first_forced_break_offset_ = block_offset;
}

void LayoutBlockFlow::PositionSpannerDescendant(
    LayoutMultiColumnSpannerPlaceholder& child) {
  LayoutBox& spanner = *child.LayoutObjectInFlowThread();
  // FIXME: |spanner| is a descendant, but never a direct child, so the names
  // here are bad, if nothing else.
  SetLogicalTopForChild(spanner, child.LogicalTop());
  DetermineLogicalLeftPositionForChild(spanner);
}

bool LayoutBlockFlow::AvoidsFloats() const {
  // Floats can't intrude into our box if we have a non-auto column count or
  // width.
  // Note: we need to use LayoutBox::avoidsFloats here since
  // LayoutBlock::avoidsFloats is always true.
  return LayoutBox::AvoidsFloats() || !Style()->HasAutoColumnCount() ||
         !Style()->HasAutoColumnWidth();
}

void LayoutBlockFlow::MoveChildrenTo(LayoutBoxModelObject* to_box_model_object,
                                     LayoutObject* start_child,
                                     LayoutObject* end_child,
                                     LayoutObject* before_child,
                                     bool full_remove_insert) {
  if (ChildrenInline())
    DeleteLineBoxTree();
  LayoutBoxModelObject::MoveChildrenTo(to_box_model_object, start_child,
                                       end_child, before_child,
                                       full_remove_insert);
}

LayoutUnit LayoutBlockFlow::LogicalLeftSelectionOffset(
    const LayoutBlock* root_block,
    LayoutUnit position) const {
  LayoutUnit logical_left =
      LogicalLeftOffsetForLine(position, kDoNotIndentText);
  if (logical_left == LogicalLeftOffsetForContent())
    return LayoutBlock::LogicalLeftSelectionOffset(root_block, position);

  const LayoutBlock* cb = this;
  while (cb != root_block) {
    logical_left += cb->LogicalLeft();
    cb = cb->ContainingBlock();
  }
  return logical_left;
}

LayoutUnit LayoutBlockFlow::LogicalRightSelectionOffset(
    const LayoutBlock* root_block,
    LayoutUnit position) const {
  LayoutUnit logical_right =
      LogicalRightOffsetForLine(position, kDoNotIndentText);
  if (logical_right == LogicalRightOffsetForContent())
    return LayoutBlock::LogicalRightSelectionOffset(root_block, position);

  const LayoutBlock* cb = this;
  while (cb != root_block) {
    logical_right += cb->LogicalLeft();
    cb = cb->ContainingBlock();
  }
  return logical_right;
}

RootInlineBox* LayoutBlockFlow::CreateRootInlineBox() {
  return new RootInlineBox(LineLayoutItem(this));
}

bool LayoutBlockFlow::IsPagedOverflow(const ComputedStyle& style) {
  return style.IsOverflowPaged() &&
         GetNode() != GetDocument().ViewportDefiningElement();
}

LayoutBlockFlow::FlowThreadType LayoutBlockFlow::GetFlowThreadType(
    const ComputedStyle& style) {
  if (IsPagedOverflow(style))
    return kPagedFlowThread;
  if (style.SpecifiesColumns())
    return kMultiColumnFlowThread;
  return kNoFlowThread;
}

LayoutMultiColumnFlowThread* LayoutBlockFlow::CreateMultiColumnFlowThread(
    FlowThreadType type) {
  switch (type) {
    case kMultiColumnFlowThread:
      return LayoutMultiColumnFlowThread::CreateAnonymous(GetDocument(),
                                                          StyleRef());
    case kPagedFlowThread:
      // Paged overflow is currently done using the multicol implementation.
      UseCounter::Count(GetDocument(), UseCounter::kCSSOverflowPaged);
      return LayoutPagedFlowThread::CreateAnonymous(GetDocument(), StyleRef());
    default:
      NOTREACHED();
      return nullptr;
  }
}

void LayoutBlockFlow::CreateOrDestroyMultiColumnFlowThreadIfNeeded(
    const ComputedStyle* old_style) {
  // Paged overflow trumps multicol in this implementation. Ideally, it should
  // be possible to have both paged overflow and multicol on the same element,
  // but then we need two flow threads. Anyway, this is nothing to worry about
  // until we can actually nest multicol properly inside other fragmentation
  // contexts.
  FlowThreadType type = GetFlowThreadType(StyleRef());

  if (MultiColumnFlowThread()) {
    DCHECK(old_style);
    if (type != GetFlowThreadType(*old_style)) {
      // If we're no longer to be multicol/paged, destroy the flow thread. Also
      // destroy it when switching between multicol and paged, since that
      // affects the column set structure (multicol containers may have
      // spanners, paged containers may not).
      MultiColumnFlowThread()->EvacuateAndDestroy();
      DCHECK(!MultiColumnFlowThread());
      pagination_state_changed_ = true;
    }
  }

  if (type == kNoFlowThread || MultiColumnFlowThread())
    return;

  // Ruby elements manage child insertion in a special way, and would mess up
  // insertion of the flow thread. The flow thread needs to be a direct child of
  // the multicol block (|this|).
  if (IsRuby())
    return;

  // Fieldsets look for a legend special child (layoutSpecialExcludedChild()).
  // We currently only support one special child per layout object, and the
  // flow thread would make for a second one.
  if (IsFieldset())
    return;

  // Form controls are replaced content, and are therefore not supposed to
  // support multicol.
  if (IsFileUploadControl() || IsTextControl() || IsListBox())
    return;

  LayoutMultiColumnFlowThread* flow_thread = CreateMultiColumnFlowThread(type);
  AddChild(flow_thread);
  pagination_state_changed_ = true;

  // Check that addChild() put the flow thread as a direct child, and didn't do
  // fancy things.
  DCHECK_EQ(flow_thread->Parent(), this);

  flow_thread->Populate();
  LayoutBlockFlowRareData& rare_data = EnsureRareData();
  DCHECK(!rare_data.multi_column_flow_thread_);
  rare_data.multi_column_flow_thread_ = flow_thread;
}

LayoutBlockFlow::LayoutBlockFlowRareData& LayoutBlockFlow::EnsureRareData() {
  if (rare_data_)
    return *rare_data_;

  rare_data_ = WTF::MakeUnique<LayoutBlockFlowRareData>(this);
  return *rare_data_;
}

void LayoutBlockFlow::PositionDialog() {
  HTMLDialogElement* dialog = toHTMLDialogElement(GetNode());
  if (dialog->GetCenteringMode() == HTMLDialogElement::kNotCentered)
    return;

  bool can_center_dialog = (Style()->GetPosition() == EPosition::kAbsolute ||
                            Style()->GetPosition() == EPosition::kFixed) &&
                           Style()->HasAutoTopAndBottom();

  if (dialog->GetCenteringMode() == HTMLDialogElement::kCentered) {
    if (can_center_dialog)
      SetY(dialog->CenteredPosition());
    return;
  }

  DCHECK_EQ(dialog->GetCenteringMode(), HTMLDialogElement::kNeedsCentering);
  if (!can_center_dialog) {
    dialog->SetNotCentered();
    return;
  }

  FrameView* frame_view = GetDocument().View();
  LayoutUnit top = LayoutUnit((Style()->GetPosition() == EPosition::kFixed)
                                  ? 0
                                  : frame_view->ScrollOffsetInt().Height());
  int visible_height =
      frame_view->VisibleContentRect(kIncludeScrollbars).Height();
  if (Size().Height() < visible_height)
    top += (visible_height - Size().Height()) / 2;
  SetY(top);
  dialog->SetCentered(top);
}

void LayoutBlockFlow::SimplifiedNormalFlowInlineLayout() {
  DCHECK(ChildrenInline());
  ListHashSet<RootInlineBox*> line_boxes;
  for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.AtEnd();
       walker.Advance()) {
    LayoutObject* o = walker.Current().GetLayoutObject();
    if (!o->IsOutOfFlowPositioned() &&
        (o->IsAtomicInlineLevel() || o->IsFloating())) {
      o->LayoutIfNeeded();
      if (ToLayoutBox(o)->InlineBoxWrapper()) {
        RootInlineBox& box = ToLayoutBox(o)->InlineBoxWrapper()->Root();
        line_boxes.insert(&box);
      }
    } else if (o->IsText() ||
               (o->IsLayoutInline() && !walker.AtEndOfInline())) {
      o->ClearNeedsLayout();
    }
  }

  // FIXME: Glyph overflow will get lost in this case, but not really a big
  // deal.
  GlyphOverflowAndFallbackFontsMap text_box_data_map;
  for (ListHashSet<RootInlineBox*>::const_iterator it = line_boxes.begin();
       it != line_boxes.end(); ++it) {
    RootInlineBox* box = *it;
    box->ComputeOverflow(box->LineTop(), box->LineBottom(), text_box_data_map);
  }
}

bool LayoutBlockFlow::RecalcInlineChildrenOverflowAfterStyleChange() {
  DCHECK(ChildrenInline());
  bool children_overflow_changed = false;
  ListHashSet<RootInlineBox*> line_boxes;
  for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.AtEnd();
       walker.Advance()) {
    LayoutObject* layout_object = walker.Current().GetLayoutObject();
    if (RecalcNormalFlowChildOverflowIfNeeded(layout_object)) {
      children_overflow_changed = true;
      if (InlineBox* inline_box_wrapper =
              ToLayoutBlock(layout_object)->InlineBoxWrapper())
        line_boxes.insert(&inline_box_wrapper->Root());
    }
  }

  // FIXME: Glyph overflow will get lost in this case, but not really a big
  // deal.
  GlyphOverflowAndFallbackFontsMap text_box_data_map;
  for (ListHashSet<RootInlineBox*>::const_iterator it = line_boxes.begin();
       it != line_boxes.end(); ++it) {
    RootInlineBox* box = *it;
    box->ClearKnownToHaveNoOverflow();
    box->ComputeOverflow(box->LineTop(), box->LineBottom(), text_box_data_map);
  }
  return children_overflow_changed;
}

PositionWithAffinity LayoutBlockFlow::PositionForPoint(
    const LayoutPoint& point) {
  if (IsAtomicInlineLevel()) {
    PositionWithAffinity position =
        PositionForPointIfOutsideAtomicInlineLevel(point);
    if (!position.IsNull())
      return position;
  }
  if (!ChildrenInline())
    return LayoutBlock::PositionForPoint(point);

  LayoutPoint point_in_contents = point;
  OffsetForContents(point_in_contents);
  LayoutPoint point_in_logical_contents(point_in_contents);
  if (!IsHorizontalWritingMode())
    point_in_logical_contents = point_in_logical_contents.TransposedPoint();

  if (!FirstRootBox())
    return CreatePositionWithAffinity(0);

  bool lines_are_flipped = Style()->IsFlippedLinesWritingMode();
  bool blocks_are_flipped = Style()->IsFlippedBlocksWritingMode();

  // look for the closest line box in the root box which is at the passed-in y
  // coordinate
  InlineBox* closest_box = nullptr;
  RootInlineBox* first_root_box_with_children = nullptr;
  RootInlineBox* last_root_box_with_children = nullptr;
  for (RootInlineBox* root = FirstRootBox(); root; root = root->NextRootBox()) {
    if (!root->FirstLeafChild())
      continue;
    if (!first_root_box_with_children)
      first_root_box_with_children = root;

    if (!lines_are_flipped && root->IsFirstAfterPageBreak() &&
        (point_in_logical_contents.Y() < root->LineTopWithLeading() ||
         (blocks_are_flipped &&
          point_in_logical_contents.Y() == root->LineTopWithLeading())))
      break;

    last_root_box_with_children = root;

    // check if this root line box is located at this y coordinate
    if (point_in_logical_contents.Y() < root->SelectionBottom() ||
        (blocks_are_flipped &&
         point_in_logical_contents.Y() == root->SelectionBottom())) {
      if (lines_are_flipped) {
        RootInlineBox* next_root_box_with_children = root->NextRootBox();
        while (next_root_box_with_children &&
               !next_root_box_with_children->FirstLeafChild())
          next_root_box_with_children =
              next_root_box_with_children->NextRootBox();

        if (next_root_box_with_children &&
            next_root_box_with_children->IsFirstAfterPageBreak() &&
            (point_in_logical_contents.Y() >
                 next_root_box_with_children->LineTopWithLeading() ||
             (!blocks_are_flipped &&
              point_in_logical_contents.Y() ==
                  next_root_box_with_children->LineTopWithLeading())))
          continue;
      }
      closest_box = root->ClosestLeafChildForLogicalLeftPosition(
          point_in_logical_contents.X());
      if (closest_box)
        break;
    }
  }

  bool move_caret_to_boundary =
      GetDocument()
          .GetFrame()
          ->GetEditor()
          .Behavior()
          .ShouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom();

  if (!move_caret_to_boundary && !closest_box && last_root_box_with_children) {
    // y coordinate is below last root line box, pretend we hit it
    closest_box =
        last_root_box_with_children->ClosestLeafChildForLogicalLeftPosition(
            point_in_logical_contents.X());
  }

  if (closest_box) {
    if (move_caret_to_boundary) {
      LayoutUnit first_root_box_with_children_top =
          std::min<LayoutUnit>(first_root_box_with_children->SelectionTop(),
                               first_root_box_with_children->LogicalTop());
      if (point_in_logical_contents.Y() < first_root_box_with_children_top ||
          (blocks_are_flipped &&
           point_in_logical_contents.Y() == first_root_box_with_children_top)) {
        InlineBox* box = first_root_box_with_children->FirstLeafChild();
        if (box->IsLineBreak()) {
          if (InlineBox* new_box = box->NextLeafChildIgnoringLineBreak())
            box = new_box;
        }
        // y coordinate is above first root line box, so return the start of the
        // first
        return PositionWithAffinity(PositionForBox(box, true));
      }
    }

    // pass the box a top position that is inside it
    LayoutPoint point(point_in_logical_contents.X(),
                      closest_box->Root().BlockDirectionPointInLine());
    if (!IsHorizontalWritingMode())
      point = point.TransposedPoint();
    if (closest_box->GetLineLayoutItem().IsAtomicInlineLevel())
      return PositionForPointRespectingEditingBoundaries(
          LineLayoutBox(closest_box->GetLineLayoutItem()), point);
    return closest_box->GetLineLayoutItem().PositionForPoint(point);
  }

  if (last_root_box_with_children) {
    // We hit this case for Mac behavior when the Y coordinate is below the last
    // box.
    DCHECK(move_caret_to_boundary);
    InlineBox* logically_last_box;
    if (last_root_box_with_children->GetLogicalEndBoxWithNode(
            logically_last_box))
      return PositionWithAffinity(PositionForBox(logically_last_box, false));
  }

  // Can't reach this. We have a root line box, but it has no kids.
  // FIXME: This should NOTREACHED(), but clicking on placeholder text
  // seems to hit this code path.
  return CreatePositionWithAffinity(0);
}

#ifndef NDEBUG

void LayoutBlockFlow::ShowLineTreeAndMark(const InlineBox* marked_box1,
                                          const char* marked_label1,
                                          const InlineBox* marked_box2,
                                          const char* marked_label2,
                                          const LayoutObject* obj) const {
  ShowLayoutObject();
  for (const RootInlineBox* root = FirstRootBox(); root;
       root = root->NextRootBox())
    root->ShowLineTreeAndMark(marked_box1, marked_label1, marked_box2,
                              marked_label2, obj, 1);
}

#endif

void LayoutBlockFlow::AddOutlineRects(
    Vector<LayoutRect>& rects,
    const LayoutPoint& additional_offset,
    IncludeBlockVisualOverflowOrNot include_block_overflows) const {
  // For blocks inside inlines, we go ahead and include margins so that we run
  // right up to the inline boxes above and below us (thus getting merged with
  // them to form a single irregular shape).
  const LayoutInline* inline_element_continuation =
      this->InlineElementContinuation();
  if (inline_element_continuation) {
    // FIXME: This check really isn't accurate.
    bool next_inline_has_line_box = inline_element_continuation->FirstLineBox();
    // FIXME: This is wrong. The principal layoutObject may not be the
    // continuation preceding this block.
    // FIXME: This is wrong for vertical writing-modes.
    // https://bugs.webkit.org/show_bug.cgi?id=46781
    bool prev_inline_has_line_box =
        ToLayoutInline(
            inline_element_continuation->GetNode()->GetLayoutObject())
            ->FirstLineBox();
    LayoutUnit top_margin =
        prev_inline_has_line_box ? CollapsedMarginBefore() : LayoutUnit();
    LayoutUnit bottom_margin =
        next_inline_has_line_box ? CollapsedMarginAfter() : LayoutUnit();
    if (top_margin || bottom_margin) {
      LayoutRect rect(additional_offset, Size());
      rect.ExpandEdges(top_margin, LayoutUnit(), bottom_margin, LayoutUnit());
      rects.push_back(rect);
    }
  }

  LayoutBlock::AddOutlineRects(rects, additional_offset,
                               include_block_overflows);

  if (include_block_overflows == kIncludeBlockVisualOverflow &&
      !HasOverflowClip() && !HasControlClip()) {
    for (RootInlineBox* curr = FirstRootBox(); curr;
         curr = curr->NextRootBox()) {
      LayoutUnit top = std::max<LayoutUnit>(curr->LineTop(), curr->Y());
      LayoutUnit bottom =
          std::min<LayoutUnit>(curr->LineBottom(), curr->Y() + curr->Height());
      LayoutRect rect(additional_offset.X() + curr->X(),
                      additional_offset.Y() + top, curr->Width(), bottom - top);
      if (!rect.IsEmpty())
        rects.push_back(rect);
    }
  }

  if (inline_element_continuation)
    inline_element_continuation->AddOutlineRects(
        rects,
        additional_offset +
            (inline_element_continuation->ContainingBlock()->Location() -
             Location()),
        include_block_overflows);
}

PaintInvalidationReason LayoutBlockFlow::DeprecatedInvalidatePaint(
    const PaintInvalidationState& paint_invalidation_state) {
  if (ContainsFloats())
    paint_invalidation_state.PaintingLayer().SetNeedsPaintPhaseFloat();

  return LayoutBlock::DeprecatedInvalidatePaint(paint_invalidation_state);
}

void LayoutBlockFlow::InvalidateDisplayItemClients(
    PaintInvalidationReason invalidation_reason) const {
  BlockFlowPaintInvalidator(*this).InvalidateDisplayItemClients(
      invalidation_reason);
}

}  // namespace blink
