Title: [226240] trunk/Source/WebCore
Revision
226240
Author
za...@apple.com
Date
2017-12-21 14:05:26 -0800 (Thu, 21 Dec 2017)

Log Message

[RenderTreeBuilder] Move RenderRubyAsBlock::addChild mutation to a RenderTreeBuilder
https://bugs.webkit.org/show_bug.cgi?id=181090
<rdar://problem/36180916>

Reviewed by Antti Koivisto.

This is in preparation for moving all ruby mutation code here.

Covered by existing tests.

* rendering/RenderRuby.cpp:
(WebCore::RenderRubyAsBlock::addChild): Deleted.
* rendering/RenderRuby.h:
* rendering/updating/RenderTreeBuilder.cpp:
(WebCore::RenderTreeBuilder::insertChild):
* rendering/updating/RenderTreeBuilderRuby.cpp:
(WebCore::isAnonymousRubyInlineBlock):
(WebCore::isRubyBeforeBlock):
(WebCore::isRubyAfterBlock):
(WebCore::isRubyChildForNormalRemoval):
(WebCore::rubyBeforeBlock):
(WebCore::rubyAfterBlock):
(WebCore::createAnonymousRubyInlineBlock):
(WebCore::lastRubyRun):
(WebCore::RenderTreeBuilder::Ruby::findOrCreateParentForChild):
* rendering/updating/RenderTreeBuilderRuby.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (226239 => 226240)


--- trunk/Source/WebCore/ChangeLog	2017-12-21 21:10:12 UTC (rev 226239)
+++ trunk/Source/WebCore/ChangeLog	2017-12-21 22:05:26 UTC (rev 226240)
@@ -1,3 +1,32 @@
+2017-12-21  Zalan Bujtas  <za...@apple.com>
+
+        [RenderTreeBuilder] Move RenderRubyAsBlock::addChild mutation to a RenderTreeBuilder
+        https://bugs.webkit.org/show_bug.cgi?id=181090
+        <rdar://problem/36180916>
+
+        Reviewed by Antti Koivisto.
+
+        This is in preparation for moving all ruby mutation code here.
+
+        Covered by existing tests.
+
+        * rendering/RenderRuby.cpp:
+        (WebCore::RenderRubyAsBlock::addChild): Deleted.
+        * rendering/RenderRuby.h:
+        * rendering/updating/RenderTreeBuilder.cpp:
+        (WebCore::RenderTreeBuilder::insertChild):
+        * rendering/updating/RenderTreeBuilderRuby.cpp:
+        (WebCore::isAnonymousRubyInlineBlock):
+        (WebCore::isRubyBeforeBlock):
+        (WebCore::isRubyAfterBlock):
+        (WebCore::isRubyChildForNormalRemoval):
+        (WebCore::rubyBeforeBlock):
+        (WebCore::rubyAfterBlock):
+        (WebCore::createAnonymousRubyInlineBlock):
+        (WebCore::lastRubyRun):
+        (WebCore::RenderTreeBuilder::Ruby::findOrCreateParentForChild):
+        * rendering/updating/RenderTreeBuilderRuby.h:
+
 2017-12-21  Jeremy Jones  <jere...@apple.com>
 
         Update FULLSCREEN_API feature defines.

Modified: trunk/Source/WebCore/rendering/RenderRuby.cpp (226239 => 226240)


--- trunk/Source/WebCore/rendering/RenderRuby.cpp	2017-12-21 21:10:12 UTC (rev 226239)
+++ trunk/Source/WebCore/rendering/RenderRuby.cpp	2017-12-21 22:05:26 UTC (rev 226240)
@@ -247,74 +247,6 @@
     propagateStyleToAnonymousChildren(PropagateToAllChildren);
 }
 
-void RenderRubyAsBlock::addChild(RenderTreeBuilder& builder, RenderPtr<RenderObject> child, RenderObject* beforeChild)
-{
-    // Insert :before and :after content before/after the RenderRubyRun(s)
-    if (child->isBeforeContent()) {
-        if (child->isInline()) {
-            // Add generated inline content normally
-            RenderBlockFlow::addChild(builder, WTFMove(child), firstChild());
-        } else {
-            // Wrap non-inline content with an anonymous inline-block.
-            RenderBlock* beforeBlock = rubyBeforeBlock(this);
-            if (!beforeBlock) {
-                auto newBlock = createAnonymousRubyInlineBlock(*this);
-                beforeBlock = newBlock.get();
-                RenderBlockFlow::addChild(builder, WTFMove(newBlock), firstChild());
-            }
-            builder.insertChild(*beforeBlock, WTFMove(child));
-        }
-        return;
-    }
-    if (child->isAfterContent()) {
-        if (child->isInline()) {
-            // Add generated inline content normally
-            RenderBlockFlow::addChild(builder, WTFMove(child));
-        } else {
-            // Wrap non-inline content with an anonymous inline-block.
-            RenderBlock* afterBlock = rubyAfterBlock(this);
-            if (!afterBlock) {
-                auto newBlock = createAnonymousRubyInlineBlock(*this);
-                afterBlock = newBlock.get();
-                RenderBlockFlow::addChild(builder, WTFMove(newBlock));
-            }
-            builder.insertChild(*afterBlock, WTFMove(child));
-        }
-        return;
-    }
-
-    // If the child is a ruby run, just add it normally.
-    if (child->isRubyRun()) {
-        RenderBlockFlow::addChild(builder, WTFMove(child), beforeChild);
-        return;
-    }
-
-    if (beforeChild && !isAfterContent(beforeChild)) {
-        // insert child into run
-        ASSERT(!beforeChild->isRubyRun());
-        RenderElement* run = beforeChild->parent();
-        while (run && !run->isRubyRun())
-            run = run->parent();
-        if (run) {
-            builder.insertChild(*run, WTFMove(child), beforeChild);
-            return;
-        }
-        ASSERT_NOT_REACHED(); // beforeChild should always have a run as parent!
-        // Emergency fallback: fall through and just append.
-    }
-
-    // If the new child would be appended, try to add the child to the previous run
-    // if possible, or create a new run otherwise.
-    // (The RenderRubyRun object will handle the details)
-    RenderRubyRun* lastRun = lastRubyRun(this);
-    if (!lastRun || lastRun->hasRubyText()) {
-        auto newRun = RenderRubyRun::staticCreateRubyRun(this);
-        lastRun = newRun.get();
-        RenderBlockFlow::addChild(builder, WTFMove(newRun), beforeChild);
-    }
-    builder.insertChild(*lastRun, WTFMove(child));
-}
-
 RenderPtr<RenderObject> RenderRubyAsBlock::takeChild(RenderObject& child)
 {
     // If the child's parent is *this (must be a ruby run or generated content or anonymous block),

Modified: trunk/Source/WebCore/rendering/RenderRuby.h (226239 => 226240)


--- trunk/Source/WebCore/rendering/RenderRuby.h	2017-12-21 21:10:12 UTC (rev 226239)
+++ trunk/Source/WebCore/rendering/RenderRuby.h	2017-12-21 22:05:26 UTC (rev 226240)
@@ -77,7 +77,6 @@
 
     Element& element() const { return downcast<Element>(nodeForNonAnonymous()); }
 
-    void addChild(RenderTreeBuilder&, RenderPtr<RenderObject> child, RenderObject* beforeChild = 0) override;
     RenderPtr<RenderObject> takeChild(RenderObject& child) override;
 
 protected:

Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp (226239 => 226240)


--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp	2017-12-21 21:10:12 UTC (rev 226239)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp	2017-12-21 22:05:26 UTC (rev 226240)
@@ -92,6 +92,11 @@
         return;
     }
 
+    if (is<RenderRubyAsBlock>(parent)) {
+        insertRecursiveIfNeeded(rubyBuilder().findOrCreateParentForChild(downcast<RenderRubyAsBlock>(parent), *child, beforeChild));
+        return;
+    }
+
     if (is<RenderRubyRun>(parent)) {
         rubyBuilder().insertChild(downcast<RenderRubyRun>(parent), WTFMove(child), beforeChild);
         return;

Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilderRuby.cpp (226239 => 226240)


--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilderRuby.cpp	2017-12-21 21:10:12 UTC (rev 226239)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilderRuby.cpp	2017-12-21 22:05:26 UTC (rev 226240)
@@ -26,10 +26,84 @@
 #include "config.h"
 #include "RenderTreeBuilderRuby.h"
 
+#include "RenderRubyRun.h"
 #include "RenderTreeBuilder.h"
 
 namespace WebCore {
 
+static inline bool isAnonymousRubyInlineBlock(const RenderObject* object)
+{
+    ASSERT(!object
+        || !isRuby(object->parent())
+        || is<RenderRubyRun>(*object)
+        || (object->isInline() && (object->isBeforeContent() || object->isAfterContent()))
+        || (object->isAnonymous() && is<RenderBlock>(*object) && object->style().display() == INLINE_BLOCK));
+
+    return object
+        && isRuby(object->parent())
+        && is<RenderBlock>(*object)
+        && !is<RenderRubyRun>(*object);
+}
+
+static inline bool isRubyBeforeBlock(const RenderObject* object)
+{
+    return isAnonymousRubyInlineBlock(object)
+        && !object->previousSibling()
+        && downcast<RenderBlock>(*object).firstChild()
+        && downcast<RenderBlock>(*object).firstChild()->style().styleType() == BEFORE;
+}
+
+static inline bool isRubyAfterBlock(const RenderObject* object)
+{
+    return isAnonymousRubyInlineBlock(object)
+        && !object->nextSibling()
+        && downcast<RenderBlock>(*object).firstChild()
+        && downcast<RenderBlock>(*object).firstChild()->style().styleType() == AFTER;
+}
+
+#ifndef ASSERT_DISABLED
+static inline bool isRubyChildForNormalRemoval(const RenderObject& object)
+{
+    return object.isRubyRun()
+    || object.isBeforeContent()
+    || object.isAfterContent()
+    || object.isRenderMultiColumnFlow()
+    || object.isRenderMultiColumnSet()
+    || isAnonymousRubyInlineBlock(&object);
+}
+#endif
+
+static inline RenderBlock* rubyBeforeBlock(const RenderElement* ruby)
+{
+    RenderObject* child = ruby->firstChild();
+    return isRubyBeforeBlock(child) ? downcast<RenderBlock>(child) : nullptr;
+}
+
+static inline RenderBlock* rubyAfterBlock(const RenderElement* ruby)
+{
+    RenderObject* child = ruby->lastChild();
+    return isRubyAfterBlock(child) ? downcast<RenderBlock>(child) : nullptr;
+}
+
+static auto createAnonymousRubyInlineBlock(RenderObject& ruby)
+{
+    auto newBlock = createRenderer<RenderBlockFlow>(ruby.document(), RenderStyle::createAnonymousStyleWithDisplay(ruby.style(), INLINE_BLOCK));
+    newBlock->initializeStyle();
+    return newBlock;
+}
+
+static RenderRubyRun* lastRubyRun(const RenderElement* ruby)
+{
+    RenderObject* child = ruby->lastChild();
+    if (child && !is<RenderRubyRun>(*child))
+        child = child->previousSibling();
+    if (!is<RenderRubyRun>(child)) {
+        ASSERT(!child || child->isBeforeContent() || child == rubyBeforeBlock(ruby));
+        return nullptr;
+    }
+    return downcast<RenderRubyRun>(child);
+}
+
 RenderTreeBuilder::Ruby::Ruby(RenderTreeBuilder& builder)
     : m_builder(builder)
 {
@@ -82,5 +156,68 @@
     m_builder.insertChild(*parent.rubyBaseSafe(), WTFMove(child), beforeChild);
 }
 
+RenderElement& RenderTreeBuilder::Ruby::findOrCreateParentForChild(RenderRubyAsBlock& parent, const RenderObject& child, RenderObject*& beforeChild)
+{
+    // Insert :before and :after content before/after the RenderRubyRun(s)
+    if (child.isBeforeContent()) {
+        // Add generated inline content normally
+        if (child.isInline())
+            return parent;
+        // Wrap non-inline content in an anonymous inline-block.
+        auto* beforeBlock = rubyBeforeBlock(&parent);
+        if (!beforeBlock) {
+            auto newBlock = createAnonymousRubyInlineBlock(parent);
+            beforeBlock = newBlock.get();
+            parent.RenderBlockFlow::addChild(m_builder, WTFMove(newBlock), parent.firstChild());
+        }
+        beforeChild = nullptr;
+        return *beforeBlock;
+    }
+
+    if (child.isAfterContent()) {
+        // Add generated inline content normally
+        if (child.isInline())
+            return parent;
+        // Wrap non-inline content with an anonymous inline-block.
+        auto* afterBlock = rubyAfterBlock(&parent);
+        if (!afterBlock) {
+            auto newBlock = createAnonymousRubyInlineBlock(parent);
+            afterBlock = newBlock.get();
+            parent.RenderBlockFlow::addChild(m_builder, WTFMove(newBlock));
+        }
+        beforeChild = nullptr;
+        return *afterBlock;
+    }
+
+    // If the child is a ruby run, just add it normally.
+    if (child.isRubyRun())
+        return parent;
+
+    if (beforeChild && !parent.isAfterContent(beforeChild)) {
+        // insert child into run
+        ASSERT(!beforeChild->isRubyRun());
+        auto* run = beforeChild->parent();
+        while (run && !run->isRubyRun())
+            run = run->parent();
+        if (run)
+            return *run;
+        ASSERT_NOT_REACHED(); // beforeChild should always have a run as parent!
+        // Emergency fallback: fall through and just append.
+    }
+
+    // If the new child would be appended, try to add the child to the previous run
+    // if possible, or create a new run otherwise.
+    // (The RenderRubyRun object will handle the details)
+    auto* lastRun = lastRubyRun(&parent);
+    if (!lastRun || lastRun->hasRubyText()) {
+        auto newRun = RenderRubyRun::staticCreateRubyRun(&parent);
+        lastRun = newRun.get();
+        parent.RenderBlockFlow::addChild(m_builder, WTFMove(newRun), beforeChild);
+    }
+    beforeChild = nullptr;
+    return *lastRun;
 }
 
+
+}
+

Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilderRuby.h (226239 => 226240)


--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilderRuby.h	2017-12-21 21:10:12 UTC (rev 226239)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilderRuby.h	2017-12-21 22:05:26 UTC (rev 226240)
@@ -29,7 +29,9 @@
 
 namespace WebCore {
 
+class RenderElement;
 class RenderObject;
+class RenderRubyAsBlock;
 class RenderRubyRun;
 class RenderTreeBuilder;
 
@@ -38,6 +40,7 @@
     Ruby(RenderTreeBuilder&);
 
     void insertChild(RenderRubyRun& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild);
+    RenderElement& findOrCreateParentForChild(RenderRubyAsBlock& parent, const RenderObject& child, RenderObject*& beforeChild);
 
 private:
     RenderTreeBuilder& m_builder;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to