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 "core/rendering/RenderLayerModelObject.h"
27
28 #include "core/frame/LocalFrame.h"
29 #include "core/rendering/RenderLayer.h"
30 #include "core/rendering/RenderView.h"
31
32 using namespace std;
33
34 namespace WebCore {
35
36 bool RenderLayerModelObject::s_wasFloating = false;
37
RenderLayerModelObject(ContainerNode * node)38 RenderLayerModelObject::RenderLayerModelObject(ContainerNode* node)
39 : RenderObject(node)
40 {
41 }
42
~RenderLayerModelObject()43 RenderLayerModelObject::~RenderLayerModelObject()
44 {
45 // Our layer should have been destroyed and cleared by now
46 ASSERT(!hasLayer());
47 ASSERT(!m_layer);
48 }
49
destroyLayer()50 void RenderLayerModelObject::destroyLayer()
51 {
52 setHasLayer(false);
53 m_layer = nullptr;
54 }
55
createLayer(LayerType type)56 void RenderLayerModelObject::createLayer(LayerType type)
57 {
58 ASSERT(!m_layer);
59 m_layer = adoptPtr(new RenderLayer(this, type));
60 setHasLayer(true);
61 m_layer->insertOnlyThisLayer();
62 }
63
hasSelfPaintingLayer() const64 bool RenderLayerModelObject::hasSelfPaintingLayer() const
65 {
66 return m_layer && m_layer->isSelfPaintingLayer();
67 }
68
scrollableArea() const69 ScrollableArea* RenderLayerModelObject::scrollableArea() const
70 {
71 return m_layer ? m_layer->scrollableArea() : 0;
72 }
73
willBeDestroyed()74 void RenderLayerModelObject::willBeDestroyed()
75 {
76 if (isPositioned()) {
77 // Don't use this->view() because the document's renderView has been set to 0 during destruction.
78 if (LocalFrame* frame = this->frame()) {
79 if (FrameView* frameView = frame->view()) {
80 if (style()->hasViewportConstrainedPosition())
81 frameView->removeViewportConstrainedObject(this);
82 }
83 }
84 }
85
86 RenderObject::willBeDestroyed();
87
88 destroyLayer();
89 }
90
styleWillChange(StyleDifference diff,const RenderStyle & newStyle)91 void RenderLayerModelObject::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
92 {
93 s_wasFloating = isFloating();
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) {
99 // Do a repaint with the old style first through RenderLayerRepainter.
100 // RenderObject::styleWillChange takes care of repainting objects without RenderLayers.
101 if (parent() && diff.needsRepaintLayer()) {
102 layer()->repainter().repaintIncludingNonCompositingDescendants();
103 if (oldStyle->hasClip() != newStyle.hasClip()
104 || oldStyle->clip() != newStyle.clip())
105 layer()->clipper().clearClipRectsIncludingDescendants();
106 } else if (diff.needsFullLayout()) {
107 if (hasLayer()) {
108 if (!layer()->hasCompositedLayerMapping() && oldStyle->position() != newStyle.position())
109 layer()->repainter().repaintIncludingNonCompositingDescendants();
110 } else if (newStyle.hasTransform() || newStyle.opacity() < 1 || newStyle.hasFilter()) {
111 // If we don't have a layer yet, but we are going to get one because of transform or opacity,
112 // then we need to repaint the old position of the object.
113 paintInvalidationForWholeRenderer();
114 }
115 }
116 }
117
118 RenderObject::styleWillChange(diff, newStyle);
119 }
120
styleDidChange(StyleDifference diff,const RenderStyle * oldStyle)121 void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
122 {
123 bool hadTransform = hasTransform();
124
125 RenderObject::styleDidChange(diff, oldStyle);
126 updateFromStyle();
127
128 LayerType type = layerTypeRequired();
129 if (type != NoLayer) {
130 if (!layer() && layerCreationAllowedForSubtree()) {
131 if (s_wasFloating && isFloating())
132 setChildNeedsLayout();
133 createLayer(type);
134 if (parent() && !needsLayout() && containingBlock()) {
135 // FIXME: This invalidation is overly broad. We should update to
136 // do the correct invalidation at RenderStyle::diff time. crbug.com/349061
137 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
138 layer()->renderer()->setShouldDoFullPaintInvalidationAfterLayout(true);
139 else
140 layer()->repainter().setRepaintStatus(NeedsFullRepaint);
141 // Hit in animations/interpolation/perspective-interpolation.html
142 // FIXME: I suspect we can remove this assert disabler now.
143 DisableCompositingQueryAsserts disabler;
144 layer()->updateLayerPositionRecursive();
145 }
146 }
147 } else if (layer() && layer()->parent()) {
148 setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit.
149 setHasReflection(false);
150 layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer
151 if (s_wasFloating && isFloating())
152 setChildNeedsLayout();
153 if (hadTransform)
154 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
155 }
156
157 if (layer()) {
158 // FIXME: Ideally we shouldn't need this setter but we can't easily infer an overflow-only layer
159 // from the style.
160 layer()->setLayerType(type);
161 layer()->styleChanged(diff, oldStyle);
162 }
163
164 if (FrameView *frameView = view()->frameView()) {
165 bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosition();
166 bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportConstrainedPosition();
167 if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) {
168 if (newStyleIsViewportConstained && layer())
169 frameView->addViewportConstrainedObject(this);
170 else
171 frameView->removeViewportConstrainedObject(this);
172 }
173 }
174 }
175
addLayerHitTestRects(LayerHitTestRects & rects,const RenderLayer * currentLayer,const LayoutPoint & layerOffset,const LayoutRect & containerRect) const176 void RenderLayerModelObject::addLayerHitTestRects(LayerHitTestRects& rects, const RenderLayer* currentLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) const
177 {
178 if (hasLayer()) {
179 if (isRenderView()) {
180 // RenderView is handled with a special fast-path, but it needs to know the current layer.
181 RenderObject::addLayerHitTestRects(rects, layer(), LayoutPoint(), LayoutRect());
182 } else {
183 // Since a RenderObject never lives outside it's container RenderLayer, we can switch
184 // to marking entire layers instead. This may sometimes mark more than necessary (when
185 // a layer is made of disjoint objects) but in practice is a significant performance
186 // savings.
187 layer()->addLayerHitTestRects(rects);
188 }
189 } else {
190 RenderObject::addLayerHitTestRects(rects, currentLayer, layerOffset, containerRect);
191 }
192 }
193
compositedLayerMapping() const194 CompositedLayerMappingPtr RenderLayerModelObject::compositedLayerMapping() const
195 {
196 return m_layer ? m_layer->compositedLayerMapping() : 0;
197 }
198
hasCompositedLayerMapping() const199 bool RenderLayerModelObject::hasCompositedLayerMapping() const
200 {
201 return m_layer ? m_layer->hasCompositedLayerMapping() : false;
202 }
203
groupedMapping() const204 CompositedLayerMapping* RenderLayerModelObject::groupedMapping() const
205 {
206 return m_layer ? m_layer->groupedMapping() : 0;
207 }
208
209 } // namespace WebCore
210
211