Title: [271357] trunk/Source/WebCore
Revision
271357
Author
[email protected]
Date
2021-01-11 03:44:41 -0800 (Mon, 11 Jan 2021)

Log Message

[css-multicol] Restore placeholders on multicolumn children position changes.
https://bugs.webkit.org/show_bug.cgi?id=218501

Reviewed by Zalan Bujtas.

Whenever there is a placeholder in a multicolumn flow ("column-span: all") it must be ensured that the spanner
associated to that placeholder is properly restored as a child of the multicolumn flow when the element with
"column-span:all" is moved out of the multicolumn flow (for example by removing it, by making it out-of-flow
or because an ancestor becomes another multicolumn flow).

This was smoothly handled by the current code for the in-flow -> out-of-flow transition but not the other way
around, i.e in the case of making the placeholder (or an ancestor) an absolutely positioned element.

* rendering/updating/RenderTreeBuilder.cpp:
(WebCore::RenderTreeBuilder::normalizeTreeAfterStyleChange): restore column spanners then the element becomes
out-of-flow as it's removed from the multicolumn flow.
* rendering/updating/RenderTreeBuilderMultiColumn.cpp:
(WebCore::RenderTreeBuilder::MultiColumn::createFragmentedFlow): Call the newly created method
restoreColumnSpannersForContainer().
(WebCore::RenderTreeBuilder::MultiColumn::restoreColumnSpannersForContainer): Refactored from createFragmentedFlow()
as it's now used by normalizeTreeAfterStyleChange().
* rendering/updating/RenderTreeBuilderMultiColumn.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (271356 => 271357)


--- trunk/Source/WebCore/ChangeLog	2021-01-11 11:15:28 UTC (rev 271356)
+++ trunk/Source/WebCore/ChangeLog	2021-01-11 11:44:41 UTC (rev 271357)
@@ -1,3 +1,28 @@
+2021-01-07  Sergio Villar Senin  <[email protected]>
+
+        [css-multicol] Restore placeholders on multicolumn children position changes.
+        https://bugs.webkit.org/show_bug.cgi?id=218501
+
+        Reviewed by Zalan Bujtas.
+
+        Whenever there is a placeholder in a multicolumn flow ("column-span: all") it must be ensured that the spanner
+        associated to that placeholder is properly restored as a child of the multicolumn flow when the element with
+        "column-span:all" is moved out of the multicolumn flow (for example by removing it, by making it out-of-flow
+        or because an ancestor becomes another multicolumn flow).
+
+        This was smoothly handled by the current code for the in-flow -> out-of-flow transition but not the other way
+        around, i.e in the case of making the placeholder (or an ancestor) an absolutely positioned element.
+
+        * rendering/updating/RenderTreeBuilder.cpp:
+        (WebCore::RenderTreeBuilder::normalizeTreeAfterStyleChange): restore column spanners then the element becomes
+        out-of-flow as it's removed from the multicolumn flow.
+        * rendering/updating/RenderTreeBuilderMultiColumn.cpp:
+        (WebCore::RenderTreeBuilder::MultiColumn::createFragmentedFlow): Call the newly created method
+        restoreColumnSpannersForContainer().
+        (WebCore::RenderTreeBuilder::MultiColumn::restoreColumnSpannersForContainer): Refactored from createFragmentedFlow()
+        as it's now used by normalizeTreeAfterStyleChange().
+        * rendering/updating/RenderTreeBuilderMultiColumn.h:
+
 2020-12-04  Sergio Villar Senin  <[email protected]>
 
         [css-multicol] Update fragment flow state on element insertion when element position changes

Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp (271356 => 271357)


--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp	2021-01-11 11:15:28 UTC (rev 271356)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp	2021-01-11 11:44:41 UTC (rev 271357)
@@ -598,9 +598,18 @@
 
     // Out of flow children of RenderMultiColumnFlow are not really part of the multicolumn flow. We need to ensure that changes in positioning like this
     // trigger insertions into the multicolumn flow.
-    if (auto* enclosingFragmentedFlow = parent.enclosingFragmentedFlow(); is<RenderMultiColumnFlow>(enclosingFragmentedFlow) && wasOutOfFlowPositioned && !isOutOfFlowPositioned) {
-        multiColumnBuilder().multiColumnDescendantInserted(downcast<RenderMultiColumnFlow>(*enclosingFragmentedFlow), renderer);
-        renderer.initializeFragmentedFlowStateOnInsertion();
+    if (auto* enclosingFragmentedFlow = parent.enclosingFragmentedFlow(); is<RenderMultiColumnFlow>(enclosingFragmentedFlow)) {
+        auto movingIntoMulticolumn = wasOutOfFlowPositioned && !isOutOfFlowPositioned;
+        if (movingIntoMulticolumn) {
+            multiColumnBuilder().multiColumnDescendantInserted(downcast<RenderMultiColumnFlow>(*enclosingFragmentedFlow), renderer);
+            renderer.initializeFragmentedFlowStateOnInsertion();
+            return;
+        }
+        auto movingOutOfMulticolumn = !wasOutOfFlowPositioned && isOutOfFlowPositioned;
+        if (movingOutOfMulticolumn) {
+            multiColumnBuilder().restoreColumnSpannersForContainer(renderer, downcast<RenderMultiColumnFlow>(*enclosingFragmentedFlow));
+            return;
+        }
     }
 }
 

Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilderMultiColumn.cpp (271356 => 271357)


--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilderMultiColumn.cpp	2021-01-11 11:15:28 UTC (rev 271356)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilderMultiColumn.cpp	2021-01-11 11:44:41 UTC (rev 271357)
@@ -153,29 +153,8 @@
     flow.deleteLines();
     // If this soon-to-be multicolumn flow is already part of a multicolumn context, we need to move back the descendant spanners
     // to their original position before moving subtrees around.
-    auto* enclosingflow = flow.enclosingFragmentedFlow();
-    if (is<RenderMultiColumnFlow>(enclosingflow)) {
-        auto& spanners = downcast<RenderMultiColumnFlow>(enclosingflow)->spannerMap();
-        Vector<RenderMultiColumnSpannerPlaceholder*> placeholdersToDelete;
-        for (auto& spannerAndPlaceholder : spanners) {
-            auto& placeholder = *spannerAndPlaceholder.value;
-            if (!placeholder.isDescendantOf(&flow))
-                continue;
-            placeholdersToDelete.append(&placeholder);
-        }
-        for (auto* placeholder : placeholdersToDelete) {
-            auto* spanner = placeholder->spanner();
-            if (!spanner) {
-                ASSERT_NOT_REACHED();
-                continue;
-            }
-            // Move the spanner back to its original position.
-            auto& spannerOriginalParent = *placeholder->parent();
-            // Detaching the spanner takes care of removing the placeholder (and merges the RenderMultiColumnSets).
-            auto spannerToReInsert = m_builder.detach(*spanner->parent(), *spanner);
-            m_builder.attach(spannerOriginalParent, WTFMove(spannerToReInsert));
-        }
-    }
+    if (auto* enclosingflow = flow.enclosingFragmentedFlow(); is<RenderMultiColumnFlow>(enclosingflow))
+        restoreColumnSpannersForContainer(flow, downcast<RenderMultiColumnFlow>(*enclosingflow));
 
     auto newFragmentedFlow = WebCore::createRenderer<RenderMultiColumnFlow>(flow.document(), RenderStyle::createAnonymousStyleWithDisplay(flow.style(), DisplayType::Block));
     newFragmentedFlow->initializeStyle();
@@ -195,6 +174,30 @@
     flow.setMultiColumnFlow(fragmentedFlow);
 }
 
+void RenderTreeBuilder::MultiColumn::restoreColumnSpannersForContainer(const RenderElement& container, RenderMultiColumnFlow& multiColumnFlow)
+{
+    auto& spanners = multiColumnFlow.spannerMap();
+    Vector<RenderMultiColumnSpannerPlaceholder*> placeholdersToRestore;
+    for (auto& spannerAndPlaceholder : spanners) {
+        auto& placeholder = *spannerAndPlaceholder.value;
+        if (!placeholder.isDescendantOf(&container))
+            continue;
+        placeholdersToRestore.append(&placeholder);
+    }
+    for (auto* placeholder : placeholdersToRestore) {
+        auto* spanner = placeholder->spanner();
+        if (!spanner) {
+            ASSERT_NOT_REACHED();
+            continue;
+        }
+        // Move the spanner back to its original position.
+        auto& spannerOriginalParent = *placeholder->parent();
+        // Detaching the spanner takes care of removing the placeholder (and merges the RenderMultiColumnSets).
+        auto spannerToReInsert = m_builder.detach(*spanner->parent(), *spanner);
+        m_builder.attach(spannerOriginalParent, WTFMove(spannerToReInsert));
+    }
+}
+
 void RenderTreeBuilder::MultiColumn::destroyFragmentedFlow(RenderBlockFlow& flow)
 {
     auto& multiColumnFlow = *flow.multiColumnFlow();

Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilderMultiColumn.h (271356 => 271357)


--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilderMultiColumn.h	2021-01-11 11:15:28 UTC (rev 271356)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilderMultiColumn.h	2021-01-11 11:44:41 UTC (rev 271357)
@@ -42,6 +42,7 @@
     // sets. If |child| is such a renderer, resolve it to the placeholder that lives at the original
     // location in the tree.
     RenderObject* resolveMovedChild(RenderFragmentedFlow& enclosingFragmentedFlow, RenderObject* beforeChild);
+    void restoreColumnSpannersForContainer(const RenderElement& container, RenderMultiColumnFlow&);
     void multiColumnDescendantInserted(RenderMultiColumnFlow&, RenderObject& newDescendant);
     void multiColumnRelativeWillBeRemoved(RenderMultiColumnFlow&, RenderObject& relative);
     static RenderObject* adjustBeforeChildForMultiColumnSpannerIfNeeded(RenderObject& beforeChild);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to