Make RenderLayer not arena-allocated.
[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, unsigned baseTypeFlags)
41     : RenderElement(element, baseTypeFlags | RenderLayerModelObjectFlag)
42 {
43 }
44
45 RenderLayerModelObject::~RenderLayerModelObject()
46 {
47     // Our layer should have been destroyed and cleared by now
48     ASSERT(!hasLayer());
49     ASSERT(!m_layer);
50 }
51
52 void RenderLayerModelObject::destroyLayer()
53 {
54     ASSERT(!hasLayer()); // Callers should have already called setHasLayer(false)
55     ASSERT(m_layer);
56     m_layer = nullptr;
57 }
58
59 void RenderLayerModelObject::ensureLayer()
60 {
61     if (m_layer)
62         return;
63
64     m_layer = std::make_unique<RenderLayer>(*this);
65     setHasLayer(true);
66     m_layer->insertOnlyThisLayer();
67 }
68
69 bool RenderLayerModelObject::hasSelfPaintingLayer() const
70 {
71     return m_layer && m_layer->isSelfPaintingLayer();
72 }
73
74 void RenderLayerModelObject::willBeDestroyed()
75 {
76     if (isPositioned()) {
77         if (style()->hasViewportConstrainedPosition())
78             view().frameView().removeViewportConstrainedObject(this);
79     }
80
81     // RenderObject::willBeDestroyed calls back to destroyLayer() for layer destruction
82     RenderElement::willBeDestroyed();
83 }
84
85 void RenderLayerModelObject::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
86 {
87     s_wasFloating = isFloating();
88     s_hadLayer = hasLayer();
89     s_hadTransform = hasTransform();
90     if (s_hadLayer)
91         s_layerWasSelfPainting = layer()->isSelfPaintingLayer();
92
93     // If our z-index changes value or our visibility changes,
94     // we need to dirty our stacking context's z-order list.
95     RenderStyle* oldStyle = style();
96     if (oldStyle && newStyle) {
97         if (parent()) {
98             // Do a repaint with the old style first, e.g., for example if we go from
99             // having an outline to not having an outline.
100             if (diff == StyleDifferenceRepaintLayer) {
101                 layer()->repaintIncludingDescendants();
102                 if (!(oldStyle->clip() == newStyle->clip()))
103                     layer()->clearClipRectsIncludingDescendants();
104             } else if (diff == StyleDifferenceRepaint || newStyle->outlineSize() < oldStyle->outlineSize())
105                 repaint();
106         }
107
108         if (diff == StyleDifferenceLayout || diff == StyleDifferenceSimplifiedLayout) {
109             // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could
110             // end up being destroyed.
111             if (hasLayer()) {
112                 if (oldStyle->position() != newStyle->position()
113                     || oldStyle->zIndex() != newStyle->zIndex()
114                     || oldStyle->hasAutoZIndex() != newStyle->hasAutoZIndex()
115                     || !(oldStyle->clip() == newStyle->clip())
116                     || oldStyle->hasClip() != newStyle->hasClip()
117                     || oldStyle->opacity() != newStyle->opacity()
118                     || oldStyle->transform() != newStyle->transform()
119 #if ENABLE(CSS_FILTERS)
120                     || oldStyle->filter() != newStyle->filter()
121 #endif
122                     )
123                 layer()->repaintIncludingDescendants();
124             } else if (newStyle->hasTransform() || newStyle->opacity() < 1 || newStyle->hasFilter()) {
125                 // If we don't have a layer yet, but we are going to get one because of transform or opacity,
126                 //  then we need to repaint the old position of the object.
127                 repaint();
128             }
129         }
130     }
131
132     RenderElement::styleWillChange(diff, newStyle);
133 }
134
135 void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
136 {
137     RenderElement::styleDidChange(diff, oldStyle);
138     updateFromStyle();
139
140     if (requiresLayer()) {
141         if (!layer() && layerCreationAllowedForSubtree()) {
142             if (s_wasFloating && isFloating())
143                 setChildNeedsLayout();
144             ensureLayer();
145             if (parent() && !needsLayout() && containingBlock()) {
146                 layer()->setRepaintStatus(NeedsFullRepaint);
147                 // There is only one layer to update, it is not worth using |cachedOffset| since
148                 // we are not sure the value will be used.
149                 layer()->updateLayerPositions(0);
150             }
151         }
152     } else if (layer() && layer()->parent()) {
153         setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit.
154         setHasReflection(false);
155         layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer
156         if (s_wasFloating && isFloating())
157             setChildNeedsLayout();
158         if (s_hadTransform)
159             setNeedsLayoutAndPrefWidthsRecalc();
160     }
161
162     if (layer()) {
163         layer()->styleChanged(diff, oldStyle);
164         if (s_hadLayer && layer()->isSelfPaintingLayer() != s_layerWasSelfPainting)
165             setChildNeedsLayout();
166     }
167
168     bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosition();
169     bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportConstrainedPosition();
170     if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) {
171         if (newStyleIsViewportConstained && layer())
172             view().frameView().addViewportConstrainedObject(this);
173         else
174             view().frameView().removeViewportConstrainedObject(this);
175     }
176 }
177
178 } // namespace WebCore
179