Chromium Code Reviews| 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 1d394cb7cd37438feba099574ccad966af718cfb..76989710eff9a59504b15dbd6a61fbaf23455f2c 100644 |
| --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp |
| +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp |
| @@ -21,17 +21,18 @@ namespace blink { |
| void PaintPropertyTreeBuilder::buildTreeRootNodes(FrameView& rootFrame, PaintPropertyTreeBuilderContext& context) |
| { |
| - RefPtr<TransformPaintPropertyNode> transformRoot = TransformPaintPropertyNode::create(TransformationMatrix(), FloatPoint3D(), nullptr); |
| - context.current.transform = context.absolutePosition.transform = context.fixedPosition.transform = transformRoot.get(); |
| - rootFrame.setRootTransform(std::move(transformRoot)); |
| - |
| - RefPtr<ClipPaintPropertyNode> clipRoot = ClipPaintPropertyNode::create(transformRoot, FloatRoundedRect(LayoutRect::infiniteIntRect()), nullptr); |
| - context.current.clip = context.absolutePosition.clip = context.fixedPosition.clip = clipRoot.get(); |
| - rootFrame.setRootClip(std::move(clipRoot)); |
| + 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)); |
| + } else { |
| + DCHECK(rootFrame.rootClip() && !rootFrame.rootClip()->parent()); |
| + DCHECK(rootFrame.rootEffect() && !rootFrame.rootEffect()->parent()); |
| + } |
| - RefPtr<EffectPaintPropertyNode> effectRoot = EffectPaintPropertyNode::create(1.0, nullptr); |
| - context.currentEffect = effectRoot.get(); |
| - rootFrame.setRootEffect(std::move(effectRoot)); |
| + context.current.transform = context.absolutePosition.transform = context.fixedPosition.transform = rootFrame.rootTransform(); |
| + context.current.clip = context.absolutePosition.clip = context.fixedPosition.clip = rootFrame.rootClip(); |
| + context.currentEffect = rootFrame.rootEffect(); |
| } |
| void PaintPropertyTreeBuilder::buildTreeNodes(FrameView& frameView, PaintPropertyTreeBuilderContext& context) |
| @@ -42,43 +43,71 @@ void PaintPropertyTreeBuilder::buildTreeNodes(FrameView& frameView, PaintPropert |
| TransformationMatrix frameTranslate; |
| frameTranslate.translate(frameView.x() + context.current.paintOffset.x(), frameView.y() + context.current.paintOffset.y()); |
| - RefPtr<TransformPaintPropertyNode> newTransformNodeForPreTranslation = TransformPaintPropertyNode::create(frameTranslate, FloatPoint3D(), context.current.transform); |
| + if (!frameView.preTranslation() || frameView.preTranslation()->matrix() != frameTranslate) |
| + frameView.setPreTranslation(TransformPaintPropertyNode::create(frameTranslate, FloatPoint3D(), context.current.transform)); |
| FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSize())); |
| - RefPtr<ClipPaintPropertyNode> newClipNodeForContentClip = ClipPaintPropertyNode::create(newTransformNodeForPreTranslation.get(), contentClip, context.current.clip); |
| + if (!frameView.contentClip() || frameView.contentClip()->clipRect() != contentClip) |
| + frameView.setContentClip(ClipPaintPropertyNode::create(frameView.preTranslation(), contentClip, context.current.clip)); |
| DoubleSize scrollOffset = frameView.scrollOffsetDouble(); |
| TransformationMatrix frameScroll; |
| frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); |
| - RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = TransformPaintPropertyNode::create(frameScroll, FloatPoint3D(), newTransformNodeForPreTranslation); |
| + if (!frameView.scrollTranslation() || frameView.scrollTranslation()->matrix() != frameScroll) |
| + frameView.setScrollTranslation(TransformPaintPropertyNode::create(frameScroll, FloatPoint3D(), frameView.preTranslation())); |
| // Initialize the context for current, absolute and fixed position cases. |
| // They are the same, except that scroll translation does not apply to |
| // fixed position descendants. |
| - context.current.transform = newTransformNodeForScrollTranslation.get(); |
| + context.current.transform = frameView.scrollTranslation(); |
| context.current.paintOffset = LayoutPoint(); |
| - context.current.clip = newClipNodeForContentClip.get(); |
| + context.current.clip = frameView.contentClip(); |
| context.absolutePosition = context.current; |
| context.containerForAbsolutePosition = nullptr; |
| context.fixedPosition = context.current; |
| - context.fixedPosition.transform = newTransformNodeForPreTranslation.get(); |
| - |
| - frameView.setPreTranslation(newTransformNodeForPreTranslation.release()); |
| - frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release()); |
| - frameView.setContentClip(newClipNodeForContentClip.release()); |
| + context.fixedPosition.transform = frameView.preTranslation(); |
| } |
| -void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +template < |
| + typename PropertyNode, |
| + PropertyNode* (ObjectPaintProperties::*Getter)() const, |
| + void (ObjectPaintProperties::*Setter)(PassRefPtr<PropertyNode>), |
| + bool (*ComputeProperty)(const LayoutObject&, PaintPropertyTreeBuilderContext&, typename PropertyNode::Value&)> |
| +PropertyNode* PaintPropertyTreeBuilder::updateObjectPaintProperty(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, PropertyNode*& contextProperty) |
|
pdr.
2016/07/21 21:34:06
This template approach is very clever. WDYT of thi
Xianzhu
2016/07/22 01:14:05
Many thanks for the sample CL. Mixed your code int
|
| { |
| - if (object.isBoxModelObject()) { |
| - // TODO(trchen): Eliminate PaintLayer dependency. |
| - PaintLayer* layer = toLayoutBoxModelObject(object).layer(); |
| - if (!layer || !layer->paintsWithTransform(GlobalPaintNormalPhase)) |
| - return; |
| + ObjectPaintProperties* previousProperties = object.objectPaintProperties(); |
| + typename PropertyNode::Value newPropertyValue; |
| + if (!ComputeProperty(object, context, newPropertyValue)) { |
| + if (previousProperties) |
| + (previousProperties->*Setter)(nullptr); |
| + return nullptr; |
| + } |
| + |
| + PropertyNode* previousPropertyNode = previousProperties ? (previousProperties->*Getter)() : nullptr; |
| + if (previousPropertyNode && previousPropertyNode->value() == newPropertyValue) { |
| + previousPropertyNode->setParent(contextProperty); |
| + contextProperty = previousPropertyNode; |
| + return previousPropertyNode; |
| } |
| + RefPtr<PropertyNode> newPropertyNode = PropertyNode::create(newPropertyValue, contextProperty); |
| + contextProperty = newPropertyNode.get(); |
| + (object.getMutableForPainting().ensureObjectPaintProperties().*Setter)(newPropertyNode.release()); |
| + return contextProperty; |
| +} |
| + |
| +bool PaintPropertyTreeBuilder::computePaintOffsetTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value) |
| +{ |
| + if (!object.isBoxModelObject()) |
| + return false; |
| + |
| + // TODO(trchen): Eliminate PaintLayer dependency. |
| + PaintLayer* layer = toLayoutBoxModelObject(object).layer(); |
| + if (!layer || !layer->paintsWithTransform(GlobalPaintNormalPhase)) |
| + return false; |
| + |
| if (context.current.paintOffset == LayoutPoint()) |
| - return; |
| + return false; |
| // 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 |
| @@ -88,12 +117,18 @@ void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(const LayoutObject& |
| IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); |
| LayoutPoint fractionalPaintOffset = LayoutPoint(context.current.paintOffset - roundedPaintOffset); |
| - RefPtr<TransformPaintPropertyNode> paintOffsetTranslation = TransformPaintPropertyNode::create( |
| - TransformationMatrix().translate(roundedPaintOffset.x(), roundedPaintOffset.y()), |
| - FloatPoint3D(), context.current.transform); |
| - context.current.transform = paintOffsetTranslation.get(); |
| + value.matrix.translate(roundedPaintOffset.x(), roundedPaintOffset.y()); |
| context.current.paintOffset = fractionalPaintOffset; |
| - object.getMutableForPainting().ensureObjectPaintProperties().setPaintOffsetTranslation(paintOffsetTranslation.release()); |
| + return true; |
| +} |
| + |
| +void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +{ |
| + updateObjectPaintProperty< |
| + TransformPaintPropertyNode, |
| + &ObjectPaintProperties::paintOffsetTranslation, |
| + &ObjectPaintProperties::setPaintOffsetTranslation, |
| + &computePaintOffsetTranslation>(object, context, context.current.transform); |
| } |
| static FloatPoint3D transformOrigin(const LayoutBox& box) |
| @@ -106,7 +141,7 @@ static FloatPoint3D transformOrigin(const LayoutBox& box) |
| style.transformOriginZ()); |
| } |
| -void PaintPropertyTreeBuilder::updateTransform(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +bool PaintPropertyTreeBuilder::computeTransform(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value) |
| { |
| if (object.isSVG() && !object.isSVGRoot()) { |
| // SVG does not use paint offset internally. |
| @@ -118,55 +153,73 @@ void PaintPropertyTreeBuilder::updateTransform(const LayoutObject& object, Paint |
| // 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; |
| + return false; |
| - // The origin is included in the local transform, so use an empty origin. |
| - RefPtr<TransformPaintPropertyNode> svgTransform = TransformPaintPropertyNode::create( |
| - transform, FloatPoint3D(0, 0, 0), context.current.transform); |
| - context.current.transform = svgTransform.get(); |
| - object.getMutableForPainting().ensureObjectPaintProperties().setTransform(svgTransform.release()); |
| - return; |
| + value.matrix = transform; |
| + // The origin is included in the local transform, so leave origin empty. |
| + return true; |
| } |
| const ComputedStyle& style = object.styleRef(); |
| if (!object.isBox() || !style.hasTransform()) |
| - return; |
| + return false; |
| - TransformationMatrix matrix; |
| - style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::ExcludeTransformOrigin, |
| + style.applyTransform(value.matrix, toLayoutBox(object).size(), ComputedStyle::ExcludeTransformOrigin, |
| ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTransformProperties); |
| - RefPtr<TransformPaintPropertyNode> transformNode = TransformPaintPropertyNode::create( |
| - matrix, transformOrigin(toLayoutBox(object)), context.current.transform); |
| - context.current.transform = transformNode.get(); |
| - object.getMutableForPainting().ensureObjectPaintProperties().setTransform(transformNode.release()); |
| + value.origin = transformOrigin(toLayoutBox(object)); |
| + return true; |
| } |
| -void PaintPropertyTreeBuilder::updateEffect(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +void PaintPropertyTreeBuilder::updateTransform(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +{ |
| + updateObjectPaintProperty< |
| + TransformPaintPropertyNode, |
| + &ObjectPaintProperties::transform, |
| + &ObjectPaintProperties::setTransform, |
| + &computeTransform>(object, context, context.current.transform); |
| +} |
| + |
| +bool PaintPropertyTreeBuilder::computeEffect(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, EffectPaintPropertyNode::Value& value) |
| { |
| if (!object.styleRef().hasOpacity()) |
| - return; |
| - RefPtr<EffectPaintPropertyNode> effectNode = EffectPaintPropertyNode::create(object.styleRef().opacity(), context.currentEffect); |
| - context.currentEffect = effectNode.get(); |
| - object.getMutableForPainting().ensureObjectPaintProperties().setEffect(effectNode.release()); |
| + return false; |
| + |
| + value = object.styleRef().opacity(); |
| + return true; |
| } |
| -void PaintPropertyTreeBuilder::updateCssClip(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +void PaintPropertyTreeBuilder::updateEffect(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +{ |
| + updateObjectPaintProperty< |
| + EffectPaintPropertyNode, |
| + &ObjectPaintProperties::effect, |
| + &ObjectPaintProperties::setEffect, |
| + &computeEffect>(object, context, context.currentEffect); |
| +} |
| + |
| +bool PaintPropertyTreeBuilder::computeCssClip(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, ClipPaintPropertyNode::Value& value) |
| { |
| if (!object.hasClip()) |
| - return; |
| - ASSERT(object.canContainAbsolutePositionObjects()); |
| + return false; |
| + DCHECK(object.canContainAbsolutePositionObjects()); |
| // Create clip node for descendants that are not fixed position. |
| // We don't have to setup context.absolutePosition.clip here because this object must be |
| // a container for absolute position descendants, and will copy from in-flow context later |
| // at updateOutOfFlowContext() step. |
| LayoutRect clipRect = toLayoutBox(object).clipRect(context.current.paintOffset); |
| - RefPtr<ClipPaintPropertyNode> clipNode = ClipPaintPropertyNode::create( |
| - context.current.transform, |
| - FloatRoundedRect(FloatRect(clipRect)), |
| - context.current.clip); |
| - context.current.clip = clipNode.get(); |
| - object.getMutableForPainting().ensureObjectPaintProperties().setCssClip(clipNode.release()); |
| + value = FloatRoundedRect(FloatRect(clipRect)); |
| + return true; |
| +} |
| + |
| +void PaintPropertyTreeBuilder::updateCssClip(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +{ |
| + if (ClipPaintPropertyNode* node = updateObjectPaintProperty< |
| + ClipPaintPropertyNode, |
| + &ObjectPaintProperties::cssClip, |
| + &ObjectPaintProperties::setCssClip, |
| + &computeCssClip>(object, context, context.current.clip)) |
| + node->setLocalTransformSpace(context.current.transform); |
| } |
| void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(const LayoutObject& object, const PaintPropertyTreeBuilderContext& context) |
| @@ -183,29 +236,49 @@ void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(const LayoutObject& o |
| } |
| // TODO(trchen): Remove this once we bake the paint offset into frameRect. |
| -void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(const LayoutObject& object, const PaintPropertyTreeBuilderContext& context) |
| +bool PaintPropertyTreeBuilder::computeScrollbarPaintOffset(const LayoutObject& object, const PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value) |
| { |
| IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); |
| if (roundedPaintOffset == IntPoint()) |
| - return; |
| + return false; |
| if (!object.isBoxModelObject()) |
| - return; |
| + return false; |
| PaintLayerScrollableArea* scrollableArea = toLayoutBoxModelObject(object).getScrollableArea(); |
| if (!scrollableArea) |
| - return; |
| + return false; |
| if (!scrollableArea->horizontalScrollbar() && !scrollableArea->verticalScrollbar()) |
| + return false; |
| + |
| + value.matrix.translate(roundedPaintOffset.x(), roundedPaintOffset.y()); |
| + return true; |
| +} |
| + |
| +// TODO(trchen): Remove this once we bake the paint offset into frameRect. |
| +void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(const LayoutObject& object, const PaintPropertyTreeBuilderContext& context) |
| +{ |
| + // This method is almost the same as updateObjectPaintProperty template, except that it doesn't |
|
pdr.
2016/07/21 21:34:06
Can you think of a way to use the same update obje
Xianzhu
2016/07/22 01:14:04
Done.
|
| + // update any context property. |
| + ObjectPaintProperties* previousProperties = object.objectPaintProperties(); |
| + TransformPaintPropertyNode::Value paintOffset; |
| + if (!computeScrollbarPaintOffset(object, context, paintOffset)) { |
| + if (previousProperties) |
| + (previousProperties->setScrollbarPaintOffset(nullptr)); |
| + return; |
| + } |
| + |
| + TransformPaintPropertyNode* previousScrollbarPaintOffsetNode = previousProperties ? previousProperties->scrollbarPaintOffset() : nullptr; |
| + if (previousScrollbarPaintOffsetNode && previousScrollbarPaintOffsetNode->value() == paintOffset) { |
| + previousScrollbarPaintOffsetNode->setParent(context.current.transform); |
| return; |
| + } |
| - auto paintOffset = TransformationMatrix().translate(roundedPaintOffset.x(), roundedPaintOffset.y()); |
| object.getMutableForPainting().ensureObjectPaintProperties().setScrollbarPaintOffset( |
| - TransformPaintPropertyNode::create(paintOffset, FloatPoint3D(), context.current.transform)); |
| + TransformPaintPropertyNode::create(paintOffset, context.current.transform)); |
| } |
| -void PaintPropertyTreeBuilder::updateOverflowClip(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +bool PaintPropertyTreeBuilder::computeOverflowClip(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, ClipPaintPropertyNode::Value& value) |
| { |
| - if (!object.isBox()) |
| - return; |
| const LayoutBox& box = toLayoutBox(object); |
| // The <input> elements can't have contents thus CSS overflow property doesn't apply. |
| @@ -218,22 +291,33 @@ void PaintPropertyTreeBuilder::updateOverflowClip(const LayoutObject& object, Pa |
| else if (box.hasOverflowClip()) |
| clipRect = box.overflowClipRect(context.current.paintOffset); |
| else |
| + return false; |
| + |
| + value = FloatRoundedRect(FloatRect(clipRect)); |
| + return true; |
| +} |
| + |
| +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.styleRef().hasBorderRadius()) { |
| + 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); |
| + borderRadiusClip = ClipPaintPropertyNode::create(context.current.transform, innerBorder, context.current.clip); |
| + context.current.clip = borderRadiusClip.get(); |
| } |
| - RefPtr<ClipPaintPropertyNode> overflowClip = ClipPaintPropertyNode::create( |
| - context.current.transform, |
| - FloatRoundedRect(FloatRect(clipRect)), |
| - borderRadiusClip ? borderRadiusClip.release() : context.current.clip); |
| - context.current.clip = overflowClip.get(); |
| - object.getMutableForPainting().ensureObjectPaintProperties().setOverflowClip(overflowClip.release()); |
| + if (ClipPaintPropertyNode* node = updateObjectPaintProperty< |
| + ClipPaintPropertyNode, |
| + &ObjectPaintProperties::overflowClip, |
| + &ObjectPaintProperties::setOverflowClip, |
| + &computeOverflowClip>(object, context, context.current.clip)) |
| + node->setLocalTransformSpace(context.current.transform); |
| } |
| static FloatPoint perspectiveOrigin(const LayoutBox& box) |
| @@ -245,24 +329,30 @@ static FloatPoint perspectiveOrigin(const LayoutBox& box) |
| floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())); |
| } |
| -void PaintPropertyTreeBuilder::updatePerspective(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +bool PaintPropertyTreeBuilder::computePerspective(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value) |
| { |
| const ComputedStyle& style = object.styleRef(); |
| if (!object.isBox() || !style.hasPerspective()) |
| - return; |
| + return false; |
| - RefPtr<TransformPaintPropertyNode> perspective = TransformPaintPropertyNode::create( |
| - TransformationMatrix().applyPerspective(style.perspective()), |
| - perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.current.paintOffset), |
| - context.current.transform); |
| - context.current.transform = perspective.get(); |
| - object.getMutableForPainting().ensureObjectPaintProperties().setPerspective(perspective.release()); |
| + value.matrix.applyPerspective(style.perspective()); |
| + value.origin = perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.current.paintOffset); |
| + return true; |
| } |
| -void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +void PaintPropertyTreeBuilder::updatePerspective(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +{ |
| + updateObjectPaintProperty< |
| + TransformPaintPropertyNode, |
| + &ObjectPaintProperties::perspective, |
| + &ObjectPaintProperties::setPerspective, |
| + &computePerspective>(object, context, context.current.transform); |
| +} |
| + |
| +bool PaintPropertyTreeBuilder::computeSvgLocalToBorderBoxTransform(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value) |
| { |
| if (!object.isSVGRoot()) |
| - return; |
| + return false; |
| AffineTransform transformToBorderBox = SVGRootPainter(toLayoutSVGRoot(object)).transformToPixelSnappedBorderBox(context.current.paintOffset); |
| @@ -271,35 +361,48 @@ void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(const LayoutOb |
| context.current.paintOffset = LayoutPoint(); |
| if (transformToBorderBox.isIdentity()) |
| - return; |
| + return false; |
| - RefPtr<TransformPaintPropertyNode> svgLocalToBorderBoxTransform = TransformPaintPropertyNode::create( |
| - transformToBorderBox, FloatPoint3D(0, 0, 0), context.current.transform); |
| - context.current.transform = svgLocalToBorderBoxTransform.get(); |
| + value.matrix = transformToBorderBox; |
| context.current.paintOffset = LayoutPoint(); |
| - object.getMutableForPainting().ensureObjectPaintProperties().setSvgLocalToBorderBoxTransform(svgLocalToBorderBoxTransform.release()); |
| + return true; |
| } |
| -void PaintPropertyTreeBuilder::updateScrollTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +{ |
| + updateObjectPaintProperty< |
| + TransformPaintPropertyNode, |
| + &ObjectPaintProperties::svgLocalToBorderBoxTransform, |
| + &ObjectPaintProperties::setSvgLocalToBorderBoxTransform, |
| + &computeSvgLocalToBorderBoxTransform>(object, context, context.current.transform); |
| +} |
| + |
| +bool PaintPropertyTreeBuilder::computeScrollTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, TransformPaintPropertyNode::Value& value) |
| { |
| if (!object.isBoxModelObject() || !object.hasOverflowClip()) |
| - return; |
| + return false; |
| PaintLayer* layer = toLayoutBoxModelObject(object).layer(); |
| ASSERT(layer); |
| DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset(); |
| if (scrollOffset.isZero() && !layer->scrollsOverflow()) |
| - return; |
| + return false; |
| - RefPtr<TransformPaintPropertyNode> scrollTranslation = TransformPaintPropertyNode::create( |
| - TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.height()), |
| - FloatPoint3D(), |
| - context.current.transform); |
| - context.current.transform = scrollTranslation.get(); |
| - object.getMutableForPainting().ensureObjectPaintProperties().setScrollTranslation(scrollTranslation.release()); |
| + value.matrix.translate(-scrollOffset.width(), -scrollOffset.height()); |
| + return true; |
| } |
| -void PaintPropertyTreeBuilder::updateOutOfFlowContext(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +void PaintPropertyTreeBuilder::updateScrollTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +{ |
| + updateObjectPaintProperty< |
| + TransformPaintPropertyNode, |
| + &ObjectPaintProperties::scrollTranslation, |
| + &ObjectPaintProperties::setScrollTranslation, |
| + &computeScrollTranslation>(object, context, context.current.transform); |
| +} |
| + |
| +// Returns true if we need to create a cssClip node for fixed position. |
| +bool PaintPropertyTreeBuilder::computeOutOfFlowContext(const LayoutObject& object, PaintPropertyTreeBuilderContext& context, ClipPaintPropertyNode::Value& value) |
| { |
| if (object.canContainAbsolutePositionObjects()) { |
| context.absolutePosition = context.current; |
| @@ -310,28 +413,38 @@ void PaintPropertyTreeBuilder::updateOutOfFlowContext(const LayoutObject& object |
| // paint properties for rootLayerScrolls. |
| if (!object.isLayoutView() && object.canContainFixedPositionObjects()) { |
| context.fixedPosition = context.current; |
| - } else if (object.objectPaintProperties() && object.objectPaintProperties()->cssClip()) { |
| - // 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 |
| - // having CSS clip implies being absolute position container. However for fixed-position |
| - // descendants we need to insert the clip here if we are not a containing block ancestor |
| - // of them. |
| - auto* cssClip = object.objectPaintProperties()->cssClip(); |
| - |
| - // Before we actually create anything, check whether in-flow context and fixed-position |
| - // context has exactly the same clip. Reuse if possible. |
| - if (context.fixedPosition.clip == cssClip->parent()) { |
| - context.fixedPosition.clip = cssClip; |
| - return; |
| - } |
| + return false; |
| + } |
| - RefPtr<ClipPaintPropertyNode> clipFixedPosition = ClipPaintPropertyNode::create( |
| - const_cast<TransformPaintPropertyNode*>(cssClip->localTransformSpace()), |
| - cssClip->clipRect(), |
| - context.fixedPosition.clip); |
| - context.fixedPosition.clip = clipFixedPosition.get(); |
| - object.getMutableForPainting().ensureObjectPaintProperties().setCssClipFixedPosition(clipFixedPosition.release()); |
| + if (!object.objectPaintProperties() || !object.objectPaintProperties()->cssClip()) |
| + return false; |
| + |
| + // 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 |
| + // having CSS clip implies being absolute position container. However for fixed-position |
| + // descendants we need to insert the clip here if we are not a containing block ancestor |
| + // of them. |
| + auto* cssClip = object.objectPaintProperties()->cssClip(); |
| + |
| + // Before we actually create anything, check whether in-flow context and fixed-position |
| + // context has exactly the same clip. Reuse if possible. |
| + if (context.fixedPosition.clip == cssClip->parent()) { |
| + context.fixedPosition.clip = cssClip; |
| + return false; |
| } |
| + |
| + value = cssClip->clipRect(); |
| + return true; |
| +} |
| + |
| +void PaintPropertyTreeBuilder::updateOutOfFlowContext(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| +{ |
| + if (ClipPaintPropertyNode* node = updateObjectPaintProperty< |
| + ClipPaintPropertyNode, |
| + &ObjectPaintProperties::cssClipFixedPosition, |
| + &ObjectPaintProperties::setCssClipFixedPosition, |
| + &computeOutOfFlowContext>(object, context, context.fixedPosition.clip)) |
| + node->setLocalTransformSpace(const_cast<TransformPaintPropertyNode*>(object.objectPaintProperties()->cssClip()->localTransformSpace())); |
| } |
| static void deriveBorderBoxFromContainerContext(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| @@ -385,8 +498,6 @@ static void deriveBorderBoxFromContainerContext(const LayoutObject& object, Pain |
| void PaintPropertyTreeBuilder::buildTreeNodes(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
| { |
| - object.getMutableForPainting().clearObjectPaintProperties(); |
| - |
| if (!object.isBoxModelObject() && !object.isSVG()) |
| return; |