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

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

Issue 143383002: Region based multicol: support explicit column breaks (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Code review. Created 6 years, 10 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
« no previous file with comments | « Source/core/rendering/RenderMultiColumnSet.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/rendering/RenderMultiColumnSet.cpp
diff --git a/Source/core/rendering/RenderMultiColumnSet.cpp b/Source/core/rendering/RenderMultiColumnSet.cpp
index 449073752ae1e6e73f252dc473a2ef0e76f621bd..07c05a6eb34d4f73e83cb0014cca7fbe584553bf 100644
--- a/Source/core/rendering/RenderMultiColumnSet.cpp
+++ b/Source/core/rendering/RenderMultiColumnSet.cpp
@@ -43,9 +43,6 @@ RenderMultiColumnSet::RenderMultiColumnSet(RenderFlowThread* flowThread)
, m_maxColumnHeight(LayoutUnit::max())
, m_minSpaceShortage(LayoutUnit::max())
, m_minimumColumnHeight(0)
- , m_forcedBreaksCount(0)
- , m_maximumDistanceBetweenForcedBreaks(0)
- , m_forcedBreakOffset(0)
{
}
@@ -81,46 +78,122 @@ void RenderMultiColumnSet::setAndConstrainColumnHeight(LayoutUnit newHeight)
// FIXME: the height may also be affected by the enclosing pagination context, if any.
}
-bool RenderMultiColumnSet::calculateBalancedHeight(bool initial)
+unsigned RenderMultiColumnSet::findRunWithTallestColumns() const
{
- ASSERT(toRenderMultiColumnBlock(parent())->requiresBalancing());
- LayoutUnit oldColumnHeight = m_computedColumnHeight;
- LayoutUnit currentMinSpaceShortage = m_minSpaceShortage;
- m_minSpaceShortage = LayoutUnit::max();
+ unsigned indexWithLargestHeight = 0;
+ LayoutUnit largestHeight;
+ LayoutUnit previousOffset;
+ size_t runCount = m_contentRuns.size();
+ ASSERT(runCount);
+ for (size_t i = 0; i < runCount; i++) {
+ const ContentRun& run = m_contentRuns[i];
+ LayoutUnit height = run.columnLogicalHeight(previousOffset);
+ if (largestHeight < height) {
+ largestHeight = height;
+ indexWithLargestHeight = i;
+ }
+ previousOffset = run.breakOffset();
+ }
+ return indexWithLargestHeight;
+}
+
+void RenderMultiColumnSet::distributeImplicitBreaks()
+{
+ unsigned breakCount = forcedBreaksCount();
+
+#ifndef NDEBUG
+ // There should be no implicit breaks assumed at this point.
+ for (unsigned i = 0; i < breakCount; i++)
+ ASSERT(!m_contentRuns[i].assumedImplicitBreaks());
+#endif // NDEBUG
+
+ // There will always be at least one break, since the flow thread reports a "forced break" at
+ // end of content.
+ ASSERT(breakCount >= 1);
+
+ // If there is room for more breaks (to reach the used value of column-count), imagine that we
+ // insert implicit breaks at suitable locations. At any given time, the content run with the
+ // currently tallest columns will get another implicit break "inserted", which will increase its
+ // column count by one and shrink its columns' height. Repeat until we have the desired total
+ // number of breaks. The largest column height among the runs will then be the initial column
+ // height for the balancer to use.
+ while (breakCount < m_computedColumnCount) {
+ unsigned index = findRunWithTallestColumns();
+ m_contentRuns[index].assumeAnotherImplicitBreak();
+ breakCount++;
+ }
+}
+LayoutUnit RenderMultiColumnSet::calculateBalancedHeight(bool initial) const
+{
if (initial) {
// Start with the lowest imaginable column height.
- LayoutUnit logicalHeightGuess = ceilf(float(flowThread()->logicalHeight()) / float(m_computedColumnCount));
- logicalHeightGuess = max(logicalHeightGuess, m_minimumColumnHeight);
- setAndConstrainColumnHeight(logicalHeightGuess);
-
- // The multicol container now typically needs at least one more layout pass with a new
- // column height, but if height was specified, we only need to do this if we found that we
- // might need less space than that. On the other hand, if we determined that the columns
- // need to be as tall as the specified height of the container, we have already laid it out
- // correctly, and there's no need for another pass.
- return m_computedColumnHeight != oldColumnHeight;
+ unsigned index = findRunWithTallestColumns();
+ LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset() : LayoutUnit();
+ return std::max<LayoutUnit>(m_contentRuns[index].columnLogicalHeight(startOffset), m_minimumColumnHeight);
}
if (columnCount() <= computedColumnCount()) {
// With the current column height, the content fits without creating overflowing columns. We're done.
- return false;
+ return m_computedColumnHeight;
+ }
+
+ if (forcedBreaksCount() > 1 && forcedBreaksCount() >= computedColumnCount()) {
+ // Too many forced breaks to allow any implicit breaks. Initial balancing should already
+ // have set a good height. There's nothing more we should do.
+ return m_computedColumnHeight;
}
// If the initial guessed column height wasn't enough, stretch it now. Stretch by the lowest
// amount of space shortage found during layout.
- ASSERT(currentMinSpaceShortage != LayoutUnit::max()); // If this can actually happen, we probably have a bug.
- if (currentMinSpaceShortage == LayoutUnit::max())
- return false; // So bail out rather than looping infinitely.
+ ASSERT(m_minSpaceShortage > 0); // We should never _shrink_ the height!
+ ASSERT(m_minSpaceShortage != LayoutUnit::max()); // If this happens, we probably have a bug.
+ if (m_minSpaceShortage == LayoutUnit::max())
+ return m_computedColumnHeight; // So bail out rather than looping infinitely.
- setAndConstrainColumnHeight(m_computedColumnHeight + currentMinSpaceShortage);
+ return m_computedColumnHeight + m_minSpaceShortage;
+}
- // If we reach the maximum column height (typically set by the height or max-height property),
- // we may not be allowed to stretch further. Return true only if stretching
- // succeeded. Otherwise, we're done.
- ASSERT(m_computedColumnHeight >= oldColumnHeight); // We shouldn't be able to shrink the height!
- return m_computedColumnHeight > oldColumnHeight;
+void RenderMultiColumnSet::clearForcedBreaks()
+{
+ m_contentRuns.clear();
+}
+
+void RenderMultiColumnSet::addForcedBreak(LayoutUnit offsetFromFirstPage)
+{
+ if (!toRenderMultiColumnBlock(parent())->requiresBalancing())
+ return;
+ if (!m_contentRuns.isEmpty() && offsetFromFirstPage <= m_contentRuns.last().breakOffset())
+ return;
+ // Append another item as long as we haven't exceeded used column count. What ends up in the
+ // overflow area shouldn't affect column balancing.
+ if (m_contentRuns.size() < m_computedColumnCount)
+ m_contentRuns.append(ContentRun(offsetFromFirstPage));
+}
+
+bool RenderMultiColumnSet::recalculateBalancedHeight(bool initial)
+{
+ ASSERT(toRenderMultiColumnBlock(parent())->requiresBalancing());
+
+ LayoutUnit oldColumnHeight = m_computedColumnHeight;
+ if (initial)
+ distributeImplicitBreaks();
+ LayoutUnit newColumnHeight = calculateBalancedHeight(initial);
+ setAndConstrainColumnHeight(newColumnHeight);
+
+ // After having calculated an initial column height, the multicol container typically needs at
+ // least one more layout pass with a new column height, but if a height was specified, we only
+ // need to do this if we think that we need less space than specified. Conversely, if we
+ // determined that the columns need to be as tall as the specified height of the container, we
+ // have already laid it out correctly, and there's no need for another pass.
+
+ if (m_computedColumnHeight == oldColumnHeight)
+ return false; // No change. We're done.
+
+ m_minSpaceShortage = LayoutUnit::max();
+ clearForcedBreaks();
+ return true; // Need another pass.
}
void RenderMultiColumnSet::recordSpaceShortage(LayoutUnit spaceShortage)
@@ -185,6 +258,8 @@ void RenderMultiColumnSet::prepareForLayout()
setAndConstrainColumnHeight(heightAdjustedForSetOffset(multicolBlock->columnHeightAvailable()));
}
+ clearForcedBreaks();
+
// Nuke previously stored minimum column height. Contents may have changed for all we know.
m_minimumColumnHeight = 0;
}
« no previous file with comments | « Source/core/rendering/RenderMultiColumnSet.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698