Home | History | Annotate | Download | only in rendering
      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