- 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;