/* * 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/ImageResourceObserver.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 LayoutBoxModelObject; class LayoutBlock; class LayoutFlowThread; class LayoutGeometryMap; class LayoutMultiColumnSpannerPlaceholder; class LayoutView; class ObjectPaintProperties; class PaintLayer; class PseudoStyleRequest; 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, // Applies to LayoutView::mapLocalToAncestor() and LayoutView::mapToVisibleRectInAncestorSpace() // only, to indicate the input point or rect is in frame coordinates instead of frame contents // coordinates. This disables view clipping and scroll offset adjustment. // TODO(wangxianzhu): Remove this when root-layer-scrolls launches. InputIsInFrameCoordinates = 1 << 4, }; typedef unsigned MapCoordinatesFlags; enum ScheduleRelayoutBehavior { ScheduleRelayout, DontScheduleRelayout }; const LayoutUnit& caretWidth(); struct AnnotatedRegionValue { DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); bool operator==(const AnnotatedRegionValue& o) const { return draggable == o.draggable && bounds == o.bounds; } LayoutRect bounds; bool draggable; }; typedef WTF::HashMap> 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 exist for several // purposes but are usually required by CSS. A good example is anonymous table // parts (see LayoutTable for the expected structure). Anonymous LayoutObjects // are generated when a new child is added to the tree in addChild(). See the // function for some important information on this. // // Also some Node don't have an associated LayoutObjects e.g. if display: none is set. For more // detail, see LayoutObject::createObject that creates the right LayoutObject based on the style. // // Because the SVG and CSS classes both inherit from this object, functions can belong to either // realm and sometimes to both. // // The purpose of the layout tree is to do layout (aka reflow) and store its results for painting and // hit-testing. // Layout is the process of sizing and positioning Nodes on the page. In Blink, layouts always start // from a relayout boundary (see objectIsRelayoutBoundary in LayoutObject.cpp). As such, we need to mark // the ancestors all the way to the enclosing relayout boundary in order to do a correct layout. // // Due to the high cost of layout, a lot of effort is done to avoid doing full layouts of nodes. // This is why there are several types of layout available to bypass the complex operations. See the // comments on the layout booleans in LayoutObjectBitfields below about the different layouts. // // To save memory, especially for the common child class LayoutText, LayoutObject doesn't provide // storage for children. Descendant classes that do allow children have to have a LayoutObjectChildList // member that stores the actual children and override virtualChildren(). // // LayoutObject is an ImageResourceObserver, which means that it gets notified when associated images // are changed. This is used for 2 main use cases: // - reply to 'background-image' as we need to invalidate the background in this case. // (See https://drafts.csswg.org/css-backgrounds-3/#the-background-image) // - image (LayoutImage, LayoutSVGImage) or video (LayoutVideo) objects that are placeholders for // displaying them. // // // ***** LIFETIME ***** // // LayoutObjects are fully owned by their associated DOM node. In other words, // it's the DOM node's responsibility to free its LayoutObject, this is why // LayoutObjects are not and SHOULD NOT be RefCounted. // // LayoutObjects are created during the DOM attachment. This phase computes // the style and create the LayoutObject associated with the Node (see // Node::attach). LayoutObjects are destructed during detachment (see // Node::detach), which can happen when the DOM node is removed from the // DOM tree, during page tear down or when the style is changed to contain // 'display: none'. // // Anonymous LayoutObjects are owned by their enclosing DOM node. This means // that if the DOM node is detached, it has to destroy any anonymous // descendants. This is done in LayoutObject::destroy(). // // Note that for correctness, destroy() is expected to clean any anonymous // wrappers as sequences of insertion / removal could make them visible to // the page. This is done by LayoutObject::destroyAndCleanupAnonymousWrappers() // which is the preferred way to destroy an object. // // // ***** INTRINSIC SIZES / PREFERRED LOGICAL WIDTHS ***** // The preferred logical widths are the intrinsic sizes of this element // (https://drafts.csswg.org/css-sizing-3/#intrinsic). Intrinsic sizes depend // mostly on the content and a limited set of style properties (e.g. any // font-related property for text, 'min-width'/'max-width', // 'min-height'/'max-height'). // // Those widths are used to determine the final layout logical width, which // depends on the layout algorithm used and the available logical width. // // LayoutObject only has getters for the widths (minPreferredLogicalWidth and // maxPreferredLogicalWidth). However the storage for them is in LayoutBox // (see m_minPreferredLogicalWidth and m_maxPreferredLogicalWidth). This is // because only boxes implementing the full box model have a need for them. // Because LayoutBlockFlow's intrinsic widths rely on the underlying text // content, LayoutBlockFlow may call LayoutText::computePreferredLogicalWidths. // // The 2 widths are computed lazily during layout when the getters are called. // The computation is done by calling computePreferredLogicalWidths() behind the // scene. The boolean used to control the lazy recomputation is // preferredLogicalWidthsDirty. // // See the individual getters below for more details about what each width is. class CORE_EXPORT LayoutObject : public ImageResourceObserver, public DisplayItemClient { friend class LayoutObjectChildList; 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; // DisplayItemClient methods. LayoutRect visualRect() const override; String debugName() const override; 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. PaintLayer* enclosingLayer() const; void addLayers(PaintLayer* parentLayer); void removeLayers(PaintLayer* parentLayer); void moveLayers(PaintLayer* oldParent, PaintLayer* newParent); PaintLayer* findNextLayer(PaintLayer* 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, ScrollType = ProgrammaticScroll, bool makeVisibleInVisualViewport = true); // 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 assertClearedPaintInvalidationFlags() const { #ifndef NDEBUG if (paintInvalidationStateIsDirty()) { showLayoutTreeForThis(); ASSERT_NOT_REACHED(); } #endif } void assertSubtreeClearedPaintInvalidationFlags() const { for (const LayoutObject* layoutObject = this; layoutObject; layoutObject = layoutObject->nextInPreOrder()) layoutObject->assertClearedPaintInvalidationFlags(); } #endif // Correct version of !layoutObjectHasNoBoxEffectObsolete(). bool hasBoxEffect() const { return hasBoxDecorationBackground() || style()->hasVisualOverflowingEffect(); } // LayoutObject tree manipulation ////////////////////////////////////////// virtual bool canHaveChildren() const { return virtualChildren(); } virtual bool isChildAllowed(LayoutObject*, const ComputedStyle&) const { return true; } // This function is called whenever a child is inserted under |this|. // // The main purpose of this function is to generate a consistent layout // tree, which means generating the missing anonymous objects. Most of the // time there'll be no anonymous objects to generate. // // The following invariants are true on the input: // - |newChild->node()| is a child of |this->node()|, if |this| is not // anonymous. If |this| is anonymous, the invariant holds with the // enclosing non-anonymous LayoutObject. // - |beforeChild->node()| (if |beforeChild| is provided and not anonymous) // is a sibling of |newChild->node()| (if |newChild| is not anonymous). // // The reason for these invariants is that insertions are performed on the // DOM tree. Because the layout tree may insert extra anonymous renderers, // the previous invariants are only guaranteed for the DOM tree. In // particular, |beforeChild| may not be a direct child when it's wrapped in // anonymous wrappers. // // Classes inserting anonymous LayoutObjects in the tree are expected to // check for the anonymous wrapper case with: // beforeChild->parent() != this // // The usage of |child/parent/sibling| in this comment actually means // |child/parent/sibling| in a flat tree because a layout tree is generated // from a structure of a flat tree if Shadow DOM is used. // See LayoutTreeBuilderTraversal and FlatTreeTraversal. // // See LayoutTable::addChild and LayoutBlock::addChild. // TODO(jchaffraix): |newChild| cannot be nullptr and should be a reference. virtual void addChild(LayoutObject* 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*); // For SPv2 only. The ObjectPaintProperties structure holds references to the // property tree nodes that are created by the layout object for painting. // The property nodes are only updated during InUpdatePaintProperties phase // of the document lifecycle and shall remain immutable during other phases. ObjectPaintProperties* objectPaintProperties() const; void setObjectPaintProperties(PassOwnPtr); void clearObjectPaintProperties(); 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 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.