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

Side by Side Diff: third_party/WebKit/Source/core/layout/ColumnBalancer.cpp

Issue 2391893004: Reformat comments in core/layout up until LayoutBox (Closed)
Patch Set: Created 4 years, 2 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/layout/ColumnBalancer.h" 5 #include "core/layout/ColumnBalancer.h"
6 6
7 #include "core/layout/LayoutMultiColumnFlowThread.h" 7 #include "core/layout/LayoutMultiColumnFlowThread.h"
8 #include "core/layout/LayoutMultiColumnSet.h" 8 #include "core/layout/LayoutMultiColumnSet.h"
9 #include "core/layout/api/LineLayoutBlockFlow.h" 9 #include "core/layout/api/LineLayoutBlockFlow.h"
10 10
(...skipping 11 matching lines...) Expand all
22 ASSERT(!flowThreadOffset()); 22 ASSERT(!flowThreadOffset());
23 } 23 }
24 24
25 void ColumnBalancer::traverseSubtree(const LayoutBox& box) { 25 void ColumnBalancer::traverseSubtree(const LayoutBox& box) {
26 if (box.childrenInline() && box.isLayoutBlockFlow()) { 26 if (box.childrenInline() && box.isLayoutBlockFlow()) {
27 // Look for breaks between lines. 27 // Look for breaks between lines.
28 for (const RootInlineBox* line = toLayoutBlockFlow(box).firstRootBox(); 28 for (const RootInlineBox* line = toLayoutBlockFlow(box).firstRootBox();
29 line; line = line->nextRootBox()) { 29 line; line = line->nextRootBox()) {
30 LayoutUnit lineTopInFlowThread = 30 LayoutUnit lineTopInFlowThread =
31 m_flowThreadOffset + line->lineTopWithLeading(); 31 m_flowThreadOffset + line->lineTopWithLeading();
32 if (lineTopInFlowThread < logicalTopInFlowThread()) 32 if (lineTopInFlowThread < logicalTopInFlowThread()) continue;
33 continue; 33 if (lineTopInFlowThread >= logicalBottomInFlowThread()) break;
34 if (lineTopInFlowThread >= logicalBottomInFlowThread())
35 break;
36 examineLine(*line); 34 examineLine(*line);
37 } 35 }
38 } 36 }
39 37
40 const LayoutFlowThread* flowThread = columnSet().flowThread(); 38 const LayoutFlowThread* flowThread = columnSet().flowThread();
41 bool isHorizontalWritingMode = flowThread->isHorizontalWritingMode(); 39 bool isHorizontalWritingMode = flowThread->isHorizontalWritingMode();
42 40
43 // The break-after value from the previous in-flow block-level object to be jo ined with the 41 // The break-after value from the previous in-flow block-level object to be
42 // joined with the
44 // break-before value of the next in-flow block-level sibling. 43 // break-before value of the next in-flow block-level sibling.
ikilpatrick 2016/10/04 16:39:02 bad.
45 EBreak previousBreakAfterValue = BreakAuto; 44 EBreak previousBreakAfterValue = BreakAuto;
46 45
47 // Look for breaks between and inside block-level children. Even if this is a block flow with 46 // Look for breaks between and inside block-level children. Even if this is a
47 // block flow with
48 // inline children, there may be interesting floats to examine here. 48 // inline children, there may be interesting floats to examine here.
49 for (const LayoutObject* child = box.slowFirstChild(); child; 49 for (const LayoutObject* child = box.slowFirstChild(); child;
50 child = child->nextSibling()) { 50 child = child->nextSibling()) {
51 if (!child->isBox() || child->isInline()) 51 if (!child->isBox() || child->isInline()) continue;
52 continue;
53 const LayoutBox& childBox = toLayoutBox(*child); 52 const LayoutBox& childBox = toLayoutBox(*child);
54 LayoutRect overflowRect = childBox.layoutOverflowRect(); 53 LayoutRect overflowRect = childBox.layoutOverflowRect();
55 LayoutUnit childLogicalBottomWithOverflow = 54 LayoutUnit childLogicalBottomWithOverflow =
56 childBox.logicalTop() + 55 childBox.logicalTop() +
57 (isHorizontalWritingMode ? overflowRect.maxY() : overflowRect.maxX()); 56 (isHorizontalWritingMode ? overflowRect.maxY() : overflowRect.maxX());
58 if (m_flowThreadOffset + childLogicalBottomWithOverflow <= 57 if (m_flowThreadOffset + childLogicalBottomWithOverflow <=
59 logicalTopInFlowThread()) { 58 logicalTopInFlowThread()) {
60 // This child is fully above the flow thread portion we're examining. 59 // This child is fully above the flow thread portion we're examining.
61 continue; 60 continue;
62 } 61 }
63 LayoutUnit childLogicalTopWithOverflow = 62 LayoutUnit childLogicalTopWithOverflow =
64 childBox.logicalTop() + 63 childBox.logicalTop() +
65 (isHorizontalWritingMode ? overflowRect.y() : overflowRect.x()); 64 (isHorizontalWritingMode ? overflowRect.y() : overflowRect.x());
66 if (m_flowThreadOffset + childLogicalTopWithOverflow >= 65 if (m_flowThreadOffset + childLogicalTopWithOverflow >=
67 logicalBottomInFlowThread()) { 66 logicalBottomInFlowThread()) {
68 // This child is fully below the flow thread portion we're examining. We c annot just 67 // This child is fully below the flow thread portion we're examining. We
68 // cannot just
ikilpatrick 2016/10/04 16:39:02 bad.
69 // stop here, though, thanks to negative margins. So keep looking. 69 // stop here, though, thanks to negative margins. So keep looking.
70 continue; 70 continue;
71 } 71 }
72 if (childBox.isOutOfFlowPositioned() || childBox.isColumnSpanAll()) 72 if (childBox.isOutOfFlowPositioned() || childBox.isColumnSpanAll())
73 continue; 73 continue;
74 74
75 // Tables are wicked. Both table rows and table cells are relative to their table section. 75 // Tables are wicked. Both table rows and table cells are relative to their
76 // table section.
76 LayoutUnit offsetForThisChild = 77 LayoutUnit offsetForThisChild =
77 childBox.isTableRow() ? LayoutUnit() : childBox.logicalTop(); 78 childBox.isTableRow() ? LayoutUnit() : childBox.logicalTop();
78 m_flowThreadOffset += offsetForThisChild; 79 m_flowThreadOffset += offsetForThisChild;
79 80
80 examineBoxAfterEntering(childBox, previousBreakAfterValue); 81 examineBoxAfterEntering(childBox, previousBreakAfterValue);
81 // Unless the child is unsplittable, or if the child establishes an inner mu lticol 82 // Unless the child is unsplittable, or if the child establishes an inner
83 // multicol
ikilpatrick 2016/10/04 16:39:02 bad.
82 // container, we descend into its subtree for further examination. 84 // container, we descend into its subtree for further examination.
83 if (childBox.getPaginationBreakability() != LayoutBox::ForbidBreaks && 85 if (childBox.getPaginationBreakability() != LayoutBox::ForbidBreaks &&
84 (!childBox.isLayoutBlockFlow() || 86 (!childBox.isLayoutBlockFlow() ||
85 !toLayoutBlockFlow(childBox).multiColumnFlowThread())) 87 !toLayoutBlockFlow(childBox).multiColumnFlowThread()))
86 traverseSubtree(childBox); 88 traverseSubtree(childBox);
87 previousBreakAfterValue = childBox.breakAfter(); 89 previousBreakAfterValue = childBox.breakAfter();
88 examineBoxBeforeLeaving(childBox); 90 examineBoxBeforeLeaving(childBox);
89 91
90 m_flowThreadOffset -= offsetForThisChild; 92 m_flowThreadOffset -= offsetForThisChild;
91 } 93 }
92 } 94 }
93 95
94 InitialColumnHeightFinder::InitialColumnHeightFinder( 96 InitialColumnHeightFinder::InitialColumnHeightFinder(
95 const LayoutMultiColumnSet& columnSet, 97 const LayoutMultiColumnSet& columnSet, LayoutUnit logicalTopInFlowThread,
96 LayoutUnit logicalTopInFlowThread,
97 LayoutUnit logicalBottomInFlowThread) 98 LayoutUnit logicalBottomInFlowThread)
98 : ColumnBalancer(columnSet, 99 : ColumnBalancer(columnSet, logicalTopInFlowThread,
99 logicalTopInFlowThread,
100 logicalBottomInFlowThread) { 100 logicalBottomInFlowThread) {
101 m_shortestStruts.resize(columnSet.usedColumnCount()); 101 m_shortestStruts.resize(columnSet.usedColumnCount());
102 for (auto& strut : m_shortestStruts) 102 for (auto& strut : m_shortestStruts) strut = LayoutUnit::max() { }
103 strut = LayoutUnit::max();
104 traverse(); 103 traverse();
105 // We have now found each explicit / forced break, and their location. Now we need to figure out 104 // We have now found each explicit / forced break, and their location. Now we
106 // how many additional implicit / soft breaks we need and guess where they wil l occur, in order 105 // need to figure out how many additional implicit / soft breaks we need and
106 // guess where they will occur, in order
107 // to provide an initial column height. 107 // to provide an initial column height.
108 distributeImplicitBreaks(); 108 distributeImplicitBreaks();
109 } 109 }
110 110
111 LayoutUnit InitialColumnHeightFinder::initialMinimalBalancedHeight() const { 111 LayoutUnit InitialColumnHeightFinder::initialMinimalBalancedHeight() const {
112 unsigned index = contentRunIndexWithTallestColumns(); 112 unsigned index = contentRunIndexWithTallestColumns();
113 LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset() 113 LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset()
114 : logicalTopInFlowThread(); 114 : logicalTopInFlowThread();
115 return m_contentRuns[index].columnLogicalHeight(startOffset); 115 return m_contentRuns[index].columnLogicalHeight(startOffset);
116 } 116 }
117 117
118 void InitialColumnHeightFinder::examineBoxAfterEntering( 118 void InitialColumnHeightFinder::examineBoxAfterEntering(
119 const LayoutBox& box, 119 const LayoutBox& box, EBreak previousBreakAfterValue) {
120 EBreak previousBreakAfterValue) {
121 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { 120 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) {
122 if (box.needsForcedBreakBefore(previousBreakAfterValue)) { 121 if (box.needsForcedBreakBefore(previousBreakAfterValue)) {
123 addContentRun(flowThreadOffset()); 122 addContentRun(flowThreadOffset());
124 } else { 123 } else {
125 ASSERT(isFirstAfterBreak(flowThreadOffset()) || !box.paginationStrut()); 124 ASSERT(isFirstAfterBreak(flowThreadOffset()) || !box.paginationStrut());
126 if (isFirstAfterBreak(flowThreadOffset())) { 125 if (isFirstAfterBreak(flowThreadOffset())) {
127 // This box is first after a soft break. 126 // This box is first after a soft break.
128 recordStrutBeforeOffset(flowThreadOffset(), box.paginationStrut()); 127 recordStrutBeforeOffset(flowThreadOffset(), box.paginationStrut());
129 } 128 }
130 } 129 }
131 } 130 }
132 131
133 if (box.getPaginationBreakability() != LayoutBox::AllowAnyBreaks) { 132 if (box.getPaginationBreakability() != LayoutBox::AllowAnyBreaks) {
134 LayoutUnit unsplittableLogicalHeight = box.logicalHeight(); 133 LayoutUnit unsplittableLogicalHeight = box.logicalHeight();
135 if (box.isFloating()) 134 if (box.isFloating())
136 unsplittableLogicalHeight += box.marginBefore() + box.marginAfter(); 135 unsplittableLogicalHeight += box.marginBefore() + box.marginAfter();
137 m_tallestUnbreakableLogicalHeight = 136 m_tallestUnbreakableLogicalHeight =
138 std::max(m_tallestUnbreakableLogicalHeight, unsplittableLogicalHeight); 137 std::max(m_tallestUnbreakableLogicalHeight, unsplittableLogicalHeight);
139 return; 138 return;
140 } 139 }
141 // Need to examine inner multicol containers to find their tallest unbreakable piece of content. 140 // Need to examine inner multicol containers to find their tallest unbreakable
142 if (!box.isLayoutBlockFlow()) 141 // piece of content.
143 return; 142 if (!box.isLayoutBlockFlow()) return;
144 LayoutMultiColumnFlowThread* innerFlowThread = 143 LayoutMultiColumnFlowThread* innerFlowThread =
145 toLayoutBlockFlow(box).multiColumnFlowThread(); 144 toLayoutBlockFlow(box).multiColumnFlowThread();
146 if (!innerFlowThread || innerFlowThread->isLayoutPagedFlowThread()) 145 if (!innerFlowThread || innerFlowThread->isLayoutPagedFlowThread()) return;
147 return;
148 LayoutUnit offsetInInnerFlowThread = 146 LayoutUnit offsetInInnerFlowThread =
149 flowThreadOffset() - 147 flowThreadOffset() -
150 innerFlowThread->blockOffsetInEnclosingFragmentationContext(); 148 innerFlowThread->blockOffsetInEnclosingFragmentationContext();
151 LayoutUnit innerUnbreakableHeight = 149 LayoutUnit innerUnbreakableHeight =
152 innerFlowThread->tallestUnbreakableLogicalHeight(offsetInInnerFlowThread); 150 innerFlowThread->tallestUnbreakableLogicalHeight(offsetInInnerFlowThread);
153 m_tallestUnbreakableLogicalHeight = 151 m_tallestUnbreakableLogicalHeight =
154 std::max(m_tallestUnbreakableLogicalHeight, innerUnbreakableHeight); 152 std::max(m_tallestUnbreakableLogicalHeight, innerUnbreakableHeight);
155 } 153 }
156 154
157 void InitialColumnHeightFinder::examineBoxBeforeLeaving(const LayoutBox& box) {} 155 void InitialColumnHeightFinder::examineBoxBeforeLeaving(const LayoutBox& box) {}
158 156
159 static inline LayoutUnit columnLogicalHeightRequirementForLine( 157 static inline LayoutUnit columnLogicalHeightRequirementForLine(
160 const ComputedStyle& style, 158 const ComputedStyle& style, const RootInlineBox& lastLine) {
161 const RootInlineBox& lastLine) { 159 // We may require a certain minimum number of lines per page in order to
162 // We may require a certain minimum number of lines per page in order to satis fy 160 // satisfy
163 // orphans and widows, and that may affect the minimum page height. 161 // orphans and widows, and that may affect the minimum page height.
ikilpatrick 2016/10/04 16:39:02 bad.
164 unsigned minimumLineCount = 162 unsigned minimumLineCount =
165 std::max<unsigned>(style.orphans(), style.widows()); 163 std::max<unsigned>(style.orphans(), style.widows());
166 const RootInlineBox* firstLine = &lastLine; 164 const RootInlineBox* firstLine = &lastLine;
167 for (unsigned i = 1; i < minimumLineCount && firstLine->prevRootBox(); i++) 165 for (unsigned i = 1; i < minimumLineCount && firstLine->prevRootBox(); i++)
168 firstLine = firstLine->prevRootBox(); 166 firstLine = firstLine->prevRootBox();
169 return lastLine.lineBottomWithLeading() - firstLine->lineTopWithLeading(); 167 return lastLine.lineBottomWithLeading() - firstLine->lineTopWithLeading();
170 } 168 }
171 169
172 void InitialColumnHeightFinder::examineLine(const RootInlineBox& line) { 170 void InitialColumnHeightFinder::examineLine(const RootInlineBox& line) {
173 LayoutUnit lineTop = line.lineTopWithLeading(); 171 LayoutUnit lineTop = line.lineTopWithLeading();
174 LayoutUnit lineTopInFlowThread = flowThreadOffset() + lineTop; 172 LayoutUnit lineTopInFlowThread = flowThreadOffset() + lineTop;
175 LayoutUnit minimumLogialHeight = 173 LayoutUnit minimumLogialHeight =
176 columnLogicalHeightRequirementForLine(line.block().styleRef(), line); 174 columnLogicalHeightRequirementForLine(line.block().styleRef(), line);
177 m_tallestUnbreakableLogicalHeight = 175 m_tallestUnbreakableLogicalHeight =
178 std::max(m_tallestUnbreakableLogicalHeight, minimumLogialHeight); 176 std::max(m_tallestUnbreakableLogicalHeight, minimumLogialHeight);
179 ASSERT( 177 ASSERT(
180 isFirstAfterBreak(lineTopInFlowThread) || !line.paginationStrut() || 178 isFirstAfterBreak(lineTopInFlowThread) || !line.paginationStrut() ||
181 !isLogicalTopWithinBounds(lineTopInFlowThread - line.paginationStrut())); 179 !isLogicalTopWithinBounds(lineTopInFlowThread - line.paginationStrut()));
182 if (isFirstAfterBreak(lineTopInFlowThread)) 180 if (isFirstAfterBreak(lineTopInFlowThread))
183 recordStrutBeforeOffset(lineTopInFlowThread, line.paginationStrut()); 181 recordStrutBeforeOffset(lineTopInFlowThread, line.paginationStrut());
184 } 182 }
185 183
186 void InitialColumnHeightFinder::recordStrutBeforeOffset( 184 void InitialColumnHeightFinder::recordStrutBeforeOffset(
187 LayoutUnit offsetInFlowThread, 185 LayoutUnit offsetInFlowThread, LayoutUnit strut) {
188 LayoutUnit strut) {
189 ASSERT(columnSet().usedColumnCount() >= 1); 186 ASSERT(columnSet().usedColumnCount() >= 1);
190 unsigned columnCount = columnSet().usedColumnCount(); 187 unsigned columnCount = columnSet().usedColumnCount();
191 ASSERT(m_shortestStruts.size() == columnCount); 188 ASSERT(m_shortestStruts.size() == columnCount);
192 unsigned index = groupAtOffset(offsetInFlowThread) 189 unsigned index = groupAtOffset(offsetInFlowThread)
193 .columnIndexAtOffset(offsetInFlowThread - strut, 190 .columnIndexAtOffset(offsetInFlowThread - strut,
194 LayoutBox::AssociateWithLatterPage); 191 LayoutBox::AssociateWithLatterPage);
195 if (index >= columnCount) 192 if (index >= columnCount) return;
196 return;
197 m_shortestStruts[index] = std::min(m_shortestStruts[index], strut); 193 m_shortestStruts[index] = std::min(m_shortestStruts[index], strut);
198 } 194 }
199 195
200 LayoutUnit InitialColumnHeightFinder::spaceUsedByStrutsAt( 196 LayoutUnit InitialColumnHeightFinder::spaceUsedByStrutsAt(
201 LayoutUnit offsetInFlowThread) const { 197 LayoutUnit offsetInFlowThread) const {
202 unsigned stopBeforeColumn = 198 unsigned stopBeforeColumn =
203 groupAtOffset(offsetInFlowThread) 199 groupAtOffset(offsetInFlowThread)
204 .columnIndexAtOffset(offsetInFlowThread, 200 .columnIndexAtOffset(offsetInFlowThread,
205 LayoutBox::AssociateWithLatterPage) + 201 LayoutBox::AssociateWithLatterPage) +
206 1; 202 1;
207 stopBeforeColumn = std::min(stopBeforeColumn, columnSet().usedColumnCount()); 203 stopBeforeColumn = std::min(stopBeforeColumn, columnSet().usedColumnCount());
208 ASSERT(stopBeforeColumn <= m_shortestStruts.size()); 204 ASSERT(stopBeforeColumn <= m_shortestStruts.size());
209 LayoutUnit totalStrutSpace; 205 LayoutUnit totalStrutSpace;
210 for (unsigned i = 0; i < stopBeforeColumn; i++) { 206 for (unsigned i = 0; i < stopBeforeColumn; i++) {
211 if (m_shortestStruts[i] != LayoutUnit::max()) 207 if (m_shortestStruts[i] != LayoutUnit::max())
212 totalStrutSpace += m_shortestStruts[i]; 208 totalStrutSpace += m_shortestStruts[i];
213 } 209 }
214 return totalStrutSpace; 210 return totalStrutSpace;
215 } 211 }
216 212
217 void InitialColumnHeightFinder::addContentRun( 213 void InitialColumnHeightFinder::addContentRun(
218 LayoutUnit endOffsetInFlowThread) { 214 LayoutUnit endOffsetInFlowThread) {
219 endOffsetInFlowThread -= spaceUsedByStrutsAt(endOffsetInFlowThread); 215 endOffsetInFlowThread -= spaceUsedByStrutsAt(endOffsetInFlowThread);
220 if (!m_contentRuns.isEmpty() && 216 if (!m_contentRuns.isEmpty() &&
221 endOffsetInFlowThread <= m_contentRuns.last().breakOffset()) 217 endOffsetInFlowThread <= m_contentRuns.last().breakOffset())
222 return; 218 return;
223 // Append another item as long as we haven't exceeded used column count. What ends up in the 219 // Append another item as long as we haven't exceeded used column count. What
220 // ends up in the
224 // overflow area shouldn't affect column balancing. 221 // overflow area shouldn't affect column balancing.
ikilpatrick 2016/10/04 16:39:02 bad.
225 if (m_contentRuns.size() < columnSet().usedColumnCount()) 222 if (m_contentRuns.size() < columnSet().usedColumnCount())
226 m_contentRuns.append(ContentRun(endOffsetInFlowThread)); 223 m_contentRuns.append(ContentRun(endOffsetInFlowThread));
227 } 224 }
228 225
229 unsigned InitialColumnHeightFinder::contentRunIndexWithTallestColumns() const { 226 unsigned InitialColumnHeightFinder::contentRunIndexWithTallestColumns() const {
230 unsigned indexWithLargestHeight = 0; 227 unsigned indexWithLargestHeight = 0;
231 LayoutUnit largestHeight; 228 LayoutUnit largestHeight;
232 LayoutUnit previousOffset = logicalTopInFlowThread(); 229 LayoutUnit previousOffset = logicalTopInFlowThread();
233 size_t runCount = m_contentRuns.size(); 230 size_t runCount = m_contentRuns.size();
234 ASSERT(runCount); 231 ASSERT(runCount);
235 for (size_t i = 0; i < runCount; i++) { 232 for (size_t i = 0; i < runCount; i++) {
236 const ContentRun& run = m_contentRuns[i]; 233 const ContentRun& run = m_contentRuns[i];
237 LayoutUnit height = run.columnLogicalHeight(previousOffset); 234 LayoutUnit height = run.columnLogicalHeight(previousOffset);
238 if (largestHeight < height) { 235 if (largestHeight < height) {
239 largestHeight = height; 236 largestHeight = height;
240 indexWithLargestHeight = i; 237 indexWithLargestHeight = i;
241 } 238 }
242 previousOffset = run.breakOffset(); 239 previousOffset = run.breakOffset();
243 } 240 }
244 return indexWithLargestHeight; 241 return indexWithLargestHeight;
245 } 242 }
246 243
247 void InitialColumnHeightFinder::distributeImplicitBreaks() { 244 void InitialColumnHeightFinder::distributeImplicitBreaks() {
248 // Insert a final content run to encompass all content. This will include over flow if we're at 245 // Insert a final content run to encompass all content. This will include
246 // overflow if we're at
249 // the end of the multicol container. 247 // the end of the multicol container.
ikilpatrick 2016/10/04 16:39:02 bad.
250 addContentRun(logicalBottomInFlowThread()); 248 addContentRun(logicalBottomInFlowThread());
251 unsigned columnCount = m_contentRuns.size(); 249 unsigned columnCount = m_contentRuns.size();
252 250
253 // If there is room for more breaks (to reach the used value of column-count), imagine that we 251 // If there is room for more breaks (to reach the used value of column-count),
254 // insert implicit breaks at suitable locations. At any given time, the conten t run with the 252 // imagine that we insert implicit breaks at suitable locations. At any given
255 // currently tallest columns will get another implicit break "inserted", which will increase its 253 // time, the content run with the currently tallest columns will get another
256 // column count by one and shrink its columns' height. Repeat until we have th e desired total 254 // implicit break "inserted", which will increase its column count by one and
257 // number of breaks. The largest column height among the runs will then be the initial column 255 // shrink its columns' height. Repeat until we have the desired total number
258 // height for the balancer to use. 256 // of breaks. The largest column height among the runs will then be the
257 // initial column height for the balancer to use.
259 while (columnCount < columnSet().usedColumnCount()) { 258 while (columnCount < columnSet().usedColumnCount()) {
260 unsigned index = contentRunIndexWithTallestColumns(); 259 unsigned index = contentRunIndexWithTallestColumns();
261 m_contentRuns[index].assumeAnotherImplicitBreak(); 260 m_contentRuns[index].assumeAnotherImplicitBreak();
262 columnCount++; 261 columnCount++;
263 } 262 }
264 } 263 }
265 264
266 MinimumSpaceShortageFinder::MinimumSpaceShortageFinder( 265 MinimumSpaceShortageFinder::MinimumSpaceShortageFinder(
267 const LayoutMultiColumnSet& columnSet, 266 const LayoutMultiColumnSet& columnSet, LayoutUnit logicalTopInFlowThread,
268 LayoutUnit logicalTopInFlowThread,
269 LayoutUnit logicalBottomInFlowThread) 267 LayoutUnit logicalBottomInFlowThread)
270 : ColumnBalancer(columnSet, 268 : ColumnBalancer(columnSet, logicalTopInFlowThread,
271 logicalTopInFlowThread,
272 logicalBottomInFlowThread), 269 logicalBottomInFlowThread),
273 m_minimumSpaceShortage(LayoutUnit::max()), 270 m_minimumSpaceShortage(LayoutUnit::max()),
274 m_pendingStrut(LayoutUnit::min()), 271 m_pendingStrut(LayoutUnit::min()),
275 m_forcedBreaksCount(0) { 272 m_forcedBreaksCount(0) {
276 traverse(); 273 traverse();
277 } 274 }
278 275
279 void MinimumSpaceShortageFinder::examineBoxAfterEntering( 276 void MinimumSpaceShortageFinder::examineBoxAfterEntering(
280 const LayoutBox& box, 277 const LayoutBox& box, EBreak previousBreakAfterValue) {
281 EBreak previousBreakAfterValue) {
282 LayoutBox::PaginationBreakability breakability = 278 LayoutBox::PaginationBreakability breakability =
283 box.getPaginationBreakability(); 279 box.getPaginationBreakability();
284 280
285 // Look for breaks before the child box. 281 // Look for breaks before the child box.
286 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { 282 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) {
287 if (box.needsForcedBreakBefore(previousBreakAfterValue)) { 283 if (box.needsForcedBreakBefore(previousBreakAfterValue)) {
288 m_forcedBreaksCount++; 284 m_forcedBreaksCount++;
289 } else { 285 } else {
290 ASSERT(isFirstAfterBreak(flowThreadOffset()) || !box.paginationStrut()); 286 ASSERT(isFirstAfterBreak(flowThreadOffset()) || !box.paginationStrut());
291 if (isFirstAfterBreak(flowThreadOffset())) { 287 if (isFirstAfterBreak(flowThreadOffset())) {
292 // This box is first after a soft break. 288 // This box is first after a soft break.
293 LayoutUnit strut = box.paginationStrut(); 289 LayoutUnit strut = box.paginationStrut();
294 // Figure out how much more space we would need to prevent it from being pushed to the next column. 290 // Figure out how much more space we would need to prevent it from being
291 // pushed to the next column.
295 recordSpaceShortage(box.logicalHeight() - strut); 292 recordSpaceShortage(box.logicalHeight() - strut);
296 if (breakability != LayoutBox::ForbidBreaks && 293 if (breakability != LayoutBox::ForbidBreaks &&
297 m_pendingStrut == LayoutUnit::min()) { 294 m_pendingStrut == LayoutUnit::min()) {
298 // We now want to look for the first piece of unbreakable content (e.g . a line or a 295 // We now want to look for the first piece of unbreakable content
299 // block-displayed image) inside this block. That ought to be a good c andidate for 296 // (e.g. a line or a block-displayed image) inside this block. That
300 // minimum space shortage; a much better one than reporting space shor tage for the 297 // ought to be a good candidate for minimum space shortage; a much
301 // entire block (which we'll also do (further down), in case we couldn 't find anything 298 // better one than reporting space shortage for the entire block
302 // more suitable). 299 // (which we'll also do (further down), in case we couldn't find
300 // anything more suitable).
303 m_pendingStrut = strut; 301 m_pendingStrut = strut;
304 } 302 }
305 } 303 }
306 } 304 }
307 } 305 }
308 306
309 if (breakability != LayoutBox::ForbidBreaks) { 307 if (breakability != LayoutBox::ForbidBreaks) {
310 // See if this breakable box crosses column boundaries. 308 // See if this breakable box crosses column boundaries.
311 LayoutUnit bottomInFlowThread = flowThreadOffset() + box.logicalHeight(); 309 LayoutUnit bottomInFlowThread = flowThreadOffset() + box.logicalHeight();
312 const MultiColumnFragmentainerGroup& group = 310 const MultiColumnFragmentainerGroup& group =
313 groupAtOffset(flowThreadOffset()); 311 groupAtOffset(flowThreadOffset());
314 if (isFirstAfterBreak(flowThreadOffset()) || 312 if (isFirstAfterBreak(flowThreadOffset()) ||
315 group.columnLogicalTopForOffset(flowThreadOffset()) != 313 group.columnLogicalTopForOffset(flowThreadOffset()) !=
316 group.columnLogicalTopForOffset(bottomInFlowThread)) { 314 group.columnLogicalTopForOffset(bottomInFlowThread)) {
317 // If the child crosses a column boundary, record space shortage, in case nothing 315 // If the child crosses a column boundary, record space shortage, in case
318 // inside it has already done so. The column balancer needs to know by how much it 316 // nothing inside it has already done so. The column balancer needs to
319 // has to stretch the columns to make more content fit. If no breaks are r eported 317 // know by how much it has to stretch the columns to make more content
320 // (but do occur), the balancer will have no clue. Only measure the space after the 318 // fit. If no breaks are reported (but do occur), the balancer will have
321 // last column boundary, in case it crosses more than one. 319 // no clue. Only measure the space after the last column boundary, in case
320 // it crosses more than one.
322 LayoutUnit spaceUsedInLastColumn = 321 LayoutUnit spaceUsedInLastColumn =
323 bottomInFlowThread - 322 bottomInFlowThread -
324 group.columnLogicalTopForOffset(bottomInFlowThread); 323 group.columnLogicalTopForOffset(bottomInFlowThread);
325 recordSpaceShortage(spaceUsedInLastColumn); 324 recordSpaceShortage(spaceUsedInLastColumn);
326 } 325 }
327 } 326 }
328 327
329 // If this is an inner multicol container, look for space shortage inside it. 328 // If this is an inner multicol container, look for space shortage inside it.
330 if (!box.isLayoutBlockFlow()) 329 if (!box.isLayoutBlockFlow()) return;
331 return;
332 LayoutMultiColumnFlowThread* flowThread = 330 LayoutMultiColumnFlowThread* flowThread =
333 toLayoutBlockFlow(box).multiColumnFlowThread(); 331 toLayoutBlockFlow(box).multiColumnFlowThread();
334 if (!flowThread || flowThread->isLayoutPagedFlowThread()) 332 if (!flowThread || flowThread->isLayoutPagedFlowThread()) return;
335 return;
336 for (const LayoutMultiColumnSet* columnSet = 333 for (const LayoutMultiColumnSet* columnSet =
337 flowThread->firstMultiColumnSet(); 334 flowThread->firstMultiColumnSet();
338 columnSet; columnSet = columnSet->nextSiblingMultiColumnSet()) { 335 columnSet; columnSet = columnSet->nextSiblingMultiColumnSet()) {
339 // Establish an inner shortage finder for this column set in the inner multi col 336 // Establish an inner shortage finder for this column set in the inner
340 // container. We need to let it walk through all fragmentainer groups in one go, or we'd 337 // multicol container. We need to let it walk through all fragmentainer
341 // miss the column boundaries between each fragmentainer group. We need to r ecord space 338 // groups in one go, or we'd miss the column boundaries between each
342 // shortage there too. 339 // fragmentainer group. We need to record space shortage there too.
343 MinimumSpaceShortageFinder innerFinder( 340 MinimumSpaceShortageFinder innerFinder(
344 *columnSet, columnSet->logicalTopInFlowThread(), 341 *columnSet, columnSet->logicalTopInFlowThread(),
345 columnSet->logicalBottomInFlowThread()); 342 columnSet->logicalBottomInFlowThread());
346 recordSpaceShortage(innerFinder.minimumSpaceShortage()); 343 recordSpaceShortage(innerFinder.minimumSpaceShortage());
347 } 344 }
348 } 345 }
349 346
350 void MinimumSpaceShortageFinder::examineBoxBeforeLeaving(const LayoutBox& box) { 347 void MinimumSpaceShortageFinder::examineBoxBeforeLeaving(const LayoutBox& box) {
351 if (m_pendingStrut == LayoutUnit::min() || 348 if (m_pendingStrut == LayoutUnit::min() ||
352 box.getPaginationBreakability() != LayoutBox::ForbidBreaks) 349 box.getPaginationBreakability() != LayoutBox::ForbidBreaks)
353 return; 350 return;
354 351
355 // The previous break was before a breakable block. Here's the first piece of unbreakable 352 // The previous break was before a breakable block. Here's the first piece of
356 // content after / inside that block. We want to record the distance from the top of the column 353 // unbreakable content after / inside that block. We want to record the
357 // to the bottom of this box as space shortage. 354 // distance from the top of the column to the bottom of this box as space
355 // shortage.
358 LayoutUnit logicalOffsetFromCurrentColumn = 356 LayoutUnit logicalOffsetFromCurrentColumn =
359 offsetFromColumnLogicalTop(flowThreadOffset()); 357 offsetFromColumnLogicalTop(flowThreadOffset());
360 recordSpaceShortage(logicalOffsetFromCurrentColumn + box.logicalHeight() - 358 recordSpaceShortage(logicalOffsetFromCurrentColumn + box.logicalHeight() -
361 m_pendingStrut); 359 m_pendingStrut);
362 m_pendingStrut = LayoutUnit::min(); 360 m_pendingStrut = LayoutUnit::min();
363 } 361 }
364 362
365 void MinimumSpaceShortageFinder::examineLine(const RootInlineBox& line) { 363 void MinimumSpaceShortageFinder::examineLine(const RootInlineBox& line) {
366 LayoutUnit lineTop = line.lineTopWithLeading(); 364 LayoutUnit lineTop = line.lineTopWithLeading();
367 LayoutUnit lineTopInFlowThread = flowThreadOffset() + lineTop; 365 LayoutUnit lineTopInFlowThread = flowThreadOffset() + lineTop;
368 LayoutUnit lineHeight = line.lineBottomWithLeading() - lineTop; 366 LayoutUnit lineHeight = line.lineBottomWithLeading() - lineTop;
369 if (m_pendingStrut != LayoutUnit::min()) { 367 if (m_pendingStrut != LayoutUnit::min()) {
370 // The previous break was before a breakable block. Here's the first line af ter / inside 368 // The previous break was before a breakable block. Here's the first line
371 // that block. We want to record the distance from the top of the column to the bottom of 369 // after / inside that block. We want to record the distance from the top of
372 // this box as space shortage. 370 // the column to the bottom of this box as space shortage.
373 LayoutUnit logicalOffsetFromCurrentColumn = 371 LayoutUnit logicalOffsetFromCurrentColumn =
374 offsetFromColumnLogicalTop(lineTopInFlowThread); 372 offsetFromColumnLogicalTop(lineTopInFlowThread);
375 recordSpaceShortage(logicalOffsetFromCurrentColumn + lineHeight - 373 recordSpaceShortage(logicalOffsetFromCurrentColumn + lineHeight -
376 m_pendingStrut); 374 m_pendingStrut);
377 m_pendingStrut = LayoutUnit::min(); 375 m_pendingStrut = LayoutUnit::min();
378 return; 376 return;
379 } 377 }
380 ASSERT( 378 ASSERT(
381 isFirstAfterBreak(lineTopInFlowThread) || !line.paginationStrut() || 379 isFirstAfterBreak(lineTopInFlowThread) || !line.paginationStrut() ||
382 !isLogicalTopWithinBounds(lineTopInFlowThread - line.paginationStrut())); 380 !isLogicalTopWithinBounds(lineTopInFlowThread - line.paginationStrut()));
383 if (isFirstAfterBreak(lineTopInFlowThread)) 381 if (isFirstAfterBreak(lineTopInFlowThread))
384 recordSpaceShortage(lineHeight - line.paginationStrut()); 382 recordSpaceShortage(lineHeight - line.paginationStrut());
385 383
386 // Even if the line box itself fits fine inside a column, some content may ove rflow the line 384 // Even if the line box itself fits fine inside a column, some content may
387 // box bottom (due to restrictive line-height, for instance). We should check if some portion 385 // overflow the line box bottom (due to restrictive line-height, for
388 // of said overflow ends up in the next column. That counts as space shortage. 386 // instance). We should check if some portion of said overflow ends up in the
387 // next column. That counts as space shortage.
389 const MultiColumnFragmentainerGroup& group = 388 const MultiColumnFragmentainerGroup& group =
390 groupAtOffset(lineTopInFlowThread); 389 groupAtOffset(lineTopInFlowThread);
391 LayoutUnit lineBottomWithOverflow = 390 LayoutUnit lineBottomWithOverflow =
392 lineTopInFlowThread + line.lineBottom() - lineTop; 391 lineTopInFlowThread + line.lineBottom() - lineTop;
393 if (group.columnLogicalTopForOffset(lineTopInFlowThread) != 392 if (group.columnLogicalTopForOffset(lineTopInFlowThread) !=
394 group.columnLogicalTopForOffset(lineBottomWithOverflow)) { 393 group.columnLogicalTopForOffset(lineBottomWithOverflow)) {
395 LayoutUnit shortage = 394 LayoutUnit shortage =
396 lineBottomWithOverflow - 395 lineBottomWithOverflow -
397 group.columnLogicalTopForOffset(lineBottomWithOverflow); 396 group.columnLogicalTopForOffset(lineBottomWithOverflow);
398 recordSpaceShortage(shortage); 397 recordSpaceShortage(shortage);
399 } 398 }
400 } 399 }
401 400
402 } // namespace blink 401 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698