mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
558 lines
28 KiB
C++
558 lines
28 KiB
C++
/*
|
|
* 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 <roc+@cs.cmu.edu>
|
|
* David Baron <dbaron@fas.harvard.edu>
|
|
* Christian Biesinger <cbiesinger@web.de>
|
|
* Randall Jesup <rjesup@wgate.com>
|
|
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
|
|
* Josh Soref <timeless@mac.com>
|
|
* Boris Zbarsky <bzbarsky@mit.edu>
|
|
*
|
|
* 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/RenderLayerScrollableArea.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(RenderLayerModelObject*, LayerType);
|
|
~RenderLayer();
|
|
|
|
String debugName() const;
|
|
|
|
RenderLayerModelObject* renderer() const { return m_renderer; }
|
|
RenderBox* renderBox() const { return m_renderer && m_renderer->isBox() ? toRenderBox(m_renderer) : 0; }
|
|
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; }
|
|
|
|
const RenderLayer* compositingContainer() const;
|
|
|
|
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() || renderer()->hasMask(); }
|
|
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();
|
|
|
|
// Our current relative position offset.
|
|
const LayoutSize offsetForInFlowPosition() const;
|
|
|
|
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;
|
|
|
|
bool usedTransparency() const { return m_usedTransparency; }
|
|
|
|
// Gets the nearest enclosing positioned ancestor layer (also includes
|
|
// the <html> layer and the root layer).
|
|
RenderLayer* enclosingPositionedAncestor() const;
|
|
|
|
RenderLayer* enclosingOverflowClipLayer(IncludeSelfOrNot = IncludeSelf) const;
|
|
|
|
RenderLayer* enclosingFilterLayer(IncludeSelfOrNot = IncludeSelf) const;
|
|
bool hasAncestorWithFilterOutsets() const;
|
|
|
|
bool canUseConvertToLayerCoords() const
|
|
{
|
|
return !renderer()->hasTransform();
|
|
}
|
|
|
|
void convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint&) const;
|
|
void convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutRect&) const;
|
|
|
|
// The two main functions that use the layer system. The paint method
|
|
// paints the layers that intersect the damage rect from back to
|
|
// front. The hitTest method looks for mouse events by walking
|
|
// layers that intersect the point from front to back.
|
|
// paint() assumes that the caller will clip to the bounds of damageRect if necessary.
|
|
void paint(GraphicsContext*, const LayoutRect& damageRect, RenderObject* paintingRoot = 0);
|
|
bool hitTest(const HitTestRequest&, HitTestResult&);
|
|
bool hitTest(const HitTestRequest&, const HitTestLocation&, HitTestResult&);
|
|
void paintOverlayScrollbars(GraphicsContext*, const LayoutRect& damageRect, RenderObject* paintingRoot = 0);
|
|
|
|
// 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;
|
|
|
|
// FIXME: This function is inconsistent as to whether the returned rect has been flipped for writing mode.
|
|
LayoutRect boundingBoxForCompositingOverlapTest() const { return overlapBoundsIncludeChildren() ? boundingBoxForCompositing() : logicalBoundingBox(); }
|
|
|
|
// 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(); }
|
|
|
|
enum CalculateBoundsOptions {
|
|
ApplyBoundsChickenEggHacks,
|
|
DoNotApplyBoundsChickenEggHacks,
|
|
};
|
|
LayoutRect boundingBoxForCompositing(const RenderLayer* ancestorLayer = 0, CalculateBoundsOptions = DoNotApplyBoundsChickenEggHacks) const;
|
|
|
|
LayoutUnit staticInlinePosition() const { return m_staticInlinePosition; }
|
|
LayoutUnit staticBlockPosition() const { return m_staticBlockPosition; }
|
|
|
|
void setStaticInlinePosition(LayoutUnit position) { m_staticInlinePosition = position; }
|
|
void setStaticBlockPosition(LayoutUnit position) { m_staticBlockPosition = position; }
|
|
|
|
LayoutSize subpixelAccumulation() const;
|
|
void setSubpixelAccumulation(const LayoutSize&);
|
|
|
|
bool hasTransform() const { return renderer()->hasTransform(); }
|
|
// Note that this transform has the transform-origin baked in.
|
|
TransformationMatrix* transform() const { return m_transform.get(); }
|
|
// currentTransform computes a transform which takes accelerated animations into account. The
|
|
// resulting transform has transform-origin baked in. If the layer does not have a transform,
|
|
// returns the identity matrix.
|
|
TransformationMatrix currentTransform(RenderStyle::ApplyTransformOrigin = RenderStyle::IncludeTransformOrigin) const;
|
|
TransformationMatrix renderableTransform() const;
|
|
|
|
// 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(); }
|
|
|
|
// 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; }
|
|
|
|
void filterNeedsPaintInvalidation();
|
|
bool hasFilter() const { return renderer()->hasFilter(); }
|
|
|
|
void* operator new(size_t);
|
|
// Only safe to call from RenderLayerModelObject::destroyLayer()
|
|
void operator delete(void*);
|
|
|
|
bool needsCompositedScrolling() const { return m_scrollableArea && m_scrollableArea->needsCompositedScrolling(); }
|
|
|
|
// Computes the position of the given render object in the space of |paintInvalidationContainer|.
|
|
// FIXME: invert the logic to have paint invalidation containers take care of painting objects into them, rather than the reverse.
|
|
// This will allow us to clean up this static method messiness.
|
|
static LayoutPoint positionFromPaintInvalidationContainer(const RenderObject*, const RenderLayerModelObject* paintInvalidationContainer, const PaintInvalidationState* = 0);
|
|
|
|
// Adjusts the given rect (in the coordinate space of the RenderObject) to the coordinate space of |paintInvalidationContainer|'s GraphicsLayer backing.
|
|
static void mapRectToPaintInvalidationBacking(const RenderObject*, const RenderLayerModelObject* paintInvalidationContainer, LayoutRect&, const PaintInvalidationState* = 0);
|
|
|
|
bool paintsWithTransform() const;
|
|
|
|
// Returns true if background phase is painted opaque in the given rect.
|
|
// The query rect is given in local coordinates.
|
|
bool backgroundIsKnownToBeOpaqueInRect(const LayoutRect&) const;
|
|
|
|
bool containsDirtyOverlayScrollbars() const { return m_containsDirtyOverlayScrollbars; }
|
|
void setContainsDirtyOverlayScrollbars(bool dirtyScrollbars) { m_containsDirtyOverlayScrollbars = dirtyScrollbars; }
|
|
|
|
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);
|
|
|
|
Node* enclosingElement() const;
|
|
|
|
bool scrollsWithRespectTo(const RenderLayer*) const;
|
|
|
|
// FIXME: This should probably return a ScrollableArea but a lot of internal methods are mistakenly exposed.
|
|
RenderLayerScrollableArea* scrollableArea() const { return m_scrollableArea.get(); }
|
|
RenderLayerClipper& clipper() { return m_clipper; }
|
|
const RenderLayerClipper& clipper() const { return m_clipper; }
|
|
|
|
inline bool isPositionedContainer() const
|
|
{
|
|
// FIXME: This is not in sync with containingBlock.
|
|
RenderLayerModelObject* layerRenderer = renderer();
|
|
return isRootLayer() || layerRenderer->isPositioned() || hasTransform();
|
|
}
|
|
|
|
bool scrollsOverflow() const;
|
|
|
|
class AncestorDependentCompositingInputs {
|
|
public:
|
|
AncestorDependentCompositingInputs()
|
|
: opacityAncestor(0)
|
|
, transformAncestor(0)
|
|
, filterAncestor(0)
|
|
, clippingContainer(0)
|
|
, ancestorScrollingLayer(0)
|
|
, scrollParent(0)
|
|
, clipParent(0)
|
|
, isUnclippedDescendant(false)
|
|
, hasAncestorWithClipPath(false)
|
|
{ }
|
|
|
|
IntRect clippedAbsoluteBoundingBox;
|
|
const RenderLayer* opacityAncestor;
|
|
const RenderLayer* transformAncestor;
|
|
const RenderLayer* filterAncestor;
|
|
const RenderObject* clippingContainer;
|
|
const RenderLayer* ancestorScrollingLayer;
|
|
|
|
// A scroll parent is a compositor concept. It's only needed in blink
|
|
// because we need to use it as a promotion trigger. A layer has a
|
|
// scroll parent if neither its compositor scrolling ancestor, nor any
|
|
// other layer scrolled by this ancestor, is a stacking ancestor of this
|
|
// layer. Layers with scroll parents must be scrolled with the main
|
|
// scrolling layer by the compositor.
|
|
const RenderLayer* scrollParent;
|
|
|
|
// A clip parent is another compositor concept that has leaked into
|
|
// blink so that it may be used as a promotion trigger. Layers with clip
|
|
// parents escape the clip of a stacking tree ancestor. The compositor
|
|
// needs to know about clip parents in order to circumvent its normal
|
|
// clipping logic.
|
|
const RenderLayer* clipParent;
|
|
|
|
// The "is unclipped descendant" concept is now only being used for one
|
|
// purpose: when traversing the RenderLayers in stacking order, we check
|
|
// if we scroll wrt to these unclipped descendants. We do this to
|
|
// proactively promote in the same way that we do for animated layers.
|
|
// Since we have no idea where scrolled content will scroll to, we just
|
|
// assume that it can overlap the unclipped thing at some point, so we
|
|
// promote. But this is unfortunate. We should be able to inflate the
|
|
// bounds of scrolling content for overlap the same way we're doing for
|
|
// animation and only promote what's necessary. Once we're doing that,
|
|
// we won't need to use the "unclipped" concept for promotion any
|
|
// longer.
|
|
unsigned isUnclippedDescendant : 1;
|
|
unsigned hasAncestorWithClipPath : 1;
|
|
};
|
|
|
|
class DescendantDependentCompositingInputs {
|
|
public:
|
|
DescendantDependentCompositingInputs()
|
|
: hasDescendantWithClipPath(false)
|
|
|
|
{ }
|
|
|
|
unsigned hasDescendantWithClipPath : 1;
|
|
};
|
|
|
|
bool childNeedsCompositingInputsUpdate() const { return m_childNeedsCompositingInputsUpdate; }
|
|
bool needsCompositingInputsUpdate() const
|
|
{
|
|
// While we're updating the compositing inputs, these values may differ.
|
|
// We should never be asking for this value when that is the case.
|
|
ASSERT(m_needsDescendantDependentCompositingInputsUpdate == m_needsAncestorDependentCompositingInputsUpdate);
|
|
return m_needsDescendantDependentCompositingInputsUpdate;
|
|
}
|
|
|
|
void updateAncestorDependentCompositingInputs(const AncestorDependentCompositingInputs&);
|
|
void updateDescendantDependentCompositingInputs(const DescendantDependentCompositingInputs&);
|
|
|
|
const AncestorDependentCompositingInputs& ancestorDependentCompositingInputs() const { ASSERT(!m_needsAncestorDependentCompositingInputsUpdate); return m_ancestorDependentCompositingInputs; }
|
|
const DescendantDependentCompositingInputs& descendantDependentCompositingInputs() const { ASSERT(!m_needsDescendantDependentCompositingInputsUpdate); return m_descendantDependentCompositingInputs; }
|
|
|
|
IntRect clippedAbsoluteBoundingBox() const { return ancestorDependentCompositingInputs().clippedAbsoluteBoundingBox; }
|
|
const RenderLayer* opacityAncestor() const { return ancestorDependentCompositingInputs().opacityAncestor; }
|
|
const RenderLayer* transformAncestor() const { return ancestorDependentCompositingInputs().transformAncestor; }
|
|
const RenderLayer* filterAncestor() const { return ancestorDependentCompositingInputs().filterAncestor; }
|
|
const RenderObject* clippingContainer() const { return ancestorDependentCompositingInputs().clippingContainer; }
|
|
const RenderLayer* ancestorScrollingLayer() const { return ancestorDependentCompositingInputs().ancestorScrollingLayer; }
|
|
RenderLayer* scrollParent() const { return const_cast<RenderLayer*>(ancestorDependentCompositingInputs().scrollParent); }
|
|
RenderLayer* clipParent() const { return const_cast<RenderLayer*>(ancestorDependentCompositingInputs().clipParent); }
|
|
bool isUnclippedDescendant() const { return ancestorDependentCompositingInputs().isUnclippedDescendant; }
|
|
bool hasAncestorWithClipPath() const { return ancestorDependentCompositingInputs().hasAncestorWithClipPath; }
|
|
bool hasDescendantWithClipPath() const { return descendantDependentCompositingInputs().hasDescendantWithClipPath; }
|
|
|
|
bool lostGroupedMapping() const { return m_lostGroupedMapping; }
|
|
void setLostGroupedMapping(bool b) { m_lostGroupedMapping = b; }
|
|
|
|
bool hasCompositingDescendant() const { return m_hasCompositingDescendant; }
|
|
void setHasCompositingDescendant(bool);
|
|
|
|
void updateOrRemoveFilterEffectRenderer();
|
|
|
|
void updateSelfPaintingLayer();
|
|
|
|
RenderLayer* enclosingTransformedAncestor() const;
|
|
LayoutPoint computeOffsetFromTransformedAncestor() const;
|
|
|
|
void didUpdateNeedsCompositedScrolling();
|
|
|
|
private:
|
|
// TODO(ojan): Get rid of this. These are basically layer-tree-only paint phases.
|
|
enum PaintLayerFlags {
|
|
PaintContent,
|
|
PaintOverlayScrollbars,
|
|
};
|
|
|
|
// Bounding box in the coordinates of this layer.
|
|
LayoutRect logicalBoundingBox() const;
|
|
|
|
bool hasOverflowControls() const;
|
|
|
|
void setAncestorChainHasSelfPaintingLayerDescendant();
|
|
void dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
|
|
|
|
void clipToRect(const LayerPaintingInfo&, GraphicsContext*, const ClipRect&, BorderRadiusClippingRule = IncludeSelfForBorderRadius);
|
|
void restoreClip(GraphicsContext*, const LayoutRect& paintDirtyRect, const ClipRect&);
|
|
|
|
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()->isBox() ? toRenderBox(renderer())->location() : LayoutPoint(); }
|
|
|
|
// paintLayer() assumes that the caller will clip to the bounds of the painting dirty if necessary.
|
|
void paintLayer(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
|
|
|
|
// paintLayerContents() assumes that the caller will clip to the bounds of the painting dirty rect if necessary.
|
|
void paintLayerContents(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
|
|
|
|
void paintLayerByApplyingTransform(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags, const LayoutPoint& translationOffset = LayoutPoint());
|
|
|
|
void paintChildren(unsigned childrenToVisit, GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
|
|
|
|
void paintBackground(GraphicsContext*, GraphicsContext* transparencyLayerContext,
|
|
const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo&, RenderObject* paintingRootForRenderer,
|
|
LayoutPoint& layerLocation, ClipRect& layerBackgroundRect);
|
|
void paintForeground(GraphicsContext*, GraphicsContext* transparencyLayerContext,
|
|
const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo&, RenderObject* paintingRootForRenderer,
|
|
LayoutPoint& layerLocation, ClipRect& layerForegroundRect);
|
|
void paintForegroundWithPhase(PaintPhase, GraphicsContext*, const LayerPaintingInfo&, RenderObject* paintingRootForRenderer,
|
|
LayoutPoint& layerLocation, ClipRect& layerForegroundRect);
|
|
void paintOutline(GraphicsContext*, const LayerPaintingInfo&, RenderObject* paintingRootForRenderer,
|
|
LayoutPoint& layerLocation, ClipRect& layerOutlineRect);
|
|
void paintOverflowControls(GraphicsContext*, const LayerPaintingInfo&,
|
|
LayoutPoint& layerLocation, ClipRect& layerBackgroundRect);
|
|
void paintMask(GraphicsContext*, const LayerPaintingInfo&, RenderObject* paintingRootForRenderer,
|
|
LayoutPoint& layerLocation, ClipRect& layerBackgroundRect);
|
|
|
|
RenderLayer* hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
|
|
const LayoutRect& hitTestRect, const HitTestLocation&, bool appliedTransform,
|
|
const HitTestingTransformState* transformState = 0, double* zOffset = 0);
|
|
RenderLayer* hitTestLayerByApplyingTransform(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest&, HitTestResult&,
|
|
const LayoutRect& hitTestRect, const HitTestLocation&, const HitTestingTransformState* = 0, double* zOffset = 0,
|
|
const LayoutPoint& translationOffset = LayoutPoint());
|
|
RenderLayer* hitTestChildren(ChildrenIteration, RenderLayer* rootLayer, const HitTestRequest&, HitTestResult&,
|
|
const LayoutRect& hitTestRect, const HitTestLocation&,
|
|
const HitTestingTransformState* transformState, double* zOffsetForDescendants, double* zOffset,
|
|
const HitTestingTransformState* unflattenedTransformState, bool depthSortDescendants);
|
|
|
|
PassRefPtr<HitTestingTransformState> createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer,
|
|
const LayoutRect& hitTestRect, const HitTestLocation&,
|
|
const HitTestingTransformState* containerTransformState,
|
|
const LayoutPoint& translationOffset = LayoutPoint()) const;
|
|
|
|
bool hitTestContents(const HitTestRequest&, HitTestResult&, const LayoutRect& layerBounds, const HitTestLocation&, HitTestFilter) const;
|
|
|
|
bool childBackgroundIsKnownToBeOpaqueInRect(const LayoutRect&) const;
|
|
|
|
bool shouldBeSelfPaintingLayer() const;
|
|
|
|
// FIXME: We should only create the stacking node if needed.
|
|
bool requiresStackingNode() const { return true; }
|
|
void updateStackingNode();
|
|
|
|
// FIXME: We could lazily allocate our ScrollableArea based on style properties ('overflow', ...)
|
|
// but for now, we are always allocating it for RenderBox as it's safer.
|
|
bool requiresScrollableArea() const { return renderBox(); }
|
|
void updateScrollableArea();
|
|
|
|
void updateTransform(const RenderStyle* oldStyle, RenderStyle* newStyle);
|
|
|
|
void dirty3DTransformedDescendantStatus();
|
|
// Both updates the status, and returns true if descendants of this have 3d.
|
|
bool update3DTransformedDescendantStatus();
|
|
|
|
void updateOrRemoveFilterClients();
|
|
|
|
LayoutRect paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation);
|
|
|
|
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_usedTransparency : 1; // Tracks whether we need to close a transparent layer, i.e., whether
|
|
// we ended up painting this layer or any descendants (and therefore need to
|
|
// blend).
|
|
|
|
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_containsDirtyOverlayScrollbars : 1;
|
|
|
|
unsigned m_hasFilterInfo : 1;
|
|
unsigned m_needsAncestorDependentCompositingInputsUpdate : 1;
|
|
unsigned m_needsDescendantDependentCompositingInputsUpdate : 1;
|
|
unsigned m_childNeedsCompositingInputsUpdate : 1;
|
|
|
|
// Used only while determining what layers should be composited. Applies to the tree of z-order lists.
|
|
unsigned m_hasCompositingDescendant : 1;
|
|
|
|
// True if this render layer just lost its grouped mapping due to the CompositedLayerMapping being destroyed,
|
|
// and we don't yet know to what graphics layer this RenderLayer will be assigned.
|
|
unsigned m_lostGroupedMapping : 1;
|
|
|
|
RenderLayerModelObject* m_renderer;
|
|
|
|
RenderLayer* m_parent;
|
|
RenderLayer* m_previous;
|
|
RenderLayer* m_next;
|
|
RenderLayer* m_first;
|
|
RenderLayer* m_last;
|
|
|
|
// Cached normal flow values for absolute positioned elements with static left/top values.
|
|
LayoutUnit m_staticInlinePosition;
|
|
LayoutUnit m_staticBlockPosition;
|
|
|
|
OwnPtr<TransformationMatrix> m_transform;
|
|
|
|
DescendantDependentCompositingInputs m_descendantDependentCompositingInputs;
|
|
AncestorDependentCompositingInputs m_ancestorDependentCompositingInputs;
|
|
|
|
OwnPtr<RenderLayerScrollableArea> m_scrollableArea;
|
|
|
|
RenderLayerClipper m_clipper; // FIXME: Lazily allocate?
|
|
OwnPtr<RenderLayerStackingNode> 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_
|