Title: [274217] trunk
Revision
274217
Author
[email protected]
Date
2021-03-10 09:31:46 -0800 (Wed, 10 Mar 2021)

Log Message

Multi-column state propagation should follow containing block rules
https://bugs.webkit.org/show_bug.cgi?id=222932
<rdar://problem/74459411>

Reviewed by Antti Koivisto.

Source/WebCore:

When a renderer(A) gains multi-column context
1. a special RenderMultiColumnFlow renderer is constructed
2. it is then inserted under the original renderer(A) and
3. all (A)'s descendants get moved under this newly constructed RenderMultiColumnFlow renderer.
At step #3 we update each descendants flow state by calling initializeFragmentedFlowStateOnInsertion().
This patch check if the out-of-flow descendant is really part of the multi-column flow and updates the state accordingly.
e.g
  <div style="column-count: 2"><div><div id=child style="position: absolute"></div></div></div>
  "child" is _not_ part of the multi-column subtree. child's containing block is an ancestor of the multi-column renderer.

  <div style="column-count: 2"><div style="position: relative"><div id=child style="position: absolute"></div></div></div>
  "child" _is_ part of the multi-column subtree. child's containing block is the relatively positioned renderer which is part of the multi-column flow.

Test: fast/multicol/state-propagation-over-out-of-flow-boundary.html

* rendering/RenderObject.cpp:
(WebCore::RenderObject::setFragmentedFlowStateIncludingDescendants):
(WebCore::RenderObject::initializeFragmentedFlowStateOnInsertion):
(WebCore::RenderObject::resetFragmentedFlowStateOnRemoval):
* rendering/RenderObject.h:

LayoutTests:

* fast/multicol/state-propagation-over-out-of-flow-boundary-expected.txt: Added.
* fast/multicol/state-propagation-over-out-of-flow-boundary.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (274216 => 274217)


--- trunk/LayoutTests/ChangeLog	2021-03-10 17:26:04 UTC (rev 274216)
+++ trunk/LayoutTests/ChangeLog	2021-03-10 17:31:46 UTC (rev 274217)
@@ -1,3 +1,14 @@
+2021-03-10  Zalan Bujtas  <[email protected]>
+
+        Multi-column state propagation should follow containing block rules
+        https://bugs.webkit.org/show_bug.cgi?id=222932
+        <rdar://problem/74459411>
+
+        Reviewed by Antti Koivisto.
+
+        * fast/multicol/state-propagation-over-out-of-flow-boundary-expected.txt: Added.
+        * fast/multicol/state-propagation-over-out-of-flow-boundary.html: Added.
+
 2021-03-10  Youenn Fablet  <[email protected]>
 
         Remove getUserMedia denied requests if user grants a new getUserMedia request

Added: trunk/LayoutTests/fast/multicol/state-propagation-over-out-of-flow-boundary-expected.txt (0 => 274217)


--- trunk/LayoutTests/fast/multicol/state-propagation-over-out-of-flow-boundary-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/multicol/state-propagation-over-out-of-flow-boundary-expected.txt	2021-03-10 17:31:46 UTC (rev 274217)
@@ -0,0 +1,4 @@
+PASS if no crash or assert.
+text
+
+

Added: trunk/LayoutTests/fast/multicol/state-propagation-over-out-of-flow-boundary.html (0 => 274217)


--- trunk/LayoutTests/fast/multicol/state-propagation-over-out-of-flow-boundary.html	                        (rev 0)
+++ trunk/LayoutTests/fast/multicol/state-propagation-over-out-of-flow-boundary.html	2021-03-10 17:31:46 UTC (rev 274217)
@@ -0,0 +1,35 @@
+<style>
+svg { 
+  position: absolute;
+  white-space: pre;
+}
+span { 
+  display: contents;
+  letter-spacing: 1em;
+}
+
+#second {
+  -webkit-column-span: all;
+}
+
+#container {
+  -webkit-animation-name: keyframes4;
+  -webkit-animation-fill-mode: backwards;
+  animation-delay: 1s;
+}
+
+@keyframes keyframes4 {
+ 100% { column-width: 10px; }
+}
+</style>
+<script>
+if (window.testRunner)
+  testRunner.dumpAsText();
+_onload_ = () => {
+  second.style.columnWidth = "10px";
+  first.remove();
+}
+</script>
+PASS if no crash or assert.
+<div id=container><div id=first></div>text<svg><foreignObject><span>
+<div id=second></div></span></foreignObject></svg></div>

Modified: trunk/Source/WebCore/ChangeLog (274216 => 274217)


--- trunk/Source/WebCore/ChangeLog	2021-03-10 17:26:04 UTC (rev 274216)
+++ trunk/Source/WebCore/ChangeLog	2021-03-10 17:31:46 UTC (rev 274217)
@@ -1,3 +1,32 @@
+2021-03-10  Zalan Bujtas  <[email protected]>
+
+        Multi-column state propagation should follow containing block rules
+        https://bugs.webkit.org/show_bug.cgi?id=222932
+        <rdar://problem/74459411>
+
+        Reviewed by Antti Koivisto.
+
+        When a renderer(A) gains multi-column context
+        1. a special RenderMultiColumnFlow renderer is constructed
+        2. it is then inserted under the original renderer(A) and
+        3. all (A)'s descendants get moved under this newly constructed RenderMultiColumnFlow renderer.
+        At step #3 we update each descendants flow state by calling initializeFragmentedFlowStateOnInsertion().
+        This patch check if the out-of-flow descendant is really part of the multi-column flow and updates the state accordingly.
+        e.g
+          <div style="column-count: 2"><div><div id=child style="position: absolute"></div></div></div>
+          "child" is _not_ part of the multi-column subtree. child's containing block is an ancestor of the multi-column renderer.
+
+          <div style="column-count: 2"><div style="position: relative"><div id=child style="position: absolute"></div></div></div>
+          "child" _is_ part of the multi-column subtree. child's containing block is the relatively positioned renderer which is part of the multi-column flow.
+
+        Test: fast/multicol/state-propagation-over-out-of-flow-boundary.html
+
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::setFragmentedFlowStateIncludingDescendants):
+        (WebCore::RenderObject::initializeFragmentedFlowStateOnInsertion):
+        (WebCore::RenderObject::resetFragmentedFlowStateOnRemoval):
+        * rendering/RenderObject.h:
+
 2021-03-10  Michael Catanzaro  <[email protected]>
 
         [GTK] Reenable -fvisibility=hidden

Modified: trunk/Source/WebCore/rendering/RenderObject.cpp (274216 => 274217)


--- trunk/Source/WebCore/rendering/RenderObject.cpp	2021-03-10 17:26:04 UTC (rev 274216)
+++ trunk/Source/WebCore/rendering/RenderObject.cpp	2021-03-10 17:31:46 UTC (rev 274217)
@@ -192,7 +192,7 @@
     return node() && node()->renderer() == this && node()->hasTagName(marqueeTag);
 }
 
-void RenderObject::setFragmentedFlowStateIncludingDescendants(FragmentedFlowState state)
+void RenderObject::setFragmentedFlowStateIncludingDescendants(FragmentedFlowState state, const RenderElement* fragmentedFlowRoot)
 {
     setFragmentedFlowState(state);
 
@@ -203,8 +203,22 @@
         // If the child is a fragmentation context it already updated the descendants flag accordingly.
         if (child.isRenderFragmentedFlow())
             continue;
+        if (fragmentedFlowRoot && child.isOutOfFlowPositioned()) {
+            // Fragmented status propagation stops at out-of-flow boundary.
+            auto isInsideMulticolumnFlow = [&] {
+                auto* containingBlock = child.containingBlock();
+                if (!containingBlock) {
+                    ASSERT_NOT_REACHED();
+                    return false;
+                }
+                // It's ok to only check the first level containing block (as opposed to the containing block chain) as setFragmentedFlowStateIncludingDescendants is top to down.
+                return containingBlock->isDescendantOf(fragmentedFlowRoot);
+            };
+            if (!isInsideMulticolumnFlow())
+                continue;
+        }
         ASSERT(state != child.fragmentedFlowState());
-        child.setFragmentedFlowStateIncludingDescendants(state);
+        child.setFragmentedFlowStateIncludingDescendants(state, fragmentedFlowRoot);
     }
 }
 
@@ -246,7 +260,8 @@
     if (fragmentedFlowState() == computedState)
         return;
 
-    setFragmentedFlowStateIncludingDescendants(computedState);
+    auto* enclosingFragmentedFlow = locateEnclosingFragmentedFlow();
+    setFragmentedFlowStateIncludingDescendants(computedState, enclosingFragmentedFlow ? enclosingFragmentedFlow->parent() : nullptr);
 }
 
 void RenderObject::resetFragmentedFlowStateOnRemoval()
@@ -263,7 +278,8 @@
     if (isRenderFragmentedFlow())
         return;
 
-    setFragmentedFlowStateIncludingDescendants(NotInsideFragmentedFlow);
+    auto* enclosingFragmentedFlow = this->enclosingFragmentedFlow();
+    setFragmentedFlowStateIncludingDescendants(NotInsideFragmentedFlow, enclosingFragmentedFlow ? enclosingFragmentedFlow->parent() : nullptr);
 }
 
 void RenderObject::setParent(RenderElement* parent)

Modified: trunk/Source/WebCore/rendering/RenderObject.h (274216 => 274217)


--- trunk/Source/WebCore/rendering/RenderObject.h	2021-03-10 17:26:04 UTC (rev 274216)
+++ trunk/Source/WebCore/rendering/RenderObject.h	2021-03-10 17:31:46 UTC (rev 274217)
@@ -295,7 +295,7 @@
         InsideInFragmentedFlow = 1,
     };
 
-    void setFragmentedFlowStateIncludingDescendants(FragmentedFlowState);
+    void setFragmentedFlowStateIncludingDescendants(FragmentedFlowState, const RenderElement* fragmentedFlowRoot);
 
     FragmentedFlowState fragmentedFlowState() const { return m_bitfields.fragmentedFlowState(); }
     void setFragmentedFlowState(FragmentedFlowState state) { m_bitfields.setFragmentedFlowState(state); }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to