/*
 * 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 "core/layout/LayoutBlock.h"

#include "core/HTMLNames.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/StyleEngine.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/editing/DragCaretController.h"
#include "core/editing/EditingUtilities.h"
#include "core/editing/FrameSelection.h"
#include "core/frame/FrameView.h"
#include "core/frame/Settings.h"
#include "core/html/HTMLMarqueeElement.h"
#include "core/layout/HitTestLocation.h"
#include "core/layout/HitTestResult.h"
#include "core/layout/LayoutAnalyzer.h"
#include "core/layout/LayoutFlexibleBox.h"
#include "core/layout/LayoutFlowThread.h"
#include "core/layout/LayoutGrid.h"
#include "core/layout/LayoutMultiColumnSpannerPlaceholder.h"
#include "core/layout/LayoutTableCell.h"
#include "core/layout/LayoutTheme.h"
#include "core/layout/LayoutView.h"
#include "core/layout/TextAutosizer.h"
#include "core/layout/api/LineLayoutBox.h"
#include "core/layout/api/LineLayoutItem.h"
#include "core/layout/line/InlineTextBox.h"
#include "core/page/Page.h"
#include "core/paint/BlockPaintInvalidator.h"
#include "core/paint/BlockPainter.h"
#include "core/paint/ObjectPaintInvalidator.h"
#include "core/paint/PaintLayer.h"
#include "core/style/ComputedStyle.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "wtf/PtrUtil.h"
#include "wtf/StdLibExtras.h"
#include <memory>

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* gPositionedDescendantsMap = nullptr;
static TrackedContainerMap* gPositionedContainerMap = 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* gPercentHeightDescendantsMap = nullptr;

LayoutBlock::LayoutBlock(ContainerNode* node)
    : LayoutBox(node),
      m_hasMarginBeforeQuirk(false),
      m_hasMarginAfterQuirk(false),
      m_beingDestroyed(false),
      m_hasMarkupTruncation(false),
      m_widthAvailableToChildrenChanged(false),
      m_heightAvailableToChildrenChanged(false),
      m_isSelfCollapsing(false),
      m_descendantsWithFloatsMarkedForLayout(false),
      m_hasPositionedObjects(false),
      m_hasPercentHeightDescendants(false) {
  // LayoutBlockFlow calls setChildrenInline(true).
  // By default, subclasses do not have inline children.
}

void LayoutBlock::removeFromGlobalMaps() {
  if (hasPositionedObjects()) {
    std::unique_ptr<TrackedLayoutBoxListHashSet> descendants =
        gPositionedDescendantsMap->take(this);
    ASSERT(!descendants->isEmpty());
    for (LayoutBox* descendant : *descendants) {
      ASSERT(gPositionedContainerMap->get(descendant) == this);
      gPositionedContainerMap->remove(descendant);
    }
  }
  if (hasPercentHeightDescendants()) {
    std::unique_ptr<TrackedLayoutBoxListHashSet> descendants =
        gPercentHeightDescendantsMap->take(this);
    ASSERT(!descendants->isEmpty());
    for (LayoutBox* descendant : *descendants) {
      ASSERT(descendant->percentHeightContainer() == this);
      descendant->setPercentHeightContainer(nullptr);
    }
  }
}

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

void LayoutBlock::willBeDestroyed() {
  if (!documentBeingDestroyed() && parent())
    parent()->dirtyLinesFromChangedChild(this);

  if (TextAutosizer* textAutosizer = document().textAutosizer())
    textAutosizer->destroy(this);

  LayoutBox::willBeDestroyed();
}

void LayoutBlock::styleWillChange(StyleDifference diff,
                                  const ComputedStyle& newStyle) {
  const ComputedStyle* oldStyle = style();

  setIsAtomicInlineLevel(newStyle.isDisplayInlineType());

  if (oldStyle && parent()) {
    bool oldStyleContainsFixedPosition =
        oldStyle->canContainFixedPositionObjects();
    bool oldStyleContainsAbsolutePosition =
        oldStyleContainsFixedPosition ||
        oldStyle->canContainAbsolutePositionObjects();
    bool newStyleContainsFixedPosition =
        newStyle.canContainFixedPositionObjects();
    bool newStyleContainsAbsolutePosition =
        newStyleContainsFixedPosition ||
        newStyle.canContainAbsolutePositionObjects();

    if ((oldStyleContainsFixedPosition && !newStyleContainsFixedPosition) ||
        (oldStyleContainsAbsolutePosition &&
         !newStyleContainsAbsolutePosition)) {
      // 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, NewContainingBlock);
    }
    if (!oldStyleContainsAbsolutePosition && newStyleContainsAbsolutePosition) {
      // 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, NewContainingBlock);
    }
    if (!oldStyleContainsFixedPosition && newStyleContainsFixedPosition) {
      // Remove our fixed positioned descendants from their current containing
      // block.
      // They will be inserted into our positioned objects list during layout.
      if (LayoutBlock* cb = containerForFixedPosition())
        cb->removePositionedObjects(this, NewContainingBlock);
    }
  }

  LayoutBox::styleWillChange(diff, newStyle);
}

enum LogicalExtent { LogicalWidth, LogicalHeight };
static bool borderOrPaddingLogicalDimensionChanged(
    const ComputedStyle& oldStyle,
    const ComputedStyle& newStyle,
    LogicalExtent logicalExtent) {
  if (newStyle.isHorizontalWritingMode() == (logicalExtent == LogicalWidth)) {
    return oldStyle.borderLeftWidth() != newStyle.borderLeftWidth() ||
           oldStyle.borderRightWidth() != newStyle.borderRightWidth() ||
           oldStyle.paddingLeft() != newStyle.paddingLeft() ||
           oldStyle.paddingRight() != newStyle.paddingRight();
  }

  return oldStyle.borderTopWidth() != newStyle.borderTopWidth() ||
         oldStyle.borderBottomWidth() != newStyle.borderBottomWidth() ||
         oldStyle.paddingTop() != newStyle.paddingTop() ||
         oldStyle.paddingBottom() != newStyle.paddingBottom();
}

void LayoutBlock::styleDidChange(StyleDifference diff,
                                 const ComputedStyle* oldStyle) {
  LayoutBox::styleDidChange(diff, oldStyle);

  const ComputedStyle& newStyle = styleRef();

  if (oldStyle && parent()) {
    if (oldStyle->position() != newStyle.position() &&
        newStyle.position() != StaticPosition) {
      // 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, NewContainingBlock);
        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* textAutosizer = document().textAutosizer())
    textAutosizer->record(this);

  propagateStyleToAnonymousChildren();

  // 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.
  m_widthAvailableToChildrenChanged |=
      oldStyle && diff.needsFullLayout() && needsLayout() &&
      borderOrPaddingLogicalDimensionChanged(*oldStyle, newStyle, LogicalWidth);
  m_heightAvailableToChildrenChanged |= oldStyle && diff.needsFullLayout() &&
                                        needsLayout() &&
                                        borderOrPaddingLogicalDimensionChanged(
                                            *oldStyle, newStyle, LogicalHeight);
}

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

  bool shouldClipOverflow =
      !styleRef().isOverflowVisible() && allowsOverflowClip();
  if (shouldClipOverflow != hasOverflowClip()) {
    if (!shouldClipOverflow)
      getScrollableArea()->invalidateAllStickyConstraints();
    setMayNeedPaintInvalidationSubtree();
  }
  setHasOverflowClip(shouldClipOverflow);
}

bool LayoutBlock::allowsOverflowClip() const {
  // If overflow has been propagated to the viewport, it has no effect here.
  return node() != document().viewportDefiningElement();
}

void LayoutBlock::addChildBeforeDescendant(LayoutObject* newChild,
                                           LayoutObject* beforeDescendant) {
  ASSERT(beforeDescendant->parent() != this);
  LayoutObject* beforeDescendantContainer = beforeDescendant->parent();
  while (beforeDescendantContainer->parent() != this)
    beforeDescendantContainer = beforeDescendantContainer->parent();
  ASSERT(beforeDescendantContainer);

  // 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.
  RELEASE_ASSERT(beforeDescendantContainer->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 (beforeDescendantContainer->isAnonymousBlock()
      // Full screen layoutObjects and full screen placeholders act as anonymous
      // blocks, not tables:
      || beforeDescendantContainer->isLayoutFullScreen() ||
      beforeDescendantContainer->isLayoutFullScreenPlaceholder()) {
    // Insert the child into the anonymous block box instead of here.
    if (newChild->isInline() || newChild->isFloatingOrOutOfFlowPositioned() ||
        beforeDescendant->parent()->slowFirstChild() != beforeDescendant)
      beforeDescendant->parent()->addChild(newChild, beforeDescendant);
    else
      addChild(newChild, beforeDescendant->parent());
    return;
  }

  ASSERT(beforeDescendantContainer->isTable());
  if (newChild->isTablePart()) {
    // Insert into the anonymous table.
    beforeDescendantContainer->addChild(newChild, beforeDescendant);
    return;
  }

  LayoutObject* beforeChild = splitAnonymousBoxesAroundChild(beforeDescendant);

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

  addChild(newChild, beforeChild);
}

void LayoutBlock::addChild(LayoutObject* newChild, LayoutObject* beforeChild) {
  if (beforeChild && beforeChild->parent() != this) {
    addChildBeforeDescendant(newChild, beforeChild);
    return;
  }

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

  if (newChild->isInline() || newChild->isFloatingOrOutOfFlowPositioned()) {
    // 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* afterChild =
        beforeChild ? beforeChild->previousSibling() : lastChild();

    if (afterChild && afterChild->isAnonymousBlock()) {
      afterChild->addChild(newChild);
      return;
    }

    if (newChild->isInline()) {
      // No suitable existing anonymous box - create a new one.
      LayoutBlock* newBox = createAnonymousBlock();
      LayoutBox::addChild(newBox, beforeChild);
      newBox->addChild(newChild);
      return;
    }
  }

  LayoutBox::addChild(newChild, beforeChild);
}

void LayoutBlock::removeLeftoverAnonymousBlock(LayoutBlock* child) {
  ASSERT(child->isAnonymousBlock());
  ASSERT(!child->childrenInline());
  ASSERT(child->parent() == this);

  if (child->continuation())
    return;

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

  // Update our scroll information if we're overflow:auto/scroll/hidden now that
  // we know if we overflow or not.
  if (hasOverflowClip())
    layer()->getScrollableArea()->updateAfterLayout();
}

void LayoutBlock::layout() {
  DCHECK(!getScrollableArea() || getScrollableArea()->scrollAnchor());

  LayoutAnalyzer::Scope analyzer(*this);

  bool needsScrollAnchoring =
      hasOverflowClip() && getScrollableArea()->shouldPerformScrollAnchoring();
  if (needsScrollAnchoring)
    getScrollableArea()->scrollAnchor()->save();

  // Table cells call layoutBlock directly, so don't add any logic here.  Put
  // code into layoutBlock().
  layoutBlock(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() && m_overflow)
    clearLayoutOverflow();

  invalidateBackgroundObscurationStatus();

  // If clamping is delayed, we will restore in
  // PaintLayerScrollableArea::clampScrollPositionsAfterLayout.
  // Restoring during the intermediate layout may clamp the scroller to the
  // wrong bounds.
  bool clampingDelayed = PaintLayerScrollableArea::
      DelayScrollPositionClampScope::clampingIsDelayed();
  if (needsScrollAnchoring && !clampingDelayed)
    getScrollableArea()->scrollAnchor()->restore();

  m_heightAvailableToChildrenChanged = false;
}

bool LayoutBlock::widthAvailableToChildrenHasChanged() {
  // TODO(robhogan): Does m_widthAvailableToChildrenChanged always get reset
  // when it needs to?
  bool widthAvailableToChildrenHasChanged = m_widthAvailableToChildrenChanged;
  m_widthAvailableToChildrenChanged = 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.
  widthAvailableToChildrenHasChanged |=
      style()->boxSizing() == BoxSizingBorderBox &&
      needsPreferredWidthsRecalculation() &&
      view()->layoutState()->containingBlockLogicalWidthChanged();

  return widthAvailableToChildrenHasChanged;
}

DISABLE_CFI_PERF
bool LayoutBlock::updateLogicalWidthAndColumnWidth() {
  LayoutUnit oldWidth = logicalWidth();
  updateLogicalWidth();
  return oldWidth != logicalWidth() || widthAvailableToChildrenHasChanged();
}

void LayoutBlock::layoutBlock(bool) {
  ASSERT_NOT_REACHED();
  clearNeedsLayout();
}

void LayoutBlock::addOverflowFromChildren() {
  if (childrenInline())
    toLayoutBlockFlow(this)->addOverflowFromInlineChildren();
  else
    addOverflowFromBlockChildren();
}

DISABLE_CFI_PERF
void LayoutBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool) {
  m_overflow.reset();

  // Add overflow from children.
  addOverflowFromChildren();

  // Add in the overflow from positioned objects.
  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 clientRect(noOverflowRect());
    LayoutRect rectToApply;
    if (isHorizontalWritingMode())
      rectToApply = LayoutRect(
          clientRect.x(), clientRect.y(), LayoutUnit(1),
          (oldClientAfterEdge - clientRect.y()).clampNegativeToZero());
    else
      rectToApply = LayoutRect(
          clientRect.x(), clientRect.y(),
          (oldClientAfterEdge - clientRect.x()).clampNegativeToZero(),
          LayoutUnit(1));
    addLayoutOverflow(rectToApply);
    if (hasOverflowModel())
      m_overflow->setLayoutClientAfterEdge(oldClientAfterEdge);
  }

  addVisualEffectOverflow();
  addVisualOverflowFromTheme();

  // An enclosing composited layer will need to update its bounds if we now
  // overflow it.
  PaintLayer* layer = enclosingLayer();
  if (!needsLayout() && layer->hasCompositedLayerMapping() &&
      !layer->visualRect().contains(visualOverflowRect()))
    layer->setNeedsCompositingInputsUpdate();
}

void LayoutBlock::addOverflowFromBlockChildren() {
  for (LayoutBox* child = firstChildBox(); child;
       child = child->nextSiblingBox()) {
    if (!child->isFloatingOrOutOfFlowPositioned() && !child->isColumnSpanAll())
      addOverflowFromChild(child);
  }
}

void LayoutBlock::addOverflowFromPositionedObjects() {
  TrackedLayoutBoxListHashSet* positionedDescendants = positionedObjects();
  if (!positionedDescendants)
    return;

  for (auto* positionedObject : *positionedDescendants) {
    // Fixed positioned elements don't contribute to layout overflow, since they
    // don't scroll with the content.
    if (positionedObject->style()->position() != FixedPosition)
      addOverflowFromChild(positionedObject,
                           toLayoutSize(positionedObject->location()));
  }
}

void LayoutBlock::addVisualOverflowFromTheme() {
  if (!style()->hasAppearance())
    return;

  IntRect inflatedRect = pixelSnappedBorderBoxRect();
  LayoutTheme::theme().addVisualOverflow(*this, inflatedRect);
  addSelfVisualOverflow(LayoutRect(inflatedRect));
}

DISABLE_CFI_PERF
bool LayoutBlock::createsNewFormattingContext() const {
  return isInlineBlockOrInlineTable() || isFloatingOrOutOfFlowPositioned() ||
         hasOverflowClip() || isFlexItemIncludingDeprecated() ||
         style()->specifiesColumns() || isLayoutFlowThread() || isTableCell() ||
         isTableCaption() || isFieldset() || isWritingModeRoot() ||
         isDocumentElement() || isColumnSpanAll() || isGridItem() ||
         style()->containsPaint() || style()->containsLayout();
}

static inline bool changeInAvailableLogicalHeightAffectsChild(
    LayoutBlock* parent,
    LayoutBox& child) {
  if (parent->style()->boxSizing() != BoxSizingBorderBox)
    return false;
  return parent->style()->isHorizontalWritingMode() &&
         !child.style()->isHorizontalWritingMode();
}

void LayoutBlock::updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren,
                                                        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 hasRelativeLogicalHeight =
      child.hasRelativeLogicalHeight() ||
      (child.isAnonymous() && this->hasRelativeLogicalHeight()) ||
      child.stretchesToViewport();
  if (relayoutChildren || (hasRelativeLogicalHeight && !isLayoutView()) ||
      (m_heightAvailableToChildrenChanged &&
       changeInAvailableLogicalHeightAffectsChild(this, child))) {
    child.setChildNeedsLayout(MarkOnlyThis);

    // If the child has percentage padding or an embedded content box, we also
    // need to invalidate the childs pref widths.
    if (child.needsPreferredWidthsRecalculation())
      child.setPreferredLogicalWidthsDirty(MarkOnlyThis);
  }
}

void LayoutBlock::simplifiedNormalFlowLayout() {
  if (childrenInline()) {
    ASSERT_WITH_SECURITY_IMPLICATION(isLayoutBlockFlow());
    LayoutBlockFlow* blockFlow = toLayoutBlockFlow(this);
    blockFlow->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, locationOffset());

    if (needsPositionedMovementLayout() &&
        !tryLayoutDoingPositionedMovementOnly())
      return false;

    if (LayoutFlowThread* flowThread = flowThreadContainingBlock()) {
      if (!flowThread->canSkipLayout(*this))
        return false;
    }

    TextAutosizer::LayoutScope textAutosizerLayoutScope(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 canContainFixedPosObjects = canContainFixedPositionObjects();
    if (posChildNeedsLayout() || needsPositionedMovementLayout() ||
        canContainFixedPosObjects)
      layoutPositionedObjects(
          false, needsPositionedMovementLayout()
                     ? ForcedLayoutAfterContainingBlockMoved
                     : (!posChildNeedsLayout() && canContainFixedPosObjects
                            ? LayoutOnlyFixedPositionedObjects
                            : DefaultLayout));

    // 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 oldClientAfterEdge = hasOverflowModel()
                                        ? m_overflow->layoutClientAfterEdge()
                                        : clientLogicalBottom();
    computeOverflow(oldClientAfterEdge, true);
  }

  updateLayerTransformAfterLayout();

  updateAfterLayout();

  clearNeedsLayout();

  if (LayoutAnalyzer* analyzer = frameView()->layoutAnalyzer())
    analyzer->increment(LayoutAnalyzer::LayoutObjectsThatNeedSimplifiedLayout);

  return true;
}

void LayoutBlock::markFixedPositionObjectForLayoutIfNeeded(
    LayoutObject* child,
    SubtreeLayoutScope& layoutScope) {
  if (child->style()->position() != FixedPosition)
    return;

  bool hasStaticBlockPosition =
      child->style()->hasStaticBlockPosition(isHorizontalWritingMode());
  bool hasStaticInlinePosition =
      child->style()->hasStaticInlinePosition(isHorizontalWritingMode());
  if (!hasStaticBlockPosition && !hasStaticInlinePosition)
    return;

  LayoutObject* o = child->parent();
  while (o && !o->isLayoutView() && o->style()->position() != AbsolutePosition)
    o = o->parent();
  if (o->style()->position() != AbsolutePosition)
    return;

  LayoutBox* box = toLayoutBox(child);
  if (hasStaticInlinePosition) {
    LogicalExtentComputedValues computedValues;
    box->computeLogicalWidth(computedValues);
    LayoutUnit newLeft = computedValues.m_position;
    if (newLeft != box->logicalLeft())
      layoutScope.setChildNeedsLayout(child);
  } else if (hasStaticBlockPosition) {
    LayoutUnit oldTop = box->logicalTop();
    box->updateLogicalHeight();
    if (box->logicalTop() != oldTop)
      layoutScope.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 marginLeft = child.style()->marginStartUsing(style());
  Length marginRight = child.style()->marginEndUsing(style());
  LayoutUnit margin;
  if (marginLeft.isFixed())
    margin += marginLeft.value();
  if (marginRight.isFixed())
    margin += marginRight.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 isHorizontal = style->isHorizontalWritingMode();
  if (style->hasStaticBlockPosition(isHorizontal)) {
    LayoutBox::LogicalExtentComputedValues computedValues;
    LayoutUnit currentLogicalTop = child->logicalTop();
    LayoutUnit currentLogicalHeight = child->logicalHeight();
    child->computeLogicalHeight(currentLogicalHeight, currentLogicalTop,
                                computedValues);
    if (computedValues.m_position != currentLogicalTop ||
        computedValues.m_extent != currentLogicalHeight)
      return true;
  }
  if (style->hasStaticInlinePosition(isHorizontal)) {
    LayoutBox::LogicalExtentComputedValues computedValues;
    LayoutUnit currentLogicalLeft = child->logicalLeft();
    LayoutUnit currentLogicalWidth = child->logicalWidth();
    child->computeLogicalWidth(computedValues);
    if (computedValues.m_position != currentLogicalLeft ||
        computedValues.m_extent != currentLogicalWidth)
      return true;
  }
  return false;
}

void LayoutBlock::layoutPositionedObjects(bool relayoutChildren,
                                          PositionedLayoutBehavior info) {
  TrackedLayoutBoxListHashSet* positionedDescendants = positionedObjects();
  if (!positionedDescendants)
    return;

  bool isPaginated = view()->layoutState()->isPaginated();

  for (auto* positionedObject : *positionedDescendants) {
    positionedObject->setMayNeedPaintInvalidation();

    SubtreeLayoutScope layoutScope(*positionedObject);
    // A fixed position element with an absolute positioned ancestor has no way
    // of knowing if the latter has changed position. So if this is a fixed
    // position element, mark it for layout if it has an abspos ancestor and
    // needs to move with that ancestor, i.e. it has static position.
    markFixedPositionObjectForLayoutIfNeeded(positionedObject, layoutScope);
    if (info == LayoutOnlyFixedPositionedObjects) {
      positionedObject->layoutIfNeeded();
      continue;
    }

    if (!positionedObject->normalChildNeedsLayout() &&
        (relayoutChildren || m_heightAvailableToChildrenChanged ||
         needsLayoutDueToStaticPosition(positionedObject)))
      layoutScope.setChildNeedsLayout(positionedObject);

    // If relayoutChildren is set and the child has percentage padding or an
    // embedded content box, we also need to invalidate the childs pref widths.
    if (relayoutChildren &&
        positionedObject->needsPreferredWidthsRecalculation())
      positionedObject->setPreferredLogicalWidthsDirty(MarkOnlyThis);

    LayoutUnit logicalTopEstimate;
    bool needsBlockDirectionLocationSetBeforeLayout =
        isPaginated &&
        positionedObject->getPaginationBreakability() != ForbidBreaks;
    if (needsBlockDirectionLocationSetBeforeLayout) {
      // 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 computedValues;
      positionedObject->computeLogicalHeight(positionedObject->logicalHeight(),
                                             positionedObject->logicalTop(),
                                             computedValues);
      logicalTopEstimate = computedValues.m_position;
      positionedObject->setLogicalTop(logicalTopEstimate);
    }

    if (!positionedObject->needsLayout())
      markChildForPaginationRelayoutIfNeeded(*positionedObject, layoutScope);

    // 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 == ForcedLayoutAfterContainingBlockMoved)
      positionedObject->setNeedsLayout(LayoutInvalidationReason::AncestorMoved,
                                       MarkOnlyThis);

    positionedObject->layoutIfNeeded();

    LayoutObject* parent = positionedObject->parent();
    bool layoutChanged = false;
    if (parent->isFlexibleBox() &&
        toLayoutFlexibleBox(parent)->setStaticPositionForPositionedLayout(
            *positionedObject)) {
      // 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?
      positionedObject->forceChildLayout();
      layoutChanged = true;
    }

    // Lay out again if our estimate was wrong.
    if (!layoutChanged && needsBlockDirectionLocationSetBeforeLayout &&
        logicalTopEstimate != logicalTopForChild(*positionedObject))
      positionedObject->forceChildLayout();
  }
}

void LayoutBlock::markPositionedObjectsForLayout() {
  if (TrackedLayoutBoxListHashSet* positionedDescendants =
          positionedObjects()) {
    for (auto* descendant : *positionedDescendants)
      descendant->setChildNeedsLayout();
  }
}

void LayoutBlock::paint(const PaintInfo& paintInfo,
                        const LayoutPoint& paintOffset) const {
  BlockPainter(*this).paint(paintInfo, paintOffset);
}

void LayoutBlock::paintChildren(const PaintInfo& paintInfo,
                                const LayoutPoint& paintOffset) const {
  BlockPainter(*this).paintChildren(paintInfo, paintOffset);
}

void LayoutBlock::paintObject(const PaintInfo& paintInfo,
                              const LayoutPoint& paintOffset) const {
  BlockPainter(*this).paintObject(paintInfo, paintOffset);
}

bool LayoutBlock::isSelectionRoot() const {
  if (isPseudoElement())
    return false;
  ASSERT(node() || isAnonymous());

  // FIXME: Eventually tables should have to learn how to fill gaps between
  // cells, at least in simple non-spanning cases.
  if (isTable())
    return false;

  if (isBody() || isDocumentElement() || hasOverflowClip() || isPositioned() ||
      isFloating() || isTableCell() || isInlineBlockOrInlineTable() ||
      hasTransformRelatedProperty() || hasReflection() || hasMask() ||
      isWritingModeRoot() || isLayoutFlowThread() ||
      isFlexItemIncludingDeprecated())
    return true;

  if (view() && view()->selectionStart()) {
    Node* startElement = view()->selectionStart()->node();
    if (startElement && rootEditableElement(*startElement) == node())
      return true;
  }

  return false;
}

LayoutUnit LayoutBlock::blockDirectionOffset(
    const LayoutSize& offsetFromBlock) const {
  return isHorizontalWritingMode() ? offsetFromBlock.height()
                                   : offsetFromBlock.width();
}

LayoutUnit LayoutBlock::inlineDirectionOffset(
    const LayoutSize& offsetFromBlock) const {
  return isHorizontalWritingMode() ? offsetFromBlock.width()
                                   : offsetFromBlock.height();
}

LayoutUnit LayoutBlock::logicalLeftSelectionOffset(const LayoutBlock* rootBlock,
                                                   LayoutUnit position) const {
  // The border can potentially be further extended by our containingBlock().
  if (rootBlock != this)
    return containingBlock()->logicalLeftSelectionOffset(
        rootBlock, position + logicalTop());
  return logicalLeftOffsetForContent();
}

LayoutUnit LayoutBlock::logicalRightSelectionOffset(
    const LayoutBlock* rootBlock,
    LayoutUnit position) const {
  // The border can potentially be further extended by our containingBlock().
  if (rootBlock != this)
    return containingBlock()->logicalRightSelectionOffset(
        rootBlock, position + logicalTop());
  return logicalRightOffsetForContent();
}

LayoutBlock* LayoutBlock::blockBeforeWithinSelectionRoot(
    LayoutSize& offset) const {
  if (isSelectionRoot())
    return nullptr;

  const LayoutObject* object = this;
  LayoutObject* sibling;
  do {
    sibling = object->previousSibling();
    while (sibling && (!sibling->isLayoutBlock() ||
                       toLayoutBlock(sibling)->isSelectionRoot()))
      sibling = sibling->previousSibling();

    offset -= LayoutSize(toLayoutBlock(object)->logicalLeft(),
                         toLayoutBlock(object)->logicalTop());
    object = object->parent();
  } while (!sibling && object && object->isLayoutBlock() &&
           !toLayoutBlock(object)->isSelectionRoot());

  if (!sibling)
    return nullptr;

  LayoutBlock* beforeBlock = toLayoutBlock(sibling);

  offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());

  LayoutObject* child = beforeBlock->lastChild();
  while (child && child->isLayoutBlock()) {
    beforeBlock = toLayoutBlock(child);
    offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
    child = beforeBlock->lastChild();
  }
  return beforeBlock;
}

void LayoutBlock::setSelectionState(SelectionState state) {
  LayoutBox::setSelectionState(state);

  if (inlineBoxWrapper() && canUpdateSelectionOnRootLineBoxes())
    inlineBoxWrapper()->root().setHasSelectedChildren(state != SelectionNone);
}

TrackedLayoutBoxListHashSet* LayoutBlock::positionedObjectsInternal() const {
  return gPositionedDescendantsMap ? gPositionedDescendantsMap->get(this)
                                   : nullptr;
}

void LayoutBlock::insertPositionedObject(LayoutBox* o) {
  ASSERT(!isAnonymousBlock());
  ASSERT(o->containingBlock() == this);

  if (gPositionedContainerMap) {
    auto containerMapIt = gPositionedContainerMap->find(o);
    if (containerMapIt != gPositionedContainerMap->end()) {
      if (containerMapIt->value == this) {
        ASSERT(hasPositionedObjects() && positionedObjects()->contains(o));
        return;
      }
      removePositionedObject(o);
    }
  } else {
    gPositionedContainerMap = new TrackedContainerMap;
  }
  gPositionedContainerMap->set(o, this);

  if (!gPositionedDescendantsMap)
    gPositionedDescendantsMap = new TrackedDescendantsMap;
  TrackedLayoutBoxListHashSet* descendantSet =
      gPositionedDescendantsMap->get(this);
  if (!descendantSet) {
    descendantSet = new TrackedLayoutBoxListHashSet;
    gPositionedDescendantsMap->set(this, wrapUnique(descendantSet));
  }
  descendantSet->add(o);

  m_hasPositionedObjects = true;
}

void LayoutBlock::removePositionedObject(LayoutBox* o) {
  if (!gPositionedContainerMap)
    return;

  LayoutBlock* container = gPositionedContainerMap->take(o);
  if (!container)
    return;

  TrackedLayoutBoxListHashSet* positionedDescendants =
      gPositionedDescendantsMap->get(container);
  ASSERT(positionedDescendants && positionedDescendants->contains(o));
  positionedDescendants->remove(o);
  if (positionedDescendants->isEmpty()) {
    gPositionedDescendantsMap->remove(container);
    container->m_hasPositionedObjects = false;
  }
}

PaintInvalidationReason LayoutBlock::invalidatePaintIfNeeded(
    const PaintInvalidationState& paintInvalidationState) {
  return LayoutBox::invalidatePaintIfNeeded(paintInvalidationState);
}

PaintInvalidationReason LayoutBlock::invalidatePaintIfNeeded(
    const PaintInvalidatorContext& context) const {
  return BlockPaintInvalidator(*this, context).invalidatePaintIfNeeded();
}

void LayoutBlock::removePositionedObjects(
    LayoutObject* o,
    ContainingBlockState containingBlockState) {
  TrackedLayoutBoxListHashSet* positionedDescendants = positionedObjects();
  if (!positionedDescendants)
    return;

  Vector<LayoutBox*, 16> deadObjects;
  for (auto* positionedObject : *positionedDescendants) {
    if (!o || (positionedObject->isDescendantOf(o) && o != positionedObject)) {
      if (containingBlockState == NewContainingBlock) {
        positionedObject->setChildNeedsLayout(MarkOnlyThis);
        if (positionedObject->needsPreferredWidthsRecalculation())
          positionedObject->setPreferredLogicalWidthsDirty(MarkOnlyThis);

        // 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 compositingDisabler;
          if (!positionedObject->isPaintInvalidationContainer())
            ObjectPaintInvalidator(*positionedObject)
                .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 = positionedObject->parent();
      while (p && !p->isLayoutBlock())
        p = p->parent();
      if (p)
        p->setChildNeedsLayout();

      deadObjects.append(positionedObject);
    }
  }

  for (auto object : deadObjects) {
    ASSERT(gPositionedContainerMap->get(object) == this);
    positionedDescendants->remove(object);
    gPositionedContainerMap->remove(object);
  }
  if (positionedDescendants->isEmpty()) {
    gPositionedDescendantsMap->remove(this);
    m_hasPositionedObjects = false;
  }
}

void LayoutBlock::addPercentHeightDescendant(LayoutBox* descendant) {
  if (descendant->percentHeightContainer()) {
    if (descendant->percentHeightContainer() == this) {
      ASSERT(hasPercentHeightDescendant(descendant));
      return;
    }
    descendant->removeFromPercentHeightContainer();
  }
  descendant->setPercentHeightContainer(this);

  if (!gPercentHeightDescendantsMap)
    gPercentHeightDescendantsMap = new TrackedDescendantsMap;
  TrackedLayoutBoxListHashSet* descendantSet =
      gPercentHeightDescendantsMap->get(this);
  if (!descendantSet) {
    descendantSet = new TrackedLayoutBoxListHashSet;
    gPercentHeightDescendantsMap->set(this, wrapUnique(descendantSet));
  }
  descendantSet->add(descendant);

  m_hasPercentHeightDescendants = true;
}

void LayoutBlock::removePercentHeightDescendant(LayoutBox* descendant) {
  if (TrackedLayoutBoxListHashSet* descendants = percentHeightDescendants()) {
    descendants->remove(descendant);
    descendant->setPercentHeightContainer(nullptr);
    if (descendants->isEmpty()) {
      gPercentHeightDescendantsMap->remove(this);
      m_hasPercentHeightDescendants = false;
    }
  }
}

TrackedLayoutBoxListHashSet* LayoutBlock::percentHeightDescendantsInternal()
    const {
  return gPercentHeightDescendantsMap ? gPercentHeightDescendantsMap->get(this)
                                      : nullptr;
}

void LayoutBlock::dirtyForLayoutFromPercentageHeightDescendants(
    SubtreeLayoutScope& layoutScope) {
  TrackedLayoutBoxListHashSet* descendants = percentHeightDescendants();
  if (!descendants)
    return;

  for (auto* box : *descendants) {
    ASSERT(box->isDescendantOf(this));
    while (box != this) {
      if (box->normalChildNeedsLayout())
        break;
      layoutScope.setChildNeedsLayout(box);
      box = box->containingBlock();
      ASSERT(box);
      if (!box)
        break;
    }
  }
}

LayoutUnit LayoutBlock::textIndentOffset() const {
  LayoutUnit cw;
  if (style()->textIndent().isPercentOrCalc())
    cw = containingBlock()->availableLogicalWidth();
  return minimumValueForLength(style()->textIndent(), cw);
}

bool LayoutBlock::isPointInOverflowControl(
    HitTestResult& result,
    const LayoutPoint& locationInContainer,
    const LayoutPoint& accumulatedOffset) const {
  if (!scrollsOverflow())
    return false;

  return layer()->getScrollableArea()->hitTestOverflowControls(
      result,
      roundedIntPoint(locationInContainer - toLayoutSize(accumulatedOffset)));
}

bool LayoutBlock::hitTestOverflowControl(
    HitTestResult& result,
    const HitTestLocation& locationInContainer,
    const LayoutPoint& adjustedLocation) {
  if (visibleToHitTestRequest(result.hitTestRequest()) &&
      isPointInOverflowControl(result, locationInContainer.point(),
                               adjustedLocation)) {
    updateHitTestResult(
        result, locationInContainer.point() - toLayoutSize(adjustedLocation));
    // FIXME: isPointInOverflowControl() doesn't handle rect-based tests yet.
    if (result.addNodeToListBasedTestResult(
            nodeForHitTest(), locationInContainer) == StopHitTesting)
      return true;
  }
  return false;
}

bool LayoutBlock::hitTestChildren(HitTestResult& result,
                                  const HitTestLocation& locationInContainer,
                                  const LayoutPoint& accumulatedOffset,
                                  HitTestAction hitTestAction) {
  ASSERT(!childrenInline());
  LayoutPoint scrolledOffset(hasOverflowClip()
                                 ? accumulatedOffset - scrolledContentOffset()
                                 : accumulatedOffset);
  HitTestAction childHitTest = hitTestAction;
  if (hitTestAction == HitTestChildBlockBackgrounds)
    childHitTest = HitTestChildBlockBackground;
  for (LayoutBox* child = lastChildBox(); child;
       child = child->previousSiblingBox()) {
    LayoutPoint childPoint = flipForWritingModeForChild(child, scrolledOffset);
    if (!child->hasSelfPaintingLayer() && !child->isFloating() &&
        !child->isColumnSpanAll() &&
        child->nodeAtPoint(result, locationInContainer, childPoint,
                           childHitTest)) {
      updateHitTestResult(
          result, flipForWritingMode(toLayoutPoint(locationInContainer.point() -
                                                   accumulatedOffset)));
      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* textBox = toInlineTextBox(box);
  return Position::editingPositionOf(
      box->getLineLayoutItem().nonPseudoNode(),
      start ? textBox->start() : textBox->start() + textBox->len());
}

static inline bool isEditingBoundary(LayoutObject* ancestor,
                                     LineLayoutBox child) {
  ASSERT(!ancestor || ancestor->nonPseudoNode());
  ASSERT(child && 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& pointInParentCoordinates) {
  LayoutPoint childLocation = child.location();
  if (child.isInFlowPositioned())
    childLocation += child.offsetForInFlowPosition();

  // FIXME: This is wrong if the child's writing-mode is different from the
  // parent's.
  LayoutPoint pointInChildCoordinates(
      toLayoutPoint(pointInParentCoordinates - childLocation));

  // If this is an anonymous layoutObject, we just recur normally
  Node* childNode = child.nonPseudoNode();
  if (!childNode)
    return child.positionForPoint(pointInChildCoordinates);

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

  // Otherwise return before or after the child, depending on if the click was
  // to the logical left or logical right of the child
  LayoutUnit childMiddle = logicalWidthForChildSize(child.size()) / 2;
  LayoutUnit logicalLeft = isHorizontalWritingMode()
                               ? pointInChildCoordinates.x()
                               : pointInChildCoordinates.y();
  if (logicalLeft < childMiddle)
    return ancestor->createPositionWithAffinity(childNode->nodeIndex());
  return ancestor->createPositionWithAffinity(childNode->nodeIndex() + 1,
                                              TextAffinity::Upstream);
}

PositionWithAffinity LayoutBlock::positionForPointIfOutsideAtomicInlineLevel(
    const LayoutPoint& point) {
  ASSERT(isAtomicInlineLevel());
  // FIXME: This seems wrong when the object's writing-mode doesn't match the
  // line's writing-mode.
  LayoutUnit pointLogicalLeft =
      isHorizontalWritingMode() ? point.x() : point.y();
  LayoutUnit pointLogicalTop =
      isHorizontalWritingMode() ? point.y() : point.x();

  if (pointLogicalLeft < 0)
    return createPositionWithAffinity(caretMinOffset());
  if (pointLogicalLeft >= logicalWidth())
    return createPositionWithAffinity(caretMaxOffset());
  if (pointLogicalTop < 0)
    return createPositionWithAffinity(caretMinOffset());
  if (pointLogicalTop >= logicalHeight())
    return createPositionWithAffinity(caretMaxOffset());
  return PositionWithAffinity();
}

static inline bool isChildHitTestCandidate(LayoutBox* box) {
  return box->size().height() &&
         box->style()->visibility() == EVisibility::Visible &&
         !box->isFloatingOrOutOfFlowPositioned() && !box->isLayoutFlowThread();
}

PositionWithAffinity LayoutBlock::positionForPoint(const LayoutPoint& point) {
  if (isTable())
    return LayoutBox::positionForPoint(point);

  if (isAtomicInlineLevel()) {
    PositionWithAffinity position =
        positionForPointIfOutsideAtomicInlineLevel(point);
    if (!position.isNull())
      return position;
  }

  LayoutPoint pointInContents = point;
  offsetForContents(pointInContents);
  LayoutPoint pointInLogicalContents(pointInContents);
  if (!isHorizontalWritingMode())
    pointInLogicalContents = pointInLogicalContents.transposedPoint();

  ASSERT(!childrenInline());

  LayoutBox* lastCandidateBox = lastChildBox();
  while (lastCandidateBox && !isChildHitTestCandidate(lastCandidateBox))
    lastCandidateBox = lastCandidateBox->previousSiblingBox();

  bool blocksAreFlipped = style()->isFlippedBlocksWritingMode();
  if (lastCandidateBox) {
    if (pointInLogicalContents.y() > logicalTopForChild(*lastCandidateBox) ||
        (!blocksAreFlipped &&
         pointInLogicalContents.y() == logicalTopForChild(*lastCandidateBox)))
      return positionForPointRespectingEditingBoundaries(
          LineLayoutBox(lastCandidateBox), pointInContents);

    for (LayoutBox* childBox = firstChildBox(); childBox;
         childBox = childBox->nextSiblingBox()) {
      if (!isChildHitTestCandidate(childBox))
        continue;
      LayoutUnit childLogicalBottom =
          logicalTopForChild(*childBox) + logicalHeightForChild(*childBox);
      // We hit child if our click is above the bottom of its padding box (like
      // IE6/7 and FF3).
      if (isChildHitTestCandidate(childBox) &&
          (pointInLogicalContents.y() < childLogicalBottom ||
           (blocksAreFlipped &&
            pointInLogicalContents.y() == childLogicalBottom)))
        return positionForPointRespectingEditingBoundaries(
            LineLayoutBox(childBox), pointInContents);
    }
  }

  // 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);
}

int LayoutBlock::columnGap() const {
  if (style()->hasNormalColumnGap()) {
    // "1em" is recommended as the normal gap setting. Matches <p> margins.
    return style()->getFontDescription().computedPixelSize();
  }
  return static_cast<int>(style()->columnGap());
}

void LayoutBlock::scrollbarsChanged(bool horizontalScrollbarChanged,
                                    bool verticalScrollbarChanged) {
  m_widthAvailableToChildrenChanged |= verticalScrollbarChanged;
  m_heightAvailableToChildrenChanged |= horizontalScrollbarChanged;
}

void LayoutBlock::computeIntrinsicLogicalWidths(
    LayoutUnit& minLogicalWidth,
    LayoutUnit& maxLogicalWidth) const {
  // Size-contained elements don't consider their contents for preferred sizing.
  if (style()->containsSize())
    return;

  if (childrenInline()) {
    // FIXME: Remove this const_cast.
    toLayoutBlockFlow(const_cast<LayoutBlock*>(this))
        ->computeInlinePreferredLogicalWidths(minLogicalWidth, maxLogicalWidth);
  } else {
    computeBlockPreferredLogicalWidths(minLogicalWidth, maxLogicalWidth);
  }

  maxLogicalWidth = std::max(minLogicalWidth, maxLogicalWidth);

  if (isHTMLMarqueeElement(node()) &&
      toHTMLMarqueeElement(node())->isHorizontal())
    minLogicalWidth = LayoutUnit();

  if (isTableCell()) {
    Length tableCellWidth = toLayoutTableCell(this)->styleOrColLogicalWidth();
    if (tableCellWidth.isFixed() && tableCellWidth.value() > 0)
      maxLogicalWidth =
          std::max(minLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(
                                        LayoutUnit(tableCellWidth.value())));
  }

  int scrollbarWidth = scrollbarLogicalWidth();
  maxLogicalWidth += scrollbarWidth;
  minLogicalWidth += scrollbarWidth;
}

DISABLE_CFI_PERF
void LayoutBlock::computePreferredLogicalWidths() {
  ASSERT(preferredLogicalWidthsDirty());

  m_minPreferredLogicalWidth = LayoutUnit();
  m_maxPreferredLogicalWidth = 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& styleToUse = styleRef();
  if (!isTableCell() && styleToUse.logicalWidth().isFixed() &&
      styleToUse.logicalWidth().value() >= 0 &&
      !(isDeprecatedFlexItem() && !styleToUse.logicalWidth().intValue()))
    m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth =
        adjustContentBoxLogicalWidthForBoxSizing(
            LayoutUnit(styleToUse.logicalWidth().value()));
  else
    computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth,
                                  m_maxPreferredLogicalWidth);

  if (styleToUse.logicalMinWidth().isFixed() &&
      styleToUse.logicalMinWidth().value() > 0) {
    m_maxPreferredLogicalWidth =
        std::max(m_maxPreferredLogicalWidth,
                 adjustContentBoxLogicalWidthForBoxSizing(
                     LayoutUnit(styleToUse.logicalMinWidth().value())));
    m_minPreferredLogicalWidth =
        std::max(m_minPreferredLogicalWidth,
                 adjustContentBoxLogicalWidthForBoxSizing(
                     LayoutUnit(styleToUse.logicalMinWidth().value())));
  }

  if (styleToUse.logicalMaxWidth().isFixed()) {
    m_maxPreferredLogicalWidth =
        std::min(m_maxPreferredLogicalWidth,
                 adjustContentBoxLogicalWidthForBoxSizing(
                     LayoutUnit(styleToUse.logicalMaxWidth().value())));
    m_minPreferredLogicalWidth =
        std::min(m_minPreferredLogicalWidth,
                 adjustContentBoxLogicalWidthForBoxSizing(
                     LayoutUnit(styleToUse.logicalMaxWidth().value())));
  }

  // Table layout uses integers, ceil the preferred widths to ensure that they
  // can contain the contents.
  if (isTableCell()) {
    m_minPreferredLogicalWidth = LayoutUnit(m_minPreferredLogicalWidth.ceil());
    m_maxPreferredLogicalWidth = LayoutUnit(m_maxPreferredLogicalWidth.ceil());
  }

  LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
  m_minPreferredLogicalWidth += borderAndPadding;
  m_maxPreferredLogicalWidth += borderAndPadding;

  clearPreferredLogicalWidthsDirty();
}

void LayoutBlock::computeBlockPreferredLogicalWidths(
    LayoutUnit& minLogicalWidth,
    LayoutUnit& maxLogicalWidth) const {
  const ComputedStyle& styleToUse = styleRef();
  bool nowrap = styleToUse.whiteSpace() == NOWRAP;

  LayoutObject* child = firstChild();
  LayoutBlock* containingBlock = this->containingBlock();
  LayoutUnit floatLeftWidth, floatRightWidth;
  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;
    }

    RefPtr<ComputedStyle> childStyle = child->mutableStyle();
    if (child->isFloating() ||
        (child->isBox() && toLayoutBox(child)->avoidsFloats())) {
      LayoutUnit floatTotalWidth = floatLeftWidth + floatRightWidth;
      if (childStyle->clear() & ClearLeft) {
        maxLogicalWidth = std::max(floatTotalWidth, maxLogicalWidth);
        floatLeftWidth = LayoutUnit();
      }
      if (childStyle->clear() & ClearRight) {
        maxLogicalWidth = std::max(floatTotalWidth, maxLogicalWidth);
        floatRightWidth = 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 startMarginLength = childStyle->marginStartUsing(&styleToUse);
    Length endMarginLength = childStyle->marginEndUsing(&styleToUse);
    LayoutUnit margin;
    LayoutUnit marginStart;
    LayoutUnit marginEnd;
    if (startMarginLength.isFixed())
      marginStart += startMarginLength.value();
    if (endMarginLength.isFixed())
      marginEnd += endMarginLength.value();
    margin = marginStart + marginEnd;

    LayoutUnit childMinPreferredLogicalWidth, childMaxPreferredLogicalWidth;
    computeChildPreferredLogicalWidths(*child, childMinPreferredLogicalWidth,
                                       childMaxPreferredLogicalWidth);

    LayoutUnit w = childMinPreferredLogicalWidth + margin;
    minLogicalWidth = std::max(w, minLogicalWidth);

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

    w = childMaxPreferredLogicalWidth + 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 = containingBlock
                       ? containingBlock->style()->isLeftToRightDirection()
                       : styleToUse.isLeftToRightDirection();
        LayoutUnit marginLogicalLeft = ltr ? marginStart : marginEnd;
        LayoutUnit marginLogicalRight = ltr ? marginEnd : marginStart;
        LayoutUnit maxLeft = marginLogicalLeft > 0
                                 ? std::max(floatLeftWidth, marginLogicalLeft)
                                 : floatLeftWidth + marginLogicalLeft;
        LayoutUnit maxRight =
            marginLogicalRight > 0
                ? std::max(floatRightWidth, marginLogicalRight)
                : floatRightWidth + marginLogicalRight;
        w = childMaxPreferredLogicalWidth + maxLeft + maxRight;
        w = std::max(w, floatLeftWidth + floatRightWidth);
      } else {
        maxLogicalWidth =
            std::max(floatLeftWidth + floatRightWidth, maxLogicalWidth);
      }
      floatLeftWidth = floatRightWidth = LayoutUnit();
    }

    if (child->isFloating()) {
      if (childStyle->floating() == EFloat::Left)
        floatLeftWidth += w;
      else
        floatRightWidth += w;
    } else {
      maxLogicalWidth = std::max(w, maxLogicalWidth);
    }

    child = child->nextSibling();
  }

  // Always make sure these values are non-negative.
  minLogicalWidth = minLogicalWidth.clampNegativeToZero();
  maxLogicalWidth = maxLogicalWidth.clampNegativeToZero();

  maxLogicalWidth = std::max(floatLeftWidth + floatRightWidth, maxLogicalWidth);
}

DISABLE_CFI_PERF
void LayoutBlock::computeChildPreferredLogicalWidths(
    LayoutObject& child,
    LayoutUnit& minPreferredLogicalWidth,
    LayoutUnit& maxPreferredLogicalWidth) 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.
    // http://dev.w3.org/csswg/css-writing-modes-3/#orthogonal-shrink-to-fit
    if (!child.needsLayout()) {
      minPreferredLogicalWidth = maxPreferredLogicalWidth =
          toLayoutBox(child).logicalHeight();
      return;
    }
    minPreferredLogicalWidth = maxPreferredLogicalWidth =
        toLayoutBox(child).computeLogicalHeightWithoutLayout();
    return;
  }
  minPreferredLogicalWidth = child.minPreferredLogicalWidth();
  maxPreferredLogicalWidth = 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& computedInlineSize = child.styleRef().logicalWidth();
    if (computedInlineSize.isMaxContent())
      minPreferredLogicalWidth = maxPreferredLogicalWidth;
    else if (computedInlineSize.isMinContent())
      maxPreferredLogicalWidth = minPreferredLogicalWidth;
  }
}

bool LayoutBlock::hasLineIfEmpty() const {
  if (!node())
    return false;

  if (isRootEditableElement(*node()))
    return true;

  if (node()->isShadowRoot() &&
      isHTMLInputElement(toShadowRoot(node())->host()))
    return true;

  return false;
}

LayoutUnit LayoutBlock::lineHeight(bool firstLine,
                                   LineDirectionMode direction,
                                   LinePositionMode linePositionMode) 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() && linePositionMode == PositionOnContainingLine)
    return LayoutBox::lineHeight(firstLine, direction, linePositionMode);

  const ComputedStyle& style =
      styleRef(firstLine && document().styleEngine().usesFirstLineRules());
  return LayoutUnit(style.computedLineHeight());
}

int LayoutBlock::beforeMarginInLineDirection(
    LineDirectionMode direction) const {
  return (direction == HorizontalLine ? marginTop() : marginRight()).toInt();
}

int LayoutBlock::baselinePosition(FontBaseline baselineType,
                                  bool firstLine,
                                  LineDirectionMode direction,
                                  LinePositionMode linePositionMode) 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() && linePositionMode == PositionOnContainingLine) {
    // 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 (style()->hasAppearance() &&
        !LayoutTheme::theme().isControlContainer(style()->appearance()))
      return LayoutTheme::theme().baselinePosition(this);

    int baselinePos = (isWritingModeRoot() && !isRubyRun())
                          ? -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 bottomOfContent =
          direction == HorizontalLine
              ? size().height() - borderBottom() - paddingBottom() -
                    horizontalScrollbarHeight()
              : size().width() - borderLeft() - paddingLeft() -
                    verticalScrollbarWidth();
      if (baselinePos > bottomOfContent)
        baselinePos = -1;
    }
    if (baselinePos != -1)
      return beforeMarginInLineDirection(direction) + baselinePos;

    return LayoutBox::baselinePosition(baselineType, firstLine, direction,
                                       linePositionMode);
  }

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

  const FontMetrics& fontMetrics = style(firstLine)->getFontMetrics();
  return (fontMetrics.ascent(baselineType) +
          (lineHeight(firstLine, direction, linePositionMode) -
           fontMetrics.height()) /
              2)
      .toInt();
}

LayoutUnit LayoutBlock::minLineHeightForReplacedObject(
    bool isFirstLine,
    LayoutUnit replacedHeight) const {
  if (!document().inNoQuirksMode() && replacedHeight)
    return replacedHeight;

  return std::max<LayoutUnit>(
      replacedHeight,
      lineHeight(isFirstLine,
                 isHorizontalWritingMode() ? HorizontalLine : VerticalLine,
                 PositionOfInteriorLineBoxes));
}

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

int LayoutBlock::firstLineBoxBaseline() const {
  ASSERT(!childrenInline());
  if (isWritingModeRoot() && !isRubyRun())
    return -1;

  for (LayoutBox* curr = firstChildBox(); curr; curr = curr->nextSiblingBox()) {
    if (!curr->isFloatingOrOutOfFlowPositioned()) {
      int result = curr->firstLineBoxBaseline();
      if (result != -1)
        return (curr->logicalTop() + result)
            .toInt();  // Translate to our coordinate space.
    }
  }
  return -1;
}

int LayoutBlock::inlineBlockBaseline(LineDirectionMode lineDirection) const {
  ASSERT(!childrenInline());
  if ((!style()->isOverflowVisible() &&
       !shouldIgnoreOverflowPropertyForInlineBlockBaseline()) ||
      style()->containsSize()) {
    // We are not calling LayoutBox::baselinePosition here because the caller
    // should add the margin-top/margin-right, not us.
    return (lineDirection == HorizontalLine ? size().height() + marginBottom()
                                            : size().width() + marginLeft())
        .toInt();
  }

  if (isWritingModeRoot() && !isRubyRun())
    return -1;

  bool haveNormalFlowChild = false;
  for (LayoutBox* curr = lastChildBox(); curr;
       curr = curr->previousSiblingBox()) {
    if (!curr->isFloatingOrOutOfFlowPositioned()) {
      haveNormalFlowChild = true;
      int result = curr->inlineBlockBaseline(lineDirection);
      if (result != -1)
        return (curr->logicalTop() + result)
            .toInt();  // Translate to our coordinate space.
    }
  }
  if (!haveNormalFlowChild && hasLineIfEmpty()) {
    const FontMetrics& fontMetrics = firstLineStyle()->getFontMetrics();
    return (fontMetrics.ascent() +
            (lineHeight(true, lineDirection, PositionOfInteriorLineBoxes) -
             fontMetrics.height()) /
                2 +
            (lineDirection == HorizontalLine ? borderTop() + paddingTop()
                                             : borderRight() + paddingRight()))
        .toInt();
  }
  return -1;
}

const LayoutBlock* LayoutBlock::enclosingFirstLineStyleBlock() const {
  const LayoutBlock* firstLineBlock = this;
  bool hasPseudo = false;
  while (true) {
    hasPseudo = firstLineBlock->style()->hasPseudoStyle(PseudoIdFirstLine);
    if (hasPseudo)
      break;
    LayoutObject* parentBlock = firstLineBlock->parent();
    if (firstLineBlock->isAtomicInlineLevel() ||
        firstLineBlock->isFloatingOrOutOfFlowPositioned() || !parentBlock ||
        !parentBlock->behavesLikeBlockContainer())
      break;
    ASSERT_WITH_SECURITY_IMPLICATION(parentBlock->isLayoutBlock());
    if (toLayoutBlock(parentBlock)->firstChild() != firstLineBlock)
      break;
    firstLineBlock = toLayoutBlock(parentBlock);
  }

  if (!hasPseudo)
    return nullptr;

  return firstLineBlock;
}

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;
}

void LayoutBlock::updateHitTestResult(HitTestResult& result,
                                      const LayoutPoint& point) {
  if (result.innerNode())
    return;

  if (Node* n = nodeForHitTest())
    result.setNodeAndPosition(n, point);
}

// 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() && node() &&
         editingIgnoresContent(node());
}

static inline bool caretBrowsingEnabled(const LocalFrame* frame) {
  Settings* settings = frame->settings();
  return settings && settings->caretBrowsingEnabled();
}

bool LayoutBlock::hasCursorCaret() const {
  LocalFrame* frame = this->frame();
  return frame->selection().caretLayoutObject() == this &&
         (frame->selection().hasEditableStyle() || caretBrowsingEnabled(frame));
}

bool LayoutBlock::hasDragCaret() const {
  LocalFrame* frame = this->frame();
  DragCaretController& dragCaretController =
      frame->page()->dragCaretController();
  return dragCaretController.hasCaretIn(*this);
}

LayoutRect LayoutBlock::localCaretRect(InlineBox* inlineBox,
                                       int caretOffset,
                                       LayoutUnit* extraWidthToEndOfLine) {
  // Do the normal calculation in most cases.
  if ((firstChild() && !firstChild()->isPseudoElement()) ||
      isInlineBoxWrapperActuallyChild())
    return LayoutBox::localCaretRect(inlineBox, caretOffset,
                                     extraWidthToEndOfLine);

  LayoutRect caretRect =
      localCaretRectForEmptyElement(size().width(), textIndentOffset());

  if (extraWidthToEndOfLine)
    *extraWidthToEndOfLine = size().width() - caretRect.maxX();

  return caretRect;
}

void LayoutBlock::addOutlineRects(
    Vector<LayoutRect>& rects,
    const LayoutPoint& additionalOffset,
    IncludeBlockVisualOverflowOrNot includeBlockOverflows) const {
  if (!isAnonymous())  // For anonymous blocks, the children add outline rects.
    rects.append(LayoutRect(additionalOffset, size()));

  if (includeBlockOverflows == IncludeBlockVisualOverflow &&
      !hasOverflowClip() && !hasControlClip()) {
    addOutlineRectsForNormalChildren(rects, additionalOffset,
                                     includeBlockOverflows);
    if (TrackedLayoutBoxListHashSet* positionedObjects =
            this->positionedObjects()) {
      for (auto* box : *positionedObjects)
        addOutlineRectsForDescendant(*box, rects, additionalOffset,
                                     includeBlockOverflows);
    }
  }
}

LayoutBox* LayoutBlock::createAnonymousBoxWithSameTypeAs(
    const LayoutObject* parent) const {
  return createAnonymousWithParentAndDisplay(parent, style()->display());
}

LayoutUnit LayoutBlock::nextPageLogicalTop(LayoutUnit logicalOffset) const {
  LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset);
  if (!pageLogicalHeight)
    return logicalOffset;

  return logicalOffset + pageRemainingLogicalHeightForOffset(
                             logicalOffset, AssociateWithLatterPage);
}

void LayoutBlock::paginatedContentWasLaidOut(
    LayoutUnit logicalBottomOffsetAfterPagination) {
  if (LayoutFlowThread* flowThread = flowThreadContainingBlock())
    flowThread->contentWasLaidOut(offsetFromLogicalTopOfFirstPage() +
                                  logicalBottomOffsetAfterPagination);
}

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->style()->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->style()->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->style()->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->style()->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::name() const {
  ASSERT_NOT_REACHED();
  return "LayoutBlock";
}

LayoutBlock* LayoutBlock::createAnonymousWithParentAndDisplay(
    const LayoutObject* parent,
    EDisplay display) {
  // FIXME: Do we need to convert all our inline displays to block-type in the
  // anonymous logic ?
  EDisplay newDisplay;
  LayoutBlock* newBox = nullptr;
  if (display == EDisplay::Flex || display == EDisplay::InlineFlex) {
    newBox = LayoutFlexibleBox::createAnonymous(&parent->document());
    newDisplay = EDisplay::Flex;
  } else if (display == EDisplay::Grid || display == EDisplay::InlineGrid) {
    newBox = LayoutGrid::createAnonymous(&parent->document());
    newDisplay = EDisplay::Grid;
  } else {
    newBox = LayoutBlockFlow::createAnonymous(&parent->document());
    newDisplay = EDisplay::Block;
  }

  RefPtr<ComputedStyle> newStyle =
      ComputedStyle::createAnonymousStyleWithDisplay(parent->styleRef(),
                                                     newDisplay);
  parent->updateAnonymousChildStyle(*newBox, *newStyle);
  newBox->setStyle(newStyle.release());
  return newBox;
}

bool LayoutBlock::recalcNormalFlowChildOverflowIfNeeded(
    LayoutObject* layoutObject) {
  if (layoutObject->isOutOfFlowPositioned() ||
      !layoutObject->needsOverflowRecalcAfterStyleChange())
    return false;

  ASSERT(layoutObject->isLayoutBlock());
  return toLayoutBlock(layoutObject)->recalcOverflowAfterStyleChange();
}

bool LayoutBlock::recalcChildOverflowAfterStyleChange() {
  ASSERT(childNeedsOverflowRecalcAfterStyleChange());
  clearChildNeedsOverflowRecalcAfterStyleChange();

  bool childrenOverflowChanged = false;

  if (childrenInline()) {
    ASSERT_WITH_SECURITY_IMPLICATION(isLayoutBlockFlow());
    childrenOverflowChanged =
        toLayoutBlockFlow(this)->recalcInlineChildrenOverflowAfterStyleChange();
  } else {
    for (LayoutBox* box = firstChildBox(); box; box = box->nextSiblingBox()) {
      if (recalcNormalFlowChildOverflowIfNeeded(box))
        childrenOverflowChanged = true;
    }
  }

  return recalcPositionedDescendantsOverflowAfterStyleChange() ||
         childrenOverflowChanged;
}

bool LayoutBlock::recalcPositionedDescendantsOverflowAfterStyleChange() {
  bool childrenOverflowChanged = false;

  TrackedLayoutBoxListHashSet* positionedDescendants = positionedObjects();
  if (!positionedDescendants)
    return childrenOverflowChanged;

  for (auto* box : *positionedDescendants) {
    if (!box->needsOverflowRecalcAfterStyleChange())
      continue;
    LayoutBlock* block = toLayoutBlock(box);
    if (!block->recalcOverflowAfterStyleChange() ||
        box->style()->position() == FixedPosition)
      continue;

    childrenOverflowChanged = true;
  }
  return childrenOverflowChanged;
}

bool LayoutBlock::recalcOverflowAfterStyleChange() {
  ASSERT(needsOverflowRecalcAfterStyleChange());

  bool childrenOverflowChanged = false;
  if (childNeedsOverflowRecalcAfterStyleChange())
    childrenOverflowChanged = recalcChildOverflowAfterStyleChange();

  if (!selfNeedsOverflowRecalcAfterStyleChange() && !childrenOverflowChanged)
    return false;

  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 oldClientAfterEdge = hasOverflowModel()
                                      ? m_overflow->layoutClientAfterEdge()
                                      : clientLogicalBottom();
  computeOverflow(oldClientAfterEdge, true);

  if (hasOverflowClip())
    layer()->getScrollableArea()->updateAfterOverflowRecalc();

  return !hasOverflowClip();
}

// 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 oldWidth = logicalWidth();
  LogicalExtentComputedValues computedValues;
  logicalExtentAfterUpdatingLogicalWidth(logicalTop(), computedValues);
  // If we shrink to fit our width may have changed, so we still need full
  // layout.
  if (oldWidth != computedValues.m_extent)
    return false;
  setLogicalWidth(computedValues.m_extent);
  setLogicalLeft(computedValues.m_position);
  setMarginStart(computedValues.m_margins.m_start);
  setMarginEnd(computedValues.m_margins.m_end);

  LayoutUnit oldHeight = logicalHeight();
  LayoutUnit oldIntrinsicContentLogicalHeight = intrinsicContentLogicalHeight();

  setIntrinsicContentLogicalHeight(contentLogicalHeight());
  computeLogicalHeight(oldHeight, logicalTop(), computedValues);

  if (oldHeight != computedValues.m_extent &&
      (hasPercentHeightDescendants() || isFlexibleBox())) {
    setIntrinsicContentLogicalHeight(oldIntrinsicContentLogicalHeight);
    return false;
  }

  setLogicalHeight(computedValues.m_extent);
  setLogicalTop(computedValues.m_position);
  setMarginBefore(computedValues.m_margins.m_before);
  setMarginAfter(computedValues.m_margins.m_after);

  return true;
}

#if ENABLE(ASSERT)
void LayoutBlock::checkPositionedObjectsNeedLayout() {
  if (!gPositionedDescendantsMap)
    return;

  if (TrackedLayoutBoxListHashSet* positionedDescendantSet =
          positionedObjects()) {
    TrackedLayoutBoxListHashSet::const_iterator end =
        positionedDescendantSet->end();
    for (TrackedLayoutBoxListHashSet::const_iterator it =
             positionedDescendantSet->begin();
         it != end; ++it) {
      LayoutBox* currBox = *it;
      ASSERT(!currBox->needsLayout());
    }
  }
}

#endif

LayoutUnit LayoutBlock::availableLogicalHeightForPercentageComputation() const {
  LayoutUnit availableHeight(-1);

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

  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 isOutOfFlowPositionedWithSpecifiedHeight =
      isOutOfFlowPositioned() &&
      (!style.logicalHeight().isAuto() ||
       (!style.logicalTop().isAuto() && !style.logicalBottom().isAuto()));

  LayoutUnit stretchedFlexHeight(-1);
  if (isFlexItem())
    stretchedFlexHeight =
        toLayoutFlexibleBox(parent())
            ->childLogicalHeightForPercentageResolution(*this);

  if (stretchedFlexHeight != LayoutUnit(-1)) {
    availableHeight = stretchedFlexHeight;
  } else if (isGridItem() && hasOverrideLogicalContentHeight()) {
    availableHeight = overrideLogicalContentHeight();
  } else if (style.logicalHeight().isFixed()) {
    LayoutUnit contentBoxHeight = adjustContentBoxLogicalHeightForBoxSizing(
        style.logicalHeight().value());
    availableHeight = std::max(
        LayoutUnit(),
        constrainContentBoxLogicalHeightByMinMax(
            contentBoxHeight - scrollbarLogicalHeight(), LayoutUnit(-1)));
  } else if (style.logicalHeight().isPercentOrCalc() &&
             !isOutOfFlowPositionedWithSpecifiedHeight) {
    LayoutUnit heightWithScrollbar =
        computePercentageLogicalHeight(style.logicalHeight());
    if (heightWithScrollbar != -1) {
      LayoutUnit contentBoxHeightWithScrollbar =
          adjustContentBoxLogicalHeightForBoxSizing(heightWithScrollbar);
      // 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 contentBoxHeight = constrainContentBoxLogicalHeightByMinMax(
          contentBoxHeightWithScrollbar - scrollbarLogicalHeight(),
          LayoutUnit(-1));
      availableHeight = std::max(LayoutUnit(), contentBoxHeight);
    }
  } else if (isOutOfFlowPositionedWithSpecifiedHeight) {
    // 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 computedValues;
    computeLogicalHeight(logicalHeight(), LayoutUnit(), computedValues);
    availableHeight = computedValues.m_extent -
                      borderAndPaddingLogicalHeight() -
                      scrollbarLogicalHeight();
  } else if (isLayoutView()) {
    availableHeight = view()->viewLogicalHeightForPercentages();
  }

  return availableHeight;
}

bool LayoutBlock::hasDefiniteLogicalHeight() const {
  return availableLogicalHeightForPercentageComputation() != LayoutUnit(-1);
}

}  // namespace blink
