Diff
Modified: trunk/Source/WebCore/ChangeLog (226519 => 226520)
--- trunk/Source/WebCore/ChangeLog 2018-01-08 18:37:37 UTC (rev 226519)
+++ trunk/Source/WebCore/ChangeLog 2018-01-08 18:38:31 UTC (rev 226520)
@@ -1,3 +1,53 @@
+2018-01-08 Zalan Bujtas <[email protected]>
+
+ [RenderTreeBuilder] Move RenderInline addChild logic to RenderTreeBuilder
+ https://bugs.webkit.org/show_bug.cgi?id=181336
+ <rdar://problem/36324693>
+
+ Reviewed by Antti Koivisto.
+
+ This is about moving the code, no cleanup and/or normalization (unfortunately it also means
+ some temporary changes).
+
+ No change in functionality.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * rendering/RenderInline.cpp:
+ (WebCore::RenderInline::addChild):
+ (WebCore::RenderInline::addChildIgnoringContinuation):
+ (WebCore::RenderInline::childBecameNonInline):
+ (WebCore::nextContinuation): Deleted.
+ (WebCore::RenderInline::continuationBefore): Deleted.
+ (WebCore::newChildIsInline): Deleted.
+ (WebCore::RenderInline::cloneAsContinuation const): Deleted.
+ (WebCore::RenderInline::splitInlines): Deleted.
+ (WebCore::RenderInline::splitFlow): Deleted.
+ (WebCore::canUseAsParentForContinuation): Deleted.
+ (WebCore::RenderInline::addChildToContinuation): Deleted.
+ * rendering/RenderInline.h:
+ * rendering/updating/RenderTreeBuilder.cpp:
+ (WebCore::RenderTreeBuilder::RenderTreeBuilder):
+ (WebCore::RenderTreeBuilder::insertChildToRenderInline):
+ (WebCore::RenderTreeBuilder::insertChildToRenderInlineIgnoringContinuation):
+ (WebCore::RenderTreeBuilder::splitFlow):
+ * rendering/updating/RenderTreeBuilder.h:
+ (WebCore::RenderTreeBuilder::inlineBuilder):
+ * rendering/updating/RenderTreeBuilderInline.cpp: Added.
+ (WebCore::canUseAsParentForContinuation):
+ (WebCore::nextContinuation):
+ (WebCore::continuationBefore):
+ (WebCore::cloneAsContinuation):
+ (WebCore::newChildIsInline):
+ (WebCore::inFlowPositionedInlineAncestor):
+ (WebCore::RenderTreeBuilder::Inline::Inline):
+ (WebCore::RenderTreeBuilder::Inline::insertChild):
+ (WebCore::RenderTreeBuilder::Inline::insertChildToContinuation):
+ (WebCore::RenderTreeBuilder::Inline::insertChildIgnoringContinuation):
+ (WebCore::RenderTreeBuilder::Inline::splitFlow):
+ (WebCore::RenderTreeBuilder::Inline::splitInlines):
+ * rendering/updating/RenderTreeBuilderInline.h: Added.
+
2018-01-08 Zalan Bujtas <[email protected]>
[RenderTreeBuilder] Move RenderBlock addChild logic to RenderTreeBuilder
Modified: trunk/Source/WebCore/Sources.txt (226519 => 226520)
--- trunk/Source/WebCore/Sources.txt 2018-01-08 18:37:37 UTC (rev 226519)
+++ trunk/Source/WebCore/Sources.txt 2018-01-08 18:38:31 UTC (rev 226520)
@@ -1987,6 +1987,7 @@
rendering/updating/RenderTreeBuilderBlock.cpp
rendering/updating/RenderTreeBuilderFirstLetter.cpp
rendering/updating/RenderTreeBuilderFormControls.cpp
+rendering/updating/RenderTreeBuilderInline.cpp
rendering/updating/RenderTreeBuilderList.cpp
rendering/updating/RenderTreeBuilderMultiColumn.cpp
rendering/updating/RenderTreeBuilderRuby.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (226519 => 226520)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2018-01-08 18:37:37 UTC (rev 226519)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2018-01-08 18:38:31 UTC (rev 226520)
@@ -1025,9 +1025,7 @@
417DA6D913734E6E007C57FB /* Internals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 417DA4CF13734326007C57FB /* Internals.cpp */; };
417DA6DA13734E6E007C57FB /* Internals.h in Headers */ = {isa = PBXBuildFile; fileRef = 417DA4CE13734326007C57FB /* Internals.h */; };
417DA71D13735DFA007C57FB /* JSInternals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 417DA71B13735DFA007C57FB /* JSInternals.cpp */; };
- 427DA71D13735DFA007C57FB /* JSServiceWorkerInternals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 427DA71B13735DFA007C57FB /* JSServiceWorkerInternals.cpp */; };
417DA71E13735DFA007C57FB /* JSInternals.h in Headers */ = {isa = PBXBuildFile; fileRef = 417DA71C13735DFA007C57FB /* JSInternals.h */; };
- 427DA71E13735DFA007C57FB /* JSServiceWorkerInternals.h in Headers */ = {isa = PBXBuildFile; fileRef = 427DA71C13735DFA007C57FB /* JSServiceWorkerInternals.h */; };
417F0D821FFEE979008EF303 /* ServiceWorkerInternals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 417F0D801FFEE14F008EF303 /* ServiceWorkerInternals.cpp */; };
41815C1E138319830057AAA4 /* WebCoreTestSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41815C1C138319830057AAA4 /* WebCoreTestSupport.cpp */; };
41815C1F138319830057AAA4 /* WebCoreTestSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 41815C1D138319830057AAA4 /* WebCoreTestSupport.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -1064,6 +1062,8 @@
41F062140F5F192600A07EAC /* InspectorDatabaseResource.h in Headers */ = {isa = PBXBuildFile; fileRef = 41F062120F5F192600A07EAC /* InspectorDatabaseResource.h */; };
41F1D21F0EF35C2A00DA8753 /* ScriptCachedFrameData.h in Headers */ = {isa = PBXBuildFile; fileRef = 41F1D21D0EF35C2A00DA8753 /* ScriptCachedFrameData.h */; settings = {ATTRIBUTES = (Private, ); }; };
41FABD2D1F4DFE4A006A6C97 /* DOMCacheEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 41FABD2B1F4DFE42006A6C97 /* DOMCacheEngine.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 427DA71D13735DFA007C57FB /* JSServiceWorkerInternals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 427DA71B13735DFA007C57FB /* JSServiceWorkerInternals.cpp */; };
+ 427DA71E13735DFA007C57FB /* JSServiceWorkerInternals.h in Headers */ = {isa = PBXBuildFile; fileRef = 427DA71C13735DFA007C57FB /* JSServiceWorkerInternals.h */; };
43107BE218CC19DE00CC18E8 /* SelectorPseudoTypeMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 43107BE118CC19DE00CC18E8 /* SelectorPseudoTypeMap.h */; };
431A2F9C13B6F2B0007791E4 /* SVGAnimatedNumberOptionalNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = 431A2F9A13B6F2B0007791E4 /* SVGAnimatedNumberOptionalNumber.h */; };
432D3FE818A8658400D7DC03 /* SelectorCheckerTestFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 432D3FE718A8658400D7DC03 /* SelectorCheckerTestFunctions.h */; };
@@ -5591,6 +5591,8 @@
119340951FED715500935F1E /* RenderTreeBuilderFormControls.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderTreeBuilderFormControls.h; sourceTree = "<group>"; };
119340A01FEE024000935F1E /* RenderTreeBuilderBlock.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeBuilderBlock.cpp; sourceTree = "<group>"; };
119340A11FEE024000935F1E /* RenderTreeBuilderBlock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderTreeBuilderBlock.h; sourceTree = "<group>"; };
+ 11C5F1162003E7750001AE60 /* RenderTreeBuilderInline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeBuilderInline.cpp; sourceTree = "<group>"; };
+ 11C5F1182003E7760001AE60 /* RenderTreeBuilderInline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTreeBuilderInline.h; sourceTree = "<group>"; };
11E067EB1E62461300162D16 /* SimpleLineLayoutCoverage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SimpleLineLayoutCoverage.cpp; sourceTree = "<group>"; };
11E067ED1E6246E500162D16 /* SimpleLineLayoutCoverage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleLineLayoutCoverage.h; sourceTree = "<group>"; };
1400D7A717136EA70077CE05 /* ScriptWrappableInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptWrappableInlines.h; sourceTree = "<group>"; };
@@ -7031,9 +7033,7 @@
417DA4CF13734326007C57FB /* Internals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Internals.cpp; sourceTree = "<group>"; };
417DA6D013734E02007C57FB /* libWebCoreTestSupport.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libWebCoreTestSupport.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
417DA71B13735DFA007C57FB /* JSInternals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSInternals.cpp; sourceTree = "<group>"; };
- 427DA71B13735DFA007C57FB /* JSServiceWorkerInternals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSServiceWorkerInternals.cpp; sourceTree = "<group>"; };
417DA71C13735DFA007C57FB /* JSInternals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInternals.h; sourceTree = "<group>"; };
- 427DA71C13735DFA007C57FB /* JSServiceWorkerInternals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSServiceWorkerInternals.h; sourceTree = "<group>"; };
417F0D7E1FFEE14E008EF303 /* ServiceWorkerInternals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServiceWorkerInternals.h; sourceTree = "<group>"; };
417F0D801FFEE14F008EF303 /* ServiceWorkerInternals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ServiceWorkerInternals.cpp; sourceTree = "<group>"; };
417F0D811FFEE150008EF303 /* ServiceWorkerInternals.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ServiceWorkerInternals.idl; sourceTree = "<group>"; };
@@ -7145,6 +7145,8 @@
41FB278F1F34C28200795487 /* WorkerGlobalScopeCaches.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerGlobalScopeCaches.cpp; sourceTree = "<group>"; };
41FB27991F34CE9C00795487 /* CacheQueryOptions.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = CacheQueryOptions.idl; sourceTree = "<group>"; };
41FB279B1F34CEF000795487 /* CacheQueryOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CacheQueryOptions.h; sourceTree = "<group>"; };
+ 427DA71B13735DFA007C57FB /* JSServiceWorkerInternals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSServiceWorkerInternals.cpp; sourceTree = "<group>"; };
+ 427DA71C13735DFA007C57FB /* JSServiceWorkerInternals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSServiceWorkerInternals.h; sourceTree = "<group>"; };
43107BE118CC19DE00CC18E8 /* SelectorPseudoTypeMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectorPseudoTypeMap.h; sourceTree = "<group>"; };
43142E7913B1E97700F1C871 /* SVGAnimatedRect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGAnimatedRect.cpp; sourceTree = "<group>"; };
431A2F9A13B6F2B0007791E4 /* SVGAnimatedNumberOptionalNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedNumberOptionalNumber.h; sourceTree = "<group>"; };
@@ -24635,6 +24637,8 @@
E47C39261FE6E0DC00BBBC6B /* RenderTreeBuilderFirstLetter.h */,
119340941FED715500935F1E /* RenderTreeBuilderFormControls.cpp */,
119340951FED715500935F1E /* RenderTreeBuilderFormControls.h */,
+ 11C5F1162003E7750001AE60 /* RenderTreeBuilderInline.cpp */,
+ 11C5F1182003E7760001AE60 /* RenderTreeBuilderInline.h */,
E47C392B1FE6E0DF00BBBC6B /* RenderTreeBuilderList.cpp */,
E47C39281FE6E0DD00BBBC6B /* RenderTreeBuilderList.h */,
E47C39231FE6E0DA00BBBC6B /* RenderTreeBuilderMultiColumn.cpp */,
Modified: trunk/Source/WebCore/rendering/RenderInline.cpp (226519 => 226520)
--- trunk/Source/WebCore/rendering/RenderInline.cpp 2018-01-08 18:37:37 UTC (rev 226519)
+++ trunk/Source/WebCore/rendering/RenderInline.cpp 2018-01-08 18:38:31 UTC (rev 226520)
@@ -257,336 +257,14 @@
void RenderInline::addChild(RenderTreeBuilder& builder, RenderPtr<RenderObject> newChild, RenderObject* beforeChild)
{
- auto* beforeChildOrPlaceholder = beforeChild;
- if (auto* fragmentedFlow = enclosingFragmentedFlow())
- beforeChildOrPlaceholder = fragmentedFlow->resolveMovedChild(beforeChild);
- if (continuation()) {
- addChildToContinuation(builder, WTFMove(newChild), beforeChildOrPlaceholder);
- return;
- }
- addChildIgnoringContinuation(builder, WTFMove(newChild), beforeChildOrPlaceholder);
+ builder.insertChildToRenderInline(*this, WTFMove(newChild), beforeChild);
}
-static RenderBoxModelObject* nextContinuation(RenderObject* renderer)
-{
- if (is<RenderInline>(*renderer) && !renderer->isReplaced())
- return downcast<RenderInline>(*renderer).continuation();
- return downcast<RenderBlock>(*renderer).inlineContinuation();
-}
-
-RenderBoxModelObject* RenderInline::continuationBefore(RenderObject* beforeChild)
-{
- if (beforeChild && beforeChild->parent() == this)
- return this;
-
- RenderBoxModelObject* curr = nextContinuation(this);
- RenderBoxModelObject* nextToLast = this;
- RenderBoxModelObject* last = this;
- while (curr) {
- if (beforeChild && beforeChild->parent() == curr) {
- if (curr->firstChild() == beforeChild)
- return last;
- return curr;
- }
-
- nextToLast = last;
- last = curr;
- curr = nextContinuation(curr);
- }
-
- if (!beforeChild && !last->firstChild())
- return nextToLast;
- return last;
-}
-
-static bool newChildIsInline(const RenderObject& newChild, const RenderInline& parent)
-{
- // inline parent generates inline-table.
- return newChild.isInline() | (parent.childRequiresTable(newChild) && parent.style().display() == INLINE);
-}
-
void RenderInline::addChildIgnoringContinuation(RenderTreeBuilder& builder, RenderPtr<RenderObject> newChild, RenderObject* beforeChild)
{
- // Make sure we don't append things after :after-generated content if we have it.
- if (!beforeChild && isAfterContent(lastChild()))
- beforeChild = lastChild();
-
- bool childInline = newChildIsInline(*newChild, *this);
- // This code is for the old block-inside-inline model that uses continuations.
- if (!childInline && !newChild->isFloatingOrOutOfFlowPositioned()) {
- // We are placing a block inside an inline. We have to perform a split of this
- // inline into continuations. This involves creating an anonymous block box to hold
- // |newChild|. We then make that block box a continuation of this inline. We take all of
- // the children after |beforeChild| and put them in a clone of this object.
- auto newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK);
-
- // If inside an inline affected by in-flow positioning the block needs to be affected by it too.
- // Giving the block a layer like this allows it to collect the x/y offsets from inline parents later.
- if (auto positionedAncestor = inFlowPositionedInlineAncestor(this))
- newStyle.setPosition(positionedAncestor->style().position());
-
- auto newBox = createRenderer<RenderBlockFlow>(document(), WTFMove(newStyle));
- newBox->initializeStyle();
- newBox->setIsContinuation();
- RenderBoxModelObject* oldContinuation = continuation();
- if (oldContinuation)
- oldContinuation->removeFromContinuationChain();
- newBox->insertIntoContinuationChainAfter(*this);
-
- splitFlow(builder, beforeChild, WTFMove(newBox), WTFMove(newChild), oldContinuation);
- return;
- }
-
- auto& child = *newChild;
- RenderBoxModelObject::addChild(builder, WTFMove(newChild), beforeChild);
- child.setNeedsLayoutAndPrefWidthsRecalc();
+ builder.insertChildToRenderInlineIgnoringContinuation(*this, WTFMove(newChild), beforeChild);
}
-RenderPtr<RenderInline> RenderInline::cloneAsContinuation() const
-{
- RenderPtr<RenderInline> cloneInline = createRenderer<RenderInline>(*element(), RenderStyle::clone(style()));
- cloneInline->initializeStyle();
- cloneInline->setFragmentedFlowState(fragmentedFlowState());
- cloneInline->setHasOutlineAutoAncestor(hasOutlineAutoAncestor());
- cloneInline->setIsContinuation();
- return cloneInline;
-}
-
-void RenderInline::splitInlines(RenderTreeBuilder& builder, RenderBlock* fromBlock, RenderBlock* toBlock,
- RenderBlock* middleBlock,
- RenderObject* beforeChild, RenderBoxModelObject* oldCont)
-{
- // Create a clone of this inline.
- RenderPtr<RenderInline> cloneInline = cloneAsContinuation();
-#if ENABLE(FULLSCREEN_API)
- // If we're splitting the inline containing the fullscreened element,
- // |beforeChild| may be the renderer for the fullscreened element. However,
- // that renderer is wrapped in a RenderFullScreen, so |this| is not its
- // parent. Since the splitting logic expects |this| to be the parent, set
- // |beforeChild| to be the RenderFullScreen.
- const Element* fullScreenElement = document().webkitCurrentFullScreenElement();
- if (fullScreenElement && beforeChild && beforeChild->node() == fullScreenElement)
- beforeChild = document().fullScreenRenderer();
-#endif
- // Now take all of the children from beforeChild to the end and remove
- // them from |this| and place them in the clone.
- for (RenderObject* rendererToMove = beforeChild; rendererToMove;) {
- RenderObject* nextSibling = rendererToMove->nextSibling();
- // When anonymous wrapper is present, we might need to move the whole subtree instead.
- if (rendererToMove->parent() != this) {
- auto* anonymousParent = rendererToMove->parent();
- while (anonymousParent && anonymousParent->parent() != this) {
- ASSERT(anonymousParent->isAnonymous());
- anonymousParent = anonymousParent->parent();
- }
- if (!anonymousParent) {
- ASSERT_NOT_REACHED();
- break;
- }
- // If beforeChild is the first child in the subtree, we could just move the whole subtree.
- if (!rendererToMove->previousSibling()) {
- // Reparent the whole anonymous wrapper tree.
- rendererToMove = anonymousParent;
- // Skip to the next sibling that is not in this subtree.
- nextSibling = anonymousParent->nextSibling();
- } else if (!rendererToMove->nextSibling()) {
- // This is the last renderer in the subtree. We need to jump out of the wrapper subtree, so that
- // the siblings are getting reparented too.
- nextSibling = anonymousParent->nextSibling();
- }
- // Otherwise just move the renderer to the inline clone. Should the renderer need an anon
- // wrapper, the addChild() will generate one for it.
- // FIXME: When the anonymous wrapper has multiple children, we end up traversing up to the topmost wrapper
- // every time, which is a bit wasteful.
- }
- auto childToMove = rendererToMove->parent()->takeChildInternal(*rendererToMove);
- cloneInline->addChildIgnoringContinuation(builder, WTFMove(childToMove));
- rendererToMove->setNeedsLayoutAndPrefWidthsRecalc();
- rendererToMove = nextSibling;
- }
- // Hook |clone| up as the continuation of the middle block.
- cloneInline->insertIntoContinuationChainAfter(*middleBlock);
- if (oldCont)
- oldCont->insertIntoContinuationChainAfter(*cloneInline);
-
- // We have been reparented and are now under the fromBlock. We need
- // to walk up our inline parent chain until we hit the containing block.
- // Once we hit the containing block we're done.
- RenderBoxModelObject* current = downcast<RenderBoxModelObject>(parent());
- RenderBoxModelObject* currentChild = this;
-
- // FIXME: Because splitting is O(n^2) as tags nest pathologically, we cap the depth at which we're willing to clone.
- // There will eventually be a better approach to this problem that will let us nest to a much
- // greater depth (see bugzilla bug 13430) but for now we have a limit. This *will* result in
- // incorrect rendering, but the alternative is to hang forever.
- unsigned splitDepth = 1;
- const unsigned cMaxSplitDepth = 200;
- while (current && current != fromBlock) {
- if (splitDepth < cMaxSplitDepth) {
- // Create a new clone.
- RenderPtr<RenderInline> cloneChild = WTFMove(cloneInline);
- cloneInline = downcast<RenderInline>(*current).cloneAsContinuation();
-
- // Insert our child clone as the first child.
- cloneInline->addChildIgnoringContinuation(builder, WTFMove(cloneChild));
-
- // Hook the clone up as a continuation of |curr|.
- cloneInline->insertIntoContinuationChainAfter(*current);
-
- // Now we need to take all of the children starting from the first child
- // *after* currentChild and append them all to the clone.
- for (auto* sibling = currentChild->nextSibling(); sibling;) {
- auto* next = sibling->nextSibling();
- auto childToMove = current->takeChildInternal(*sibling);
- cloneInline->addChildIgnoringContinuation(builder, WTFMove(childToMove));
- sibling->setNeedsLayoutAndPrefWidthsRecalc();
- sibling = next;
- }
- }
-
- // Keep walking up the chain.
- currentChild = current;
- current = downcast<RenderBoxModelObject>(current->parent());
- ++splitDepth;
- }
-
- // Clear the flow thread containing blocks cached during the detached state insertions.
- for (auto& cloneBlockChild : childrenOfType<RenderBlock>(*cloneInline))
- cloneBlockChild.resetEnclosingFragmentedFlowAndChildInfoIncludingDescendants();
-
- // Now we are at the block level. We need to put the clone into the toBlock.
- toBlock->insertChildInternal(WTFMove(cloneInline), nullptr);
-
- // Now take all the children after currentChild and remove them from the fromBlock
- // and put them in the toBlock.
- for (auto* current = currentChild->nextSibling(); current;) {
- auto* next = current->nextSibling();
- auto childToMove = fromBlock->takeChildInternal(*current);
- toBlock->insertChildInternal(WTFMove(childToMove), nullptr);
- current = next;
- }
-}
-
-void RenderInline::splitFlow(RenderTreeBuilder& builder, RenderObject* beforeChild, RenderPtr<RenderBlock> newBlockBox, RenderPtr<RenderObject> newChild, RenderBoxModelObject* oldCont)
-{
- auto& addedBlockBox = *newBlockBox;
- RenderBlock* pre = nullptr;
- RenderBlock* block = containingBlock();
-
- // Delete our line boxes before we do the inline split into continuations.
- block->deleteLines();
-
- RenderPtr<RenderBlock> createdPre;
- bool madeNewBeforeBlock = false;
- if (block->isAnonymousBlock() && (!block->parent() || !block->parent()->createsAnonymousWrapper())) {
- // We can reuse this block and make it the preBlock of the next continuation.
- pre = block;
- pre->removePositionedObjects(nullptr);
- // FIXME-BLOCKFLOW: The enclosing method should likely be switched over
- // to only work on RenderBlockFlow, in which case this conversion can be
- // removed.
- if (is<RenderBlockFlow>(*pre))
- downcast<RenderBlockFlow>(*pre).removeFloatingObjects();
- block = block->containingBlock();
- } else {
- // No anonymous block available for use. Make one.
- createdPre = block->createAnonymousBlock();
- pre = createdPre.get();
- madeNewBeforeBlock = true;
- }
-
- auto createdPost = pre->createAnonymousBoxWithSameTypeAs(*block);
- auto& post = downcast<RenderBlock>(*createdPost);
-
- RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
- if (createdPre)
- block->insertChildInternal(WTFMove(createdPre), boxFirst);
- block->insertChildInternal(WTFMove(newBlockBox), boxFirst);
- block->insertChildInternal(WTFMove(createdPost), boxFirst);
- block->setChildrenInline(false);
-
- if (madeNewBeforeBlock) {
- RenderObject* o = boxFirst;
- while (o) {
- RenderObject* no = o;
- o = no->nextSibling();
- auto childToMove = block->takeChildInternal(*no);
- pre->insertChildInternal(WTFMove(childToMove), nullptr);
- no->setNeedsLayoutAndPrefWidthsRecalc();
- }
- }
-
- splitInlines(builder, pre, &post, &addedBlockBox, beforeChild, oldCont);
-
- // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
- // time in makeChildrenNonInline by just setting this explicitly up front.
- addedBlockBox.setChildrenInline(false);
-
- // We delayed adding the newChild until now so that the |newBlockBox| would be fully
- // connected, thus allowing newChild access to a renderArena should it need
- // to wrap itself in additional boxes (e.g., table construction).
- builder.insertChild(addedBlockBox, WTFMove(newChild));
-
- // Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
- // get deleted properly. Because objects moves from the pre block into the post block, we want to
- // make new line boxes instead of leaving the old line boxes around.
- pre->setNeedsLayoutAndPrefWidthsRecalc();
- block->setNeedsLayoutAndPrefWidthsRecalc();
- post.setNeedsLayoutAndPrefWidthsRecalc();
-}
-
-static bool canUseAsParentForContinuation(const RenderObject* renderer)
-{
- if (!renderer)
- return false;
- if (!is<RenderBlock>(renderer) && renderer->isAnonymous())
- return false;
- if (is<RenderTable>(renderer))
- return false;
- return true;
-}
-
-void RenderInline::addChildToContinuation(RenderTreeBuilder& builder, RenderPtr<RenderObject> newChild, RenderObject* beforeChild)
-{
- auto* flow = continuationBefore(beforeChild);
- // It may or may not be the direct parent of the beforeChild.
- RenderBoxModelObject* beforeChildAncestor = nullptr;
- if (!beforeChild) {
- auto* continuation = nextContinuation(flow);
- beforeChildAncestor = continuation ? continuation : flow;
- } else if (canUseAsParentForContinuation(beforeChild->parent()))
- beforeChildAncestor = downcast<RenderBoxModelObject>(beforeChild->parent());
- else if (beforeChild->parent()) {
- // In case of anonymous wrappers, the parent of the beforeChild is mostly irrelevant. What we need is the topmost wrapper.
- auto* parent = beforeChild->parent();
- while (parent && parent->parent() && parent->parent()->isAnonymous()) {
- // The ancestor candidate needs to be inside the continuation.
- if (parent->isContinuation())
- break;
- parent = parent->parent();
- }
- ASSERT(parent && parent->parent());
- beforeChildAncestor = downcast<RenderBoxModelObject>(parent->parent());
- } else
- ASSERT_NOT_REACHED();
-
- if (newChild->isFloatingOrOutOfFlowPositioned())
- return beforeChildAncestor->addChildIgnoringContinuation(builder, WTFMove(newChild), beforeChild);
-
- if (flow == beforeChildAncestor)
- return flow->addChildIgnoringContinuation(builder, WTFMove(newChild), beforeChild);
- // A continuation always consists of two potential candidates: an inline or an anonymous
- // block box holding block children.
- bool childInline = newChildIsInline(*newChild, *this);
- // The goal here is to match up if we can, so that we can coalesce and create the
- // minimal # of continuations needed for the inline.
- if (childInline == beforeChildAncestor->isInline())
- return beforeChildAncestor->addChildIgnoringContinuation(builder, WTFMove(newChild), beforeChild);
- if (flow->isInline() == childInline)
- return flow->addChildIgnoringContinuation(builder, WTFMove(newChild)); // Just treat like an append.
- return beforeChildAncestor->addChildIgnoringContinuation(builder, WTFMove(newChild), beforeChild);
-}
-
void RenderInline::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
m_lineBoxes.paint(this, paintInfo, paintOffset);
@@ -1369,7 +1047,7 @@
newBox->insertIntoContinuationChainAfter(*this);
RenderObject* beforeChild = child.nextSibling();
auto removedChild = takeChildInternal(child);
- splitFlow(*RenderTreeBuilder::current(), beforeChild, WTFMove(newBox), WTFMove(removedChild), oldContinuation);
+ RenderTreeBuilder::current()->splitFlow(*this, beforeChild, WTFMove(newBox), WTFMove(removedChild), oldContinuation);
}
void RenderInline::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
Modified: trunk/Source/WebCore/rendering/RenderInline.h (226519 => 226520)
--- trunk/Source/WebCore/rendering/RenderInline.h 2018-01-08 18:37:37 UTC (rev 226519)
+++ trunk/Source/WebCore/rendering/RenderInline.h 2018-01-08 18:38:31 UTC (rev 226520)
@@ -94,6 +94,8 @@
bool hitTestCulledInline(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset);
+ void addChildIgnoringContinuation(RenderTreeBuilder&, RenderPtr<RenderObject> newChild, RenderObject* beforeChild = nullptr) final;
+
protected:
void willBeDestroyed() override;
@@ -116,12 +118,6 @@
template<typename GeneratorContext>
void generateCulledLineBoxRects(GeneratorContext& yield, const RenderInline* container) const;
- void addChildToContinuation(RenderTreeBuilder&, RenderPtr<RenderObject> newChild, RenderObject* beforeChild);
- void addChildIgnoringContinuation(RenderTreeBuilder&, RenderPtr<RenderObject> newChild, RenderObject* beforeChild = nullptr) final;
-
- void splitInlines(RenderTreeBuilder&, RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock, RenderObject* beforeChild, RenderBoxModelObject* oldCont);
- void splitFlow(RenderTreeBuilder&, RenderObject* beforeChild, RenderPtr<RenderBlock> newBlockBox, RenderPtr<RenderObject> newChild, RenderBoxModelObject* oldCont);
-
void layout() final { ASSERT_NOT_REACHED(); } // Do nothing for layout()
void paint(PaintInfo&, const LayoutPoint&) final;
@@ -162,11 +158,8 @@
#if ENABLE(DASHBOARD_SUPPORT)
void addAnnotatedRegions(Vector<AnnotatedRegionValue>&) final;
#endif
-
- RenderPtr<RenderInline> cloneAsContinuation() const;
void paintOutlineForLine(GraphicsContext&, const LayoutPoint&, const LayoutRect& prevLine, const LayoutRect& thisLine, const LayoutRect& nextLine, const Color&);
- RenderBoxModelObject* continuationBefore(RenderObject* beforeChild);
bool willChangeCreatesStackingContext() const
{
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp (226519 => 226520)
--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp 2018-01-08 18:37:37 UTC (rev 226519)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp 2018-01-08 18:38:31 UTC (rev 226520)
@@ -36,6 +36,7 @@
#include "RenderTreeBuilderBlock.h"
#include "RenderTreeBuilderFirstLetter.h"
#include "RenderTreeBuilderFormControls.h"
+#include "RenderTreeBuilderInline.h"
#include "RenderTreeBuilderList.h"
#include "RenderTreeBuilderMultiColumn.h"
#include "RenderTreeBuilderRuby.h"
@@ -107,6 +108,7 @@
, m_rubyBuilder(std::make_unique<Ruby>(*this))
, m_formControlsBuilder(std::make_unique<FormControls>(*this))
, m_blockBuilder(std::make_unique<Block>(*this))
+ , m_inlineBuilder(std::make_unique<Inline>(*this))
{
RELEASE_ASSERT(!s_current || &m_view != &s_current->m_view);
m_previous = s_current;
@@ -272,6 +274,21 @@
return beforeChild;
}
+void RenderTreeBuilder::insertChildToRenderInline(RenderInline& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
+{
+ inlineBuilder().insertChild(parent, WTFMove(child), beforeChild);
+}
+
+void RenderTreeBuilder::insertChildToRenderInlineIgnoringContinuation(RenderInline& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
+{
+ inlineBuilder().insertChildIgnoringContinuation(parent, WTFMove(child), beforeChild);
+}
+
+void RenderTreeBuilder::splitFlow(RenderInline& parent, RenderObject* beforeChild, RenderPtr<RenderBlock> newBlockBox, RenderPtr<RenderObject> child, RenderBoxModelObject* oldCont)
+{
+ inlineBuilder().splitFlow(parent, beforeChild, WTFMove(newBlockBox), WTFMove(child), oldCont);
+}
+
void RenderTreeBuilder::updateAfterDescendants(RenderElement& renderer)
{
if (is<RenderBlock>(renderer))
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.h (226519 => 226520)
--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.h 2018-01-08 18:37:37 UTC (rev 226519)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.h 2018-01-08 18:38:31 UTC (rev 226520)
@@ -52,6 +52,11 @@
void makeChildrenNonInline(RenderBlock& parent, RenderObject* insertionPoint = nullptr);
RenderObject* splitAnonymousBoxesAroundChild(RenderBox& parent, RenderObject* beforeChild);
+ // These functions are temporary until after all block/inline/continuation code is moved over.
+ void insertChildToRenderInline(RenderInline& parent, RenderPtr<RenderObject>, RenderObject* beforeChild = nullptr);
+ void insertChildToRenderInlineIgnoringContinuation(RenderInline& parent, RenderPtr<RenderObject>, RenderObject* beforeChild = nullptr);
+ void splitFlow(RenderInline& parent, RenderObject* beforeChild, RenderPtr<RenderBlock> newBlockBox, RenderPtr<RenderObject> child, RenderBoxModelObject* oldCont);
+
private:
class FirstLetter;
class List;
@@ -60,6 +65,7 @@
class Ruby;
class FormControls;
class Block;
+ class Inline;
FirstLetter& firstLetterBuilder() { return *m_firstLetterBuilder; }
List& listBuilder() { return *m_listBuilder; }
@@ -68,6 +74,7 @@
Ruby& rubyBuilder() { return *m_rubyBuilder; }
FormControls& formControlsBuilder() { return *m_formControlsBuilder; }
Block& blockBuilder() { return *m_blockBuilder; }
+ Inline& inlineBuilder() { return *m_inlineBuilder; }
RenderView& m_view;
@@ -81,6 +88,7 @@
std::unique_ptr<Ruby> m_rubyBuilder;
std::unique_ptr<FormControls> m_formControlsBuilder;
std::unique_ptr<Block> m_blockBuilder;
+ std::unique_ptr<Inline> m_inlineBuilder;
};
}
Added: trunk/Source/WebCore/rendering/updating/RenderTreeBuilderInline.cpp (0 => 226520)
--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilderInline.cpp (rev 0)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilderInline.cpp 2018-01-08 18:38:31 UTC (rev 226520)
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderTreeBuilderInline.h"
+
+#include "RenderChildIterator.h"
+#include "RenderFullScreen.h"
+#include "RenderInline.h"
+#include "RenderTable.h"
+
+namespace WebCore {
+
+static bool canUseAsParentForContinuation(const RenderObject* renderer)
+{
+ if (!renderer)
+ return false;
+ if (!is<RenderBlock>(renderer) && renderer->isAnonymous())
+ return false;
+ if (is<RenderTable>(renderer))
+ return false;
+ return true;
+}
+
+static RenderBoxModelObject* nextContinuation(RenderObject* renderer)
+{
+ if (is<RenderInline>(*renderer) && !renderer->isReplaced())
+ return downcast<RenderInline>(*renderer).continuation();
+ return downcast<RenderBlock>(*renderer).inlineContinuation();
+}
+
+static RenderBoxModelObject* continuationBefore(RenderInline& parent, RenderObject* beforeChild)
+{
+ if (beforeChild && beforeChild->parent() == &parent)
+ return &parent;
+
+ RenderBoxModelObject* curr = nextContinuation(&parent);
+ RenderBoxModelObject* nextToLast = &parent;
+ RenderBoxModelObject* last = &parent;
+ while (curr) {
+ if (beforeChild && beforeChild->parent() == curr) {
+ if (curr->firstChild() == beforeChild)
+ return last;
+ return curr;
+ }
+
+ nextToLast = last;
+ last = curr;
+ curr = nextContinuation(curr);
+ }
+
+ if (!beforeChild && !last->firstChild())
+ return nextToLast;
+ return last;
+}
+
+static RenderPtr<RenderInline> cloneAsContinuation(RenderInline& renderer)
+{
+ RenderPtr<RenderInline> cloneInline = createRenderer<RenderInline>(*renderer.element(), RenderStyle::clone(renderer.style()));
+ cloneInline->initializeStyle();
+ cloneInline->setFragmentedFlowState(renderer.fragmentedFlowState());
+ cloneInline->setHasOutlineAutoAncestor(renderer.hasOutlineAutoAncestor());
+ cloneInline->setIsContinuation();
+ return cloneInline;
+}
+
+static bool newChildIsInline(const RenderObject& child, const RenderInline& parent)
+{
+ // inline parent generates inline-table.
+ return child.isInline() | (parent.childRequiresTable(child) && parent.style().display() == INLINE);
+}
+
+static RenderElement* inFlowPositionedInlineAncestor(RenderElement& renderer)
+{
+ auto* ancestor = &renderer;
+ while (ancestor && ancestor->isRenderInline()) {
+ if (ancestor->isInFlowPositioned())
+ return ancestor;
+ ancestor = ancestor->parent();
+ }
+ return nullptr;
+}
+
+RenderTreeBuilder::Inline::Inline(RenderTreeBuilder& builder)
+ : m_builder(builder)
+{
+}
+
+void RenderTreeBuilder::Inline::insertChild(RenderInline& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
+{
+ auto* beforeChildOrPlaceholder = beforeChild;
+ if (auto* fragmentedFlow = parent.enclosingFragmentedFlow())
+ beforeChildOrPlaceholder = fragmentedFlow->resolveMovedChild(beforeChild);
+ if (parent.continuation()) {
+ insertChildToContinuation(parent, WTFMove(child), beforeChildOrPlaceholder);
+ return;
+ }
+ insertChildIgnoringContinuation(parent, WTFMove(child), beforeChildOrPlaceholder);
+}
+
+void RenderTreeBuilder::Inline::insertChildToContinuation(RenderInline& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
+{
+ auto* flow = continuationBefore(parent, beforeChild);
+ // It may or may not be the direct parent of the beforeChild.
+ RenderBoxModelObject* beforeChildAncestor = nullptr;
+ if (!beforeChild) {
+ auto* continuation = nextContinuation(flow);
+ beforeChildAncestor = continuation ? continuation : flow;
+ } else if (canUseAsParentForContinuation(beforeChild->parent()))
+ beforeChildAncestor = downcast<RenderBoxModelObject>(beforeChild->parent());
+ else if (beforeChild->parent()) {
+ // In case of anonymous wrappers, the parent of the beforeChild is mostly irrelevant. What we need is the topmost wrapper.
+ auto* parent = beforeChild->parent();
+ while (parent && parent->parent() && parent->parent()->isAnonymous()) {
+ // The ancestor candidate needs to be inside the continuation.
+ if (parent->isContinuation())
+ break;
+ parent = parent->parent();
+ }
+ ASSERT(parent && parent->parent());
+ beforeChildAncestor = downcast<RenderBoxModelObject>(parent->parent());
+ } else
+ ASSERT_NOT_REACHED();
+
+ if (child->isFloatingOrOutOfFlowPositioned())
+ return beforeChildAncestor->addChildIgnoringContinuation(m_builder, WTFMove(child), beforeChild);
+
+ if (flow == beforeChildAncestor)
+ return flow->addChildIgnoringContinuation(m_builder, WTFMove(child), beforeChild);
+ // A continuation always consists of two potential candidates: an inline or an anonymous
+ // block box holding block children.
+ bool childInline = newChildIsInline(*child, parent);
+ // The goal here is to match up if we can, so that we can coalesce and create the
+ // minimal # of continuations needed for the inline.
+ if (childInline == beforeChildAncestor->isInline())
+ return beforeChildAncestor->addChildIgnoringContinuation(m_builder, WTFMove(child), beforeChild);
+ if (flow->isInline() == childInline)
+ return flow->addChildIgnoringContinuation(m_builder, WTFMove(child)); // Just treat like an append.
+ return beforeChildAncestor->addChildIgnoringContinuation(m_builder, WTFMove(child), beforeChild);
+}
+
+void RenderTreeBuilder::Inline::insertChildIgnoringContinuation(RenderInline& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
+{
+ // Make sure we don't append things after :after-generated content if we have it.
+ if (!beforeChild && parent.isAfterContent(parent.lastChild()))
+ beforeChild = parent.lastChild();
+
+ bool childInline = newChildIsInline(*child, parent);
+ // This code is for the old block-inside-inline model that uses continuations.
+ if (!childInline && !child->isFloatingOrOutOfFlowPositioned()) {
+ // We are placing a block inside an inline. We have to perform a split of this
+ // inline into continuations. This involves creating an anonymous block box to hold
+ // |newChild|. We then make that block box a continuation of this inline. We take all of
+ // the children after |beforeChild| and put them in a clone of this object.
+ auto newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent.style(), BLOCK);
+
+ // If inside an inline affected by in-flow positioning the block needs to be affected by it too.
+ // Giving the block a layer like this allows it to collect the x/y offsets from inline parents later.
+ if (auto positionedAncestor = inFlowPositionedInlineAncestor(parent))
+ newStyle.setPosition(positionedAncestor->style().position());
+
+ auto newBox = createRenderer<RenderBlockFlow>(parent.document(), WTFMove(newStyle));
+ newBox->initializeStyle();
+ newBox->setIsContinuation();
+ RenderBoxModelObject* oldContinuation = parent.continuation();
+ if (oldContinuation)
+ oldContinuation->removeFromContinuationChain();
+ newBox->insertIntoContinuationChainAfter(parent);
+
+ splitFlow(parent, beforeChild, WTFMove(newBox), WTFMove(child), oldContinuation);
+ return;
+ }
+
+ auto& childToAdd = *child;
+ parent.RenderBoxModelObject::addChild(m_builder, WTFMove(child), beforeChild);
+ childToAdd.setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+void RenderTreeBuilder::Inline::splitFlow(RenderInline& parent, RenderObject* beforeChild, RenderPtr<RenderBlock> newBlockBox, RenderPtr<RenderObject> child, RenderBoxModelObject* oldCont)
+{
+ auto& addedBlockBox = *newBlockBox;
+ RenderBlock* pre = nullptr;
+ RenderBlock* block = parent.containingBlock();
+
+ // Delete our line boxes before we do the inline split into continuations.
+ block->deleteLines();
+
+ RenderPtr<RenderBlock> createdPre;
+ bool madeNewBeforeBlock = false;
+ if (block->isAnonymousBlock() && (!block->parent() || !block->parent()->createsAnonymousWrapper())) {
+ // We can reuse this block and make it the preBlock of the next continuation.
+ pre = block;
+ pre->removePositionedObjects(nullptr);
+ // FIXME-BLOCKFLOW: The enclosing method should likely be switched over
+ // to only work on RenderBlockFlow, in which case this conversion can be
+ // removed.
+ if (is<RenderBlockFlow>(*pre))
+ downcast<RenderBlockFlow>(*pre).removeFloatingObjects();
+ block = block->containingBlock();
+ } else {
+ // No anonymous block available for use. Make one.
+ createdPre = block->createAnonymousBlock();
+ pre = createdPre.get();
+ madeNewBeforeBlock = true;
+ }
+
+ auto createdPost = pre->createAnonymousBoxWithSameTypeAs(*block);
+ auto& post = downcast<RenderBlock>(*createdPost);
+
+ RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
+ if (createdPre)
+ block->insertChildInternal(WTFMove(createdPre), boxFirst);
+ block->insertChildInternal(WTFMove(newBlockBox), boxFirst);
+ block->insertChildInternal(WTFMove(createdPost), boxFirst);
+ block->setChildrenInline(false);
+
+ if (madeNewBeforeBlock) {
+ RenderObject* o = boxFirst;
+ while (o) {
+ RenderObject* no = o;
+ o = no->nextSibling();
+ auto childToMove = block->takeChildInternal(*no);
+ pre->insertChildInternal(WTFMove(childToMove), nullptr);
+ no->setNeedsLayoutAndPrefWidthsRecalc();
+ }
+ }
+
+ splitInlines(parent, pre, &post, &addedBlockBox, beforeChild, oldCont);
+
+ // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
+ // time in makeChildrenNonInline by just setting this explicitly up front.
+ addedBlockBox.setChildrenInline(false);
+
+ // We delayed adding the newChild until now so that the |newBlockBox| would be fully
+ // connected, thus allowing newChild access to a renderArena should it need
+ // to wrap itself in additional boxes (e.g., table construction).
+ m_builder.insertChild(addedBlockBox, WTFMove(child));
+
+ // Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
+ // get deleted properly. Because objects moves from the pre block into the post block, we want to
+ // make new line boxes instead of leaving the old line boxes around.
+ pre->setNeedsLayoutAndPrefWidthsRecalc();
+ block->setNeedsLayoutAndPrefWidthsRecalc();
+ post.setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+void RenderTreeBuilder::Inline::splitInlines(RenderInline& parent, RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock, RenderObject* beforeChild, RenderBoxModelObject* oldCont)
+{
+ // Create a clone of this inline.
+ RenderPtr<RenderInline> cloneInline = cloneAsContinuation(parent);
+#if ENABLE(FULLSCREEN_API)
+ // If we're splitting the inline containing the fullscreened element,
+ // |beforeChild| may be the renderer for the fullscreened element. However,
+ // that renderer is wrapped in a RenderFullScreen, so |this| is not its
+ // parent. Since the splitting logic expects |this| to be the parent, set
+ // |beforeChild| to be the RenderFullScreen.
+ const Element* fullScreenElement = parent.document().webkitCurrentFullScreenElement();
+ if (fullScreenElement && beforeChild && beforeChild->node() == fullScreenElement)
+ beforeChild = parent.document().fullScreenRenderer();
+#endif
+ // Now take all of the children from beforeChild to the end and remove
+ // them from |this| and place them in the clone.
+ for (RenderObject* rendererToMove = beforeChild; rendererToMove;) {
+ RenderObject* nextSibling = rendererToMove->nextSibling();
+ // When anonymous wrapper is present, we might need to move the whole subtree instead.
+ if (rendererToMove->parent() != &parent) {
+ auto* anonymousParent = rendererToMove->parent();
+ while (anonymousParent && anonymousParent->parent() != &parent) {
+ ASSERT(anonymousParent->isAnonymous());
+ anonymousParent = anonymousParent->parent();
+ }
+ if (!anonymousParent) {
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ // If beforeChild is the first child in the subtree, we could just move the whole subtree.
+ if (!rendererToMove->previousSibling()) {
+ // Reparent the whole anonymous wrapper tree.
+ rendererToMove = anonymousParent;
+ // Skip to the next sibling that is not in this subtree.
+ nextSibling = anonymousParent->nextSibling();
+ } else if (!rendererToMove->nextSibling()) {
+ // This is the last renderer in the subtree. We need to jump out of the wrapper subtree, so that
+ // the siblings are getting reparented too.
+ nextSibling = anonymousParent->nextSibling();
+ }
+ // Otherwise just move the renderer to the inline clone. Should the renderer need an anon
+ // wrapper, the addChild() will generate one for it.
+ // FIXME: When the anonymous wrapper has multiple children, we end up traversing up to the topmost wrapper
+ // every time, which is a bit wasteful.
+ }
+ auto childToMove = rendererToMove->parent()->takeChildInternal(*rendererToMove);
+ cloneInline->addChildIgnoringContinuation(m_builder, WTFMove(childToMove));
+ rendererToMove->setNeedsLayoutAndPrefWidthsRecalc();
+ rendererToMove = nextSibling;
+ }
+ // Hook |clone| up as the continuation of the middle block.
+ cloneInline->insertIntoContinuationChainAfter(*middleBlock);
+ if (oldCont)
+ oldCont->insertIntoContinuationChainAfter(*cloneInline);
+
+ // We have been reparented and are now under the fromBlock. We need
+ // to walk up our inline parent chain until we hit the containing block.
+ // Once we hit the containing block we're done.
+ RenderBoxModelObject* current = downcast<RenderBoxModelObject>(parent.parent());
+ RenderBoxModelObject* currentChild = &parent;
+
+ // FIXME: Because splitting is O(n^2) as tags nest pathologically, we cap the depth at which we're willing to clone.
+ // There will eventually be a better approach to this problem that will let us nest to a much
+ // greater depth (see bugzilla bug 13430) but for now we have a limit. This *will* result in
+ // incorrect rendering, but the alternative is to hang forever.
+ unsigned splitDepth = 1;
+ const unsigned cMaxSplitDepth = 200;
+ while (current && current != fromBlock) {
+ if (splitDepth < cMaxSplitDepth) {
+ // Create a new clone.
+ RenderPtr<RenderInline> cloneChild = WTFMove(cloneInline);
+ cloneInline = cloneAsContinuation(downcast<RenderInline>(*current));
+
+ // Insert our child clone as the first child.
+ cloneInline->addChildIgnoringContinuation(m_builder, WTFMove(cloneChild));
+
+ // Hook the clone up as a continuation of |curr|.
+ cloneInline->insertIntoContinuationChainAfter(*current);
+
+ // Now we need to take all of the children starting from the first child
+ // *after* currentChild and append them all to the clone.
+ for (auto* sibling = currentChild->nextSibling(); sibling;) {
+ auto* next = sibling->nextSibling();
+ auto childToMove = current->takeChildInternal(*sibling);
+ cloneInline->addChildIgnoringContinuation(m_builder, WTFMove(childToMove));
+ sibling->setNeedsLayoutAndPrefWidthsRecalc();
+ sibling = next;
+ }
+ }
+
+ // Keep walking up the chain.
+ currentChild = current;
+ current = downcast<RenderBoxModelObject>(current->parent());
+ ++splitDepth;
+ }
+
+ // Clear the flow thread containing blocks cached during the detached state insertions.
+ for (auto& cloneBlockChild : childrenOfType<RenderBlock>(*cloneInline))
+ cloneBlockChild.resetEnclosingFragmentedFlowAndChildInfoIncludingDescendants();
+
+ // Now we are at the block level. We need to put the clone into the toBlock.
+ toBlock->insertChildInternal(WTFMove(cloneInline), nullptr);
+
+ // Now take all the children after currentChild and remove them from the fromBlock
+ // and put them in the toBlock.
+ for (auto* current = currentChild->nextSibling(); current;) {
+ auto* next = current->nextSibling();
+ auto childToMove = fromBlock->takeChildInternal(*current);
+ toBlock->insertChildInternal(WTFMove(childToMove), nullptr);
+ current = next;
+ }
+}
+
+}
+
Copied: trunk/Source/WebCore/rendering/updating/RenderTreeBuilderInline.h (from rev 226519, trunk/Source/WebCore/rendering/updating/RenderTreeBuilderTable.h) (0 => 226520)
--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilderInline.h (rev 0)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilderInline.h 2018-01-08 18:38:31 UTC (rev 226520)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "RenderTreeBuilder.h"
+
+namespace WebCore {
+
+class RenderTreeBuilder::Inline {
+public:
+ Inline(RenderTreeBuilder&);
+
+ void insertChild(RenderInline& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild);
+ void insertChildIgnoringContinuation(RenderInline& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild);
+
+ // Make this private once all the mutation code is in RenderTreeBuilder.
+ void splitFlow(RenderInline& parent, RenderObject* beforeChild, RenderPtr<RenderBlock> newBlockBox, RenderPtr<RenderObject> child, RenderBoxModelObject* oldCont);
+
+private:
+ void insertChildToContinuation(RenderInline& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild);
+ void splitInlines(RenderInline& parent, RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock, RenderObject* beforeChild, RenderBoxModelObject* oldCont);
+
+ RenderTreeBuilder& m_builder;
+};
+
+}
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilderTable.h (226519 => 226520)
--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilderTable.h 2018-01-08 18:37:37 UTC (rev 226519)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilderTable.h 2018-01-08 18:38:31 UTC (rev 226520)
@@ -31,6 +31,8 @@
class RenderElement;
class RenderObject;
+class RenderTable;
+class RenderTableSection;
class RenderTableRow;
class RenderTreeBuilder;