/* * Copyright (C) 2003, 2009, 2012 Apple Inc. All rights reserved. * Copyright (C) 2013 Intel Corporation. All rights reserved. * * Portions are Copyright (C) 1998 Netscape Communications Corporation. * * Other contributors: * Robert O'Callahan * David Baron * Christian Biesinger * Randall Jesup * Roland Mainz * Josh Soref * Boris Zbarsky * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Alternatively, the contents of this file may be used under the terms * of either the Mozilla Public License Version 1.1, found at * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html * (the "GPL"), in which case the provisions of the MPL or the GPL are * applicable instead of those above. If you wish to allow use of your * version of this file only under the terms of one of those two * licenses (the MPL or the GPL) and not to allow others to use your * version of this file under the LGPL, indicate your decision by * deletingthe provisions above and replace them with the notice and * other provisions required by the MPL or the GPL, as the case may be. * If you do not delete the provisions above, a recipient may use your * version of this file under any of the LGPL, the MPL or the GPL. */ #ifndef SKY_ENGINE_CORE_RENDERING_RENDERLAYER_H_ #define SKY_ENGINE_CORE_RENDERING_RENDERLAYER_H_ #include "sky/engine/core/rendering/LayerPaintingInfo.h" #include "sky/engine/core/rendering/RenderBox.h" #include "sky/engine/core/rendering/RenderLayerClipper.h" #include "sky/engine/core/rendering/RenderLayerFilterInfo.h" #include "sky/engine/core/rendering/RenderLayerStackingNode.h" #include "sky/engine/core/rendering/RenderLayerStackingNodeIterator.h" #include "sky/engine/public/platform/WebBlendMode.h" #include "sky/engine/wtf/OwnPtr.h" namespace blink { class FilterEffectRenderer; class FilterOperations; class HitTestRequest; class HitTestResult; class HitTestingTransformState; class RenderStyle; class TransformationMatrix; enum BorderRadiusClippingRule { IncludeSelfForBorderRadius, DoNotIncludeSelfForBorderRadius }; enum IncludeSelfOrNot { IncludeSelf, ExcludeSelf }; class RenderLayer { WTF_MAKE_NONCOPYABLE(RenderLayer); public: RenderLayer(RenderBox*, LayerType); ~RenderLayer(); String debugName() const; RenderBox* renderer() const { return m_renderer; } // FIXME(sky): Remove RenderBox* renderBox() const { return m_renderer; } RenderLayer* parent() const { return m_parent; } RenderLayer* previousSibling() const { return m_previous; } RenderLayer* nextSibling() const { return m_next; } RenderLayer* firstChild() const { return m_first; } RenderLayer* lastChild() const { return m_last; } void addChild(RenderLayer* newChild, RenderLayer* beforeChild = 0); RenderLayer* removeChild(RenderLayer*); void removeOnlyThisLayer(); void insertOnlyThisLayer(); void styleChanged(StyleDifference, const RenderStyle* oldStyle); // FIXME: Many people call this function while it has out-of-date information. bool isSelfPaintingLayer() const { return m_isSelfPaintingLayer; } void setLayerType(LayerType layerType) { m_layerType = layerType; } bool isTransparent() const { return renderer()->isTransparent(); } RenderLayer* transparentPaintingAncestor(); void beginTransparencyLayers(GraphicsContext*, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation); const RenderLayer* root() const { const RenderLayer* curr = this; while (curr->parent()) curr = curr->parent(); return curr; } LayoutPoint location() const; IntSize size() const; LayoutRect rect() const { return LayoutRect(location(), size()); } bool isRootLayer() const { return m_isRootLayer; } void updateLayerPositionsAfterLayout(); void updateTransformationMatrix(); RenderLayer* renderingContextRoot(); RenderLayerStackingNode* stackingNode() { return m_stackingNode.get(); } const RenderLayerStackingNode* stackingNode() const { return m_stackingNode.get(); } bool hasBoxDecorationsOrBackground() const; bool hasVisibleBoxDecorations() const; // Returns true if this layer has visible content (ignoring any child layers). bool isVisuallyNonEmpty() const; // True if this layer container renderers that paint. bool hasNonEmptyChildRenderers() const; // Gets the nearest enclosing positioned ancestor layer (also includes // the layer and the root layer). RenderLayer* enclosingPositionedAncestor() const; RenderLayer* enclosingOverflowClipLayer(IncludeSelfOrNot = IncludeSelf) const; const RenderLayer* compositingContainer() const; void convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint&) const; void convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutRect&) const; // Pass offsetFromRoot if known. bool intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot = 0) const; // Bounding box relative to some ancestor layer. Pass offsetFromRoot if known. LayoutRect physicalBoundingBox(const RenderLayer* ancestorLayer, const LayoutPoint* offsetFromRoot = 0) const; LayoutRect physicalBoundingBoxIncludingReflectionAndStackingChildren(const RenderLayer* ancestorLayer, const LayoutPoint& offsetFromRoot) const; // If true, this layer's children are included in its bounds for overlap testing. // We can't rely on the children's positions if this layer has a filter that could have moved the children's pixels around. bool overlapBoundsIncludeChildren() const { return hasFilter() && renderer()->style()->filter().hasFilterThatMovesPixels(); } LayoutRect boundingBoxForCompositing(const RenderLayer* ancestorLayer = 0) const; LayoutSize subpixelAccumulation() const; void setSubpixelAccumulation(const LayoutSize&); bool hasTransform() const { return renderer()->hasTransform(); } // This transform has the transform-origin baked in. TransformationMatrix* transform() const { return m_transform.get(); } // Get the perspective transform, which is applied to transformed sublayers. // Returns true if the layer has a -webkit-perspective. // Note that this transform has the perspective-origin baked in. TransformationMatrix perspectiveTransform() const; FloatPoint perspectiveOrigin() const; bool preserves3D() const { return renderer()->style()->transformStyle3D() == TransformStyle3DPreserve3D; } bool has3DTransform() const { return m_transform && !m_transform->isAffine(); } bool has3DTransformedDescendant() const { return m_has3DTransformedDescendant; } // Both updates the status, and returns true if descendants of this have 3d. bool update3DTransformedDescendantStatus(); // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959 bool shouldPreserve3D() const { return renderer()->style()->transformStyle3D() == TransformStyle3DPreserve3D; } bool hasFilter() const { return renderer()->hasFilter(); } void* operator new(size_t); // Only safe to call from RenderBox::destroyLayer() void operator delete(void*); FilterOperations computeFilterOperations(const RenderStyle*); bool paintsWithFilters() const; bool requiresFullLayerImageForFilters() const; FilterEffectRenderer* filterRenderer() const { RenderLayerFilterInfo* filterInfo = this->filterInfo(); return filterInfo ? filterInfo->renderer() : 0; } RenderLayerFilterInfo* filterInfo() const { return hasFilterInfo() ? RenderLayerFilterInfo::filterInfoForRenderLayer(this) : 0; } RenderLayerFilterInfo* ensureFilterInfo() { return RenderLayerFilterInfo::createFilterInfoForRenderLayerIfNeeded(this); } void removeFilterInfoIfNeeded() { if (hasFilterInfo()) RenderLayerFilterInfo::removeFilterInfoForRenderLayer(this); } bool hasFilterInfo() const { return m_hasFilterInfo; } void setHasFilterInfo(bool hasFilterInfo) { m_hasFilterInfo = hasFilterInfo; } void updateFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle); RenderLayerClipper& clipper() { return m_clipper; } const RenderLayerClipper& clipper() const { return m_clipper; } inline bool isPositionedContainer() const { // FIXME: This is not in sync with containingBlock. RenderBox* layerRenderer = renderer(); return isRootLayer() || layerRenderer->isPositioned() || hasTransform(); } void updateOrRemoveFilterEffectRenderer(); void updateSelfPaintingLayer(); void clipToRect(const LayerPaintingInfo&, GraphicsContext*, const ClipRect&, BorderRadiusClippingRule = IncludeSelfForBorderRadius); void restoreClip(GraphicsContext*, const LayoutRect& paintDirtyRect, const ClipRect&); private: // TODO(ojan): Get rid of this. These are basically layer-tree-only paint phases. enum PaintLayerFlags { PaintContent, }; // Bounding box in the coordinates of this layer. LayoutRect logicalBoundingBox() const; void setAncestorChainHasSelfPaintingLayerDescendant(); void dirtyAncestorChainHasSelfPaintingLayerDescendantStatus(); void setNextSibling(RenderLayer* next) { m_next = next; } void setPreviousSibling(RenderLayer* prev) { m_previous = prev; } void setFirstChild(RenderLayer* first) { m_first = first; } void setLastChild(RenderLayer* last) { m_last = last; } void updateHasSelfPaintingLayerDescendant() const; bool hasSelfPaintingLayerDescendant() const { if (m_hasSelfPaintingLayerDescendantDirty) updateHasSelfPaintingLayerDescendant(); ASSERT(!m_hasSelfPaintingLayerDescendantDirty); return m_hasSelfPaintingLayerDescendant; } LayoutPoint renderBoxLocation() const { return renderer()->location(); } bool shouldBeSelfPaintingLayer() const; // FIXME: We should only create the stacking node if needed. bool requiresStackingNode() const { return true; } void updateStackingNode(); void updateTransform(const RenderStyle* oldStyle, RenderStyle* newStyle); void dirty3DTransformedDescendantStatus(); void updateOrRemoveFilterClients(); LayerType m_layerType; // Self-painting layer is an optimization where we avoid the heavy RenderLayer painting // machinery for a RenderLayer allocated only to handle the overflow clip case. // FIXME(crbug.com/332791): Self-painting layer should be merged into the overflow-only concept. unsigned m_isSelfPaintingLayer : 1; // If have no self-painting descendants, we don't have to walk our children during painting. This can lead to // significant savings, especially if the tree has lots of non-self-painting layers grouped together (e.g. table cells). mutable unsigned m_hasSelfPaintingLayerDescendant : 1; mutable unsigned m_hasSelfPaintingLayerDescendantDirty : 1; const unsigned m_isRootLayer : 1; unsigned m_3DTransformedDescendantStatusDirty : 1; // Set on a stacking context layer that has 3D descendants anywhere // in a preserves3D hierarchy. Hint to do 3D-aware hit testing. unsigned m_has3DTransformedDescendant : 1; unsigned m_hasFilterInfo : 1; RenderBox* m_renderer; RenderLayer* m_parent; RenderLayer* m_previous; RenderLayer* m_next; RenderLayer* m_first; RenderLayer* m_last; OwnPtr m_transform; RenderLayerClipper m_clipper; // FIXME: Lazily allocate? OwnPtr m_stackingNode; LayoutSize m_subpixelAccumulation; // The accumulated subpixel offset of a composited layer's composited bounds compared to absolute coordinates. }; } // namespace blink #ifndef NDEBUG // Outside the WebCore namespace for ease of invocation from gdb. void showLayerTree(const blink::RenderLayer*); void showLayerTree(const blink::RenderObject*); #endif #endif // SKY_ENGINE_CORE_RENDERING_RENDERLAYER_H_