Chromium Code Reviews| Index: third_party/WebKit/Source/core/layout/LayoutBlock.cpp |
| diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp |
| index d7deb930e29466e1cd094b316bf2bca92eafb2f8..195c16568e7e844eeec7fe6f4c9dc04a35f4f880 100644 |
| --- a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp |
| +++ b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp |
| @@ -251,6 +251,85 @@ static bool borderOrPaddingLogicalDimensionChanged(const ComputedStyle& oldStyle |
| || oldStyle.paddingBottom() != newStyle.paddingBottom(); |
| } |
| +void LayoutBlock::collapseAnonymousBlockChildAfterMerge(LayoutObject* prev, LayoutObject* next, bool canMergeAnonymousBlocks) |
|
rhogan
2016/03/03 21:48:36
I don't see a good alternative to passing canMerge
|
| +{ |
| + if (!canCollapseAnonymousBlockChild()) |
| + return; |
| + |
| + LayoutObject* child = prev ? prev : next; |
| + if (canMergeAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling()) { |
| + // The removal has knocked us down to containing only a single anonymous |
| + // box. We can go ahead and pull the content right back up into our |
| + // box. |
| + collapseAnonymousBlockChild(this, toLayoutBlock(child)); |
| + } else if (((prev && prev->isAnonymousBlock()) || (next && next->isAnonymousBlock()))) { |
| + // It's possible that the removal has knocked us down to a single anonymous |
| + // block with pseudo-style element siblings (e.g. first-letter). If these |
| + // are floating, then we need to pull the content up also. |
| + LayoutBlock* anonymousBlock = toLayoutBlock((prev && prev->isAnonymousBlock()) ? prev : next); |
| + if ((anonymousBlock->previousSibling() || anonymousBlock->nextSibling()) |
| + && (!anonymousBlock->previousSibling() || (anonymousBlock->previousSibling()->style()->styleType() != NOPSEUDO && anonymousBlock->previousSibling()->isFloating() && !anonymousBlock->previousSibling()->previousSibling())) |
| + && (!anonymousBlock->nextSibling() || (anonymousBlock->nextSibling()->style()->styleType() != NOPSEUDO && anonymousBlock->nextSibling()->isFloating() && !anonymousBlock->nextSibling()->nextSibling()))) { |
| + collapseAnonymousBlockChild(this, anonymousBlock); |
| + } |
| + } |
| +} |
| + |
| +static bool canMergeContiguousAnonymousBlocks(LayoutObject* prev, LayoutObject* next) |
| +{ |
| + if ((prev && (!prev->isAnonymousBlock() || toLayoutBlock(prev)->continuation() || toLayoutBlock(prev)->beingDestroyed())) |
| + || (next && (!next->isAnonymousBlock() || toLayoutBlock(next)->continuation() || toLayoutBlock(next)->beingDestroyed()))) |
| + return false; |
| + |
| + if ((prev && (prev->isRubyRun() || prev->isRubyBase())) |
| + || (next && (next->isRubyRun() || next->isRubyBase()))) |
| + return false; |
| + |
| + return true; |
| +} |
| + |
| +static void mergeContiguousAnonymousBlocks(LayoutBlock* parent, LayoutObject*& prev, LayoutObject*& next) |
| +{ |
| + ASSERT(canMergeContiguousAnonymousBlocks(prev, next)); |
| + if (!prev || !next) |
| + return; |
| + |
| + prev->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::AnonymousBlockChange); |
| + LayoutBlockFlow* nextBlock = toLayoutBlockFlow(next); |
| + LayoutBlockFlow* prevBlock = toLayoutBlockFlow(prev); |
| + |
| + if (prev->childrenInline() != next->childrenInline()) { |
| + LayoutBlock* inlineChildrenBlock = prev->childrenInline() ? prevBlock : nextBlock; |
| + LayoutBlock* blockChildrenBlock = prev->childrenInline() ? nextBlock : prevBlock; |
| + |
| + // Place the inline children block inside of the block children block instead of deleting it. |
| + ASSERT(!inlineChildrenBlock->continuation()); |
| + bool inlineChildrenBlockHasLayer = inlineChildrenBlock->hasLayer(); |
| + parent->children()->removeChildNode(parent, inlineChildrenBlock, inlineChildrenBlockHasLayer); |
| + |
| + // Now just put the inlineChildrenBlock inside the blockChildrenBlock. |
| + blockChildrenBlock->children()->insertChildNode(blockChildrenBlock, inlineChildrenBlock, prev == inlineChildrenBlock ? blockChildrenBlock->firstChild() : 0, |
| + inlineChildrenBlockHasLayer || blockChildrenBlock->hasLayer()); |
| + next->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::AnonymousBlockChange); |
| + |
| + // inlineChildrenBlock got reparented to blockChildrenBlock, so it is no longer a child |
| + // of "this". we null out prev or next so that is not used later in the function. |
| + if (inlineChildrenBlock == prevBlock) |
| + prev = nullptr; |
| + else |
| + next = nullptr; |
| + } else { |
| + // Take all the children out of the |next| block and put them in |
| + // the |prev| block. |
| + nextBlock->moveAllChildrenIncludingFloatsTo(prevBlock, nextBlock->hasLayer() || prevBlock->hasLayer()); |
| + |
| + // Delete the now-empty block's lines and nuke it. |
| + nextBlock->deleteLineBoxTree(); |
| + nextBlock->destroy(); |
| + next = nullptr; |
| + } |
| +} |
| + |
| static void addNextFloatingOrOutOfFlowSiblingsToBlock(LayoutBlock* block) |
| { |
| if (!block->parent() || !block->parent()->isLayoutBlockFlow()) |
| @@ -259,11 +338,19 @@ static void addNextFloatingOrOutOfFlowSiblingsToBlock(LayoutBlock* block) |
| return; |
| LayoutObject* child = block->nextSibling(); |
| + LayoutBlock* parent = toLayoutBlock(block->parent()); |
| while (child && child->isFloatingOrOutOfFlowPositioned()) { |
| LayoutObject* sibling = child->nextSibling(); |
| - toLayoutBlock(block->parent())->moveChildTo(block, child, nullptr, false); |
| + parent->moveChildTo(block, child, nullptr, false); |
| child = sibling; |
| } |
| + |
| + LayoutObject* prev = block; |
| + LayoutObject* next = block->nextSibling(); |
| + if (canMergeContiguousAnonymousBlocks(prev, next)) { |
| + mergeContiguousAnonymousBlocks(parent, prev, next); |
| + parent->collapseAnonymousBlockChildAfterMerge(prev, next, true); |
|
rhogan
2016/03/03 21:48:36
Was forced into the use of parent-> by canCollapse
|
| + } |
| } |
| static void addPreviousFloatingOrOutOfFlowSiblingsToBlock(LayoutBlock* block) |
| @@ -620,22 +707,6 @@ void LayoutBlock::removeLeftoverAnonymousBlock(LayoutBlock* child) |
| child->destroy(); |
| } |
| -static bool canMergeContiguousAnonymousBlocks(LayoutObject* oldChild, LayoutObject* prev, LayoutObject* next) |
| -{ |
| - if (oldChild->documentBeingDestroyed() || oldChild->isInline() || oldChild->virtualContinuation()) |
| - return false; |
| - |
| - if ((prev && (!prev->isAnonymousBlock() || toLayoutBlock(prev)->continuation() || toLayoutBlock(prev)->beingDestroyed())) |
| - || (next && (!next->isAnonymousBlock() || toLayoutBlock(next)->continuation() || toLayoutBlock(next)->beingDestroyed()))) |
| - return false; |
| - |
| - if ((prev && (prev->isRubyRun() || prev->isRubyBase())) |
| - || (next && (next->isRubyRun() || next->isRubyBase()))) |
| - return false; |
| - |
| - return true; |
| -} |
| - |
| void LayoutBlock::makeChildrenInlineIfPossible() |
| { |
| ASSERT(isLayoutBlockFlow()); |
| @@ -715,63 +786,13 @@ void LayoutBlock::removeChild(LayoutObject* oldChild) |
| // fold the inline content back together. |
| LayoutObject* prev = oldChild->previousSibling(); |
| LayoutObject* next = oldChild->nextSibling(); |
| - bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(oldChild, prev, next); |
| - if (canMergeAnonymousBlocks && prev && next) { |
| - prev->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::AnonymousBlockChange); |
| - LayoutBlockFlow* nextBlock = toLayoutBlockFlow(next); |
| - LayoutBlockFlow* prevBlock = toLayoutBlockFlow(prev); |
| - |
| - if (prev->childrenInline() != next->childrenInline()) { |
| - LayoutBlock* inlineChildrenBlock = prev->childrenInline() ? prevBlock : nextBlock; |
| - LayoutBlock* blockChildrenBlock = prev->childrenInline() ? nextBlock : prevBlock; |
| - |
| - // Place the inline children block inside of the block children block instead of deleting it. |
| - ASSERT(!inlineChildrenBlock->continuation()); |
| - bool inlineChildrenBlockHasLayer = inlineChildrenBlock->hasLayer(); |
| - children()->removeChildNode(this, inlineChildrenBlock, inlineChildrenBlockHasLayer); |
| - |
| - // Now just put the inlineChildrenBlock inside the blockChildrenBlock. |
| - blockChildrenBlock->children()->insertChildNode(blockChildrenBlock, inlineChildrenBlock, prev == inlineChildrenBlock ? blockChildrenBlock->firstChild() : 0, |
| - inlineChildrenBlockHasLayer || blockChildrenBlock->hasLayer()); |
| - next->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::AnonymousBlockChange); |
| - |
| - // inlineChildrenBlock got reparented to blockChildrenBlock, so it is no longer a child |
| - // of "this". we null out prev or next so that is not used later in the function. |
| - if (inlineChildrenBlock == prevBlock) |
| - prev = nullptr; |
| - else |
| - next = nullptr; |
| - } else { |
| - // Take all the children out of the |next| block and put them in |
| - // the |prev| block. |
| - nextBlock->moveAllChildrenIncludingFloatsTo(prevBlock, nextBlock->hasLayer() || prevBlock->hasLayer()); |
| - |
| - // Delete the now-empty block's lines and nuke it. |
| - nextBlock->deleteLineBoxTree(); |
| - nextBlock->destroy(); |
| - next = nullptr; |
| - } |
| - } |
| + bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(prev, next) && !oldChild->documentBeingDestroyed() && !oldChild->isInline() && !oldChild->virtualContinuation(); |
| + if (canMergeAnonymousBlocks) |
| + mergeContiguousAnonymousBlocks(this, prev, next); |
| LayoutBox::removeChild(oldChild); |
| - LayoutObject* child = prev ? prev : next; |
| - if (canMergeAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && canCollapseAnonymousBlockChild()) { |
| - // The removal has knocked us down to containing only a single anonymous |
| - // box. We can go ahead and pull the content right back up into our |
| - // box. |
| - collapseAnonymousBlockChild(this, toLayoutBlock(child)); |
| - } else if (((prev && prev->isAnonymousBlock()) || (next && next->isAnonymousBlock())) && canCollapseAnonymousBlockChild()) { |
| - // It's possible that the removal has knocked us down to a single anonymous |
| - // block with pseudo-style element siblings (e.g. first-letter). If these |
| - // are floating, then we need to pull the content up also. |
| - LayoutBlock* anonymousBlock = toLayoutBlock((prev && prev->isAnonymousBlock()) ? prev : next); |
| - if ((anonymousBlock->previousSibling() || anonymousBlock->nextSibling()) |
| - && (!anonymousBlock->previousSibling() || (anonymousBlock->previousSibling()->style()->styleType() != NOPSEUDO && anonymousBlock->previousSibling()->isFloating() && !anonymousBlock->previousSibling()->previousSibling())) |
| - && (!anonymousBlock->nextSibling() || (anonymousBlock->nextSibling()->style()->styleType() != NOPSEUDO && anonymousBlock->nextSibling()->isFloating() && !anonymousBlock->nextSibling()->nextSibling()))) { |
| - collapseAnonymousBlockChild(this, anonymousBlock); |
| - } |
| - } |
| + collapseAnonymousBlockChildAfterMerge(prev, next, canMergeAnonymousBlocks); |
| if (!firstChild()) { |
| // If this was our last child be sure to clear out our line boxes. |