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

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

Issue 688703003: [New Multicolumn] Add RenderMultiColumnSpannerSet. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: There won't ever be any intervening non-multicol fragmentation contexts. Created 6 years, 1 month 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 a6bd077631340a6ab76f66050846204bb21e013f..6eaed6f174181af1b3308840f9bf3bb3b990256a 100644
--- a/Source/core/rendering/RenderMultiColumnFlowThread.cpp
+++ b/Source/core/rendering/RenderMultiColumnFlowThread.cpp
@@ -27,6 +27,7 @@
#include "core/rendering/RenderMultiColumnFlowThread.h"
#include "core/rendering/RenderMultiColumnSet.h"
+#include "core/rendering/RenderMultiColumnSpannerSet.h"
namespace blink {
@@ -70,21 +71,22 @@ RenderMultiColumnSet* RenderMultiColumnFlowThread::lastMultiColumnSet() const
return 0;
}
-void RenderMultiColumnFlowThread::addChild(RenderObject* newChild, RenderObject* beforeChild)
+RenderMultiColumnSpannerSet* RenderMultiColumnFlowThread::containingColumnSpannerSet(const RenderObject* descendant) const
{
- RenderBlockFlow::addChild(newChild, beforeChild);
- if (firstMultiColumnSet())
- return;
-
- // For now we only create one column set. It's created as soon as the multicol container gets
- // any content at all.
- RenderMultiColumnSet* newSet = RenderMultiColumnSet::createAnonymous(this, multiColumnBlockFlow()->style());
-
- // Need to skip RenderBlockFlow's implementation of addChild(), or we'd get redirected right
- // back here.
- multiColumnBlockFlow()->RenderBlock::addChild(newSet);
-
- invalidateRegions();
+ 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()))
+ 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;
+ }
+ return 0;
}
void RenderMultiColumnFlowThread::populate()
@@ -227,6 +229,64 @@ void RenderMultiColumnFlowThread::calculateColumnCountAndWidth(LayoutUnit& width
}
}
+void RenderMultiColumnFlowThread::createAndInsertMultiColumnSet()
+{
+ RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
+ RenderMultiColumnSet* newSet = RenderMultiColumnSet::createAnonymous(this, multicolContainer->style());
+ multicolContainer->RenderBlock::addChild(newSet);
+ invalidateRegions();
+
+ // 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());
+}
+
+void RenderMultiColumnFlowThread::createAndInsertSpannerSet(RenderBox* spanner)
+{
+ RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
+ RenderMultiColumnSpannerSet* newSpannerSet = RenderMultiColumnSpannerSet::createAnonymous(this, multicolContainer->style(), spanner);
+ multicolContainer->RenderBlock::addChild(newSpannerSet);
+ m_spannerMap.add(spanner, newSpannerSet);
+ invalidateRegions();
+}
+
+bool RenderMultiColumnFlowThread::descendantIsValidColumnSpanner(RenderObject* descendant) const
+{
+ // We assume that we're inside the flow thread. This function is not to be called otherwise.
+ ASSERT(descendant->isDescendantOf(this));
+
+ // 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;
+
+ if (!descendant->containingBlock()->isRenderBlockFlow()) {
+ // Needs to be in a block-flow container, and not e.g. a table.
+ return false;
+ }
+
+ // 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()) {
+ if (ancestor->isRenderFlowThread()) {
+ ASSERT(ancestor == this);
+ return true;
+ }
+ if (m_spannerMap.get(ancestor)) {
+ // 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
+ // explicit widths on the outer spanner, or on any children between the outer and inner
+ // spanner, will affect the width of the inner spanner this way, which might be
+ // undesirable. The spec has nothing to say on the matter.
+ return false; // Ignore nested spanners.
+ }
+ if (ancestor->isUnsplittableForPagination())
+ return false;
+ }
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
const char* RenderMultiColumnFlowThread::renderName() const
{
return "RenderMultiColumnFlowThread";
@@ -246,6 +306,7 @@ 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.
@@ -255,6 +316,25 @@ void RenderMultiColumnFlowThread::willBeRemovedFromTree()
RenderFlowThread::willBeRemovedFromTree();
}
+void RenderMultiColumnFlowThread::flowThreadDescendantWasInserted(RenderObject* descendant)
+{
+ // 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).
+ for (RenderObject* renderer = descendant; renderer; renderer = renderer->nextInPreOrder(descendant)) {
+ if (containingColumnSpannerSet(renderer))
+ continue; // Inside a column spanner set. Nothing to do, then.
+ if (descendantIsValidColumnSpanner(renderer)) {
+ // This renderer is a spanner, so it needs to establish a spanner set.
+ createAndInsertSpannerSet(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())
+ createAndInsertMultiColumnSet();
+ }
+}
+
void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
{
// We simply remain at our intrinsic height.
« 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