1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2005 Allan Sandfeld Jensen (kde (at) carewolf.com) 5 * (C) 2005, 2006 Samuel Weinig (sam.weinig (at) 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/Frame.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 38 RenderLayerModelObject::RenderLayerModelObject(ContainerNode* node) 39 : RenderObject(node) 40 { 41 } 42 43 RenderLayerModelObject::~RenderLayerModelObject() 44 { 45 // Our layer should have been destroyed and cleared by now 46 ASSERT(!hasLayer()); 47 ASSERT(!m_layer); 48 } 49 50 void RenderLayerModelObject::destroyLayer() 51 { 52 setHasLayer(false); 53 m_layer = nullptr; 54 } 55 56 void RenderLayerModelObject::createLayer() 57 { 58 ASSERT(!m_layer); 59 m_layer = adoptPtr(new RenderLayer(this)); 60 setHasLayer(true); 61 m_layer->insertOnlyThisLayer(); 62 } 63 64 bool RenderLayerModelObject::hasSelfPaintingLayer() const 65 { 66 return m_layer && m_layer->isSelfPaintingLayer(); 67 } 68 69 ScrollableArea* RenderLayerModelObject::scrollableArea() const 70 { 71 return m_layer ? m_layer->scrollableArea() : 0; 72 } 73 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 (Frame* 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 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 && 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()->repainter().repaintIncludingDescendants(); 104 if (!(oldStyle->clip() == newStyle->clip())) 105 layer()->clipper().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 || oldStyle->filter() != newStyle->filter() 122 ) 123 layer()->repainter().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 RenderObject::styleWillChange(diff, newStyle); 133 } 134 135 void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) 136 { 137 bool hadTransform = hasTransform(); 138 bool hadLayer = hasLayer(); 139 bool layerWasSelfPainting = hadLayer && layer()->isSelfPaintingLayer(); 140 141 RenderObject::styleDidChange(diff, oldStyle); 142 updateFromStyle(); 143 144 if (requiresLayer()) { 145 if (!layer() && layerCreationAllowedForSubtree()) { 146 if (s_wasFloating && isFloating()) 147 setChildNeedsLayout(); 148 createLayer(); 149 if (parent() && !needsLayout() && containingBlock()) { 150 layer()->repainter().setRepaintStatus(NeedsFullRepaint); 151 // There is only one layer to update, it is not worth using |cachedOffset| since 152 // we are not sure the value will be used. 153 layer()->updateLayerPositions(0); 154 } 155 } 156 } else if (layer() && layer()->parent()) { 157 setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit. 158 setHasReflection(false); 159 layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer 160 if (s_wasFloating && isFloating()) 161 setChildNeedsLayout(); 162 if (hadTransform) 163 setNeedsLayoutAndPrefWidthsRecalc(); 164 } 165 166 if (layer()) { 167 layer()->styleChanged(diff, oldStyle); 168 if (hadLayer && layer()->isSelfPaintingLayer() != layerWasSelfPainting) 169 setChildNeedsLayout(); 170 } 171 172 if (FrameView *frameView = view()->frameView()) { 173 bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosition(); 174 bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportConstrainedPosition(); 175 if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) { 176 if (newStyleIsViewportConstained && layer()) 177 frameView->addViewportConstrainedObject(this); 178 else 179 frameView->removeViewportConstrainedObject(this); 180 } 181 } 182 } 183 184 void RenderLayerModelObject::addLayerHitTestRects(LayerHitTestRects& rects, const RenderLayer* currentLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) const 185 { 186 if (hasLayer()) { 187 if (isRenderView()) { 188 // RenderView is handled with a special fast-path, but it needs to know the current layer. 189 RenderObject::addLayerHitTestRects(rects, layer(), LayoutPoint(), LayoutRect()); 190 } else { 191 // Since a RenderObject never lives outside it's container RenderLayer, we can switch 192 // to marking entire layers instead. This may sometimes mark more than necessary (when 193 // a layer is made of disjoint objects) but in practice is a significant performance 194 // savings. 195 layer()->addLayerHitTestRects(rects); 196 } 197 } else { 198 RenderObject::addLayerHitTestRects(rects, currentLayer, layerOffset, containerRect); 199 } 200 } 201 202 CompositedLayerMappingPtr RenderLayerModelObject::compositedLayerMapping() const 203 { 204 return m_layer ? m_layer->compositedLayerMapping() : 0; 205 } 206 207 bool RenderLayerModelObject::hasCompositedLayerMapping() const 208 { 209 return m_layer ? m_layer->hasCompositedLayerMapping() : false; 210 } 211 212 CompositedLayerMapping* RenderLayerModelObject::groupedMapping() const 213 { 214 return m_layer ? m_layer->groupedMapping() : 0; 215 } 216 217 } // namespace WebCore 218 219