Introduce RenderTreeBuilder
[WebKit-https.git] / Source / WebCore / style / RenderTreeUpdaterGeneratedContent.cpp
index a620a05..9446b5a 100644 (file)
@@ -61,7 +61,7 @@ void RenderTreeUpdater::GeneratedContent::updateQuotesUpTo(RenderQuote* lastQuot
     for (; it != end; ++it) {
         auto& quote = *it;
         // Quote character depends on quote depth so we chain the updates.
-        quote.updateRenderer(m_previousUpdatedQuote);
+        quote.updateRenderer(m_updater.m_builder, m_previousUpdatedQuote);
         m_previousUpdatedQuote = &quote;
         if (&quote == lastQuote)
             return;
@@ -69,26 +69,24 @@ void RenderTreeUpdater::GeneratedContent::updateQuotesUpTo(RenderQuote* lastQuot
     ASSERT(!lastQuote);
 }
 
-static void createContentRenderers(RenderElement& renderer)
+static void createContentRenderers(RenderTreeBuilder& builder, RenderElement& pseudoRenderer, const RenderStyle& style)
 {
-    auto& style = renderer.style();
     ASSERT(style.contentData());
 
     for (const ContentData* content = style.contentData(); content; content = content->next()) {
-        auto child = content->createContentRenderer(renderer.document(), style);
-        if (renderer.isChildAllowed(*child, style))
-            renderer.addChild(WTFMove(child));
+        auto child = content->createContentRenderer(pseudoRenderer.document(), style);
+        if (pseudoRenderer.isChildAllowed(*child, style))
+            builder.insertChild(pseudoRenderer, WTFMove(child));
     }
 }
 
-static void updateStyleForContentRenderers(RenderElement& renderer)
+static void updateStyleForContentRenderers(RenderElement& pseudoRenderer, const RenderStyle& style)
 {
-    for (auto* child = renderer.nextInPreOrder(&renderer); child; child = child->nextInPreOrder(&renderer)) {
+    for (auto& contentRenderer : descendantsOfType<RenderElement>(pseudoRenderer)) {
         // We only manage the style for the generated content which must be images or text.
-        if (!is<RenderImage>(*child) && !is<RenderQuote>(*child))
+        if (!is<RenderImage>(contentRenderer) && !is<RenderQuote>(contentRenderer))
             continue;
-        auto createdStyle = RenderStyle::createStyleInheritingFromPseudoStyle(renderer.style());
-        downcast<RenderElement>(*child).setStyle(WTFMove(createdStyle));
+        contentRenderer.setStyle(RenderStyle::createStyleInheritingFromPseudoStyle(style));
     }
 }
 
@@ -102,9 +100,9 @@ void RenderTreeUpdater::GeneratedContent::updatePseudoElement(Element& current,
     if (!needsPseudoElement(update)) {
         if (pseudoElement) {
             if (pseudoId == BEFORE)
-                current.clearBeforePseudoElement();
+                removeBeforePseudoElement(current);
             else
-                current.clearAfterPseudoElement();
+                removeAfterPseudoElement(current);
         }
         return;
     }
@@ -125,23 +123,37 @@ void RenderTreeUpdater::GeneratedContent::updatePseudoElement(Element& current,
             current.setAfterPseudoElement(newPseudoElement.releaseNonNull());
     }
 
-    m_updater.updateElementRenderer(*pseudoElement, *update);
+    if (update->style->display() == CONTENTS) {
+        // For display:contents we create an inline wrapper that inherits its
+        // style from the display:contents style.
+        auto contentsStyle = RenderStyle::createPtr();
+        contentsStyle->setStyleType(pseudoId);
+        contentsStyle->inheritFrom(*update->style);
+        contentsStyle->copyContentFrom(*update->style);
+
+        Style::ElementUpdate contentsUpdate { WTFMove(contentsStyle), update->change, update->recompositeLayer };
+        m_updater.updateElementRenderer(*pseudoElement, contentsUpdate);
+        pseudoElement->storeDisplayContentsStyle(RenderStyle::clonePtr(*update->style));
+    } else {
+        m_updater.updateElementRenderer(*pseudoElement, *update);
+        ASSERT(!pseudoElement->hasDisplayContents());
+    }
 
-    auto* pseudoRenderer = pseudoElement->renderer();
-    if (!pseudoRenderer)
+    auto* pseudoElementRenderer = pseudoElement->renderer();
+    if (!pseudoElementRenderer)
         return;
 
     if (update->change == Style::Detach)
-        createContentRenderers(*pseudoRenderer);
+        createContentRenderers(m_updater.m_builder, *pseudoElementRenderer, *update->style);
     else
-        updateStyleForContentRenderers(*pseudoRenderer);
+        updateStyleForContentRenderers(*pseudoElementRenderer, *update->style);
 
     if (m_updater.renderView().hasQuotesNeedingUpdate()) {
-        for (auto& child : descendantsOfType<RenderQuote>(*pseudoRenderer))
+        for (auto& child : descendantsOfType<RenderQuote>(*pseudoElementRenderer))
             updateQuotesUpTo(&child);
     }
-    if (is<RenderListItem>(*pseudoRenderer))
-        ListItem::updateMarker(downcast<RenderListItem>(*pseudoRenderer));
+    if (is<RenderListItem>(*pseudoElementRenderer))
+        ListItem::updateMarker(m_updater.m_builder, downcast<RenderListItem>(*pseudoElementRenderer));
 }
 
 bool RenderTreeUpdater::GeneratedContent::needsPseudoElement(const std::optional<Style::ElementUpdate>& update)
@@ -155,4 +167,22 @@ bool RenderTreeUpdater::GeneratedContent::needsPseudoElement(const std::optional
     return true;
 }
 
+void RenderTreeUpdater::GeneratedContent::removeBeforePseudoElement(Element& element)
+{
+    auto* pseudoElement = element.beforePseudoElement();
+    if (!pseudoElement)
+        return;
+    tearDownRenderers(*pseudoElement, TeardownType::Full);
+    element.clearBeforePseudoElement();
+}
+
+void RenderTreeUpdater::GeneratedContent::removeAfterPseudoElement(Element& element)
+{
+    auto* pseudoElement = element.afterPseudoElement();
+    if (!pseudoElement)
+        return;
+    tearDownRenderers(*pseudoElement, TeardownType::Full);
+    element.clearAfterPseudoElement();
+}
+
 }