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

Unified Diff: Source/core/layout/LayoutMultiColumnFlowThread.cpp

Issue 1109513002: [New Multicolumn] Don't enter child multicol contexts when processing object insertions / removals. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: code review: renderer -> layoutObject Created 5 years, 8 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
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.
}
« no previous file with comments | « LayoutTests/fast/multicol/inner-multicol-moved-into-continuation-expected.txt ('k') | Source/core/layout/LayoutObject.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698