OLD | NEW |
---|---|
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 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
136 strut = LayoutUnit::max(); | 136 strut = LayoutUnit::max(); |
137 traverse(); | 137 traverse(); |
138 // We have now found each explicit / forced break, and their location. Now we | 138 // We have now found each explicit / forced break, and their location. Now we |
139 // need to figure out how many additional implicit / soft breaks we need and | 139 // need to figure out how many additional implicit / soft breaks we need and |
140 // guess where they will occur, in order | 140 // guess where they will occur, in order |
141 // to provide an initial column height. | 141 // to provide an initial column height. |
142 distributeImplicitBreaks(); | 142 distributeImplicitBreaks(); |
143 } | 143 } |
144 | 144 |
145 LayoutUnit InitialColumnHeightFinder::initialMinimalBalancedHeight() const { | 145 LayoutUnit InitialColumnHeightFinder::initialMinimalBalancedHeight() const { |
146 LayoutUnit rowLogicalTop; | |
147 if (m_contentRuns.size() > columnSet().usedColumnCount()) { | |
148 // We have not inserted additional fragmentainer groups yet (because we | |
149 // aren't able to calculate their constraints yet), but we already know for | |
150 // sure that there'll be more than one of them, due to the number of forced | |
151 // breaks in a nested multicol container. We will now attempt to take all | |
152 // the imaginary rows into account and calculate a minimal balanced logical | |
153 // height for everything. | |
154 unsigned stride = columnSet().usedColumnCount(); | |
155 LayoutUnit rowStartOffset = logicalTopInFlowThread(); | |
156 for (unsigned i = 0; i < firstContentRunIndexInLastRow(); i += stride) { | |
157 LayoutUnit rowEndOffset = m_contentRuns[i + stride - 1].breakOffset(); | |
158 float rowHeight = float(rowEndOffset - rowStartOffset) / float(stride); | |
159 rowLogicalTop += LayoutUnit::fromFloatCeil(rowHeight); | |
eae
2016/11/10 23:37:12
why ceil?
mstensho (USE GERRIT)
2016/11/11 08:47:46
That's what InitialColumnHeightFinder::ContentRun:
| |
160 rowStartOffset = rowEndOffset; | |
161 } | |
162 } | |
146 unsigned index = contentRunIndexWithTallestColumns(); | 163 unsigned index = contentRunIndexWithTallestColumns(); |
147 LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset() | 164 LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset() |
148 : logicalTopInFlowThread(); | 165 : logicalTopInFlowThread(); |
149 return m_contentRuns[index].columnLogicalHeight(startOffset); | 166 LayoutUnit height = m_contentRuns[index].columnLogicalHeight(startOffset); |
167 return rowLogicalTop + std::max(height, m_tallestUnbreakableLogicalHeight); | |
150 } | 168 } |
151 | 169 |
152 void InitialColumnHeightFinder::examineBoxAfterEntering( | 170 void InitialColumnHeightFinder::examineBoxAfterEntering( |
153 const LayoutBox& box, | 171 const LayoutBox& box, |
154 LayoutUnit childLogicalHeight, | 172 LayoutUnit childLogicalHeight, |
155 EBreak previousBreakAfterValue) { | 173 EBreak previousBreakAfterValue) { |
156 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { | 174 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { |
157 if (box.needsForcedBreakBefore(previousBreakAfterValue)) { | 175 if (box.needsForcedBreakBefore(previousBreakAfterValue)) { |
158 addContentRun(flowThreadOffset()); | 176 addContentRun(flowThreadOffset()); |
159 } else { | 177 } else { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
248 return totalStrutSpace; | 266 return totalStrutSpace; |
249 } | 267 } |
250 | 268 |
251 void InitialColumnHeightFinder::addContentRun( | 269 void InitialColumnHeightFinder::addContentRun( |
252 LayoutUnit endOffsetInFlowThread) { | 270 LayoutUnit endOffsetInFlowThread) { |
253 endOffsetInFlowThread -= spaceUsedByStrutsAt(endOffsetInFlowThread); | 271 endOffsetInFlowThread -= spaceUsedByStrutsAt(endOffsetInFlowThread); |
254 if (!m_contentRuns.isEmpty() && | 272 if (!m_contentRuns.isEmpty() && |
255 endOffsetInFlowThread <= m_contentRuns.last().breakOffset()) | 273 endOffsetInFlowThread <= m_contentRuns.last().breakOffset()) |
256 return; | 274 return; |
257 // Append another item as long as we haven't exceeded used column count. What | 275 // Append another item as long as we haven't exceeded used column count. What |
258 // ends up in the overflow area shouldn't affect column balancing. | 276 // ends up in the overflow area shouldn't affect column balancing. However, if |
259 if (m_contentRuns.size() < columnSet().usedColumnCount()) | 277 // we're in a nested fragmentation context, we may still need to record all |
260 m_contentRuns.append(ContentRun(endOffsetInFlowThread)); | 278 // runs, since there'll be no overflow area in the inline direction then, but |
279 // rather additional rows of columns in multiple outer fragmentainers. | |
280 if (m_contentRuns.size() >= columnSet().usedColumnCount()) { | |
281 const auto* flowThread = columnSet().multiColumnFlowThread(); | |
282 if (!flowThread->enclosingFragmentationContext() || | |
283 columnSet().newFragmentainerGroupsAllowed()) | |
284 return; | |
285 } | |
286 m_contentRuns.append(ContentRun(endOffsetInFlowThread)); | |
261 } | 287 } |
262 | 288 |
263 unsigned InitialColumnHeightFinder::contentRunIndexWithTallestColumns() const { | 289 unsigned InitialColumnHeightFinder::contentRunIndexWithTallestColumns() const { |
264 unsigned indexWithLargestHeight = 0; | 290 unsigned indexWithLargestHeight = 0; |
265 LayoutUnit largestHeight; | 291 LayoutUnit largestHeight; |
266 LayoutUnit previousOffset = logicalTopInFlowThread(); | 292 LayoutUnit previousOffset = logicalTopInFlowThread(); |
267 size_t runCount = m_contentRuns.size(); | 293 size_t runCount = m_contentRuns.size(); |
268 ASSERT(runCount); | 294 ASSERT(runCount); |
269 for (size_t i = 0; i < runCount; i++) { | 295 for (size_t i = firstContentRunIndexInLastRow(); i < runCount; i++) { |
270 const ContentRun& run = m_contentRuns[i]; | 296 const ContentRun& run = m_contentRuns[i]; |
271 LayoutUnit height = run.columnLogicalHeight(previousOffset); | 297 LayoutUnit height = run.columnLogicalHeight(previousOffset); |
272 if (largestHeight < height) { | 298 if (largestHeight < height) { |
273 largestHeight = height; | 299 largestHeight = height; |
274 indexWithLargestHeight = i; | 300 indexWithLargestHeight = i; |
275 } | 301 } |
276 previousOffset = run.breakOffset(); | 302 previousOffset = run.breakOffset(); |
277 } | 303 } |
278 return indexWithLargestHeight; | 304 return indexWithLargestHeight; |
279 } | 305 } |
280 | 306 |
281 void InitialColumnHeightFinder::distributeImplicitBreaks() { | 307 void InitialColumnHeightFinder::distributeImplicitBreaks() { |
282 // Insert a final content run to encompass all content. This will include | 308 // Insert a final content run to encompass all content. This will include |
283 // overflow if we're at the end of the multicol container. | 309 // overflow if we're at the end of the multicol container. |
284 addContentRun(logicalBottomInFlowThread()); | 310 addContentRun(logicalBottomInFlowThread()); |
285 unsigned columnCount = m_contentRuns.size(); | 311 unsigned columnCount = m_contentRuns.size(); |
286 | 312 |
287 // If there is room for more breaks (to reach the used value of column-count), | 313 // If there is room for more breaks (to reach the used value of column-count), |
288 // imagine that we insert implicit breaks at suitable locations. At any given | 314 // imagine that we insert implicit breaks at suitable locations. At any given |
289 // time, the content run with the currently tallest columns will get another | 315 // time, the content run with the currently tallest columns will get another |
290 // implicit break "inserted", which will increase its column count by one and | 316 // implicit break "inserted", which will increase its column count by one and |
291 // shrink its columns' height. Repeat until we have the desired total number | 317 // shrink its columns' height. Repeat until we have the desired total number |
292 // of breaks. The largest column height among the runs will then be the | 318 // of breaks. The largest column height among the runs will then be the |
293 // initial column height for the balancer to use. | 319 // initial column height for the balancer to use. |
320 if (columnCount > columnSet().usedColumnCount()) { | |
321 // If we exceed used column-count (which we are allowed to do if we're at | |
322 // the initial balancing pass for a multicol that lives inside another | |
323 // to-be-balanced outer multicol container), we only care about content that | |
324 // could end up in the last row. We need to pad up the number of columns, so | |
325 // that all rows will contain as many columns as used column-count dictates. | |
326 columnCount %= columnSet().usedColumnCount(); | |
327 // If there are just enough explicit breaks to fill all rows with the right | |
328 // amount of columns, we won't be needing any implicit breaks. | |
329 if (!columnCount) | |
330 return; | |
331 } | |
294 while (columnCount < columnSet().usedColumnCount()) { | 332 while (columnCount < columnSet().usedColumnCount()) { |
295 unsigned index = contentRunIndexWithTallestColumns(); | 333 unsigned index = contentRunIndexWithTallestColumns(); |
296 m_contentRuns[index].assumeAnotherImplicitBreak(); | 334 m_contentRuns[index].assumeAnotherImplicitBreak(); |
297 columnCount++; | 335 columnCount++; |
298 } | 336 } |
299 } | 337 } |
300 | 338 |
301 MinimumSpaceShortageFinder::MinimumSpaceShortageFinder( | 339 MinimumSpaceShortageFinder::MinimumSpaceShortageFinder( |
302 const LayoutMultiColumnSet& columnSet, | 340 const LayoutMultiColumnSet& columnSet, |
303 LayoutUnit logicalTopInFlowThread, | 341 LayoutUnit logicalTopInFlowThread, |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
435 if (group.columnLogicalTopForOffset(lineTopInFlowThread) != | 473 if (group.columnLogicalTopForOffset(lineTopInFlowThread) != |
436 group.columnLogicalTopForOffset(lineBottomWithOverflow)) { | 474 group.columnLogicalTopForOffset(lineBottomWithOverflow)) { |
437 LayoutUnit shortage = | 475 LayoutUnit shortage = |
438 lineBottomWithOverflow - | 476 lineBottomWithOverflow - |
439 group.columnLogicalTopForOffset(lineBottomWithOverflow); | 477 group.columnLogicalTopForOffset(lineBottomWithOverflow); |
440 recordSpaceShortage(shortage); | 478 recordSpaceShortage(shortage); |
441 } | 479 } |
442 } | 480 } |
443 | 481 |
444 } // namespace blink | 482 } // namespace blink |
OLD | NEW |