| Index: Source/core/layout/LayoutMultiColumnFlowThread.cpp
|
| diff --git a/Source/core/layout/LayoutMultiColumnFlowThread.cpp b/Source/core/layout/LayoutMultiColumnFlowThread.cpp
|
| index 80850ec8c1f9e36dbf369fcceb8744162b1e462a..a6d0cf6f2096dc84ec11da64a4d378632309d525 100644
|
| --- a/Source/core/layout/LayoutMultiColumnFlowThread.cpp
|
| +++ b/Source/core/layout/LayoutMultiColumnFlowThread.cpp
|
| @@ -445,45 +445,67 @@ 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)) {
|
| - if (containingColumnSpannerPlaceholder(renderer))
|
| + LayoutObject* next;
|
| + for (LayoutObject* layoutObject = descendant; layoutObject; layoutObject = next) {
|
| + if (shouldSkipInsertedOrRemovedChild(*layoutObject)) {
|
| + next = layoutObject->nextInPreOrderAfterChildren(descendant);
|
| + continue;
|
| + }
|
| + next = layoutObject->nextInPreOrder(descendant);
|
| + if (containingColumnSpannerPlaceholder(layoutObject))
|
| 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.
|
| + if (descendantIsValidColumnSpanner(layoutObject)) {
|
| + // This layoutObject 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
|
| + // next layoutObject 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
|
| + // The next layoutObject isn't a spanner; it's regular column content. Examine what
|
| // comes right before us in the flow thread, then.
|
| - LayoutObject* previousRenderer = renderer->previousInPreOrder(this);
|
| - if (!previousRenderer || previousRenderer == this) {
|
| + LayoutObject* previousLayoutObject = layoutObject->previousInPreOrder(this);
|
| + if (!previousLayoutObject || previousLayoutObject == this) {
|
| // The spanner is inserted as the first child of the multicol container,
|
| // which means that we simply insert a new spanner placeholder at the
|
| // beginning.
|
| insertBefore = firstMultiColumnBox();
|
| - } else if (LayoutMultiColumnSpannerPlaceholder* previousPlaceholder = containingColumnSpannerPlaceholder(previousRenderer)) {
|
| + } else if (LayoutMultiColumnSpannerPlaceholder* previousPlaceholder = containingColumnSpannerPlaceholder(previousLayoutObject)) {
|
| // Before us is another spanner. We belong right after it then.
|
| insertBefore = previousPlaceholder->nextSiblingMultiColumnBox();
|
| } else {
|
| // We're inside regular column content with both feet. Find out which column
|
| // 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));
|
| + setToSplit = findSetRendering(previousLayoutObject);
|
| + 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
|
| @@ -492,23 +514,23 @@ void LayoutMultiColumnFlowThread::flowThreadDescendantWasInserted(LayoutObject*
|
| }
|
| ASSERT(setToSplit || insertBefore);
|
| }
|
| - createAndInsertSpannerPlaceholder(toLayoutBox(renderer), insertBefore);
|
| + createAndInsertSpannerPlaceholder(toLayoutBox(layoutObject), insertBefore);
|
| if (setToSplit)
|
| createAndInsertMultiColumnSet(insertBefore);
|
| continue;
|
| }
|
| - // This renderer is regular column content (i.e. not a spanner). Create a set if necessary.
|
| - if (nextRenderer) {
|
| - if (LayoutMultiColumnSpannerPlaceholder* placeholder = nextRenderer->spannerPlaceholder()) {
|
| + // This layoutObject is regular column content (i.e. not a spanner). Create a set if necessary.
|
| + 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
|
| - // already a set for that content. We can use it for this renderer too.
|
| - ASSERT(findSetRendering(nextRenderer));
|
| - ASSERT(findSetRendering(renderer) == findSetRendering(nextRenderer));
|
| + // 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 layoutObject too.
|
| + ASSERT(findSetRendering(objectAfterSubtree));
|
| + ASSERT(findSetRendering(layoutObject) == findSetRendering(objectAfterSubtree));
|
| }
|
| } else {
|
| // Inserting at the end. Then we just need to make sure that there's a column set at the end.
|
| @@ -528,15 +550,21 @@ 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) {
|
| - LayoutMultiColumnSpannerPlaceholder* placeholder = renderer->spannerPlaceholder();
|
| + for (LayoutObject* layoutObject = descendant; layoutObject; layoutObject = next) {
|
| + if (shouldSkipInsertedOrRemovedChild(*layoutObject)) {
|
| + next = layoutObject->nextInPreOrderAfterChildren(descendant);
|
| + continue;
|
| + }
|
| + processedSomething = true;
|
| + LayoutMultiColumnSpannerPlaceholder* placeholder = layoutObject->spannerPlaceholder();
|
| if (!placeholder) {
|
| - next = renderer->nextInPreOrder(descendant);
|
| + next = layoutObject->nextInPreOrder(descendant);
|
| continue;
|
| }
|
| - next = renderer->nextInPreOrderAfterChildren(descendant); // It's a spanner. Its children are of no interest to us.
|
| + next = layoutObject->nextInPreOrderAfterChildren(descendant); // It's a spanner. Its children are of no interest to us.
|
| if (LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox()) {
|
| LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColumnBox();
|
| if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet()
|
| @@ -549,21 +577,21 @@ 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;
|
| - LayoutObject* previousRenderer = descendant->previousInPreOrder(this);
|
| - if (previousRenderer && previousRenderer != this) {
|
| - adjacentPreviousSpannerPlaceholder = containingColumnSpannerPlaceholder(previousRenderer);
|
| + LayoutObject* previousLayoutObject = descendant->previousInPreOrder(this);
|
| + if (previousLayoutObject && previousLayoutObject != this) {
|
| + adjacentPreviousSpannerPlaceholder = containingColumnSpannerPlaceholder(previousLayoutObject);
|
| if (!adjacentPreviousSpannerPlaceholder)
|
| return; // Preceded by column content. Set still needed.
|
| }
|
| LayoutMultiColumnSpannerPlaceholder* adjacentNextSpannerPlaceholder = 0;
|
| - LayoutObject* nextRenderer = descendant->nextInPreOrderAfterChildren(this);
|
| - if (nextRenderer) {
|
| - adjacentNextSpannerPlaceholder = containingColumnSpannerPlaceholder(nextRenderer);
|
| + LayoutObject* nextLayoutObject = descendant->nextInPreOrderAfterChildren(this);
|
| + if (nextLayoutObject) {
|
| + adjacentNextSpannerPlaceholder = containingColumnSpannerPlaceholder(nextLayoutObject);
|
| if (!adjacentNextSpannerPlaceholder)
|
| return; // Followed by column content. Set still needed.
|
| }
|
|
|