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