Move some RenderObject member functions to RenderElement.
[WebKit-https.git] / Source / WebCore / rendering / RenderElement.h
1 /*
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.
6  *
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.
11  *
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.
16  *
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.
21  */
22
23 #ifndef RenderElement_h
24 #define RenderElement_h
25
26 #include "AnimationController.h"
27 #include "RenderObject.h"
28
29 namespace WebCore {
30
31 class ControlStates;
32
33 class RenderElement : public RenderObject {
34 public:
35     virtual ~RenderElement();
36
37     static RenderPtr<RenderElement> createFor(Element&, PassRef<RenderStyle>);
38
39     bool hasInitializedStyle() const { return m_hasInitializedStyle; }
40
41     RenderStyle& style() const { return const_cast<RenderStyle&>(m_style.get()); }
42     RenderStyle& firstLineStyle() const;
43
44     void initializeStyle();
45
46     void setStyle(PassRef<RenderStyle>);
47     // Called to update a style that is allowed to trigger animations.
48     void setAnimatableStyle(PassRef<RenderStyle>);
49
50     // This is null for anonymous renderers.
51     Element* element() const { return downcast<Element>(RenderObject::node()); }
52     Element* nonPseudoElement() const { return downcast<Element>(RenderObject::nonPseudoNode()); }
53     Element* generatingElement() const;
54
55     RenderObject* firstChild() const { return m_firstChild; }
56     RenderObject* lastChild() const { return m_lastChild; }
57
58     virtual bool isEmpty() const override { return !firstChild(); }
59
60     // FIXME: Make these standalone and move to relevant files.
61     bool isRenderLayerModelObject() const;
62     bool isBoxModelObject() const;
63     bool isRenderBlock() const;
64     bool isRenderBlockFlow() const;
65     bool isRenderReplaced() const;
66     bool isRenderInline() const;
67     bool isRenderNamedFlowFragmentContainer() const;
68
69     virtual bool isChildAllowed(const RenderObject&, const RenderStyle&) const { return true; }
70     virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
71     virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild = 0) { return addChild(newChild, beforeChild); }
72     virtual RenderObject* removeChild(RenderObject&);
73
74     // The following functions are used when the render tree hierarchy changes to make sure layers get
75     // properly added and removed. Since containership can be implemented by any subclass, and since a hierarchy
76     // can contain a mixture of boxes and other object types, these functions need to be in the base class.
77     void addLayers(RenderLayer* parentLayer);
78     void removeLayers(RenderLayer* parentLayer);
79     void moveLayers(RenderLayer* oldParent, RenderLayer* newParent);
80     RenderLayer* findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint, bool checkParent = true);
81
82     enum NotifyChildrenType { NotifyChildren, DontNotifyChildren };
83     void insertChildInternal(RenderObject*, RenderObject* beforeChild, NotifyChildrenType);
84     RenderObject* removeChildInternal(RenderObject&, NotifyChildrenType);
85
86     virtual RenderElement* hoverAncestor() const;
87
88     virtual void dirtyLinesFromChangedChild(RenderObject&) { }
89
90     bool ancestorLineBoxDirty() const { return m_ancestorLineBoxDirty; }
91     void setAncestorLineBoxDirty(bool f = true);
92
93     void setChildNeedsLayout(MarkingBehavior = MarkContainingBlockChain);
94     void clearChildNeedsLayout();
95     void setNeedsPositionedMovementLayout(const RenderStyle* oldStyle);
96     void setNeedsSimplifiedNormalFlowLayout();
97
98     virtual void paint(PaintInfo&, const LayoutPoint&) = 0;
99
100     // Recursive function that computes the size and position of this object and all its descendants.
101     virtual void layout();
102
103     /* This function performs a layout only if one is needed. */
104     void layoutIfNeeded() { if (needsLayout()) layout(); }
105
106     // Return the renderer whose background style is used to paint the root background. Should only be called on the renderer for which isRoot() is true.
107     RenderElement& rendererForRootBackground();
108
109     // Used only by Element::pseudoStyleCacheIsInvalid to get a first line style based off of a
110     // given new style, without accessing the cache.
111     PassRefPtr<RenderStyle> uncachedFirstLineStyle(RenderStyle*) const;
112
113     // Updates only the local style ptr of the object. Does not update the state of the object,
114     // and so only should be called when the style is known not to have changed (or from setStyle).
115     void setStyleInternal(PassRef<RenderStyle> style) { m_style = WTF::move(style); }
116
117     // Repaint only if our old bounds and new bounds are different. The caller may pass in newBounds and newOutlineBox if they are known.
118     bool repaintAfterLayoutIfNeeded(const RenderLayerModelObject* repaintContainer, const LayoutRect& oldBounds, const LayoutRect& oldOutlineBox, const LayoutRect* newBoundsPtr = nullptr, const LayoutRect* newOutlineBoxPtr = nullptr);
119
120     bool borderImageIsLoadedAndCanBeRendered() const;
121
122     // Returns true if this renderer requires a new stacking context.
123     bool createsGroup() const { return isTransparent() || hasMask() || hasFilter() || hasBlendMode(); }
124
125     bool isTransparent() const { return style().opacity() < 1.0f; }
126     float opacity() const { return style().opacity(); }
127
128     bool visibleToHitTesting() const { return style().visibility() == VISIBLE && style().pointerEvents() != PE_NONE; }
129
130     bool hasBackground() const { return style().hasBackground(); }
131     bool hasMask() const { return style().hasMask(); }
132     bool hasClip() const { return isOutOfFlowPositioned() && style().hasClip(); }
133     bool hasClipOrOverflowClip() const { return hasClip() || hasOverflowClip(); }
134     bool hasClipPath() const { return style().clipPath(); }
135     bool hasHiddenBackface() const { return style().backfaceVisibility() == BackfaceVisibilityHidden; }
136
137     bool hasFilter() const { return style().hasFilter(); }
138
139 #if ENABLE(CSS_COMPOSITING)
140     bool hasBlendMode() const { return style().hasBlendMode(); }
141 #else
142     bool hasBlendMode() const { return false; }
143 #endif
144
145 #if ENABLE(CSS_SHAPES)
146     bool hasShapeOutside() const { return style().shapeOutside(); }
147 #else
148     bool hasShapeOutside() const { return false; }
149 #endif
150
151     bool repaintForPausedImageAnimationsIfNeeded(const IntRect& visibleRect);
152     bool hasPausedImageAnimations() const { return m_hasPausedImageAnimations; }
153     void setHasPausedImageAnimations(bool b) { m_hasPausedImageAnimations = b; }
154
155     RenderNamedFlowThread* renderNamedFlowThreadWrapper();
156
157     void setRenderBoxNeedsLazyRepaint(bool b) { m_renderBoxNeedsLazyRepaint = b; }
158     bool renderBoxNeedsLazyRepaint() const { return m_renderBoxNeedsLazyRepaint; }
159
160     bool hasCounterNodeMap() const { return m_hasCounterNodeMap; }
161     void setHasCounterNodeMap(bool f) { m_hasCounterNodeMap = f; }
162
163     bool isCSSAnimating() const { return m_isCSSAnimating; }
164     void setIsCSSAnimating(bool b) { m_isCSSAnimating = b; }
165
166 protected:
167     enum BaseTypeFlags {
168         RenderLayerModelObjectFlag = 1 << 0,
169         RenderBoxModelObjectFlag = 1 << 1,
170         RenderInlineFlag = 1 << 2,
171         RenderReplacedFlag = 1 << 3,
172         RenderBlockFlag = 1 << 4,
173         RenderBlockFlowFlag = 1 << 5,
174     };
175
176     RenderElement(Element&, PassRef<RenderStyle>, unsigned baseTypeFlags);
177     RenderElement(Document&, PassRef<RenderStyle>, unsigned baseTypeFlags);
178
179     bool layerCreationAllowedForSubtree() const;
180
181     enum StylePropagationType { PropagateToAllChildren, PropagateToBlockChildrenOnly };
182     void propagateStyleToAnonymousChildren(StylePropagationType);
183
184     LayoutUnit valueForLength(const Length&, LayoutUnit maximumValue) const;
185     LayoutUnit minimumValueForLength(const Length&, LayoutUnit maximumValue, bool roundPercentages = false) const;
186
187     void setFirstChild(RenderObject* child) { m_firstChild = child; }
188     void setLastChild(RenderObject* child) { m_lastChild = child; }
189     void destroyLeftoverChildren();
190
191     virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle);
192     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
193
194     virtual void insertedIntoTree() override;
195     virtual void willBeRemovedFromTree() override;
196     virtual void willBeDestroyed() override;
197
198     void setRenderInlineAlwaysCreatesLineBoxes(bool b) { m_renderInlineAlwaysCreatesLineBoxes = b; }
199     bool renderInlineAlwaysCreatesLineBoxes() const { return m_renderInlineAlwaysCreatesLineBoxes; }
200
201     void setHasContinuation(bool b) { m_hasContinuation = b; }
202     bool hasContinuation() const { return m_hasContinuation; }
203
204     static bool hasControlStatesForRenderer(const RenderObject*);
205     static ControlStates* controlStatesForRenderer(const RenderObject*);
206     static void removeControlStatesForRenderer(const RenderObject*);
207     static void addControlStatesForRenderer(const RenderObject*, ControlStates*);
208
209 private:
210     RenderElement(ContainerNode&, PassRef<RenderStyle>, unsigned baseTypeFlags);
211     void node() const = delete;
212     void nonPseudoNode() const = delete;
213     void generatingNode() const = delete;
214     void isText() const = delete;
215     void isRenderElement() const = delete;
216
217     virtual RenderObject* firstChildSlow() const override final { return firstChild(); }
218     virtual RenderObject* lastChildSlow() const override final { return lastChild(); }
219
220     // Called when an object that was floating or positioned becomes a normal flow object
221     // again.  We have to make sure the render tree updates as needed to accommodate the new
222     // normal flow object.
223     void handleDynamicFloatPositionChange();
224     void removeAnonymousWrappersForInlinesIfNecessary();
225
226     bool shouldRepaintForStyleDifference(StyleDifference) const;
227     bool hasImmediateNonWhitespaceTextChildOrBorderOrOutline() const;
228
229     void updateFillImages(const FillLayer*, const FillLayer*);
230     void updateImage(StyleImage*, StyleImage*);
231 #if ENABLE(CSS_SHAPES)
232     void updateShapeImage(const ShapeValue*, const ShapeValue*);
233 #endif
234
235     StyleDifference adjustStyleDifference(StyleDifference, unsigned contextSensitiveProperties) const;
236     RenderStyle* cachedFirstLineStyle() const;
237
238     virtual void newImageAnimationFrameAvailable(CachedImage&) final override;
239
240     unsigned m_baseTypeFlags : 6;
241     unsigned m_ancestorLineBoxDirty : 1;
242     unsigned m_hasInitializedStyle : 1;
243
244     unsigned m_renderInlineAlwaysCreatesLineBoxes : 1;
245     unsigned m_renderBoxNeedsLazyRepaint : 1;
246     unsigned m_hasPausedImageAnimations : 1;
247     unsigned m_hasCounterNodeMap : 1;
248     unsigned m_isCSSAnimating : 1;
249     unsigned m_hasContinuation : 1;
250
251     RenderObject* m_firstChild;
252     RenderObject* m_lastChild;
253
254     Ref<RenderStyle> m_style;
255
256     // FIXME: Get rid of this hack.
257     // Store state between styleWillChange and styleDidChange
258     static bool s_affectsParentBlock;
259     static bool s_noLongerAffectsParentBlock;
260 };
261
262 inline void RenderElement::setAnimatableStyle(PassRef<RenderStyle> style)
263 {
264     setStyle(animation().updateAnimations(*this, WTF::move(style)));
265 }
266
267 inline RenderStyle& RenderElement::firstLineStyle() const
268 {
269     return document().styleSheetCollection().usesFirstLineRules() ? *cachedFirstLineStyle() : style();
270 }
271
272 inline void RenderElement::setAncestorLineBoxDirty(bool f)
273 {
274     m_ancestorLineBoxDirty = f;
275     if (m_ancestorLineBoxDirty)
276         setNeedsLayout();
277 }
278
279 inline void RenderElement::setChildNeedsLayout(MarkingBehavior markParents)
280 {
281     ASSERT(!isSetNeedsLayoutForbidden());
282     if (normalChildNeedsLayout())
283         return;
284     setNormalChildNeedsLayoutBit(true);
285     if (markParents == MarkContainingBlockChain)
286         markContainingBlocksForLayout();
287 }
288
289 inline LayoutUnit RenderElement::valueForLength(const Length& length, LayoutUnit maximumValue) const
290 {
291     return WebCore::valueForLength(length, maximumValue);
292 }
293
294 inline LayoutUnit RenderElement::minimumValueForLength(const Length& length, LayoutUnit maximumValue, bool roundPercentages) const
295 {
296     return WebCore::minimumValueForLength(length, maximumValue, roundPercentages);
297 }
298
299 inline bool RenderElement::isRenderLayerModelObject() const
300 {
301     return m_baseTypeFlags & RenderLayerModelObjectFlag;
302 }
303
304 inline bool RenderElement::isBoxModelObject() const
305 {
306     return m_baseTypeFlags & RenderBoxModelObjectFlag;
307 }
308
309 inline bool RenderElement::isRenderBlock() const
310 {
311     return m_baseTypeFlags & RenderBlockFlag;
312 }
313
314 inline bool RenderElement::isRenderBlockFlow() const
315 {
316     return m_baseTypeFlags & RenderBlockFlowFlag;
317 }
318
319 inline bool RenderElement::isRenderReplaced() const
320 {
321     return m_baseTypeFlags & RenderReplacedFlag;
322 }
323
324 inline bool RenderElement::isRenderInline() const
325 {
326     return m_baseTypeFlags & RenderInlineFlag;
327 }
328
329 inline Element* RenderElement::generatingElement() const
330 {
331     if (parent() && isRenderNamedFlowFragment())
332         return parent()->generatingElement();
333     return downcast<Element>(RenderObject::generatingNode());
334 }
335
336 inline bool RenderObject::isRenderLayerModelObject() const
337 {
338     return is<RenderElement>(*this) && downcast<RenderElement>(*this).isRenderLayerModelObject();
339 }
340
341 inline bool RenderObject::isBoxModelObject() const
342 {
343     return is<RenderElement>(*this) && downcast<RenderElement>(*this).isBoxModelObject();
344 }
345
346 inline bool RenderObject::isRenderBlock() const
347 {
348     return is<RenderElement>(*this) && downcast<RenderElement>(*this).isRenderBlock();
349 }
350
351 inline bool RenderObject::isRenderBlockFlow() const
352 {
353     return is<RenderElement>(*this) && downcast<RenderElement>(*this).isRenderBlockFlow();
354 }
355
356 inline bool RenderObject::isRenderReplaced() const
357 {
358     return is<RenderElement>(*this) && downcast<RenderElement>(*this).isRenderReplaced();
359 }
360
361 inline bool RenderObject::isRenderInline() const
362 {
363     return is<RenderElement>(*this) && downcast<RenderElement>(*this).isRenderInline();
364 }
365
366 inline RenderStyle& RenderObject::style() const
367 {
368     if (isText())
369         return m_parent->style();
370     return downcast<RenderElement>(*this).style();
371 }
372
373 inline RenderStyle& RenderObject::firstLineStyle() const
374 {
375     if (isText())
376         return m_parent->firstLineStyle();
377     return downcast<RenderElement>(*this).firstLineStyle();
378 }
379
380 inline RenderElement* ContainerNode::renderer() const
381 {
382     return downcast<RenderElement>(Node::renderer());
383 }
384
385 inline int adjustForAbsoluteZoom(int value, const RenderElement& renderer)
386 {
387     return adjustForAbsoluteZoom(value, renderer.style());
388 }
389
390 inline LayoutUnit adjustLayoutUnitForAbsoluteZoom(LayoutUnit value, const RenderElement& renderer)
391 {
392     return adjustLayoutUnitForAbsoluteZoom(value, renderer.style());
393 }
394
395 } // namespace WebCore
396
397 SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderElement, isRenderElement())
398
399 #endif // RenderElement_h