Index: Source/core/rendering/RenderMultiColumnSet.h |
diff --git a/Source/core/rendering/RenderMultiColumnSet.h b/Source/core/rendering/RenderMultiColumnSet.h |
index 057f4bf260b6f1691628c3c51f0fffc748845d51..4ece7e3b9f68adf3fe2944548ecc159dc4e3b440 100644 |
--- a/Source/core/rendering/RenderMultiColumnSet.h |
+++ b/Source/core/rendering/RenderMultiColumnSet.h |
@@ -28,6 +28,7 @@ |
#define RenderMultiColumnSet_h |
#include "core/rendering/RenderRegionSet.h" |
+#include "wtf/Vector.h" |
namespace WebCore { |
@@ -62,30 +63,14 @@ public: |
void updateMinimumColumnHeight(LayoutUnit height) { m_minimumColumnHeight = std::max(height, m_minimumColumnHeight); } |
LayoutUnit minimumColumnHeight() const { return m_minimumColumnHeight; } |
- unsigned forcedBreaksCount() const { return m_forcedBreaksCount; } |
- LayoutUnit forcedBreakOffset() const { return m_forcedBreakOffset; } |
- LayoutUnit maximumDistanceBetweenForcedBreaks() const { return m_maximumDistanceBetweenForcedBreaks; } |
- void clearForcedBreaks() |
- { |
- m_forcedBreaksCount = 0; |
- m_maximumDistanceBetweenForcedBreaks = 0; |
- m_forcedBreakOffset = 0; |
- } |
- void addForcedBreak(LayoutUnit offsetFromFirstPage) |
- { |
- ASSERT(!computedColumnHeight()); |
- LayoutUnit distanceFromLastBreak = offsetFromFirstPage - m_forcedBreakOffset; |
- if (!distanceFromLastBreak) |
- return; |
- m_forcedBreaksCount++; |
- m_maximumDistanceBetweenForcedBreaks = std::max(m_maximumDistanceBetweenForcedBreaks, distanceFromLastBreak); |
- m_forcedBreakOffset = offsetFromFirstPage; |
- } |
+ unsigned forcedBreaksCount() const { return m_contentRuns.size(); } |
+ void clearForcedBreaks(); |
+ void addForcedBreak(LayoutUnit offsetFromFirstPage); |
- // Calculate the column height when contents are supposed to be balanced. If 'initial' is set, |
- // guess an initial column height; otherwise, stretch the column height a tad. Return true if |
- // column height changed and another layout pass is required. |
- bool calculateBalancedHeight(bool initial); |
+ // (Re-)calculate the column height when contents are supposed to be balanced. If 'initial' is |
+ // set, guess an initial column height; otherwise, stretch the column height a tad. Return true |
+ // if column height changed and another layout pass is required. |
+ bool recalculateBalancedHeight(bool initial); |
// Record space shortage (the amount of space that would have been enough to prevent some |
// element from being moved to the next column) at a column break. The smallest amount of space |
@@ -139,17 +124,52 @@ private: |
void setAndConstrainColumnHeight(LayoutUnit); |
- unsigned m_computedColumnCount; |
- LayoutUnit m_computedColumnWidth; |
+ // Return the index of the content run with the currently tallest columns, taking all implicit |
+ // breaks assumed so far into account. |
+ unsigned findRunWithTallestColumns() const; |
+ |
+ // Given the current list of content runs, make assumptions about where we need to insert |
+ // implicit breaks (if there's room for any at all; depending on the number of explicit breaks), |
+ // and store the results. This is needed in order to balance the columns. |
+ void distributeImplicitBreaks(); |
+ |
+ LayoutUnit calculateBalancedHeight(bool initial) const; |
+ |
+ unsigned m_computedColumnCount; // Used column count (the resulting 'N' from the pseudo-algorithm in the multicol spec) |
+ LayoutUnit m_computedColumnWidth; // Used column width (the resulting 'W' from the pseudo-algorithm in the multicol spec) |
LayoutUnit m_computedColumnHeight; |
// The following variables are used when balancing the column set. |
LayoutUnit m_maxColumnHeight; // Maximum column height allowed. |
LayoutUnit m_minSpaceShortage; // The smallest amout of space shortage that caused a column break. |
LayoutUnit m_minimumColumnHeight; |
- unsigned m_forcedBreaksCount; // FIXME: We will ultimately need to cache more information to balance around forced breaks properly. |
- LayoutUnit m_maximumDistanceBetweenForcedBreaks; |
- LayoutUnit m_forcedBreakOffset; |
+ |
+ // A run of content without explicit (forced) breaks; i.e. a flow thread portion between two |
+ // explicit breaks, between flow thread start and an explicit break, between an explicit break |
+ // and flow thread end, or, in cases when there are no explicit breaks at all: between flow flow |
+ // thread start and flow thread end. We need to know where the explicit breaks are, in order to |
+ // figure out where the implicit breaks will end up, so that we get the columns properly |
+ // balanced. A content run starts out as representing one single column, and will represent one |
+ // additional column for each implicit break "inserted" there. |
+ class ContentRun { |
+ public: |
+ ContentRun(LayoutUnit breakOffset) |
+ : m_breakOffset(breakOffset) |
+ , m_assumedImplicitBreaks(0) { } |
+ |
+ unsigned assumedImplicitBreaks() const { return m_assumedImplicitBreaks; } |
+ void assumeAnotherImplicitBreak() { m_assumedImplicitBreaks++; } |
+ LayoutUnit breakOffset() const { return m_breakOffset; } |
+ |
+ // Return the column height that this content run would require, considering the implicit |
+ // breaks assumed so far. |
+ LayoutUnit columnLogicalHeight(LayoutUnit startOffset) const { return ceilf(float(m_breakOffset - startOffset) / float(m_assumedImplicitBreaks + 1)); } |
+ |
+ private: |
+ LayoutUnit m_breakOffset; // Flow thread offset where this run ends. |
+ unsigned m_assumedImplicitBreaks; // Number of implicit breaks in this run assumed so far. |
+ }; |
+ Vector<ContentRun, 1> m_contentRuns; |
}; |
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderMultiColumnSet, isRenderMultiColumnSet()); |