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

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

Issue 2493833004: InitialColumnHeightFinder needs to take all expected rows into account. (Closed)
Patch Set: Created 4 years, 1 month 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 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698