| Index: Source/WebCore/rendering/RenderBlock.cpp
|
| ===================================================================
|
| --- Source/WebCore/rendering/RenderBlock.cpp (revision 118862)
|
| +++ Source/WebCore/rendering/RenderBlock.cpp (working copy)
|
| @@ -932,6 +932,14 @@
|
| }
|
|
|
| RenderBox::addChild(newChild, beforeChild);
|
| +
|
| + // Handle positioning of run-ins.
|
| + if (newChild->isRunIn())
|
| + moveRunInUnderSiblingBlockIfNeeded(newChild);
|
| + else if (RenderObject* prevSibling = newChild->previousSibling()) {
|
| + if (prevSibling->isRunIn())
|
| + moveRunInUnderSiblingBlockIfNeeded(prevSibling);
|
| + }
|
|
|
| if (madeBoxesNonInline && parent() && isAnonymousBlock() && parent()->isRenderBlock())
|
| toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
|
| @@ -1038,6 +1046,13 @@
|
| if (!child)
|
| return;
|
|
|
| + // Since we are going to have block children, we have to move
|
| + // back the run-in to its original place.
|
| + if (child->isRunIn()) {
|
| + moveRunInToOriginalPosition(child);
|
| + child = firstChild();
|
| + }
|
| +
|
| deleteLineBoxTree();
|
|
|
| while (child) {
|
| @@ -1724,8 +1739,7 @@
|
| {
|
| // Handle in the given order
|
| return handlePositionedChild(child, marginInfo)
|
| - || handleFloatingChild(child, marginInfo)
|
| - || handleRunInChild(child);
|
| + || handleFloatingChild(child, marginInfo);
|
| }
|
|
|
|
|
| @@ -1749,77 +1763,115 @@
|
| return false;
|
| }
|
|
|
| -bool RenderBlock::handleRunInChild(RenderBox* child)
|
| +static void destroyRunIn(RenderBoxModelObject* runIn)
|
| {
|
| - // See if we have a run-in element with inline children. If the
|
| - // children aren't inline, then just treat the run-in as a normal
|
| - // block.
|
| - if (!child->isRunIn() || !child->childrenInline())
|
| - return false;
|
| + ASSERT(runIn->isRunIn());
|
| + ASSERT(!runIn->firstChild());
|
|
|
| + // If it is a block run-in, delete its line box tree as well. This is needed as our
|
| + // children got moved and our line box tree is no longer valid.
|
| + if (runIn->isRenderBlock())
|
| + toRenderBlock(runIn)->deleteLineBoxTree();
|
| + runIn->destroy();
|
| +}
|
| +
|
| +RenderBoxModelObject* RenderBlock::createReplacementRunIn(RenderBoxModelObject* runIn)
|
| +{
|
| + ASSERT(runIn->isRunIn());
|
| +
|
| + // First we destroy any :before/:after content. It will be regenerated by the new run-in.
|
| + // Exception is if the run-in itself is generated.
|
| + if (runIn->style()->styleType() != BEFORE && runIn->style()->styleType() != AFTER) {
|
| + RenderObject* generatedContent;
|
| + if (runIn->getCachedPseudoStyle(BEFORE) && (generatedContent = runIn->beforePseudoElementRenderer()))
|
| + generatedContent->destroy();
|
| + if (runIn->getCachedPseudoStyle(AFTER) && (generatedContent = runIn->afterPseudoElementRenderer()))
|
| + generatedContent->destroy();
|
| + }
|
| +
|
| + bool newRunInShouldBeBlock = !runIn->isRenderBlock();
|
| + Node* runInNode = runIn->node();
|
| + RenderBoxModelObject* newRunIn = 0;
|
| + if (newRunInShouldBeBlock)
|
| + newRunIn = new (renderArena()) RenderBlock(runInNode ? runInNode : document());
|
| + else
|
| + newRunIn = new (renderArena()) RenderInline(runInNode ? runInNode : document());
|
| + newRunIn->setStyle(runIn->style());
|
| +
|
| + runIn->moveAllChildrenTo(newRunIn, true);
|
| +
|
| + // If the run-in had an element, we need to set the new renderer.
|
| + if (runInNode)
|
| + runInNode->setRenderer(newRunIn);
|
| +
|
| + return newRunIn;
|
| +}
|
| +
|
| +void RenderBlock::moveRunInUnderSiblingBlockIfNeeded(RenderObject* runIn)
|
| +{
|
| + ASSERT(runIn->isRunIn());
|
| +
|
| + // See if we have inline children. If the children aren't inline,
|
| + // then just treat the run-in as a normal block.
|
| + if (!runIn->childrenInline())
|
| + return;
|
| +
|
| // FIXME: We don't handle non-block elements with run-in for now.
|
| - if (!child->isRenderBlock())
|
| - return false;
|
| + if (!runIn->isRenderBlock())
|
| + return;
|
|
|
| - // Run-in child shouldn't intrude into the sibling block if it is part of a
|
| + // We shouldn't run in into the sibling block if we are part of a
|
| // continuation chain. In that case, treat it as a normal block.
|
| - if (child->isElementContinuation() || child->virtualContinuation())
|
| - return false;
|
| + if (runIn->isElementContinuation() || runIn->virtualContinuation())
|
| + return;
|
|
|
| // Check if this node is allowed to run-in. E.g. <select> expects its renderer to
|
| // be a RenderListBox or RenderMenuList, and hence cannot be a RenderInline run-in.
|
| - Node* runInNode = child->node();
|
| + Node* runInNode = runIn->node();
|
| if (runInNode && runInNode->hasTagName(selectTag))
|
| - return false;
|
| + return;
|
|
|
| - RenderBlock* blockRunIn = toRenderBlock(child);
|
| - RenderObject* curr = blockRunIn->nextSibling();
|
| - if (!curr || !curr->isRenderBlock() || !curr->childrenInline() || curr->isRunIn() || curr->isAnonymous() || curr->isFloatingOrPositioned())
|
| - return false;
|
| + RenderObject* curr = runIn->nextSibling();
|
| + if (!curr || !curr->isRenderBlock() || !curr->childrenInline())
|
| + return;
|
|
|
| - RenderBlock* currBlock = toRenderBlock(curr);
|
| + // Per CSS3, "A run-in cannot run in to a block that already starts with a
|
| + // run-in or that itself is a run-in".
|
| + if (curr->isRunIn() || (curr->firstChild() && curr->firstChild()->isRunIn()))
|
| + return;
|
|
|
| - // First we destroy any :before/:after content. It will be regenerated by the new inline.
|
| - // Exception is if the run-in itself is generated.
|
| - if (child->style()->styleType() != BEFORE && child->style()->styleType() != AFTER) {
|
| - RenderObject* generatedContent;
|
| - if (child->getCachedPseudoStyle(BEFORE) && (generatedContent = child->beforePseudoElementRenderer()))
|
| - generatedContent->destroy();
|
| - if (child->getCachedPseudoStyle(AFTER) && (generatedContent = child->afterPseudoElementRenderer()))
|
| - generatedContent->destroy();
|
| - }
|
| + if (curr->isAnonymous() || curr->isFloatingOrPositioned())
|
| + return;
|
|
|
| - // Remove the old child.
|
| - children()->removeChildNode(this, blockRunIn);
|
| + RenderBoxModelObject* oldRunIn = toRenderBoxModelObject(runIn);
|
| + RenderBoxModelObject* newRunIn = createReplacementRunIn(oldRunIn);
|
| + destroyRunIn(oldRunIn);
|
|
|
| - // Create an inline.
|
| - RenderInline* inlineRunIn = new (renderArena()) RenderInline(runInNode ? runInNode : document());
|
| - inlineRunIn->setStyle(blockRunIn->style());
|
| + // Now insert the new child under |curr| block. Use addChild instead of insertChildNode
|
| + // since it handles correct placement of the children, especially where we cannot insert
|
| + // anything before the first child. e.g. details tag. See https://bugs.webkit.org/show_bug.cgi?id=58228.
|
| + curr->addChild(newRunIn, curr->firstChild());
|
| +}
|
|
|
| - // Move the nodes from the old child to the new child
|
| - for (RenderObject* runInChild = blockRunIn->firstChild(); runInChild;) {
|
| - RenderObject* nextSibling = runInChild->nextSibling();
|
| - blockRunIn->children()->removeChildNode(blockRunIn, runInChild);
|
| - inlineRunIn->addChild(runInChild); // Use addChild instead of appendChildNode since it handles correct placement of the children relative to :after-generated content.
|
| - runInChild = nextSibling;
|
| - }
|
| +void RenderBlock::moveRunInToOriginalPosition(RenderObject* runIn)
|
| +{
|
| + ASSERT(runIn->isRunIn());
|
|
|
| - // Now insert the new child under |currBlock|. Use addChild instead of insertChildNode since it handles correct placement of the children, esp where we cannot insert
|
| - // anything before the first child. e.g. details tag. See https://bugs.webkit.org/show_bug.cgi?id=58228.
|
| - currBlock->addChild(inlineRunIn, currBlock->firstChild());
|
| -
|
| - // If the run-in had an element, we need to set the new renderer.
|
| - if (runInNode)
|
| - runInNode->setRenderer(inlineRunIn);
|
| + // If we don't have a parent, there is nothing to move. This might
|
| + // happen if |this| got detached from parent after |runIn| run into |this|.
|
| + if (!parent())
|
| + return;
|
|
|
| - // Destroy the block run-in, which includes deleting its line box tree.
|
| - blockRunIn->deleteLineBoxTree();
|
| - blockRunIn->destroy();
|
| + // An intruded run-in needs to be an inline.
|
| + if (!runIn->isRenderInline())
|
| + return;
|
|
|
| - // The block acts like an inline, so just null out its
|
| - // position.
|
| -
|
| - return true;
|
| + RenderBoxModelObject* oldRunIn = toRenderBoxModelObject(runIn);
|
| + RenderBoxModelObject* newRunIn = createReplacementRunIn(oldRunIn);
|
| + destroyRunIn(oldRunIn);
|
| +
|
| + // Add the run-in block as our previous sibling.
|
| + parent()->addChild(newRunIn, this);
|
| }
|
|
|
| LayoutUnit RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
|
|
|