Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(930)

Unified Diff: third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp

Issue 2144823006: Reuse existing paint property node is possible (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: - Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;

Powered by Google App Engine
This is Rietveld 408576698