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; |