Remove RenderObjectChildList
[WebKit-https.git] / Source / WebCore / rendering / RenderLayerModelObject.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
5  *           (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
6  * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
7  * Copyright (C) 2010, 2012 Google Inc. All rights reserved.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 #include "config.h"
26 #include "RenderLayerModelObject.h"
27
28 #include "RenderLayer.h"
29 #include "RenderView.h"
30
31 using namespace std;
32
33 namespace WebCore {
34
35 bool RenderLayerModelObject::s_wasFloating = false;
36 bool RenderLayerModelObject::s_hadLayer = false;
37 bool RenderLayerModelObject::s_hadTransform = false;
38 bool RenderLayerModelObject::s_layerWasSelfPainting = false;
39
40 RenderLayerModelObject::RenderLayerModelObject(Element* element)
41     : RenderElement(element)
42     , m_layer(0)
43 {
44 }
45
46 RenderLayerModelObject::~RenderLayerModelObject()
47 {
48     // Our layer should have been destroyed and cleared by now
49     ASSERT(!hasLayer());
50     ASSERT(!m_layer);
51 }
52
53 void RenderLayerModelObject::destroyLayer()
54 {
55     ASSERT(!hasLayer()); // Callers should have already called setHasLayer(false)
56     ASSERT(m_layer);
57     m_layer->destroy(renderArena());
58     m_layer = 0;
59 }
60
61 void RenderLayerModelObject::ensureLayer()
62 {
63     if (m_layer)
64         return;
65
66     m_layer = new (renderArena()) RenderLayer(*this);
67     setHasLayer(true);
68     m_layer->insertOnlyThisLayer();
69 }
70
71 bool RenderLayerModelObject::hasSelfPaintingLayer() const
72 {
73     return m_layer && m_layer->isSelfPaintingLayer();
74 }
75
76 void RenderLayerModelObject::willBeDestroyed()
77 {
78     if (isPositioned()) {
79         if (style()->hasViewportConstrainedPosition())
80             view().frameView().removeViewportConstrainedObject(this);
81     }
82
83     // RenderObject::willBeDestroyed calls back to destroyLayer() for layer destruction
84     RenderElement::willBeDestroyed();
85 }
86
87 void RenderLayerModelObject::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
88 {
89     s_wasFloating = isFloating();
90     s_hadLayer = hasLayer();
91     s_hadTransform = hasTransform();
92     if (s_hadLayer)
93         s_layerWasSelfPainting = layer()->isSelfPaintingLayer();
94
95     // If our z-index changes value or our visibility changes,
96     // we need to dirty our stacking context's z-order list.
97     RenderStyle* oldStyle = style();
98     if (oldStyle && newStyle) {
99         if (parent()) {
100             // Do a repaint with the old style first, e.g., for example if we go from
101             // having an outline to not having an outline.
102             if (diff == StyleDifferenceRepaintLayer) {
103                 layer()->repaintIncludingDescendants();
104                 if (!(oldStyle->clip() == newStyle->clip()))
105                     layer()->clearClipRectsIncludingDescendants();
106             } else if (diff == StyleDifferenceRepaint || newStyle->outlineSize() < oldStyle->outlineSize())
107                 repaint();
108         }
109
110         if (diff == StyleDifferenceLayout || diff == StyleDifferenceSimplifiedLayout) {
111             // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could
112             // end up being destroyed.
113             if (hasLayer()) {
114                 if (oldStyle->position() != newStyle->position()
115                     || oldStyle->zIndex() != newStyle->zIndex()
116                     || oldStyle->hasAutoZIndex() != newStyle->hasAutoZIndex()
117                     || !(oldStyle->clip() == newStyle->clip())
118                     || oldStyle->hasClip() != newStyle->hasClip()
119                     || oldStyle->opacity() != newStyle->opacity()
120                     || oldStyle->transform() != newStyle->transform()
121 #if ENABLE(CSS_FILTERS)
122                     || oldStyle->filter() != newStyle->filter()
123 #endif
124                     )
125                 layer()->repaintIncludingDescendants();
126             } else if (newStyle->hasTransform() || newStyle->opacity() < 1 || newStyle->hasFilter()) {
127                 // If we don't have a layer yet, but we are going to get one because of transform or opacity,
128                 //  then we need to repaint the old position of the object.
129                 repaint();
130             }
131         }
132     }
133
134     RenderElement::styleWillChange(diff, newStyle);
135 }
136
137 void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
138 {
139     RenderElement::styleDidChange(diff, oldStyle);
140     updateFromStyle();
141
142     if (requiresLayer()) {
143         if (!layer() && layerCreationAllowedForSubtree()) {
144             if (s_wasFloating && isFloating())
145                 setChildNeedsLayout(true);
146             ensureLayer();
147             if (parent() && !needsLayout() && containingBlock()) {
148                 layer()->setRepaintStatus(NeedsFullRepaint);
149                 // There is only one layer to update, it is not worth using |cachedOffset| since
150                 // we are not sure the value will be used.
151                 layer()->updateLayerPositions(0);
152             }
153         }
154     } else if (layer() && layer()->parent()) {
155         setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit.
156         setHasReflection(false);
157         layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer
158         if (s_wasFloating && isFloating())
159             setChildNeedsLayout(true);
160         if (s_hadTransform)
161             setNeedsLayoutAndPrefWidthsRecalc();
162     }
163
164     if (layer()) {
165         layer()->styleChanged(diff, oldStyle);
166         if (s_hadLayer && layer()->isSelfPaintingLayer() != s_layerWasSelfPainting)
167             setChildNeedsLayout(true);
168     }
169
170     bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosition();
171     bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportConstrainedPosition();
172     if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) {
173         if (newStyleIsViewportConstained && layer())
174             view().frameView().addViewportConstrainedObject(this);
175         else
176             view().frameView().removeViewportConstrainedObject(this);
177     }
178 }
179
180 bool RenderLayerModelObject::updateLayerIfNeeded()
181 {
182     LayoutStateDisabler layoutStateDisabler(&view());
183
184     bool hadLayer = hasLayer();
185     if (requiresLayer()) {
186         if (!layer() && layerCreationAllowedForSubtree()) {
187             ensureLayer();
188             if (parent() && containingBlock()) {
189                 layer()->setRepaintStatus(NeedsFullRepaint);
190                 // There is only one layer to update, it is not worth using |cachedOffset| since
191                 // we are not sure the value will be used.
192                 layer()->updateLayerPositions(0);
193             }
194         }
195     } else if (layer() && layer()->parent())
196         layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer
197
198     if (hadLayer == hasLayer())
199         return false;
200
201     if (layer())
202         layer()->styleChanged(StyleDifferenceEqual, 0);
203
204     return true;
205 }
206
207 } // namespace WebCore
208