| Index: third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
|
| diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
|
| index 76989710eff9a59504b15dbd6a61fbaf23455f2c..0ea39143ab8bc1eb315f76a4c60f5f2803cd496e 100644
|
| --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
|
| +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
|
| @@ -24,7 +24,7 @@ void PaintPropertyTreeBuilder::buildTreeRootNodes(FrameView& rootFrame, PaintPro
|
| if (!rootFrame.rootTransform() || rootFrame.rootTransform()->parent()) {
|
| rootFrame.setRootTransform(TransformPaintPropertyNode::create(TransformationMatrix(), FloatPoint3D(), nullptr));
|
| rootFrame.setRootClip(ClipPaintPropertyNode::create(rootFrame.rootTransform(), FloatRoundedRect(LayoutRect::infiniteIntRect()), nullptr));
|
| - rootFrame.setRootEffect(EffectPaintPropertyNode::create(1.0, nullptr));
|
| + rootFrame.setRootEffect(EffectPaintPropertyNode::create(1.0f, nullptr));
|
| } else {
|
| DCHECK(rootFrame.rootClip() && !rootFrame.rootClip()->parent());
|
| DCHECK(rootFrame.rootEffect() && !rootFrame.rootEffect()->parent());
|
| @@ -72,12 +72,13 @@ template <
|
| typename PropertyNode,
|
| PropertyNode* (ObjectPaintProperties::*Getter)() const,
|
| void (ObjectPaintProperties::*Setter)(PassRefPtr<PropertyNode>),
|
| - bool (*ComputeProperty)(const LayoutObject&, PaintPropertyTreeBuilderContext&, typename PropertyNode::Value&)>
|
| + PaintPropertyTreeBuilder::PaintPropertyNodeType (*ComputeProperty)(const LayoutObject&, PaintPropertyTreeBuilderContext&, typename PropertyNode::Value&)>
|
| PropertyNode* PaintPropertyTreeBuilder::updateObjectPaintProperty(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, PropertyNode*& contextProperty)
|
| {
|
| ObjectPaintProperties* previousProperties = object.objectPaintProperties();
|
| typename PropertyNode::Value newPropertyValue;
|
| - if (!ComputeProperty(object, context, newPropertyValue)) {
|
| + PaintPropertyNodeType nodeType = ComputeProperty(object, context, newPropertyValue);
|
| + if (nodeType == NoNode) {
|
| if (previousProperties)
|
| (previousProperties->*Setter)(nullptr);
|
| return nullptr;
|
| @@ -87,27 +88,71 @@ PropertyNode* PaintPropertyTreeBuilder::updateObjectPaintProperty(const LayoutOb
|
| if (previousPropertyNode && previousPropertyNode->value() == newPropertyValue) {
|
| previousPropertyNode->setParent(contextProperty);
|
| contextProperty = previousPropertyNode;
|
| - return previousPropertyNode;
|
| + } else {
|
| + RefPtr<PropertyNode> newPropertyNode = PropertyNode::create(newPropertyValue, contextProperty);
|
| + contextProperty = newPropertyNode.get();
|
| + (object.getMutableForPainting().ensureObjectPaintProperties().*Setter)(newPropertyNode.release());
|
| }
|
|
|
| - RefPtr<PropertyNode> newPropertyNode = PropertyNode::create(newPropertyValue, contextProperty);
|
| - contextProperty = newPropertyNode.get();
|
| - (object.getMutableForPainting().ensureObjectPaintProperties().*Setter)(newPropertyNode.release());
|
| + if (nodeType == IsolationNode)
|
| + contextProperty->setIsIsolationNode();
|
| return contextProperty;
|
| }
|
|
|
| -bool PaintPropertyTreeBuilder::computePaintOffsetTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value)
|
| +// We treat out-of-flow positioned objects and stacking context objects as "paint property isolation
|
| +// boundaries". That is, we will create a no-op property nodes if needed that serve as the isolated
|
| +// roots of the paint property subtrees, to ensure that there is no paint property parent references
|
| +// from descendants to ancestors crossing the isolated boundaries. When a whole stacking context is
|
| +// unchanged in the current document cycle, no property node in the subtree will need update.
|
| +//
|
| +// An exception of the above no-reference-crossing-isolation-boundaries rule is for references from a
|
| +// descendant which is a isolation boundary, e.g. from nodes for an out-of-flow positioned object to
|
| +// nodes for the container or ancestor of the container of the out-of-flow positioned object, crossing
|
| +// stacking contexts (isolation boundaries) which are are not the containers of the out-of-flow
|
| +// positioned object. For example, in
|
| +//
|
| +// <div id="transform" style="transform: translate(10px, 10px)">
|
| +// <div id="opacity" style="opacity: 0.5">
|
| +// <div id="absolute" style="position: absolute"></div>
|
| +// <div>
|
| +// </div>
|
| +//
|
| +// the property nodes for 'absolute' can directly reference nodes of 'transform', crossing 'opacity'
|
| +// which is a stacking context and isolation boundary.
|
| +//
|
| +// The exception avoids the necessity to create multiple no-op property nodes for normal descendants
|
| +// and out-of-flow positioned descendants in different tree paths.
|
| +static bool isPaintPropertyIsolationBoundary(const LayoutObject& object)
|
| +{
|
| + return
|
| + // This condition excludes objects that have stacking-context style but don't actually
|
| + // create stacking contexts (e.g. SVG objects having opacity).
|
| + object.hasLayer()
|
| + // For now we already have property isolation for LayoutView by FrameView paint properties.
|
| + // TODO(wangxianzhu): Revisit this for root-layer-scrolls.
|
| + && !object.isLayoutView()
|
| + && (object.isOutOfFlowPositioned() || object.styleRef().isStackingContext());
|
| +}
|
| +
|
| +PaintPropertyTreeBuilder::PaintPropertyNodeType PaintPropertyTreeBuilder::computePaintOffsetTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value)
|
| {
|
| if (!object.isBoxModelObject())
|
| - return false;
|
| + return NoNode;
|
|
|
| // TODO(trchen): Eliminate PaintLayer dependency.
|
| PaintLayer* layer = toLayoutBoxModelObject(object).layer();
|
| - if (!layer || !layer->paintsWithTransform(GlobalPaintNormalPhase))
|
| - return false;
|
| -
|
| - if (context.current.paintOffset == LayoutPoint())
|
| - return false;
|
| + if (!layer)
|
| + return NoNode;
|
| +
|
| + if (context.current.paintOffset == LayoutPoint() || !layer->paintsWithTransform(GlobalPaintNormalPhase)) {
|
| + if (isPaintPropertyIsolationBoundary(object)) {
|
| + // Will create a no-op paintOffsetTranslation node, if the object is a isolation boundary
|
| + // and it won't create other transform nodes.
|
| + if (!object.styleRef().hasTransform() && !object.styleRef().hasPerspective())
|
| + return IsolationNode;
|
| + }
|
| + return NoNode;
|
| + }
|
|
|
| // We should use the same subpixel paint offset values for snapping regardless of whether a
|
| // transform is present. If there is a transform we round the paint offset but keep around
|
| @@ -119,7 +164,7 @@ bool PaintPropertyTreeBuilder::computePaintOffsetTranslation(const LayoutObject&
|
|
|
| value.matrix.translate(roundedPaintOffset.x(), roundedPaintOffset.y());
|
| context.current.paintOffset = fractionalPaintOffset;
|
| - return true;
|
| + return NormalNode;
|
| }
|
|
|
| void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
|
| @@ -141,7 +186,7 @@ static FloatPoint3D transformOrigin(const LayoutBox& box)
|
| style.transformOriginZ());
|
| }
|
|
|
| -bool PaintPropertyTreeBuilder::computeTransform(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value)
|
| +PaintPropertyTreeBuilder::PaintPropertyNodeType PaintPropertyTreeBuilder::computeTransform(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value)
|
| {
|
| if (object.isSVG() && !object.isSVGRoot()) {
|
| // SVG does not use paint offset internally.
|
| @@ -153,21 +198,21 @@ bool PaintPropertyTreeBuilder::computeTransform(const LayoutObject& object, Pain
|
| // FIXME(pdr): Refactor this so all non-root SVG objects use the same transform function.
|
| const AffineTransform& transform = object.isSVGForeignObject() ? object.localSVGTransform() : object.localToSVGParentTransform();
|
| if (transform.isIdentity())
|
| - return false;
|
| + return NoNode;
|
|
|
| value.matrix = transform;
|
| // The origin is included in the local transform, so leave origin empty.
|
| - return true;
|
| + return NormalNode;
|
| }
|
|
|
| const ComputedStyle& style = object.styleRef();
|
| if (!object.isBox() || !style.hasTransform())
|
| - return false;
|
| + return NoNode;
|
|
|
| style.applyTransform(value.matrix, toLayoutBox(object).size(), ComputedStyle::ExcludeTransformOrigin,
|
| ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTransformProperties);
|
| value.origin = transformOrigin(toLayoutBox(object));
|
| - return true;
|
| + return NormalNode;
|
| }
|
|
|
| void PaintPropertyTreeBuilder::updateTransform(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
|
| @@ -179,13 +224,19 @@ void PaintPropertyTreeBuilder::updateTransform(const LayoutObject& object, Paint
|
| &computeTransform>(object, context, context.current.transform);
|
| }
|
|
|
| -bool PaintPropertyTreeBuilder::computeEffect(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, EffectPaintPropertyNode::Value& value)
|
| +PaintPropertyTreeBuilder::PaintPropertyNodeType PaintPropertyTreeBuilder::computeEffect(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, EffectPaintPropertyNode::Value& value)
|
| {
|
| - if (!object.styleRef().hasOpacity())
|
| - return false;
|
| + if (!object.styleRef().hasOpacity()) {
|
| + if (isPaintPropertyIsolationBoundary(object)) {
|
| + // Will create a no-op effect node if the object is a isolation boundary.
|
| + value = 1.0f;
|
| + return IsolationNode;
|
| + }
|
| + return NoNode;
|
| + }
|
|
|
| value = object.styleRef().opacity();
|
| - return true;
|
| + return NormalNode;
|
| }
|
|
|
| void PaintPropertyTreeBuilder::updateEffect(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
|
| @@ -197,10 +248,11 @@ void PaintPropertyTreeBuilder::updateEffect(const LayoutObject& object, PaintPro
|
| &computeEffect>(object, context, context.currentEffect);
|
| }
|
|
|
| -bool PaintPropertyTreeBuilder::computeCssClip(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, ClipPaintPropertyNode::Value& value)
|
| +PaintPropertyTreeBuilder::PaintPropertyNodeType PaintPropertyTreeBuilder::computeCssClip(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, ClipPaintPropertyNode::Value& value)
|
| {
|
| if (!object.hasClip())
|
| - return false;
|
| + return NoNode;
|
| +
|
| DCHECK(object.canContainAbsolutePositionObjects());
|
|
|
| // Create clip node for descendants that are not fixed position.
|
| @@ -209,7 +261,7 @@ bool PaintPropertyTreeBuilder::computeCssClip(const LayoutObject& object, PaintP
|
| // at updateOutOfFlowContext() step.
|
| LayoutRect clipRect = toLayoutBox(object).clipRect(context.current.paintOffset);
|
| value = FloatRoundedRect(FloatRect(clipRect));
|
| - return true;
|
| + return NormalNode;
|
| }
|
|
|
| void PaintPropertyTreeBuilder::updateCssClip(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
|
| @@ -236,22 +288,22 @@ void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(const LayoutObject& o
|
| }
|
|
|
| // TODO(trchen): Remove this once we bake the paint offset into frameRect.
|
| -bool PaintPropertyTreeBuilder::computeScrollbarPaintOffset(const LayoutObject& object, const PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value)
|
| +PaintPropertyTreeBuilder::PaintPropertyNodeType PaintPropertyTreeBuilder::computeScrollbarPaintOffset(const LayoutObject& object, const PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value)
|
| {
|
| IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset);
|
| if (roundedPaintOffset == IntPoint())
|
| - return false;
|
| + return NoNode;
|
|
|
| if (!object.isBoxModelObject())
|
| - return false;
|
| + return NoNode;
|
| PaintLayerScrollableArea* scrollableArea = toLayoutBoxModelObject(object).getScrollableArea();
|
| if (!scrollableArea)
|
| - return false;
|
| + return NoNode;
|
| if (!scrollableArea->horizontalScrollbar() && !scrollableArea->verticalScrollbar())
|
| - return false;
|
| + return NoNode;
|
|
|
| value.matrix.translate(roundedPaintOffset.x(), roundedPaintOffset.y());
|
| - return true;
|
| + return NormalNode;
|
| }
|
|
|
| // TODO(trchen): Remove this once we bake the paint offset into frameRect.
|
| @@ -277,39 +329,47 @@ void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(const LayoutObject& ob
|
| TransformPaintPropertyNode::create(paintOffset, context.current.transform));
|
| }
|
|
|
| -bool PaintPropertyTreeBuilder::computeOverflowClip(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, ClipPaintPropertyNode::Value& value)
|
| +PaintPropertyTreeBuilder::PaintPropertyNodeType PaintPropertyTreeBuilder::computeOverflowClip(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, ClipPaintPropertyNode::Value& value)
|
| {
|
| - const LayoutBox& box = toLayoutBox(object);
|
| -
|
| - // The <input> elements can't have contents thus CSS overflow property doesn't apply.
|
| - // However for layout purposes we do generate child layout objects for them, e.g. button label.
|
| - // We should clip the overflow from those children. This is called control clip and we
|
| - // technically treat them like overflow clip.
|
| - LayoutRect clipRect;
|
| - if (box.hasControlClip())
|
| - clipRect = box.controlClipRect(context.current.paintOffset);
|
| - else if (box.hasOverflowClip())
|
| - clipRect = box.overflowClipRect(context.current.paintOffset);
|
| - else
|
| - return false;
|
| + if (object.isBox()) {
|
| + const LayoutBox& box = toLayoutBox(object);
|
| + // The <input> elements can't have contents thus CSS overflow property doesn't apply.
|
| + // However for layout purposes we do generate child layout objects for them, e.g. button label.
|
| + // We should clip the overflow from those children. This is called control clip and we
|
| + // technically treat them like overflow clip.
|
| + if (box.hasControlClip()) {
|
| + value = FloatRoundedRect(FloatRect(box.controlClipRect(context.current.paintOffset)));
|
| + return NormalNode;
|
| + }
|
| + if (box.hasOverflowClip()) {
|
| + value = FloatRoundedRect(FloatRect(box.overflowClipRect(context.current.paintOffset)));
|
| + return NormalNode;
|
| + }
|
| + }
|
|
|
| - value = FloatRoundedRect(FloatRect(clipRect));
|
| - return true;
|
| + if (isPaintPropertyIsolationBoundary(object)) {
|
| + // Will create a no-op overflowClip node, if the object is an isolation boundary
|
| + // and it hasn't create a cssClip node.
|
| + if (!object.hasClip()) {
|
| + value = FloatRoundedRect(LayoutRect::infiniteIntRect());
|
| + return IsolationNode;
|
| + }
|
| + }
|
| + return NoNode;
|
| }
|
|
|
| void PaintPropertyTreeBuilder::updateOverflowClip(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
|
| {
|
| - if (!object.isBox())
|
| - return;
|
| - const LayoutBox& box = toLayoutBox(object);
|
| -
|
| // This need to be in top-level block to hold the reference until we finish creating the normal clip node.
|
| RefPtr<ClipPaintPropertyNode> borderRadiusClip;
|
| - if ((box.hasControlClip() || box.hasOverflowClip()) && box.styleRef().hasBorderRadius()) {
|
| - auto innerBorder = box.styleRef().getRoundedInnerBorderFor(
|
| - LayoutRect(context.current.paintOffset, box.size()));
|
| - borderRadiusClip = ClipPaintPropertyNode::create(context.current.transform, innerBorder, context.current.clip);
|
| - context.current.clip = borderRadiusClip.get();
|
| + if (object.isBox()) {
|
| + const LayoutBox& box = toLayoutBox(object);
|
| + if ((box.hasControlClip() || box.hasOverflowClip()) && box.styleRef().hasBorderRadius()) {
|
| + auto innerBorder = box.styleRef().getRoundedInnerBorderFor(
|
| + LayoutRect(context.current.paintOffset, box.size()));
|
| + borderRadiusClip = ClipPaintPropertyNode::create(context.current.transform, innerBorder, context.current.clip);
|
| + context.current.clip = borderRadiusClip.get();
|
| + }
|
| }
|
|
|
| if (ClipPaintPropertyNode* node = updateObjectPaintProperty<
|
| @@ -329,15 +389,15 @@ static FloatPoint perspectiveOrigin(const LayoutBox& box)
|
| floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height()));
|
| }
|
|
|
| -bool PaintPropertyTreeBuilder::computePerspective(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value)
|
| +PaintPropertyTreeBuilder::PaintPropertyNodeType PaintPropertyTreeBuilder::computePerspective(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value)
|
| {
|
| const ComputedStyle& style = object.styleRef();
|
| if (!object.isBox() || !style.hasPerspective())
|
| - return false;
|
| + return NoNode;
|
|
|
| value.matrix.applyPerspective(style.perspective());
|
| value.origin = perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.current.paintOffset);
|
| - return true;
|
| + return NormalNode;
|
| }
|
|
|
| void PaintPropertyTreeBuilder::updatePerspective(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
|
| @@ -349,10 +409,10 @@ void PaintPropertyTreeBuilder::updatePerspective(const LayoutObject& object, Pai
|
| &computePerspective>(object, context, context.current.transform);
|
| }
|
|
|
| -bool PaintPropertyTreeBuilder::computeSvgLocalToBorderBoxTransform(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value)
|
| +PaintPropertyTreeBuilder::PaintPropertyNodeType PaintPropertyTreeBuilder::computeSvgLocalToBorderBoxTransform(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value)
|
| {
|
| if (!object.isSVGRoot())
|
| - return false;
|
| + return NoNode;
|
|
|
| AffineTransform transformToBorderBox = SVGRootPainter(toLayoutSVGRoot(object)).transformToPixelSnappedBorderBox(context.current.paintOffset);
|
|
|
| @@ -361,11 +421,11 @@ bool PaintPropertyTreeBuilder::computeSvgLocalToBorderBoxTransform(const LayoutO
|
| context.current.paintOffset = LayoutPoint();
|
|
|
| if (transformToBorderBox.isIdentity())
|
| - return false;
|
| + return NoNode;
|
|
|
| value.matrix = transformToBorderBox;
|
| context.current.paintOffset = LayoutPoint();
|
| - return true;
|
| + return NormalNode;
|
| }
|
|
|
| void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
|
| @@ -377,19 +437,19 @@ void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(const LayoutOb
|
| &computeSvgLocalToBorderBoxTransform>(object, context, context.current.transform);
|
| }
|
|
|
| -bool PaintPropertyTreeBuilder::computeScrollTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value)
|
| +PaintPropertyTreeBuilder::PaintPropertyNodeType PaintPropertyTreeBuilder::computeScrollTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value)
|
| {
|
| if (!object.isBoxModelObject() || !object.hasOverflowClip())
|
| - return false;
|
| + return NoNode;
|
|
|
| PaintLayer* layer = toLayoutBoxModelObject(object).layer();
|
| ASSERT(layer);
|
| DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset();
|
| if (scrollOffset.isZero() && !layer->scrollsOverflow())
|
| - return false;
|
| + return NoNode;
|
|
|
| value.matrix.translate(-scrollOffset.width(), -scrollOffset.height());
|
| - return true;
|
| + return NormalNode;
|
| }
|
|
|
| void PaintPropertyTreeBuilder::updateScrollTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
|
| @@ -402,7 +462,7 @@ void PaintPropertyTreeBuilder::updateScrollTranslation(const LayoutObject& objec
|
| }
|
|
|
| // Returns true if we need to create a cssClip node for fixed position.
|
| -bool PaintPropertyTreeBuilder::computeOutOfFlowContext(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, ClipPaintPropertyNode::Value& value)
|
| +PaintPropertyTreeBuilder::PaintPropertyNodeType PaintPropertyTreeBuilder::computeOutOfFlowContext(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, ClipPaintPropertyNode::Value& value)
|
| {
|
| if (object.canContainAbsolutePositionObjects()) {
|
| context.absolutePosition = context.current;
|
| @@ -413,11 +473,11 @@ bool PaintPropertyTreeBuilder::computeOutOfFlowContext(const LayoutObject& objec
|
| // paint properties for rootLayerScrolls.
|
| if (!object.isLayoutView() && object.canContainFixedPositionObjects()) {
|
| context.fixedPosition = context.current;
|
| - return false;
|
| + return NoNode;
|
| }
|
|
|
| if (!object.objectPaintProperties() || !object.objectPaintProperties()->cssClip())
|
| - return false;
|
| + return NoNode;
|
|
|
| // CSS clip applies to all descendants, even if this object is not a containing block
|
| // ancestor of the descendant. It is okay for absolute-position descendants because
|
| @@ -430,11 +490,11 @@ bool PaintPropertyTreeBuilder::computeOutOfFlowContext(const LayoutObject& objec
|
| // context has exactly the same clip. Reuse if possible.
|
| if (context.fixedPosition.clip == cssClip->parent()) {
|
| context.fixedPosition.clip = cssClip;
|
| - return false;
|
| + return NoNode;
|
| }
|
|
|
| value = cssClip->clipRect();
|
| - return true;
|
| + return NormalNode;
|
| }
|
|
|
| void PaintPropertyTreeBuilder::updateOutOfFlowContext(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
|
| @@ -496,6 +556,20 @@ static void deriveBorderBoxFromContainerContext(const LayoutObject& object, Pain
|
| }
|
| }
|
|
|
| +#if DCHECK_IS_ON()
|
| +void PaintPropertyTreeBuilder::checkPropertyIsolationBoundaryForStackingContext(const LayoutObject& object)
|
| +{
|
| + if (!isPaintPropertyIsolationBoundary(object))
|
| + return;
|
| +
|
| + ObjectPaintProperties* properties = object.objectPaintProperties();
|
| + DCHECK(properties);
|
| + DCHECK(properties->paintOffsetTranslation() || properties->transform() || properties->perspective());
|
| + DCHECK(properties->effect());
|
| + DCHECK(properties->cssClip() || properties->overflowClip());
|
| +}
|
| +#endif
|
| +
|
| void PaintPropertyTreeBuilder::buildTreeNodes(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
|
| {
|
| if (!object.isBoxModelObject() && !object.isSVG())
|
| @@ -516,6 +590,9 @@ void PaintPropertyTreeBuilder::buildTreeNodes(const LayoutObject& object, PaintP
|
| updateSvgLocalToBorderBoxTransform(object, context);
|
| updateScrollTranslation(object, context);
|
| updateOutOfFlowContext(object, context);
|
| +#if DCHECK_IS_ON()
|
| + checkPropertyIsolationBoundaryForStackingContext(object);
|
| +#endif
|
| }
|
|
|
| } // namespace blink
|
|
|