/*
 * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
 *           (C) 2000 Antti Koivisto (koivisto@kde.org)
 *           (C) 2000 Dirk Mueller (mueller@kde.org)
 *           (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc.
 *               All rights reserved.
 * Copyright (C) 2009 Google Inc. 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.
 *
 */

#ifndef LayoutObject_h
#define LayoutObject_h

#include "core/CoreExport.h"
#include "core/dom/Document.h"
#include "core/dom/DocumentLifecycle.h"
#include "core/dom/Element.h"
#include "core/editing/Forward.h"
#include "core/frame/LocalFrameView.h"
#include "core/html_names.h"
#include "core/layout/LayoutObjectChildList.h"
#include "core/layout/MapCoordinatesFlags.h"
#include "core/layout/ScrollAlignment.h"
#include "core/layout/SubtreeLayoutScope.h"
#include "core/layout/api/HitTestAction.h"
#include "core/layout/api/SelectionState.h"
#include "core/loader/resource/ImageResourceObserver.h"
#include "core/paint/FragmentData.h"
#include "core/paint/LayerHitTestRects.h"
#include "core/paint/PaintPhase.h"
#include "core/paint/RarePaintData.h"
#include "core/paint/compositing/CompositingState.h"
#include "core/style/ComputedStyle.h"
#include "core/style/StyleDifference.h"
#include "platform/geometry/FloatQuad.h"
#include "platform/geometry/LayoutRect.h"
#include "platform/geometry/TransformState.h"
#include "platform/graphics/CompositingReasons.h"
#include "platform/graphics/PaintInvalidationReason.h"
#include "platform/graphics/paint/DisplayItemClient.h"
#include "platform/transforms/TransformationMatrix.h"
#include "platform/wtf/AutoReset.h"

namespace blink {

class AffineTransform;
class Cursor;
class HitTestLocation;
class HitTestRequest;
class HitTestResult;
class InlineBox;
class LayoutBoxModelObject;
class LayoutBlock;
class LayoutBlockFlow;
class LayoutFlowThread;
class LayoutGeometryMap;
class LayoutMultiColumnSpannerPlaceholder;
class LayoutView;
class NGPhysicalBoxFragment;
class ObjectPaintProperties;
class PaintLayer;
class PseudoStyleRequest;

struct PaintInfo;
struct PaintInvalidatorContext;

enum VisualRectFlags { kDefaultVisualRectFlags = 0, kEdgeInclusive = 1 };

enum CursorDirective { kSetCursorBasedOnStyle, kSetCursor, kDoNotSetCursor };

enum HitTestFilter { kHitTestAll, kHitTestSelf, kHitTestDescendants };

enum MarkingBehavior {
  kMarkOnlyThis,
  kMarkContainerChain,
};

enum ScheduleRelayoutBehavior { kScheduleRelayout, kDontScheduleRelayout };

struct AnnotatedRegionValue {
  DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
  bool operator==(const AnnotatedRegionValue& o) const {
    return draggable == o.draggable && bounds == o.bounds;
  }

  LayoutRect bounds;
  bool draggable;
};

#ifndef NDEBUG
const int kShowTreeCharacterOffset = 39;
#endif

// LayoutObject is the base class for all layout tree objects.
//
// LayoutObjects form a tree structure that is a close mapping of the DOM tree.
// The root of the LayoutObject tree is the LayoutView, which is the
// LayoutObject associated with the Document.
//
// Some LayoutObjects don't have an associated Node and are called "anonymous"
// (see the constructor below). Anonymous LayoutObjects exist for several
// purposes but are usually required by CSS. A good example is anonymous table
// parts (see LayoutTable for the expected structure). Anonymous LayoutObjects
// are generated when a new child is added to the tree in addChild(). See the
// function for some important information on this.
//
// Also some Node don't have an associated LayoutObjects e.g. if display: none
// or display: contents is set. For more detail, see LayoutObject::createObject
// that creates the right LayoutObject based on the style.
//
// Because the SVG and CSS classes both inherit from this object, functions can
// belong to either realm and sometimes to both.
//
// The purpose of the layout tree is to do layout (aka reflow) and store its
// results for painting and hit-testing. Layout is the process of sizing and
// positioning Nodes on the page. In Blink, layouts always start from a relayout
// boundary (see objectIsRelayoutBoundary in LayoutObject.cpp). As such, we
// need to mark the ancestors all the way to the enclosing relayout boundary in
// order to do a correct layout.
//
// Due to the high cost of layout, a lot of effort is done to avoid doing full
// layouts of nodes. This is why there are several types of layout available to
// bypass the complex operations. See the comments on the layout booleans in
// LayoutObjectBitfields below about the different layouts.
//
// To save memory, especially for the common child class LayoutText,
// LayoutObject doesn't provide storage for children. Descendant classes that do
// allow children have to have a LayoutObjectChildList member that stores the
// actual children and override virtualChildren().
//
// LayoutObject is an ImageResourceObserver, which means that it gets notified
// when associated images are changed. This is used for 2 main use cases:
// - reply to 'background-image' as we need to invalidate the background in this
//   case.
//   (See https://drafts.csswg.org/css-backgrounds-3/#the-background-image)
// - image (LayoutImage, LayoutSVGImage) or video (LayoutVideo) objects that are
//   placeholders for displaying them.
//
//
// ***** LIFETIME *****
//
// LayoutObjects are fully owned by their associated DOM node. In other words,
// it's the DOM node's responsibility to free its LayoutObject, this is why
// LayoutObjects are not and SHOULD NOT be RefCounted.
//
// LayoutObjects are created during the DOM attachment. This phase computes
// the style and create the LayoutObject associated with the Node (see
// Node::attachLayoutTree). LayoutObjects are destructed during detachment (see
// Node::detachLayoutTree), which can happen when the DOM node is removed from
// the
// DOM tree, during page tear down or when the style is changed to contain
// 'display: none'.
//
// Anonymous LayoutObjects are owned by their enclosing DOM node. This means
// that if the DOM node is detached, it has to destroy any anonymous
// descendants. This is done in LayoutObject::destroy().
//
// Note that for correctness, destroy() is expected to clean any anonymous
// wrappers as sequences of insertion / removal could make them visible to
// the page. This is done by LayoutObject::destroyAndCleanupAnonymousWrappers()
// which is the preferred way to destroy an object.
//
//
// ***** INTRINSIC SIZES / PREFERRED LOGICAL WIDTHS *****
// The preferred logical widths are the intrinsic sizes of this element
// (https://drafts.csswg.org/css-sizing-3/#intrinsic). Intrinsic sizes depend
// mostly on the content and a limited set of style properties (e.g. any
// font-related property for text, 'min-width'/'max-width',
// 'min-height'/'max-height').
//
// Those widths are used to determine the final layout logical width, which
// depends on the layout algorithm used and the available logical width.
//
// LayoutObject only has getters for the widths (MinPreferredLogicalWidth and
// MaxPreferredLogicalWidth). However the storage for them is in LayoutBox (see
// min_preferred_logical_width_ and max_preferred_logical_width_). This is
// because only boxes implementing the full box model have a need for them.
// Because LayoutBlockFlow's intrinsic widths rely on the underlying text
// content, LayoutBlockFlow may call LayoutText::ComputePreferredLogicalWidths.
//
// The 2 widths are computed lazily during layout when the getters are called.
// The computation is done by calling ComputePreferredLogicalWidths() behind the
// scene. The boolean used to control the lazy recomputation is
// PreferredLogicalWidthsDirty.
//
// See the individual getters below for more details about what each width is.
class CORE_EXPORT LayoutObject : public ImageResourceObserver,
                                 public DisplayItemClient {
  friend class LayoutObjectChildList;
  FRIEND_TEST_ALL_PREFIXES(LayoutObjectTest, MutableForPaintingClearPaintFlags);
  FRIEND_TEST_ALL_PREFIXES(LayoutObjectTest,
                           LocationInBackingAndSelectionVisualRect);
  friend class VisualRectMappingTest;
  WTF_MAKE_NONCOPYABLE(LayoutObject);

 public:
  // Anonymous objects should pass the document as their node, and they will
  // then automatically be marked as anonymous in the constructor.
  explicit LayoutObject(Node*);
  ~LayoutObject() override;

  // Returns the name of the layout object.
  virtual const char* GetName() const = 0;

  // Returns the decorated name used by run-layout-tests. The name contains the
  // name of the object along with extra information about the layout object
  // state (e.g. positioning).
  String DecoratedName() const;

  // DisplayItemClient methods.

  // Do not call VisualRect directly outside of the DisplayItemClient
  // interface, use a per-fragment one on FragmentData instead.
 private:
  LayoutRect VisualRect() const final;

 public:
  void ClearPartialInvalidationRect() const final {
    DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
    return GetMutableForPainting().SetPartialInvalidationRect(LayoutRect());
  }

  String DebugName() const final;

  LayoutObject* Parent() const { return parent_; }
  bool IsDescendantOf(const LayoutObject*) const;

  LayoutObject* PreviousSibling() const { return previous_; }
  LayoutObject* NextSibling() const { return next_; }

  DISABLE_CFI_PERF
  LayoutObject* SlowFirstChild() const {
    if (const LayoutObjectChildList* children = VirtualChildren())
      return children->FirstChild();
    return nullptr;
  }
  LayoutObject* SlowLastChild() const {
    if (const LayoutObjectChildList* children = VirtualChildren())
      return children->LastChild();
    return nullptr;
  }

  // See comment in the class description as to why there is no child.
  virtual LayoutObjectChildList* VirtualChildren() { return nullptr; }
  virtual const LayoutObjectChildList* VirtualChildren() const {
    return nullptr;
  }

  LayoutObject* NextInPreOrder() const;
  LayoutObject* NextInPreOrder(const LayoutObject* stay_within) const;
  LayoutObject* NextInPreOrderAfterChildren() const;
  LayoutObject* NextInPreOrderAfterChildren(
      const LayoutObject* stay_within) const;
  LayoutObject* PreviousInPreOrder() const;
  LayoutObject* PreviousInPreOrder(const LayoutObject* stay_within) const;
  LayoutObject* ChildAt(unsigned) const;

  LayoutObject* LastLeafChild() const;

  // The following functions are used when the layout tree hierarchy changes to
  // make sure layers get properly added and removed. Since containership can be
  // implemented by any subclass, and since a hierarchy can contain a mixture of
  // boxes and other object types, these functions need to be in the base class.
  PaintLayer* EnclosingLayer() const;
  void AddLayers(PaintLayer* parent_layer);
  void RemoveLayers(PaintLayer* parent_layer);
  void MoveLayers(PaintLayer* old_parent, PaintLayer* new_parent);
  PaintLayer* FindNextLayer(PaintLayer* parent_layer,
                            LayoutObject* start_point,
                            bool check_parent = true);

  // Returns the layer that will paint this object. During paint invalidation,
  // we should use the faster PaintInvalidatorContext::painting_layer instead.
  PaintLayer* PaintingLayer() const;

  bool IsFixedPositionObjectInPagedMedia() const;

  // Scrolling is a LayoutBox concept, however some code just cares about
  // recursively scrolling our enclosing ScrollableArea(s).
  bool ScrollRectToVisible(
      const LayoutRect&,
      const ScrollAlignment& align_x = ScrollAlignment::kAlignCenterIfNeeded,
      const ScrollAlignment& align_y = ScrollAlignment::kAlignCenterIfNeeded,
      ScrollType = kProgrammaticScroll,
      bool make_visible_in_visual_viewport = true,
      ScrollBehavior = kScrollBehaviorAuto);

  // Convenience function for getting to the nearest enclosing box of a
  // LayoutObject.
  LayoutBox* EnclosingBox() const;
  LayoutBoxModelObject* EnclosingBoxModelObject() const;

  LayoutBox* EnclosingScrollableBox() const;

  // Returns |EnclosingBox()| if it's a LayoutNGBlockFlow, or nullptr otherwise.
  LayoutBlockFlow* EnclosingNGBlockFlow() const;

  // Returns |NGPhysicalBoxFragment| for |EnclosingNGBlockFlow()| or nullptr
  // otherwise.
  const NGPhysicalBoxFragment* EnclosingBlockFlowFragment() const;

  // Function to return our enclosing flow thread if we are contained inside
  // one. This function follows the containing block chain.
  LayoutFlowThread* FlowThreadContainingBlock() const {
    if (!IsInsideFlowThread())
      return nullptr;
    return LocateFlowThreadContainingBlock();
  }

#if DCHECK_IS_ON()
  void SetHasAXObject(bool flag) { has_ax_object_ = flag; }
  bool HasAXObject() const { return has_ax_object_; }

  // Helper class forbidding calls to setNeedsLayout() during its lifetime.
  class SetLayoutNeededForbiddenScope {
   public:
    explicit SetLayoutNeededForbiddenScope(LayoutObject&);
    ~SetLayoutNeededForbiddenScope();

   private:
    LayoutObject& layout_object_;
    bool preexisting_forbidden_;
  };

  void AssertLaidOut() const {
#ifndef NDEBUG
    if (NeedsLayout())
      ShowLayoutTreeForThis();
#endif
    SECURITY_DCHECK(!NeedsLayout());
  }

  void AssertSubtreeIsLaidOut() const {
    for (const LayoutObject* layout_object = this; layout_object;
         layout_object = layout_object->NextInPreOrder())
      layout_object->AssertLaidOut();
  }

  void AssertClearedPaintInvalidationFlags() const {
#ifndef NDEBUG
    if (PaintInvalidationStateIsDirty()) {
      ShowLayoutTreeForThis();
      NOTREACHED();
    }
#endif
  }

  void AssertSubtreeClearedPaintInvalidationFlags() const {
    for (const LayoutObject* layout_object = this; layout_object;
         layout_object = layout_object->NextInPreOrder())
      layout_object->AssertClearedPaintInvalidationFlags();
  }

#endif

  // LayoutObject tree manipulation
  //////////////////////////////////////////
  DISABLE_CFI_PERF virtual bool CanHaveChildren() const {
    return VirtualChildren();
  }
  virtual bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const {
    return true;
  }

  // This function is called whenever a child is inserted under |this|.
  //
  // The main purpose of this function is to generate a consistent layout
  // tree, which means generating the missing anonymous objects. Most of the
  // time there'll be no anonymous objects to generate.
  //
  // The following invariants are true on the input:
  // - |newChild->node()| is a child of |this->node()|, if |this| is not
  //   anonymous. If |this| is anonymous, the invariant holds with the
  //   enclosing non-anonymous LayoutObject.
  // - |beforeChild->node()| (if |beforeChild| is provided and not anonymous)
  //   is a sibling of |newChild->node()| (if |newChild| is not anonymous).
  //
  // The reason for these invariants is that insertions are performed on the
  // DOM tree. Because the layout tree may insert extra anonymous renderers,
  // the previous invariants are only guaranteed for the DOM tree. In
  // particular, |beforeChild| may not be a direct child when it's wrapped in
  // anonymous wrappers.
  //
  // Classes inserting anonymous LayoutObjects in the tree are expected to
  // check for the anonymous wrapper case with:
  //                    beforeChild->parent() != this
  //
  // The usage of |child/parent/sibling| in this comment actually means
  // |child/parent/sibling| in a flat tree because a layout tree is generated
  // from a structure of a flat tree if Shadow DOM is used.
  // See LayoutTreeBuilderTraversal and FlatTreeTraversal.
  //
  // See LayoutTable::addChild and LayoutBlock::addChild.
  // TODO(jchaffraix): |newChild| cannot be nullptr and should be a reference.
  virtual void AddChild(LayoutObject* new_child,
                        LayoutObject* before_child = nullptr);
  virtual void AddChildIgnoringContinuation(
      LayoutObject* new_child,
      LayoutObject* before_child = nullptr) {
    return AddChild(new_child, before_child);
  }
  virtual void RemoveChild(LayoutObject*);
  virtual bool CreatesAnonymousWrapper() const { return false; }
  //////////////////////////////////////////

  // Sets the parent of this object but doesn't add it as a child of the parent.
  void SetDangerousOneWayParent(LayoutObject*);

  UniqueObjectId UniqueId() const {
    DCHECK(fragment_.GetRarePaintData());
    return fragment_.GetRarePaintData()
               ? fragment_.GetRarePaintData()->UniqueId()
               : 0;
  }

 private:
  //////////////////////////////////////////
  // Helper functions. Dangerous to use!
  void SetPreviousSibling(LayoutObject* previous) { previous_ = previous; }
  void SetNextSibling(LayoutObject* next) { next_ = next; }
  void SetParent(LayoutObject* parent) {
    parent_ = parent;

    // Only update if our flow thread state is different from our new parent and
    // if we're not a LayoutFlowThread.
    // A LayoutFlowThread is always considered to be inside itself, so it never
    // has to change its state in response to parent changes.
    bool inside_flow_thread = parent && parent->IsInsideFlowThread();
    if (inside_flow_thread != IsInsideFlowThread() && !IsLayoutFlowThread())
      SetIsInsideFlowThreadIncludingDescendants(inside_flow_thread);
  }

  //////////////////////////////////////////
 private:
#if DCHECK_IS_ON()
  bool IsSetNeedsLayoutForbidden() const { return set_needs_layout_forbidden_; }
  void SetNeedsLayoutIsForbidden(bool flag) {
    set_needs_layout_forbidden_ = flag;
  }
#endif

  void AddAbsoluteRectForLayer(IntRect& result);
  bool RequiresAnonymousTableWrappers(const LayoutObject*) const;

 public:
#ifndef NDEBUG
  void ShowTreeForThis() const;
  void ShowLayoutTreeForThis() const;
  void ShowLineTreeForThis() const;
  void ShowLayoutObject() const;

  // Dump this layout object to the specified string builder.
  void DumpLayoutObject(StringBuilder&) const;

  // Dump the subtree established by this layout object to the specified string
  // builder. There will be one object per line, and descendants will be
  // indented according to their tree level. The optional "marked_foo"
  // parameters can be used to mark up to two objects in the subtree with a
  // label.
  void DumpLayoutTreeAndMark(StringBuilder&,
                             const LayoutObject* marked_object1 = nullptr,
                             const char* marked_label1 = nullptr,
                             const LayoutObject* marked_object2 = nullptr,
                             const char* marked_label2 = nullptr,
                             unsigned depth = 0) const;
#endif

  // This function is used to create the appropriate LayoutObject based
  // on the style, in particular 'display' and 'content'.
  // "display: none" or "display: contents" are the only times this function
  // will return nullptr.
  //
  // For renderer creation, the inline-* values create the same renderer
  // as the non-inline version. The difference is that inline-* sets
  // is_inline_ during initialization. This means that
  // "display: inline-table" creates a LayoutTable, like "display: table".
  //
  // Ideally every Element::createLayoutObject would call this function to
  // respond to 'display' but there are deep rooted assumptions about
  // which LayoutObject is created on a fair number of Elements. This
  // function also doesn't handle the default association between a tag
  // and its renderer (e.g. <iframe> creates a LayoutIFrame even if the
  // initial 'display' value is inline).
  static LayoutObject* CreateObject(Element*, const ComputedStyle&);

  // LayoutObjects are allocated out of the rendering partition.
  void* operator new(size_t);
  void operator delete(void*);

  bool IsPseudoElement() const {
    return GetNode() && GetNode()->IsPseudoElement();
  }

  virtual bool IsBoxModelObject() const { return false; }
  bool IsBR() const { return IsOfType(kLayoutObjectBr); }
  bool IsCanvas() const { return IsOfType(kLayoutObjectCanvas); }
  bool IsCounter() const { return IsOfType(kLayoutObjectCounter); }
  bool IsDetailsMarker() const { return IsOfType(kLayoutObjectDetailsMarker); }
  bool IsEmbeddedObject() const {
    return IsOfType(kLayoutObjectEmbeddedObject);
  }
  bool IsFieldset() const { return IsOfType(kLayoutObjectFieldset); }
  bool IsFileUploadControl() const {
    return IsOfType(kLayoutObjectFileUploadControl);
  }
  bool IsFrame() const { return IsOfType(kLayoutObjectFrame); }
  bool IsFrameSet() const { return IsOfType(kLayoutObjectFrameSet); }
  bool IsLayoutNGBlockFlow() const {
    return IsOfType(kLayoutObjectNGBlockFlow);
  }
  bool IsLayoutNGMixin() const { return IsOfType(kLayoutObjectNGMixin); }
  bool IsLayoutNGListItem() const { return IsOfType(kLayoutObjectNGListItem); }
  bool IsLayoutTableCol() const {
    return IsOfType(kLayoutObjectLayoutTableCol);
  }
  bool IsListBox() const { return IsOfType(kLayoutObjectListBox); }
  bool IsListItem() const { return IsOfType(kLayoutObjectListItem); }
  bool IsListMarker() const { return IsOfType(kLayoutObjectListMarker); }
  bool IsMedia() const { return IsOfType(kLayoutObjectMedia); }
  bool IsMenuList() const { return IsOfType(kLayoutObjectMenuList); }
  bool IsProgress() const { return IsOfType(kLayoutObjectProgress); }
  bool IsQuote() const { return IsOfType(kLayoutObjectQuote); }
  bool IsLayoutButton() const { return IsOfType(kLayoutObjectLayoutButton); }
  bool IsLayoutFullScreen() const {
    return IsOfType(kLayoutObjectLayoutFullScreen);
  }
  bool IsLayoutFullScreenPlaceholder() const {
    return IsOfType(kLayoutObjectLayoutFullScreenPlaceholder);
  }
  bool IsLayoutGrid() const { return IsOfType(kLayoutObjectLayoutGrid); }
  bool IsLayoutIFrame() const { return IsOfType(kLayoutObjectLayoutIFrame); }
  bool IsLayoutImage() const { return IsOfType(kLayoutObjectLayoutImage); }
  bool IsLayoutMultiColumnSet() const {
    return IsOfType(kLayoutObjectLayoutMultiColumnSet);
  }
  bool IsLayoutMultiColumnSpannerPlaceholder() const {
    return IsOfType(kLayoutObjectLayoutMultiColumnSpannerPlaceholder);
  }
  bool IsLayoutReplaced() const {
    return IsOfType(kLayoutObjectLayoutReplaced);
  }
  bool IsLayoutScrollbarPart() const {
    return IsOfType(kLayoutObjectLayoutScrollbarPart);
  }
  bool IsLayoutView() const { return IsOfType(kLayoutObjectLayoutView); }
  bool IsRuby() const { return IsOfType(kLayoutObjectRuby); }
  bool IsRubyBase() const { return IsOfType(kLayoutObjectRubyBase); }
  bool IsRubyRun() const { return IsOfType(kLayoutObjectRubyRun); }
  bool IsRubyText() const { return IsOfType(kLayoutObjectRubyText); }
  bool IsSlider() const { return IsOfType(kLayoutObjectSlider); }
  bool IsSliderThumb() const { return IsOfType(kLayoutObjectSliderThumb); }
  bool IsTable() const { return IsOfType(kLayoutObjectTable); }
  bool IsTableCaption() const { return IsOfType(kLayoutObjectTableCaption); }
  bool IsTableCell() const { return IsOfType(kLayoutObjectTableCell); }
  bool IsTableRow() const { return IsOfType(kLayoutObjectTableRow); }
  bool IsTableSection() const { return IsOfType(kLayoutObjectTableSection); }
  bool IsTextArea() const { return IsOfType(kLayoutObjectTextArea); }
  bool IsTextControl() const { return IsOfType(kLayoutObjectTextControl); }
  bool IsTextField() const { return IsOfType(kLayoutObjectTextField); }
  bool IsVideo() const { return IsOfType(kLayoutObjectVideo); }
  bool IsWidget() const { return IsOfType(kLayoutObjectWidget); }

  virtual bool IsImage() const { return false; }

  virtual bool IsInlineBlockOrInlineTable() const { return false; }
  virtual bool IsLayoutBlock() const { return false; }
  virtual bool IsLayoutBlockFlow() const { return false; }
  virtual bool IsLayoutFlowThread() const { return false; }
  virtual bool IsLayoutInline() const { return false; }
  virtual bool IsLayoutEmbeddedContent() const { return false; }

  bool IsDocumentElement() const {
    return GetDocument().documentElement() == node_;
  }
  // isBody is called from LayoutBox::styleWillChange and is thus quite hot.
  bool IsBody() const {
    return GetNode() && GetNode()->HasTagName(HTMLNames::bodyTag);
  }
  bool IsHR() const;

  bool IsTablePart() const {
    return IsTableCell() || IsLayoutTableCol() || IsTableCaption() ||
           IsTableRow() || IsTableSection();
  }

  inline bool IsBeforeContent() const;
  inline bool IsAfterContent() const;
  inline bool IsBeforeOrAfterContent() const;
  static inline bool IsAfterContent(const LayoutObject* obj) {
    return obj && obj->IsAfterContent();
  }

  bool HasCounterNodeMap() const { return bitfields_.HasCounterNodeMap(); }
  void SetHasCounterNodeMap(bool has_counter_node_map) {
    bitfields_.SetHasCounterNodeMap(has_counter_node_map);
  }

  bool IsTruncated() const { return bitfields_.IsTruncated(); }
  void SetIsTruncated(bool is_truncated) {
    bitfields_.SetIsTruncated(is_truncated);
  }

  bool EverHadLayout() const { return bitfields_.EverHadLayout(); }

  bool ChildrenInline() const { return bitfields_.ChildrenInline(); }
  void SetChildrenInline(bool b) { bitfields_.SetChildrenInline(b); }

  bool AlwaysCreateLineBoxesForLayoutInline() const {
    DCHECK(IsLayoutInline());
    return bitfields_.AlwaysCreateLineBoxesForLayoutInline();
  }
  void SetAlwaysCreateLineBoxesForLayoutInline(bool always_create_line_boxes) {
    DCHECK(IsLayoutInline());
    bitfields_.SetAlwaysCreateLineBoxesForLayoutInline(
        always_create_line_boxes);
  }

  bool AncestorLineBoxDirty() const {
    return bitfields_.AncestorLineBoxDirty();
  }
  void SetAncestorLineBoxDirty(bool value = true) {
    bitfields_.SetAncestorLineBoxDirty(value);
    if (value)
      SetNeedsLayoutAndFullPaintInvalidation(
          LayoutInvalidationReason::kLineBoxesChanged);
  }

  void SetIsInsideFlowThreadIncludingDescendants(bool);

  bool IsInsideFlowThread() const { return bitfields_.IsInsideFlowThread(); }
  void SetIsInsideFlowThread(bool inside_flow_thread) {
    bitfields_.SetIsInsideFlowThread(inside_flow_thread);
  }

  // FIXME: Until all SVG layoutObjects can be subclasses of
  // LayoutSVGModelObject we have to add SVG layoutObject methods to
  // LayoutObject with an NOTREACHED() default implementation.
  bool IsSVG() const { return IsOfType(kLayoutObjectSVG); }
  bool IsSVGRoot() const { return IsOfType(kLayoutObjectSVGRoot); }
  bool IsSVGChild() const { return IsSVG() && !IsSVGRoot(); }
  bool IsSVGContainer() const { return IsOfType(kLayoutObjectSVGContainer); }
  bool IsSVGTransformableContainer() const {
    return IsOfType(kLayoutObjectSVGTransformableContainer);
  }
  bool IsSVGViewportContainer() const {
    return IsOfType(kLayoutObjectSVGViewportContainer);
  }
  bool IsSVGHiddenContainer() const {
    return IsOfType(kLayoutObjectSVGHiddenContainer);
  }
  bool IsSVGShape() const { return IsOfType(kLayoutObjectSVGShape); }
  bool IsSVGText() const { return IsOfType(kLayoutObjectSVGText); }
  bool IsSVGTextPath() const { return IsOfType(kLayoutObjectSVGTextPath); }
  bool IsSVGInline() const { return IsOfType(kLayoutObjectSVGInline); }
  bool IsSVGInlineText() const { return IsOfType(kLayoutObjectSVGInlineText); }
  bool IsSVGImage() const { return IsOfType(kLayoutObjectSVGImage); }
  bool IsSVGForeignObject() const {
    return IsOfType(kLayoutObjectSVGForeignObject);
  }
  bool IsSVGResourceContainer() const {
    return IsOfType(kLayoutObjectSVGResourceContainer);
  }
  bool IsSVGResourceFilter() const {
    return IsOfType(kLayoutObjectSVGResourceFilter);
  }
  bool IsSVGResourceFilterPrimitive() const {
    return IsOfType(kLayoutObjectSVGResourceFilterPrimitive);
  }

  // FIXME: Those belong into a SVG specific base-class for all layoutObjects
  // (see above). Unfortunately we don't have such a class yet, because it's not
  // possible for all layoutObjects to inherit from LayoutSVGObject ->
  // LayoutObject (some need LayoutBlock inheritance for instance)
  virtual void SetNeedsTransformUpdate() {}
  virtual void SetNeedsBoundariesUpdate();

  bool IsBlendingAllowed() const {
    return !IsSVG() || (IsSVGContainer() && !IsSVGHiddenContainer()) ||
           IsSVGShape() || IsSVGImage() || IsSVGText();
  }
  virtual bool HasNonIsolatedBlendingDescendants() const {
    // This is only implemented for layout objects that containt SVG flow.
    // For HTML/CSS layout objects, use the PaintLayer version instead.
    DCHECK(IsSVG());
    return false;
  }
  enum DescendantIsolationState {
    kDescendantIsolationRequired,
    kDescendantIsolationNeedsUpdate,
  };
  virtual void DescendantIsolationRequirementsChanged(
      DescendantIsolationState) {}

  // Per SVG 1.1 objectBoundingBox ignores clipping, masking, filter effects,
  // opacity and stroke-width.
  // This is used for all computation of objectBoundingBox relative units and by
  // SVGGraphicsElement::getBBox().
  // NOTE: Markers are not specifically ignored here by SVG 1.1 spec, but we
  // ignore them since stroke-width is ignored (and marker size can depend on
  // stroke-width). objectBoundingBox is returned local coordinates.
  // The name objectBoundingBox is taken from the SVG 1.1 spec.
  virtual FloatRect ObjectBoundingBox() const;
  virtual FloatRect StrokeBoundingBox() const;

  // Returns the smallest rectangle enclosing all of the painted content
  // respecting clipping, masking, filters, opacity, stroke-width and markers.
  // The local SVG coordinate space is the space where localSVGTransform
  // applies. For SVG objects defining viewports (e.g.
  // LayoutSVGViewportContainer and  LayoutSVGResourceMarker), the local SVG
  // coordinate space is the viewport space.
  virtual FloatRect VisualRectInLocalSVGCoordinates() const;

  // This returns the transform applying to the local SVG coordinate space,
  // which combines the CSS transform properties and animation motion transform.
  // See SVGElement::calculateTransform().
  // Most callsites want localToSVGParentTransform() instead.
  virtual AffineTransform LocalSVGTransform() const;

  // Returns the full transform mapping from local coordinates to parent's local
  // coordinates. For most SVG objects, this is the same as localSVGTransform.
  // For SVG objects defining viewports (see visualRectInLocalSVGCoordinates),
  // this includes any viewport transforms and x/y offsets as well as
  // localSVGTransform.
  virtual AffineTransform LocalToSVGParentTransform() const {
    return LocalSVGTransform();
  }

  // Returns the reference box for clip path layout. Note the actual bounding
  // box of the clip path can be bigger or smaller than the reference.
  FloatRect LocalReferenceBoxForClipPath() const;
  // Returns the bounding box of the clip path in local coordinates.
  Optional<FloatRect> LocalClipPathBoundingBox() const;

  // SVG uses FloatPoint precise hit testing, and passes the point in parent
  // coordinates instead of in paint invalidation container coordinates.
  // Eventually the rest of the layout tree will move to a similar model.
  virtual bool NodeAtFloatPoint(HitTestResult&,
                                const FloatPoint& point_in_parent,
                                HitTestAction);

  // End of SVG-specific methods.

  bool IsAnonymous() const { return bitfields_.IsAnonymous(); }
  bool IsAnonymousBlock() const {
    // This function is kept in sync with anonymous block creation conditions in
    // LayoutBlock::createAnonymousBlock(). This includes creating an anonymous
    // LayoutBlock having a BLOCK or BOX display. Other classes such as
    // LayoutTextFragment are not LayoutBlocks and will return false.
    // See https://bugs.webkit.org/show_bug.cgi?id=56709.
    return IsAnonymous() &&
           (Style()->Display() == EDisplay::kBlock ||
            Style()->Display() == EDisplay::kWebkitBox) &&
           Style()->StyleType() == kPseudoIdNone && IsLayoutBlock() &&
           !IsListMarker() && !IsLayoutFlowThread() &&
           !IsLayoutMultiColumnSet() && !IsLayoutFullScreen() &&
           !IsLayoutFullScreenPlaceholder();
  }
  bool IsElementContinuation() const {
    return GetNode() && GetNode()->GetLayoutObject() != this;
  }
  bool IsInlineElementContinuation() const {
    return IsElementContinuation() && IsInline();
  }
  virtual LayoutBoxModelObject* VirtualContinuation() const { return nullptr; }

  bool IsFloating() const { return bitfields_.Floating(); }

  bool IsFloatingWithNonContainingBlockParent() const {
    return IsFloating() && Parent() && !Parent()->IsLayoutBlockFlow();
  }

  // absolute or fixed positioning
  bool IsOutOfFlowPositioned() const {
    return bitfields_.IsOutOfFlowPositioned();
  }
  // relative or sticky positioning
  bool IsInFlowPositioned() const { return bitfields_.IsInFlowPositioned(); }
  bool IsRelPositioned() const { return bitfields_.IsRelPositioned(); }
  bool IsStickyPositioned() const { return bitfields_.IsStickyPositioned(); }
  bool IsFixedPositioned() const {
    return IsOutOfFlowPositioned() &&
           Style()->GetPosition() == EPosition::kFixed;
  }
  bool IsAbsolutePositioned() const {
    return IsOutOfFlowPositioned() &&
           Style()->GetPosition() == EPosition::kAbsolute;
  }
  bool IsPositioned() const { return bitfields_.IsPositioned(); }

  bool IsText() const { return bitfields_.IsText(); }
  bool IsBox() const { return bitfields_.IsBox(); }
  bool IsInline() const { return bitfields_.IsInline(); }  // inline object
  bool IsAtomicInlineLevel() const { return bitfields_.IsAtomicInlineLevel(); }
  bool IsHorizontalWritingMode() const {
    return bitfields_.HorizontalWritingMode();
  }
  bool HasFlippedBlocksWritingMode() const {
    return Style()->IsFlippedBlocksWritingMode();
  }

  bool HasLayer() const { return bitfields_.HasLayer(); }

  // This may be different from StyleRef().hasBoxDecorationBackground() because
  // some objects may have box decoration background other than from their own
  // style.
  bool HasBoxDecorationBackground() const {
    return bitfields_.HasBoxDecorationBackground();
  }

  bool BackgroundIsKnownToBeObscured() const;

  bool NeedsLayout() const {
    return bitfields_.SelfNeedsLayout() ||
           bitfields_.NormalChildNeedsLayout() ||
           bitfields_.PosChildNeedsLayout() ||
           bitfields_.NeedsSimplifiedNormalFlowLayout() ||
           bitfields_.NeedsPositionedMovementLayout();
  }

  bool SelfNeedsLayout() const { return bitfields_.SelfNeedsLayout(); }
  bool NeedsPositionedMovementLayout() const {
    return bitfields_.NeedsPositionedMovementLayout();
  }

  bool PosChildNeedsLayout() const { return bitfields_.PosChildNeedsLayout(); }
  bool NeedsSimplifiedNormalFlowLayout() const {
    return bitfields_.NeedsSimplifiedNormalFlowLayout();
  }
  bool NormalChildNeedsLayout() const {
    return bitfields_.NormalChildNeedsLayout();
  }
  bool NeedsCollectInlines() const { return bitfields_.NeedsCollectInlines(); }

  bool PreferredLogicalWidthsDirty() const {
    return bitfields_.PreferredLogicalWidthsDirty();
  }

  bool NeedsOverflowRecalcAfterStyleChange() const {
    return bitfields_.SelfNeedsOverflowRecalcAfterStyleChange() ||
           bitfields_.ChildNeedsOverflowRecalcAfterStyleChange();
  }
  bool SelfNeedsOverflowRecalcAfterStyleChange() const {
    return bitfields_.SelfNeedsOverflowRecalcAfterStyleChange();
  }
  bool ChildNeedsOverflowRecalcAfterStyleChange() const {
    return bitfields_.ChildNeedsOverflowRecalcAfterStyleChange();
  }

  bool IsSelectionBorder() const;

  bool HasClip() const {
    return IsOutOfFlowPositioned() && !Style()->HasAutoClip();
  }
  bool HasOverflowClip() const { return bitfields_.HasOverflowClip(); }
  bool HasClipRelatedProperty() const;

  bool HasTransformRelatedProperty() const {
    return bitfields_.HasTransformRelatedProperty();
  }
  bool IsTransformApplicable() const { return IsBox() || IsSVG(); }
  bool HasMask() const { return Style() && Style()->HasMask(); }
  bool HasClipPath() const { return Style() && Style()->ClipPath(); }
  bool HasHiddenBackface() const {
    return Style() &&
           Style()->BackfaceVisibility() == EBackfaceVisibility::kHidden;
  }
  bool HasBackdropFilter() const {
    return Style() && Style()->HasBackdropFilter();
  }

  // Returns |true| if any property that renders using filter operations is
  // used (including, but not limited to, 'filter' and 'box-reflect').
  // Not calling style()->hasFilterInducingProperty because some objects force
  // to ignore reflection style (e.g. LayoutInline).
  bool HasFilterInducingProperty() const {
    return (Style() && Style()->HasFilter()) || HasReflection();
  }

  bool HasShapeOutside() const { return Style() && Style()->ShapeOutside(); }

  inline bool PreservesNewline() const;

  // The pseudo element style can be cached or uncached.  Use the cached method
  // if the pseudo element doesn't respect any pseudo classes (and therefore
  // has no concept of changing state).
  ComputedStyle* GetCachedPseudoStyle(
      PseudoId,
      const ComputedStyle* parent_style = nullptr) const;
  scoped_refptr<ComputedStyle> GetUncachedPseudoStyle(
      const PseudoStyleRequest&,
      const ComputedStyle* parent_style = nullptr) const;

  LayoutView* View() const { return GetDocument().GetLayoutView(); }
  LocalFrameView* GetFrameView() const { return GetDocument().View(); }

  bool IsRooted() const;

  Node* GetNode() const { return IsAnonymous() ? nullptr : node_; }

  Node* NonPseudoNode() const {
    return IsPseudoElement() ? nullptr : GetNode();
  }

  void ClearNode() { node_ = nullptr; }

  // Returns the styled node that caused the generation of this layoutObject.
  // This is the same as node() except for layoutObjects of :before, :after and
  // :first-letter pseudo elements for which their parent node is returned.
  Node* GeneratingNode() const {
    return IsPseudoElement() ? GetNode()->ParentOrShadowHostNode() : GetNode();
  }

  Document& GetDocument() const {
    DCHECK(node_ || Parent());  // crbug.com/402056
    return node_ ? node_->GetDocument() : Parent()->GetDocument();
  }
  LocalFrame* GetFrame() const { return GetDocument().GetFrame(); }

  virtual LayoutMultiColumnSpannerPlaceholder* SpannerPlaceholder() const {
    return nullptr;
  }
  bool IsColumnSpanAll() const {
    return Style()->GetColumnSpan() == EColumnSpan::kAll &&
           SpannerPlaceholder();
  }

  // We include isLayoutButton() in this check, because buttons are
  // implemented using flex box but should still support things like
  // first-line, first-letter and text-overflow.
  // The flex box and grid specs require that flex box and grid do not
  // support first-line|first-letter, though.
  // When LayoutObject and display do not agree, allow first-line|first-letter
  // only when both indicate it's a block container.
  // TODO(cbiesinger): Remove when buttons are implemented with align-items
  // instead of flex box. crbug.com/226252.
  bool BehavesLikeBlockContainer() const {
    return (IsLayoutBlockFlow() && Style()->IsDisplayBlockContainer()) ||
           IsLayoutButton();
  }

  // May be optionally passed to container() and various other similar methods
  // that search the ancestry for some sort of containing block. Used to
  // determine if we skipped certain objects while walking the ancestry.
  class AncestorSkipInfo {
   public:
    AncestorSkipInfo(const LayoutObject* ancestor,
                     bool check_for_filters = false)
        : ancestor_(ancestor), check_for_filters_(check_for_filters) {}

    // Update skip info output based on the layout object passed.
    void Update(const LayoutObject& object) {
      if (&object == ancestor_)
        ancestor_skipped_ = true;
      if (check_for_filters_ && object.HasFilterInducingProperty())
        filter_skipped_ = true;
    }

    // TODO(mstensho): Get rid of this. It's just a temporary thing to retain
    // old behavior in LayoutObject::container().
    void ResetOutput() {
      ancestor_skipped_ = false;
      filter_skipped_ = false;
    }

    bool AncestorSkipped() const { return ancestor_skipped_; }
    bool FilterSkipped() const {
      DCHECK(check_for_filters_);
      return filter_skipped_;
    }

   private:
    // Input: A potential ancestor to look for. If we walk past this one while
    // walking the ancestry in search of some containing block, ancestorSkipped
    // will be set to true.
    const LayoutObject* ancestor_;
    // Input: When set, we'll check if we skip objects with filter inducing
    // properties.
    bool check_for_filters_;

    // Output: Set to true if |ancestor| was walked past while walking the
    // ancestry.
    bool ancestor_skipped_ = false;
    // Output: Set to true if we walked past a filter object. This will be set
    // regardless of the value of |ancestor|.
    bool filter_skipped_ = false;
  };

  // This function returns the containing block of the object.
  // Due to CSS being inconsistent, a containing block can be a relatively
  // positioned inline, thus we can't return a LayoutBlock from this function.
  //
  // This method is extremely similar to containingBlock(), but with a few
  // notable exceptions.
  // (1) For normal flow elements, it just returns the parent.
  // (2) For absolute positioned elements, it will return a relative
  //     positioned inline. containingBlock() simply skips relpositioned inlines
  //     and lets an enclosing block handle the layout of the positioned object.
  //     This does mean that computePositionedLogicalWidth and
  //     computePositionedLogicalHeight have to use container().
  //
  // Note that floating objects don't belong to either of the above exceptions.
  //
  // This function should be used for any invalidation as it would correctly
  // walk the containing block chain. See e.g. markContainerChainForLayout.
  // It is also used for correctly sizing absolutely positioned elements
  // (point 3 above).
  LayoutObject* Container(AncestorSkipInfo* = nullptr) const;
  // Finds the container as if this object is fixed-position.
  LayoutBlock* ContainerForFixedPosition(AncestorSkipInfo* = nullptr) const;
  // Finds the containing block as if this object is absolute-position.
  LayoutBlock* ContainingBlockForAbsolutePosition(
      AncestorSkipInfo* = nullptr) const;

  virtual LayoutObject* HoverAncestor() const { return Parent(); }

  Element* OffsetParent(const Element* = nullptr) const;

  void MarkContainerNeedsCollectInlines();
  void ClearNeedsCollectInlines() { SetNeedsCollectInlines(false); }

  void MarkContainerChainForLayout(bool schedule_relayout = true,
                                   SubtreeLayoutScope* = nullptr);
  void SetNeedsLayout(LayoutInvalidationReasonForTracing,
                      MarkingBehavior = kMarkContainerChain,
                      SubtreeLayoutScope* = nullptr);
  void SetNeedsLayoutAndFullPaintInvalidation(
      LayoutInvalidationReasonForTracing,
      MarkingBehavior = kMarkContainerChain,
      SubtreeLayoutScope* = nullptr);
  void ClearNeedsLayout();
  void SetChildNeedsLayout(MarkingBehavior = kMarkContainerChain,
                           SubtreeLayoutScope* = nullptr);
  void SetNeedsPositionedMovementLayout();
  void SetPreferredLogicalWidthsDirty(MarkingBehavior = kMarkContainerChain);
  void ClearPreferredLogicalWidthsDirty();

  void SetNeedsLayoutAndPrefWidthsRecalc(
      LayoutInvalidationReasonForTracing reason) {
    SetNeedsLayout(reason);
    SetPreferredLogicalWidthsDirty();
  }
  void SetNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(
      LayoutInvalidationReasonForTracing reason) {
    SetNeedsLayoutAndFullPaintInvalidation(reason);
    SetPreferredLogicalWidthsDirty();
  }

  void SetPositionState(EPosition position) {
    DCHECK(
        (position != EPosition::kAbsolute && position != EPosition::kFixed) ||
        IsBox());
    bitfields_.SetPositionedState(position);
  }
  void ClearPositionedState() { bitfields_.ClearPositionedState(); }

  void SetFloating(bool is_floating) { bitfields_.SetFloating(is_floating); }
  void SetInline(bool is_inline) { bitfields_.SetIsInline(is_inline); }

  void SetHasBoxDecorationBackground(bool);

  enum BackgroundObscurationState {
    kBackgroundObscurationStatusInvalid,
    kBackgroundKnownToBeObscured,
    kBackgroundMayBeVisible,
  };
  void InvalidateBackgroundObscurationStatus();
  virtual bool ComputeBackgroundIsKnownToBeObscured() const { return false; }

  void SetIsText() { bitfields_.SetIsText(true); }
  void SetIsBox() { bitfields_.SetIsBox(true); }
  void SetIsAtomicInlineLevel(bool is_atomic_inline_level) {
    bitfields_.SetIsAtomicInlineLevel(is_atomic_inline_level);
  }
  void SetHorizontalWritingMode(bool has_horizontal_writing_mode) {
    bitfields_.SetHorizontalWritingMode(has_horizontal_writing_mode);
  }
  void SetHasOverflowClip(bool has_overflow_clip) {
    bitfields_.SetHasOverflowClip(has_overflow_clip);
  }
  void SetHasLayer(bool has_layer) { bitfields_.SetHasLayer(has_layer); }
  void SetHasTransformRelatedProperty(bool has_transform) {
    bitfields_.SetHasTransformRelatedProperty(has_transform);
  }
  void SetHasReflection(bool has_reflection) {
    bitfields_.SetHasReflection(has_reflection);
  }
  void SetCanContainFixedPositionObjects(bool can_contain_fixed_position) {
    bitfields_.SetCanContainFixedPositionObjects(can_contain_fixed_position);
  }

  // paintOffset is the offset from the origin of the GraphicsContext at which
  // to paint the current object.
  virtual void Paint(const PaintInfo&, const LayoutPoint& paint_offset) const;

  virtual bool RecalcOverflowAfterStyleChange();

  // Subclasses must reimplement this method to compute the size and position
  // of this object and all its descendants.
  //
  // By default, layout only lays out the children that are marked for layout.
  // In some cases, layout has to force laying out more children. An example is
  // when the width of the LayoutObject changes as this impacts children with
  // 'width' set to auto.
  virtual void UpdateLayout() = 0;
  virtual bool UpdateImageLoadingPriorities() { return false; }

  void HandleSubtreeModifications();
  virtual void SubtreeDidChange() {}

  // Flags used to mark if an object consumes subtree change notifications.
  bool ConsumesSubtreeChangeNotification() const {
    return bitfields_.ConsumesSubtreeChangeNotification();
  }
  void SetConsumesSubtreeChangeNotification() {
    bitfields_.SetConsumesSubtreeChangeNotification(true);
  }

  // Flags used to mark if a descendant subtree of this object has changed.
  void NotifyOfSubtreeChange();
  void NotifyAncestorsOfSubtreeChange();
  bool WasNotifiedOfSubtreeChange() const {
    return bitfields_.NotifiedOfSubtreeChange();
  }

  // Flags used to signify that a layoutObject needs to be notified by its
  // descendants that they have had their child subtree changed.
  void RegisterSubtreeChangeListenerOnDescendants(bool);
  bool HasSubtreeChangeListenerRegistered() const {
    return bitfields_.SubtreeChangeListenerRegistered();
  }

  /* This function performs a layout only if one is needed. */
  DISABLE_CFI_PERF void LayoutIfNeeded() {
    if (NeedsLayout())
      UpdateLayout();
  }

  void ForceLayout();
  void ForceChildLayout();

  // Used for element state updates that cannot be fixed with a paint
  // invalidation and do not need a relayout.
  virtual void UpdateFromElement() {}

  virtual void AddAnnotatedRegions(Vector<AnnotatedRegionValue>&);

  CompositingState GetCompositingState() const;
  virtual CompositingReasons AdditionalCompositingReasons() const;

  bool HitTest(HitTestResult&,
               const HitTestLocation& location_in_container,
               const LayoutPoint& accumulated_offset,
               HitTestFilter = kHitTestAll);
  // Returns the node that is ultimately added to the hit test result. Some
  // objects report a hit testing node that is not their own (such as
  // continuations and some psuedo elements) and it is important that the
  // node be consistent between point- and list-based hit test results.
  virtual Node* NodeForHitTest() const;
  virtual void UpdateHitTestResult(HitTestResult&, const LayoutPoint&);
  virtual bool NodeAtPoint(HitTestResult&,
                           const HitTestLocation& location_in_container,
                           const LayoutPoint& accumulated_offset,
                           HitTestAction);

  virtual PositionWithAffinity PositionForPoint(const LayoutPoint&);
  PositionWithAffinity CreatePositionWithAffinity(int offset, TextAffinity);
  PositionWithAffinity CreatePositionWithAffinity(int offset);
  PositionWithAffinity CreatePositionWithAffinity(const Position&);

  virtual void DirtyLinesFromChangedChild(
      LayoutObject*,
      MarkingBehavior marking_behaviour = kMarkContainerChain);

  // Set the style of the object and update the state of the object accordingly.
  void SetStyle(scoped_refptr<ComputedStyle>);

  // Set the style of the object if it's generated content.
  void SetPseudoStyle(scoped_refptr<ComputedStyle>);

  // Updates only the local style ptr of the object.  Does not update the state
  // of the object, and so only should be called when the style is known not to
  // have changed (or from setStyle).
  void SetStyleInternal(scoped_refptr<ComputedStyle> style) {
    style_ = std::move(style);
  }

  void SetStyleWithWritingModeOf(scoped_refptr<ComputedStyle>,
                                 LayoutObject* parent);
  void SetStyleWithWritingModeOfParent(scoped_refptr<ComputedStyle>);
  void AddChildWithWritingModeOfParent(LayoutObject* new_child,
                                       LayoutObject* before_child);

  void FirstLineStyleDidChange(const ComputedStyle& old_style,
                               const ComputedStyle& new_style);

  void ClearBaseComputedStyle();

  // This function returns an enclosing non-anonymous LayoutBlock for this
  // element. This function is not always returning the containing block as
  // defined by CSS. In particular:
  // - if the CSS containing block is a relatively positioned inline,
  //   the function returns the inline's enclosing non-anonymous LayoutBlock.
  //   This means that a LayoutInline would be skipped (expected as it's not a
  //   LayoutBlock) but so would be an inline LayoutTable or LayoutBlockFlow.
  //   TODO(jchaffraix): Is that REALLY what we want here?
  // - if the CSS containing block is anonymous, we find its enclosing
  //   non-anonymous LayoutBlock.
  //   Note that in the previous examples, the returned LayoutBlock has no
  //   logical relationship to the original element.
  //
  // LayoutBlocks are the one that handle laying out positioned elements,
  // thus this function is important during layout, to insert the positioned
  // elements into the correct LayoutBlock.
  //
  // See container() for the function that returns the containing block.
  // See LayoutBlock.h for some extra explanations on containing blocks.
  LayoutBlock* ContainingBlock(AncestorSkipInfo* = nullptr) const;

  bool CanContainAbsolutePositionObjects() const {
    return style_->CanContainAbsolutePositionObjects() ||
           CanContainFixedPositionObjects();
  }
  bool CanContainFixedPositionObjects() const {
    return bitfields_.CanContainFixedPositionObjects();
  }

  // Convert the given local point to absolute coordinates
  // FIXME: Temporary. If UseTransforms is true, take transforms into account.
  // Eventually localToAbsolute() will always be transform-aware.
  FloatPoint LocalToAbsolute(const FloatPoint& local_point = FloatPoint(),
                             MapCoordinatesFlags = 0) const;

  // If the LayoutBoxModelObject ancestor is non-null, the input point is in the
  // space of the ancestor.
  // Otherwise:
  //   If TraverseDocumentBoundaries is specified, the input point is in the
  //   space of the local root frame.
  //   Otherwise, the input point is in the space of the containing frame.
  FloatPoint AncestorToLocal(LayoutBoxModelObject*,
                             const FloatPoint&,
                             MapCoordinatesFlags = 0) const;
  FloatPoint AbsoluteToLocal(const FloatPoint& point,
                             MapCoordinatesFlags mode = 0) const {
    return AncestorToLocal(nullptr, point, mode);
  }

  // Convert a local quad to absolute coordinates, taking transforms into
  // account.
  FloatQuad LocalToAbsoluteQuad(const FloatQuad& quad,
                                MapCoordinatesFlags mode = 0) const {
    return LocalToAncestorQuad(quad, nullptr, mode);
  }

  // Convert a quad in ancestor coordinates to local coordinates.
  // If the LayoutBoxModelObject ancestor is non-null, the input quad is in the
  // space of the ancestor.
  // Otherwise:
  //   If TraverseDocumentBoundaries is specified, the input quad is in the
  //   space of the local root frame.
  //   Otherwise, the input quad is in the space of the containing frame.
  FloatQuad AncestorToLocalQuad(LayoutBoxModelObject*,
                                const FloatQuad&,
                                MapCoordinatesFlags mode = 0) const;
  FloatQuad AbsoluteToLocalQuad(const FloatQuad& quad,
                                MapCoordinatesFlags mode = 0) const {
    return AncestorToLocalQuad(nullptr, quad, mode);
  }

  // Convert a local quad into the coordinate system of container, taking
  // transforms into account.
  // If the LayoutBoxModelObject ancestor is non-null, the result will be in the
  // space of the ancestor.
  // Otherwise:
  //   If TraverseDocumentBoundaries is specified, the result will be in the
  //   space of the local root frame.
  //   Otherwise, the result will be in the space of the containing frame.
  FloatQuad LocalToAncestorQuad(const FloatQuad&,
                                const LayoutBoxModelObject* ancestor,
                                MapCoordinatesFlags = 0) const;
  FloatPoint LocalToAncestorPoint(const FloatPoint&,
                                  const LayoutBoxModelObject* ancestor,
                                  MapCoordinatesFlags = 0) const;
  void LocalToAncestorRects(Vector<LayoutRect>&,
                            const LayoutBoxModelObject* ancestor,
                            const LayoutPoint& pre_offset,
                            const LayoutPoint& post_offset) const;

  // Convert a local quad into the coordinate system of container, not
  // include transforms. See localToAncestorQuad for details.
  FloatQuad LocalToAncestorQuadWithoutTransforms(
      const FloatQuad&,
      const LayoutBoxModelObject* ancestor,
      MapCoordinatesFlags = 0) const;

  // Return the transformation matrix to map points from local to the coordinate
  // system of a container, taking transforms into account.
  // Passing null for |ancestor| behaves the same as localToAncestorQuad.
  TransformationMatrix LocalToAncestorTransform(
      const LayoutBoxModelObject* ancestor,
      MapCoordinatesFlags = 0) const;
  TransformationMatrix LocalToAbsoluteTransform(
      MapCoordinatesFlags mode = 0) const {
    return LocalToAncestorTransform(nullptr, mode);
  }

  // Return the offset from the container() layoutObject (excluding transforms
  // and multicol).
  virtual LayoutSize OffsetFromContainer(const LayoutObject*) const;
  // Return the offset from an object up the container() chain. Asserts that
  // none of the intermediate objects have transforms.
  LayoutSize OffsetFromAncestorContainer(const LayoutObject*) const;

  virtual void AbsoluteRects(Vector<IntRect>&, const LayoutPoint&) const {}

  FloatRect AbsoluteBoundingBoxFloatRect() const;
  // This returns an IntRect enclosing this object. If this object has an
  // integral size and the position has fractional values, the resultant
  // IntRect can be larger than the integral size.
  IntRect AbsoluteBoundingBoxRect(MapCoordinatesFlags = 0) const;
  // FIXME: This function should go away eventually
  IntRect AbsoluteBoundingBoxRectIgnoringTransforms() const;

  // Build an array of quads in absolute coords for line boxes
  virtual void AbsoluteQuads(Vector<FloatQuad>&,
                             MapCoordinatesFlags mode = 0) const {}

  static FloatRect AbsoluteBoundingBoxRectForRange(const EphemeralRange&);

  // The bounding box (see: absoluteBoundingBoxRect) including all descendant
  // bounding boxes.
  IntRect AbsoluteBoundingBoxRectIncludingDescendants() const;

  // For accessibility, we want the bounding box rect of this element
  // in local coordinates, which can then be converted to coordinates relative
  // to any ancestor using, e.g., localToAncestorTransform.
  virtual FloatRect LocalBoundingBoxRectForAccessibility() const = 0;

  // This function returns the minimal logical width this object can have
  // without overflowing. This means that all the opportunities for wrapping
  // have been taken.
  //
  // See INTRINSIC SIZES / PREFERRED LOGICAL WIDTHS above.
  //
  // CSS 2.1 calls this width the "preferred minimum width" (thus this name)
  // and "minimum content width" (for table).
  // However CSS 3 calls it the "min-content inline size".
  // https://drafts.csswg.org/css-sizing-3/#min-content-inline-size
  // TODO(jchaffraix): We will probably want to rename it to match CSS 3.
  virtual LayoutUnit MinPreferredLogicalWidth() const { return LayoutUnit(); }

  // This function returns the maximum logical width this object can have.
  //
  // See INTRINSIC SIZES / PREFERRED LOGICAL WIDTHS above.
  //
  // CSS 2.1 calls this width the "preferred width". However CSS 3 calls it
  // the "max-content inline size".
  // https://drafts.csswg.org/css-sizing-3/#max-content-inline-size
  // TODO(jchaffraix): We will probably want to rename it to match CSS 3.
  virtual LayoutUnit MaxPreferredLogicalWidth() const { return LayoutUnit(); }

  const ComputedStyle* Style() const { return style_.get(); }
  ComputedStyle* MutableStyle() const { return style_.get(); }

  // style_ can only be nullptr before the first style is set, thus most
  // callers will never see a nullptr style and should use StyleRef().
  // FIXME: It would be better if style() returned a const reference.
  const ComputedStyle& StyleRef() const { return MutableStyleRef(); }
  ComputedStyle& MutableStyleRef() const {
    DCHECK(style_);
    return *style_;
  }

  /* The following methods are inlined in LayoutObjectInlines.h */
  inline const ComputedStyle* FirstLineStyle() const;
  inline const ComputedStyle& FirstLineStyleRef() const;
  inline const ComputedStyle* Style(bool first_line) const;
  inline const ComputedStyle& StyleRef(bool first_line) const;

  static inline Color ResolveColor(const ComputedStyle& style_to_use,
                                   CSSPropertyID color_property) {
    return style_to_use.VisitedDependentColor(color_property);
  }

  inline Color ResolveColor(CSSPropertyID color_property) const {
    return Style()->VisitedDependentColor(color_property);
  }

  virtual CursorDirective GetCursor(const LayoutPoint&, Cursor&) const;

  // Return the LayoutBoxModelObject in the container chain which is responsible
  // for painting this object. The function crosses frames boundaries so the
  // returned value can be in a different document.
  //
  // This is the container that should be passed to the '*forPaintInvalidation'
  // methods.
  const LayoutBoxModelObject& ContainerForPaintInvalidation() const;

  bool IsPaintInvalidationContainer() const;

  // Invalidate the paint of a specific subrectangle within a given object. The
  // rect is in the object's coordinate space.
  void InvalidatePaintRectangle(const LayoutRect&);

  void SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants();

  // Returns the rect that should have paint invalidated whenever this object
  // changes. The rect is in the view's coordinate space. This method deals with
  // outlines and overflow.
  virtual LayoutRect AbsoluteVisualRect() const;

  // Returns the rect that should have paint invalidated whenever this object
  // changes. The rect is in the object's local coordinate space. This is for
  // non-SVG objects and LayoutSVGRoot only. SVG objects (except LayoutSVGRoot)
  // should use visualRectInLocalSVGCoordinates() and map with SVG transforms
  // instead.
  LayoutRect LocalVisualRect() const {
    if (StyleRef().Visibility() != EVisibility::kVisible &&
        VisualRectRespectsVisibility())
      return LayoutRect();
    return LocalVisualRectIgnoringVisibility();
  }

  // Given a rect in the object's coordinate space, mutates the rect into one
  // representing the size of its visual painted output as if |ancestor| was the
  // root of the page: the rect is modified by any intervening clips, transforms
  // and scrolls between |this| and |ancestor| (not inclusive of |ancestor|),
  // but not any above |ancestor|.
  // The output is in the physical, painted coordinate pixel space of
  // |ancestor|.
  // Overflow clipping, CSS clipping and scrolling is *not* applied for
  // |ancestor| itself if |ancestor| scrolls overflow.
  // The output rect is suitable for purposes such as paint invalidation.
  //
  // If visualRectFlags has the EdgeInclusive bit set, clipping operations will
  // use/ LayoutRect::inclusiveIntersect, and the return value of
  // inclusiveIntersect will be propagated to the return value of this method.
  // Otherwise, clipping operations will use LayoutRect::intersect, and the
  // return value will be true only if the clipped rect has non-zero area.
  // See the documentation for LayoutRect::inclusiveIntersect for more
  // information.
  bool MapToVisualRectInAncestorSpace(
      const LayoutBoxModelObject* ancestor,
      LayoutRect&,
      VisualRectFlags = kDefaultVisualRectFlags) const;

  // Do not call this method directly. Call mapToVisualRectInAncestorSpace
  // instead.
  virtual bool MapToVisualRectInAncestorSpaceInternal(
      const LayoutBoxModelObject* ancestor,
      TransformState&,
      VisualRectFlags = kDefaultVisualRectFlags) const;

  // Return the offset to the column in which the specified point (in
  // flow-thread coordinates) lives. This is used to convert a flow-thread point
  // to a point in the containing coordinate space.
  virtual LayoutSize ColumnOffset(const LayoutPoint&) const {
    return LayoutSize();
  }

  virtual unsigned length() const { return 1; }

  bool IsFloatingOrOutOfFlowPositioned() const {
    return (IsFloating() || IsOutOfFlowPositioned());
  }

  bool IsTransparent() const { return Style()->HasOpacity(); }
  float Opacity() const { return Style()->Opacity(); }

  bool HasReflection() const { return bitfields_.HasReflection(); }

  // The current selection state for an object.  For blocks, the state refers to
  // the state of the leaf descendants (as described above in the SelectionState
  // enum declaration).
  SelectionState GetSelectionState() const {
    return bitfields_.GetSelectionState();
  }
  virtual void SetSelectionState(SelectionState state) {
    bitfields_.SetSelectionState(state);
  }
  inline void SetSelectionStateIfNeeded(SelectionState);
  bool CanUpdateSelectionOnRootLineBoxes() const;

  // A single rectangle that encompasses all of the selected objects within this
  // object. Used to determine the tightest possible bounding box for the
  // selection. The rect returned is in the object's local coordinate space.
  virtual LayoutRect LocalSelectionRect() const { return LayoutRect(); }

  // View coordinates means the coordinate space of |view()|.
  LayoutRect SelectionRectInViewCoordinates() const;

  bool CanBeSelectionLeaf() const;
  bool HasSelectedChildren() const {
    return GetSelectionState() != SelectionState::kNone;
  }

  bool IsSelectable() const;

  /**
     * Returns the local coordinates of the caret within this layout object.
     * @param caretOffset zero-based offset determining position within the
   * layout object.
     * @param extraWidthToEndOfLine optional out arg to give extra width to end
   * of line -
     * useful for character range rect computations
     */
  virtual LayoutRect LocalCaretRect(
      const InlineBox*,
      int caret_offset,
      LayoutUnit* extra_width_to_end_of_line = nullptr) const;

  // When performing a global document tear-down, the layoutObject of the
  // document is cleared. We use this as a hook to detect the case of document
  // destruction and don't waste time doing unnecessary work.
  bool DocumentBeingDestroyed() const;

  void DestroyAndCleanupAnonymousWrappers();

  // While the destroy() method is virtual, this should only be overriden in
  // very rare circumstances.
  // You want to override willBeDestroyed() instead unless you explicitly need
  // to stop this object from being destroyed (for example,
  // LayoutEmbeddedContent overrides destroy() for this purpose).
  virtual void Destroy();

  // Virtual function helpers for the deprecated Flexible Box Layout (display:
  // -webkit-box).
  virtual bool IsDeprecatedFlexibleBox() const { return false; }

  // Virtual function helper for the new FlexibleBox Layout (display:
  // -webkit-flex).
  virtual bool IsFlexibleBox() const { return false; }

  bool IsFlexibleBoxIncludingDeprecated() const {
    return IsFlexibleBox() || IsDeprecatedFlexibleBox();
  }

  virtual bool IsCombineText() const { return false; }

  virtual int CaretMinOffset() const;
  virtual int CaretMaxOffset() const;

  // ImageResourceClient override.
  void ImageChanged(ImageResourceContent*,
                    CanDeferInvalidation,
                    const IntRect* = nullptr) final;
  void ImageChanged(WrappedImagePtr,
                    CanDeferInvalidation,
                    const IntRect* = nullptr) override {}
  bool WillRenderImage() final;
  bool GetImageAnimationPolicy(ImageAnimationPolicy&) final;

  void Remove() {
    if (Parent())
      Parent()->RemoveChild(this);
  }

  bool VisibleToHitTestRequest(const HitTestRequest& request) const {
    return Style()->Visibility() == EVisibility::kVisible &&
           (request.IgnorePointerEventsNone() ||
            Style()->PointerEvents() != EPointerEvents::kNone) &&
           !IsInert();
  }

  // Warning: inertness can change without causing relayout.
  bool VisibleToHitTesting() const {
    return Style()->VisibleToHitTesting() && !IsInert();
  }

  // Map points and quads through elements, potentially via 3d transforms. You
  // should never need to call these directly; use localToAbsolute/
  // absoluteToLocal methods instead.
  virtual void MapLocalToAncestor(
      const LayoutBoxModelObject* ancestor,
      TransformState&,
      MapCoordinatesFlags = kApplyContainerFlip) const;
  // If the LayoutBoxModelObject ancestor is non-null, the input quad is in the
  // space of the ancestor.
  // Otherwise:
  //   If TraverseDocumentBoundaries is specified, the input quad is in the
  //   space of the local root frame.
  //   Otherwise, the input quad is in the space of the containing frame.
  virtual void MapAncestorToLocal(
      const LayoutBoxModelObject*,
      TransformState&,
      MapCoordinatesFlags = kApplyContainerFlip) const;

  // Pushes state onto LayoutGeometryMap about how to map coordinates from this
  // layoutObject to its container, or ancestorToStopAt (whichever is
  // encountered first). Returns the layoutObject which was mapped to (container
  // or ancestorToStopAt).
  virtual const LayoutObject* PushMappingToContainer(
      const LayoutBoxModelObject* ancestor_to_stop_at,
      LayoutGeometryMap&) const;

  bool ShouldUseTransformFromContainer(const LayoutObject* container) const;
  void GetTransformFromContainer(const LayoutObject* container,
                                 const LayoutSize& offset_in_container,
                                 TransformationMatrix&) const;

  bool CreatesGroup() const {
    return IsTransparent() || HasMask() || HasFilterInducingProperty() ||
           Style()->HasBlendMode();
  }

  // Collects rectangles that the outline of this object would be drawing along
  // the outside of, even if the object isn't styled with a outline for now. The
  // rects also cover continuations.
  enum IncludeBlockVisualOverflowOrNot {
    kDontIncludeBlockVisualOverflow,
    kIncludeBlockVisualOverflow,
  };
  virtual void AddOutlineRects(Vector<LayoutRect>&,
                               const LayoutPoint& additional_offset,
                               IncludeBlockVisualOverflowOrNot) const {}

  // For history and compatibility reasons, we draw outline:auto (for focus
  // rings) and normal style outline differently.
  // Focus rings enclose block visual overflows (of line boxes and descendants),
  // while normal outlines don't.
  IncludeBlockVisualOverflowOrNot OutlineRectsShouldIncludeBlockVisualOverflow()
      const {
    return StyleRef().OutlineStyleIsAuto() ? kIncludeBlockVisualOverflow
                                           : kDontIncludeBlockVisualOverflow;
  }

  // Collects rectangles enclosing visual overflows of the DOM subtree under
  // this object.
  // The rects also cover continuations which may be not in the layout subtree
  // of this object.
  // TODO(crbug.com/614781): Currently the result rects don't cover list markers
  // and outlines.
  void AddElementVisualOverflowRects(
      Vector<LayoutRect>& rects,
      const LayoutPoint& additional_offset) const {
    AddOutlineRects(rects, additional_offset, kIncludeBlockVisualOverflow);
  }

  // Returns the rect enclosing united visual overflow of the DOM subtree under
  // this object. It includes continuations which may be not in the layout
  // subtree of this object.
  virtual IntRect AbsoluteElementBoundingBoxRect() const;

  // Compute a list of hit-test rectangles per layer rooted at this
  // layoutObject with at most the given touch action.
  virtual void ComputeLayerHitTestRects(LayerHitTestRects&, TouchAction) const;

  static RespectImageOrientationEnum ShouldRespectImageOrientation(
      const LayoutObject*);

  bool IsRelayoutBoundaryForInspector() const;

  // The visual rect, in the the space of the paint invalidation container
  // (*not* the graphics layer that paints this object).
  LayoutRect VisualRectIncludingCompositedScrolling(
      const LayoutBoxModelObject& paint_invalidation_container) const;

  // Called when the previous visual rect(s) is no longer valid.
  virtual void ClearPreviousVisualRects();

  PaintInvalidationReason FullPaintInvalidationReason() const {
    return bitfields_.FullPaintInvalidationReason();
  }
  bool ShouldDoFullPaintInvalidation() const {
    return bitfields_.FullPaintInvalidationReason() !=
           PaintInvalidationReason::kNone;
  }
  void SetShouldDoFullPaintInvalidation(
      PaintInvalidationReason = PaintInvalidationReason::kFull);
  void SetShouldDoFullPaintInvalidationWithoutGeometryChange(
      PaintInvalidationReason = PaintInvalidationReason::kFull);
  void ClearShouldDoFullPaintInvalidation() {
    bitfields_.SetFullPaintInvalidationReason(PaintInvalidationReason::kNone);
  }

  void ClearPaintInvalidationFlags();

  bool MayNeedPaintInvalidation() const {
    return bitfields_.MayNeedPaintInvalidation();
  }
  void SetMayNeedPaintInvalidation();
  void SetMayNeedPaintInvalidationWithoutGeometryChange();

  bool MayNeedPaintInvalidationSubtree() const {
    return bitfields_.MayNeedPaintInvalidationSubtree();
  }
  void SetMayNeedPaintInvalidationSubtree();

  bool NeedsPaintOffsetAndVisualRectUpdate() const {
    return bitfields_.NeedsPaintOffsetAndVisualRectUpdate();
  }

  bool MayNeedPaintInvalidationAnimatedBackgroundImage() const {
    return bitfields_.MayNeedPaintInvalidationAnimatedBackgroundImage();
  }
  void SetMayNeedPaintInvalidationAnimatedBackgroundImage();

  bool ShouldInvalidateSelection() const {
    return bitfields_.ShouldInvalidateSelection();
  }
  void SetShouldInvalidateSelection();

  bool ShouldCheckForPaintInvalidation() const {
    return MayNeedPaintInvalidation() || ShouldDoFullPaintInvalidation();
  }

  virtual LayoutRect ViewRect() const;

  // New version to replace the above old version.
  virtual PaintInvalidationReason InvalidatePaint(
      const PaintInvalidatorContext&) const;

  // When this object is invalidated for paint, this method is called to
  // invalidate any DisplayItemClients owned by this object, including the
  // object itself, LayoutText/LayoutInline line boxes, etc.,
  // not including children which will be invalidated normally during
  // invalidateTreeIfNeeded() and parts which are invalidated separately (e.g.
  // scrollbars). The caller should ensure the painting layer has been
  // setNeedsRepaint before calling this function.
  virtual void InvalidateDisplayItemClients(PaintInvalidationReason) const;

  virtual bool HasNonCompositedScrollbars() const { return false; }

  // Called before anonymousChild.setStyle(). Override to set custom styles for
  // the child.
  virtual void UpdateAnonymousChildStyle(const LayoutObject& anonymous_child,
                                         ComputedStyle& style) const {}

  // Returns a rect corresponding to this LayoutObject's bounds for use in
  // debugging output
  virtual LayoutRect DebugRect() const;

  // Each LayoutObject has one or more painting fragments (exactly one
  // in the absence of multicol/pagination).
  // See ../paint/README.md for more on fragments.
  const FragmentData& FirstFragment() const { return fragment_; }

  // Returns the bounding box of the visual rects of all fragments.
  LayoutRect FragmentsVisualRectBoundingBox() const;

  // Painters can use const methods only, except for these explicitly declared
  // methods.
  class CORE_EXPORT MutableForPainting {
   public:
    // Convenience mutator that clears paint invalidation flags and this object
    // and its descendants' needs-paint-property-update flags.
    void ClearPaintFlags() {
      DCHECK_EQ(layout_object_.GetDocument().Lifecycle().GetState(),
                DocumentLifecycle::kInPrePaint);
      layout_object_.ClearPaintInvalidationFlags();
      layout_object_.bitfields_.SetNeedsPaintPropertyUpdate(false);
      layout_object_.bitfields_.SetSubtreeNeedsPaintPropertyUpdate(false);
      layout_object_.bitfields_.SetDescendantNeedsPaintPropertyUpdate(false);
    }
    void SetShouldDoFullPaintInvalidation(PaintInvalidationReason reason) {
      layout_object_.SetShouldDoFullPaintInvalidation(reason);
    }
    void SetShouldDoFullPaintInvalidationWithoutGeometryChange(
        PaintInvalidationReason reason) {
      layout_object_.SetShouldDoFullPaintInvalidationWithoutGeometryChange(
          reason);
    }
    void SetBackgroundChangedSinceLastPaintInvalidation() {
      layout_object_.SetBackgroundChangedSinceLastPaintInvalidation();
    }
    void EnsureIsReadyForPaintInvalidation() {
      layout_object_.EnsureIsReadyForPaintInvalidation();
    }

    // The following setters store the current values as calculated during the
    // pre-paint tree walk. TODO(wangxianzhu): Add check of lifecycle states.
    void SetVisualRect(const LayoutRect& r) {
      layout_object_.fragment_.SetVisualRect(r);
    }

    void SetSelectionVisualRect(const LayoutRect& r) {
      if (layout_object_.fragment_.GetRarePaintData() || !r.IsEmpty()) {
        layout_object_.fragment_.EnsureRarePaintData().SetSelectionVisualRect(
            r);
      }
    }

    void SetPreviousBackgroundObscured(bool b) {
      layout_object_.SetPreviousBackgroundObscured(b);
    }
    void UpdatePreviousOutlineMayBeAffectedByDescendants() {
      layout_object_.SetPreviousOutlineMayBeAffectedByDescendants(
          layout_object_.OutlineMayBeAffectedByDescendants());
    }

    void ClearPreviousVisualRects() {
      layout_object_.ClearPreviousVisualRects();
    }
    void SetNeedsPaintPropertyUpdate() {
      layout_object_.SetNeedsPaintPropertyUpdate();
    }

    void SetPartialInvalidationRect(const LayoutRect& r) {
      layout_object_.SetPartialInvalidationRect(r);
    }

#if DCHECK_IS_ON()
    // Same as setNeedsPaintPropertyUpdate() but does not mark ancestors as
    // having a descendant needing a paint property update.
    void SetOnlyThisNeedsPaintPropertyUpdateForTesting() {
      layout_object_.bitfields_.SetNeedsPaintPropertyUpdate(true);
    }
    void ClearNeedsPaintPropertyUpdateForTesting() {
      layout_object_.bitfields_.SetNeedsPaintPropertyUpdate(false);
    }
#endif

    FragmentData& FirstFragment() { return layout_object_.fragment_; }

   protected:
    friend class LayoutBoxModelObject;
    friend class LayoutScrollbar;
    friend class PaintInvalidationCapableScrollableArea;
    friend class PaintInvalidator;
    friend class PaintPropertyTreeBuilder;
    friend class PrePaintTreeWalk;
    FRIEND_TEST_ALL_PREFIXES(AnimationCompositorAnimationsTest,
                             canStartElementOnCompositorTransformSPv2);
    FRIEND_TEST_ALL_PREFIXES(AnimationCompositorAnimationsTest,
                             canStartElementOnCompositorEffectSPv2);
    FRIEND_TEST_ALL_PREFIXES(PrePaintTreeWalkTest, ClipRects);
    FRIEND_TEST_ALL_PREFIXES(LayoutObjectTest, VisualRect);
    FRIEND_TEST_ALL_PREFIXES(LayoutObjectTest,
                             LocationInBackingAndSelectionVisualRect);
    FRIEND_TEST_ALL_PREFIXES(BoxPaintInvalidatorTest,
                             ComputePaintInvalidationReasonBasic);

    friend class LayoutObject;
    MutableForPainting(const LayoutObject& layout_object)
        : layout_object_(const_cast<LayoutObject&>(layout_object)) {}

    LayoutObject& layout_object_;
  };
  MutableForPainting GetMutableForPainting() const {
    return MutableForPainting(*this);
  }

  // Paint properties (see: |ObjectPaintProperties|) are built from an object's
  // state (location, transform, etc) as well as properties from ancestors.
  // When these inputs change, setNeedsPaintPropertyUpdate will cause a property
  // tree update during the next document lifecycle update.
  //
  // In addition to tracking if an object needs its own paint properties
  // updated, setNeedsPaintPropertyUpdate marks all ancestors as having a
  // descendant needing a paint property update too.
  void SetNeedsPaintPropertyUpdate();
  bool NeedsPaintPropertyUpdate() const {
    return bitfields_.NeedsPaintPropertyUpdate();
  }
  void SetSubtreeNeedsPaintPropertyUpdate() {
    bitfields_.SetSubtreeNeedsPaintPropertyUpdate(true);
    SetNeedsPaintPropertyUpdate();
  }
  bool SubtreeNeedsPaintPropertyUpdate() const {
    return bitfields_.SubtreeNeedsPaintPropertyUpdate();
  }
  bool DescendantNeedsPaintPropertyUpdate() const {
    return bitfields_.DescendantNeedsPaintPropertyUpdate();
  }
  // Main thread scrolling reasons require fully updating paint propeties of all
  // ancestors (see: ScrollPaintPropertyNode.h).
  void SetAncestorsNeedPaintPropertyUpdateForMainThreadScrolling();

  void SetIsScrollAnchorObject() { bitfields_.SetIsScrollAnchorObject(true); }
  // Clears the IsScrollAnchorObject bit if and only if no ScrollAnchors still
  // reference this LayoutObject.
  void MaybeClearIsScrollAnchorObject();

  bool ScrollAnchorDisablingStyleChanged() {
    return bitfields_.ScrollAnchorDisablingStyleChanged();
  }
  void SetScrollAnchorDisablingStyleChanged(bool changed) {
    bitfields_.SetScrollAnchorDisablingStyleChanged(changed);
  }

  void ClearChildNeedsOverflowRecalcAfterStyleChange() {
    bitfields_.SetChildNeedsOverflowRecalcAfterStyleChange(false);
  }

  bool CompositedScrollsWithRespectTo(
      const LayoutBoxModelObject& paint_invalidation_container) const;
  IntSize ScrollAdjustmentForPaintInvalidation(
      const LayoutBoxModelObject& paint_invalidation_container) const;

  bool PreviousBackgroundObscured() const {
    return bitfields_.PreviousBackgroundObscured();
  }
  void SetPreviousBackgroundObscured(bool b) {
    bitfields_.SetPreviousBackgroundObscured(b);
  }

  bool IsBackgroundAttachmentFixedObject() const {
    return bitfields_.IsBackgroundAttachmentFixedObject();
  }

  bool BackgroundChangedSinceLastPaintInvalidation() const {
    return bitfields_.BackgroundChangedSinceLastPaintInvalidation();
  }
  void SetBackgroundChangedSinceLastPaintInvalidation() {
    bitfields_.SetBackgroundChangedSinceLastPaintInvalidation(true);
  }

  bool OutlineMayBeAffectedByDescendants() const {
    return bitfields_.OutlineMayBeAffectedByDescendants();
  }
  bool PreviousOutlineMayBeAffectedByDescendants() const {
    return bitfields_.PreviousOutlineMayBeAffectedByDescendants();
  }

  LayoutRect SelectionVisualRect() const {
    return fragment_.GetRarePaintData()
               ? fragment_.GetRarePaintData()->SelectionVisualRect()
               : LayoutRect();
  }
  LayoutRect PartialInvalidationRect() const {
    return fragment_.GetRarePaintData()
               ? fragment_.GetRarePaintData()->PartialInvalidationRect()
               : LayoutRect();
  }

  void InvalidateIfControlStateChanged(ControlState);

 protected:
  enum LayoutObjectType {
    kLayoutObjectBr,
    kLayoutObjectCanvas,
    kLayoutObjectFieldset,
    kLayoutObjectCounter,
    kLayoutObjectDetailsMarker,
    kLayoutObjectEmbeddedObject,
    kLayoutObjectFileUploadControl,
    kLayoutObjectFrame,
    kLayoutObjectFrameSet,
    kLayoutObjectLayoutTableCol,
    kLayoutObjectListBox,
    kLayoutObjectListItem,
    kLayoutObjectListMarker,
    kLayoutObjectMedia,
    kLayoutObjectMenuList,
    kLayoutObjectNGBlockFlow,
    kLayoutObjectNGMixin,
    kLayoutObjectNGListItem,
    kLayoutObjectProgress,
    kLayoutObjectQuote,
    kLayoutObjectLayoutButton,
    kLayoutObjectLayoutFlowThread,
    kLayoutObjectLayoutFullScreen,
    kLayoutObjectLayoutFullScreenPlaceholder,
    kLayoutObjectLayoutGrid,
    kLayoutObjectLayoutIFrame,
    kLayoutObjectLayoutImage,
    kLayoutObjectLayoutInline,
    kLayoutObjectLayoutMultiColumnSet,
    kLayoutObjectLayoutMultiColumnSpannerPlaceholder,
    kLayoutObjectLayoutEmbeddedContent,
    kLayoutObjectLayoutReplaced,
    kLayoutObjectLayoutScrollbarPart,
    kLayoutObjectLayoutView,
    kLayoutObjectRuby,
    kLayoutObjectRubyBase,
    kLayoutObjectRubyRun,
    kLayoutObjectRubyText,
    kLayoutObjectSlider,
    kLayoutObjectSliderThumb,
    kLayoutObjectTable,
    kLayoutObjectTableCaption,
    kLayoutObjectTableCell,
    kLayoutObjectTableRow,
    kLayoutObjectTableSection,
    kLayoutObjectTextArea,
    kLayoutObjectTextControl,
    kLayoutObjectTextField,
    kLayoutObjectVideo,
    kLayoutObjectWidget,

    kLayoutObjectSVG, /* Keep by itself? */
    kLayoutObjectSVGRoot,
    kLayoutObjectSVGContainer,
    kLayoutObjectSVGTransformableContainer,
    kLayoutObjectSVGViewportContainer,
    kLayoutObjectSVGHiddenContainer,
    kLayoutObjectSVGShape,
    kLayoutObjectSVGText,
    kLayoutObjectSVGTextPath,
    kLayoutObjectSVGInline,
    kLayoutObjectSVGInlineText,
    kLayoutObjectSVGImage,
    kLayoutObjectSVGForeignObject,
    kLayoutObjectSVGResourceContainer,
    kLayoutObjectSVGResourceFilter,
    kLayoutObjectSVGResourceFilterPrimitive,
  };
  virtual bool IsOfType(LayoutObjectType type) const { return false; }

  // Overrides should call the superclass at the end. style_ will be 0 the
  // first time this function will be called.
  virtual void StyleWillChange(StyleDifference, const ComputedStyle& new_style);
  // Overrides should call the superclass at the start. |oldStyle| will be 0 the
  // first time this function is called.
  virtual void StyleDidChange(StyleDifference, const ComputedStyle* old_style);
  void PropagateStyleToAnonymousChildren();
  // Return true for objects that don't want style changes automatically
  // propagated via propagateStyleToAnonymousChildren(), but rather rely on
  // other custom mechanisms (if they need to be notified of parent style
  // changes at all).
  virtual bool AnonymousHasStylePropagationOverride() { return false; }

 protected:
  // This function is called before calling the destructor so that some clean-up
  // can happen regardless of whether they call a virtual function or not. As a
  // rule of thumb, this function should be preferred to the destructor. See
  // destroy() that is the one calling willBeDestroyed().
  //
  // There are 2 types of destructions: regular destructions and tree tear-down.
  // Regular destructions happen when the renderer is not needed anymore (e.g.
  // 'display' changed or the DOM Node was removed).
  // Tree tear-down is when the whole tree destroyed during navigation. It is
  // handled in the code by checking if documentBeingDestroyed() returns 'true'.
  // In this case, the code skips some unneeded expensive operations as we know
  // the tree is not reused (e.g. avoid clearing the containing block's line
  // box).
  virtual void WillBeDestroyed();

  virtual void InsertedIntoTree();
  virtual void WillBeRemovedFromTree();

  void SetDocumentForAnonymous(Document* document) {
    DCHECK(IsAnonymous());
    node_ = document;
  }

  // Add hit-test rects for the layout tree rooted at this node to the provided
  // collection on a per-Layer basis.
  // currentLayer must be the enclosing layer, and layerOffset is the current
  // offset within this layer. Subclass implementations will add any offset for
  // this layoutObject within it's container, so callers should provide only the
  // offset of the container within it's layer.
  // containerRect is a rect that has already been added for the currentLayer
  // which is likely to be a container for child elements. Any rect wholly
  // contained by containerRect can be skipped.
  virtual void AddLayerHitTestRects(
      LayerHitTestRects&,
      const PaintLayer* current_layer,
      const LayoutPoint& layer_offset,
      TouchAction supported_fast_actions,
      const LayoutRect& container_rect,
      TouchAction container_whitelisted_touch_action) const;

  // Add hit-test rects for this layoutObject only to the provided list.
  // layerOffset is the offset of this layoutObject within the current layer
  // that should be used for each result.
  virtual void ComputeSelfHitTestRects(Vector<LayoutRect>&,
                                       const LayoutPoint& layer_offset) const {}

  void SetPartialInvalidationRect(const LayoutRect& rect) {
    if (fragment_.GetRarePaintData() || !rect.IsEmpty())
      fragment_.EnsureRarePaintData().SetPartialInvalidationRect(rect);
  }

#if DCHECK_IS_ON()
  virtual bool PaintInvalidationStateIsDirty() const {
    return BackgroundChangedSinceLastPaintInvalidation() ||
           ShouldCheckForPaintInvalidation() || ShouldInvalidateSelection() ||
           NeedsPaintOffsetAndVisualRectUpdate() ||
           (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
            fragment_.GetRarePaintData() &&
            !fragment_.GetRarePaintData()->PartialInvalidationRect().IsEmpty());
  }
#endif

  // Called before paint invalidation.
  virtual void EnsureIsReadyForPaintInvalidation() { DCHECK(!NeedsLayout()); }

  void SetIsBackgroundAttachmentFixedObject(bool);

  void ClearSelfNeedsOverflowRecalcAfterStyleChange() {
    bitfields_.SetSelfNeedsOverflowRecalcAfterStyleChange(false);
  }
  void SetEverHadLayout() { bitfields_.SetEverHadLayout(true); }

  // Remove this object and all descendants from the containing
  // LayoutFlowThread.
  void RemoveFromLayoutFlowThread();

  bool ContainsInlineWithOutlineAndContinuation() const {
    return bitfields_.ContainsInlineWithOutlineAndContinuation();
  }
  void SetContainsInlineWithOutlineAndContinuation(bool b) {
    bitfields_.SetContainsInlineWithOutlineAndContinuation(b);
  }

  void SetOutlineMayBeAffectedByDescendants(bool b) {
    bitfields_.SetOutlineMayBeAffectedByDescendants(b);
  }
  void SetPreviousOutlineMayBeAffectedByDescendants(bool b) {
    bitfields_.SetPreviousOutlineMayBeAffectedByDescendants(b);
  }

  virtual bool VisualRectRespectsVisibility() const { return true; }
  virtual LayoutRect LocalVisualRectIgnoringVisibility() const;

  virtual bool CanBeSelectionLeafInternal() const { return false; }

 private:
  // Used only by applyFirstLineChanges to get a first line style based off of a
  // given new style, without accessing the cache.
  scoped_refptr<ComputedStyle> UncachedFirstLineStyle() const;

  // Adjusts a visual rect in the space of |visual_rect| to be in the space of
  // the |paint_invalidation_container|, if needed. They can be different only
  // if |paint_invalidation_container| is a composited scroller.
  void AdjustVisualRectForCompositedScrolling(
      LayoutRect& visual_rect,
      const LayoutBoxModelObject& paint_invalidation_container) const;

  FloatQuad LocalToAncestorQuadInternal(const FloatQuad&,
                                        const LayoutBoxModelObject* ancestor,
                                        MapCoordinatesFlags = 0) const;

  void ClearLayoutRootIfNeeded() const;

  bool IsInert() const;

  void UpdateImage(StyleImage*, StyleImage*);

  void ScheduleRelayout();

  void UpdateShapeImage(const ShapeValue*, const ShapeValue*);
  void UpdateFillImages(const FillLayer* old_layers,
                        const FillLayer& new_layers);
  void UpdateCursorImages(const CursorList* old_cursors,
                          const CursorList* new_cursors);
  void CheckCounterChanges(const ComputedStyle* old_style,
                           const ComputedStyle* new_style);

  void SetNeedsOverflowRecalcAfterStyleChange();

  // Walk up the parent chain and find the first scrolling block to disable
  // scroll anchoring on.
  void SetScrollAnchorDisablingStyleChangedOnAncestor();

  // FIXME: This should be 'markContaingBoxChainForOverflowRecalc when we make
  // LayoutBox recomputeOverflow-capable. crbug.com/437012 and crbug.com/434700.
  inline void MarkAncestorsForOverflowRecalcIfNeeded();

  inline void MarkAncestorsForPaintInvalidation();
  inline void SetNeedsPaintOffsetAndVisualRectUpdate();

  inline void InvalidateContainerPreferredLogicalWidths();

  LayoutObject* ContainerForAbsolutePosition(AncestorSkipInfo* = nullptr) const;

  const LayoutBoxModelObject* EnclosingCompositedContainer() const;

  LayoutFlowThread* LocateFlowThreadContainingBlock() const;
  void RemoveFromLayoutFlowThreadRecursive(LayoutFlowThread*);

  ComputedStyle* CachedFirstLineStyle() const;
  StyleDifference AdjustStyleDifference(StyleDifference) const;

  void RemoveShapeImageClient(ShapeValue*);
  void RemoveCursorImageClient(const CursorList*);

#if DCHECK_IS_ON()
  void CheckBlockPositionedObjectsNeedLayout();
#endif

  bool IsTextOrSVGChild() const { return IsText() || IsSVGChild(); }

  static bool IsAllowedToModifyLayoutTreeStructure(Document&);

  // Returns the parent LayoutObject, or nullptr. This has a special case for
  // LayoutView to return the owning LayoutObject in the containing frame.
  inline LayoutObject* ParentCrossingFrames() const;

  void InvalidatePaintForSelection();
  void ApplyPseudoStyleChanges(const ComputedStyle& old_style);
  void ApplyFirstLineChanges(const ComputedStyle& old_style);

  scoped_refptr<ComputedStyle> style_;

  // Oilpan: This untraced pointer to the owning Node is considered safe.
  UntracedMember<Node> node_;

  LayoutObject* parent_;
  LayoutObject* previous_;
  LayoutObject* next_;

#if DCHECK_IS_ON()
  unsigned has_ax_object_ : 1;
  unsigned set_needs_layout_forbidden_ : 1;
#endif

#define ADD_BOOLEAN_BITFIELD(field_name_, MethodNameBase) \
 private:                                                 \
  unsigned field_name_ : 1;                               \
                                                          \
 public:                                                  \
  bool MethodNameBase() const { return field_name_; }     \
  void Set##MethodNameBase(bool new_value) { field_name_ = new_value; }

  class LayoutObjectBitfields {
    enum PositionedState {
      kIsStaticallyPositioned = 0,
      kIsRelativelyPositioned = 1,
      kIsOutOfFlowPositioned = 2,
      kIsStickyPositioned = 3,
    };

   public:
    // LayoutObjectBitfields holds all the boolean values for LayoutObject.
    //
    // This is done to promote better packing on LayoutObject (at the expense of
    // preventing bit field packing for the subclasses). Classes concerned about
    // packing and memory use should hoist their boolean to this class. See
    // below the field from sub-classes (e.g. childrenInline).
    //
    // Some of those booleans are caches of ComputedStyle values (e.g.
    // positionState). This enables better memory locality and thus better
    // performance.
    //
    // This class is an artifact of the WebKit era where LayoutObject wasn't
    // allowed to grow and each sub-class was strictly monitored for memory
    // increase. Our measurements indicate that the size of LayoutObject and
    // subsequent classes do not impact memory or speed in a significant
    // manner. This is based on growing LayoutObject in
    // https://codereview.chromium.org/44673003 and subsequent relaxations
    // of the memory constraints on layout objects.
    LayoutObjectBitfields(Node* node)
        : self_needs_layout_(false),
          needs_positioned_movement_layout_(false),
          normal_child_needs_layout_(false),
          pos_child_needs_layout_(false),
          needs_simplified_normal_flow_layout_(false),
          self_needs_overflow_recalc_after_style_change_(false),
          child_needs_overflow_recalc_after_style_change_(false),
          preferred_logical_widths_dirty_(false),
          needs_collect_inlines_(false),
          may_need_paint_invalidation_(false),
          may_need_paint_invalidation_subtree_(false),
          may_need_paint_invalidation_animated_background_image_(false),
          needs_paint_offset_and_visual_rect_update_(false),
          should_invalidate_selection_(false),
          floating_(false),
          is_anonymous_(!node),
          is_text_(false),
          is_box_(false),
          is_inline_(true),
          is_atomic_inline_level_(false),
          horizontal_writing_mode_(true),
          has_layer_(false),
          has_overflow_clip_(false),
          has_transform_related_property_(false),
          has_reflection_(false),
          can_contain_fixed_position_objects_(false),
          has_counter_node_map_(false),
          ever_had_layout_(false),
          ancestor_line_box_dirty_(false),
          is_inside_flow_thread_(false),
          subtree_change_listener_registered_(false),
          notified_of_subtree_change_(false),
          consumes_subtree_change_notification_(false),
          children_inline_(false),
          contains_inline_with_outline_and_continuation_(false),
          always_create_line_boxes_for_layout_inline_(false),
          previous_background_obscured_(false),
          is_background_attachment_fixed_object_(false),
          is_scroll_anchor_object_(false),
          scroll_anchor_disabling_style_changed_(false),
          has_box_decoration_background_(false),
          needs_paint_property_update_(true),
          subtree_needs_paint_property_update_(true),
          descendant_needs_paint_property_update_(true),
          background_changed_since_last_paint_invalidation_(false),
          outline_may_be_affected_by_descendants_(false),
          previous_outline_may_be_affected_by_descendants_(false),
          is_truncated_(false),
          positioned_state_(kIsStaticallyPositioned),
          selection_state_(static_cast<unsigned>(SelectionState::kNone)),
          background_obscuration_state_(kBackgroundObscurationStatusInvalid),
          full_paint_invalidation_reason_(
              static_cast<unsigned>(PaintInvalidationReason::kNone)) {}

    // Self needs layout means that this layout object is marked for a full
    // layout. This is the default layout but it is expensive as it recomputes
    // everything. For CSS boxes, this includes the width (laying out the line
    // boxes again), the margins (due to block collapsing margins), the
    // positions, the height and the potential overflow.
    ADD_BOOLEAN_BITFIELD(self_needs_layout_, SelfNeedsLayout);

    // A positioned movement layout is a specialized type of layout used on
    // positioned objects that only visually moved. This layout is used when
    // changing 'top'/'left' on a positioned element or margins on an
    // out-of-flow one. Because the following operations don't impact the size
    // of the object or sibling LayoutObjects, this layout is very lightweight.
    //
    // Positioned movement layout is implemented in
    // LayoutBlock::simplifiedLayout.
    ADD_BOOLEAN_BITFIELD(needs_positioned_movement_layout_,
                         NeedsPositionedMovementLayout);

    // This boolean is set when a normal flow ('position' == static || relative)
    // child requires layout (but this object doesn't). Due to the nature of
    // CSS, laying out a child can cause the parent to resize (e.g., if 'height'
    // is auto).
    ADD_BOOLEAN_BITFIELD(normal_child_needs_layout_, NormalChildNeedsLayout);

    // This boolean is set when an out-of-flow positioned ('position' == fixed
    // || absolute) child requires layout (but this object doesn't).
    ADD_BOOLEAN_BITFIELD(pos_child_needs_layout_, PosChildNeedsLayout);

    // Simplified normal flow layout only relayouts the normal flow children,
    // ignoring the out-of-flow descendants.
    //
    // The implementation of this layout is in
    // LayoutBlock::simplifiedNormalFlowLayout.
    ADD_BOOLEAN_BITFIELD(needs_simplified_normal_flow_layout_,
                         NeedsSimplifiedNormalFlowLayout);

    // Some properties only have a visual impact and don't impact the actual
    // layout position and sizes of the object. An example of this is the
    // 'transform' property, who doesn't modify the layout but gets applied at
    // paint time. Setting this flag only recomputes the overflow information.
    ADD_BOOLEAN_BITFIELD(self_needs_overflow_recalc_after_style_change_,
                         SelfNeedsOverflowRecalcAfterStyleChange);

    // This flag is set on the ancestor of a LayoutObject needing
    // selfNeedsOverflowRecalcAfterStyleChange. This is needed as a descendant
    // overflow can bleed into its containing block's so we have to recompute it
    // in some cases.
    ADD_BOOLEAN_BITFIELD(child_needs_overflow_recalc_after_style_change_,
                         ChildNeedsOverflowRecalcAfterStyleChange);

    // This boolean marks preferred logical widths for lazy recomputation.
    //
    // See INTRINSIC SIZES / PREFERRED LOGICAL WIDTHS above about those
    // widths.
    ADD_BOOLEAN_BITFIELD(preferred_logical_widths_dirty_,
                         PreferredLogicalWidthsDirty);

    // This flag is set on inline container boxes that need to run the
    // Pre-layout phase in LayoutNG. See NGInlineNode::CollectInlines().
    // Also maybe set to inline boxes to optimize the propagation.
    ADD_BOOLEAN_BITFIELD(needs_collect_inlines_, NeedsCollectInlines);

    ADD_BOOLEAN_BITFIELD(may_need_paint_invalidation_,
                         MayNeedPaintInvalidation);
    ADD_BOOLEAN_BITFIELD(may_need_paint_invalidation_subtree_,
                         MayNeedPaintInvalidationSubtree);
    ADD_BOOLEAN_BITFIELD(may_need_paint_invalidation_animated_background_image_,
                         MayNeedPaintInvalidationAnimatedBackgroundImage);
    ADD_BOOLEAN_BITFIELD(needs_paint_offset_and_visual_rect_update_,
                         NeedsPaintOffsetAndVisualRectUpdate);
    ADD_BOOLEAN_BITFIELD(should_invalidate_selection_,
                         ShouldInvalidateSelection);

    // This boolean is the cached value of 'float'
    // (see ComputedStyle::isFloating).
    ADD_BOOLEAN_BITFIELD(floating_, Floating);

    ADD_BOOLEAN_BITFIELD(is_anonymous_, IsAnonymous);
    ADD_BOOLEAN_BITFIELD(is_text_, IsText);
    ADD_BOOLEAN_BITFIELD(is_box_, IsBox);

    // This boolean represents whether the LayoutObject is 'inline-level'
    // (a CSS concept). Inline-level boxes are laid out inside a line. If
    // unset, the box is 'block-level' and thus stack on top of its
    // siblings (think of paragraphs).
    ADD_BOOLEAN_BITFIELD(is_inline_, IsInline);

    // This boolean is set if the element is an atomic inline-level box.
    //
    // In CSS, atomic inline-level boxes are laid out on a line but they
    // are opaque from the perspective of line layout. This means that they
    // can't be split across lines like normal inline boxes (LayoutInline).
    // Examples of atomic inline-level elements: inline tables, inline
    // blocks and replaced inline elements.
    // See http://www.w3.org/TR/CSS2/visuren.html#inline-boxes.
    //
    // Our code is confused about the use of this boolean and confuses it
    // with being replaced (see LayoutReplaced about this).
    // TODO(jchaffraix): We should inspect callers and clarify their use.
    // TODO(jchaffraix): We set this boolean for replaced elements that are
    // not inline but shouldn't (crbug.com/567964). This should be enforced.
    ADD_BOOLEAN_BITFIELD(is_atomic_inline_level_, IsAtomicInlineLevel);
    ADD_BOOLEAN_BITFIELD(horizontal_writing_mode_, HorizontalWritingMode);

    ADD_BOOLEAN_BITFIELD(has_layer_, HasLayer);

    // This boolean is set if overflow != 'visible'.
    // This means that this object may need an overflow clip to be applied
    // at paint time to its visual overflow (see OverflowModel for more
    // details). Only set for LayoutBoxes and descendants.
    ADD_BOOLEAN_BITFIELD(has_overflow_clip_, HasOverflowClip);

    // This boolean is the cached value from
    // ComputedStyle::hasTransformRelatedProperty.
    ADD_BOOLEAN_BITFIELD(has_transform_related_property_,
                         HasTransformRelatedProperty);
    ADD_BOOLEAN_BITFIELD(has_reflection_, HasReflection);

    // This boolean is used to know if this LayoutObject is a container for
    // fixed position descendants.
    ADD_BOOLEAN_BITFIELD(can_contain_fixed_position_objects_,
                         CanContainFixedPositionObjects);

    // This boolean is used to know if this LayoutObject has one (or more)
    // associated CounterNode(s).
    // See class comment in LayoutCounter.h for more detail.
    ADD_BOOLEAN_BITFIELD(has_counter_node_map_, HasCounterNodeMap);

    ADD_BOOLEAN_BITFIELD(ever_had_layout_, EverHadLayout);
    ADD_BOOLEAN_BITFIELD(ancestor_line_box_dirty_, AncestorLineBoxDirty);

    ADD_BOOLEAN_BITFIELD(is_inside_flow_thread_, IsInsideFlowThread);

    ADD_BOOLEAN_BITFIELD(subtree_change_listener_registered_,
                         SubtreeChangeListenerRegistered);
    ADD_BOOLEAN_BITFIELD(notified_of_subtree_change_, NotifiedOfSubtreeChange);
    ADD_BOOLEAN_BITFIELD(consumes_subtree_change_notification_,
                         ConsumesSubtreeChangeNotification);

    // from LayoutBlock
    ADD_BOOLEAN_BITFIELD(children_inline_, ChildrenInline);

    // from LayoutBlockFlow
    ADD_BOOLEAN_BITFIELD(contains_inline_with_outline_and_continuation_,
                         ContainsInlineWithOutlineAndContinuation);

    // from LayoutInline
    ADD_BOOLEAN_BITFIELD(always_create_line_boxes_for_layout_inline_,
                         AlwaysCreateLineBoxesForLayoutInline);

    // Background obscuration status of the previous frame.
    ADD_BOOLEAN_BITFIELD(previous_background_obscured_,
                         PreviousBackgroundObscured);

    ADD_BOOLEAN_BITFIELD(is_background_attachment_fixed_object_,
                         IsBackgroundAttachmentFixedObject);
    ADD_BOOLEAN_BITFIELD(is_scroll_anchor_object_, IsScrollAnchorObject);

    // Whether changes in this LayoutObject's CSS properties since the last
    // layout should suppress any adjustments that would be made during the next
    // layout by ScrollAnchor objects for which this LayoutObject is on the path
    // from the anchor node to the scroller.
    // See http://bit.ly/sanaclap for more info.
    ADD_BOOLEAN_BITFIELD(scroll_anchor_disabling_style_changed_,
                         ScrollAnchorDisablingStyleChanged);

    ADD_BOOLEAN_BITFIELD(has_box_decoration_background_,
                         HasBoxDecorationBackground);

    // Whether the paint properties need to be updated. For more details, see
    // LayoutObject::needsPaintPropertyUpdate().
    ADD_BOOLEAN_BITFIELD(needs_paint_property_update_,
                         NeedsPaintPropertyUpdate);
    // Whether paint properties of the whole subtree need to be updated.
    ADD_BOOLEAN_BITFIELD(subtree_needs_paint_property_update_,
                         SubtreeNeedsPaintPropertyUpdate)
    // Whether the paint properties of a descendant need to be updated. For more
    // details, see LayoutObject::descendantNeedsPaintPropertyUpdate().
    ADD_BOOLEAN_BITFIELD(descendant_needs_paint_property_update_,
                         DescendantNeedsPaintPropertyUpdate);

    ADD_BOOLEAN_BITFIELD(background_changed_since_last_paint_invalidation_,
                         BackgroundChangedSinceLastPaintInvalidation);

    // Whether shape of outline may be affected by any descendants. This is
    // updated before paint invalidation, checked during paint invalidation.
    ADD_BOOLEAN_BITFIELD(outline_may_be_affected_by_descendants_,
                         OutlineMayBeAffectedByDescendants);
    // The outlineMayBeAffectedByDescendants status of the last paint
    // invalidation.
    ADD_BOOLEAN_BITFIELD(previous_outline_may_be_affected_by_descendants_,
                         PreviousOutlineMayBeAffectedByDescendants);

    ADD_BOOLEAN_BITFIELD(is_truncated_, IsTruncated);

   protected:
    // Use protected to avoid warning about unused variable.
    unsigned unused_bits_ : 4;

   private:
    // This is the cached 'position' value of this object
    // (see ComputedStyle::position).
    unsigned positioned_state_ : 2;  // PositionedState
    unsigned selection_state_ : 3;   // SelectionState
    // Mutable for getter which lazily update this field.
    mutable unsigned
        background_obscuration_state_ : 2;         // BackgroundObscurationState

    unsigned full_paint_invalidation_reason_ : 5;  // PaintInvalidationReason
    static_assert(static_cast<unsigned>(PaintInvalidationReason::kMax) <
                      (1u << 5),
                  "PaintInvalidationReason should fit in the bit field");

   public:
    bool IsOutOfFlowPositioned() const {
      return positioned_state_ == kIsOutOfFlowPositioned;
    }
    bool IsRelPositioned() const {
      return positioned_state_ == kIsRelativelyPositioned;
    }
    bool IsStickyPositioned() const {
      return positioned_state_ == kIsStickyPositioned;
    }
    bool IsInFlowPositioned() const {
      return positioned_state_ == kIsRelativelyPositioned ||
             positioned_state_ == kIsStickyPositioned;
    }
    bool IsPositioned() const {
      return positioned_state_ != kIsStaticallyPositioned;
    }

    void SetPositionedState(EPosition position_state) {
      // This maps FixedPosition and AbsolutePosition to
      // IsOutOfFlowPositioned, saving one bit.
      switch (position_state) {
        case EPosition::kStatic:
          positioned_state_ = kIsStaticallyPositioned;
          break;
        case EPosition::kRelative:
          positioned_state_ = kIsRelativelyPositioned;
          break;
        case EPosition::kAbsolute:
        case EPosition::kFixed:
          positioned_state_ = kIsOutOfFlowPositioned;
          break;
        case EPosition::kSticky:
          positioned_state_ = kIsStickyPositioned;
          break;
        default:
          NOTREACHED();
          break;
      }
    }
    void ClearPositionedState() {
      positioned_state_ = kIsStaticallyPositioned;
    }

    ALWAYS_INLINE SelectionState GetSelectionState() const {
      return static_cast<SelectionState>(selection_state_);
    }
    ALWAYS_INLINE void SetSelectionState(SelectionState selection_state) {
      selection_state_ = static_cast<unsigned>(selection_state);
    }

    ALWAYS_INLINE BackgroundObscurationState
    GetBackgroundObscurationState() const {
      return static_cast<BackgroundObscurationState>(
          background_obscuration_state_);
    }
    ALWAYS_INLINE void SetBackgroundObscurationState(
        BackgroundObscurationState s) const {
      background_obscuration_state_ = s;
    }

    PaintInvalidationReason FullPaintInvalidationReason() const {
      return static_cast<PaintInvalidationReason>(
          full_paint_invalidation_reason_);
    }
    void SetFullPaintInvalidationReason(PaintInvalidationReason reason) {
      full_paint_invalidation_reason_ = static_cast<unsigned>(reason);
    }
  };

#undef ADD_BOOLEAN_BITFIELD

  LayoutObjectBitfields bitfields_;

  void SetSelfNeedsLayout(bool b) { bitfields_.SetSelfNeedsLayout(b); }
  void SetNeedsPositionedMovementLayout(bool b) {
    bitfields_.SetNeedsPositionedMovementLayout(b);
  }
  void SetNormalChildNeedsLayout(bool b) {
    bitfields_.SetNormalChildNeedsLayout(b);
  }
  void SetPosChildNeedsLayout(bool b) { bitfields_.SetPosChildNeedsLayout(b); }
  void SetNeedsSimplifiedNormalFlowLayout(bool b) {
    bitfields_.SetNeedsSimplifiedNormalFlowLayout(b);
  }
  void SetNeedsCollectInlines(bool b) { bitfields_.SetNeedsCollectInlines(b); }

  void SetSelfNeedsOverflowRecalcAfterStyleChange() {
    bitfields_.SetSelfNeedsOverflowRecalcAfterStyleChange(true);
  }
  void SetChildNeedsOverflowRecalcAfterStyleChange() {
    bitfields_.SetChildNeedsOverflowRecalcAfterStyleChange(true);
  }

 private:
  friend class LineLayoutItem;

  // Store state between styleWillChange and styleDidChange
  static bool affects_parent_block_;

  FragmentData fragment_;
};

// FIXME: remove this once the layout object lifecycle ASSERTS are no longer
// hit.
class DeprecatedDisableModifyLayoutTreeStructureAsserts {
  STACK_ALLOCATED();
  WTF_MAKE_NONCOPYABLE(DeprecatedDisableModifyLayoutTreeStructureAsserts);

 public:
  DeprecatedDisableModifyLayoutTreeStructureAsserts();

  static bool CanModifyLayoutTreeStateInAnyState();

 private:
  AutoReset<bool> disabler_;
};

// Allow equality comparisons of LayoutObjects by reference or pointer,
// interchangeably.
DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES(LayoutObject)

inline bool LayoutObject::DocumentBeingDestroyed() const {
  return GetDocument().Lifecycle().GetState() >= DocumentLifecycle::kStopping;
}

inline bool LayoutObject::IsBeforeContent() const {
  if (Style()->StyleType() != kPseudoIdBefore)
    return false;
  // Text nodes don't have their own styles, so ignore the style on a text node.
  if (IsText() && !IsBR())
    return false;
  return true;
}

inline bool LayoutObject::IsAfterContent() const {
  if (Style()->StyleType() != kPseudoIdAfter)
    return false;
  // Text nodes don't have their own styles, so ignore the style on a text node.
  if (IsText() && !IsBR())
    return false;
  return true;
}

inline bool LayoutObject::IsBeforeOrAfterContent() const {
  return IsBeforeContent() || IsAfterContent();
}

// setNeedsLayout() won't cause full paint invalidations as
// setNeedsLayoutAndFullPaintInvalidation() does. Otherwise the two methods are
// identical.
inline void LayoutObject::SetNeedsLayout(
    LayoutInvalidationReasonForTracing reason,
    MarkingBehavior mark_parents,
    SubtreeLayoutScope* layouter) {
#if DCHECK_IS_ON()
  DCHECK(!IsSetNeedsLayoutForbidden());
#endif
  bool already_needed_layout = bitfields_.SelfNeedsLayout();
  SetSelfNeedsLayout(true);
  MarkContainerNeedsCollectInlines();
  if (!already_needed_layout) {
    TRACE_EVENT_INSTANT1(
        TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"),
        "LayoutInvalidationTracking", TRACE_EVENT_SCOPE_THREAD, "data",
        InspectorLayoutInvalidationTrackingEvent::Data(this, reason));
    if (mark_parents == kMarkContainerChain &&
        (!layouter || layouter->Root() != this))
      MarkContainerChainForLayout(!layouter, layouter);
  }
}

inline void LayoutObject::SetNeedsLayoutAndFullPaintInvalidation(
    LayoutInvalidationReasonForTracing reason,
    MarkingBehavior mark_parents,
    SubtreeLayoutScope* layouter) {
  SetNeedsLayout(reason, mark_parents, layouter);
  SetShouldDoFullPaintInvalidation();
}

inline void LayoutObject::ClearNeedsLayout() {
  // Set flags for later stages/cycles.
  SetEverHadLayout();
  SetMayNeedPaintInvalidation();

  // Clear needsLayout flags.
  SetSelfNeedsLayout(false);
  SetPosChildNeedsLayout(false);
  SetNeedsSimplifiedNormalFlowLayout(false);
  SetNormalChildNeedsLayout(false);
  SetNeedsPositionedMovementLayout(false);
  SetAncestorLineBoxDirty(false);

#if DCHECK_IS_ON()
  CheckBlockPositionedObjectsNeedLayout();
#endif

  SetScrollAnchorDisablingStyleChanged(false);
}

inline void LayoutObject::SetChildNeedsLayout(MarkingBehavior mark_parents,
                                              SubtreeLayoutScope* layouter) {
#if DCHECK_IS_ON()
  DCHECK(!IsSetNeedsLayoutForbidden());
#endif
  bool already_needed_layout = NormalChildNeedsLayout();
  SetNormalChildNeedsLayout(true);
  MarkContainerNeedsCollectInlines();
  // FIXME: Replace MarkOnlyThis with the SubtreeLayoutScope code path and
  // remove the MarkingBehavior argument entirely.
  if (!already_needed_layout && mark_parents == kMarkContainerChain &&
      (!layouter || layouter->Root() != this))
    MarkContainerChainForLayout(!layouter, layouter);
}

inline void LayoutObject::SetNeedsPositionedMovementLayout() {
  bool already_needed_layout = NeedsPositionedMovementLayout();
  SetNeedsPositionedMovementLayout(true);
#if DCHECK_IS_ON()
  DCHECK(!IsSetNeedsLayoutForbidden());
#endif
  if (!already_needed_layout)
    MarkContainerChainForLayout();
}

inline bool LayoutObject::PreservesNewline() const {
  if (IsSVGInlineText())
    return false;

  return Style()->PreserveNewline();
}

inline void LayoutObject::SetSelectionStateIfNeeded(SelectionState state) {
  if (GetSelectionState() == state)
    return;

  SetSelectionState(state);
}

inline void LayoutObject::SetHasBoxDecorationBackground(bool b) {
  if (b == bitfields_.HasBoxDecorationBackground())
    return;

  bitfields_.SetHasBoxDecorationBackground(b);
  InvalidateBackgroundObscurationStatus();
}

inline void LayoutObject::InvalidateBackgroundObscurationStatus() {
  bitfields_.SetBackgroundObscurationState(kBackgroundObscurationStatusInvalid);
}

DISABLE_CFI_PERF
inline bool LayoutObject::BackgroundIsKnownToBeObscured() const {
  if (bitfields_.GetBackgroundObscurationState() ==
      kBackgroundObscurationStatusInvalid) {
    BackgroundObscurationState state = ComputeBackgroundIsKnownToBeObscured()
                                           ? kBackgroundKnownToBeObscured
                                           : kBackgroundMayBeVisible;
    bitfields_.SetBackgroundObscurationState(state);
  }
  return bitfields_.GetBackgroundObscurationState() ==
         kBackgroundKnownToBeObscured;
}

inline void MakeMatrixRenderable(TransformationMatrix& matrix,
                                 bool has3d_rendering) {
  if (!has3d_rendering)
    matrix.MakeAffine();
}

enum class LayoutObjectSide {
  kRemainingTextIfOnBoundary,
  kFirstLetterIfOnBoundary
};
CORE_EXPORT const LayoutObject* AssociatedLayoutObjectOf(
    const Node&,
    int offset_in_node,
    LayoutObjectSide = LayoutObjectSide::kRemainingTextIfOnBoundary);

#define DEFINE_LAYOUT_OBJECT_TYPE_CASTS(thisType, predicate)           \
  DEFINE_TYPE_CASTS(thisType, LayoutObject, object, object->predicate, \
                    object.predicate)

}  // namespace blink

#ifndef NDEBUG
// Outside the blink namespace for ease of invocation from gdb.
CORE_EXPORT void showTree(const blink::LayoutObject*);
CORE_EXPORT void showLineTree(const blink::LayoutObject*);
CORE_EXPORT void showLayoutTree(const blink::LayoutObject* object1);
// We don't make object2 an optional parameter so that showLayoutTree
// can be called from gdb easily.
CORE_EXPORT void showLayoutTree(const blink::LayoutObject* object1,
                                const blink::LayoutObject* object2);

#endif

#endif  // LayoutObject_h
