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

Unified Diff: Source/core/rendering/RenderMultiColumnFlowThread.cpp

Issue 789433006: [New Multicolumn] Let a spanner's containing block be the multicol container. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Compiling release: paint invalidation state is cleared in the super class anyway. Created 6 years 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/rendering/RenderMultiColumnFlowThread.cpp
diff --git a/Source/core/rendering/RenderMultiColumnFlowThread.cpp b/Source/core/rendering/RenderMultiColumnFlowThread.cpp
index 6eaed6f174181af1b3308840f9bf3bb3b990256a..3fcf0db63513c843ae6c22dc48c08d79324a6d2d 100644
--- a/Source/core/rendering/RenderMultiColumnFlowThread.cpp
+++ b/Source/core/rendering/RenderMultiColumnFlowThread.cpp
@@ -27,7 +27,7 @@
#include "core/rendering/RenderMultiColumnFlowThread.h"
#include "core/rendering/RenderMultiColumnSet.h"
-#include "core/rendering/RenderMultiColumnSpannerSet.h"
+#include "core/rendering/RenderMultiColumnSpannerPlaceholder.h"
namespace blink {
@@ -37,6 +37,7 @@ RenderMultiColumnFlowThread::RenderMultiColumnFlowThread()
, m_inBalancingPass(false)
, m_needsColumnHeightsRecalculation(false)
, m_progressionIsInline(true)
+ , m_isBeingEvacuated(false)
{
setFlowThreadState(InsideInFlowThread);
}
@@ -71,20 +72,20 @@ RenderMultiColumnSet* RenderMultiColumnFlowThread::lastMultiColumnSet() const
return 0;
}
-RenderMultiColumnSpannerSet* RenderMultiColumnFlowThread::containingColumnSpannerSet(const RenderObject* descendant) const
+RenderMultiColumnSpannerPlaceholder* RenderMultiColumnFlowThread::containingColumnSpannerPlaceholder(const RenderObject* descendant) const
{
ASSERT(descendant->isDescendantOf(this));
// Before we spend time on searching the ancestry, see if there's a quick way to determine
// whether there might be any spanners at all.
- RenderMultiColumnSet* firstSet = firstMultiColumnSet();
- if (!firstSet || (firstSet == lastMultiColumnSet() && !firstSet->isRenderMultiColumnSpannerSet()))
+ RenderBox* firstBox = firstMultiColumnBox();
+ if (!firstBox || (firstBox == lastMultiColumnBox() && firstBox->isRenderMultiColumnSet()))
return 0;
// We have spanners. See if the renderer in question is one or inside of one then.
for (const RenderObject* ancestor = descendant; ancestor && ancestor != this; ancestor = ancestor->parent()) {
- if (RenderMultiColumnSpannerSet* spanner = m_spannerMap.get(ancestor))
- return spanner;
+ if (RenderMultiColumnSpannerPlaceholder* placeholder = ancestor->spannerPlaceholder())
+ return placeholder;
}
return 0;
}
@@ -102,10 +103,13 @@ void RenderMultiColumnFlowThread::populate()
void RenderMultiColumnFlowThread::evacuateAndDestroy()
{
RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
+ m_isBeingEvacuated = true;
- // Remove all sets.
- while (RenderMultiColumnSet* columnSet = firstMultiColumnSet())
- columnSet->destroy();
+ // Remove all sets and spanners.
+ while (RenderBox* columnBox = firstMultiColumnBox()) {
+ ASSERT(columnBox->isAnonymous());
+ columnBox->destroy();
+ }
ASSERT(!previousSibling());
ASSERT(!nextSibling());
@@ -162,7 +166,12 @@ void RenderMultiColumnFlowThread::layoutColumns(bool relayoutChildren, SubtreeLa
return;
}
- for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; columnSet = columnSet->nextSiblingMultiColumnSet()) {
+ for (RenderBox* columnBox = firstMultiColumnBox(); columnBox; columnBox = columnBox->nextSiblingBox()) {
+ if (!columnBox->isRenderMultiColumnSet()) {
+ ASSERT(columnBox->isRenderMultiColumnSpannerPlaceholder()); // no other type is expected.
+ continue;
+ }
+ RenderMultiColumnSet* columnSet = toRenderMultiColumnSet(columnBox);
if (!m_inBalancingPass) {
// This is the initial layout pass. We need to reset the column height, because contents
// typically have changed.
@@ -238,17 +247,16 @@ void RenderMultiColumnFlowThread::createAndInsertMultiColumnSet()
// We cannot handle immediate column set siblings (and there's no need for it, either).
// There has to be at least one spanner separating them.
- ASSERT(!newSet->previousSiblingMultiColumnSet() || newSet->previousSiblingMultiColumnSet()->isRenderMultiColumnSpannerSet());
- ASSERT(!newSet->nextSiblingMultiColumnSet() || newSet->nextSiblingMultiColumnSet()->isRenderMultiColumnSpannerSet());
+ ASSERT(!newSet->previousSiblingMultiColumnBox() || !newSet->previousSiblingMultiColumnBox()->isRenderMultiColumnSet());
+ ASSERT(!newSet->nextSiblingMultiColumnBox() || !newSet->nextSiblingMultiColumnBox()->isRenderMultiColumnSet());
}
-void RenderMultiColumnFlowThread::createAndInsertSpannerSet(RenderBox* spanner)
+void RenderMultiColumnFlowThread::createAndInsertSpannerPlaceholder(RenderBox* spanner)
{
RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
- RenderMultiColumnSpannerSet* newSpannerSet = RenderMultiColumnSpannerSet::createAnonymous(this, multicolContainer->style(), spanner);
- multicolContainer->RenderBlock::addChild(newSpannerSet);
- m_spannerMap.add(spanner, newSpannerSet);
- invalidateRegions();
+ RenderMultiColumnSpannerPlaceholder* newPlaceholder = RenderMultiColumnSpannerPlaceholder::createAnonymous(multicolContainer->style(), spanner);
+ multicolContainer->RenderBlock::addChild(newPlaceholder);
+ spanner->setSpannerPlaceholder(*newPlaceholder);
}
bool RenderMultiColumnFlowThread::descendantIsValidColumnSpanner(RenderObject* descendant) const
@@ -256,6 +264,10 @@ bool RenderMultiColumnFlowThread::descendantIsValidColumnSpanner(RenderObject* d
// We assume that we're inside the flow thread. This function is not to be called otherwise.
ASSERT(descendant->isDescendantOf(this));
+ // We're evaluating if the descendant should be turned into a proper spanner. It shouldn't
+ // already be one.
+ ASSERT(!descendant->spannerPlaceholder());
+
// The spec says that column-span only applies to in-flow block-level elements.
if (descendant->style()->columnSpan() != ColumnSpanAll || !descendant->isBox() || descendant->isInline() || descendant->isFloatingOrOutOfFlowPositioned())
return false;
@@ -266,12 +278,12 @@ bool RenderMultiColumnFlowThread::descendantIsValidColumnSpanner(RenderObject* d
}
// This looks like a spanner, but if we're inside something unbreakable, it's not to be treated as one.
- for (RenderBlock* ancestor = descendant->containingBlock(); ancestor && ancestor->flowThreadContainingBlock() == this; ancestor = ancestor->containingBlock()) {
+ for (RenderBlock* ancestor = descendant->containingBlock(); ancestor; ancestor = ancestor->containingBlock()) {
if (ancestor->isRenderFlowThread()) {
ASSERT(ancestor == this);
return true;
}
- if (m_spannerMap.get(ancestor)) {
+ if (ancestor->spannerPlaceholder()) {
// FIXME: do we want to support nested spanners in a different way? The outer spanner
// has already broken out from the columns to become sized by the multicol container,
// which may be good enough for the inner spanner. But margins, borders, padding and
@@ -306,7 +318,6 @@ void RenderMultiColumnFlowThread::addRegionToThread(RenderMultiColumnSet* column
void RenderMultiColumnFlowThread::willBeRemovedFromTree()
{
- m_spannerMap.clear();
// Detach all column sets from the flow thread. Cannot destroy them at this point, since they
// are siblings of this object, and there may be pointers to this object's sibling somewhere
// further up on the call stack.
@@ -318,23 +329,51 @@ void RenderMultiColumnFlowThread::willBeRemovedFromTree()
void RenderMultiColumnFlowThread::flowThreadDescendantWasInserted(RenderObject* descendant)
{
+ ASSERT(!m_isBeingEvacuated);
// Go through the subtree that was just inserted and create column sets (needed by regular
- // column content) and spanner sets (one needed by each spanner).
+ // column content) and spanner placeholders (one needed by each spanner).
for (RenderObject* renderer = descendant; renderer; renderer = renderer->nextInPreOrder(descendant)) {
- if (containingColumnSpannerSet(renderer))
- continue; // Inside a column spanner set. Nothing to do, then.
+ 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 set.
- createAndInsertSpannerSet(toRenderBox(renderer));
+ // This renderer is a spanner, so it needs to establish a spanner placeholder.
+ createAndInsertSpannerPlaceholder(toRenderBox(renderer));
continue;
}
// This renderer is regular column content (i.e. not a spanner). Create a set if necessary.
- RenderMultiColumnSet* lastSet = lastMultiColumnSet();
- if (!lastSet || lastSet->isRenderMultiColumnSpannerSet())
+ RenderBox* lastColumnBox = lastMultiColumnBox();
+ if (!lastColumnBox || !lastColumnBox->isRenderMultiColumnSet())
createAndInsertMultiColumnSet();
}
}
+void RenderMultiColumnFlowThread::flowThreadDescendantWillBeRemoved(RenderObject* descendant)
+{
+ if (m_isBeingEvacuated)
+ return;
+ RenderObject* next;
+ // Remove spanner placeholders that are no longer needed, and merge column sets around them.
+ for (RenderObject* renderer = descendant; renderer; renderer = next) {
+ RenderMultiColumnSpannerPlaceholder* placeholder = renderer->spannerPlaceholder();
+ if (!placeholder) {
+ next = renderer->nextInPreOrder(descendant);
+ continue;
+ }
+ next = renderer->nextInPreOrderAfterChildren(descendant); // It's a spanner. Its children are of no interest to us.
+ if (RenderBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox()) {
+ RenderBox* previousColumnBox = placeholder->previousSiblingMultiColumnBox();
+ if (nextColumnBox && nextColumnBox->isRenderMultiColumnSet()
+ && previousColumnBox && previousColumnBox->isRenderMultiColumnSet()) {
+ // Need to merge two column sets.
+ nextColumnBox->destroy();
+ previousColumnBox->setNeedsLayout();
+ invalidateRegions();
+ }
+ }
+ placeholder->destroy();
+ }
+}
+
void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
{
// We simply remain at our intrinsic height.
@@ -352,8 +391,10 @@ void RenderMultiColumnFlowThread::updateLogicalWidth()
void RenderMultiColumnFlowThread::layout()
{
RenderFlowThread::layout();
- if (RenderMultiColumnSet* lastSet = lastMultiColumnSet())
- lastSet->expandToEncompassFlowThreadContentsIfNeeded();
+ if (RenderMultiColumnSet* lastSet = lastMultiColumnSet()) {
+ if (!lastSet->nextSiblingMultiColumnBox())
+ lastSet->expandToEncompassFlowThreadContentsIfNeeded();
+ }
}
void RenderMultiColumnFlowThread::setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage)
« no previous file with comments | « Source/core/rendering/RenderMultiColumnFlowThread.h ('k') | Source/core/rendering/RenderMultiColumnFlowThreadTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698