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

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

Issue 2468193002: Revert of Improve how the column balancer handles top margins on floats. (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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 break; 45 break;
46 examineLine(*line); 46 examineLine(*line);
47 } 47 }
48 } 48 }
49 49
50 void ColumnBalancer::traverseChildren(const LayoutObject& object) { 50 void ColumnBalancer::traverseChildren(const LayoutObject& object) {
51 // The break-after value from the previous in-flow block-level object to be 51 // The break-after value from the previous in-flow block-level object to be
52 // joined with the break-before value of the next in-flow block-level sibling. 52 // joined with the break-before value of the next in-flow block-level sibling.
53 EBreak previousBreakAfterValue = BreakAuto; 53 EBreak previousBreakAfterValue = BreakAuto;
54 54
55 const LayoutFlowThread* flowThread = columnSet().flowThread();
56 bool isHorizontalWritingMode = flowThread->isHorizontalWritingMode();
57
55 for (const LayoutObject* child = object.slowFirstChild(); child; 58 for (const LayoutObject* child = object.slowFirstChild(); child;
56 child = child->nextSibling()) { 59 child = child->nextSibling()) {
57 if (!child->isBox()) { 60 if (!child->isBox()) {
58 // Keep traversing inside inlines. There may be floats there. 61 // Keep traversing inside inlines. There may be floats there.
59 if (child->isLayoutInline()) 62 if (child->isLayoutInline())
60 traverseChildren(*child); 63 traverseChildren(*child);
61 continue; 64 continue;
62 } 65 }
63 66
64 const LayoutBox& childBox = toLayoutBox(*child); 67 const LayoutBox& childBox = toLayoutBox(*child);
65 68 LayoutRect overflowRect = childBox.layoutOverflowRect();
66 LayoutUnit borderEdgeOffset; 69 LayoutUnit childLogicalBottomWithOverflow =
67 LayoutUnit logicalTop = childBox.logicalTop(); 70 childBox.logicalTop() +
68 LayoutUnit logicalHeight = childBox.logicalHeightWithVisibleOverflow(); 71 (isHorizontalWritingMode ? overflowRect.maxY() : overflowRect.maxX());
69 // Floats' margins don't collapse with column boundaries, and we don't want 72 if (m_flowThreadOffset + childLogicalBottomWithOverflow <=
70 // to break inside them, or separate them from the float's border box. Set
71 // the offset to the margin-before edge (rather than border-before edge),
72 // and include the block direction margins in the child height.
73 if (childBox.isFloating()) {
74 LayoutUnit marginBefore = childBox.marginBefore(object.style());
75 LayoutUnit marginAfter = childBox.marginAfter(object.style());
76 logicalHeight =
77 std::max(logicalHeight, childBox.logicalHeight() + marginAfter);
78 logicalTop -= marginBefore;
79 logicalHeight += marginBefore;
80
81 // As soon as we want to process content inside this child, though, we
82 // need to get to its border-before edge.
83 borderEdgeOffset = marginBefore;
84 }
85
86 if (m_flowThreadOffset + logicalTop + logicalHeight <=
87 logicalTopInFlowThread()) { 73 logicalTopInFlowThread()) {
88 // This child is fully above the flow thread portion we're examining. 74 // This child is fully above the flow thread portion we're examining.
89 continue; 75 continue;
90 } 76 }
91 if (m_flowThreadOffset + logicalTop >= logicalBottomInFlowThread()) { 77 LayoutUnit childLogicalTopWithOverflow =
78 childBox.logicalTop() +
79 (isHorizontalWritingMode ? overflowRect.y() : overflowRect.x());
80 if (m_flowThreadOffset + childLogicalTopWithOverflow >=
81 logicalBottomInFlowThread()) {
92 // This child is fully below the flow thread portion we're examining. We 82 // This child is fully below the flow thread portion we're examining. We
93 // cannot just stop here, though, thanks to negative margins. 83 // cannot just stop here, though, thanks to negative margins.
94 // So keep looking. 84 // So keep looking.
95 continue; 85 continue;
96 } 86 }
97 if (childBox.isOutOfFlowPositioned() || childBox.isColumnSpanAll()) 87 if (childBox.isOutOfFlowPositioned() || childBox.isColumnSpanAll())
98 continue; 88 continue;
99 89
100 // Tables are wicked. Both table rows and table cells are relative to their 90 // Tables are wicked. Both table rows and table cells are relative to their
101 // table section. 91 // table section.
102 LayoutUnit offsetForThisChild = 92 LayoutUnit offsetForThisChild =
103 childBox.isTableRow() ? LayoutUnit() : logicalTop; 93 childBox.isTableRow() ? LayoutUnit() : childBox.logicalTop();
104
105 m_flowThreadOffset += offsetForThisChild; 94 m_flowThreadOffset += offsetForThisChild;
106 95
107 examineBoxAfterEntering(childBox, logicalHeight, previousBreakAfterValue); 96 examineBoxAfterEntering(childBox, previousBreakAfterValue);
108 // Unless the child is unsplittable, or if the child establishes an inner 97 // Unless the child is unsplittable, or if the child establishes an inner
109 // multicol container, we descend into its subtree for further examination. 98 // multicol container, we descend into its subtree for further examination.
110 if (childBox.getPaginationBreakability() != LayoutBox::ForbidBreaks && 99 if (childBox.getPaginationBreakability() != LayoutBox::ForbidBreaks &&
111 (!childBox.isLayoutBlockFlow() || 100 (!childBox.isLayoutBlockFlow() ||
112 !toLayoutBlockFlow(childBox).multiColumnFlowThread())) { 101 !toLayoutBlockFlow(childBox).multiColumnFlowThread()))
113 // We need to get to the border edge before processing content inside
114 // this child. If the child is floated, we're currently at the margin
115 // edge.
116 m_flowThreadOffset += borderEdgeOffset;
117 traverseSubtree(childBox); 102 traverseSubtree(childBox);
118 m_flowThreadOffset -= borderEdgeOffset;
119 }
120 previousBreakAfterValue = childBox.breakAfter(); 103 previousBreakAfterValue = childBox.breakAfter();
121 examineBoxBeforeLeaving(childBox, logicalHeight); 104 examineBoxBeforeLeaving(childBox);
122 105
123 m_flowThreadOffset -= offsetForThisChild; 106 m_flowThreadOffset -= offsetForThisChild;
124 } 107 }
125 } 108 }
126 109
127 InitialColumnHeightFinder::InitialColumnHeightFinder( 110 InitialColumnHeightFinder::InitialColumnHeightFinder(
128 const LayoutMultiColumnSet& columnSet, 111 const LayoutMultiColumnSet& columnSet,
129 LayoutUnit logicalTopInFlowThread, 112 LayoutUnit logicalTopInFlowThread,
130 LayoutUnit logicalBottomInFlowThread) 113 LayoutUnit logicalBottomInFlowThread)
131 : ColumnBalancer(columnSet, 114 : ColumnBalancer(columnSet,
(...skipping 12 matching lines...) Expand all
144 127
145 LayoutUnit InitialColumnHeightFinder::initialMinimalBalancedHeight() const { 128 LayoutUnit InitialColumnHeightFinder::initialMinimalBalancedHeight() const {
146 unsigned index = contentRunIndexWithTallestColumns(); 129 unsigned index = contentRunIndexWithTallestColumns();
147 LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset() 130 LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset()
148 : logicalTopInFlowThread(); 131 : logicalTopInFlowThread();
149 return m_contentRuns[index].columnLogicalHeight(startOffset); 132 return m_contentRuns[index].columnLogicalHeight(startOffset);
150 } 133 }
151 134
152 void InitialColumnHeightFinder::examineBoxAfterEntering( 135 void InitialColumnHeightFinder::examineBoxAfterEntering(
153 const LayoutBox& box, 136 const LayoutBox& box,
154 LayoutUnit childLogicalHeight,
155 EBreak previousBreakAfterValue) { 137 EBreak previousBreakAfterValue) {
156 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { 138 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) {
157 if (box.needsForcedBreakBefore(previousBreakAfterValue)) { 139 if (box.needsForcedBreakBefore(previousBreakAfterValue)) {
158 addContentRun(flowThreadOffset()); 140 addContentRun(flowThreadOffset());
159 } else { 141 } else {
160 if (isFirstAfterBreak(flowThreadOffset())) { 142 if (isFirstAfterBreak(flowThreadOffset())) {
161 // This box is first after a soft break. 143 // This box is first after a soft break.
162 recordStrutBeforeOffset(flowThreadOffset(), box.paginationStrut()); 144 recordStrutBeforeOffset(flowThreadOffset(), box.paginationStrut());
163 } 145 }
164 } 146 }
165 } 147 }
166 148
167 if (box.getPaginationBreakability() != LayoutBox::AllowAnyBreaks) { 149 if (box.getPaginationBreakability() != LayoutBox::AllowAnyBreaks) {
150 LayoutUnit unsplittableLogicalHeight = box.logicalHeight();
151 if (box.isFloating())
152 unsplittableLogicalHeight += box.marginBefore() + box.marginAfter();
168 m_tallestUnbreakableLogicalHeight = 153 m_tallestUnbreakableLogicalHeight =
169 std::max(m_tallestUnbreakableLogicalHeight, childLogicalHeight); 154 std::max(m_tallestUnbreakableLogicalHeight, unsplittableLogicalHeight);
170 return; 155 return;
171 } 156 }
172 // Need to examine inner multicol containers to find their tallest unbreakable 157 // Need to examine inner multicol containers to find their tallest unbreakable
173 // piece of content. 158 // piece of content.
174 if (!box.isLayoutBlockFlow()) 159 if (!box.isLayoutBlockFlow())
175 return; 160 return;
176 LayoutMultiColumnFlowThread* innerFlowThread = 161 LayoutMultiColumnFlowThread* innerFlowThread =
177 toLayoutBlockFlow(box).multiColumnFlowThread(); 162 toLayoutBlockFlow(box).multiColumnFlowThread();
178 if (!innerFlowThread || innerFlowThread->isLayoutPagedFlowThread()) 163 if (!innerFlowThread || innerFlowThread->isLayoutPagedFlowThread())
179 return; 164 return;
180 LayoutUnit offsetInInnerFlowThread = 165 LayoutUnit offsetInInnerFlowThread =
181 flowThreadOffset() - 166 flowThreadOffset() -
182 innerFlowThread->blockOffsetInEnclosingFragmentationContext(); 167 innerFlowThread->blockOffsetInEnclosingFragmentationContext();
183 LayoutUnit innerUnbreakableHeight = 168 LayoutUnit innerUnbreakableHeight =
184 innerFlowThread->tallestUnbreakableLogicalHeight(offsetInInnerFlowThread); 169 innerFlowThread->tallestUnbreakableLogicalHeight(offsetInInnerFlowThread);
185 m_tallestUnbreakableLogicalHeight = 170 m_tallestUnbreakableLogicalHeight =
186 std::max(m_tallestUnbreakableLogicalHeight, innerUnbreakableHeight); 171 std::max(m_tallestUnbreakableLogicalHeight, innerUnbreakableHeight);
187 } 172 }
188 173
189 void InitialColumnHeightFinder::examineBoxBeforeLeaving( 174 void InitialColumnHeightFinder::examineBoxBeforeLeaving(const LayoutBox& box) {}
190 const LayoutBox& box,
191 LayoutUnit childLogicalHeight) {}
192 175
193 static inline LayoutUnit columnLogicalHeightRequirementForLine( 176 static inline LayoutUnit columnLogicalHeightRequirementForLine(
194 const ComputedStyle& style, 177 const ComputedStyle& style,
195 const RootInlineBox& lastLine) { 178 const RootInlineBox& lastLine) {
196 // We may require a certain minimum number of lines per page in order to 179 // We may require a certain minimum number of lines per page in order to
197 // satisfy orphans and widows, and that may affect the minimum page height. 180 // satisfy orphans and widows, and that may affect the minimum page height.
198 unsigned minimumLineCount = 181 unsigned minimumLineCount =
199 std::max<unsigned>(style.orphans(), style.widows()); 182 std::max<unsigned>(style.orphans(), style.widows());
200 const RootInlineBox* firstLine = &lastLine; 183 const RootInlineBox* firstLine = &lastLine;
201 for (unsigned i = 1; i < minimumLineCount && firstLine->prevRootBox(); i++) 184 for (unsigned i = 1; i < minimumLineCount && firstLine->prevRootBox(); i++)
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 logicalTopInFlowThread, 289 logicalTopInFlowThread,
307 logicalBottomInFlowThread), 290 logicalBottomInFlowThread),
308 m_minimumSpaceShortage(LayoutUnit::max()), 291 m_minimumSpaceShortage(LayoutUnit::max()),
309 m_pendingStrut(LayoutUnit::min()), 292 m_pendingStrut(LayoutUnit::min()),
310 m_forcedBreaksCount(0) { 293 m_forcedBreaksCount(0) {
311 traverse(); 294 traverse();
312 } 295 }
313 296
314 void MinimumSpaceShortageFinder::examineBoxAfterEntering( 297 void MinimumSpaceShortageFinder::examineBoxAfterEntering(
315 const LayoutBox& box, 298 const LayoutBox& box,
316 LayoutUnit childLogicalHeight,
317 EBreak previousBreakAfterValue) { 299 EBreak previousBreakAfterValue) {
318 LayoutBox::PaginationBreakability breakability = 300 LayoutBox::PaginationBreakability breakability =
319 box.getPaginationBreakability(); 301 box.getPaginationBreakability();
320 302
321 // Look for breaks before the child box. 303 // Look for breaks before the child box.
322 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { 304 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) {
323 if (box.needsForcedBreakBefore(previousBreakAfterValue)) { 305 if (box.needsForcedBreakBefore(previousBreakAfterValue)) {
324 m_forcedBreaksCount++; 306 m_forcedBreaksCount++;
325 } else { 307 } else {
326 if (isFirstAfterBreak(flowThreadOffset())) { 308 if (isFirstAfterBreak(flowThreadOffset())) {
327 // This box is first after a soft break. 309 // This box is first after a soft break.
328 LayoutUnit strut = box.paginationStrut(); 310 LayoutUnit strut = box.paginationStrut();
329 // Figure out how much more space we would need to prevent it from being 311 // Figure out how much more space we would need to prevent it from being
330 // pushed to the next column. 312 // pushed to the next column.
331 recordSpaceShortage(childLogicalHeight - strut); 313 recordSpaceShortage(box.logicalHeight() - strut);
332 if (breakability != LayoutBox::ForbidBreaks && 314 if (breakability != LayoutBox::ForbidBreaks &&
333 m_pendingStrut == LayoutUnit::min()) { 315 m_pendingStrut == LayoutUnit::min()) {
334 // We now want to look for the first piece of unbreakable content 316 // We now want to look for the first piece of unbreakable content
335 // (e.g. a line or a block-displayed image) inside this block. That 317 // (e.g. a line or a block-displayed image) inside this block. That
336 // ought to be a good candidate for minimum space shortage; a much 318 // ought to be a good candidate for minimum space shortage; a much
337 // better one than reporting space shortage for the entire block 319 // better one than reporting space shortage for the entire block
338 // (which we'll also do (further down), in case we couldn't find 320 // (which we'll also do (further down), in case we couldn't find
339 // anything more suitable). 321 // anything more suitable).
340 m_pendingStrut = strut; 322 m_pendingStrut = strut;
341 } 323 }
342 } 324 }
343 } 325 }
344 } 326 }
345 327
346 if (breakability != LayoutBox::ForbidBreaks) { 328 if (breakability != LayoutBox::ForbidBreaks) {
347 // See if this breakable box crosses column boundaries. 329 // See if this breakable box crosses column boundaries.
348 LayoutUnit bottomInFlowThread = flowThreadOffset() + childLogicalHeight; 330 LayoutUnit bottomInFlowThread = flowThreadOffset() + box.logicalHeight();
349 const MultiColumnFragmentainerGroup& group = 331 const MultiColumnFragmentainerGroup& group =
350 groupAtOffset(flowThreadOffset()); 332 groupAtOffset(flowThreadOffset());
351 if (isFirstAfterBreak(flowThreadOffset()) || 333 if (isFirstAfterBreak(flowThreadOffset()) ||
352 group.columnLogicalTopForOffset(flowThreadOffset()) != 334 group.columnLogicalTopForOffset(flowThreadOffset()) !=
353 group.columnLogicalTopForOffset(bottomInFlowThread)) { 335 group.columnLogicalTopForOffset(bottomInFlowThread)) {
354 // If the child crosses a column boundary, record space shortage, in case 336 // If the child crosses a column boundary, record space shortage, in case
355 // nothing inside it has already done so. The column balancer needs to 337 // nothing inside it has already done so. The column balancer needs to
356 // know by how much it has to stretch the columns to make more content 338 // know by how much it has to stretch the columns to make more content
357 // fit. If no breaks are reported (but do occur), the balancer will have 339 // fit. If no breaks are reported (but do occur), the balancer will have
358 // no clue. Only measure the space after the last column boundary, in case 340 // no clue. Only measure the space after the last column boundary, in case
(...skipping 19 matching lines...) Expand all
378 // multicol container. We need to let it walk through all fragmentainer 360 // multicol container. We need to let it walk through all fragmentainer
379 // groups in one go, or we'd miss the column boundaries between each 361 // groups in one go, or we'd miss the column boundaries between each
380 // fragmentainer group. We need to record space shortage there too. 362 // fragmentainer group. We need to record space shortage there too.
381 MinimumSpaceShortageFinder innerFinder( 363 MinimumSpaceShortageFinder innerFinder(
382 *columnSet, columnSet->logicalTopInFlowThread(), 364 *columnSet, columnSet->logicalTopInFlowThread(),
383 columnSet->logicalBottomInFlowThread()); 365 columnSet->logicalBottomInFlowThread());
384 recordSpaceShortage(innerFinder.minimumSpaceShortage()); 366 recordSpaceShortage(innerFinder.minimumSpaceShortage());
385 } 367 }
386 } 368 }
387 369
388 void MinimumSpaceShortageFinder::examineBoxBeforeLeaving( 370 void MinimumSpaceShortageFinder::examineBoxBeforeLeaving(const LayoutBox& box) {
389 const LayoutBox& box,
390 LayoutUnit childLogicalHeight) {
391 if (m_pendingStrut == LayoutUnit::min() || 371 if (m_pendingStrut == LayoutUnit::min() ||
392 box.getPaginationBreakability() != LayoutBox::ForbidBreaks) 372 box.getPaginationBreakability() != LayoutBox::ForbidBreaks)
393 return; 373 return;
394 374
395 // The previous break was before a breakable block. Here's the first piece of 375 // The previous break was before a breakable block. Here's the first piece of
396 // unbreakable content after / inside that block. We want to record the 376 // unbreakable content after / inside that block. We want to record the
397 // distance from the top of the column to the bottom of this box as space 377 // distance from the top of the column to the bottom of this box as space
398 // shortage. 378 // shortage.
399 LayoutUnit logicalOffsetFromCurrentColumn = 379 LayoutUnit logicalOffsetFromCurrentColumn =
400 offsetFromColumnLogicalTop(flowThreadOffset()); 380 offsetFromColumnLogicalTop(flowThreadOffset());
401 recordSpaceShortage(logicalOffsetFromCurrentColumn + childLogicalHeight - 381 recordSpaceShortage(logicalOffsetFromCurrentColumn + box.logicalHeight() -
402 m_pendingStrut); 382 m_pendingStrut);
403 m_pendingStrut = LayoutUnit::min(); 383 m_pendingStrut = LayoutUnit::min();
404 } 384 }
405 385
406 void MinimumSpaceShortageFinder::examineLine(const RootInlineBox& line) { 386 void MinimumSpaceShortageFinder::examineLine(const RootInlineBox& line) {
407 LayoutUnit lineTop = line.lineTopWithLeading(); 387 LayoutUnit lineTop = line.lineTopWithLeading();
408 LayoutUnit lineTopInFlowThread = flowThreadOffset() + lineTop; 388 LayoutUnit lineTopInFlowThread = flowThreadOffset() + lineTop;
409 LayoutUnit lineHeight = line.lineBottomWithLeading() - lineTop; 389 LayoutUnit lineHeight = line.lineBottomWithLeading() - lineTop;
410 if (m_pendingStrut != LayoutUnit::min()) { 390 if (m_pendingStrut != LayoutUnit::min()) {
411 // The previous break was before a breakable block. Here's the first line 391 // The previous break was before a breakable block. Here's the first line
(...skipping 23 matching lines...) Expand all
435 if (group.columnLogicalTopForOffset(lineTopInFlowThread) != 415 if (group.columnLogicalTopForOffset(lineTopInFlowThread) !=
436 group.columnLogicalTopForOffset(lineBottomWithOverflow)) { 416 group.columnLogicalTopForOffset(lineBottomWithOverflow)) {
437 LayoutUnit shortage = 417 LayoutUnit shortage =
438 lineBottomWithOverflow - 418 lineBottomWithOverflow -
439 group.columnLogicalTopForOffset(lineBottomWithOverflow); 419 group.columnLogicalTopForOffset(lineBottomWithOverflow);
440 recordSpaceShortage(shortage); 420 recordSpaceShortage(shortage);
441 } 421 }
442 } 422 }
443 423
444 } // namespace blink 424 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/ColumnBalancer.h ('k') | third_party/WebKit/Source/core/layout/LayoutBox.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698