/*
 * 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/PositionWithAffinity.h"
#include "core/fetch/ImageResourceClient.h"
#include "core/html/HTMLElement.h"
#include "core/inspector/InspectorTraceEvents.h"
#include "core/layout/HitTestRequest.h"
#include "core/layout/LayoutObjectChildList.h"
#include "core/layout/PaintInvalidationState.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/layout/compositing/CompositingState.h"
#include "core/layout/compositing/CompositingTriggers.h"
#include "core/style/ComputedStyle.h"
#include "core/style/StyleInheritedData.h"
#include "platform/geometry/FloatQuad.h"
#include "platform/geometry/LayoutRect.h"
#include "platform/graphics/CompositingReasons.h"
#include "platform/graphics/PaintInvalidationReason.h"
#include "platform/graphics/paint/DisplayItemClient.h"
#include "platform/transforms/TransformationMatrix.h"

namespace blink {

class AffineTransform;
class Cursor;
class Document;
class HitTestLocation;
class HitTestResult;
class InlineBox;
class PseudoStyleRequest;
class LayoutBoxModelObject;
class LayoutBlock;
class LayoutFlowThread;
class LayoutGeometryMap;
class DeprecatedPaintLayer;
class LayoutMultiColumnSpannerPlaceholder;
class LayoutView;
class TransformState;

struct PaintInfo;

enum CursorDirective {
    SetCursorBasedOnStyle,
    SetCursor,
    DoNotSetCursor
};

enum HitTestFilter {
    HitTestAll,
    HitTestSelf,
    HitTestDescendants
};

enum MarkingBehavior {
    MarkOnlyThis,
    MarkContainerChain,
};

enum MapCoordinatesMode {
    IsFixed = 1 << 0,
    UseTransforms = 1 << 1,
    ApplyContainerFlip = 1 << 2,
    TraverseDocumentBoundaries = 1 << 3,
};
typedef unsigned MapCoordinatesFlags;

const LayoutUnit& caretWidth();

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

    LayoutRect bounds;
    bool draggable;
};

typedef WTF::HashMap<const DeprecatedPaintLayer*, Vector<LayoutRect>> LayerHitTestRects;

#ifndef NDEBUG
const int showTreeCharacterOffset = 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 exists for several purposes but are usually required by CSS. A
// good example is anonymous table parts (http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes).
// Also some Node don't have an associated LayoutObjects e.g. if display: none 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 ImageResourceClient, 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.
class CORE_EXPORT LayoutObject : public ImageResourceClient {
    friend class LayoutObjectChildList;
    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* name() 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;

    // Returns the decorated name along with the debug information from the associated Node object.
    String debugName() const;

    LayoutObject* parent() const { return m_parent; }
    bool isDescendantOf(const LayoutObject*) const;

    LayoutObject* previousSibling() const { return m_previous; }
    LayoutObject* nextSibling() const { return m_next; }

    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* stayWithin) const;
    LayoutObject* nextInPreOrderAfterChildren() const;
    LayoutObject* nextInPreOrderAfterChildren(const LayoutObject* stayWithin) const;
    LayoutObject* previousInPreOrder() const;
    LayoutObject* previousInPreOrder(const LayoutObject* stayWithin) const;
    LayoutObject* childAt(unsigned) const;

    LayoutObject* lastLeafChild() const;

    // The following six 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.
    DeprecatedPaintLayer* enclosingLayer() const;
    void addLayers(DeprecatedPaintLayer* parentLayer);
    void removeLayers(DeprecatedPaintLayer* parentLayer);
    void moveLayers(DeprecatedPaintLayer* oldParent, DeprecatedPaintLayer* newParent);
    DeprecatedPaintLayer* findNextLayer(DeprecatedPaintLayer* parentLayer, LayoutObject* startPoint, bool checkParent = true);

    // Scrolling is a LayoutBox concept, however some code just cares about recursively scrolling our enclosing ScrollableArea(s).
    bool scrollRectToVisible(const LayoutRect&, const ScrollAlignment& alignX = ScrollAlignment::alignCenterIfNeeded, const ScrollAlignment& alignY = ScrollAlignment::alignCenterIfNeeded);

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

    LayoutBox* enclosingScrollableBox() 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 ENABLE(ASSERT)
    void setHasAXObject(bool flag) { m_hasAXObject = flag; }
    bool hasAXObject() const { return m_hasAXObject; }

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

    void assertLaidOut() const
    {
#ifndef NDEBUG
        if (needsLayout())
            showLayoutTreeForThis();
#endif
        ASSERT_WITH_SECURITY_IMPLICATION(!needsLayout());
    }

    void assertSubtreeIsLaidOut() const
    {
        for (const LayoutObject* layoutObject = this; layoutObject; layoutObject = layoutObject->nextInPreOrder())
            layoutObject->assertLaidOut();
    }

    void assertClearedPaintInvalidationState() const
    {
#ifndef NDEBUG
        if (paintInvalidationStateIsDirty()) {
            showLayoutTreeForThis();
            ASSERT_NOT_REACHED();
        }
#endif
    }

    void assertSubtreeClearedPaintInvalidationState() const
    {
        for (const LayoutObject* layoutObject = this; layoutObject; layoutObject = layoutObject->nextInPreOrder())
            layoutObject->assertClearedPaintInvalidationState();
    }

#endif

    // Correct version of !layoutObjectHasNoBoxEffectObsolete().
    bool hasBoxEffect() const
    {
        return hasBoxDecorationBackground() || style()->hasVisualOverflowingEffect();
    }

    // Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline
    // children.
    virtual LayoutBlock* firstLineBlock() const;

    // LayoutObject tree manipulation
    //////////////////////////////////////////
    virtual bool canHaveChildren() const { return virtualChildren(); }
    virtual bool isChildAllowed(LayoutObject*, const ComputedStyle&) const { return true; }
    virtual void addChild(LayoutObject* newChild, LayoutObject* beforeChild = nullptr);
    virtual void addChildIgnoringContinuation(LayoutObject* newChild, LayoutObject* beforeChild = nullptr) { return addChild(newChild, beforeChild); }
    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*);

private:
    //////////////////////////////////////////
    // Helper functions. Dangerous to use!
    void setPreviousSibling(LayoutObject* previous) { m_previous = previous; }
    void setNextSibling(LayoutObject* next) { m_next = next; }
    void setParent(LayoutObject* parent)
    {
        m_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 insideFlowThread = parent && parent->isInsideFlowThread();
        if (insideFlowThread != isInsideFlowThread() && !isLayoutFlowThread())
            setIsInsideFlowThreadIncludingDescendants(insideFlowThread);
    }

    //////////////////////////////////////////
private:
#if ENABLE(ASSERT)
    bool isSetNeedsLayoutForbidden() const { return m_setNeedsLayoutForbidden; }
    void setNeedsLayoutIsForbidden(bool flag) { m_setNeedsLayoutForbidden = flag; }
#endif

    void addAbsoluteRectForLayer(IntRect& result);
    bool requiresAnonymousTableWrappers(const LayoutObject*) const;

    // Gets pseudoStyle from Shadow host(in case of input elements)
    // or from Parent element.
    PassRefPtr<ComputedStyle> getUncachedPseudoStyleFromParentOrShadowHost() const;

    bool skipInvalidationWhenLaidOutChildren() const;

public:
#ifndef NDEBUG
    void showTreeForThis() const;
    void showLayoutTreeForThis() const;
    void showLineTreeForThis() const;

    void showLayoutObject() const;
    // We don't make printedCharacters an optional parameter so that
    // showLayoutObject can be called from gdb easily.
    void showLayoutObject(int printedCharacters) const;
    void showLayoutTreeAndMark(const LayoutObject* markedObject1 = nullptr, const char* markedLabel1 = nullptr, const LayoutObject* markedObject2 = nullptr, const char* markedLabel2 = nullptr, int depth = 0) const;
#endif

    // This function is used to create the appropriate LayoutObject based
    // on the style, in particular 'display' and 'content'.
    // "display: none" is the only time 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
    // m_isInline 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 node() && node()->isPseudoElement(); }

    virtual bool isBoxModelObject() const { return false; }
    bool isBR() const { return isOfType(LayoutObjectBr); }
    bool isCanvas() const { return isOfType(LayoutObjectCanvas); }
    bool isCounter() const { return isOfType(LayoutObjectCounter); }
    bool isDetailsMarker() const { return isOfType(LayoutObjectDetailsMarker); }
    bool isEmbeddedObject() const { return isOfType(LayoutObjectEmbeddedObject); }
    bool isFieldset() const { return isOfType(LayoutObjectFieldset); }
    bool isFileUploadControl() const { return isOfType(LayoutObjectFileUploadControl); }
    bool isFrame() const { return isOfType(LayoutObjectFrame); }
    bool isFrameSet() const { return isOfType(LayoutObjectFrameSet); }
    bool isLayoutTableCol() const { return isOfType(LayoutObjectLayoutTableCol); }
    bool isListBox() const { return isOfType(LayoutObjectListBox); }
    bool isListItem() const { return isOfType(LayoutObjectListItem); }
    bool isListMarker() const { return isOfType(LayoutObjectListMarker); }
    bool isMedia() const { return isOfType(LayoutObjectMedia); }
    bool isMenuList() const { return isOfType(LayoutObjectMenuList); }
    bool isMeter() const { return isOfType(LayoutObjectMeter); }
    bool isProgress() const { return isOfType(LayoutObjectProgress); }
    bool isQuote() const { return isOfType(LayoutObjectQuote); }
    bool isLayoutButton() const { return isOfType(LayoutObjectLayoutButton); }
    bool isLayoutFullScreen() const { return isOfType(LayoutObjectLayoutFullScreen); }
    bool isLayoutFullScreenPlaceholder() const { return isOfType(LayoutObjectLayoutFullScreenPlaceholder); }
    bool isLayoutGrid() const { return isOfType(LayoutObjectLayoutGrid); }
    bool isLayoutIFrame() const { return isOfType(LayoutObjectLayoutIFrame); }
    bool isLayoutImage() const { return isOfType(LayoutObjectLayoutImage); }
    bool isLayoutMultiColumnSet() const { return isOfType(LayoutObjectLayoutMultiColumnSet); }
    bool isLayoutMultiColumnSpannerPlaceholder() const { return isOfType(LayoutObjectLayoutMultiColumnSpannerPlaceholder); }
    bool isLayoutScrollbarPart() const { return isOfType(LayoutObjectLayoutScrollbarPart); }
    bool isLayoutView() const { return isOfType(LayoutObjectLayoutView); }
    bool isReplica() const { return isOfType(LayoutObjectReplica); }
    bool isRuby() const { return isOfType(LayoutObjectRuby); }
    bool isRubyBase() const { return isOfType(LayoutObjectRubyBase); }
    bool isRubyRun() const { return isOfType(LayoutObjectRubyRun); }
    bool isRubyText() const { return isOfType(LayoutObjectRubyText); }
    bool isSlider() const { return isOfType(LayoutObjectSlider); }
    bool isSliderThumb() const { return isOfType(LayoutObjectSliderThumb); }
    bool isTable() const { return isOfType(LayoutObjectTable); }
    bool isTableCaption() const { return isOfType(LayoutObjectTableCaption); }
    bool isTableCell() const { return isOfType(LayoutObjectTableCell); }
    bool isTableRow() const { return isOfType(LayoutObjectTableRow); }
    bool isTableSection() const { return isOfType(LayoutObjectTableSection); }
    bool isTextArea() const { return isOfType(LayoutObjectTextArea); }
    bool isTextControl() const { return isOfType(LayoutObjectTextControl); }
    bool isTextField() const { return isOfType(LayoutObjectTextField); }
    bool isVideo() const { return isOfType(LayoutObjectVideo); }
    bool isWidget() const { return isOfType(LayoutObjectWidget); }

    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 isLayoutPart() const { return false; }

    bool isDocumentElement() const { return document().documentElement() == m_node; }
    // isBody is called from LayoutBox::styleWillChange and is thus quite hot.
    bool isBody() const { return node() && node()->hasTagName(HTMLNames::bodyTag); }
    bool isHR() const;
    bool isLegend() 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 m_bitfields.hasCounterNodeMap(); }
    void setHasCounterNodeMap(bool hasCounterNodeMap) { m_bitfields.setHasCounterNodeMap(hasCounterNodeMap); }

    bool everHadLayout() const { return m_bitfields.everHadLayout(); }

    bool childrenInline() const { return m_bitfields.childrenInline(); }
    void setChildrenInline(bool b) { m_bitfields.setChildrenInline(b); }

    bool alwaysCreateLineBoxesForLayoutInline() const
    {
        ASSERT(isLayoutInline());
        return m_bitfields.alwaysCreateLineBoxesForLayoutInline();
    }
    void setAlwaysCreateLineBoxesForLayoutInline(bool alwaysCreateLineBoxes)
    {
        ASSERT(isLayoutInline());
        m_bitfields.setAlwaysCreateLineBoxesForLayoutInline(alwaysCreateLineBoxes);
    }

    bool ancestorLineBoxDirty() const { return m_bitfields.ancestorLineBoxDirty(); }
    void setAncestorLineBoxDirty(bool value = true)
    {
        m_bitfields.setAncestorLineBoxDirty(value);
        if (value)
            setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::LineBoxesChanged);
    }

    void setIsInsideFlowThreadIncludingDescendants(bool);

    bool isInsideFlowThread() const { return m_bitfields.isInsideFlowThread(); }
    void setIsInsideFlowThread(bool insideFlowThread) { m_bitfields.setIsInsideFlowThread(insideFlowThread); }

    // FIXME: Until all SVG layoutObjects can be subclasses of LayoutSVGModelObject we have
    // to add SVG layoutObject methods to LayoutObject with an ASSERT_NOT_REACHED() default implementation.
    bool isSVG() const { return isOfType(LayoutObjectSVG); }
    bool isSVGRoot() const { return isOfType(LayoutObjectSVGRoot); }
    bool isSVGContainer() const { return isOfType(LayoutObjectSVGContainer); }
    bool isSVGTransformableContainer() const { return isOfType(LayoutObjectSVGTransformableContainer); }
    bool isSVGViewportContainer() const { return isOfType(LayoutObjectSVGViewportContainer); }
    bool isSVGGradientStop() const { return isOfType(LayoutObjectSVGGradientStop); }
    bool isSVGHiddenContainer() const { return isOfType(LayoutObjectSVGHiddenContainer); }
    bool isSVGShape() const { return isOfType(LayoutObjectSVGShape); }
    bool isSVGText() const { return isOfType(LayoutObjectSVGText); }
    bool isSVGTextPath() const { return isOfType(LayoutObjectSVGTextPath); }
    bool isSVGInline() const { return isOfType(LayoutObjectSVGInline); }
    bool isSVGInlineText() const { return isOfType(LayoutObjectSVGInlineText); }
    bool isSVGImage() const { return isOfType(LayoutObjectSVGImage); }
    bool isSVGForeignObject() const { return isOfType(LayoutObjectSVGForeignObject); }
    bool isSVGResourceContainer() const { return isOfType(LayoutObjectSVGResourceContainer); }
    bool isSVGResourceFilter() const { return isOfType(LayoutObjectSVGResourceFilter); }
    bool isSVGResourceFilterPrimitive() const { return isOfType(LayoutObjectSVGResourceFilterPrimitive); }

    // 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 { return false; }
    enum DescendantIsolationState {
        DescendantIsolationRequired,
        DescendantIsolationNeedsUpdate,
    };
    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 SVGLocatable::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
    virtual FloatRect paintInvalidationRectInLocalCoordinates() const;

    // This only returns the transform="" value from the element
    // most callsites want localToParentTransform() instead.
    virtual AffineTransform localTransform() const;

    // Returns the full transform mapping from local coordinates to local coords for the parent SVG layoutObject
    // This includes any viewport transforms and x/y offsets as well as the transform="" value off the element.
    virtual const AffineTransform& localToParentTransform() const;

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

    bool isAnonymous() const { return m_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() == BLOCK || style()->display() == BOX) && style()->styleType() == NOPSEUDO && isLayoutBlock() && !isListMarker() && !isLayoutFlowThread() && !isLayoutMultiColumnSet()
            && !isLayoutFullScreen()
            && !isLayoutFullScreenPlaceholder();
    }
    bool isElementContinuation() const { return node() && node()->layoutObject() != this; }
    bool isInlineElementContinuation() const { return isElementContinuation() && isInline(); }
    virtual LayoutBoxModelObject* virtualContinuation() const { return nullptr; }

    bool isFloating() const { return m_bitfields.floating(); }

    bool isOutOfFlowPositioned() const { return m_bitfields.isOutOfFlowPositioned(); } // absolute or fixed positioning
    bool isInFlowPositioned() const { return m_bitfields.isInFlowPositioned(); } // relative or sticky positioning
    bool isRelPositioned() const { return m_bitfields.isRelPositioned(); } // relative positioning
    bool isStickyPositioned() const { return m_bitfields.isStickyPositioned(); } // sticky positioning
    bool isPositioned() const { return m_bitfields.isPositioned(); }

    bool isText() const  { return m_bitfields.isText(); }
    bool isBox() const { return m_bitfields.isBox(); }
    bool isInline() const { return m_bitfields.isInline(); } // inline object
    bool isDragging() const { return m_bitfields.isDragging(); }
    bool isReplaced() const { return m_bitfields.isReplaced(); } // a "replaced" element (see CSS)
    bool isHorizontalWritingMode() const { return m_bitfields.horizontalWritingMode(); }
    bool hasFlippedBlocksWritingMode() const
    {
        return style()->isFlippedBlocksWritingMode();
    }

    bool hasLayer() const { return m_bitfields.hasLayer(); }

    // "Box decoration background" includes all box decorations and backgrounds
    // that are painted as the background of the object. It includes borders,
    // box-shadows, background-color and background-image, etc.
    enum BoxDecorationBackgroundState {
        NoBoxDecorationBackground,
        HasBoxDecorationBackgroundObscurationStatusInvalid,
        HasBoxDecorationBackgroundKnownToBeObscured,
        HasBoxDecorationBackgroundMayBeVisible,
    };
    bool hasBoxDecorationBackground() const { return m_bitfields.boxDecorationBackgroundState() != NoBoxDecorationBackground; }
    bool boxDecorationBackgroundIsKnownToBeObscured();
    bool mustInvalidateFillLayersPaintOnHeightChange(const FillLayer&) const;
    bool hasBackground() const { return style()->hasBackground(); }

    bool needsLayoutBecauseOfChildren() const { return needsLayout() && !selfNeedsLayout() && !needsPositionedMovementLayout() && !needsSimplifiedNormalFlowLayout(); }

    bool needsLayout() const
    {
        return m_bitfields.selfNeedsLayout() || m_bitfields.normalChildNeedsLayout() || m_bitfields.posChildNeedsLayout()
            || m_bitfields.needsSimplifiedNormalFlowLayout() || m_bitfields.needsPositionedMovementLayout();
    }

    bool selfNeedsLayout() const { return m_bitfields.selfNeedsLayout(); }
    bool needsPositionedMovementLayout() const { return m_bitfields.needsPositionedMovementLayout(); }
    bool needsPositionedMovementLayoutOnly() const
    {
        return m_bitfields.needsPositionedMovementLayout() && !m_bitfields.selfNeedsLayout() && !m_bitfields.normalChildNeedsLayout()
            && !m_bitfields.posChildNeedsLayout() && !m_bitfields.needsSimplifiedNormalFlowLayout();
    }

    bool posChildNeedsLayout() const { return m_bitfields.posChildNeedsLayout(); }
    bool needsSimplifiedNormalFlowLayout() const { return m_bitfields.needsSimplifiedNormalFlowLayout(); }
    bool normalChildNeedsLayout() const { return m_bitfields.normalChildNeedsLayout(); }

    bool preferredLogicalWidthsDirty() const { return m_bitfields.preferredLogicalWidthsDirty(); }

    bool needsOverflowRecalcAfterStyleChange() const { return m_bitfields.selfNeedsOverflowRecalcAfterStyleChange() || m_bitfields.childNeedsOverflowRecalcAfterStyleChange(); }
    bool selfNeedsOverflowRecalcAfterStyleChange() const { return m_bitfields.selfNeedsOverflowRecalcAfterStyleChange(); }
    bool childNeedsOverflowRecalcAfterStyleChange() const { return m_bitfields.childNeedsOverflowRecalcAfterStyleChange(); }

    bool isSelectionBorder() const;

    bool hasClip() const { return isOutOfFlowPositioned() && !style()->hasAutoClip(); }
    bool hasOverflowClip() const { return m_bitfields.hasOverflowClip(); }
    bool hasClipOrOverflowClip() const { return hasClip() || hasOverflowClip(); }

    bool hasTransformRelatedProperty() const { return m_bitfields.hasTransformRelatedProperty(); }
    bool hasMask() const { return style() && style()->hasMask(); }
    bool hasClipPath() const { return style() && style()->clipPath(); }
    bool hasHiddenBackface() const { return style() && style()->backfaceVisibility() == BackfaceVisibilityHidden; }

    bool hasFilter() const { return style() && style()->hasFilter(); }
    bool hasBackdropFilter() const { return style() && style()->hasBackdropFilter(); }

    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* parentStyle = nullptr) const;
    PassRefPtr<ComputedStyle> getUncachedPseudoStyle(const PseudoStyleRequest&, const ComputedStyle* parentStyle = nullptr, const ComputedStyle* ownStyle = nullptr) const;

    virtual void updateDragState(bool dragOn);

    LayoutView* view() const { return document().layoutView(); }
    FrameView* frameView() const { return document().view(); }

    bool isRooted() const;

    Node* node() const
    {
        return isAnonymous() ? 0 : m_node;
    }

    Node* nonPseudoNode() const
    {
        return isPseudoElement() ? 0 : node();
    }

    void clearNode() { m_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() ? node()->parentOrShadowHostNode() : node(); }

    Document& document() const { return m_node->document(); }
    LocalFrame* frame() const { return document().frame(); }

    virtual LayoutMultiColumnSpannerPlaceholder* spannerPlaceholder() const { return nullptr; }
    bool isColumnSpanAll() const { return style()->columnSpan() == ColumnSpanAll && spannerPlaceholder(); }

    // 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) It can be used on orphaned subtrees, i.e., it can be called safely
    // even when the object is not part of the primary document subtree yet.
    // (2) For normal flow elements, it just returns the parent.
    // (3) 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().
    //
    // 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).
    //
    // If |paintInvalidationContainer| and |paintInvalidationContainerSkipped|
    // are not null, on return *paintInvalidationContainerSkipped is true if
    // the layoutObject returned is an ancestor of |paintInvalidationContainer|.
    LayoutObject* container(const LayoutBoxModelObject* paintInvalidationContainer = nullptr, bool* paintInvalidationContainerSkipped = nullptr) const;
    LayoutObject* containerCrossingFrameBoundaries() const;
    LayoutBlock* containerForFixedPosition(const LayoutBoxModelObject* paintInvalidationContainer = nullptr, bool* paintInvalidationContainerSkipped = nullptr) const;
    LayoutBlock* containingBlockForAbsolutePosition() const;

    virtual LayoutObject* hoverAncestor() const { return parent(); }

    Element* offsetParent() const;

    void markContainerChainForLayout(bool scheduleRelayout = true, SubtreeLayoutScope* = nullptr);
    void setNeedsLayout(LayoutInvalidationReasonForTracing, MarkingBehavior = MarkContainerChain, SubtreeLayoutScope* = nullptr);
    void setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReasonForTracing, MarkingBehavior = MarkContainerChain, SubtreeLayoutScope* = nullptr);
    void clearNeedsLayout();
    void setChildNeedsLayout(MarkingBehavior = MarkContainerChain, SubtreeLayoutScope* = nullptr);
    void setNeedsPositionedMovementLayout();
    void setPreferredLogicalWidthsDirty(MarkingBehavior = MarkContainerChain);
    void clearPreferredLogicalWidthsDirty();

    void setNeedsLayoutAndPrefWidthsRecalc(LayoutInvalidationReasonForTracing reason)
    {
        setNeedsLayout(reason);
        setPreferredLogicalWidthsDirty();
    }
    void setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReasonForTracing reason)
    {
        setNeedsLayoutAndFullPaintInvalidation(reason);
        setPreferredLogicalWidthsDirty();
    }

    void setPositionState(EPosition position)
    {
        ASSERT((position != AbsolutePosition && position != FixedPosition) || isBox());
        m_bitfields.setPositionedState(position);
    }
    void clearPositionedState() { m_bitfields.clearPositionedState(); }

    void setFloating(bool isFloating) { m_bitfields.setFloating(isFloating); }
    void setInline(bool isInline) { m_bitfields.setIsInline(isInline); }

    void setHasBoxDecorationBackground(bool);
    void invalidateBackgroundObscurationStatus();
    virtual bool computeBackgroundIsKnownToBeObscured() { return false; }

    void setIsText() { m_bitfields.setIsText(true); }
    void setIsBox() { m_bitfields.setIsBox(true); }
    void setReplaced(bool isReplaced) { m_bitfields.setIsReplaced(isReplaced); }
    void setHorizontalWritingMode(bool hasHorizontalWritingMode) { m_bitfields.setHorizontalWritingMode(hasHorizontalWritingMode); }
    void setHasOverflowClip(bool hasOverflowClip) { m_bitfields.setHasOverflowClip(hasOverflowClip); }
    void setHasLayer(bool hasLayer) { m_bitfields.setHasLayer(hasLayer); }
    void setHasTransformRelatedProperty(bool hasTransform) { m_bitfields.setHasTransformRelatedProperty(hasTransform); }
    void setHasReflection(bool hasReflection) { m_bitfields.setHasReflection(hasReflection); }

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

    // 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 layout() = 0;
    virtual bool updateImageLoadingPriorities() { return false; }
    void setHasPendingResourceUpdate(bool hasPendingResourceUpdate) { m_bitfields.setHasPendingResourceUpdate(hasPendingResourceUpdate); }
    bool hasPendingResourceUpdate() const { return m_bitfields.hasPendingResourceUpdate(); }

    void handleSubtreeModifications();
    virtual void subtreeDidChange() { }

    // Flags used to mark if an object consumes subtree change notifications.
    bool consumesSubtreeChangeNotification() const { return m_bitfields.consumesSubtreeChangeNotification(); }
    void setConsumesSubtreeChangeNotification() { m_bitfields.setConsumesSubtreeChangeNotification(true); }

    // Flags used to mark if a descendant subtree of this object has changed.
    void notifyOfSubtreeChange();
    void notifyAncestorsOfSubtreeChange();
    bool wasNotifiedOfSubtreeChange() const { return m_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 m_bitfields.subtreeChangeListenerRegistered(); }

    /* This function performs a layout only if one is needed. */
    void layoutIfNeeded()
    {
        if (needsLayout())
            layout();
    }

    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 compositingState() const;
    virtual CompositingReasons additionalCompositingReasons() const;

    bool hitTest(HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestFilter = HitTestAll);
    virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&);
    virtual bool nodeAtPoint(HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);

    virtual PositionWithAffinity positionForPoint(const LayoutPoint&);
    PositionWithAffinity createPositionWithAffinity(int offset, TextAffinity);
    PositionWithAffinity createPositionWithAffinity(int offset);
    PositionWithAffinity createPositionWithAffinity(const Position&);

    virtual void dirtyLinesFromChangedChild(LayoutObject*);

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

    // Set the style of the object if it's generated content.
    void setPseudoStyle(PassRefPtr<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(PassRefPtr<ComputedStyle> style) { m_style = style; }

    void firstLineStyleDidChange(const ComputedStyle& oldStyle, const ComputedStyle& newStyle);

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

    bool canContainFixedPositionObjects() const
    {
        return isLayoutView() || (hasTransformRelatedProperty() && isLayoutBlock()) || isSVGForeignObject();
    }

    // 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& localPoint = FloatPoint(), MapCoordinatesFlags = 0) const;
    FloatPoint absoluteToLocal(const FloatPoint&, MapCoordinatesFlags = 0) const;

    // Convert a local quad to absolute coordinates, taking transforms into account.
    FloatQuad localToAbsoluteQuad(const FloatQuad& quad, MapCoordinatesFlags mode = 0, bool* wasFixed = nullptr) const
    {
        return localToContainerQuad(quad, 0, mode, wasFixed);
    }
    // Convert an absolute quad to local coordinates.
    FloatQuad absoluteToLocalQuad(const FloatQuad&, MapCoordinatesFlags mode = 0) const;

    // Convert a local quad into the coordinate system of container, taking transforms into account.
    FloatQuad localToContainerQuad(const FloatQuad&, const LayoutBoxModelObject* paintInvalidationContainer, MapCoordinatesFlags = 0, bool* wasFixed = nullptr) const;
    FloatPoint localToContainerPoint(const FloatPoint&, const LayoutBoxModelObject* paintInvalidationContainer, MapCoordinatesFlags = 0, bool* wasFixed = nullptr, const PaintInvalidationState* = nullptr) const;

    // Convert a local point into the coordinate system of backing coordinates. Also returns the backing layer if needed.
    FloatPoint localToInvalidationBackingPoint(const LayoutPoint&, DeprecatedPaintLayer** backingLayer = nullptr);

    // Return the offset from the container() layoutObject (excluding transforms). In multi-column layout,
    // different offsets apply at different points, so return the offset that applies to the given point.
    virtual LayoutSize offsetFromContainer(const LayoutObject*, const LayoutPoint&, bool* offsetDependsOnPoint = nullptr) 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() 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>&, bool* /* wasFixed */ = nullptr) const { }

    static FloatRect absoluteBoundingBoxRectForRange(const Range*);

    // the rect that will be painted if this object is passed as the paintingRoot
    IntRect paintingRootRect(IntRect& topLevelRect);

    virtual LayoutUnit minPreferredLogicalWidth() const { return 0; }
    virtual LayoutUnit maxPreferredLogicalWidth() const { return 0; }

    const ComputedStyle* style() const { return m_style.get(); }
    ComputedStyle* mutableStyle() const { return m_style.get(); }

    // m_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 { ASSERT(m_style); return *m_style; }

    /* The following methods are inlined in LayoutObjectInlines.h */
    const ComputedStyle* firstLineStyle() const;
    const ComputedStyle& firstLineStyleRef() const;
    const ComputedStyle* style(bool firstLine) const;
    const ComputedStyle& styleRef(bool firstLine) const;

    static inline Color resolveColor(const ComputedStyle& styleToUse, int colorProperty)
    {
        return styleToUse.visitedDependentColor(colorProperty);
    }

    inline Color resolveColor(int colorProperty) const
    {
        return style()->visitedDependentColor(colorProperty);
    }

    // Used only by Element::pseudoStyleCacheIsInvalid to get a first line style based off of a
    // given new style, without accessing the cache.
    PassRefPtr<ComputedStyle> uncachedFirstLineStyle(ComputedStyle*) const;

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

    struct AppliedTextDecoration {
        STACK_ALLOCATED();
        Color color;
        TextDecorationStyle style;
        AppliedTextDecoration() : color(Color::transparent), style(TextDecorationStyleSolid) { }
    };

    void getTextDecorations(unsigned decorations, AppliedTextDecoration& underline, AppliedTextDecoration& overline, AppliedTextDecoration& linethrough, bool quirksMode = false, bool firstlineStyle = false);

    // Return the LayoutBoxModelObject in the container chain which is responsible for painting this object, or layout view
    // if painting is root-relative. This is the container that should be passed to the 'forPaintInvalidation'
    // methods.
    const LayoutBoxModelObject& containerForPaintInvalidationOnRootedTree() const;

    // This method will be deprecated in a long term, replaced by containerForPaintInvalidationOnRootedTree.
    const LayoutBoxModelObject* containerForPaintInvalidation() const;

    const LayoutBoxModelObject* adjustCompositedContainerForSpecialAncestors(const LayoutBoxModelObject* paintInvalidationContainer) const;
    bool isPaintInvalidationContainer() const;

    LayoutRect computePaintInvalidationRect()
    {
        return computePaintInvalidationRect(containerForPaintInvalidation());
    }

    // Returns the paint invalidation rect for this LayoutObject in the coordinate space of the paint backing (typically a GraphicsLayer) for |paintInvalidationContainer|.
    LayoutRect computePaintInvalidationRect(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* = nullptr) const;

    // Returns the rect bounds needed to invalidate the paint of this object, in the coordinate space of the layoutObject backing of |paintInvalidationContainer|
    LayoutRect boundsRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* = nullptr) const;

    // Actually do the paint invalidate of rect r for this object which has been computed in the coordinate space
    // of the GraphicsLayer backing of |paintInvalidationContainer|. Note that this coordinaten space is not the same
    // as the local coordinate space of |paintInvalidationContainer| in the presence of layer squashing.
    void invalidatePaintUsingContainer(const LayoutBoxModelObject& paintInvalidationContainer, const LayoutRect&, PaintInvalidationReason) const;

    // Invalidate the paint of a specific subrectangle within a given object. The rect |r| is in the object's coordinate space.
    void invalidatePaintRectangle(const LayoutRect&) const;
    void invalidatePaintRectangleNotInvalidatingDisplayItemClients(const LayoutRect& r) const { invalidatePaintRectangleInternal(r); }

    // Walk the tree after layout issuing paint invalidations for layoutObjects that have changed or moved, updating bounds that have changed, and clearing paint invalidation state.
    virtual void invalidateTreeIfNeeded(PaintInvalidationState&);

    virtual void invalidatePaintForOverflow();
    void invalidatePaintForOverflowIfNeeded();

    void invalidatePaintIncludingNonCompositingDescendants();
    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 absoluteClippedOverflowRect() const;
    virtual LayoutRect clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* = nullptr) const;

    // Given a rect in the object's coordinate space, compute a rect suitable for invalidating paints of
    // that rect in the coordinate space of paintInvalidationContainer.
    virtual void mapRectToPaintInvalidationBacking(const LayoutBoxModelObject* paintInvalidationContainer, LayoutRect&, const PaintInvalidationState*) 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 visual point.
    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 m_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 selectionState() const { return m_bitfields.selectionState(); }
    virtual void setSelectionState(SelectionState state) { m_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 coordinate space of the paint invalidation container's backing.
    virtual LayoutRect selectionRectForPaintInvalidation(const LayoutBoxModelObject* /* paintInvalidationContainer */) const { return LayoutRect(); }

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

    virtual bool canBeSelectionLeaf() const { return false; }
    bool hasSelectedChildren() const { return selectionState() != SelectionNone; }

    bool isSelectable() const;
    // Obtains the selection colors that should be used when painting a selection.
    Color selectionBackgroundColor() const;
    Color selectionForegroundColor(const GlobalPaintFlags) const;
    Color selectionEmphasisMarkColor(const GlobalPaintFlags) const;

    // Whether or not a given block needs to paint selection gaps.
    virtual bool shouldPaintSelectionGaps() const { return false; }

    /**
     * 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(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = nullptr);

    // 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, LayoutPart 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;

    virtual int previousOffset(int current) const;
    virtual int previousOffsetForBackwardDeletion(int current) const;
    virtual int nextOffset(int current) const;

    // ImageResourceClient override.
    void imageChanged(ImageResource*, const IntRect* = nullptr) final;
    bool willRenderImage(ImageResource*) final;
    bool getImageAnimationPolicy(ImageResource*, ImageAnimationPolicy&) final;

    // Sub-classes that have an associated image need to override this function
    // to get notified of any image change.
    virtual void imageChanged(WrappedImagePtr, const IntRect* = nullptr) { }

    void selectionStartEnd(int& spos, int& epos) const;

    void remove()
    {
        if (parent())
            parent()->removeChild(this);
    }

    bool visibleToHitTestRequest(const HitTestRequest& request) const { return style()->visibility() == VISIBLE && (request.ignorePointerEventsNone() || style()->pointerEvents() != PE_NONE) && !isInert(); }

    bool visibleToHitTesting() const { return style()->visibility() == VISIBLE && style()->pointerEvents() != PE_NONE && !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 mapLocalToContainer(const LayoutBoxModelObject* paintInvalidationContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = nullptr, const PaintInvalidationState* = nullptr) const;
    virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) 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* ancestorToStopAt, LayoutGeometryMap&) const;

    bool shouldUseTransformFromContainer(const LayoutObject* container) const;
    void getTransformFromContainer(const LayoutObject* container, const LayoutSize& offsetInContainer, TransformationMatrix&) const;

    bool createsGroup() const { return isTransparent() || hasMask() || hasFilter() || 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 {
        DontIncludeBlockVisualOverflow,
        IncludeBlockVisualOverflow,
    };
    virtual void addOutlineRects(Vector<LayoutRect>&, const LayoutPoint& additionalOffset, 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() ? IncludeBlockVisualOverflow : DontIncludeBlockVisualOverflow;
    }

    // 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.
    void addElementVisualOverflowRects(Vector<LayoutRect>& rects, const LayoutPoint& additionalOffset) const
    {
        addOutlineRects(rects, additionalOffset, IncludeBlockVisualOverflow);
    }

    // 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.
    virtual void computeLayerHitTestRects(LayerHitTestRects&) const;

    RespectImageOrientationEnum shouldRespectImageOrientation() const;

    bool isRelayoutBoundaryForInspector() const;

    // The previous paint invalidation rect, in the the space of the paint invalidation container (*not* the graphics layer that paints
    // this object).
    LayoutRect previousPaintInvalidationRectIncludingCompositedScrolling(const LayoutBoxModelObject& paintInvalidationContainer) const;
    LayoutSize previousPaintInvalidationRectSize() const { return previousPaintInvalidationRect().size(); }
    void setPreviousPaintInvalidationRect(const LayoutRect& rect) { m_previousPaintInvalidationRect = rect; }

    // Only adjusts if the paint invalidation container is not a composited scroller.
    void adjustPreviousPaintInvalidationForScrollIfNeeded(const DoubleSize& scrollDelta);

    // The previous position of the top-left corner of the object in its previous paint backing.
    const LayoutPoint& previousPositionFromPaintInvalidationBacking() const
    {
        ASSERT(!RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled());
        return m_previousPositionFromPaintInvalidationBacking;
    }
    void setPreviousPositionFromPaintInvalidationBacking(const LayoutPoint& positionFromPaintInvalidationBacking)
    {
        ASSERT(!RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled());
        m_previousPositionFromPaintInvalidationBacking = positionFromPaintInvalidationBacking;
    }

    PaintInvalidationReason fullPaintInvalidationReason() const { return m_bitfields.fullPaintInvalidationReason(); }
    bool shouldDoFullPaintInvalidation() const { return m_bitfields.fullPaintInvalidationReason() != PaintInvalidationNone; }
    void setShouldDoFullPaintInvalidation(PaintInvalidationReason = PaintInvalidationFull);
    void clearShouldDoFullPaintInvalidation() { m_bitfields.setFullPaintInvalidationReason(PaintInvalidationNone); }

    bool shouldInvalidateOverflowForPaint() const { return m_bitfields.shouldInvalidateOverflowForPaint(); }

    virtual void clearPaintInvalidationState(const PaintInvalidationState&);

    bool mayNeedPaintInvalidation() const { return m_bitfields.mayNeedPaintInvalidation(); }
    void setMayNeedPaintInvalidation();

    bool shouldInvalidateSelection() const { return m_bitfields.shouldInvalidateSelection(); }
    void setShouldInvalidateSelection();

    bool shouldCheckForPaintInvalidation(const PaintInvalidationState& paintInvalidationState) const
    {
        // Should check for paint invalidation if some ancestor changed location, because this object
        // may also change paint offset or location in paint invalidation container, even if there is
        // no paint invalidation flag set.
        return paintInvalidationState.forcedSubtreeInvalidationWithinContainer() || shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState();
    }

    bool shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState() const
    {
        return mayNeedPaintInvalidation() || shouldDoFullPaintInvalidation() || shouldInvalidateSelection() || m_bitfields.childShouldCheckForPaintInvalidation();
    }

    virtual bool supportsPaintInvalidationStateCachedOffsets() const { return !hasTransformRelatedProperty() && !hasReflection() && !style()->isFlippedBlocksWritingMode(); }

    virtual LayoutRect viewRect() const;

    DisplayItemClient displayItemClient() const { return toDisplayItemClient(this); }

    void invalidateDisplayItemClient(const DisplayItemClientWrapper&) const;
    void invalidateDisplayItemClientForNonCompositingDescendants() const { invalidateDisplayItemClientForNonCompositingDescendantsOf(*this); }
    // A normal object should use invalidateDisplayItemClientForNonCompositingDescendants()
    // to invalidate its descendants which are painted on the same backing. However, for
    // an object (e.g. LayoutScrollbarPart, custom scroll corner, custom resizer) which is
    // not hooked up in the layout tree and not able to find its paint backing, it should
    // let its owning layout object call the following function.
    // FIXME: should we hook up scrollbar parts in the layout tree? crbug.com/484263.
    void invalidateDisplayItemClientForNonCompositingDescendantsOf(const LayoutObject&) const;

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

protected:
    enum LayoutObjectType {
        LayoutObjectBr,
        LayoutObjectCanvas,
        LayoutObjectFieldset,
        LayoutObjectCounter,
        LayoutObjectDetailsMarker,
        LayoutObjectEmbeddedObject,
        LayoutObjectFileUploadControl,
        LayoutObjectFrame,
        LayoutObjectFrameSet,
        LayoutObjectLayoutTableCol,
        LayoutObjectListBox,
        LayoutObjectListItem,
        LayoutObjectListMarker,
        LayoutObjectMedia,
        LayoutObjectMenuList,
        LayoutObjectMeter,
        LayoutObjectProgress,
        LayoutObjectQuote,
        LayoutObjectLayoutButton,
        LayoutObjectLayoutFlowThread,
        LayoutObjectLayoutFullScreen,
        LayoutObjectLayoutFullScreenPlaceholder,
        LayoutObjectLayoutGrid,
        LayoutObjectLayoutIFrame,
        LayoutObjectLayoutImage,
        LayoutObjectLayoutInline,
        LayoutObjectLayoutMultiColumnSet,
        LayoutObjectLayoutMultiColumnSpannerPlaceholder,
        LayoutObjectLayoutPart,
        LayoutObjectLayoutScrollbarPart,
        LayoutObjectLayoutView,
        LayoutObjectReplica,
        LayoutObjectRuby,
        LayoutObjectRubyBase,
        LayoutObjectRubyRun,
        LayoutObjectRubyText,
        LayoutObjectSlider,
        LayoutObjectSliderThumb,
        LayoutObjectTable,
        LayoutObjectTableCaption,
        LayoutObjectTableCell,
        LayoutObjectTableRow,
        LayoutObjectTableSection,
        LayoutObjectTextArea,
        LayoutObjectTextControl,
        LayoutObjectTextField,
        LayoutObjectVideo,
        LayoutObjectWidget,

        LayoutObjectSVG, /* Keep by itself? */
        LayoutObjectSVGRoot,
        LayoutObjectSVGContainer,
        LayoutObjectSVGTransformableContainer,
        LayoutObjectSVGViewportContainer,
        LayoutObjectSVGHiddenContainer,
        LayoutObjectSVGGradientStop,
        LayoutObjectSVGShape,
        LayoutObjectSVGText,
        LayoutObjectSVGTextPath,
        LayoutObjectSVGInline,
        LayoutObjectSVGInlineText,
        LayoutObjectSVGImage,
        LayoutObjectSVGForeignObject,
        LayoutObjectSVGResourceContainer,
        LayoutObjectSVGResourceFilter,
        LayoutObjectSVGResourceFilterPrimitive,
    };
    virtual bool isOfType(LayoutObjectType type) const { return false; }

    inline bool layerCreationAllowedForSubtree() const;

    // Overrides should call the superclass at the end. m_style will be 0 the first time
    // this function will be called.
    virtual void styleWillChange(StyleDifference, const ComputedStyle& newStyle);
    // 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* oldStyle);
    void propagateStyleToAnonymousChildren(bool blockChildrenOnly = 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) { ASSERT(isAnonymous()); m_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 DeprecatedPaintLayer* currentLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) 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& layerOffset) const { }

    virtual PaintInvalidationReason paintInvalidationReason(const LayoutBoxModelObject& paintInvalidationContainer,
        const LayoutRect& oldPaintInvalidationRect, const LayoutPoint& oldPositionFromPaintInvalidationBacking,
        const LayoutRect& newPaintInvalidationRect, const LayoutPoint& newPositionFromPaintInvalidationBacking) const;
    virtual void incrementallyInvalidatePaint(const LayoutBoxModelObject& paintInvalidationContainer, const LayoutRect& oldBounds, const LayoutRect& newBounds, const LayoutPoint& positionFromPaintInvalidationBacking);

    virtual bool hasNonCompositedScrollbars() const { return false; }

#if ENABLE(ASSERT)
    virtual bool paintInvalidationStateIsDirty() const
    {
        return m_bitfields.neededLayoutBecauseOfChildren() || shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState();
    }
#endif

    virtual void invalidatePaintOfSubtreesIfNeeded(PaintInvalidationState& childPaintInvalidationState);
    virtual PaintInvalidationReason invalidatePaintIfNeeded(PaintInvalidationState&, const LayoutBoxModelObject& paintInvalidationContainer);

    // 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).
    virtual void invalidateDisplayItemClients(const LayoutBoxModelObject& paintInvalidationContainer) const;

    void setIsSlowRepaintObject(bool);

    void clearSelfNeedsOverflowRecalcAfterStyleChange() { m_bitfields.setSelfNeedsOverflowRecalcAfterStyleChange(false); }
    void clearChildNeedsOverflowRecalcAfterStyleChange() { m_bitfields.setChildNeedsOverflowRecalcAfterStyleChange(false); }
    void setShouldInvalidateOverflowForPaint() { m_bitfields.setShouldInvalidateOverflowForPaint(true); }
    void setEverHadLayout() { m_bitfields.setEverHadLayout(true); }

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

    bool containsInlineWithOutlineAndContinuation() const { return m_bitfields.containsInlineWithOutlineAndContinuation(); }
    void setContainsInlineWithOutlineAndContinuation(bool b) { m_bitfields.setContainsInlineWithOutlineAndContinuation(b); }

private:
    void fullyInvalidatePaint(const LayoutBoxModelObject& paintInvalidationContainer, PaintInvalidationReason, const LayoutRect& oldBounds, const LayoutRect& newBounds);

    const LayoutRect& previousPaintInvalidationRect() const { return m_previousPaintInvalidationRect; }

    // Adjusts a paint invalidation rect in the space of |m_previousPaintInvalidationRect| and |m_previousPositionFromPaintInvalidationBacking|
    // to be in the space of the |paintInvalidationContainer|,
    // if needed. They can be different only if |paintInvalidationContainer| is a composited scroller.
    void adjustInvalidationRectForCompositedScrolling(LayoutRect&, const LayoutBoxModelObject& paintInvalidationContainer) const;

    void clearLayoutRootIfNeeded() const;

    bool isInert() const;

    void updateImage(StyleImage*, StyleImage*);

    void scheduleRelayout();

    void updateShapeImage(const ShapeValue*, const ShapeValue*);
    void updateFillImages(const FillLayer* oldLayers, const FillLayer& newLayers);

    void setNeedsOverflowRecalcAfterStyleChange();

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

    inline void markContainerChainForPaintInvalidation();

    inline void invalidateSelectionIfNeeded(const LayoutBoxModelObject&, PaintInvalidationReason);

    inline void invalidateContainerPreferredLogicalWidths();

    void invalidatePaintIncludingNonCompositingDescendantsInternal(const LayoutBoxModelObject& repaintContainer);

    LayoutRect previousSelectionRectForPaintInvalidation() const;
    void setPreviousSelectionRectForPaintInvalidation(const LayoutRect&);

    const LayoutBoxModelObject* enclosingCompositedContainer() const;

    LayoutFlowThread* locateFlowThreadContainingBlock() const;
    void removeFromLayoutFlowThreadRecursive(LayoutFlowThread*);

    ComputedStyle* cachedFirstLineStyle() const;
    StyleDifference adjustStyleDifference(StyleDifference) const;

    Color selectionColor(int colorProperty, const GlobalPaintFlags) const;

    void removeShapeImageClient(ShapeValue*);

#if ENABLE(ASSERT)
    void checkBlockPositionedObjectsNeedLayout();
#endif

    bool isTextOrSVGChild() const { return isText() || (isSVG() && !isSVGRoot()); }

    static bool isAllowedToModifyLayoutTreeStructure(Document&);

    const LayoutBoxModelObject* invalidatePaintRectangleInternal(const LayoutRect&) const;

    RefPtr<ComputedStyle> m_style;

    // Oilpan: raw pointer back to the owning Node is considered safe.
    GC_PLUGIN_IGNORE("http://crbug.com/509911")
    Node* m_node;

    LayoutObject* m_parent;
    LayoutObject* m_previous;
    LayoutObject* m_next;

#if ENABLE(ASSERT)
    unsigned m_hasAXObject             : 1;
    unsigned m_setNeedsLayoutForbidden : 1;
#endif

#define ADD_BOOLEAN_BITFIELD(name, Name) \
    private:\
        unsigned m_##name : 1;\
    public:\
        bool name() const { return m_##name; }\
        void set##Name(bool name) { m_##name = name; }\

    class LayoutObjectBitfields {
        enum PositionedState {
            IsStaticallyPositioned = 0,
            IsRelativelyPositioned = 1,
            IsOutOfFlowPositioned = 2,
            IsStickyPositioned = 3,
        };

    public:
        LayoutObjectBitfields(Node* node)
            : m_selfNeedsLayout(false)
            , m_needsPositionedMovementLayout(false)
            , m_normalChildNeedsLayout(false)
            , m_posChildNeedsLayout(false)
            , m_needsSimplifiedNormalFlowLayout(false)
            , m_selfNeedsOverflowRecalcAfterStyleChange(false)
            , m_childNeedsOverflowRecalcAfterStyleChange(false)
            , m_preferredLogicalWidthsDirty(false)
            , m_shouldInvalidateOverflowForPaint(false)
            , m_childShouldCheckForPaintInvalidation(false)
            , m_mayNeedPaintInvalidation(false)
            , m_shouldInvalidateSelection(false)
            , m_neededLayoutBecauseOfChildren(false)
            , m_floating(false)
            , m_isAnonymous(!node)
            , m_isText(false)
            , m_isBox(false)
            , m_isInline(true)
            , m_isReplaced(false)
            , m_horizontalWritingMode(true)
            , m_isDragging(false)
            , m_hasLayer(false)
            , m_hasOverflowClip(false)
            , m_hasTransformRelatedProperty(false)
            , m_hasReflection(false)
            , m_hasCounterNodeMap(false)
            , m_everHadLayout(false)
            , m_ancestorLineBoxDirty(false)
            , m_hasPendingResourceUpdate(false)
            , m_isInsideFlowThread(false)
            , m_subtreeChangeListenerRegistered(false)
            , m_notifiedOfSubtreeChange(false)
            , m_consumesSubtreeChangeNotification(false)
            , m_childrenInline(false)
            , m_containsInlineWithOutlineAndContinuation(false)
            , m_alwaysCreateLineBoxesForLayoutInline(false)
            , m_lastBoxDecorationBackgroundObscured(false)
            , m_isSlowRepaintObject(false)
            , m_positionedState(IsStaticallyPositioned)
            , m_selectionState(SelectionNone)
            , m_boxDecorationBackgroundState(NoBoxDecorationBackground)
            , m_fullPaintInvalidationReason(PaintInvalidationNone)
        {
        }

        // 32 bits have been used in the first word, and 17 in the second.

        // 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(selfNeedsLayout, 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(needsPositionedMovementLayout, 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(normalChildNeedsLayout, 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(posChildNeedsLayout, 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(needsSimplifiedNormalFlowLayout, 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(selfNeedsOverflowRecalcAfterStyleChange, 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(childNeedsOverflowRecalcAfterStyleChange, ChildNeedsOverflowRecalcAfterStyleChange);

        // The preferred logical widths are the intrinsic sizes of this element.
        // 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.
        //
        // Blink stores them in LayoutBox (m_minPreferredLogicalWidth and
        // m_maxPreferredLogicalWidth).
        //
        // Setting this boolean marks both widths for lazy recomputation when
        // LayoutBox::minPreferredLogicalWidth() or maxPreferredLogicalWidth() is called.
        ADD_BOOLEAN_BITFIELD(preferredLogicalWidthsDirty, PreferredLogicalWidthsDirty);

        ADD_BOOLEAN_BITFIELD(shouldInvalidateOverflowForPaint, ShouldInvalidateOverflowForPaint); // TODO(wangxianzhu): Remove for slimming paint v2.
        ADD_BOOLEAN_BITFIELD(childShouldCheckForPaintInvalidation, ChildShouldCheckForPaintInvalidation);
        ADD_BOOLEAN_BITFIELD(mayNeedPaintInvalidation, MayNeedPaintInvalidation);
        ADD_BOOLEAN_BITFIELD(shouldInvalidateSelection, ShouldInvalidateSelection); // TODO(wangxianzhu): Remove for slimming paint v2.
        ADD_BOOLEAN_BITFIELD(neededLayoutBecauseOfChildren, NeededLayoutBecauseOfChildren); // TODO(wangxianzhu): Remove for slimming paint v2.
        ADD_BOOLEAN_BITFIELD(floating, Floating);

        ADD_BOOLEAN_BITFIELD(isAnonymous, IsAnonymous);
        ADD_BOOLEAN_BITFIELD(isText, IsText);
        ADD_BOOLEAN_BITFIELD(isBox, 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 paragraph).
        ADD_BOOLEAN_BITFIELD(isInline, IsInline);

        ADD_BOOLEAN_BITFIELD(isReplaced, IsReplaced);
        ADD_BOOLEAN_BITFIELD(horizontalWritingMode, HorizontalWritingMode);
        ADD_BOOLEAN_BITFIELD(isDragging, IsDragging);

        ADD_BOOLEAN_BITFIELD(hasLayer, HasLayer);
        ADD_BOOLEAN_BITFIELD(hasOverflowClip, HasOverflowClip); // Set in the case of overflow:auto/scroll/hidden
        ADD_BOOLEAN_BITFIELD(hasTransformRelatedProperty, HasTransformRelatedProperty);
        ADD_BOOLEAN_BITFIELD(hasReflection, HasReflection);

        // 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(hasCounterNodeMap, HasCounterNodeMap);

        ADD_BOOLEAN_BITFIELD(everHadLayout, EverHadLayout);
        ADD_BOOLEAN_BITFIELD(ancestorLineBoxDirty, AncestorLineBoxDirty);

        ADD_BOOLEAN_BITFIELD(hasPendingResourceUpdate, HasPendingResourceUpdate);

        ADD_BOOLEAN_BITFIELD(isInsideFlowThread, IsInsideFlowThread);

        ADD_BOOLEAN_BITFIELD(subtreeChangeListenerRegistered, SubtreeChangeListenerRegistered);
        ADD_BOOLEAN_BITFIELD(notifiedOfSubtreeChange, NotifiedOfSubtreeChange);
        ADD_BOOLEAN_BITFIELD(consumesSubtreeChangeNotification, ConsumesSubtreeChangeNotification);

        // from LayoutBlock
        ADD_BOOLEAN_BITFIELD(childrenInline, ChildrenInline);

        // from LayoutBlockFlow
        ADD_BOOLEAN_BITFIELD(containsInlineWithOutlineAndContinuation, ContainsInlineWithOutlineAndContinuation);

        // from LayoutInline
        ADD_BOOLEAN_BITFIELD(alwaysCreateLineBoxesForLayoutInline, AlwaysCreateLineBoxesForLayoutInline);

        // For slimming-paint.
        ADD_BOOLEAN_BITFIELD(lastBoxDecorationBackgroundObscured, LastBoxDecorationBackgroundObscured);

        ADD_BOOLEAN_BITFIELD(isSlowRepaintObject, IsSlowRepaintObject);

    private:
        unsigned m_positionedState : 2; // PositionedState
        unsigned m_selectionState : 3; // SelectionState
        unsigned m_boxDecorationBackgroundState : 2; // BoxDecorationBackgroundState
        unsigned m_fullPaintInvalidationReason : 5; // PaintInvalidationReason

    public:
        bool isOutOfFlowPositioned() const { return m_positionedState == IsOutOfFlowPositioned; }
        bool isRelPositioned() const { return m_positionedState == IsRelativelyPositioned; }
        bool isStickyPositioned() const { return m_positionedState == IsStickyPositioned; }
        bool isInFlowPositioned() const { return m_positionedState == IsRelativelyPositioned || m_positionedState == IsStickyPositioned; }
        bool isPositioned() const { return m_positionedState != IsStaticallyPositioned; }

        void setPositionedState(int positionState)
        {
            // This mask maps FixedPosition and AbsolutePosition to IsOutOfFlowPositioned, saving one bit.
            m_positionedState = static_cast<PositionedState>(positionState & 0x3);
        }
        void clearPositionedState() { m_positionedState = StaticPosition; }

        ALWAYS_INLINE SelectionState selectionState() const { return static_cast<SelectionState>(m_selectionState); }
        ALWAYS_INLINE void setSelectionState(SelectionState selectionState) { m_selectionState = selectionState; }

        ALWAYS_INLINE BoxDecorationBackgroundState boxDecorationBackgroundState() const { return static_cast<BoxDecorationBackgroundState>(m_boxDecorationBackgroundState); }
        ALWAYS_INLINE void setBoxDecorationBackgroundState(BoxDecorationBackgroundState s) { m_boxDecorationBackgroundState = s; }

        PaintInvalidationReason fullPaintInvalidationReason() const { return static_cast<PaintInvalidationReason>(m_fullPaintInvalidationReason); }
        void setFullPaintInvalidationReason(PaintInvalidationReason reason) { m_fullPaintInvalidationReason = reason; }
    };

#undef ADD_BOOLEAN_BITFIELD

    LayoutObjectBitfields m_bitfields;

    void setSelfNeedsLayout(bool b) { m_bitfields.setSelfNeedsLayout(b); }
    void setNeedsPositionedMovementLayout(bool b) { m_bitfields.setNeedsPositionedMovementLayout(b); }
    void setNormalChildNeedsLayout(bool b) { m_bitfields.setNormalChildNeedsLayout(b); }
    void setPosChildNeedsLayout(bool b) { m_bitfields.setPosChildNeedsLayout(b); }
    void setNeedsSimplifiedNormalFlowLayout(bool b) { m_bitfields.setNeedsSimplifiedNormalFlowLayout(b); }
    void setIsDragging(bool b) { m_bitfields.setIsDragging(b); }
    void clearShouldInvalidateOverflowForPaint() { m_bitfields.setShouldInvalidateOverflowForPaint(false); }
    void setSelfNeedsOverflowRecalcAfterStyleChange() { m_bitfields.setSelfNeedsOverflowRecalcAfterStyleChange(true); }
    void setChildNeedsOverflowRecalcAfterStyleChange() { m_bitfields.setChildNeedsOverflowRecalcAfterStyleChange(true); }

private:
    // Store state between styleWillChange and styleDidChange
    static bool s_affectsParentBlock;

    // This stores the paint invalidation rect from the previous frame. This rect does *not* account for composited scrolling. See
    // adjustInvalidationRectForCompositedScrolling().
    LayoutRect m_previousPaintInvalidationRect;

    // This stores the position in the paint invalidation backing's coordinate.
    // It is used to detect layoutObject shifts that forces a full invalidation.
    // This point does *not* account for composited scrolling. See adjustInvalidationRectForCompositedScrolling().
    LayoutPoint m_previousPositionFromPaintInvalidationBacking;
};

// 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:
    TemporaryChange<bool> m_disabler;
};

// FIXME: We should not allow paint invalidation out of paint invalidation state. crbug.com/457415
// Remove this once we fix the bug.
class DisablePaintInvalidationStateAsserts {
    STACK_ALLOCATED();
    WTF_MAKE_NONCOPYABLE(DisablePaintInvalidationStateAsserts);
public:
    DisablePaintInvalidationStateAsserts();
private:
    TemporaryChange<bool> m_disabler;
};

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

inline bool LayoutObject::documentBeingDestroyed() const
{
    return document().lifecycle().state() >= DocumentLifecycle::Stopping;
}

inline bool LayoutObject::isBeforeContent() const
{
    if (style()->styleType() != BEFORE)
        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() != AFTER)
        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 markParents, SubtreeLayoutScope* layouter)
{
    ASSERT(!isSetNeedsLayoutForbidden());
    bool alreadyNeededLayout = m_bitfields.selfNeedsLayout();
    setSelfNeedsLayout(true);
    if (!alreadyNeededLayout) {
        TRACE_EVENT_INSTANT1(
            TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"),
            "LayoutInvalidationTracking",
            TRACE_EVENT_SCOPE_THREAD,
            "data",
            InspectorLayoutInvalidationTrackingEvent::data(this, reason));
        if (markParents == MarkContainerChain && (!layouter || layouter->root() != this))
            markContainerChainForLayout(true, layouter);
    }
}

inline void LayoutObject::setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReasonForTracing reason, MarkingBehavior markParents, SubtreeLayoutScope* layouter)
{
    setNeedsLayout(reason, markParents, layouter);
    setShouldDoFullPaintInvalidation();
}

inline void LayoutObject::clearNeedsLayout()
{
    // Set flags for later stages/cycles.
    setEverHadLayout();
    setMayNeedPaintInvalidation();
    m_bitfields.setNeededLayoutBecauseOfChildren(needsLayoutBecauseOfChildren());

    // Clear needsLayout flags.
    setSelfNeedsLayout(false);
    setPosChildNeedsLayout(false);
    setNeedsSimplifiedNormalFlowLayout(false);
    setNormalChildNeedsLayout(false);
    setNeedsPositionedMovementLayout(false);
    setAncestorLineBoxDirty(false);

#if ENABLE(ASSERT)
    checkBlockPositionedObjectsNeedLayout();
#endif
}

inline void LayoutObject::setChildNeedsLayout(MarkingBehavior markParents, SubtreeLayoutScope* layouter)
{
    ASSERT(!isSetNeedsLayoutForbidden());
    bool alreadyNeededLayout = normalChildNeedsLayout();
    setNormalChildNeedsLayout(true);
    // FIXME: Replace MarkOnlyThis with the SubtreeLayoutScope code path and remove the MarkingBehavior argument entirely.
    if (!alreadyNeededLayout && markParents == MarkContainerChain && (!layouter || layouter->root() != this))
        markContainerChainForLayout(true, layouter);
}

inline void LayoutObject::setNeedsPositionedMovementLayout()
{
    bool alreadyNeededLayout = needsPositionedMovementLayout();
    setNeedsPositionedMovementLayout(true);
    ASSERT(!isSetNeedsLayoutForbidden());
    if (!alreadyNeededLayout)
        markContainerChainForLayout();
}

inline bool LayoutObject::preservesNewline() const
{
    if (isSVGInlineText())
        return false;

    return style()->preserveNewline();
}

inline bool LayoutObject::layerCreationAllowedForSubtree() const
{
    LayoutObject* parentLayoutObject = parent();
    while (parentLayoutObject) {
        if (parentLayoutObject->isSVGHiddenContainer())
            return false;
        parentLayoutObject = parentLayoutObject->parent();
    }

    return true;
}

inline void LayoutObject::setSelectionStateIfNeeded(SelectionState state)
{
    if (selectionState() == state)
        return;

    setSelectionState(state);
}

inline void LayoutObject::setHasBoxDecorationBackground(bool b)
{
    if (!b) {
        m_bitfields.setBoxDecorationBackgroundState(NoBoxDecorationBackground);
        return;
    }
    if (hasBoxDecorationBackground())
        return;
    m_bitfields.setBoxDecorationBackgroundState(HasBoxDecorationBackgroundObscurationStatusInvalid);
}

inline void LayoutObject::invalidateBackgroundObscurationStatus()
{
    if (!hasBoxDecorationBackground())
        return;
    m_bitfields.setBoxDecorationBackgroundState(HasBoxDecorationBackgroundObscurationStatusInvalid);
}

inline bool LayoutObject::boxDecorationBackgroundIsKnownToBeObscured()
{
    if (m_bitfields.boxDecorationBackgroundState() == HasBoxDecorationBackgroundObscurationStatusInvalid) {
        BoxDecorationBackgroundState state = computeBackgroundIsKnownToBeObscured() ? HasBoxDecorationBackgroundKnownToBeObscured : HasBoxDecorationBackgroundMayBeVisible;
        m_bitfields.setBoxDecorationBackgroundState(state);
    }
    return m_bitfields.boxDecorationBackgroundState() == HasBoxDecorationBackgroundKnownToBeObscured;
}

inline void makeMatrixRenderable(TransformationMatrix& matrix, bool has3DRendering)
{
    if (!has3DRendering)
        matrix.makeAffine();
}

inline int adjustForAbsoluteZoom(int value, LayoutObject* layoutObject)
{
    return adjustForAbsoluteZoom(value, layoutObject->style());
}

inline double adjustDoubleForAbsoluteZoom(double value, LayoutObject& layoutObject)
{
    ASSERT(layoutObject.style());
    return adjustDoubleForAbsoluteZoom(value, *layoutObject.style());
}

inline LayoutUnit adjustLayoutUnitForAbsoluteZoom(LayoutUnit value, LayoutObject& layoutObject)
{
    ASSERT(layoutObject.style());
    return adjustLayoutUnitForAbsoluteZoom(value, *layoutObject.style());
}

inline void adjustFloatQuadForAbsoluteZoom(FloatQuad& quad, LayoutObject& layoutObject)
{
    float zoom = layoutObject.style()->effectiveZoom();
    if (zoom != 1)
        quad.scale(1 / zoom, 1 / zoom);
}

inline void adjustFloatRectForAbsoluteZoom(FloatRect& rect, LayoutObject& layoutObject)
{
    float zoom = layoutObject.style()->effectiveZoom();
    if (zoom != 1)
        rect.scale(1 / zoom, 1 / zoom);
}

inline double adjustScrollForAbsoluteZoom(double value, LayoutObject& layoutObject)
{
    ASSERT(layoutObject.style());
    return adjustScrollForAbsoluteZoom(value, *layoutObject.style());
}

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

} // namespace blink

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

#endif

#endif // LayoutObject_h
