2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * Copyright (C) 2003, 2006, 2007, 2009, 2013 Apple Inc. All rights reserved.
5 * Copyright (C) 2010, 2012 Google Inc. All rights reserved.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
23 #ifndef RenderElement_h
24 #define RenderElement_h
26 #include "AnimationController.h"
27 #include "LengthFunctions.h"
28 #include "RenderObject.h"
29 #include "StyleInheritedData.h"
36 class RenderElement : public RenderObject {
38 virtual ~RenderElement();
40 static RenderPtr<RenderElement> createFor(Element&, RenderStyle&&);
42 bool hasInitializedStyle() const { return m_hasInitializedStyle; }
44 const RenderStyle& style() const { return m_style; }
45 const RenderStyle& firstLineStyle() const;
47 // FIXME: Style shouldn't be mutated.
48 RenderStyle& mutableStyle() { return m_style; }
50 void initializeStyle();
52 // Calling with minimalStyleDifference > StyleDifferenceEqual indicates that
53 // out-of-band state (e.g. animations) requires that styleDidChange processing
54 // continue even if the style isn't different from the current style.
55 void setStyle(RenderStyle&&, StyleDifference minimalStyleDifference = StyleDifferenceEqual);
57 // The pseudo element style can be cached or uncached. Use the cached method if the pseudo element doesn't respect
58 // any pseudo classes (and therefore has no concept of changing state).
59 const RenderStyle* getCachedPseudoStyle(PseudoId, const RenderStyle* parentStyle = nullptr) const;
60 RenderStyle* getMutableCachedPseudoStyle(PseudoId, const RenderStyle* parentStyle = nullptr);
61 std::unique_ptr<RenderStyle> getUncachedPseudoStyle(const PseudoStyleRequest&, const RenderStyle* parentStyle = nullptr, const RenderStyle* ownStyle = nullptr) const;
63 // This is null for anonymous renderers.
64 Element* element() const { return downcast<Element>(RenderObject::node()); }
65 Element* nonPseudoElement() const { return downcast<Element>(RenderObject::nonPseudoNode()); }
66 Element* generatingElement() const;
68 RenderObject* firstChild() const { return m_firstChild; }
69 RenderObject* lastChild() const { return m_lastChild; }
71 bool canContainFixedPositionObjects() const;
72 bool canContainAbsolutelyPositionedObjects() const;
74 Color selectionColor(int colorProperty) const;
75 std::unique_ptr<RenderStyle> selectionPseudoStyle() const;
77 // Obtains the selection colors that should be used when painting a selection.
78 Color selectionBackgroundColor() const;
79 Color selectionForegroundColor() const;
80 Color selectionEmphasisMarkColor() const;
82 // FIXME: Make these standalone and move to relevant files.
83 bool isRenderLayerModelObject() const;
84 bool isBoxModelObject() const;
85 bool isRenderBlock() const;
86 bool isRenderBlockFlow() const;
87 bool isRenderReplaced() const;
88 bool isRenderInline() const;
89 bool isRenderNamedFlowFragmentContainer() const;
91 virtual bool isChildAllowed(const RenderObject&, const RenderStyle&) const { return true; }
92 virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = nullptr);
93 virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild = nullptr) { return addChild(newChild, beforeChild); }
94 virtual void removeChild(RenderObject&);
96 // The following functions are used when the render tree hierarchy changes to make sure layers get
97 // properly added and removed. Since containership can be implemented by any subclass, and since a hierarchy
98 // can contain a mixture of boxes and other object types, these functions need to be in the base class.
99 void addLayers(RenderLayer* parentLayer);
100 void removeLayers(RenderLayer* parentLayer);
101 void moveLayers(RenderLayer* oldParent, RenderLayer* newParent);
102 RenderLayer* findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint, bool checkParent = true);
104 enum NotifyChildrenType { NotifyChildren, DontNotifyChildren };
105 void insertChildInternal(RenderObject*, RenderObject* beforeChild, NotifyChildrenType);
106 void removeChildInternal(RenderObject&, NotifyChildrenType);
108 virtual RenderElement* hoverAncestor() const;
110 virtual void dirtyLinesFromChangedChild(RenderObject&) { }
112 bool ancestorLineBoxDirty() const { return m_ancestorLineBoxDirty; }
113 void setAncestorLineBoxDirty(bool f = true);
115 void setChildNeedsLayout(MarkingBehavior = MarkContainingBlockChain);
116 void clearChildNeedsLayout();
117 void setNeedsPositionedMovementLayout(const RenderStyle* oldStyle);
118 void setNeedsSimplifiedNormalFlowLayout();
120 virtual void paint(PaintInfo&, const LayoutPoint&) = 0;
122 // inline-block elements paint all phases atomically. This function ensures that. Certain other elements
123 // (grid items, flex items) require this behavior as well, and this function exists as a helper for them.
124 // It is expected that the caller will call this function independent of the value of paintInfo.phase.
125 void paintAsInlineBlock(PaintInfo&, const LayoutPoint&);
127 // Recursive function that computes the size and position of this object and all its descendants.
128 virtual void layout();
130 /* This function performs a layout only if one is needed. */
131 void layoutIfNeeded() { if (needsLayout()) layout(); }
133 // Return the renderer whose background style is used to paint the root background. Should only be called on the renderer for which isDocumentElementRenderer() is true.
134 RenderElement& rendererForRootBackground();
136 // Used only by Element::pseudoStyleCacheIsInvalid to get a first line style based off of a
137 // given new style, without accessing the cache.
138 std::unique_ptr<RenderStyle> uncachedFirstLineStyle(RenderStyle*) const;
140 // Updates only the local style ptr of the object. Does not update the state of the object,
141 // and so only should be called when the style is known not to have changed (or from setStyle).
142 void setStyleInternal(RenderStyle&& style) { m_style = WTFMove(style); }
144 // Repaint only if our old bounds and new bounds are different. The caller may pass in newBounds and newOutlineBox if they are known.
145 bool repaintAfterLayoutIfNeeded(const RenderLayerModelObject* repaintContainer, const LayoutRect& oldBounds, const LayoutRect& oldOutlineBox, const LayoutRect* newBoundsPtr = nullptr, const LayoutRect* newOutlineBoxPtr = nullptr);
147 bool borderImageIsLoadedAndCanBeRendered() const;
148 bool mayCauseRepaintInsideViewport(const IntRect* visibleRect = nullptr) const;
150 // Returns true if this renderer requires a new stacking context.
151 bool createsGroup() const { return isTransparent() || hasMask() || hasClipPath() || hasFilter() || hasBackdropFilter() || hasBlendMode(); }
153 bool isTransparent() const { return style().opacity() < 1.0f; }
154 float opacity() const { return style().opacity(); }
156 bool visibleToHitTesting() const { return style().visibility() == VISIBLE && style().pointerEvents() != PE_NONE; }
158 bool hasBackground() const { return style().hasBackground(); }
159 bool hasMask() const { return style().hasMask(); }
160 bool hasClip() const { return isOutOfFlowPositioned() && style().hasClip(); }
161 bool hasClipOrOverflowClip() const { return hasClip() || hasOverflowClip(); }
162 bool hasClipPath() const { return style().clipPath(); }
163 bool hasHiddenBackface() const { return style().backfaceVisibility() == BackfaceVisibilityHidden; }
164 bool hasOutlineAnnotation() const;
165 bool hasOutline() const { return style().hasOutline() || hasOutlineAnnotation(); }
166 bool hasSelfPaintingLayer() const;
168 bool checkForRepaintDuringLayout() const;
170 // anchorRect() is conceptually similar to absoluteBoundingBoxRect(), but is intended for scrolling to an anchor.
171 // For inline renderers, this gets the logical top left of the first leaf child and the logical bottom right of the
172 // last leaf child, converts them to absolute coordinates, and makes a box out of them.
173 LayoutRect anchorRect() const;
175 bool hasFilter() const { return style().hasFilter(); }
176 bool hasBackdropFilter() const
178 #if ENABLE(FILTERS_LEVEL_2)
179 return style().hasBackdropFilter();
186 #if ENABLE(CSS_COMPOSITING)
187 bool hasBlendMode() const { return style().hasBlendMode(); }
189 bool hasBlendMode() const { return false; }
192 #if ENABLE(CSS_SHAPES)
193 bool hasShapeOutside() const { return style().shapeOutside(); }
195 bool hasShapeOutside() const { return false; }
198 void registerForVisibleInViewportCallback();
199 void unregisterForVisibleInViewportCallback();
200 void visibleInViewportStateChanged(VisibleInViewportState);
202 bool repaintForPausedImageAnimationsIfNeeded(const IntRect& visibleRect);
203 bool hasPausedImageAnimations() const { return m_hasPausedImageAnimations; }
204 void setHasPausedImageAnimations(bool b) { m_hasPausedImageAnimations = b; }
206 RenderNamedFlowThread* renderNamedFlowThreadWrapper();
208 void setRenderBoxNeedsLazyRepaint(bool b) { m_renderBoxNeedsLazyRepaint = b; }
209 bool renderBoxNeedsLazyRepaint() const { return m_renderBoxNeedsLazyRepaint; }
211 bool hasCounterNodeMap() const { return m_hasCounterNodeMap; }
212 void setHasCounterNodeMap(bool f) { m_hasCounterNodeMap = f; }
214 bool isCSSAnimating() const { return m_isCSSAnimating; }
215 void setIsCSSAnimating(bool b) { m_isCSSAnimating = b; }
217 const RenderElement* enclosingRendererWithTextDecoration(TextDecoration, bool firstLine) const;
218 void drawLineForBoxSide(GraphicsContext&, const FloatRect&, BoxSide, Color, EBorderStyle, float adjacentWidth1, float adjacentWidth2, bool antialias = false) const;
220 bool childRequiresTable(const RenderObject& child) const;
221 bool hasContinuation() const { return m_hasContinuation; }
223 #if ENABLE(IOS_TEXT_AUTOSIZING)
224 void adjustComputedFontSizesOnBlocks(float size, float visibleWidth);
225 WEBCORE_EXPORT void resetTextAutosizing();
227 RenderBlock* containingBlockForFixedPosition() const;
228 RenderBlock* containingBlockForAbsolutePosition() const;
230 RespectImageOrientationEnum shouldRespectImageOrientation() const;
234 RenderLayerModelObjectFlag = 1 << 0,
235 RenderBoxModelObjectFlag = 1 << 1,
236 RenderInlineFlag = 1 << 2,
237 RenderReplacedFlag = 1 << 3,
238 RenderBlockFlag = 1 << 4,
239 RenderBlockFlowFlag = 1 << 5,
242 typedef unsigned BaseTypeFlags;
244 RenderElement(Element&, RenderStyle&&, BaseTypeFlags);
245 RenderElement(Document&, RenderStyle&&, BaseTypeFlags);
247 bool layerCreationAllowedForSubtree() const;
249 enum StylePropagationType { PropagateToAllChildren, PropagateToBlockChildrenOnly };
250 void propagateStyleToAnonymousChildren(StylePropagationType);
252 LayoutUnit valueForLength(const Length&, LayoutUnit maximumValue) const;
253 LayoutUnit minimumValueForLength(const Length&, LayoutUnit maximumValue) const;
255 void setFirstChild(RenderObject* child) { m_firstChild = child; }
256 void setLastChild(RenderObject* child) { m_lastChild = child; }
257 void destroyLeftoverChildren();
259 virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle);
260 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
262 void insertedIntoTree() override;
263 void willBeRemovedFromTree() override;
264 void willBeDestroyed() override;
266 void setRenderInlineAlwaysCreatesLineBoxes(bool b) { m_renderInlineAlwaysCreatesLineBoxes = b; }
267 bool renderInlineAlwaysCreatesLineBoxes() const { return m_renderInlineAlwaysCreatesLineBoxes; }
269 void setHasContinuation(bool b) { m_hasContinuation = b; }
271 void setRenderBlockHasMarginBeforeQuirk(bool b) { m_renderBlockHasMarginBeforeQuirk = b; }
272 void setRenderBlockHasMarginAfterQuirk(bool b) { m_renderBlockHasMarginAfterQuirk = b; }
273 void setRenderBlockShouldForceRelayoutChildren(bool b) { m_renderBlockShouldForceRelayoutChildren = b; }
274 bool renderBlockHasMarginBeforeQuirk() const { return m_renderBlockHasMarginBeforeQuirk; }
275 bool renderBlockHasMarginAfterQuirk() const { return m_renderBlockHasMarginAfterQuirk; }
276 bool renderBlockShouldForceRelayoutChildren() const { return m_renderBlockShouldForceRelayoutChildren; }
278 void setRenderBlockFlowLineLayoutPath(unsigned u) { m_renderBlockFlowLineLayoutPath = u; }
279 void setRenderBlockFlowHasMarkupTruncation(bool b) { m_renderBlockFlowHasMarkupTruncation = b; }
280 unsigned renderBlockFlowLineLayoutPath() const { return m_renderBlockFlowLineLayoutPath; }
281 bool renderBlockFlowHasMarkupTruncation() const { return m_renderBlockFlowHasMarkupTruncation; }
283 void paintFocusRing(PaintInfo&, const RenderStyle&, const Vector<LayoutRect>& focusRingRects);
284 void paintOutline(PaintInfo&, const LayoutRect&);
285 void updateOutlineAutoAncestor(bool hasOutlineAuto);
288 RenderElement(ContainerNode&, RenderStyle&&, BaseTypeFlags);
289 void node() const = delete;
290 void nonPseudoNode() const = delete;
291 void generatingNode() const = delete;
292 void isText() const = delete;
293 void isRenderElement() const = delete;
295 RenderObject* firstChildSlow() const final { return firstChild(); }
296 RenderObject* lastChildSlow() const final { return lastChild(); }
298 // Called when an object that was floating or positioned becomes a normal flow object
299 // again. We have to make sure the render tree updates as needed to accommodate the new
300 // normal flow object.
301 void handleDynamicFloatPositionChange();
302 void removeAnonymousWrappersForInlinesIfNecessary();
304 bool shouldRepaintForStyleDifference(StyleDifference) const;
305 bool hasImmediateNonWhitespaceTextChildOrBorderOrOutline() const;
307 void updateFillImages(const FillLayer*, const FillLayer*);
308 void updateImage(StyleImage*, StyleImage*);
309 #if ENABLE(CSS_SHAPES)
310 void updateShapeImage(const ShapeValue*, const ShapeValue*);
313 StyleDifference adjustStyleDifference(StyleDifference, unsigned contextSensitiveProperties) const;
314 const RenderStyle* cachedFirstLineStyle() const;
316 void newImageAnimationFrameAvailable(CachedImage&) final;
318 bool getLeadingCorner(FloatPoint& output) const;
319 bool getTrailingCorner(FloatPoint& output) const;
321 void clearLayoutRootIfNeeded() const;
323 bool shouldWillChangeCreateStackingContext() const;
324 void issueRepaintForOutlineAuto(float outlineSize);
326 unsigned m_baseTypeFlags : 6;
327 unsigned m_ancestorLineBoxDirty : 1;
328 unsigned m_hasInitializedStyle : 1;
330 unsigned m_renderInlineAlwaysCreatesLineBoxes : 1;
331 unsigned m_renderBoxNeedsLazyRepaint : 1;
332 unsigned m_hasPausedImageAnimations : 1;
333 unsigned m_hasCounterNodeMap : 1;
334 unsigned m_isCSSAnimating : 1;
335 unsigned m_hasContinuation : 1;
337 unsigned m_renderBlockHasMarginBeforeQuirk : 1;
338 unsigned m_renderBlockHasMarginAfterQuirk : 1;
339 unsigned m_renderBlockShouldForceRelayoutChildren : 1;
340 unsigned m_renderBlockFlowHasMarkupTruncation : 1;
341 unsigned m_renderBlockFlowLineLayoutPath : 2;
343 VisibleInViewportState m_visibleInViewportState { VisibilityUnknown };
345 RenderObject* m_firstChild;
346 RenderObject* m_lastChild;
350 // FIXME: Get rid of this hack.
351 // Store state between styleWillChange and styleDidChange
352 static bool s_affectsParentBlock;
353 static bool s_noLongerAffectsParentBlock;
356 inline void RenderElement::setAncestorLineBoxDirty(bool f)
358 m_ancestorLineBoxDirty = f;
359 if (m_ancestorLineBoxDirty)
363 inline void RenderElement::setChildNeedsLayout(MarkingBehavior markParents)
365 ASSERT(!isSetNeedsLayoutForbidden());
366 if (normalChildNeedsLayout())
368 setNormalChildNeedsLayoutBit(true);
369 if (markParents == MarkContainingBlockChain)
370 markContainingBlocksForLayout();
373 inline LayoutUnit RenderElement::valueForLength(const Length& length, LayoutUnit maximumValue) const
375 return WebCore::valueForLength(length, maximumValue);
378 inline LayoutUnit RenderElement::minimumValueForLength(const Length& length, LayoutUnit maximumValue) const
380 return WebCore::minimumValueForLength(length, maximumValue);
383 inline bool RenderElement::isRenderLayerModelObject() const
385 return m_baseTypeFlags & RenderLayerModelObjectFlag;
388 inline bool RenderElement::isBoxModelObject() const
390 return m_baseTypeFlags & RenderBoxModelObjectFlag;
393 inline bool RenderElement::isRenderBlock() const
395 return m_baseTypeFlags & RenderBlockFlag;
398 inline bool RenderElement::isRenderBlockFlow() const
400 return m_baseTypeFlags & RenderBlockFlowFlag;
403 inline bool RenderElement::isRenderReplaced() const
405 return m_baseTypeFlags & RenderReplacedFlag;
408 inline bool RenderElement::isRenderInline() const
410 return m_baseTypeFlags & RenderInlineFlag;
413 inline Element* RenderElement::generatingElement() const
415 if (parent() && isRenderNamedFlowFragment())
416 return parent()->generatingElement();
417 return downcast<Element>(RenderObject::generatingNode());
420 inline bool RenderElement::canContainFixedPositionObjects() const
422 return isRenderView()
423 || (hasTransform() && isRenderBlock())
424 || isSVGForeignObject()
425 || isOutOfFlowRenderFlowThread();
428 inline bool RenderElement::canContainAbsolutelyPositionedObjects() const
430 return style().position() != StaticPosition
431 || (isRenderBlock() && hasTransformRelatedProperty())
432 || isSVGForeignObject()
436 inline bool RenderObject::isRenderLayerModelObject() const
438 return is<RenderElement>(*this) && downcast<RenderElement>(*this).isRenderLayerModelObject();
441 inline bool RenderObject::isBoxModelObject() const
443 return is<RenderElement>(*this) && downcast<RenderElement>(*this).isBoxModelObject();
446 inline bool RenderObject::isRenderBlock() const
448 return is<RenderElement>(*this) && downcast<RenderElement>(*this).isRenderBlock();
451 inline bool RenderObject::isRenderBlockFlow() const
453 return is<RenderElement>(*this) && downcast<RenderElement>(*this).isRenderBlockFlow();
456 inline bool RenderObject::isRenderReplaced() const
458 return is<RenderElement>(*this) && downcast<RenderElement>(*this).isRenderReplaced();
461 inline bool RenderObject::isRenderInline() const
463 return is<RenderElement>(*this) && downcast<RenderElement>(*this).isRenderInline();
466 inline const RenderStyle& RenderObject::style() const
469 return m_parent->style();
470 return downcast<RenderElement>(*this).style();
473 inline const RenderStyle& RenderObject::firstLineStyle() const
476 return m_parent->firstLineStyle();
477 return downcast<RenderElement>(*this).firstLineStyle();
480 inline RenderElement* ContainerNode::renderer() const
482 return downcast<RenderElement>(Node::renderer());
485 inline int adjustForAbsoluteZoom(int value, const RenderElement& renderer)
487 return adjustForAbsoluteZoom(value, renderer.style());
490 inline LayoutUnit adjustLayoutUnitForAbsoluteZoom(LayoutUnit value, const RenderElement& renderer)
492 return adjustLayoutUnitForAbsoluteZoom(value, renderer.style());
495 } // namespace WebCore
497 SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderElement, isRenderElement())
499 #endif // RenderElement_h