/*
 * 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),
      m_paginationStateChanged(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();
    if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()) {
      // The overflow clip paint property depends on whether overflow clip is
      // present so we need to update paint properties if this changes.
      setNeedsPaintPropertyUpdate();
    }
  }
  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;

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

  // 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();
  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() == EBoxSizing::kBorderBox &&
      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() ||
         isSVGForeignObject() || style()->display() == EDisplay::FlowRoot;
}

static inline bool changeInAvailableLogicalHeightAffectsChild(
    LayoutBlock* parent,
    LayoutBox& child) {
  if (parent->style()->boxSizing() != EBoxSizing::kBorderBox)
    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()) {
    SECURITY_DCHECK(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);

    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();
  // The LayoutView is absolute-positioned, but does not move.
  if (o->isLayoutView())
    return;

  // We must compute child's width and height, but not update them now.
  // The child will update its width and height when it gets laid out, and needs
  // to see them change there.
  LayoutBox* box = toLayoutBox(child);
  if (hasStaticInlinePosition) {
    LogicalExtentComputedValues computedValues;
    box->computeLogicalWidth(computedValues);
    LayoutUnit newLeft = computedValues.m_position;
    if (newLeft != box->logicalLeft())
      layoutScope.setChildNeedsLayout(child);
  } else if (hasStaticBlockPosition) {
    LogicalExtentComputedValues computedValues;
    box->computeLogicalHeight(computedValues);
    LayoutUnit newTop = computedValues.m_position;
    if (newTop != box->logicalTop())
      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;

  for (auto* positionedObject : *positionedDescendants) {
    layoutPositionedObject(positionedObject, relayoutChildren, info);
  }
}

void LayoutBlock::layoutPositionedObject(LayoutBox* positionedObject,
                                         bool relayoutChildren,
                                         PositionedLayoutBehavior info) {
  positionedObject->setMayNeedPaintInvalidation();

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

  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 isPaginated = view()->layoutState()->isPaginated();
  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();

  if (isPaginated)
    updateFragmentationInfoForChild(*positionedObject);
}

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, WTF::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.push_back(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, WTF::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::kVisible &&
         !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,
                                    ScrollbarChangeContext context) {
  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() == EWhiteSpace::kNowrap;

  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::kLeft)
        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 {
  // InlineFlowBox::placeBoxesInBlockDirection will flip lines in
  // case of verticalLR mode, so we can assume verticalRL for now.
  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 SimpleFontData* fontData = style(firstLine)->font().primaryFont();
  DCHECK(fontData);
  if (!fontData)
    return -1;

  const FontMetrics& fontMetrics = fontData->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.
    }
  }
  const SimpleFontData* fontData = firstLineStyle()->font().primaryFont();
  if (fontData && !haveNormalFlowChild && hasLineIfEmpty()) {
    const FontMetrics& fontMetrics = fontData->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;
    SECURITY_DCHECK(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());
}

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

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.push_back(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());
}

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 {
    newBox = LayoutBlockFlow::createAnonymous(&parent->document());
    newDisplay = EDisplay::Block;
  }

  RefPtr<ComputedStyle> newStyle =
      ComputedStyle::createAnonymousStyleWithDisplay(parent->styleRef(),
                                                     newDisplay);
  parent->updateAnonymousChildStyle(*newBox, *newStyle);
  newBox->setStyle(std::move(newStyle));
  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()) {
    SECURITY_DCHECK(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 DCHECK_IS_ON()
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
