diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-10-13 13:24:50 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-10-14 10:57:25 +0000 |
commit | af3d4809763ef308f08ced947a73b624729ac7ea (patch) | |
tree | 4402b911e30383f6c6dace1e8cf3b8e85355db3a /chromium/third_party/WebKit/Source/core/layout/LayoutObject.h | |
parent | 0e8ff63a407fe323e215bb1a2c423c09a4747c8a (diff) | |
download | qtwebengine-chromium-af3d4809763ef308f08ced947a73b624729ac7ea.tar.gz |
BASELINE: Update Chromium to 47.0.2526.14
Also adding in sources needed for spellchecking.
Change-Id: Idd44170fa1616f26315188970a8d5ba7d472b18a
Reviewed-by: Michael BrĂ¼ning <michael.bruning@theqtcompany.com>
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/layout/LayoutObject.h')
-rw-r--r-- | chromium/third_party/WebKit/Source/core/layout/LayoutObject.h | 509 |
1 files changed, 399 insertions, 110 deletions
diff --git a/chromium/third_party/WebKit/Source/core/layout/LayoutObject.h b/chromium/third_party/WebKit/Source/core/layout/LayoutObject.h index 8885d9bd0be..e97e1a1cd5a 100644 --- a/chromium/third_party/WebKit/Source/core/layout/LayoutObject.h +++ b/chromium/third_party/WebKit/Source/core/layout/LayoutObject.h @@ -30,9 +30,7 @@ #include "core/dom/Document.h" #include "core/dom/DocumentLifecycle.h" #include "core/dom/Element.h" -#include "core/dom/Position.h" #include "core/editing/PositionWithAffinity.h" -#include "core/editing/TextAffinity.h" #include "core/fetch/ImageResourceClient.h" #include "core/html/HTMLElement.h" #include "core/inspector/InspectorTraceEvents.h" @@ -41,6 +39,8 @@ #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" @@ -65,7 +65,7 @@ class LayoutBoxModelObject; class LayoutBlock; class LayoutFlowThread; class LayoutGeometryMap; -class DeprecatedPaintLayer; +class PaintLayer; class LayoutMultiColumnSpannerPlaceholder; class LayoutView; class TransformState; @@ -84,14 +84,6 @@ enum HitTestFilter { HitTestDescendants }; -enum HitTestAction { - HitTestBlockBackground, - HitTestChildBlockBackground, - HitTestChildBlockBackgrounds, - HitTestFloat, - HitTestForeground -}; - enum MarkingBehavior { MarkOnlyThis, MarkContainerChain, @@ -108,6 +100,7 @@ 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; @@ -117,25 +110,59 @@ struct AnnotatedRegionValue { bool draggable; }; -typedef WTF::HashMap<const DeprecatedPaintLayer*, Vector<LayoutRect>> LayerHitTestRects; +typedef WTF::HashMap<const PaintLayer*, Vector<LayoutRect>> LayerHitTestRects; #ifndef NDEBUG const int showTreeCharacterOffset = 39; #endif -// Base class for all layout tree objects. +// 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 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 LayoutBlock; - friend class LayoutBlockFlow; - friend class DeprecatedPaintLayerReflectionInfo; // For setParent - friend class DeprecatedPaintLayerScrollableArea; // For setParent. 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*); - virtual ~LayoutObject(); + ~LayoutObject() override; // Returns the name of the layout object. virtual const char* name() const = 0; @@ -166,6 +193,7 @@ public: 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; } @@ -182,11 +210,11 @@ public: // 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); + 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); @@ -267,13 +295,41 @@ public: ////////////////////////////////////////// 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 + // 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; } ////////////////////////////////////////// -protected: + // 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; } @@ -319,13 +375,27 @@ public: 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*); -public: bool isPseudoElement() const { return node() && node()->isPseudoElement(); } virtual bool isBoxModelObject() const { return false; } @@ -399,6 +469,7 @@ public: 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(); } @@ -506,7 +577,9 @@ public: 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(); } @@ -532,7 +605,7 @@ public: HasBoxDecorationBackgroundMayBeVisible, }; bool hasBoxDecorationBackground() const { return m_bitfields.boxDecorationBackgroundState() != NoBoxDecorationBackground; } - bool boxDecorationBackgroundIsKnownToBeObscured(); + bool boxDecorationBackgroundIsKnownToBeObscured() const; bool mustInvalidateFillLayersPaintOnHeightChange(const FillLayer&) const; bool hasBackground() const { return style()->hasBackground(); } @@ -574,6 +647,7 @@ public: 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(); } @@ -614,9 +688,29 @@ public: virtual LayoutMultiColumnSpannerPlaceholder* spannerPlaceholder() const { return nullptr; } bool isColumnSpanAll() const { return style()->columnSpan() == ColumnSpanAll && spannerPlaceholder(); } - // Returns the object containing this one. Can be different from parent for positioned elements. - // If paintInvalidationContainer and paintInvalidationContainerSkipped are not null, on return *paintInvalidationContainerSkipped - // is true if the layoutObject returned is an ancestor of paintInvalidationContainer. + // 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; @@ -658,7 +752,7 @@ public: void setHasBoxDecorationBackground(bool); void invalidateBackgroundObscurationStatus(); - virtual bool computeBackgroundIsKnownToBeObscured() { return false; } + virtual bool computeBackgroundIsKnownToBeObscured() const { return false; } void setIsText() { m_bitfields.setIsText(true); } void setIsBox() { m_bitfields.setIsBox(true); } @@ -670,10 +764,15 @@ public: 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); + virtual void paint(const PaintInfo&, const LayoutPoint& paintOffset) const; // 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); } @@ -720,7 +819,8 @@ public: virtual bool nodeAtPoint(HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction); virtual PositionWithAffinity positionForPoint(const LayoutPoint&); - PositionWithAffinity createPositionWithAffinity(int offset, EAffinity); + PositionWithAffinity createPositionWithAffinity(int offset, TextAffinity); + PositionWithAffinity createPositionWithAffinity(int offset); PositionWithAffinity createPositionWithAffinity(const Position&); virtual void dirtyLinesFromChangedChild(LayoutObject*); @@ -737,7 +837,26 @@ public: void firstLineStyleDidChange(const ComputedStyle& oldStyle, const ComputedStyle& newStyle); - // returns the containing block level element for this element. + // 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 @@ -763,7 +882,7 @@ public: 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); + FloatPoint localToInvalidationBackingPoint(const LayoutPoint&, PaintLayer** 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. @@ -784,8 +903,6 @@ public: // Build an array of quads in absolute coords for line boxes virtual void absoluteQuads(Vector<FloatQuad>&, bool* /* wasFixed */ = nullptr) const { } - virtual IntRect absoluteFocusRingBoundingBoxRect() const; - static FloatRect absoluteBoundingBoxRectForRange(const Range*); // the rect that will be painted if this object is passed as the paintingRoot @@ -826,6 +943,7 @@ public: virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const; struct AppliedTextDecoration { + STACK_ALLOCATED(); Color color; TextDecorationStyle style; AppliedTextDecoration() : color(Color::transparent), style(TextDecorationStyleSolid) { } @@ -877,7 +995,6 @@ public: // coordinate space. This method deals with outlines and overflow. virtual LayoutRect absoluteClippedOverflowRect() const; virtual LayoutRect clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* = nullptr) const; - virtual LayoutRect rectWithOutlineForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, LayoutUnit outlineWidth, 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. @@ -896,14 +1013,6 @@ public: bool hasReflection() const { return m_bitfields.hasReflection(); } - enum SelectionState { - SelectionNone, // The object is not selected. - SelectionStart, // The object either contains the start of a selection run or is the start of a run - SelectionInside, // The object is fully encompassed by a selection run - SelectionEnd, // The object either contains the end of a selection run or is the end of a run - SelectionBoth // The object contains an entire run or is the sole selected object in that run - }; - // 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(); } @@ -913,7 +1022,7 @@ public: // 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(); } + virtual LayoutRect selectionRectForPaintInvalidation(const LayoutBoxModelObject* /* paintInvalidationContainer */) const { return LayoutRect(); } // View coordinates means the coordinate space of |view()|. LayoutRect selectionRectInViewCoordinates() const; @@ -924,8 +1033,8 @@ public: bool isSelectable() const; // Obtains the selection colors that should be used when painting a selection. Color selectionBackgroundColor() const; - Color selectionForegroundColor() const; - Color selectionEmphasisMarkColor() 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; } @@ -969,10 +1078,14 @@ public: virtual int previousOffsetForBackwardDeletion(int current) const; virtual int nextOffset(int current) const; - virtual void imageChanged(ImageResource*, const IntRect* = nullptr) override final; + // 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) { } - virtual bool willRenderImage(ImageResource*) override final; - virtual bool getImageAnimationPolicy(ImageResource*, ImageAnimationPolicy&) override final; void selectionStartEnd(int& spos, int& epos) const; @@ -1000,7 +1113,31 @@ public: bool createsGroup() const { return isTransparent() || hasMask() || hasFilter() || style()->hasBlendMode(); } - virtual void addFocusRingRects(Vector<LayoutRect>&, const LayoutPoint& additionalOffset) const { } + // 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; @@ -1009,13 +1146,37 @@ public: bool isRelayoutBoundaryForInspector() const; - // The previous paint invalidation rect in the object's previous paint backing. - const LayoutRect& previousPaintInvalidationRect() const { return m_previousPaintInvalidationRect; } + // 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 { return m_previousPositionFromPaintInvalidationBacking; } - void setPreviousPositionFromPaintInvalidationBacking(const LayoutPoint& positionFromPaintInvalidationBacking) { m_previousPositionFromPaintInvalidationBacking = positionFromPaintInvalidationBacking; } + const LayoutPoint& previousPositionFromPaintInvalidationBacking() const + { + ASSERT(!RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled()); + return m_previousPositionFromPaintInvalidationBacking; + } + void setPreviousPositionFromPaintInvalidationBacking(const LayoutPoint& positionFromPaintInvalidationBacking) + { + ASSERT(!RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled()); + m_previousPositionFromPaintInvalidationBacking = positionFromPaintInvalidationBacking; + } + + bool paintOffsetChanged(const LayoutPoint& newPaintOffset) const + { + ASSERT(RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled()); + return m_previousPositionFromPaintInvalidationBacking != uninitializedPaintOffset() && m_previousPositionFromPaintInvalidationBacking != newPaintOffset; + } + void setPreviousPaintOffset(const LayoutPoint& paintOffset) const + { + ASSERT(RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled()); + m_previousPositionFromPaintInvalidationBacking = paintOffset; + } PaintInvalidationReason fullPaintInvalidationReason() const { return m_bitfields.fullPaintInvalidationReason(); } bool shouldDoFullPaintInvalidation() const { return m_bitfields.fullPaintInvalidationReason() != PaintInvalidationNone; } @@ -1026,31 +1187,25 @@ public: virtual void clearPaintInvalidationState(const PaintInvalidationState&); - // Indicates whether this layout object was re-laid-out since the last frame. - // The flag will be cleared during invalidateTreeIfNeeded. - bool layoutDidGetCalledSinceLastFrame() const { return m_bitfields.layoutDidGetCalledSinceLastFrame(); } - bool mayNeedPaintInvalidation() const { return m_bitfields.mayNeedPaintInvalidation(); } void setMayNeedPaintInvalidation(); bool shouldInvalidateSelection() const { return m_bitfields.shouldInvalidateSelection(); } void setShouldInvalidateSelection(); - void clearShouldInvalidateSelection() { m_bitfields.setShouldInvalidateSelection(false); } - - bool neededLayoutBecauseOfChildren() const { return m_bitfields.neededLayoutBecauseOfChildren(); } - void setNeededLayoutBecauseOfChildren(bool b) { m_bitfields.setNeededLayoutBecauseOfChildren(b); } 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.ancestorHadPaintInvalidationForLocationChange() || shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState(); + return paintInvalidationState.forcedSubtreeInvalidationWithinContainer() + || paintInvalidationState.forcedSubtreeInvalidationRectUpdateWithinContainer() + || shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState(); } bool shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState() const { - return layoutDidGetCalledSinceLastFrame() || mayNeedPaintInvalidation() || shouldDoFullPaintInvalidation() || shouldInvalidateSelection(); + return mayNeedPaintInvalidation() || shouldDoFullPaintInvalidation() || shouldInvalidateSelection() || m_bitfields.childShouldCheckForPaintInvalidation(); } virtual bool supportsPaintInvalidationStateCachedOffsets() const { return !hasTransformRelatedProperty() && !hasReflection() && !style()->isFlippedBlocksWritingMode(); } @@ -1069,6 +1224,9 @@ public: // 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, @@ -1149,11 +1307,20 @@ protected: // time this function is called. virtual void styleDidChange(StyleDifference, const ComputedStyle* oldStyle); void propagateStyleToAnonymousChildren(bool blockChildrenOnly = false); - virtual void updateAnonymousChildStyle(const LayoutObject& child, ComputedStyle& style) const { } protected: - void setSelfMayNeedPaintInvalidation(); - + // 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(); @@ -1169,7 +1336,7 @@ protected: // 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; + virtual void addLayerHitTestRects(LayerHitTestRects&, const PaintLayer* 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. @@ -1179,14 +1346,13 @@ protected: 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); - void fullyInvalidatePaint(const LayoutBoxModelObject& paintInvalidationContainer, PaintInvalidationReason, const LayoutRect& oldBounds, const LayoutRect& newBounds); virtual bool hasNonCompositedScrollbars() const { return false; } #if ENABLE(ASSERT) virtual bool paintInvalidationStateIsDirty() const { - return neededLayoutBecauseOfChildren() || shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState(); + return m_bitfields.neededLayoutBecauseOfChildren() || shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState(); } #endif @@ -1201,7 +1367,27 @@ protected: 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); } + + const LayoutRect& previousPaintInvalidationRect() const { return m_previousPaintInvalidationRect; } + private: + void fullyInvalidatePaint(const LayoutBoxModelObject& paintInvalidationContainer, PaintInvalidationReason, const LayoutRect& oldBounds, const LayoutRect& newBounds); + + // 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; @@ -1225,11 +1411,6 @@ private: inline void invalidateContainerPreferredLogicalWidths(); - void clearMayNeedPaintInvalidation(); - - void setLayoutDidGetCalledSinceLastFrame(); - void clearLayoutDidGetCalledSinceLastFrame() { m_bitfields.setLayoutDidGetCalledSinceLastFrame(false); } - void invalidatePaintIncludingNonCompositingDescendantsInternal(const LayoutBoxModelObject& repaintContainer); LayoutRect previousSelectionRectForPaintInvalidation() const; @@ -1238,13 +1419,12 @@ private: const LayoutBoxModelObject* enclosingCompositedContainer() const; LayoutFlowThread* locateFlowThreadContainingBlock() const; - void removeFromLayoutFlowThread(); void removeFromLayoutFlowThreadRecursive(LayoutFlowThread*); ComputedStyle* cachedFirstLineStyle() const; StyleDifference adjustStyleDifference(StyleDifference) const; - Color selectionColor(int colorProperty) const; + Color selectionColor(int colorProperty, const GlobalPaintFlags) const; void removeShapeImageClient(ShapeValue*); @@ -1258,9 +1438,12 @@ private: const LayoutBoxModelObject* invalidatePaintRectangleInternal(const LayoutRect&) const; + static LayoutPoint uninitializedPaintOffset() { return LayoutPoint(LayoutUnit::max(), LayoutUnit::max()); } + 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; @@ -1284,25 +1467,44 @@ private: IsStaticallyPositioned = 0, IsRelativelyPositioned = 1, IsOutOfFlowPositioned = 2, + IsStickyPositioned = 3, }; public: + // LayoutObjectBitfields holds all the boolean values for LayoutObject. + // + // This is done to promote better packing on LayoutObject (at the + // expense of preventing bit field packing for the subclasses). Classes + // concerned about packing and memory use should hoist their boolean to + // this class. See below the field from sub-classes (e.g. + // childrenInline). + // + // Some of those booleans are caches of ComputedStyle values (e.g. + // positionState). This enables better memory locality and thus better + // performance. + // + // This class is an artifact of the WebKit era where LayoutObject wasn't + // allowed to grow and each sub-class was strictly monitored for memory + // increase. Our measurements indicate that the size of LayoutObject and + // subsequent classes do not impact memory or speed in a significant + // manner. This is based on growing LayoutObject in + // https://codereview.chromium.org/44673003 and subsequent relaxations + // of the memory constraints on layout objects. LayoutObjectBitfields(Node* node) : m_selfNeedsLayout(false) - , m_shouldInvalidateOverflowForPaint(false) - // FIXME: We should remove mayNeedPaintInvalidation once we are able to - // use the other layout flags to detect the same cases. crbug.com/370118 - , m_mayNeedPaintInvalidation(false) - , m_shouldInvalidateSelection(false) - , m_neededLayoutBecauseOfChildren(false) , m_needsPositionedMovementLayout(false) , m_normalChildNeedsLayout(false) , m_posChildNeedsLayout(false) , m_needsSimplifiedNormalFlowLayout(false) - , m_preferredLogicalWidthsDirty(false) - , m_floating(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) @@ -1317,13 +1519,13 @@ private: , m_hasCounterNodeMap(false) , m_everHadLayout(false) , m_ancestorLineBoxDirty(false) - , m_layoutDidGetCalledSinceLastFrame(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) @@ -1334,40 +1536,109 @@ private: { } - // 32 bits have been used in the first word, and 16 in the second. + // 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); - ADD_BOOLEAN_BITFIELD(shouldInvalidateOverflowForPaint, ShouldInvalidateOverflowForPaint); - ADD_BOOLEAN_BITFIELD(mayNeedPaintInvalidation, MayNeedPaintInvalidation); - ADD_BOOLEAN_BITFIELD(shouldInvalidateSelection, ShouldInvalidateSelection); - ADD_BOOLEAN_BITFIELD(neededLayoutBecauseOfChildren, NeededLayoutBecauseOfChildren); + + // 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); - ADD_BOOLEAN_BITFIELD(preferredLogicalWidthsDirty, PreferredLogicalWidthsDirty); - ADD_BOOLEAN_BITFIELD(floating, Floating); + + // 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. + + // This boolean is the cached value of 'float' + // (see ComputedStyle::isFloating). + 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 paragraphs). 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 + + // This boolean is set if overflow != 'visible'. + // This means that this object may need an overflow clip to be applied + // at paint time to its visual overflow (see OverflowModel for more + // details). + // Only set for LayoutBoxes and descendants. + ADD_BOOLEAN_BITFIELD(hasOverflowClip, HasOverflowClip); + + // This boolean is the cached value from + // ComputedStyle::hasTransformRelatedProperty. 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(layoutDidGetCalledSinceLastFrame, LayoutDidGetCalledSinceLastFrame); - ADD_BOOLEAN_BITFIELD(hasPendingResourceUpdate, HasPendingResourceUpdate); ADD_BOOLEAN_BITFIELD(isInsideFlowThread, IsInsideFlowThread); @@ -1379,6 +1650,9 @@ private: // from LayoutBlock ADD_BOOLEAN_BITFIELD(childrenInline, ChildrenInline); + // from LayoutBlockFlow + ADD_BOOLEAN_BITFIELD(containsInlineWithOutlineAndContinuation, ContainsInlineWithOutlineAndContinuation); + // from LayoutInline ADD_BOOLEAN_BITFIELD(alwaysCreateLineBoxesForLayoutInline, AlwaysCreateLineBoxesForLayoutInline); @@ -1388,14 +1662,19 @@ private: ADD_BOOLEAN_BITFIELD(isSlowRepaintObject, IsSlowRepaintObject); private: + // This is the cached 'position' value of this object + // (see ComputedStyle::position). unsigned m_positionedState : 2; // PositionedState unsigned m_selectionState : 3; // SelectionState - unsigned m_boxDecorationBackgroundState : 2; // BoxDecorationBackgroundState + // Mutable for getter which lazily update this field. + mutable 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) @@ -1409,7 +1688,7 @@ private: 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; } + ALWAYS_INLINE void setBoxDecorationBackgroundState(BoxDecorationBackgroundState s) const { m_boxDecorationBackgroundState = s; } PaintInvalidationReason fullPaintInvalidationReason() const { return static_cast<PaintInvalidationReason>(m_fullPaintInvalidationReason); } void setFullPaintInvalidationReason(PaintInvalidationReason reason) { m_fullPaintInvalidationReason = reason; } @@ -1425,25 +1704,30 @@ private: 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 setEverHadLayout(bool b) { m_bitfields.setEverHadLayout(b); } - void setShouldInvalidateOverflowForPaint(bool b) { m_bitfields.setShouldInvalidateOverflowForPaint(b); } - void setSelfNeedsOverflowRecalcAfterStyleChange(bool b) { m_bitfields.setSelfNeedsOverflowRecalcAfterStyleChange(b); } - void setChildNeedsOverflowRecalcAfterStyleChange(bool b) { m_bitfields.setChildNeedsOverflowRecalcAfterStyleChange(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 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. - LayoutPoint m_previousPositionFromPaintInvalidationBacking; + // This point does *not* account for composited scrolling. See adjustInvalidationRectForCompositedScrolling(). + // For slimmingPaintOffsetCaching, this stores the previous paint offset. + // TODO(wangxianzhu): Rename this to m_previousPaintOffset when we enable slimmingPaintOffsetCaching. + // TODO(wangxianzhu): Better mutation control for painting. + mutable 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(); @@ -1457,6 +1741,7 @@ private: // 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(); @@ -1524,15 +1809,19 @@ inline void LayoutObject::setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidat inline void LayoutObject::clearNeedsLayout() { - setNeededLayoutBecauseOfChildren(needsLayoutBecauseOfChildren()); - setLayoutDidGetCalledSinceLastFrame(); + // Set flags for later stages/cycles. + setEverHadLayout(); + setMayNeedPaintInvalidation(); + m_bitfields.setNeededLayoutBecauseOfChildren(needsLayoutBecauseOfChildren()); + + // Clear needsLayout flags. setSelfNeedsLayout(false); - setEverHadLayout(true); setPosChildNeedsLayout(false); setNeedsSimplifiedNormalFlowLayout(false); setNormalChildNeedsLayout(false); setNeedsPositionedMovementLayout(false); setAncestorLineBoxDirty(false); + #if ENABLE(ASSERT) checkBlockPositionedObjectsNeedLayout(); #endif @@ -1603,7 +1892,7 @@ inline void LayoutObject::invalidateBackgroundObscurationStatus() m_bitfields.setBoxDecorationBackgroundState(HasBoxDecorationBackgroundObscurationStatusInvalid); } -inline bool LayoutObject::boxDecorationBackgroundIsKnownToBeObscured() +inline bool LayoutObject::boxDecorationBackgroundIsKnownToBeObscured() const { if (m_bitfields.boxDecorationBackgroundState() == HasBoxDecorationBackgroundObscurationStatusInvalid) { BoxDecorationBackgroundState state = computeBackgroundIsKnownToBeObscured() ? HasBoxDecorationBackgroundKnownToBeObscured : HasBoxDecorationBackgroundMayBeVisible; |