Chromium Code Reviews| Index: Source/core/layout/LayoutMultiColumnFlowThread.cpp |
| diff --git a/Source/core/layout/LayoutMultiColumnFlowThread.cpp b/Source/core/layout/LayoutMultiColumnFlowThread.cpp |
| index 80850ec8c1f9e36dbf369fcceb8744162b1e462a..219fa2c1559e0dc97f630d6363ab0a9d633261cb 100644 |
| --- a/Source/core/layout/LayoutMultiColumnFlowThread.cpp |
| +++ b/Source/core/layout/LayoutMultiColumnFlowThread.cpp |
| @@ -445,27 +445,49 @@ LayoutUnit LayoutMultiColumnFlowThread::skipColumnSpanner(LayoutBox* renderer, L |
| return adjustment; |
| } |
| +// When processing layout objects to remove or when processing layout objects that have just been |
| +// inserted, certain types of objects should be skipped. |
| +static bool shouldSkipInsertedOrRemovedChild(const LayoutObject& child) |
| +{ |
| + if (child.isLayoutFlowThread()) { |
| + // Found an inner flow thread. We need to skip it and its descendants. |
| + return true; |
| + } |
| + if (child.isLayoutMultiColumnSet() || child.isLayoutMultiColumnSpannerPlaceholder()) { |
| + // Column sets and spanner placeholders in a child multicol context don't affect the parent |
| + // flow thread. |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| void LayoutMultiColumnFlowThread::flowThreadDescendantWasInserted(LayoutObject* descendant) |
| { |
| ASSERT(!m_isBeingEvacuated); |
| - LayoutObject* nextRenderer = descendant->nextInPreOrderAfterChildren(this); |
| + LayoutObject* objectAfterSubtree = descendant->nextInPreOrderAfterChildren(this); |
| // This method ensures that the list of column sets and spanner placeholders reflects the |
| // multicol content after having inserted a descendant (or descendant subtree). See the header |
| // file for more information. Go through the subtree that was just inserted and create column |
| // sets (needed by regular column content) and spanner placeholders (one needed by each spanner) |
| // where needed. |
| - for (LayoutObject* renderer = descendant; renderer; renderer = renderer->nextInPreOrder(descendant)) { |
| + LayoutObject* next; |
| + for (LayoutObject* renderer = descendant; renderer; renderer = next) { |
|
dsinclair
2015/04/24 13:13:30
nit: s/renderer/layoutObject/
mstensho (USE GERRIT)
2015/04/24 13:27:26
Done.
Note that I didn't really introduce this in
|
| + if (shouldSkipInsertedOrRemovedChild(*renderer)) { |
| + next = renderer->nextInPreOrderAfterChildren(descendant); |
| + continue; |
| + } |
| + next = renderer->nextInPreOrder(descendant); |
| if (containingColumnSpannerPlaceholder(renderer)) |
| continue; // Inside a column spanner. Nothing to do, then. |
| if (descendantIsValidColumnSpanner(renderer)) { |
| // This renderer is a spanner, so it needs to establish a spanner placeholder. |
| LayoutBox* insertBefore = 0; |
| LayoutMultiColumnSet* setToSplit = 0; |
| - if (nextRenderer) { |
| + if (objectAfterSubtree) { |
| // The spanner is inserted before something. Figure out what this entails. If the |
| // next renderer is a spanner too, it means that we can simply insert a new spanner |
| // placeholder in front of its placeholder. |
| - insertBefore = nextRenderer->spannerPlaceholder(); |
| + insertBefore = objectAfterSubtree->spannerPlaceholder(); |
| if (!insertBefore) { |
| // The next renderer isn't a spanner; it's regular column content. Examine what |
| // comes right before us in the flow thread, then. |
| @@ -483,7 +505,7 @@ void LayoutMultiColumnFlowThread::flowThreadDescendantWasInserted(LayoutObject* |
| // set this is. It needs to be split it into two sets, so that we can insert |
| // a new spanner placeholder between them. |
| setToSplit = findSetRendering(previousRenderer); |
| - ASSERT(setToSplit == findSetRendering(nextRenderer)); |
| + ASSERT(setToSplit == findSetRendering(objectAfterSubtree)); |
| setToSplit->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::ColumnsChanged); |
| insertBefore = setToSplit->nextSiblingMultiColumnBox(); |
| // We've found out which set that needs to be split. Now proceed to |
| @@ -498,17 +520,17 @@ void LayoutMultiColumnFlowThread::flowThreadDescendantWasInserted(LayoutObject* |
| continue; |
| } |
| // This renderer is regular column content (i.e. not a spanner). Create a set if necessary. |
| - if (nextRenderer) { |
| - if (LayoutMultiColumnSpannerPlaceholder* placeholder = nextRenderer->spannerPlaceholder()) { |
| + if (objectAfterSubtree) { |
| + if (LayoutMultiColumnSpannerPlaceholder* placeholder = objectAfterSubtree->spannerPlaceholder()) { |
| // If inserted right before a spanner, we need to make sure that there's a set for us there. |
| LayoutBox* previous = placeholder->previousSiblingMultiColumnBox(); |
| if (!previous || !previous->isLayoutMultiColumnSet()) |
| createAndInsertMultiColumnSet(placeholder); |
| } else { |
| - // Otherwise, since |nextRenderer| isn't a spanner, it has to mean that there's |
| + // Otherwise, since |objectAfterSubtree| isn't a spanner, it has to mean that there's |
| // already a set for that content. We can use it for this renderer too. |
| - ASSERT(findSetRendering(nextRenderer)); |
| - ASSERT(findSetRendering(renderer) == findSetRendering(nextRenderer)); |
| + ASSERT(findSetRendering(objectAfterSubtree)); |
| + ASSERT(findSetRendering(renderer) == findSetRendering(objectAfterSubtree)); |
| } |
| } else { |
| // Inserting at the end. Then we just need to make sure that there's a column set at the end. |
| @@ -528,9 +550,15 @@ void LayoutMultiColumnFlowThread::flowThreadDescendantWillBeRemoved(LayoutObject |
| if (m_isBeingEvacuated) |
| return; |
| bool hadContainingPlaceholder = containingColumnSpannerPlaceholder(descendant); |
| + bool processedSomething = false; |
| LayoutObject* next; |
| // Remove spanner placeholders that are no longer needed, and merge column sets around them. |
| for (LayoutObject* renderer = descendant; renderer; renderer = next) { |
| + if (shouldSkipInsertedOrRemovedChild(*renderer)) { |
| + next = renderer->nextInPreOrderAfterChildren(descendant); |
| + continue; |
| + } |
| + processedSomething = true; |
| LayoutMultiColumnSpannerPlaceholder* placeholder = renderer->spannerPlaceholder(); |
| if (!placeholder) { |
| next = renderer->nextInPreOrder(descendant); |
| @@ -549,8 +577,8 @@ void LayoutMultiColumnFlowThread::flowThreadDescendantWillBeRemoved(LayoutObject |
| } |
| placeholder->destroy(); |
| } |
| - if (hadContainingPlaceholder) |
| - return; // We're only removing a spanner (or something inside one), which means that no column content will be removed. |
| + if (hadContainingPlaceholder || !processedSomething) |
| + return; // No column content will be removed, so we can stop here. |
| // Column content will be removed. Does this mean that we should destroy a column set? |
| LayoutMultiColumnSpannerPlaceholder* adjacentPreviousSpannerPlaceholder = 0; |