Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / core / layout / MultiColumnFragmentainerGroup.h
blob1de413e3a119849b4057522e31373473a9eb0741
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef MultiColumnFragmentainerGroup_h
6 #define MultiColumnFragmentainerGroup_h
8 #include "core/layout/LayoutMultiColumnFlowThread.h"
9 #include "wtf/Allocator.h"
11 namespace blink {
13 // A group of columns, that are laid out in the inline progression direction, all with the same
14 // column height.
16 // When a multicol container is inside another fragmentation context, and said multicol container
17 // lives in multiple outer fragmentainers (pages / columns), we need to put these inner columns into
18 // separate groups, with one group per outer fragmentainer. Such a group of columns is what
19 // comprises a "row of column boxes" in spec lingo.
21 // Column balancing, when enabled, takes place within a column fragmentainer group.
23 // Each fragmentainer group may have its own actual column count (if there are unused columns
24 // because of forced breaks, for example). If there are multiple fragmentainer groups, the actual
25 // column count must not exceed the used column count (the one calculated based on column-count and
26 // column-width from CSS), or they'd overflow the outer fragmentainer in the inline direction. If we
27 // need more columns than what a group has room for, we'll create another group and put them there
28 // (and make them appear in the next outer fragmentainer).
29 class MultiColumnFragmentainerGroup {
30 ALLOW_ONLY_INLINE_ALLOCATION();
31 public:
32 MultiColumnFragmentainerGroup(LayoutMultiColumnSet&);
34 bool isLastGroup() const;
36 // Position within the LayoutMultiColumnSet.
37 LayoutUnit logicalTop() const { return m_logicalTop; }
38 void setLogicalTop(LayoutUnit logicalTop) { m_logicalTop = logicalTop; }
40 LayoutUnit logicalHeight() const { return m_columnHeight; }
42 LayoutSize offsetFromColumnSet() const;
44 // Return the block offset from the enclosing flow thread, if nested. In the coordinate space
45 // of the enclosing flow thread.
46 LayoutUnit blockOffsetInEnclosingFlowThread() const;
48 // The top of our flow thread portion
49 LayoutUnit logicalTopInFlowThread() const { return m_logicalTopInFlowThread; }
50 void setLogicalTopInFlowThread(LayoutUnit logicalTopInFlowThread) { m_logicalTopInFlowThread = logicalTopInFlowThread; }
52 // The bottom of our flow thread portion
53 LayoutUnit logicalBottomInFlowThread() const { return m_logicalBottomInFlowThread; }
54 void setLogicalBottomInFlowThread(LayoutUnit logicalBottomInFlowThread) { ASSERT(logicalBottomInFlowThread >= m_logicalTopInFlowThread); m_logicalBottomInFlowThread = logicalBottomInFlowThread; }
56 // The height of our flow thread portion
57 LayoutUnit logicalHeightInFlowThread() const { return m_logicalBottomInFlowThread - m_logicalTopInFlowThread; }
59 bool heightIsAuto() const;
60 void resetColumnHeight();
61 void addContentRun(LayoutUnit endOffsetInFlowThread);
62 void updateMinimumColumnHeight(LayoutUnit height) { m_minimumColumnHeight = std::max(height, m_minimumColumnHeight); }
63 void recordSpaceShortage(LayoutUnit);
64 bool recalculateColumnHeight(BalancedColumnHeightCalculation calculationMode);
66 LayoutSize flowThreadTranslationAtOffset(LayoutUnit offsetInFlowThread) const;
67 LayoutUnit columnLogicalTopForOffset(LayoutUnit offsetInFlowThread) const;
68 LayoutPoint visualPointToFlowThreadPoint(const LayoutPoint& visualPoint) const;
69 LayoutRect fragmentsBoundingBox(const LayoutRect& boundingBoxInFlowThread) const;
71 void collectLayerFragments(DeprecatedPaintLayerFragments&, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect) const;
72 LayoutRect calculateOverflow() const;
74 // The "CSS actual" value of column-count. This includes overflowing columns, if any.
75 unsigned actualColumnCount() const;
77 private:
78 LayoutUnit heightAdjustedForRowOffset(LayoutUnit height) const;
79 LayoutUnit calculateMaxColumnHeight() const;
80 void setAndConstrainColumnHeight(LayoutUnit);
82 // Return the index of the content run with the currently tallest columns, taking all implicit
83 // breaks assumed so far into account.
84 unsigned findRunWithTallestColumns() const;
86 // Given the current list of content runs, make assumptions about where we need to insert
87 // implicit breaks (if there's room for any at all; depending on the number of explicit breaks),
88 // and store the results. This is needed in order to balance the columns.
89 void distributeImplicitBreaks();
91 LayoutUnit calculateColumnHeight(BalancedColumnHeightCalculation) const;
93 LayoutRect columnRectAt(unsigned columnIndex) const;
94 LayoutUnit logicalTopInFlowThreadAt(unsigned columnIndex) const { return m_logicalTopInFlowThread + columnIndex * m_columnHeight; }
95 LayoutRect flowThreadPortionRectAt(unsigned columnIndex) const;
96 LayoutRect flowThreadPortionOverflowRectAt(unsigned columnIndex) const;
98 enum ColumnIndexCalculationMode {
99 ClampToExistingColumns, // Stay within the range of already existing columns.
100 AssumeNewColumns // Allow column indices outside the range of already existing columns.
102 unsigned columnIndexAtOffset(LayoutUnit offsetInFlowThread, ColumnIndexCalculationMode = ClampToExistingColumns) const;
104 // Return the column that the specified visual point belongs to. Only the coordinate on the
105 // column progression axis is relevant. Every point belongs to a column, even if said point is
106 // not inside any of the columns.
107 unsigned columnIndexAtVisualPoint(const LayoutPoint& visualPoint) const;
109 // Get the first and the last column intersecting the specified block range.
110 // Note that |logicalBottomInFlowThread| is an exclusive endpoint.
111 void columnIntervalForBlockRangeInFlowThread(LayoutUnit logicalTopInFlowThread, LayoutUnit logicalBottomInFlowThread, unsigned& firstColumn, unsigned& lastColumn) const;
113 // Get the first and the last column intersecting the specified visual rectangle.
114 void columnIntervalForVisualRect(const LayoutRect&, unsigned& firstColumn, unsigned& lastColumn) const;
116 LayoutMultiColumnSet& m_columnSet;
118 LayoutUnit m_logicalTop;
119 LayoutUnit m_logicalTopInFlowThread;
120 LayoutUnit m_logicalBottomInFlowThread;
122 LayoutUnit m_columnHeight;
124 // The following variables are used when balancing the column set.
125 LayoutUnit m_maxColumnHeight; // Maximum column height allowed.
126 LayoutUnit m_minSpaceShortage; // The smallest amout of space shortage that caused a column break.
127 LayoutUnit m_minimumColumnHeight;
129 // A run of content without explicit (forced) breaks; i.e. a flow thread portion between two
130 // explicit breaks, between flow thread start and an explicit break, between an explicit break
131 // and flow thread end, or, in cases when there are no explicit breaks at all: between flow
132 // thread portion start and flow thread portion end. We need to know where the explicit breaks
133 // are, in order to figure out where the implicit breaks will end up, so that we get the columns
134 // properly balanced. A content run starts out as representing one single column, and will
135 // represent one additional column for each implicit break "inserted" there.
136 class ContentRun {
137 public:
138 ContentRun(LayoutUnit breakOffset)
139 : m_breakOffset(breakOffset)
140 , m_assumedImplicitBreaks(0) { }
142 unsigned assumedImplicitBreaks() const { return m_assumedImplicitBreaks; }
143 void assumeAnotherImplicitBreak() { m_assumedImplicitBreaks++; }
144 LayoutUnit breakOffset() const { return m_breakOffset; }
146 // Return the column height that this content run would require, considering the implicit
147 // breaks assumed so far.
148 LayoutUnit columnLogicalHeight(LayoutUnit startOffset) const { return ceilf((m_breakOffset - startOffset).toFloat() / float(m_assumedImplicitBreaks + 1)); }
150 private:
151 LayoutUnit m_breakOffset; // Flow thread offset where this run ends.
152 unsigned m_assumedImplicitBreaks; // Number of implicit breaks in this run assumed so far.
154 Vector<ContentRun, 1> m_contentRuns;
157 // List of all fragmentainer groups within a column set. There will always be at least one
158 // group. Deleting the one group is not allowed (or possible). There will be more than one group if
159 // the owning column set lives in multiple outer fragmentainers (e.g. multicol inside paged media).
160 class CORE_EXPORT MultiColumnFragmentainerGroupList {
161 DISALLOW_ALLOCATION();
162 public:
163 MultiColumnFragmentainerGroupList(LayoutMultiColumnSet&);
164 ~MultiColumnFragmentainerGroupList();
166 // Add an additional fragmentainer group to the end of the list, and return it.
167 MultiColumnFragmentainerGroup& addExtraGroup();
169 // Remove all fragmentainer groups but the first one.
170 void deleteExtraGroups();
172 MultiColumnFragmentainerGroup& first() { return m_groups.first(); }
173 const MultiColumnFragmentainerGroup& first() const { return m_groups.first(); }
174 MultiColumnFragmentainerGroup& last() { return m_groups.last(); }
175 const MultiColumnFragmentainerGroup& last() const { return m_groups.last(); }
177 typedef Vector<MultiColumnFragmentainerGroup, 1>::iterator iterator;
178 typedef Vector<MultiColumnFragmentainerGroup, 1>::const_iterator const_iterator;
180 iterator begin() { return m_groups.begin(); }
181 const_iterator begin() const { return m_groups.begin(); }
182 iterator end() { return m_groups.end(); }
183 const_iterator end() const { return m_groups.end(); }
185 size_t size() const { return m_groups.size(); }
186 MultiColumnFragmentainerGroup& operator[](size_t i) { return m_groups.at(i); }
187 const MultiColumnFragmentainerGroup& operator[](size_t i) const { return m_groups.at(i); }
189 void append(const MultiColumnFragmentainerGroup& group) { m_groups.append(group); }
190 void shrink(size_t size) { m_groups.shrink(size); }
192 private:
193 LayoutMultiColumnSet& m_columnSet;
195 Vector<MultiColumnFragmentainerGroup, 1> m_groups;
198 } // namespace blink
200 #endif // MultiColumnFragmentainerGroup_h