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 cfa3354378d20c10f581e8ed6d39f253b884a6ca..e3455594a44303c9a87b2fa0edd1e0895a3b8512 100644 |
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp |
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp |
@@ -666,6 +666,40 @@ void PaintPropertyTreeBuilder::updateOutOfFlowContext( |
properties->clearCssClipFixedPosition(); |
} |
+// Override ContainingBlockContext based on the properties of a containing block |
+// 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 containing block 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 containing block of "absolute" is "relative" which is not in the |
+// tree-walk order of "columns" -> spanner placeholder -> spanner -> absolute. |
+// Here we rebuild a ContainingBlockContext based on the properties of |
+// "relative" for "absolute". |
+static void overrideContaineringBlockContextFromRealContainingBlock( |
+ const LayoutBlock& containingBlock, |
+ PaintPropertyTreeBuilderContext::ContainingBlockContext& context) { |
+ const auto* properties = |
+ containingBlock.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) { |
@@ -681,7 +715,25 @@ 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); |
+ // The container is never a LayoutInline. In the example above |
+ // overrideContaineringBlockContextFromRealContainingBlock(), if we |
+ // change the container to an inline, there will be an anonymous |
+ // blocks created because the spanner is always a block. |
+ overrideContaineringBlockContextFromRealContainingBlock( |
+ toLayoutBlock(*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. |
@@ -699,7 +751,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. |
+ overrideContaineringBlockContextFromRealContainingBlock( |
+ toLayoutBlock(*boxModelObject.container()), context.current); |
+ } else { |
+ context.current = context.fixedPosition; |
+ } |
break; |
default: |
ASSERT_NOT_REACHED(); |