/*
 * 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 (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
