Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(312)

Unified Diff: Source/WebCore/rendering/RenderBlock.cpp

Issue 10448067: Merge 117482 (Closed) Base URL: http://svn.webkit.org/repository/webkit/branches/chromium/1132/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/WebCore/rendering/RenderBlock.h ('k') | Source/WebCore/rendering/RenderBox.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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)
« no previous file with comments | « Source/WebCore/rendering/RenderBlock.h ('k') | Source/WebCore/rendering/RenderBox.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698