/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2007 David Smith (catfish.man@gmail.com)
 * Copyright (C) 2003-2013 Apple Inc. All rights reserved.
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 * 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.
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_BLOCK_FLOW_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_BLOCK_FLOW_H_

#include <memory>
#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_item.h"
#include "third_party/blink/renderer/core/layout/floating_objects.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/line/line_box_list.h"
#include "third_party/blink/renderer/core/layout/line/root_inline_box.h"
#include "third_party/blink/renderer/core/layout/line/trailing_objects.h"

namespace blink {

template <class Run>
class BidiRunList;
class BlockChildrenLayoutInfo;
class LayoutInline;
class LineInfo;
class LineLayoutState;
class LineWidth;
class LayoutMultiColumnFlowThread;
class LayoutMultiColumnSpannerPlaceholder;
class LayoutRubyRun;
class MarginInfo;
class NGBreakToken;
class NGConstraintSpace;
class NGLayoutResult;
class NGPaintFragment;
class NGPhysicalFragment;

struct NGInlineNodeData;

enum IndentTextOrNot { kDoNotIndentText, kIndentText };

// LayoutBlockFlow is the class that implements a block container in CSS 2.1.
// http://www.w3.org/TR/CSS21/visuren.html#block-boxes
//
// LayoutBlockFlows are the only LayoutObject allowed to own floating objects
// (aka floats): http://www.w3.org/TR/CSS21/visuren.html#floats .
//
// Floats are inserted into |m_floatingObjects| (see FloatingObjects for more
// information on how floats are modelled) during layout. This happens either as
// part of laying out blocks (layoutBlockChildren) or line layout (LineBreaker
// class). This is because floats can be part of an inline or a block context.
//
// An interesting feature of floats is that they can intrude into the next
// block(s). This means that |m_floatingObjects| can potentially contain
// pointers to a previous sibling LayoutBlockFlow's float.
//
// LayoutBlockFlow is also the only LayoutObject to own a line box tree and
// perform inline layout. See LayoutBlockFlowLine.cpp for these parts.
//
// TODO(jchaffraix): We need some float and line box expert to expand on this.
//
// LayoutBlockFlow enforces the following invariant:
//
// All in-flow children (ie excluding floating and out-of-flow positioned) are
// either all blocks or all inline boxes.
//
// This is suggested by CSS to correctly the layout mixed inlines and blocks
// lines (http://www.w3.org/TR/CSS21/visuren.html#anonymous-block-level). See
// LayoutBlock::addChild about how the invariant is enforced.
class CORE_EXPORT LayoutBlockFlow : public LayoutBlock {
 public:
  explicit LayoutBlockFlow(ContainerNode*);
  ~LayoutBlockFlow() override;

  static LayoutBlockFlow* CreateAnonymous(Document*,
                                          scoped_refptr<ComputedStyle>);
  bool BeingDestroyed() const { return being_destroyed_; }

  bool IsLayoutBlockFlow() const final { return true; }

  void UpdateBlockLayout(bool relayout_children) override;

  void ComputeOverflow(LayoutUnit old_client_after_edge,
                       bool recompute_floats = false) override;

  void DeleteLineBoxTree();

  bool CanContainFirstFormattedLine() const;

  LayoutUnit AvailableLogicalWidthForLine(
      LayoutUnit position,
      IndentTextOrNot indent_text,
      LayoutUnit logical_height = LayoutUnit()) const {
    return (LogicalRightOffsetForLine(position, indent_text, logical_height) -
            LogicalLeftOffsetForLine(position, indent_text, logical_height))
        .ClampNegativeToZero();
  }
  LayoutUnit LogicalRightOffsetForLine(
      LayoutUnit position,
      IndentTextOrNot indent_text,
      LayoutUnit logical_height = LayoutUnit()) const {
    return LogicalRightOffsetForLine(position, LogicalRightOffsetForContent(),
                                     indent_text, logical_height);
  }
  LayoutUnit LogicalLeftOffsetForLine(
      LayoutUnit position,
      IndentTextOrNot indent_text,
      LayoutUnit logical_height = LayoutUnit()) const {
    return LogicalLeftOffsetForLine(position, LogicalLeftOffsetForContent(),
                                    indent_text, logical_height);
  }
  LayoutUnit StartOffsetForLine(
      LayoutUnit position,
      IndentTextOrNot indent_text,
      LayoutUnit logical_height = LayoutUnit()) const {
    return Style()->IsLeftToRightDirection()
               ? LogicalLeftOffsetForLine(position, indent_text, logical_height)
               : LogicalWidth() - LogicalRightOffsetForLine(
                                      position, indent_text, logical_height);
  }

  LayoutUnit AvailableLogicalWidthForAvoidingFloats(
      LayoutUnit position,
      LayoutUnit logical_height = LayoutUnit()) const {
    return (LogicalRightOffsetForAvoidingFloats(position, logical_height) -
            LogicalLeftOffsetForAvoidingFloats(position, logical_height))
        .ClampNegativeToZero();
  }
  LayoutUnit LogicalLeftOffsetForAvoidingFloats(
      LayoutUnit position,
      LayoutUnit logical_height = LayoutUnit()) const {
    return LogicalLeftFloatOffsetForAvoidingFloats(
        position, LogicalLeftOffsetForContent(), logical_height);
  }
  LayoutUnit LogicalRightOffsetForAvoidingFloats(
      LayoutUnit position,
      LayoutUnit logical_height = LayoutUnit()) const {
    return LogicalRightFloatOffsetForAvoidingFloats(
        position, LogicalRightOffsetForContent(), logical_height);
  }
  LayoutUnit StartOffsetForAvoidingFloats(
      LayoutUnit position,
      LayoutUnit logical_height = LayoutUnit()) const {
    return Style()->IsLeftToRightDirection()
               ? LogicalLeftOffsetForAvoidingFloats(position, logical_height)
               : LogicalWidth() - LogicalRightOffsetForAvoidingFloats(
                                      position, logical_height);
  }
  LayoutUnit EndOffsetForAvoidingFloats(
      LayoutUnit position,
      LayoutUnit logical_height = LayoutUnit()) const {
    return !Style()->IsLeftToRightDirection()
               ? LogicalLeftOffsetForAvoidingFloats(position, logical_height)
               : LogicalWidth() - LogicalRightOffsetForAvoidingFloats(
                                      position, logical_height);
  }

  const LineBoxList& LineBoxes() const { return line_boxes_; }
  LineBoxList* LineBoxes() { return &line_boxes_; }
  InlineFlowBox* FirstLineBox() const { return line_boxes_.First(); }
  InlineFlowBox* LastLineBox() const { return line_boxes_.Last(); }
  RootInlineBox* FirstRootBox() const {
    return static_cast<RootInlineBox*>(FirstLineBox());
  }
  RootInlineBox* LastRootBox() const {
    return static_cast<RootInlineBox*>(LastLineBox());
  }

  RootInlineBox* CreateAndAppendRootInlineBox();
  RootInlineBox* ConstructLine(BidiRunList<BidiRun>&, const LineInfo&);

  // Return the number of lines in *this* block flow. Does not recurse into
  // block flow children.
  // Will start counting from the first line, and stop counting right after
  // |stopRootInlineBox|, if specified.
  int LineCount(const RootInlineBox* stop_root_inline_box = nullptr) const;

  LayoutUnit FirstLineBoxBaseline() const override;
  LayoutUnit InlineBlockBaseline(LineDirectionMode) const override;

  void RemoveFloatingObjectsFromDescendants();
  void MarkAllDescendantsWithFloatsForLayout(
      LayoutBox* float_to_remove = nullptr,
      bool in_layout = true);
  void MarkSiblingsWithFloatsForLayout(LayoutBox* float_to_remove = nullptr);

  bool ContainsFloats() const {
    return floating_objects_ && !floating_objects_->Set().IsEmpty();
  }
  bool ContainsFloat(LayoutBox*) const;

  void RemoveFloatingObjects();

  LayoutBoxModelObject* VirtualContinuation() const final {
    return Continuation();
  }
  bool IsAnonymousBlockContinuation() const {
    return Continuation() && IsAnonymousBlock();
  }

  using LayoutBoxModelObject::Continuation;
  using LayoutBoxModelObject::SetContinuation;

  LayoutInline* InlineElementContinuation() const;

  void AddChild(LayoutObject* new_child,
                LayoutObject* before_child = nullptr) override;
  void RemoveChild(LayoutObject*) override;

  void MoveAllChildrenIncludingFloatsTo(LayoutBlock* to_block,
                                        bool full_remove_insert);

  void ChildBecameFloatingOrOutOfFlow(LayoutBox* child);
  void CollapseAnonymousBlockChild(LayoutBlockFlow* child);

  bool GeneratesLineBoxesForInlineChild(LayoutObject*);

  LayoutUnit LogicalTopForFloat(const FloatingObject& floating_object) const {
    return IsHorizontalWritingMode() ? floating_object.Y()
                                     : floating_object.X();
  }
  LayoutUnit LogicalBottomForFloat(
      const FloatingObject& floating_object) const {
    return IsHorizontalWritingMode() ? floating_object.MaxY()
                                     : floating_object.MaxX();
  }
  LayoutUnit LogicalLeftForFloat(const FloatingObject& floating_object) const {
    return IsHorizontalWritingMode() ? floating_object.X()
                                     : floating_object.Y();
  }
  LayoutUnit LogicalRightForFloat(const FloatingObject& floating_object) const {
    return IsHorizontalWritingMode() ? floating_object.MaxX()
                                     : floating_object.MaxY();
  }
  LayoutUnit LogicalWidthForFloat(const FloatingObject& floating_object) const {
    return IsHorizontalWritingMode() ? floating_object.Width()
                                     : floating_object.Height();
  }

  void SetLogicalTopForFloat(FloatingObject& floating_object,
                             LayoutUnit logical_top) {
    if (IsHorizontalWritingMode())
      floating_object.SetY(logical_top);
    else
      floating_object.SetX(logical_top);
  }
  void SetLogicalLeftForFloat(FloatingObject& floating_object,
                              LayoutUnit logical_left) {
    if (IsHorizontalWritingMode())
      floating_object.SetX(logical_left);
    else
      floating_object.SetY(logical_left);
  }
  void SetLogicalHeightForFloat(FloatingObject& floating_object,
                                LayoutUnit logical_height) {
    if (IsHorizontalWritingMode())
      floating_object.SetHeight(logical_height);
    else
      floating_object.SetWidth(logical_height);
  }
  void SetLogicalWidthForFloat(FloatingObject& floating_object,
                               LayoutUnit logical_width) {
    if (IsHorizontalWritingMode())
      floating_object.SetWidth(logical_width);
    else
      floating_object.SetHeight(logical_width);
  }

  LayoutUnit StartAlignedOffsetForLine(LayoutUnit position, IndentTextOrNot);

  void SetStaticInlinePositionForChild(LayoutBox&, LayoutUnit inline_position);
  void UpdateStaticInlinePositionForChild(LayoutBox&,
                                          LayoutUnit logical_top,
                                          IndentTextOrNot = kDoNotIndentText);

  static bool ShouldSkipCreatingRunsForObject(LineLayoutItem obj) {
    return obj.IsFloating() || (obj.IsOutOfFlowPositioned() &&
                                !obj.Style()->IsOriginalDisplayInlineType() &&
                                !obj.Container().IsLayoutInline());
  }

  LayoutMultiColumnFlowThread* MultiColumnFlowThread() const {
    return rare_data_ ? rare_data_->multi_column_flow_thread_ : nullptr;
  }
  void ResetMultiColumnFlowThread() {
    if (rare_data_)
      rare_data_->multi_column_flow_thread_ = nullptr;
  }

  void AddOverflowFromInlineChildren();

  // FIXME: This should be const to avoid a const_cast, but can modify child
  // dirty bits and LayoutTextCombine.
  void ComputeInlinePreferredLogicalWidths(LayoutUnit& min_logical_width,
                                           LayoutUnit& max_logical_width);

  bool AllowsPaginationStrut() const;
  // Pagination strut caused by the first line or child block inside this
  // block-level object.
  //
  // When the first piece of content (first child block or line) inside an
  // object wants to insert a soft page or column break, rather than setting a
  // pagination strut on itself it normally propagates the strut to its
  // containing block (|this|), as long as our implementation can handle it.
  // The idea is that we want to push the entire object to the next page or
  // column along with the child content that caused the break, instead of
  // leaving unusable space at the beginning of the object at the end of one
  // column or page and just push the first line or block to the next column or
  // page. That would waste space in the container for no good reason, and it
  // would also be a spec violation, since there is no break opportunity defined
  // between the content logical top of an object and its first child or line
  // (only *between* blocks or lines).
  LayoutUnit PaginationStrutPropagatedFromChild() const {
    return rare_data_ ? rare_data_->pagination_strut_propagated_from_child_
                      : LayoutUnit();
  }
  void SetPaginationStrutPropagatedFromChild(LayoutUnit);

  LayoutUnit FirstForcedBreakOffset() const {
    if (!rare_data_)
      return LayoutUnit();
    return rare_data_->first_forced_break_offset_;
  }
  void SetFirstForcedBreakOffset(LayoutUnit);

  void PositionSpannerDescendant(LayoutMultiColumnSpannerPlaceholder& child);

  bool CreatesNewFormattingContext() const override;
  bool AvoidsFloats() const final;

  using LayoutBoxModelObject::MoveChildrenTo;
  void MoveChildrenTo(LayoutBoxModelObject* to_box_model_object,
                      LayoutObject* start_child,
                      LayoutObject* end_child,
                      LayoutObject* before_child,
                      bool full_remove_insert = false) override;

  LayoutUnit XPositionForFloatIncludingMargin(
      const FloatingObject& child) const {
    LayoutUnit scrollbar_adjustment(OriginAdjustmentForScrollbars().Width());
    if (IsHorizontalWritingMode()) {
      return child.X() + child.GetLayoutObject()->MarginLeft() +
             scrollbar_adjustment;
    }
    return child.X() + MarginBeforeForChild(*child.GetLayoutObject());
  }

  DISABLE_CFI_PERF
  LayoutUnit YPositionForFloatIncludingMargin(
      const FloatingObject& child) const {
    if (IsHorizontalWritingMode())
      return child.Y() + MarginBeforeForChild(*child.GetLayoutObject());

    return child.Y() + child.GetLayoutObject()->MarginTop();
  }

  LayoutPoint FlipFloatForWritingModeForChild(const FloatingObject&,
                                              const LayoutPoint&) const;

  const char* GetName() const override { return "LayoutBlockFlow"; }

  FloatingObject* InsertFloatingObject(LayoutBox&);

  // Position and lay out all floats that have not yet been positioned.
  //
  // This will mark them as "placed", which means that they have found their
  // final location in this layout pass.
  //
  // |logicalTopMarginEdge| is the minimum logical top for the floats. The
  // final logical top of the floats will also be affected by clearance and
  // space available after having positioned earlier floats.
  //
  // Returns true if and only if it has placed any floats.
  bool PlaceNewFloats(LayoutUnit logical_top_margin_edge, LineWidth* = nullptr);

  // Position and lay out the float, if it needs layout.
  // |logicalTopMarginEdge| is the minimum logical top offset for the float.
  // The value returned is the minimum logical top offset for subsequent
  // floats.
  LayoutUnit PositionAndLayoutFloat(FloatingObject&,
                                    LayoutUnit logical_top_margin_edge);

  LayoutUnit NextFloatLogicalBottomBelow(LayoutUnit) const;
  LayoutUnit NextFloatLogicalBottomBelowForBlock(LayoutUnit) const;

  FloatingObject* LastFloatFromPreviousLine() const {
    return ContainsFloats() ? floating_objects_->Set().back().get() : nullptr;
  }

  void SetShouldDoFullPaintInvalidationForFirstLine();

  void SimplifiedNormalFlowInlineLayout();
  bool RecalcInlineChildrenOverflowAfterStyleChange();

  PositionWithAffinity PositionForPoint(const LayoutPoint&) const override;

  LayoutUnit LowestFloatLogicalBottom(EClear = EClear::kBoth) const;

  bool HasOverhangingFloats() const {
    return Parent() && ContainsFloats() &&
           LowestFloatLogicalBottom() > LogicalHeight();
  }
  bool IsOverhangingFloat(const FloatingObject& float_object) const {
    return LogicalBottomForFloat(float_object) > LogicalHeight();
  }

  LayoutUnit LogicalHeightWithVisibleOverflow() const final;

  // This function is only public so we can call it from NGBlockNode while we're
  // still working on LayoutNG.
  void UpdateIsSelfCollapsing() {
    is_self_collapsing_ = CheckIfIsSelfCollapsingBlock();
  }

  // This function is only public so we can call it from NGBlockNode while we're
  // still working on LayoutNG.
  void AddOverflowFromFloats();

  virtual NGInlineNodeData* TakeNGInlineNodeData() { return nullptr; }
  virtual NGInlineNodeData* GetNGInlineNodeData() const { return nullptr; }
  virtual void ResetNGInlineNodeData() {}
  virtual bool HasNGInlineNodeData() const { return false; }
  virtual NGPaintFragment* PaintFragment() const { return nullptr; }
  virtual scoped_refptr<NGLayoutResult> CachedLayoutResult(
      const NGConstraintSpace&,
      NGBreakToken*) const;
  virtual const NGConstraintSpace* CachedConstraintSpace() const;
  virtual scoped_refptr<NGLayoutResult> CachedLayoutResultForTesting();
  virtual void SetCachedLayoutResult(const NGConstraintSpace&,
                                     NGBreakToken*,
                                     scoped_refptr<NGLayoutResult>);
  virtual void WillCollectInlines() {}
  virtual void SetPaintFragment(scoped_refptr<const NGPhysicalFragment>);
  virtual void ClearPaintFragment() {}
  virtual const NGPhysicalBoxFragment* CurrentFragment() const {
    return nullptr;
  }

#ifndef NDEBUG
  void ShowLineTreeAndMark(const InlineBox* = nullptr,
                           const char* = nullptr,
                           const InlineBox* = nullptr,
                           const char* = nullptr,
                           const LayoutObject* = nullptr) const;
#endif

 protected:
  void RebuildFloatsFromIntruding();
  void LayoutInlineChildren(bool relayout_children, LayoutUnit after_edge);
  void AddLowestFloatFromChildren(LayoutBlockFlow*);

  void CreateFloatingObjects();

  void WillBeDestroyed() override;
  void StyleWillChange(StyleDifference,
                       const ComputedStyle& new_style) override;
  void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;

  void UpdateBlockChildDirtyBitsBeforeLayout(bool relayout_children,
                                             LayoutBox&);

  void ComputeSelfHitTestRects(Vector<LayoutRect>&,
                               const LayoutPoint& layer_offset) const override;

  void AbsoluteRects(Vector<IntRect>&,
                     const LayoutPoint& accumulated_offset) const override;
  void AbsoluteQuads(Vector<FloatQuad>&,
                     MapCoordinatesFlags mode = 0) const override;
  void AbsoluteQuadsForSelf(Vector<FloatQuad>& quads,
                            MapCoordinatesFlags mode = 0) const override;
  LayoutObject* HoverAncestor() const final;

  LayoutUnit LogicalRightOffsetForLine(
      LayoutUnit logical_top,
      LayoutUnit fixed_offset,
      IndentTextOrNot apply_text_indent,
      LayoutUnit logical_height = LayoutUnit()) const {
    return AdjustLogicalRightOffsetForLine(
        LogicalRightFloatOffsetForLine(logical_top, fixed_offset,
                                       logical_height),
        apply_text_indent);
  }
  LayoutUnit LogicalLeftOffsetForLine(
      LayoutUnit logical_top,
      LayoutUnit fixed_offset,
      IndentTextOrNot apply_text_indent,
      LayoutUnit logical_height = LayoutUnit()) const {
    return AdjustLogicalLeftOffsetForLine(
        LogicalLeftFloatOffsetForLine(logical_top, fixed_offset,
                                      logical_height),
        apply_text_indent);
  }

  virtual LayoutObject* LayoutSpecialExcludedChild(bool /*relayoutChildren*/,
                                                   SubtreeLayoutScope&);
  bool UpdateLogicalWidthAndColumnWidth() override;

  void SetLogicalLeftForChild(LayoutBox& child, LayoutUnit logical_left);
  void SetLogicalTopForChild(LayoutBox& child, LayoutUnit logical_top);
  void DetermineLogicalLeftPositionForChild(LayoutBox& child);

  void AddOutlineRects(Vector<LayoutRect>&,
                       const LayoutPoint& additional_offset,
                       IncludeBlockVisualOverflowOrNot) const override;

  bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const override;
  void InvalidateDisplayItemClients(PaintInvalidationReason) const override;

  Node* NodeForHitTest() const final;
  bool HitTestChildren(HitTestResult&,
                       const HitTestLocation& location_in_container,
                       const LayoutPoint& accumulated_offset,
                       HitTestAction) override;

  LayoutSize AccumulateInFlowPositionOffsets() const override;

 private:
  void ResetLayout();
  void LayoutChildren(bool relayout_children, SubtreeLayoutScope&);
  void AddOverhangingFloatsFromChildren(LayoutUnit unconstrained_height);
  void LayoutBlockChildren(bool relayout_children,
                           SubtreeLayoutScope&,
                           LayoutUnit before_edge,
                           LayoutUnit after_edge);

  void MarkDescendantsWithFloatsForLayoutIfNeeded(
      LayoutBlockFlow& child,
      LayoutUnit new_logical_top,
      LayoutUnit previous_float_logical_bottom);
  bool PositionAndLayoutOnceIfNeeded(LayoutBox& child,
                                     LayoutUnit new_logical_top,
                                     BlockChildrenLayoutInfo&);

  // Handle breaking policy before the child, and insert a forced break in front
  // of it if needed.
  void InsertForcedBreakBeforeChildIfNeeded(LayoutBox& child,
                                            BlockChildrenLayoutInfo&);

  void LayoutBlockChild(LayoutBox& child, BlockChildrenLayoutInfo&);
  void AdjustPositionedBlock(LayoutBox& child, const BlockChildrenLayoutInfo&);
  void AdjustFloatingBlock(const MarginInfo&);

  LayoutPoint ComputeLogicalLocationForFloat(
      const FloatingObject&,
      LayoutUnit logical_top_offset) const;

  void RemoveFloatingObject(LayoutBox*);
  void RemoveFloatingObjectsBelow(FloatingObject*, LayoutUnit logical_offset);

  LayoutUnit GetClearDelta(LayoutBox* child, LayoutUnit y_pos);

  bool HasOverhangingFloat(LayoutBox*);
  void AddIntrudingFloats(LayoutBlockFlow* prev,
                          LayoutUnit xoffset,
                          LayoutUnit yoffset);
  void AddOverhangingFloats(LayoutBlockFlow* child,
                            bool make_child_paint_other_floats);

  bool HitTestFloats(HitTestResult&,
                     const HitTestLocation& location_in_container,
                     const LayoutPoint& accumulated_offset);

  void ClearFloats(EClear);

  LayoutUnit LogicalRightFloatOffsetForLine(LayoutUnit logical_top,
                                            LayoutUnit fixed_offset,
                                            LayoutUnit logical_height) const;
  LayoutUnit LogicalLeftFloatOffsetForLine(LayoutUnit logical_top,
                                           LayoutUnit fixed_offset,
                                           LayoutUnit logical_height) const;

  LayoutUnit LogicalLeftFloatOffsetForAvoidingFloats(
      LayoutUnit logical_top,
      LayoutUnit fixed_offset,
      LayoutUnit logical_height) const;
  LayoutUnit LogicalRightFloatOffsetForAvoidingFloats(
      LayoutUnit logical_top,
      LayoutUnit fixed_offset,
      LayoutUnit logical_height) const;

  LayoutUnit LogicalRightOffsetForPositioningFloat(
      LayoutUnit logical_top,
      LayoutUnit fixed_offset,
      LayoutUnit* height_remaining) const;
  LayoutUnit LogicalLeftOffsetForPositioningFloat(
      LayoutUnit logical_top,
      LayoutUnit fixed_offset,
      LayoutUnit* height_remaining) const;

  LayoutUnit AdjustLogicalRightOffsetForLine(
      LayoutUnit offset_from_floats,
      IndentTextOrNot apply_text_indent) const;
  LayoutUnit AdjustLogicalLeftOffsetForLine(
      LayoutUnit offset_from_floats,
      IndentTextOrNot apply_text_indent) const;

  virtual RootInlineBox* CreateRootInlineBox();  // Subclassed by SVG

  void DirtyLinesFromChangedChild(
      LayoutObject* child,
      MarkingBehavior marking_behaviour = kMarkContainerChain) final {
    line_boxes_.DirtyLinesFromChangedChild(
        LineLayoutItem(this), LineLayoutItem(child),
        marking_behaviour == kMarkContainerChain);
  }

  bool IsPagedOverflow(const ComputedStyle&);

  enum FlowThreadType {
    kNoFlowThread,
    kMultiColumnFlowThread,
    kPagedFlowThread
  };

  FlowThreadType GetFlowThreadType(const ComputedStyle&);

  LayoutMultiColumnFlowThread* CreateMultiColumnFlowThread(FlowThreadType);
  void CreateOrDestroyMultiColumnFlowThreadIfNeeded(
      const ComputedStyle* old_style);

  // Merge children of |siblingThatMayBeDeleted| into this object if possible,
  // and delete |siblingThatMayBeDeleted|. Returns true if we were able to
  // merge. In that case, |siblingThatMayBeDeleted| will be dead. We'll only be
  // able to merge if both blocks are anonymous.
  bool MergeSiblingContiguousAnonymousBlock(
      LayoutBlockFlow* sibling_that_may_be_deleted);

  // Reparent subsequent or preceding adjacent floating or out-of-flow siblings
  // into this object.
  void ReparentSubsequentFloatingOrOutOfFlowSiblings();
  void ReparentPrecedingFloatingOrOutOfFlowSiblings();

  bool NeedsAnonymousInlineWrapper() const;
  void MakeChildrenInlineIfPossible();

  void MakeChildrenNonInline(LayoutObject* insertion_point = nullptr);
  void ChildBecameNonInline(LayoutObject* child) final;

  void UpdateLogicalWidthForAlignment(const ETextAlign&,
                                      const RootInlineBox*,
                                      BidiRun* trailing_space_run,
                                      LayoutUnit& logical_left,
                                      LayoutUnit& total_logical_width,
                                      LayoutUnit& available_logical_width,
                                      unsigned expansion_opportunity_count);

  bool ShouldBreakAtLineToAvoidWidow() const {
    return rare_data_ && rare_data_->line_break_to_avoid_widow_ >= 0;
  }
  void ClearShouldBreakAtLineToAvoidWidow() const;
  int LineBreakToAvoidWidow() const {
    return rare_data_ ? rare_data_->line_break_to_avoid_widow_ : -1;
  }
  void SetBreakAtLineToAvoidWidow(int);
  void ClearDidBreakAtLineToAvoidWidow();
  void SetDidBreakAtLineToAvoidWidow();
  bool DidBreakAtLineToAvoidWidow() const {
    return rare_data_ && rare_data_->did_break_at_line_to_avoid_widow_;
  }

 public:
  struct FloatWithRect {
    DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
    FloatWithRect(LayoutBox* f)
        : object(f), rect(f->FrameRect()), ever_had_layout(f->EverHadLayout()) {
      rect.Expand(f->MarginBoxOutsets());
    }

    LayoutBox* object;
    LayoutRect rect;
    bool ever_had_layout;
  };

  // MarginValues holds the margins in the block direction
  // used during collapsing margins computation.
  // CSS mandates to keep track of both positive and negative margins:
  // "When two or more margins collapse, the resulting margin width is the
  // maximum of the collapsing margins' widths. In the case of negative
  // margins, the maximum of the absolute values of the negative adjoining
  // margins is deducted from the maximum of the positive adjoining margins.
  // If there are no positive margins, the maximum of the absolute values of
  // the adjoining margins is deducted from zero."
  // https://drafts.csswg.org/css2/box.html#collapsing-margins
  class MarginValues {
    DISALLOW_NEW();

   public:
    MarginValues(LayoutUnit before_pos,
                 LayoutUnit before_neg,
                 LayoutUnit after_pos,
                 LayoutUnit after_neg)
        : positive_margin_before_(before_pos),
          negative_margin_before_(before_neg),
          positive_margin_after_(after_pos),
          negative_margin_after_(after_neg) {}

    LayoutUnit PositiveMarginBefore() const { return positive_margin_before_; }
    LayoutUnit NegativeMarginBefore() const { return negative_margin_before_; }
    LayoutUnit PositiveMarginAfter() const { return positive_margin_after_; }
    LayoutUnit NegativeMarginAfter() const { return negative_margin_after_; }

    void SetPositiveMarginBefore(LayoutUnit pos) {
      positive_margin_before_ = pos;
    }
    void SetNegativeMarginBefore(LayoutUnit neg) {
      negative_margin_before_ = neg;
    }
    void SetPositiveMarginAfter(LayoutUnit pos) {
      positive_margin_after_ = pos;
    }
    void SetNegativeMarginAfter(LayoutUnit neg) {
      negative_margin_after_ = neg;
    }

   private:
    LayoutUnit positive_margin_before_;
    LayoutUnit negative_margin_before_;
    LayoutUnit positive_margin_after_;
    LayoutUnit negative_margin_after_;
  };
  MarginValues MarginValuesForChild(LayoutBox& child) const;

  // Allocated only when some of these fields have non-default values
  struct LayoutBlockFlowRareData {
    USING_FAST_MALLOC(LayoutBlockFlowRareData);

   public:
    LayoutBlockFlowRareData(const LayoutBlockFlow* block)
        : margins_(PositiveMarginBeforeDefault(block),
                   NegativeMarginBeforeDefault(block),
                   PositiveMarginAfterDefault(block),
                   NegativeMarginAfterDefault(block)),
          multi_column_flow_thread_(nullptr),
          break_before_(static_cast<unsigned>(EBreakBetween::kAuto)),
          break_after_(static_cast<unsigned>(EBreakBetween::kAuto)),
          line_break_to_avoid_widow_(-1),
          did_break_at_line_to_avoid_widow_(false),
          discard_margin_before_(false),
          discard_margin_after_(false) {}

    static LayoutUnit PositiveMarginBeforeDefault(
        const LayoutBlockFlow* block) {
      return block->MarginBefore().ClampNegativeToZero();
    }
    static LayoutUnit NegativeMarginBeforeDefault(
        const LayoutBlockFlow* block) {
      return (-block->MarginBefore()).ClampNegativeToZero();
    }
    static LayoutUnit PositiveMarginAfterDefault(const LayoutBlockFlow* block) {
      return block->MarginAfter().ClampNegativeToZero();
    }
    static LayoutUnit NegativeMarginAfterDefault(const LayoutBlockFlow* block) {
      return (-block->MarginAfter()).ClampNegativeToZero();
    }

    MarginValues margins_;
    LayoutUnit pagination_strut_propagated_from_child_;

    LayoutUnit first_forced_break_offset_;

    LayoutMultiColumnFlowThread* multi_column_flow_thread_;

    unsigned break_before_ : 4;
    unsigned break_after_ : 4;
    int line_break_to_avoid_widow_;
    bool did_break_at_line_to_avoid_widow_ : 1;
    bool discard_margin_before_ : 1;
    bool discard_margin_after_ : 1;
    DISALLOW_COPY_AND_ASSIGN(LayoutBlockFlowRareData);
  };

  const FloatingObjects* GetFloatingObjects() const {
    return floating_objects_.get();
  }

  static void UpdateAncestorShouldPaintFloatingObject(
      const LayoutBox& float_box);

  bool ShouldTruncateOverflowingText() const;

  base::Optional<LayoutUnit> ComputeDialogYPosition(LayoutUnit height) const;

  int GetLayoutPassCountForTesting();

 protected:
  LayoutUnit MaxPositiveMarginBefore() const {
    return rare_data_
               ? rare_data_->margins_.PositiveMarginBefore()
               : LayoutBlockFlowRareData::PositiveMarginBeforeDefault(this);
  }
  LayoutUnit MaxNegativeMarginBefore() const {
    return rare_data_
               ? rare_data_->margins_.NegativeMarginBefore()
               : LayoutBlockFlowRareData::NegativeMarginBeforeDefault(this);
  }
  LayoutUnit MaxPositiveMarginAfter() const {
    return rare_data_
               ? rare_data_->margins_.PositiveMarginAfter()
               : LayoutBlockFlowRareData::PositiveMarginAfterDefault(this);
  }
  LayoutUnit MaxNegativeMarginAfter() const {
    return rare_data_
               ? rare_data_->margins_.NegativeMarginAfter()
               : LayoutBlockFlowRareData::NegativeMarginAfterDefault(this);
  }

  void SetMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg);
  void SetMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg);

  void SetMustDiscardMarginBefore(bool = true);
  void SetMustDiscardMarginAfter(bool = true);

  bool MustDiscardMarginBefore() const;
  bool MustDiscardMarginAfter() const;

  bool MustDiscardMarginBeforeForChild(const LayoutBox&) const;
  bool MustDiscardMarginAfterForChild(const LayoutBox&) const;

  bool MustSeparateMarginBeforeForChild(const LayoutBox&) const;
  bool MustSeparateMarginAfterForChild(const LayoutBox&) const;

  void InitMaxMarginValues() {
    if (rare_data_) {
      rare_data_->margins_ = MarginValues(
          LayoutBlockFlowRareData::PositiveMarginBeforeDefault(this),
          LayoutBlockFlowRareData::NegativeMarginBeforeDefault(this),
          LayoutBlockFlowRareData::PositiveMarginAfterDefault(this),
          LayoutBlockFlowRareData::NegativeMarginAfterDefault(this));

      rare_data_->discard_margin_before_ = false;
      rare_data_->discard_margin_after_ = false;
    }
  }

  virtual ETextAlign TextAlignmentForLine(bool ends_with_soft_break) const;

 private:
  LayoutUnit CollapsedMarginBefore() const final {
    return MaxPositiveMarginBefore() - MaxNegativeMarginBefore();
  }
  LayoutUnit CollapsedMarginAfter() const final {
    return MaxPositiveMarginAfter() - MaxNegativeMarginAfter();
  }

  LayoutUnit AdjustedMarginBeforeForPagination(
      const LayoutBox&,
      LayoutUnit logical_top_margin_edge,
      LayoutUnit logical_top_border_edge,
      const BlockChildrenLayoutInfo&) const;

  LayoutUnit CollapseMargins(LayoutBox& child,
                             BlockChildrenLayoutInfo&,
                             bool child_is_self_collapsing,
                             bool child_discard_margin_before,
                             bool child_discard_margin_after);
  LayoutUnit ClearFloatsIfNeeded(LayoutBox& child,
                                 MarginInfo&,
                                 LayoutUnit old_top_pos_margin,
                                 LayoutUnit old_top_neg_margin,
                                 LayoutUnit y_pos,
                                 bool child_is_self_collapsing,
                                 bool child_discard_margin);
  LayoutUnit EstimateLogicalTopPosition(
      LayoutBox& child,
      const BlockChildrenLayoutInfo&,
      LayoutUnit& estimate_without_pagination);
  void MarginBeforeEstimateForChild(LayoutBox&,
                                    LayoutUnit&,
                                    LayoutUnit&,
                                    bool&) const;
  void HandleAfterSideOfBlock(LayoutBox* last_child,
                              LayoutUnit top,
                              LayoutUnit bottom,
                              MarginInfo&);
  void SetCollapsedBottomMargin(const MarginInfo&);

  // Apply any forced fragmentainer break that's set on the current class A
  // break point.
  LayoutUnit ApplyForcedBreak(LayoutUnit logical_offset, EBreakBetween);

  void SetBreakBefore(EBreakBetween);
  void SetBreakAfter(EBreakBetween);
  EBreakBetween BreakBefore() const override;
  EBreakBetween BreakAfter() const override;

  LayoutUnit AdjustBlockChildForPagination(LayoutUnit logical_top,
                                           LayoutBox& child,
                                           BlockChildrenLayoutInfo&,
                                           bool at_before_side_of_block);

  // If a float cannot fit in the current fragmentainer, return the logical top
  // margin edge that the float needs to have in order to be pushed to the top
  // of the next fragmentainer. Otherwise, just return |logicalTopMarginEdge|.
  LayoutUnit AdjustFloatLogicalTopForPagination(
      LayoutBox&,
      LayoutUnit logical_top_margin_edge);

  // Computes a deltaOffset value that put a line at the top of the next page if
  // it doesn't fit on the current page.
  void AdjustLinePositionForPagination(RootInlineBox&,
                                       LayoutUnit& delta_offset);

  // If the child is unsplittable and can't fit on the current page, return the
  // top of the next page/column.
  LayoutUnit AdjustForUnsplittableChild(LayoutBox&,
                                        LayoutUnit logical_offset) const;

  // Used to store state between styleWillChange and styleDidChange
  static bool can_propagate_float_into_sibling_;

  LineBoxList line_boxes_;  // All of the root line boxes created for this block
                            // flow.  For example, <div>Hello<br>world.</div>
                            // will have two total lines for the <div>.

  LayoutBlockFlowRareData& EnsureRareData();

  bool IsSelfCollapsingBlock() const override;
  bool CheckIfIsSelfCollapsingBlock() const;

 protected:
  std::unique_ptr<LayoutBlockFlowRareData> rare_data_;
  std::unique_ptr<FloatingObjects> floating_objects_;

  friend class MarginInfo;
  friend class LineWidth;  // needs to know FloatingObject

  // LayoutRubyBase objects need to be able to split and merge, moving their
  // children around (calling makeChildrenNonInline).
  // TODO(mstensho): Try to get rid of this friendship.
  friend class LayoutRubyBase;

  // FIXME-BLOCKFLOW: These methods have implementations in
  // LayoutBlockFlowLine. They should be moved to the proper header once the
  // line layout code is separated from LayoutBlock and LayoutBlockFlow.
  // START METHODS DEFINED IN LayoutBlockFlowLine
 private:
  InlineFlowBox* CreateLineBoxes(LineLayoutItem,
                                 const LineInfo&,
                                 InlineBox* child_box);
  void SetMarginsForRubyRun(BidiRun*,
                            LayoutRubyRun*,
                            LayoutObject*,
                            const LineInfo&);
  void ComputeInlineDirectionPositionsForLine(RootInlineBox*,
                                              const LineInfo&,
                                              BidiRun* first_run,
                                              BidiRun* trailing_space_run,
                                              bool reached_end,
                                              GlyphOverflowAndFallbackFontsMap&,
                                              VerticalPositionCache&,
                                              const WordMeasurements&);
  BidiRun* ComputeInlineDirectionPositionsForSegment(
      RootInlineBox*,
      const LineInfo&,
      LayoutUnit& logical_left,
      LayoutUnit& available_logical_width,
      BidiRun* first_run,
      BidiRun* trailing_space_run,
      GlyphOverflowAndFallbackFontsMap& text_box_data_map,
      VerticalPositionCache&,
      const WordMeasurements&);
  void ComputeBlockDirectionPositionsForLine(RootInlineBox*,
                                             BidiRun*,
                                             GlyphOverflowAndFallbackFontsMap&,
                                             VerticalPositionCache&);
  void AppendFloatingObjectToLastLine(FloatingObject&);
  void AppendFloatsToLastLine(LineLayoutState&,
                              const InlineIterator& clean_line_start,
                              const InlineBidiResolver&,
                              const BidiStatus& clean_line_bidi_status);
  // Helper function for layoutInlineChildren()
  RootInlineBox* CreateLineBoxesFromBidiRuns(unsigned bidi_level,
                                             BidiRunList<BidiRun>&,
                                             const InlineIterator& end,
                                             LineInfo&,
                                             VerticalPositionCache&,
                                             BidiRun* trailing_space_run,
                                             const WordMeasurements&);
  void LayoutRunsAndFloats(LineLayoutState&);
  const InlineIterator& RestartLayoutRunsAndFloatsInRange(
      LayoutUnit old_logical_height,
      LayoutUnit new_logical_height,
      FloatingObject* last_float_from_previous_line,
      InlineBidiResolver&,
      const InlineIterator&);
  void LayoutRunsAndFloatsInRange(LineLayoutState&,
                                  InlineBidiResolver&,
                                  const InlineIterator& clean_line_start,
                                  const BidiStatus& clean_line_bidi_status);
  void LinkToEndLineIfNeeded(LineLayoutState&);
  void MarkDirtyFloatsForPaintInvalidation(Vector<FloatWithRect>& floats);
  RootInlineBox* DetermineStartPosition(LineLayoutState&, InlineBidiResolver&);
  void DetermineEndPosition(LineLayoutState&,
                            RootInlineBox* start_box,
                            InlineIterator& clean_line_start,
                            BidiStatus& clean_line_bidi_status);
  bool LineBoxHasBRWithClearance(RootInlineBox*);
  bool CheckPaginationAndFloatsAtEndLine(LineLayoutState&);
  bool MatchedEndLine(LineLayoutState&,
                      const InlineBidiResolver&,
                      const InlineIterator& end_line_start,
                      const BidiStatus& end_line_status);
  void DeleteEllipsisLineBoxes();
  void CheckLinesForTextOverflow();
  void TryPlacingEllipsisOnAtomicInlines(RootInlineBox*,
                                         LayoutUnit block_right_edge,
                                         LayoutUnit block_left_edge,
                                         LayoutUnit width,
                                         const AtomicString&,
                                         InlineBox*);
  void ClearTruncationOnAtomicInlines(RootInlineBox*);
  void MarkLinesDirtyInBlockRange(LayoutUnit logical_top,
                                  LayoutUnit logical_bottom,
                                  RootInlineBox* highest = nullptr);
  // Positions new floats and also adjust all floats encountered on the line if
  // any of them have to move to the next page/column.
  void PositionDialog();
  void IncrementLayoutPassCount();

  // END METHODS DEFINED IN LayoutBlockFlowLine
};

DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutBlockFlow, IsLayoutBlockFlow());

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_BLOCK_FLOW_H_
