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 5a627a037a844570a70db6d54df4fbe64439033e..3e8e63a2ce6fdaf4f8cb42b2f5e5dce0e79a1a75 100644 |
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp |
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp |
@@ -658,6 +658,45 @@ void PaintPropertyTreeBuilder::updateOutOfFlowContext( |
properties->clearCssClipFixedPosition(); |
} |
+// Override ContainerContext based on the properties of a container that was |
+// previously walked in a subtree other than the current subtree being walked. |
+// Used for out-of-flow positioned descendants of multi-column spanner when |
+// the container is not in the normal tree walk order. |
+// For example: |
+// <div id="columns" style="columns: 2"> |
+// <div id="relative" style="position: relative"> |
+// <div id="spanner" style="column-span: all"> |
+// <div id="absolute" style="position: absolute"></div> |
+// </div> |
+// </div> |
+// <div> |
+// The real container of "absolute" is "relative" which is not in the tree-walk |
+// order of "columns" -> spanner placeholder -> spanner -> absolute. Here we |
+// rebuild a ContainerContext based on the properties of "relative" for |
+// "absolute". |
+static void overrideContainerContextFromContainer( |
+ const LayoutObject& container, |
+ PaintPropertyTreeBuilderContext::ContainerContext& context) { |
+ // The container is never a LayoutInline. In the above example, if we change |
+ // the container to an inline, there must be an anonymous blocks created |
+ // because the spanner is always a block. |
+ DCHECK(container.isLayoutBlock()); |
+ |
+ const auto* properties = |
+ container.objectPaintProperties()->localBorderBoxProperties(); |
+ DCHECK(properties); |
+ |
+ context.transform = properties->propertyTreeState.transform(); |
+ context.paintOffset = properties->paintOffset; |
+ context.shouldFlattenInheritedTransform = |
+ context.transform && context.transform->flattensInheritedTransform(); |
+ context.renderingContextID = |
+ context.transform ? context.transform->renderingContextID() : 0; |
+ context.clip = properties->propertyTreeState.clip(); |
+ context.scroll = const_cast<ScrollPaintPropertyNode*>( |
+ properties->propertyTreeState.scroll()); |
+} |
+ |
static void deriveBorderBoxFromContainerContext( |
const LayoutObject& object, |
PaintPropertyTreeBuilderContext& context) { |
@@ -673,9 +712,23 @@ static void deriveBorderBoxFromContainerContext( |
context.current.paintOffset += boxModelObject.offsetForInFlowPosition(); |
break; |
case AbsolutePosition: { |
- context.current = context.absolutePosition; |
+ if (context.isUnderMultiColumnSpanner) { |
+ const LayoutObject* container = boxModelObject.container(); |
+ if (container != context.containerForAbsolutePosition) { |
+ // The container of the absolute-position is not in the normal tree- |
+ // walk order. |
+ context.containerForAbsolutePosition = |
+ toLayoutBoxModelObject(container); |
+ overrideContainerContextFromContainer(*container, context.current); |
+ } |
+ } else { |
+ DCHECK(context.containerForAbsolutePosition == |
+ boxModelObject.container()); |
+ context.current = context.absolutePosition; |
+ } |
- // Absolutely positioned content in an inline should be positioned relative to the inline. |
+ // Absolutely positioned content in an inline should be positioned |
+ // relative to the inline. |
const LayoutObject* container = context.containerForAbsolutePosition; |
if (container && container->isInFlowPositioned() && |
container->isLayoutInline()) { |
@@ -690,7 +743,14 @@ static void deriveBorderBoxFromContainerContext( |
context.current.paintOffset += boxModelObject.offsetForInFlowPosition(); |
break; |
case FixedPosition: |
- context.current = context.fixedPosition; |
+ if (context.isUnderMultiColumnSpanner) { |
+ // The container of the fixed-position object may or may not be in the |
+ // normal tree-walk order. |
+ overrideContainerContextFromContainer(*boxModelObject.container(), |
+ context.current); |
+ } else { |
+ context.current = context.fixedPosition; |
+ } |
break; |
default: |
ASSERT_NOT_REACHED(); |