/*
 * 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, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc.
 *               All rights reserved.
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "third_party/blink/renderer/core/layout/layout_block.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/editing/drag_caret.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/text_affinity.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/html/html_marquee_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_box.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_item.h"
#include "third_party/blink/renderer/core/layout/hit_test_location.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
#include "third_party/blink/renderer/core/layout/layout_flexible_box.h"
#include "third_party/blink/renderer/core/layout/layout_flow_thread.h"
#include "third_party/blink/renderer/core/layout/layout_grid.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h"
#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/root_scroller_controller.h"
#include "third_party/blink/renderer/core/paint/block_paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/block_painter.h"
#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"

namespace blink {

struct SameSizeAsLayoutBlock : public LayoutBox {
  LayoutObjectChildList children;
  uint32_t bitfields;
};

static_assert(sizeof(LayoutBlock) == sizeof(SameSizeAsLayoutBlock),
              "LayoutBlock should stay small");

// This map keeps track of the positioned objects associated with a containing
// block.
//
// This map is populated during layout. It is kept across layouts to handle
// that we skip unchanged sub-trees during layout, in such a way that we are
// able to lay out deeply nested out-of-flow descendants if their containing
// block got laid out. The map could be invalidated during style change but
// keeping track of containing blocks at that time is complicated (we are in
// the middle of recomputing the style so we can't rely on any of its
// information), which is why it's easier to just update it for every layout.
static TrackedDescendantsMap* g_positioned_descendants_map = nullptr;
static TrackedContainerMap* g_positioned_container_map = nullptr;

// This map keeps track of the descendants whose 'height' is percentage
// associated with a containing block. Like |gPositionedDescendantsMap|, it is
// also recomputed for every layout (see the comment above about why).
static TrackedDescendantsMap* g_percent_height_descendants_map = nullptr;

LayoutBlock::LayoutBlock(ContainerNode* node)
    : LayoutBox(node),
      has_margin_before_quirk_(false),
      has_margin_after_quirk_(false),
      being_destroyed_(false),
      has_markup_truncation_(false),
      width_available_to_children_changed_(false),
      height_available_to_children_changed_(false),
      is_self_collapsing_(false),
      descendants_with_floats_marked_for_layout_(false),
      has_positioned_objects_(false),
      has_percent_height_descendants_(false),
      pagination_state_changed_(false) {
  // LayoutBlockFlow calls setChildrenInline(true).
  // By default, subclasses do not have inline children.
}

void LayoutBlock::RemoveFromGlobalMaps() {
  if (HasPositionedObjects()) {
    std::unique_ptr<TrackedLayoutBoxListHashSet> descendants =
        g_positioned_descendants_map->Take(this);
    DCHECK(!descendants->IsEmpty());
    for (LayoutBox* descendant : *descendants) {
      DCHECK_EQ(g_positioned_container_map->at(descendant), this);
      g_positioned_container_map->erase(descendant);
    }
  }
  if (HasPercentHeightDescendants()) {
    std::unique_ptr<TrackedLayoutBoxListHashSet> descendants =
        g_percent_height_descendants_map->Take(this);
    DCHECK(!descendants->IsEmpty());
    for (LayoutBox* descendant : *descendants) {
      DCHECK_EQ(descendant->PercentHeightContainer(), this);
      descendant->SetPercentHeightContainer(nullptr);
    }
  }
}

LayoutBlock::~LayoutBlock() {
  RemoveFromGlobalMaps();
}

void LayoutBlock::WillBeDestroyed() {
  if (!DocumentBeingDestroyed() && Parent())
    Parent()->DirtyLinesFromChangedChild(this);

  if (LocalFrame* frame = GetFrame()) {
    frame->Selection().LayoutBlockWillBeDestroyed(*this);
    frame->GetPage()->GetDragCaret().LayoutBlockWillBeDestroyed(*this);
  }

  if (TextAutosizer* text_autosizer = GetDocument().GetTextAutosizer())
    text_autosizer->Destroy(this);

  LayoutBox::WillBeDestroyed();
}

void LayoutBlock::StyleWillChange(StyleDifference diff,
                                  const ComputedStyle& new_style) {
  const ComputedStyle* old_style = Style();

  SetIsAtomicInlineLevel(new_style.IsDisplayInlineType());

  if (old_style && Parent()) {
    bool old_style_contains_fixed_position =
        old_style->CanContainFixedPositionObjects(IsDocumentElement()) ||
        ShouldApplyPaintContainment() || ShouldApplyLayoutContainment();
    bool old_style_contains_absolute_position =
        old_style_contains_fixed_position ||
        old_style->CanContainAbsolutePositionObjects();
    bool new_style_contains_fixed_position =
        new_style.CanContainFixedPositionObjects(IsDocumentElement()) ||
        ShouldApplyPaintContainment() || ShouldApplyLayoutContainment();
    bool new_style_contains_absolute_position =
        new_style_contains_fixed_position ||
        new_style.CanContainAbsolutePositionObjects();

    if ((old_style_contains_fixed_position &&
         !new_style_contains_fixed_position) ||
        (old_style_contains_absolute_position &&
         !new_style_contains_absolute_position)) {
      // Clear our positioned objects list. Our absolute and fixed positioned
      // descendants will be inserted into our containing block's positioned
      // objects list during layout.
      RemovePositionedObjects(nullptr, kNewContainingBlock);
    }
    if (!old_style_contains_absolute_position &&
        new_style_contains_absolute_position) {
      // Remove our absolutely positioned descendants from their current
      // containing block.
      // They will be inserted into our positioned objects list during layout.
      if (LayoutBlock* cb = ContainingBlockForAbsolutePosition())
        cb->RemovePositionedObjects(this, kNewContainingBlock);
    }
    if (!old_style_contains_fixed_position &&
        new_style_contains_fixed_position) {
      // Remove our fixed positioned descendants from their current containing
      // block.
      // They will be inserted into our positioned objects list during layout.
      if (LayoutBlock* cb = ContainingBlockForFixedPosition())
        cb->RemovePositionedObjects(this, kNewContainingBlock);
    }
  }

  LayoutBox::StyleWillChange(diff, new_style);
}

enum LogicalExtent { kLogicalWidth, kLogicalHeight };
static bool BorderOrPaddingLogicalDimensionChanged(
    const ComputedStyle& old_style,
    const ComputedStyle& new_style,
    LogicalExtent logical_extent) {
  if (new_style.IsHorizontalWritingMode() ==
      (logical_extent == kLogicalWidth)) {
    return old_style.BorderLeftWidth() != new_style.BorderLeftWidth() ||
           old_style.BorderRightWidth() != new_style.BorderRightWidth() ||
           old_style.PaddingLeft() != new_style.PaddingLeft() ||
           old_style.PaddingRight() != new_style.PaddingRight();
  }

  return old_style.BorderTopWidth() != new_style.BorderTopWidth() ||
         old_style.BorderBottomWidth() != new_style.BorderBottomWidth() ||
         old_style.PaddingTop() != new_style.PaddingTop() ||
         old_style.PaddingBottom() != new_style.PaddingBottom();
}

void LayoutBlock::StyleDidChange(StyleDifference diff,
                                 const ComputedStyle* old_style) {
  LayoutBox::StyleDidChange(diff, old_style);

  const ComputedStyle& new_style = StyleRef();

  if (old_style && Parent()) {
    if (old_style->GetPosition() != new_style.GetPosition() &&
        new_style.GetPosition() != EPosition::kStatic) {
      // In LayoutObject::styleWillChange() we already removed ourself from our
      // old containing block's positioned descendant list, and we will be
      // inserted to the new containing block's list during layout. However the
      // positioned descendant layout logic assumes layout objects to obey
      // parent-child order in the list. Remove our descendants here so they
      // will be re-inserted after us.
      if (LayoutBlock* cb = ContainingBlock()) {
        cb->RemovePositionedObjects(this, kNewContainingBlock);
        if (IsOutOfFlowPositioned()) {
          // Insert this object into containing block's positioned descendants
          // list in case the parent won't layout. This is needed especially
          // there are descendants scheduled for overflow recalc.
          cb->InsertPositionedObject(this);
        }
      }
    }
  }

  if (TextAutosizer* text_autosizer = GetDocument().GetTextAutosizer())
    text_autosizer->Record(this);

  PropagateStyleToAnonymousChildren();

  // The LayoutView is always a container of fixed positioned descendants. In
  // addition, SVG foreignObjects become such containers, so that descendants
  // of a foreignObject cannot escape it. Similarly, text controls let authors
  // select elements inside that are created by user agent shadow DOM, and we
  // have (C++) code that assumes that the elements are indeed contained by the
  // text control. So just make sure this is the case. Finally, computed style
  // may turn us into a container of all things, e.g. if the element is
  // transformed, or contain:paint is specified.
  SetCanContainFixedPositionObjects(
      IsLayoutView() || IsSVGForeignObject() || IsTextControl() ||
      new_style.CanContainFixedPositionObjects(IsDocumentElement()) ||
      ShouldApplyPaintContainment() || ShouldApplyLayoutContainment());

  // It's possible for our border/padding to change, but for the overall logical
  // width or height of the block to end up being the same. We keep track of
  // this change so in layoutBlock, we can know to set relayoutChildren=true.
  width_available_to_children_changed_ |=
      old_style && NeedsLayout() &&
      (diff.NeedsFullLayout() || BorderOrPaddingLogicalDimensionChanged(
                                     *old_style, new_style, kLogicalWidth));
  height_available_to_children_changed_ |=
      old_style && diff.NeedsFullLayout() && NeedsLayout() &&
      BorderOrPaddingLogicalDimensionChanged(*old_style, new_style,
                                             kLogicalHeight);
}

void LayoutBlock::UpdateFromStyle() {
  LayoutBox::UpdateFromStyle();

  bool should_clip_overflow =
      !StyleRef().IsOverflowVisible() && AllowsOverflowClip();
  if (should_clip_overflow != HasOverflowClip()) {
    if (!should_clip_overflow)
      GetScrollableArea()->InvalidateAllStickyConstraints();
    SetSubtreeShouldCheckForPaintInvalidation();
    // The overflow clip paint property depends on whether overflow clip is
    // present so we need to update paint properties if this changes.
    SetNeedsPaintPropertyUpdate();
    if (Layer())
      Layer()->SetNeedsCompositingInputsUpdate();
  }
  SetHasOverflowClip(should_clip_overflow);
}

bool LayoutBlock::AllowsOverflowClip() const {
  // If overflow has been propagated to the viewport, it has no effect here.
  return GetNode() != GetDocument().ViewportDefiningElement();
}

void LayoutBlock::AddChildBeforeDescendant(LayoutObject* new_child,
                                           LayoutObject* before_descendant) {
  DCHECK_NE(before_descendant->Parent(), this);
  LayoutObject* before_descendant_container = before_descendant->Parent();
  while (before_descendant_container->Parent() != this)
    before_descendant_container = before_descendant_container->Parent();
  DCHECK(before_descendant_container);

  // We really can't go on if what we have found isn't anonymous. We're not
  // supposed to use some random non-anonymous object and put the child there.
  // That's a recipe for security issues.
  CHECK(before_descendant_container->IsAnonymous());

  // If the requested insertion point is not one of our children, then this is
  // because there is an anonymous container within this object that contains
  // the beforeDescendant.
  if (before_descendant_container->IsAnonymousBlock()) {
    // Insert the child into the anonymous block box instead of here.
    if (new_child->IsInline() ||
        (new_child->IsFloatingOrOutOfFlowPositioned() && !IsFlexibleBox() &&
         !IsLayoutGrid()) ||
        before_descendant->Parent()->SlowFirstChild() != before_descendant) {
      before_descendant_container->AddChild(new_child, before_descendant);
    } else {
      AddChild(new_child, before_descendant->Parent());
    }
    return;
  }

  DCHECK(before_descendant_container->IsTable());
  if (new_child->IsTablePart()) {
    // Insert into the anonymous table.
    before_descendant_container->AddChild(new_child, before_descendant);
    return;
  }

  LayoutObject* before_child =
      SplitAnonymousBoxesAroundChild(before_descendant);

  DCHECK_EQ(before_child->Parent(), this);
  if (before_child->Parent() != this) {
    // We should never reach here. If we do, we need to use the
    // safe fallback to use the topmost beforeChild container.
    before_child = before_descendant_container;
  }

  AddChild(new_child, before_child);
}

void LayoutBlock::AddChild(LayoutObject* new_child,
                           LayoutObject* before_child) {
  if (before_child && before_child->Parent() != this) {
    AddChildBeforeDescendant(new_child, before_child);
    return;
  }

  // Only LayoutBlockFlow should have inline children, and then we shouldn't be
  // here.
  DCHECK(!ChildrenInline());

  if (new_child->IsInline() || (new_child->IsFloatingOrOutOfFlowPositioned() &&
                                !IsFlexibleBox() && !IsLayoutGrid())) {
    // If we're inserting an inline child but all of our children are blocks,
    // then we have to make sure it is put into an anomyous block box. We try to
    // use an existing anonymous box if possible, otherwise a new one is created
    // and inserted into our list of children in the appropriate position.
    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.
      LayoutBlock* new_box = CreateAnonymousBlock();
      LayoutBox::AddChild(new_box, before_child);
      new_box->AddChild(new_child);
      return;
    }
  }

  LayoutBox::AddChild(new_child, before_child);
}

void LayoutBlock::RemoveLeftoverAnonymousBlock(LayoutBlock* child) {
  DCHECK(child->IsAnonymousBlock());
  DCHECK(!child->ChildrenInline());
  DCHECK_EQ(child->Parent(), this);

  if (child->Continuation())
    return;

  // Promote all the leftover anonymous block's children (to become children of
  // this block instead). We still want to keep the leftover block in the tree
  // for a moment, for notification purposes done further below (flow threads
  // and grids).
  child->MoveAllChildrenTo(this, child->NextSibling());

  // Remove all the information in the flow thread associated with the leftover
  // anonymous block.
  child->RemoveFromLayoutFlowThread();

  // LayoutGrid keeps track of its children, we must notify it about changes in
  // the tree.
  if (child->Parent()->IsLayoutGrid())
    ToLayoutGrid(child->Parent())->DirtyGrid();

  // Now remove the leftover anonymous block from the tree, and destroy it.
  // We'll rip it out manually from the tree before destroying it, because we
  // don't want to trigger any tree adjustments with regards to anonymous blocks
  // (or any other kind of undesired chain-reaction).
  Children()->RemoveChildNode(this, child, false);
  child->Destroy();
}

void LayoutBlock::UpdateAfterLayout() {
  InvalidateStickyConstraints();

  LayoutBox::UpdateAfterLayout();
}

void LayoutBlock::UpdateLayout() {
  DCHECK(!GetScrollableArea() || GetScrollableArea()->GetScrollAnchor());

  LayoutAnalyzer::Scope analyzer(*this);

  bool needs_scroll_anchoring =
      HasOverflowClip() && GetScrollableArea()->ShouldPerformScrollAnchoring();
  if (needs_scroll_anchoring)
    GetScrollableArea()->GetScrollAnchor()->NotifyBeforeLayout();

  // Table cells call UpdateBlockLayout directly, as does
  // PaintLayerScrollableArea for nested scrollbar layouts. Most logic should be
  // in UpdateBlockLayout instead of UpdateLayout.
  UpdateBlockLayout(false);

  // It's safe to check for control clip here, since controls can never be table
  // cells. If we have a lightweight clip, there can never be any overflow from
  // children.
  if (HasControlClip() && overflow_)
    ClearLayoutOverflow();

  height_available_to_children_changed_ = false;
}

bool LayoutBlock::WidthAvailableToChildrenHasChanged() {
  // TODO(robhogan): Does m_widthAvailableToChildrenChanged always get reset
  // when it needs to?
  bool width_available_to_children_has_changed =
      width_available_to_children_changed_;
  width_available_to_children_changed_ = false;

  // If we use border-box sizing, have percentage padding, and our parent has
  // changed width then the width available to our children has changed even
  // though our own width has remained the same.
  // TODO(mstensho): NeedsPreferredWidthsRecalculation() is used here to check
  // if we have percentage padding, which is rather non-obvious. That method
  // returns true in other cases as well.
  width_available_to_children_has_changed |=
      StyleRef().BoxSizing() == EBoxSizing::kBorderBox &&
      NeedsPreferredWidthsRecalculation() &&
      View()->GetLayoutState()->ContainingBlockLogicalWidthChanged();

  return width_available_to_children_has_changed;
}

DISABLE_CFI_PERF
bool LayoutBlock::UpdateLogicalWidthAndColumnWidth() {
  LayoutUnit old_width = LogicalWidth();
  UpdateLogicalWidth();
  return old_width != LogicalWidth() || WidthAvailableToChildrenHasChanged();
}

void LayoutBlock::UpdateBlockLayout(bool) {
  NOTREACHED();
  ClearNeedsLayout();
}

void LayoutBlock::AddOverflowFromChildren() {
  if (ChildrenInline())
    ToLayoutBlockFlow(this)->AddOverflowFromInlineChildren();
  else
    AddOverflowFromBlockChildren();
}

DISABLE_CFI_PERF
void LayoutBlock::ComputeOverflow(LayoutUnit old_client_after_edge, bool) {
  LayoutRect previous_visual_overflow_rect = VisualOverflowRect();
  overflow_.reset();

  AddOverflowFromChildren();
  AddOverflowFromPositionedObjects();

  if (HasOverflowClip()) {
    // When we have overflow clip, propagate the original spillout since it will
    // include collapsed bottom margins and bottom padding. Set the axis we
    // don't care about to be 1, since we want this overflow to always be
    // considered reachable.
    LayoutRect client_rect(NoOverflowRect());
    LayoutRect rect_to_apply;
    if (IsHorizontalWritingMode())
      rect_to_apply = LayoutRect(
          client_rect.X(), client_rect.Y(), LayoutUnit(1),
          (old_client_after_edge - client_rect.Y()).ClampNegativeToZero());
    else
      rect_to_apply = LayoutRect(
          client_rect.X(), client_rect.Y(),
          (old_client_after_edge - client_rect.X()).ClampNegativeToZero(),
          LayoutUnit(1));
    AddLayoutOverflow(rect_to_apply);
    if (HasOverflowModel())
      overflow_->SetLayoutClientAfterEdge(old_client_after_edge);
  }

  AddVisualEffectOverflow();
  AddVisualOverflowFromTheme();

  if (Layer() && VisualOverflowRect() != previous_visual_overflow_rect)
    Layer()->SetNeedsCompositingInputsUpdate();
}

void LayoutBlock::AddOverflowFromBlockChildren() {
  for (LayoutBox* child = FirstChildBox(); child;
       child = child->NextSiblingBox()) {
    if (child->IsFloatingOrOutOfFlowPositioned() || child->IsColumnSpanAll())
      continue;

    // If the child contains inline with outline and continuation, its
    // visual overflow computed during its layout might be inaccurate because
    // the layout of continuations might not be up-to-date at that time.
    // Re-add overflow from inline children to ensure its overflow covers
    // the outline which may enclose continuations.
    if (child->IsLayoutBlockFlow() &&
        ToLayoutBlockFlow(child)->ContainsInlineWithOutlineAndContinuation())
      ToLayoutBlockFlow(child)->AddOverflowFromInlineChildren();

    AddOverflowFromChild(*child);
  }
}

void LayoutBlock::AddOverflowFromPositionedObjects() {
  TrackedLayoutBoxListHashSet* positioned_descendants = PositionedObjects();
  if (!positioned_descendants)
    return;

  for (auto* positioned_object : *positioned_descendants) {
    // Fixed positioned elements don't contribute to layout overflow, since they
    // don't scroll with the content.
    if (positioned_object->StyleRef().GetPosition() != EPosition::kFixed)
      AddOverflowFromChild(*positioned_object,
                           ToLayoutSize(positioned_object->Location()));
  }
}

void LayoutBlock::AddVisualOverflowFromTheme() {
  if (!StyleRef().HasAppearance())
    return;

  IntRect inflated_rect = PixelSnappedBorderBoxRect();
  LayoutTheme::GetTheme().AddVisualOverflow(GetNode(), StyleRef(),
                                            inflated_rect);
  AddSelfVisualOverflow(LayoutRect(inflated_rect));
}

static inline bool ChangeInAvailableLogicalHeightAffectsChild(
    LayoutBlock* parent,
    LayoutBox& child) {
  if (parent->StyleRef().BoxSizing() != EBoxSizing::kBorderBox)
    return false;
  return parent->StyleRef().IsHorizontalWritingMode() &&
         !child.StyleRef().IsHorizontalWritingMode();
}

void LayoutBlock::UpdateBlockChildDirtyBitsBeforeLayout(bool relayout_children,
                                                        LayoutBox& child) {
  if (child.IsOutOfFlowPositioned()) {
    // It's rather useless to mark out-of-flow children at this point. We may
    // not be their containing block (and if we are, it's just pure luck), so
    // this would be the wrong place for it. Furthermore, it would cause trouble
    // for out-of-flow descendants of column spanners, if the containing block
    // is outside the spanner but inside the multicol container.
    return;
  }
  // FIXME: Technically percentage height objects only need a relayout if their
  // percentage isn't going to be turned into an auto value. Add a method to
  // determine this, so that we can avoid the relayout.
  bool has_relative_logical_height =
      child.HasRelativeLogicalHeight() ||
      (child.IsAnonymous() && HasRelativeLogicalHeight()) ||
      child.StretchesToViewport();
  if (relayout_children || (has_relative_logical_height && !IsLayoutView()) ||
      (height_available_to_children_changed_ &&
       ChangeInAvailableLogicalHeightAffectsChild(this, child)) ||
      (child.IsListMarker() && IsListItem() &&
       ToLayoutBlockFlow(this)->ContainsFloats())) {
    child.SetChildNeedsLayout(kMarkOnlyThis);
  }
}

void LayoutBlock::SimplifiedNormalFlowLayout() {
  if (ChildrenInline()) {
    SECURITY_DCHECK(IsLayoutBlockFlow());
    LayoutBlockFlow* block_flow = ToLayoutBlockFlow(this);
    block_flow->SimplifiedNormalFlowInlineLayout();
  } else {
    for (LayoutBox* box = FirstChildBox(); box; box = box->NextSiblingBox()) {
      if (!box->IsOutOfFlowPositioned()) {
        if (box->IsLayoutMultiColumnSpannerPlaceholder())
          ToLayoutMultiColumnSpannerPlaceholder(box)
              ->MarkForLayoutIfObjectInFlowThreadNeedsLayout();
        box->LayoutIfNeeded();
      }
    }
  }
}

bool LayoutBlock::SimplifiedLayout() {
  // Check if we need to do a full layout.
  if (NormalChildNeedsLayout() || SelfNeedsLayout())
    return false;

  // Check that we actually need to do a simplified layout.
  if (!PosChildNeedsLayout() &&
      !(NeedsSimplifiedNormalFlowLayout() || NeedsPositionedMovementLayout()))
    return false;

  {
    // LayoutState needs this deliberate scope to pop before paint invalidation.
    LayoutState state(*this);

    if (NeedsPositionedMovementLayout() &&
        !TryLayoutDoingPositionedMovementOnly())
      return false;

    if (LayoutFlowThread* flow_thread = FlowThreadContainingBlock()) {
      if (!flow_thread->CanSkipLayout(*this))
        return false;
    }

    TextAutosizer::LayoutScope text_autosizer_layout_scope(this);

    // Lay out positioned descendants or objects that just need to recompute
    // overflow.
    if (NeedsSimplifiedNormalFlowLayout())
      SimplifiedNormalFlowLayout();

    // Lay out our positioned objects if our positioned child bit is set.
    // Also, if an absolute position element inside a relative positioned
    // container moves, and the absolute element has a fixed position child
    // neither the fixed element nor its container learn of the movement since
    // posChildNeedsLayout() is only marked as far as the relative positioned
    // container. So if we can have fixed pos objects in our positioned objects
    // list check if any of them are statically positioned and thus need to move
    // with their absolute ancestors.
    bool can_contain_fixed_pos_objects = CanContainFixedPositionObjects();
    if (PosChildNeedsLayout() || NeedsPositionedMovementLayout() ||
        can_contain_fixed_pos_objects)
      LayoutPositionedObjects(
          false, NeedsPositionedMovementLayout()
                     ? kForcedLayoutAfterContainingBlockMoved
                     : (!PosChildNeedsLayout() && can_contain_fixed_pos_objects
                            ? kLayoutOnlyFixedPositionedObjects
                            : kDefaultLayout));

    // Recompute our overflow information.
    // FIXME: We could do better here by computing a temporary overflow object
    // from layoutPositionedObjects and only updating our overflow if we either
    // used to have overflow or if the new temporary object has overflow.
    // For now just always recompute overflow. This is no worse performance-wise
    // than the old code that called rightmostPosition and lowestPosition on
    // every relayout so it's not a regression. computeOverflow expects the
    // bottom edge before we clamp our height. Since this information isn't
    // available during simplifiedLayout, we cache the value in m_overflow.
    LayoutUnit old_client_after_edge = HasOverflowModel()
                                           ? overflow_->LayoutClientAfterEdge()
                                           : ClientLogicalBottom();
    ComputeOverflow(old_client_after_edge, true);
  }

  UpdateAfterLayout();

  ClearNeedsLayout();

  if (LayoutAnalyzer* analyzer = GetFrameView()->GetLayoutAnalyzer())
    analyzer->Increment(LayoutAnalyzer::kLayoutObjectsThatNeedSimplifiedLayout);

  return true;
}

void LayoutBlock::MarkFixedPositionObjectForLayoutIfNeeded(
    LayoutObject* child,
    SubtreeLayoutScope& layout_scope) {
  if (child->StyleRef().GetPosition() != EPosition::kFixed)
    return;

  bool has_static_block_position =
      child->StyleRef().HasStaticBlockPosition(IsHorizontalWritingMode());
  bool has_static_inline_position =
      child->StyleRef().HasStaticInlinePosition(IsHorizontalWritingMode());
  if (!has_static_block_position && !has_static_inline_position)
    return;

  LayoutObject* o = child->Parent();
  while (!o->IsLayoutView() &&
         o->StyleRef().GetPosition() != EPosition::kAbsolute)
    o = o->Parent();
  // The LayoutView is absolute-positioned, but does not move.
  if (o->IsLayoutView())
    return;

  // We must compute child's width and height, but not update them now.
  // The child will update its width and height when it gets laid out, and needs
  // to see them change there.
  LayoutBox* box = ToLayoutBox(child);
  if (has_static_inline_position) {
    LogicalExtentComputedValues computed_values;
    box->ComputeLogicalWidth(computed_values);
    LayoutUnit new_left = computed_values.position_;
    if (new_left != box->LogicalLeft())
      layout_scope.SetChildNeedsLayout(child);
  }
  if (has_static_block_position) {
    LogicalExtentComputedValues computed_values;
    box->ComputeLogicalHeight(computed_values);
    LayoutUnit new_top = computed_values.position_;
    if (new_top != box->LogicalTop())
      layout_scope.SetChildNeedsLayout(child);
  }
}

LayoutUnit LayoutBlock::MarginIntrinsicLogicalWidthForChild(
    const LayoutBox& child) const {
  // A margin has three types: fixed, percentage, and auto (variable).
  // Auto and percentage margins become 0 when computing min/max width.
  // Fixed margins can be added in as is.
  Length margin_left = child.StyleRef().MarginStartUsing(StyleRef());
  Length margin_right = child.StyleRef().MarginEndUsing(StyleRef());
  LayoutUnit margin;
  if (margin_left.IsFixed())
    margin += margin_left.Value();
  if (margin_right.IsFixed())
    margin += margin_right.Value();
  return margin;
}

static bool NeedsLayoutDueToStaticPosition(LayoutBox* child) {
  // When a non-positioned block element moves, it may have positioned children
  // that are implicitly positioned relative to the non-positioned block.
  const ComputedStyle* style = child->Style();
  bool is_horizontal = style->IsHorizontalWritingMode();
  if (style->HasStaticBlockPosition(is_horizontal)) {
    LayoutBox::LogicalExtentComputedValues computed_values;
    LayoutUnit current_logical_top = child->LogicalTop();
    LayoutUnit current_logical_height = child->LogicalHeight();
    child->ComputeLogicalHeight(current_logical_height, current_logical_top,
                                computed_values);
    if (computed_values.position_ != current_logical_top ||
        computed_values.extent_ != current_logical_height)
      return true;
  }
  if (style->HasStaticInlinePosition(is_horizontal)) {
    LayoutBox::LogicalExtentComputedValues computed_values;
    LayoutUnit current_logical_left = child->LogicalLeft();
    LayoutUnit current_logical_width = child->LogicalWidth();
    child->ComputeLogicalWidth(computed_values);
    if (computed_values.position_ != current_logical_left ||
        computed_values.extent_ != current_logical_width)
      return true;
  }
  return false;
}

void LayoutBlock::LayoutPositionedObjects(bool relayout_children,
                                          PositionedLayoutBehavior info) {
  TrackedLayoutBoxListHashSet* positioned_descendants = PositionedObjects();
  if (!positioned_descendants)
    return;

  for (auto* positioned_object : *positioned_descendants) {
    LayoutPositionedObject(positioned_object, relayout_children, info);
  }
}

void LayoutBlock::LayoutPositionedObject(LayoutBox* positioned_object,
                                         bool relayout_children,
                                         PositionedLayoutBehavior info) {
  positioned_object->SetShouldCheckForPaintInvalidation();

  SubtreeLayoutScope layout_scope(*positioned_object);
  // If positionedObject is fixed-positioned and moves with an absolute-
  // positioned ancestor (other than the LayoutView, which cannot move),
  // mark it for layout now.
  MarkFixedPositionObjectForLayoutIfNeeded(positioned_object, layout_scope);
  if (info == kLayoutOnlyFixedPositionedObjects) {
    positioned_object->LayoutIfNeeded();
    return;
  }

  if (!positioned_object->NormalChildNeedsLayout() &&
      (relayout_children || height_available_to_children_changed_ ||
       (!IsLayoutNGBlockFlow() &&
        NeedsLayoutDueToStaticPosition(positioned_object))))
    layout_scope.SetChildNeedsLayout(positioned_object);

  LayoutUnit logical_top_estimate;
  bool is_paginated = View()->GetLayoutState()->IsPaginated();
  bool needs_block_direction_location_set_before_layout =
      is_paginated &&
      positioned_object->GetPaginationBreakability() != kForbidBreaks;
  if (needs_block_direction_location_set_before_layout) {
    // Out-of-flow objects are normally positioned after layout (while in-flow
    // objects are positioned before layout). If the child object is paginated
    // in the same context as we are, estimate its logical top now. We need to
    // know this up-front, to correctly evaluate if we need to mark for
    // relayout, and, if our estimate is correct, we'll even be able to insert
    // correct pagination struts on the first attempt.
    LogicalExtentComputedValues computed_values;
    positioned_object->ComputeLogicalHeight(positioned_object->LogicalHeight(),
                                            positioned_object->LogicalTop(),
                                            computed_values);
    logical_top_estimate = computed_values.position_;
    positioned_object->SetLogicalTop(logical_top_estimate);
  }

  if (!positioned_object->NeedsLayout())
    MarkChildForPaginationRelayoutIfNeeded(*positioned_object, layout_scope);

  // FIXME: We should be able to do a r->setNeedsPositionedMovementLayout()
  // here instead of a full layout. Need to investigate why it does not
  // trigger the correct invalidations in that case. crbug.com/350756
  if (info == kForcedLayoutAfterContainingBlockMoved) {
    positioned_object->SetNeedsLayout(LayoutInvalidationReason::kAncestorMoved,
                                      kMarkOnlyThis);
  }

  positioned_object->LayoutIfNeeded();

  LayoutObject* parent = positioned_object->Parent();
  bool layout_changed = false;
  if (parent->IsFlexibleBox() &&
      ToLayoutFlexibleBox(parent)->SetStaticPositionForPositionedLayout(
          *positioned_object)) {
    // The static position of an abspos child of a flexbox depends on its size
    // (for example, they can be centered). So we may have to reposition the
    // item after layout.
    // TODO(cbiesinger): We could probably avoid a layout here and just
    // reposition?
    positioned_object->ForceChildLayout();
    layout_changed = true;
  }

  // Lay out again if our estimate was wrong.
  if (!layout_changed && needs_block_direction_location_set_before_layout &&
      logical_top_estimate != LogicalTopForChild(*positioned_object))
    positioned_object->ForceChildLayout();

  if (is_paginated)
    UpdateFragmentationInfoForChild(*positioned_object);
}

void LayoutBlock::MarkPositionedObjectsForLayout() {
  if (TrackedLayoutBoxListHashSet* positioned_descendants =
          PositionedObjects()) {
    for (auto* descendant : *positioned_descendants)
      descendant->SetChildNeedsLayout();
  }
}

void LayoutBlock::Paint(const PaintInfo& paint_info) const {
  BlockPainter(*this).Paint(paint_info);
}

void LayoutBlock::PaintChildren(const PaintInfo& paint_info,
                                const LayoutPoint&) const {
  BlockPainter(*this).PaintChildren(paint_info);
}

void LayoutBlock::PaintObject(const PaintInfo& paint_info,
                              const LayoutPoint& paint_offset) const {
  BlockPainter(*this).PaintObject(paint_info, paint_offset);
}

TrackedLayoutBoxListHashSet* LayoutBlock::PositionedObjectsInternal() const {
  return g_positioned_descendants_map ? g_positioned_descendants_map->at(this)
                                      : nullptr;
}

void LayoutBlock::InsertPositionedObject(LayoutBox* o) {
  DCHECK(!IsAnonymousBlock());
  DCHECK_EQ(o->ContainingBlock(), this);

  o->ClearOverrideContainingBlockContentSize();

  if (g_positioned_container_map) {
    auto container_map_it = g_positioned_container_map->find(o);
    if (container_map_it != g_positioned_container_map->end()) {
      if (container_map_it->value == this) {
        DCHECK(HasPositionedObjects());
        DCHECK(PositionedObjects()->Contains(o));
        return;
      }
      RemovePositionedObject(o);
    }
  } else {
    g_positioned_container_map = new TrackedContainerMap;
  }
  g_positioned_container_map->Set(o, this);

  if (!g_positioned_descendants_map)
    g_positioned_descendants_map = new TrackedDescendantsMap;
  TrackedLayoutBoxListHashSet* descendant_set =
      g_positioned_descendants_map->at(this);
  if (!descendant_set) {
    descendant_set = new TrackedLayoutBoxListHashSet;
    g_positioned_descendants_map->Set(this, base::WrapUnique(descendant_set));
  }
  descendant_set->insert(o);

  has_positioned_objects_ = true;
}

void LayoutBlock::RemovePositionedObject(LayoutBox* o) {
  if (!g_positioned_container_map)
    return;

  LayoutBlock* container = g_positioned_container_map->Take(o);
  if (!container)
    return;

  TrackedLayoutBoxListHashSet* positioned_descendants =
      g_positioned_descendants_map->at(container);
  DCHECK(positioned_descendants);
  DCHECK(positioned_descendants->Contains(o));
  positioned_descendants->erase(o);
  if (positioned_descendants->IsEmpty()) {
    g_positioned_descendants_map->erase(container);
    container->has_positioned_objects_ = false;
  }

  // Need to clear the anchor of the positioned object in its container box.
  // The anchors are created in the logical container box, not in the CSS
  // containing block.
  if (LayoutObject* parent = o->Parent())
    parent->MarkContainerNeedsCollectInlines();
}

void LayoutBlock::InvalidatePaint(
    const PaintInvalidatorContext& context) const {
  BlockPaintInvalidator(*this).InvalidatePaint(context);
}

void LayoutBlock::ClearPreviousVisualRects() {
  LayoutBox::ClearPreviousVisualRects();
  BlockPaintInvalidator(*this).ClearPreviousVisualRects();
}

void LayoutBlock::RemovePositionedObjects(
    LayoutObject* o,
    ContainingBlockState containing_block_state) {
  TrackedLayoutBoxListHashSet* positioned_descendants = PositionedObjects();
  if (!positioned_descendants)
    return;

  Vector<LayoutBox*, 16> dead_objects;
  for (auto* positioned_object : *positioned_descendants) {
    if (!o ||
        (positioned_object->IsDescendantOf(o) && o != positioned_object)) {
      if (containing_block_state == kNewContainingBlock) {
        positioned_object->SetChildNeedsLayout(kMarkOnlyThis);

        // The positioned object changing containing block may change paint
        // invalidation container.
        // Invalidate it (including non-compositing descendants) on its original
        // paint invalidation container.
        if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
          // This valid because we need to invalidate based on the current
          // status.
          DisableCompositingQueryAsserts compositing_disabler;
          if (!positioned_object->IsPaintInvalidationContainer())
            ObjectPaintInvalidator(*positioned_object)
                .InvalidatePaintIncludingNonCompositingDescendants();
        }
      }

      // It is parent blocks job to add positioned child to positioned objects
      // list of its containing block
      // Parent layout needs to be invalidated to ensure this happens.
      LayoutObject* p = positioned_object->Parent();
      while (p && !p->IsLayoutBlock())
        p = p->Parent();
      if (p)
        p->SetChildNeedsLayout();

      dead_objects.push_back(positioned_object);
    }
  }

  for (auto* object : dead_objects) {
    DCHECK_EQ(g_positioned_container_map->at(object), this);
    positioned_descendants->erase(object);
    g_positioned_container_map->erase(object);
  }
  if (positioned_descendants->IsEmpty()) {
    g_positioned_descendants_map->erase(this);
    has_positioned_objects_ = false;
  }
}

void LayoutBlock::AddPercentHeightDescendant(LayoutBox* descendant) {
  if (descendant->PercentHeightContainer()) {
    if (descendant->PercentHeightContainer() == this) {
      DCHECK(HasPercentHeightDescendant(descendant));
      return;
    }
    descendant->RemoveFromPercentHeightContainer();
  }
  descendant->SetPercentHeightContainer(this);

  if (!g_percent_height_descendants_map)
    g_percent_height_descendants_map = new TrackedDescendantsMap;
  TrackedLayoutBoxListHashSet* descendant_set =
      g_percent_height_descendants_map->at(this);
  if (!descendant_set) {
    descendant_set = new TrackedLayoutBoxListHashSet;
    g_percent_height_descendants_map->Set(this,
                                          base::WrapUnique(descendant_set));
  }
  descendant_set->insert(descendant);

  has_percent_height_descendants_ = true;
}

void LayoutBlock::RemovePercentHeightDescendant(LayoutBox* descendant) {
  if (TrackedLayoutBoxListHashSet* descendants = PercentHeightDescendants()) {
    descendants->erase(descendant);
    descendant->SetPercentHeightContainer(nullptr);
    if (descendants->IsEmpty()) {
      g_percent_height_descendants_map->erase(this);
      has_percent_height_descendants_ = false;
    }
  }
}

TrackedLayoutBoxListHashSet* LayoutBlock::PercentHeightDescendantsInternal()
    const {
  return g_percent_height_descendants_map
             ? g_percent_height_descendants_map->at(this)
             : nullptr;
}

void LayoutBlock::DirtyForLayoutFromPercentageHeightDescendants(
    SubtreeLayoutScope& layout_scope) {
  TrackedLayoutBoxListHashSet* descendants = PercentHeightDescendants();
  if (!descendants)
    return;

  for (auto* box : *descendants) {
    DCHECK(box->IsDescendantOf(this));
    while (box != this) {
      if (box->NormalChildNeedsLayout())
        break;
      layout_scope.SetChildNeedsLayout(box);
      box = box->ContainingBlock();
      DCHECK(box);
      if (!box)
        break;
    }
  }
}

LayoutUnit LayoutBlock::TextIndentOffset() const {
  LayoutUnit cw;
  if (StyleRef().TextIndent().IsPercentOrCalc())
    cw = ContainingBlock()->AvailableLogicalWidth();
  return MinimumValueForLength(StyleRef().TextIndent(), cw);
}

bool LayoutBlock::IsPointInOverflowControl(
    HitTestResult& result,
    const LayoutPoint& location_in_container,
    const LayoutPoint& accumulated_offset) const {
  if (!ScrollsOverflow())
    return false;

  return Layer()->GetScrollableArea()->HitTestOverflowControls(
      result, RoundedIntPoint(location_in_container -
                              ToLayoutSize(accumulated_offset)));
}

bool LayoutBlock::HitTestOverflowControl(
    HitTestResult& result,
    const HitTestLocation& location_in_container,
    const LayoutPoint& adjusted_location) {
  if (VisibleToHitTestRequest(result.GetHitTestRequest()) &&
      IsPointInOverflowControl(result, location_in_container.Point(),
                               adjusted_location)) {
    UpdateHitTestResult(result, location_in_container.Point() -
                                    ToLayoutSize(adjusted_location));
    // FIXME: isPointInOverflowControl() doesn't handle rect-based tests yet.
    if (result.AddNodeToListBasedTestResult(
            NodeForHitTest(), location_in_container) == kStopHitTesting)
      return true;
  }
  return false;
}

bool LayoutBlock::HitTestChildren(HitTestResult& result,
                                  const HitTestLocation& location_in_container,
                                  const LayoutPoint& accumulated_offset,
                                  HitTestAction hit_test_action) {
  DCHECK(!ChildrenInline());
  LayoutPoint scrolled_offset(HasOverflowClip()
                                  ? accumulated_offset - ScrolledContentOffset()
                                  : accumulated_offset);
  HitTestAction child_hit_test = hit_test_action;
  if (hit_test_action == kHitTestChildBlockBackgrounds)
    child_hit_test = kHitTestChildBlockBackground;
  for (LayoutBox* child = LastChildBox(); child;
       child = child->PreviousSiblingBox()) {
    LayoutPoint child_point =
        FlipForWritingModeForChild(child, scrolled_offset);
    if (!child->HasSelfPaintingLayer() && !child->IsFloating() &&
        !child->IsColumnSpanAll() &&
        child->NodeAtPoint(result, location_in_container, child_point,
                           child_hit_test)) {
      UpdateHitTestResult(
          result, FlipForWritingMode(ToLayoutPoint(
                      location_in_container.Point() - accumulated_offset)));
      return true;
    }
  }

  return false;
}

Position LayoutBlock::PositionForBox(InlineBox* box, bool start) const {
  if (!box)
    return Position();

  if (!box->GetLineLayoutItem().NonPseudoNode())
    return Position::EditingPositionOf(
        NonPseudoNode(), start ? CaretMinOffset() : CaretMaxOffset());

  if (!box->IsInlineTextBox())
    return Position::EditingPositionOf(
        box->GetLineLayoutItem().NonPseudoNode(),
        start ? box->GetLineLayoutItem().CaretMinOffset()
              : box->GetLineLayoutItem().CaretMaxOffset());

  InlineTextBox* text_box = ToInlineTextBox(box);
  return Position::EditingPositionOf(
      box->GetLineLayoutItem().NonPseudoNode(),
      start ? text_box->Start() : text_box->Start() + text_box->Len());
}

static inline bool IsEditingBoundary(const LayoutObject* ancestor,
                                     LineLayoutBox child) {
  DCHECK(!ancestor || ancestor->NonPseudoNode());
  DCHECK(child);
  DCHECK(child.NonPseudoNode());
  return !ancestor || !ancestor->Parent() ||
         (ancestor->HasLayer() && ancestor->Parent()->IsLayoutView()) ||
         HasEditableStyle(*ancestor->NonPseudoNode()) ==
             HasEditableStyle(*child.NonPseudoNode());
}

// FIXME: This function should go on LayoutObject.
// Then all cases in which positionForPoint recurs could call this instead to
// prevent crossing editable boundaries. This would require many tests.
PositionWithAffinity LayoutBlock::PositionForPointRespectingEditingBoundaries(
    LineLayoutBox child,
    const LayoutPoint& point_in_parent_coordinates) const {
  LayoutPoint child_location = child.Location();
  if (child.IsInFlowPositioned())
    child_location += child.OffsetForInFlowPosition();

  // FIXME: This is wrong if the child's writing-mode is different from the
  // parent's.
  LayoutPoint point_in_child_coordinates(
      ToLayoutPoint(point_in_parent_coordinates - child_location));

  // If this is an anonymous layoutObject, we just recur normally
  const Node* child_node = child.NonPseudoNode();
  if (!child_node)
    return child.PositionForPoint(point_in_child_coordinates);

  // Otherwise, first make sure that the editability of the parent and child
  // agree. If they don't agree, then we return a visible position just before
  // or after the child
  const LayoutObject* ancestor = this;
  while (ancestor && !ancestor->NonPseudoNode())
    ancestor = ancestor->Parent();

  // If we can't find an ancestor to check editability on, or editability is
  // unchanged, we recur like normal
  if (IsEditingBoundary(ancestor, child))
    return child.PositionForPoint(point_in_child_coordinates);

  // Otherwise return before or after the child, depending on if the click was
  // to the logical left or logical right of the child
  LayoutUnit child_middle = LogicalWidthForChildSize(child.Size()) / 2;
  LayoutUnit logical_left = IsHorizontalWritingMode()
                                ? point_in_child_coordinates.X()
                                : point_in_child_coordinates.Y();
  if (logical_left < child_middle)
    return ancestor->CreatePositionWithAffinity(child_node->NodeIndex());
  return ancestor->CreatePositionWithAffinity(child_node->NodeIndex() + 1,
                                              TextAffinity::kUpstream);
}

PositionWithAffinity LayoutBlock::PositionForPointIfOutsideAtomicInlineLevel(
    const LayoutPoint& point) const {
  DCHECK(IsAtomicInlineLevel());
  // FIXME: This seems wrong when the object's writing-mode doesn't match the
  // line's writing-mode.
  LayoutUnit point_logical_left =
      IsHorizontalWritingMode() ? point.X() : point.Y();
  LayoutUnit point_logical_top =
      IsHorizontalWritingMode() ? point.Y() : point.X();

  const bool is_ltr = IsLtr(ResolvedDirection());
  if (point_logical_left < 0) {
    return CreatePositionWithAffinity(is_ltr ? CaretMinOffset()
                                             : CaretMaxOffset());
  }
  if (point_logical_left >= LogicalWidth()) {
    return CreatePositionWithAffinity(is_ltr ? CaretMaxOffset()
                                             : CaretMinOffset());
  }
  if (point_logical_top < 0)
    return CreatePositionWithAffinity(CaretMinOffset());
  if (point_logical_top >= LogicalHeight())
    return CreatePositionWithAffinity(CaretMaxOffset());
  return PositionWithAffinity();
}

static inline bool IsChildHitTestCandidate(LayoutBox* box) {
  return box->Size().Height() &&
         box->StyleRef().Visibility() == EVisibility::kVisible &&
         !box->IsOutOfFlowPositioned() && !box->IsLayoutFlowThread();
}

PositionWithAffinity LayoutBlock::PositionForPoint(
    const LayoutPoint& point) const {
  if (IsTable())
    return LayoutBox::PositionForPoint(point);

  if (IsAtomicInlineLevel()) {
    PositionWithAffinity position =
        PositionForPointIfOutsideAtomicInlineLevel(point);
    if (!position.IsNull())
      return position;
  }

  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();

  DCHECK(!ChildrenInline());

  LayoutBox* last_candidate_box = LastChildBox();
  while (last_candidate_box && !IsChildHitTestCandidate(last_candidate_box))
    last_candidate_box = last_candidate_box->PreviousSiblingBox();

  bool blocks_are_flipped = StyleRef().IsFlippedBlocksWritingMode();
  if (last_candidate_box) {
    if (point_in_logical_contents.Y() >
            LogicalTopForChild(*last_candidate_box) ||
        (!blocks_are_flipped && point_in_logical_contents.Y() ==
                                    LogicalTopForChild(*last_candidate_box)))
      return PositionForPointRespectingEditingBoundaries(
          LineLayoutBox(last_candidate_box), point_in_contents);

    for (LayoutBox* child_box = FirstChildBox(); child_box;
         child_box = child_box->NextSiblingBox()) {
      if (!IsChildHitTestCandidate(child_box))
        continue;
      LayoutUnit child_logical_bottom =
          LogicalTopForChild(*child_box) + LogicalHeightForChild(*child_box);
      if (child_box->IsLayoutBlockFlow())
          child_logical_bottom += ToLayoutBlockFlow(child_box)->LowestFloatLogicalBottom();

      // We hit child if our click is above the bottom of its padding box (like
      // IE6/7 and FF3).
      if (point_in_logical_contents.Y() < child_logical_bottom ||
          (blocks_are_flipped &&
           point_in_logical_contents.Y() == child_logical_bottom)) {
        return PositionForPointRespectingEditingBoundaries(
            LineLayoutBox(child_box), point_in_contents);
      }
    }
  }

  // We only get here if there are no hit test candidate children below the
  // click.
  return LayoutBox::PositionForPoint(point);
}

void LayoutBlock::OffsetForContents(LayoutPoint& offset) const {
  offset = FlipForWritingMode(offset);

  if (HasOverflowClip())
    offset += LayoutSize(ScrolledContentOffset());

  offset = FlipForWritingMode(offset);
}

void LayoutBlock::ScrollbarsChanged(bool horizontal_scrollbar_changed,
                                    bool vertical_scrollbar_changed,
                                    ScrollbarChangeContext context) {
  width_available_to_children_changed_ |= vertical_scrollbar_changed;
  height_available_to_children_changed_ |= horizontal_scrollbar_changed;
}

void LayoutBlock::ComputeIntrinsicLogicalWidths(
    LayoutUnit& min_logical_width,
    LayoutUnit& max_logical_width) const {
  // Size-contained elements don't consider their contents for preferred sizing.
  if (ShouldApplySizeContainment())
    return;

  if (ChildrenInline()) {
    // FIXME: Remove this const_cast.
    ToLayoutBlockFlow(const_cast<LayoutBlock*>(this))
        ->ComputeInlinePreferredLogicalWidths(min_logical_width,
                                              max_logical_width);
  } else {
    ComputeBlockPreferredLogicalWidths(min_logical_width, max_logical_width);
  }

  max_logical_width = std::max(min_logical_width, max_logical_width);

  if (IsHTMLMarqueeElement(GetNode()) &&
      ToHTMLMarqueeElement(GetNode())->IsHorizontal())
    min_logical_width = LayoutUnit();

  if (IsTableCell()) {
    Length table_cell_width = ToLayoutTableCell(this)->StyleOrColLogicalWidth();
    if (table_cell_width.IsFixed() && table_cell_width.Value() > 0)
      max_logical_width = std::max(min_logical_width,
                                   AdjustContentBoxLogicalWidthForBoxSizing(
                                       LayoutUnit(table_cell_width.Value())));
  }

  int scrollbar_width = ScrollbarLogicalWidth();
  max_logical_width += scrollbar_width;
  min_logical_width += scrollbar_width;
}

DISABLE_CFI_PERF
void LayoutBlock::ComputePreferredLogicalWidths() {
  DCHECK(PreferredLogicalWidthsDirty());

  min_preferred_logical_width_ = LayoutUnit();
  max_preferred_logical_width_ = LayoutUnit();

  // FIXME: The isFixed() calls here should probably be checking for isSpecified
  // since you should be able to use percentage, calc or viewport relative
  // values for width.
  const ComputedStyle& style_to_use = StyleRef();
  if (!IsTableCell() && style_to_use.LogicalWidth().IsFixed() &&
      style_to_use.LogicalWidth().Value() >= 0 &&
      !(IsDeprecatedFlexItem() && !style_to_use.LogicalWidth().IntValue()))
    min_preferred_logical_width_ = max_preferred_logical_width_ =
        AdjustContentBoxLogicalWidthForBoxSizing(
            LayoutUnit(style_to_use.LogicalWidth().Value()));
  else
    ComputeIntrinsicLogicalWidths(min_preferred_logical_width_,
                                  max_preferred_logical_width_);

  if (style_to_use.LogicalMaxWidth().IsFixed()) {
    max_preferred_logical_width_ =
        std::min(max_preferred_logical_width_,
                 AdjustContentBoxLogicalWidthForBoxSizing(
                     LayoutUnit(style_to_use.LogicalMaxWidth().Value())));
    min_preferred_logical_width_ =
        std::min(min_preferred_logical_width_,
                 AdjustContentBoxLogicalWidthForBoxSizing(
                     LayoutUnit(style_to_use.LogicalMaxWidth().Value())));
  }

  if (style_to_use.LogicalMinWidth().IsFixed() &&
      style_to_use.LogicalMinWidth().Value() > 0) {
    max_preferred_logical_width_ =
        std::max(max_preferred_logical_width_,
                 AdjustContentBoxLogicalWidthForBoxSizing(
                     LayoutUnit(style_to_use.LogicalMinWidth().Value())));
    min_preferred_logical_width_ =
        std::max(min_preferred_logical_width_,
                 AdjustContentBoxLogicalWidthForBoxSizing(
                     LayoutUnit(style_to_use.LogicalMinWidth().Value())));
  }

  LayoutUnit border_and_padding = BorderAndPaddingLogicalWidth();
  DCHECK_GE(border_and_padding, LayoutUnit());
  min_preferred_logical_width_ += border_and_padding;
  max_preferred_logical_width_ += border_and_padding;

  // Table layout uses integers, ceil the preferred widths to ensure that they
  // can contain the contents.
  if (IsTableCell()) {
    min_preferred_logical_width_ =
        LayoutUnit(min_preferred_logical_width_.Ceil());
    max_preferred_logical_width_ =
        LayoutUnit(max_preferred_logical_width_.Ceil());
  }

  ClearPreferredLogicalWidthsDirty();
}

void LayoutBlock::ComputeBlockPreferredLogicalWidths(
    LayoutUnit& min_logical_width,
    LayoutUnit& max_logical_width) const {
  const ComputedStyle& style_to_use = StyleRef();
  bool nowrap = style_to_use.WhiteSpace() == EWhiteSpace::kNowrap;

  LayoutObject* child = FirstChild();
  LayoutBlock* containing_block = ContainingBlock();
  LayoutUnit float_left_width, float_right_width;
  while (child) {
    // Positioned children don't affect the min/max width. Spanners only affect
    // the min/max width of the multicol container, not the flow thread.
    if (child->IsOutOfFlowPositioned() || child->IsColumnSpanAll()) {
      child = child->NextSibling();
      continue;
    }

    if (child->IsBox() &&
        ToLayoutBox(child)->NeedsPreferredWidthsRecalculation()) {
      // We don't really know whether the containing block of this child did
      // change or is going to change size. However, this is our only
      // opportunity to make sure that it gets its min/max widths calculated.
      child->SetPreferredLogicalWidthsDirty();
    }

    scoped_refptr<const ComputedStyle> child_style = child->Style();
    if (child->IsFloating() ||
        (child->IsBox() && ToLayoutBox(child)->AvoidsFloats())) {
      LayoutUnit float_total_width = float_left_width + float_right_width;
      if (child_style->Clear() == EClear::kBoth ||
          child_style->Clear() == EClear::kLeft) {
        max_logical_width = std::max(float_total_width, max_logical_width);
        float_left_width = LayoutUnit();
      }
      if (child_style->Clear() == EClear::kBoth ||
          child_style->Clear() == EClear::kRight) {
        max_logical_width = std::max(float_total_width, max_logical_width);
        float_right_width = LayoutUnit();
      }
    }

    // A margin basically has three types: fixed, percentage, and auto
    // (variable).
    // Auto and percentage margins simply become 0 when computing min/max width.
    // Fixed margins can be added in as is.
    Length start_margin_length = child_style->MarginStartUsing(style_to_use);
    Length end_margin_length = child_style->MarginEndUsing(style_to_use);
    LayoutUnit margin;
    LayoutUnit margin_start;
    LayoutUnit margin_end;
    if (start_margin_length.IsFixed())
      margin_start += start_margin_length.Value();
    if (end_margin_length.IsFixed())
      margin_end += end_margin_length.Value();
    margin = margin_start + margin_end;

    LayoutUnit child_min_preferred_logical_width,
        child_max_preferred_logical_width;
    ComputeChildPreferredLogicalWidths(*child,
                                       child_min_preferred_logical_width,
                                       child_max_preferred_logical_width);

    LayoutUnit w = child_min_preferred_logical_width + margin;
    min_logical_width = std::max(w, min_logical_width);

    // IE ignores tables for calculation of nowrap. Makes some sense.
    if (nowrap && !child->IsTable())
      max_logical_width = std::max(w, max_logical_width);

    w = child_max_preferred_logical_width + margin;

    if (!child->IsFloating()) {
      if (child->IsBox() && ToLayoutBox(child)->AvoidsFloats()) {
        // Determine a left and right max value based off whether or not the
        // floats can fit in the margins of the object. For negative margins, we
        // will attempt to overlap the float if the negative margin is smaller
        // than the float width.
        bool ltr = containing_block
                       ? containing_block->StyleRef().IsLeftToRightDirection()
                       : style_to_use.IsLeftToRightDirection();
        LayoutUnit margin_logical_left = ltr ? margin_start : margin_end;
        LayoutUnit margin_logical_right = ltr ? margin_end : margin_start;
        LayoutUnit max_left =
            margin_logical_left > 0
                ? std::max(float_left_width, margin_logical_left)
                : float_left_width + margin_logical_left;
        LayoutUnit max_right =
            margin_logical_right > 0
                ? std::max(float_right_width, margin_logical_right)
                : float_right_width + margin_logical_right;
        w = child_max_preferred_logical_width + max_left + max_right;
        w = std::max(w, float_left_width + float_right_width);
      } else {
        max_logical_width =
            std::max(float_left_width + float_right_width, max_logical_width);
      }
      float_left_width = float_right_width = LayoutUnit();
    }

    if (child->IsFloating()) {
      if (child_style->Floating() == EFloat::kLeft)
        float_left_width += w;
      else
        float_right_width += w;
    } else {
      max_logical_width = std::max(w, max_logical_width);
    }

    child = child->NextSibling();
  }

  // Always make sure these values are non-negative.
  min_logical_width = min_logical_width.ClampNegativeToZero();
  max_logical_width = max_logical_width.ClampNegativeToZero();

  max_logical_width =
      std::max(float_left_width + float_right_width, max_logical_width);
}

DISABLE_CFI_PERF
void LayoutBlock::ComputeChildPreferredLogicalWidths(
    LayoutObject& child,
    LayoutUnit& min_preferred_logical_width,
    LayoutUnit& max_preferred_logical_width) const {
  if (child.IsBox() &&
      child.IsHorizontalWritingMode() != IsHorizontalWritingMode()) {
    // If the child is an orthogonal flow, child's height determines the width,
    // but the height is not available until layout.
    // https://drafts.csswg.org/css-writing-modes/#orthogonal-shrink-to-fit
    if (!child.NeedsLayout()) {
      min_preferred_logical_width = max_preferred_logical_width =
          ToLayoutBox(child).LogicalHeight();
      return;
    }
    min_preferred_logical_width = max_preferred_logical_width =
        ToLayoutBox(child).ComputeLogicalHeightWithoutLayout();
    return;
  }
  min_preferred_logical_width = child.MinPreferredLogicalWidth();
  max_preferred_logical_width = child.MaxPreferredLogicalWidth();

  // For non-replaced blocks if the inline size is min|max-content or a definite
  // size the min|max-content contribution is that size plus border, padding and
  // margin https://drafts.csswg.org/css-sizing/#block-intrinsic
  if (child.IsLayoutBlock()) {
    const Length& computed_inline_size = child.StyleRef().LogicalWidth();
    if (computed_inline_size.IsMaxContent())
      min_preferred_logical_width = max_preferred_logical_width;
    else if (computed_inline_size.IsMinContent())
      max_preferred_logical_width = min_preferred_logical_width;
  }
}

bool LayoutBlock::HasLineIfEmpty() const {
  if (!GetNode())
    return false;

  if (IsRootEditableElement(*GetNode()))
    return true;

  if (GetNode()->IsShadowRoot() &&
      IsHTMLInputElement(ToShadowRoot(GetNode())->host()))
    return true;

  return false;
}

LayoutUnit LayoutBlock::LineHeight(bool first_line,
                                   LineDirectionMode direction,
                                   LinePositionMode line_position_mode) const {
  // Inline blocks are replaced elements. Otherwise, just pass off to
  // the base class.  If we're being queried as though we're the root line
  // box, then the fact that we're an inline-block is irrelevant, and we behave
  // just like a block.
  if (IsAtomicInlineLevel() && line_position_mode == kPositionOnContainingLine)
    return LayoutBox::LineHeight(first_line, direction, line_position_mode);

  const ComputedStyle& style = StyleRef(
      first_line && GetDocument().GetStyleEngine().UsesFirstLineRules());
  return LayoutUnit(style.ComputedLineHeight());
}

LayoutUnit LayoutBlock::BeforeMarginInLineDirection(
    LineDirectionMode direction) const {
  // InlineFlowBox::placeBoxesInBlockDirection will flip lines in
  // case of verticalLR mode, so we can assume verticalRL for now.
  return direction == kHorizontalLine ? MarginTop() : MarginRight();
}

LayoutUnit LayoutBlock::BaselinePosition(
    FontBaseline baseline_type,
    bool first_line,
    LineDirectionMode direction,
    LinePositionMode line_position_mode) const {
  // Inline blocks are replaced elements. Otherwise, just pass off to
  // the base class.  If we're being queried as though we're the root line
  // box, then the fact that we're an inline-block is irrelevant, and we behave
  // just like a block.
  if (IsInline() && line_position_mode == kPositionOnContainingLine) {
    // For "leaf" theme objects, let the theme decide what the baseline position
    // is.
    // FIXME: Might be better to have a custom CSS property instead, so that if
    //        the theme is turned off, checkboxes/radios will still have decent
    //        baselines.
    // FIXME: Need to patch form controls to deal with vertical lines.
    if (StyleRef().HasAppearance() &&
        !LayoutTheme::GetTheme().IsControlContainer(StyleRef().Appearance())) {
      return Size().Height() + MarginTop() +
             LayoutTheme::GetTheme().BaselinePositionAdjustment(StyleRef());
    }

    LayoutUnit baseline_pos = (IsWritingModeRoot() && !IsRubyRun())
                                  ? LayoutUnit(-1)
                                  : InlineBlockBaseline(direction);

    if (IsDeprecatedFlexibleBox()) {
      // Historically, we did this check for all baselines. But we can't
      // remove this code from deprecated flexbox, because it effectively
      // breaks -webkit-line-clamp, which is used in the wild -- we would
      // calculate the baseline as if -webkit-line-clamp wasn't used.
      // For simplicity, we use this for all uses of deprecated flexbox.
      LayoutUnit bottom_of_content =
          direction == kHorizontalLine
              ? Size().Height() - BorderBottom() - PaddingBottom() -
                    HorizontalScrollbarHeight()
              : Size().Width() - BorderLeft() - PaddingLeft() -
                    VerticalScrollbarWidth();
      if (baseline_pos > bottom_of_content)
        baseline_pos = LayoutUnit(-1);
    }
    if (baseline_pos != -1)
      return BeforeMarginInLineDirection(direction) + baseline_pos;

    return LayoutBox::BaselinePosition(baseline_type, first_line, direction,
                                       line_position_mode);
  }

  // If we're not replaced, we'll only get called with
  // PositionOfInteriorLineBoxes.
  // Note that inline-block counts as replaced here.
  DCHECK_EQ(line_position_mode, kPositionOfInteriorLineBoxes);

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

  const FontMetrics& font_metrics = font_data->GetFontMetrics();
  return LayoutUnit((font_metrics.Ascent(baseline_type) +
                     (LineHeight(first_line, direction, line_position_mode) -
                      font_metrics.Height()) /
                         2)
                        .ToInt());
}

LayoutUnit LayoutBlock::MinLineHeightForReplacedObject(
    bool is_first_line,
    LayoutUnit replaced_height) const {
  if (!GetDocument().InNoQuirksMode() && replaced_height)
    return replaced_height;

  return std::max<LayoutUnit>(
      replaced_height,
      LineHeight(is_first_line,
                 IsHorizontalWritingMode() ? kHorizontalLine : kVerticalLine,
                 kPositionOfInteriorLineBoxes));
}

// TODO(mstensho): Figure out if all of this baseline code is needed here, or if
// it should be moved down to LayoutBlockFlow. LayoutDeprecatedFlexibleBox and
// LayoutGrid lack baseline calculation overrides, so the code is here just for
// them. Just walking the block children in logical order seems rather wrong for
// those two layout modes, though.

LayoutUnit LayoutBlock::FirstLineBoxBaseline() const {
  DCHECK(!ChildrenInline());
  if (IsWritingModeRoot() && !IsRubyRun())
    return LayoutUnit(-1);

  for (LayoutBox* curr = FirstChildBox(); curr; curr = curr->NextSiblingBox()) {
    if (!curr->IsFloatingOrOutOfFlowPositioned()) {
      LayoutUnit result = curr->FirstLineBoxBaseline();
      if (result != -1) {
        // Translate to our coordinate space.
        return curr->LogicalTop() + result;
      }
    }
  }
  return LayoutUnit(-1);
}

bool LayoutBlock::UseLogicalBottomMarginEdgeForInlineBlockBaseline() 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.
  return (!StyleRef().IsOverflowVisible() &&
          !ShouldIgnoreOverflowPropertyForInlineBlockBaseline()) ||
         ShouldApplySizeContainment();
}

LayoutUnit LayoutBlock::InlineBlockBaseline(
    LineDirectionMode line_direction) const {
  DCHECK(!ChildrenInline());
  if (UseLogicalBottomMarginEdgeForInlineBlockBaseline()) {
    // We are not calling LayoutBox::baselinePosition here because the caller
    // should add the margin-top/margin-right, not us.
    return line_direction == kHorizontalLine ? Size().Height() + MarginBottom()
                                             : Size().Width() + MarginLeft();
  }

  if (IsWritingModeRoot() && !IsRubyRun())
    return LayoutUnit(-1);

  bool have_normal_flow_child = false;
  for (LayoutBox* curr = LastChildBox(); curr;
       curr = curr->PreviousSiblingBox()) {
    if (!curr->IsFloatingOrOutOfFlowPositioned()) {
      have_normal_flow_child = true;
      LayoutUnit result = curr->InlineBlockBaseline(line_direction);
      if (result != -1) {
        // Translate to our coordinate space.
        return curr->LogicalTop() + result;
      }
    }
  }
  const SimpleFontData* font_data = FirstLineStyle()->GetFont().PrimaryFont();
  if (font_data && !have_normal_flow_child && HasLineIfEmpty()) {
    const FontMetrics& font_metrics = font_data->GetFontMetrics();
    return LayoutUnit(
        (font_metrics.Ascent() +
         (LineHeight(true, line_direction, kPositionOfInteriorLineBoxes) -
          font_metrics.Height()) /
             2 +
         (line_direction == kHorizontalLine ? BorderTop() + PaddingTop()
                                            : BorderRight() + PaddingRight()))
            .ToInt());
  }
  return LayoutUnit(-1);
}

const LayoutBlock* LayoutBlock::EnclosingFirstLineStyleBlock() const {
  const LayoutBlock* first_line_block = this;
  bool has_pseudo = false;
  while (true) {
    has_pseudo =
        first_line_block->StyleRef().HasPseudoStyle(kPseudoIdFirstLine);
    if (has_pseudo)
      break;
    LayoutObject* parent_block = first_line_block->Parent();
    if (first_line_block->IsAtomicInlineLevel() ||
        first_line_block->IsFloatingOrOutOfFlowPositioned() || !parent_block ||
        !parent_block->BehavesLikeBlockContainer())
      break;
    SECURITY_DCHECK(parent_block->IsLayoutBlock());
    if (ToLayoutBlock(parent_block)->FirstChild() != first_line_block)
      break;
    first_line_block = ToLayoutBlock(parent_block);
  }

  if (!has_pseudo)
    return nullptr;

  return first_line_block;
}

LayoutBlockFlow* LayoutBlock::NearestInnerBlockWithFirstLine() {
  if (ChildrenInline())
    return ToLayoutBlockFlow(this);
  for (LayoutObject* child = FirstChild();
       child && !child->IsFloatingOrOutOfFlowPositioned() &&
       child->IsLayoutBlockFlow();
       child = ToLayoutBlock(child)->FirstChild()) {
    if (child->ChildrenInline())
      return ToLayoutBlockFlow(child);
  }
  return nullptr;
}

// An inline-block uses its inlineBox as the inlineBoxWrapper,
// so the firstChild() is nullptr if the only child is an empty inline-block.
inline bool LayoutBlock::IsInlineBoxWrapperActuallyChild() const {
  return IsInlineBlockOrInlineTable() && !Size().IsEmpty() && GetNode() &&
         EditingIgnoresContent(*GetNode());
}

bool LayoutBlock::ShouldPaintCursorCaret() const {
  return GetFrame()->Selection().ShouldPaintCaret(*this);
}

bool LayoutBlock::ShouldPaintDragCaret() const {
  return GetFrame()->GetPage()->GetDragCaret().ShouldPaintCaret(*this);
}

LayoutRect LayoutBlock::LocalCaretRect(
    const InlineBox* inline_box,
    int caret_offset,
    LayoutUnit* extra_width_to_end_of_line) const {
  // Do the normal calculation in most cases.
  if ((FirstChild() && !FirstChild()->IsPseudoElement()) ||
      IsInlineBoxWrapperActuallyChild())
    return LayoutBox::LocalCaretRect(inline_box, caret_offset,
                                     extra_width_to_end_of_line);

  LayoutRect caret_rect =
      LocalCaretRectForEmptyElement(Size().Width(), TextIndentOffset());

  if (extra_width_to_end_of_line)
    *extra_width_to_end_of_line = Size().Width() - caret_rect.MaxX();

  return caret_rect;
}

void LayoutBlock::AddOutlineRects(
    Vector<LayoutRect>& rects,
    const LayoutPoint& additional_offset,
    IncludeBlockVisualOverflowOrNot include_block_overflows) const {
  if (!IsAnonymous())  // For anonymous blocks, the children add outline rects.
    rects.push_back(LayoutRect(additional_offset, Size()));

  if (include_block_overflows == kIncludeBlockVisualOverflow &&
      !HasOverflowClip() && !HasControlClip()) {
    AddOutlineRectsForNormalChildren(rects, additional_offset,
                                     include_block_overflows);
    if (TrackedLayoutBoxListHashSet* positioned_objects = PositionedObjects()) {
      for (auto* box : *positioned_objects)
        AddOutlineRectsForDescendant(*box, rects, additional_offset,
                                     include_block_overflows);
    }
  }
}

LayoutBox* LayoutBlock::CreateAnonymousBoxWithSameTypeAs(
    const LayoutObject* parent) const {
  return CreateAnonymousWithParentAndDisplay(parent, StyleRef().Display());
}

void LayoutBlock::PaginatedContentWasLaidOut(
    LayoutUnit logical_bottom_offset_after_pagination) {
  if (LayoutFlowThread* flow_thread = FlowThreadContainingBlock())
    flow_thread->ContentWasLaidOut(OffsetFromLogicalTopOfFirstPage() +
                                   logical_bottom_offset_after_pagination);
}

LayoutUnit LayoutBlock::CollapsedMarginBeforeForChild(
    const LayoutBox& child) const {
  // If the child has the same directionality as we do, then we can just return
  // its collapsed margin.
  if (!child.IsWritingModeRoot())
    return child.CollapsedMarginBefore();

  // The child has a different directionality.  If the child is parallel, then
  // it's just flipped relative to us.  We can use the collapsed margin for the
  // opposite edge.
  if (child.IsHorizontalWritingMode() == IsHorizontalWritingMode())
    return child.CollapsedMarginAfter();

  // 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.
  return MarginBeforeForChild(child);
}

LayoutUnit LayoutBlock::CollapsedMarginAfterForChild(
    const LayoutBox& child) const {
  // If the child has the same directionality as we do, then we can just return
  // its collapsed margin.
  if (!child.IsWritingModeRoot())
    return child.CollapsedMarginAfter();

  // The child has a different directionality.  If the child is parallel, then
  // it's just flipped relative to us.  We can use the collapsed margin for the
  // opposite edge.
  if (child.IsHorizontalWritingMode() == IsHorizontalWritingMode())
    return child.CollapsedMarginBefore();

  // The child is perpendicular to us, which means its margins don't collapse
  // but are on the "logical left/right" side of the child box. We can just
  // return the raw margin in this case.
  return MarginAfterForChild(child);
}

bool LayoutBlock::HasMarginBeforeQuirk(const LayoutBox* child) const {
  // If the child has the same directionality as we do, then we can just return
  // its margin quirk.
  if (!child->IsWritingModeRoot()) {
    return child->IsLayoutBlock() ? ToLayoutBlock(child)->HasMarginBeforeQuirk()
                                  : child->StyleRef().HasMarginBeforeQuirk();
  }

  // The child has a different directionality. If the child is parallel, then
  // it's just flipped relative to us. We can use the opposite edge.
  if (child->IsHorizontalWritingMode() == IsHorizontalWritingMode()) {
    return child->IsLayoutBlock() ? ToLayoutBlock(child)->HasMarginAfterQuirk()
                                  : child->StyleRef().HasMarginAfterQuirk();
  }

  // The child is perpendicular to us and box sides are never quirky in
  // html.css, and we don't really care about whether or not authors specified
  // quirky ems, since they're an implementation detail.
  return false;
}

bool LayoutBlock::HasMarginAfterQuirk(const LayoutBox* child) const {
  // If the child has the same directionality as we do, then we can just return
  // its margin quirk.
  if (!child->IsWritingModeRoot()) {
    return child->IsLayoutBlock() ? ToLayoutBlock(child)->HasMarginAfterQuirk()
                                  : child->StyleRef().HasMarginAfterQuirk();
  }

  // The child has a different directionality. If the child is parallel, then
  // it's just flipped relative to us. We can use the opposite edge.
  if (child->IsHorizontalWritingMode() == IsHorizontalWritingMode()) {
    return child->IsLayoutBlock() ? ToLayoutBlock(child)->HasMarginBeforeQuirk()
                                  : child->StyleRef().HasMarginBeforeQuirk();
  }

  // The child is perpendicular to us and box sides are never quirky in
  // html.css, and we don't really care about whether or not authors specified
  // quirky ems, since they're an implementation detail.
  return false;
}

const char* LayoutBlock::GetName() const {
  NOTREACHED();
  return "LayoutBlock";
}

LayoutBlock* LayoutBlock::CreateAnonymousWithParentAndDisplay(
    const LayoutObject* parent,
    EDisplay display) {
  // TODO(layout-dev): Do we need to convert all our inline displays to block
  // type in the anonymous logic?
  const EDisplay new_display =
      display == EDisplay::kFlex || display == EDisplay::kInlineFlex
          ? EDisplay::kFlex
          : EDisplay::kBlock;
  scoped_refptr<ComputedStyle> new_style =
      ComputedStyle::CreateAnonymousStyleWithDisplay(parent->StyleRef(),
                                                     new_display);
  parent->UpdateAnonymousChildStyle(nullptr, *new_style);
  LayoutBlock* layout_block;
  if (new_display == EDisplay::kFlex) {
    layout_block = LayoutObjectFactory::CreateFlexibleBox(parent->GetDocument(),
                                                          *new_style);
  } else {
    DCHECK_EQ(new_display, EDisplay::kBlock);
    layout_block =
        LayoutObjectFactory::CreateBlockFlow(parent->GetDocument(), *new_style);
  }
  layout_block->SetDocumentForAnonymous(&parent->GetDocument());
  layout_block->SetStyle(std::move(new_style));
  return layout_block;
}

bool LayoutBlock::RecalcNormalFlowChildOverflowIfNeeded(
    LayoutObject* layout_object) {
  if (layout_object->IsOutOfFlowPositioned())
    return false;
  return layout_object->RecalcOverflowAfterStyleChange();
}

bool LayoutBlock::RecalcChildOverflowAfterStyleChange() {
  DCHECK(!IsTable());
  DCHECK(ChildNeedsOverflowRecalcAfterStyleChange());
  ClearChildNeedsOverflowRecalcAfterStyleChange();

  bool children_overflow_changed = false;

  if (ChildrenInline()) {
    SECURITY_DCHECK(IsLayoutBlockFlow());
    children_overflow_changed =
        ToLayoutBlockFlow(this)->RecalcInlineChildrenOverflowAfterStyleChange();
  } else {
    for (LayoutBox* box = FirstChildBox(); box; box = box->NextSiblingBox()) {
      if (RecalcNormalFlowChildOverflowIfNeeded(box))
        children_overflow_changed = true;
    }
  }

  return RecalcPositionedDescendantsOverflowAfterStyleChange() ||
         children_overflow_changed;
}

bool LayoutBlock::RecalcPositionedDescendantsOverflowAfterStyleChange() {
  bool children_overflow_changed = false;

  TrackedLayoutBoxListHashSet* positioned_descendants = PositionedObjects();
  if (!positioned_descendants)
    return children_overflow_changed;

  for (auto* box : *positioned_descendants) {
    if (box->RecalcOverflowAfterStyleChange())
      children_overflow_changed = true;
  }
  return children_overflow_changed;
}

bool LayoutBlock::RecalcOverflowAfterStyleChange() {
  bool children_overflow_changed = false;
  if (ChildNeedsOverflowRecalcAfterStyleChange())
    children_overflow_changed = RecalcChildOverflowAfterStyleChange();

  bool self_needs_overflow_recalc = SelfNeedsOverflowRecalcAfterStyleChange();
  if (!self_needs_overflow_recalc && !children_overflow_changed)
    return false;

  return RecalcSelfOverflowAfterStyleChange();
}

bool LayoutBlock::RecalcSelfOverflowAfterStyleChange() {
  bool self_needs_overflow_recalc = SelfNeedsOverflowRecalcAfterStyleChange();
  ClearSelfNeedsOverflowRecalcAfterStyleChange();
  // If the current block needs layout, overflow will be recalculated during
  // layout time anyway. We can safely exit here.
  if (NeedsLayout())
    return false;

  LayoutUnit old_client_after_edge = HasOverflowModel()
                                         ? overflow_->LayoutClientAfterEdge()
                                         : ClientLogicalBottom();
  ComputeOverflow(old_client_after_edge, true);

  if (HasOverflowClip())
    Layer()->GetScrollableArea()->UpdateAfterOverflowRecalc();

  return !HasOverflowClip() || self_needs_overflow_recalc;
}

// Called when a positioned object moves but doesn't necessarily change size.
// A simplified layout is attempted that just updates the object's position.
// If the size does change, the object remains dirty.
bool LayoutBlock::TryLayoutDoingPositionedMovementOnly() {
  LayoutUnit old_width = LogicalWidth();
  LogicalExtentComputedValues computed_values;
  LogicalExtentAfterUpdatingLogicalWidth(LogicalTop(), computed_values);
  // If we shrink to fit our width may have changed, so we still need full
  // layout.
  if (old_width != computed_values.extent_)
    return false;
  SetLogicalWidth(computed_values.extent_);
  SetLogicalLeft(computed_values.position_);
  SetMarginStart(computed_values.margins_.start_);
  SetMarginEnd(computed_values.margins_.end_);

  LayoutUnit old_height = LogicalHeight();
  LayoutUnit old_intrinsic_content_logical_height =
      IntrinsicContentLogicalHeight();

  SetIntrinsicContentLogicalHeight(ContentLogicalHeight());
  ComputeLogicalHeight(old_height, LogicalTop(), computed_values);

  if (old_height != computed_values.extent_ &&
      (HasPercentHeightDescendants() || IsFlexibleBox())) {
    SetIntrinsicContentLogicalHeight(old_intrinsic_content_logical_height);
    return false;
  }

  SetLogicalHeight(computed_values.extent_);
  SetLogicalTop(computed_values.position_);
  SetMarginBefore(computed_values.margins_.before_);
  SetMarginAfter(computed_values.margins_.after_);

  return true;
}

#if DCHECK_IS_ON()
void LayoutBlock::CheckPositionedObjectsNeedLayout() {
  if (!g_positioned_descendants_map)
    return;

  if (TrackedLayoutBoxListHashSet* positioned_descendant_set =
          PositionedObjects()) {
    TrackedLayoutBoxListHashSet::const_iterator end =
        positioned_descendant_set->end();
    for (TrackedLayoutBoxListHashSet::const_iterator it =
             positioned_descendant_set->begin();
         it != end; ++it) {
      LayoutBox* curr_box = *it;
      DCHECK(!curr_box->NeedsLayout());
    }
  }
}

#endif

LayoutUnit LayoutBlock::AvailableLogicalHeightForPercentageComputation() const {
  LayoutUnit available_height(-1);

  // For anonymous blocks that are skipped during percentage height calculation,
  // we consider them to have an indefinite height.
  if (SkipContainingBlockForPercentHeightCalculation(this))
    return available_height;

  const ComputedStyle& style = StyleRef();

  // A positioned element that specified both top/bottom or that specifies
  // height should be treated as though it has a height explicitly specified
  // that can be used for any percentage computations.
  bool is_out_of_flow_positioned_with_specified_height =
      IsOutOfFlowPositioned() &&
      (!style.LogicalHeight().IsAuto() ||
       (!style.LogicalTop().IsAuto() && !style.LogicalBottom().IsAuto()));

  LayoutUnit stretched_flex_height(-1);
  if (IsFlexItem()) {
    const LayoutFlexibleBox* flex_box = ToLayoutFlexibleBox(Parent());
    if (flex_box->UseOverrideLogicalHeightForPerentageResolution(*this))
      stretched_flex_height = OverrideContentLogicalHeight();
  }
  if (stretched_flex_height != LayoutUnit(-1)) {
    available_height = stretched_flex_height;
  } else if (IsGridItem() && HasOverrideLogicalHeight()) {
    available_height = OverrideContentLogicalHeight();
  } else if (style.LogicalHeight().IsFixed()) {
    LayoutUnit content_box_height = AdjustContentBoxLogicalHeightForBoxSizing(
        style.LogicalHeight().Value());
    available_height = std::max(
        LayoutUnit(),
        ConstrainContentBoxLogicalHeightByMinMax(
            content_box_height - ScrollbarLogicalHeight(), LayoutUnit(-1)));
  } else if (style.LogicalHeight().IsPercentOrCalc() &&
             !is_out_of_flow_positioned_with_specified_height) {
    LayoutUnit height_with_scrollbar =
        ComputePercentageLogicalHeight(style.LogicalHeight());
    if (height_with_scrollbar != -1) {
      LayoutUnit content_box_height_with_scrollbar =
          AdjustContentBoxLogicalHeightForBoxSizing(height_with_scrollbar);
      // We need to adjust for min/max height because this method does not
      // handle the min/max of the current block, its caller does. So the
      // return value from the recursive call will not have been adjusted
      // yet.
      LayoutUnit content_box_height = ConstrainContentBoxLogicalHeightByMinMax(
          content_box_height_with_scrollbar - ScrollbarLogicalHeight(),
          LayoutUnit(-1));
      available_height = std::max(LayoutUnit(), content_box_height);
    }
  } else if (is_out_of_flow_positioned_with_specified_height) {
    // Don't allow this to affect the block' size() member variable, since this
    // can get called while the block is still laying out its kids.
    LogicalExtentComputedValues computed_values;
    ComputeLogicalHeight(LogicalHeight(), LayoutUnit(), computed_values);
    available_height = computed_values.extent_ -
                       BorderAndPaddingLogicalHeight() -
                       ScrollbarLogicalHeight();
  } else if (IsLayoutView()) {
    available_height = View()->ViewLogicalHeightForPercentages();
  }

  return available_height;
}

bool LayoutBlock::HasDefiniteLogicalHeight() const {
  return AvailableLogicalHeightForPercentageComputation() != LayoutUnit(-1);
}

bool LayoutBlock::NeedsPreferredWidthsRecalculation() const {
  return (HasRelativeLogicalHeight() && StyleRef().LogicalWidth().IsAuto()) ||
         LayoutBox::NeedsPreferredWidthsRecalculation();
}

}  // namespace blink
