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

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

Issue 1913453002: ColumnBalancer: Don't leak the break-after value from the previous sibling to children. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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
« no previous file with comments | « third_party/WebKit/Source/core/layout/ColumnBalancer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
11 namespace blink { 11 namespace blink {
12 12
13 ColumnBalancer::ColumnBalancer(const LayoutMultiColumnSet& columnSet, LayoutUnit logicalTopInFlowThread, LayoutUnit logicalBottomInFlowThread) 13 ColumnBalancer::ColumnBalancer(const LayoutMultiColumnSet& columnSet, LayoutUnit logicalTopInFlowThread, LayoutUnit logicalBottomInFlowThread)
14 : m_columnSet(columnSet) 14 : m_columnSet(columnSet)
15 , m_logicalTopInFlowThread(logicalTopInFlowThread) 15 , m_logicalTopInFlowThread(logicalTopInFlowThread)
16 , m_logicalBottomInFlowThread(logicalBottomInFlowThread) 16 , m_logicalBottomInFlowThread(logicalBottomInFlowThread)
17 , m_previousBreakAfterValue(BreakAuto)
18 { 17 {
19 } 18 }
20 19
21 void ColumnBalancer::traverse() 20 void ColumnBalancer::traverse()
22 { 21 {
23 traverseSubtree(*columnSet().flowThread()); 22 traverseSubtree(*columnSet().flowThread());
24 ASSERT(!flowThreadOffset()); 23 ASSERT(!flowThreadOffset());
25 } 24 }
26 25
27 void ColumnBalancer::traverseSubtree(const LayoutBox& box) 26 void ColumnBalancer::traverseSubtree(const LayoutBox& box)
28 { 27 {
29 if (box.childrenInline() && box.isLayoutBlockFlow()) { 28 if (box.childrenInline() && box.isLayoutBlockFlow()) {
30 // Look for breaks between lines. 29 // Look for breaks between lines.
31 for (const RootInlineBox* line = toLayoutBlockFlow(box).firstRootBox(); line; line = line->nextRootBox()) { 30 for (const RootInlineBox* line = toLayoutBlockFlow(box).firstRootBox(); line; line = line->nextRootBox()) {
32 LayoutUnit lineTopInFlowThread = m_flowThreadOffset + line->lineTopW ithLeading(); 31 LayoutUnit lineTopInFlowThread = m_flowThreadOffset + line->lineTopW ithLeading();
33 if (lineTopInFlowThread < logicalTopInFlowThread()) 32 if (lineTopInFlowThread < logicalTopInFlowThread())
34 continue; 33 continue;
35 if (lineTopInFlowThread >= logicalBottomInFlowThread()) 34 if (lineTopInFlowThread >= logicalBottomInFlowThread())
36 break; 35 break;
37 examineLine(*line); 36 examineLine(*line);
38 } 37 }
39 } 38 }
40 39
41 const LayoutFlowThread* flowThread = columnSet().flowThread(); 40 const LayoutFlowThread* flowThread = columnSet().flowThread();
42 bool isHorizontalWritingMode = flowThread->isHorizontalWritingMode(); 41 bool isHorizontalWritingMode = flowThread->isHorizontalWritingMode();
43 42
43 // The break-after value from the previous in-flow block-level object to be joined with the
44 // break-before value of the next in-flow block-level sibling.
45 EBreak previousBreakAfterValue = BreakAuto;
46
44 // Look for breaks between and inside block-level children. Even if this is a block flow with 47 // Look for breaks between and inside block-level children. Even if this is a block flow with
45 // inline children, there may be interesting floats to examine here. 48 // inline children, there may be interesting floats to examine here.
46 for (const LayoutObject* child = box.slowFirstChild(); child; child = child- >nextSibling()) { 49 for (const LayoutObject* child = box.slowFirstChild(); child; child = child- >nextSibling()) {
47 if (!child->isBox() || child->isInline()) 50 if (!child->isBox() || child->isInline())
48 continue; 51 continue;
49 const LayoutBox& childBox = toLayoutBox(*child); 52 const LayoutBox& childBox = toLayoutBox(*child);
50 LayoutRect overflowRect = childBox.layoutOverflowRect(); 53 LayoutRect overflowRect = childBox.layoutOverflowRect();
51 LayoutUnit childLogicalBottomWithOverflow = childBox.logicalTop() + (isH orizontalWritingMode ? overflowRect.maxY() : overflowRect.maxX()); 54 LayoutUnit childLogicalBottomWithOverflow = childBox.logicalTop() + (isH orizontalWritingMode ? overflowRect.maxY() : overflowRect.maxX());
52 if (m_flowThreadOffset + childLogicalBottomWithOverflow <= logicalTopInF lowThread()) { 55 if (m_flowThreadOffset + childLogicalBottomWithOverflow <= logicalTopInF lowThread()) {
53 // This child is fully above the flow thread portion we're examining . 56 // This child is fully above the flow thread portion we're examining .
54 continue; 57 continue;
55 } 58 }
56 LayoutUnit childLogicalTopWithOverflow = childBox.logicalTop() + (isHori zontalWritingMode ? overflowRect.y() : overflowRect.x()); 59 LayoutUnit childLogicalTopWithOverflow = childBox.logicalTop() + (isHori zontalWritingMode ? overflowRect.y() : overflowRect.x());
57 if (m_flowThreadOffset + childLogicalTopWithOverflow >= logicalBottomInF lowThread()) { 60 if (m_flowThreadOffset + childLogicalTopWithOverflow >= logicalBottomInF lowThread()) {
58 // This child is fully below the flow thread portion we're examining . We cannot just 61 // This child is fully below the flow thread portion we're examining . We cannot just
59 // stop here, though, thanks to negative margins. So keep looking. 62 // stop here, though, thanks to negative margins. So keep looking.
60 continue; 63 continue;
61 } 64 }
62 if (childBox.isOutOfFlowPositioned() || childBox.isColumnSpanAll()) 65 if (childBox.isOutOfFlowPositioned() || childBox.isColumnSpanAll())
63 continue; 66 continue;
64 67
65 // Tables are wicked. Both table rows and table cells are relative to th eir table section. 68 // Tables are wicked. Both table rows and table cells are relative to th eir table section.
66 LayoutUnit offsetForThisChild = childBox.isTableRow() ? LayoutUnit() : c hildBox.logicalTop(); 69 LayoutUnit offsetForThisChild = childBox.isTableRow() ? LayoutUnit() : c hildBox.logicalTop();
67 m_flowThreadOffset += offsetForThisChild; 70 m_flowThreadOffset += offsetForThisChild;
68 71
69 examineBoxAfterEntering(childBox); 72 examineBoxAfterEntering(childBox, previousBreakAfterValue);
70 // Unless the child is unsplittable, or if the child establishes an inne r multicol 73 // Unless the child is unsplittable, or if the child establishes an inne r multicol
71 // container, we descend into its subtree for further examination. 74 // container, we descend into its subtree for further examination.
72 if (childBox.getPaginationBreakability() != LayoutBox::ForbidBreaks 75 if (childBox.getPaginationBreakability() != LayoutBox::ForbidBreaks
73 && (!childBox.isLayoutBlockFlow() || !toLayoutBlockFlow(childBox).mu ltiColumnFlowThread())) 76 && (!childBox.isLayoutBlockFlow() || !toLayoutBlockFlow(childBox).mu ltiColumnFlowThread()))
74 traverseSubtree(childBox); 77 traverseSubtree(childBox);
75 m_previousBreakAfterValue = childBox.breakAfter(); 78 previousBreakAfterValue = childBox.breakAfter();
76 examineBoxBeforeLeaving(childBox); 79 examineBoxBeforeLeaving(childBox);
77 80
78 m_flowThreadOffset -= offsetForThisChild; 81 m_flowThreadOffset -= offsetForThisChild;
79 } 82 }
80 } 83 }
81 84
82 InitialColumnHeightFinder::InitialColumnHeightFinder(const LayoutMultiColumnSet& columnSet, LayoutUnit logicalTopInFlowThread, LayoutUnit logicalBottomInFlowThr ead) 85 InitialColumnHeightFinder::InitialColumnHeightFinder(const LayoutMultiColumnSet& columnSet, LayoutUnit logicalTopInFlowThread, LayoutUnit logicalBottomInFlowThr ead)
83 : ColumnBalancer(columnSet, logicalTopInFlowThread, logicalBottomInFlowThrea d) 86 : ColumnBalancer(columnSet, logicalTopInFlowThread, logicalBottomInFlowThrea d)
84 { 87 {
85 m_shortestStruts.resize(columnSet.usedColumnCount()); 88 m_shortestStruts.resize(columnSet.usedColumnCount());
86 for (auto& strut : m_shortestStruts) 89 for (auto& strut : m_shortestStruts)
87 strut = LayoutUnit::max(); 90 strut = LayoutUnit::max();
88 traverse(); 91 traverse();
89 // We have now found each explicit / forced break, and their location. Now w e need to figure out 92 // We have now found each explicit / forced break, and their location. Now w e need to figure out
90 // how many additional implicit / soft breaks we need and guess where they w ill occur, in order 93 // how many additional implicit / soft breaks we need and guess where they w ill occur, in order
91 // to provide an initial column height. 94 // to provide an initial column height.
92 distributeImplicitBreaks(); 95 distributeImplicitBreaks();
93 } 96 }
94 97
95 LayoutUnit InitialColumnHeightFinder::initialMinimalBalancedHeight() const 98 LayoutUnit InitialColumnHeightFinder::initialMinimalBalancedHeight() const
96 { 99 {
97 unsigned index = contentRunIndexWithTallestColumns(); 100 unsigned index = contentRunIndexWithTallestColumns();
98 LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset() : logicalTopInFlowThread(); 101 LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset() : logicalTopInFlowThread();
99 return m_contentRuns[index].columnLogicalHeight(startOffset); 102 return m_contentRuns[index].columnLogicalHeight(startOffset);
100 } 103 }
101 104
102 void InitialColumnHeightFinder::examineBoxAfterEntering(const LayoutBox& box) 105 void InitialColumnHeightFinder::examineBoxAfterEntering(const LayoutBox& box, EB reak previousBreakAfterValue)
103 { 106 {
104 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { 107 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) {
105 if (box.needsForcedBreakBefore(previousBreakAfterValue())) { 108 if (box.needsForcedBreakBefore(previousBreakAfterValue)) {
106 addContentRun(flowThreadOffset()); 109 addContentRun(flowThreadOffset());
107 } else { 110 } else {
108 ASSERT(isFirstAfterBreak(flowThreadOffset()) || !box.paginationStrut ()); 111 ASSERT(isFirstAfterBreak(flowThreadOffset()) || !box.paginationStrut ());
109 if (isFirstAfterBreak(flowThreadOffset())) { 112 if (isFirstAfterBreak(flowThreadOffset())) {
110 // This box is first after a soft break. 113 // This box is first after a soft break.
111 recordStrutBeforeOffset(flowThreadOffset(), box.paginationStrut( )); 114 recordStrutBeforeOffset(flowThreadOffset(), box.paginationStrut( ));
112 } 115 }
113 } 116 }
114 } 117 }
115 118
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 236
234 MinimumSpaceShortageFinder::MinimumSpaceShortageFinder(const LayoutMultiColumnSe t& columnSet, LayoutUnit logicalTopInFlowThread, LayoutUnit logicalBottomInFlowT hread) 237 MinimumSpaceShortageFinder::MinimumSpaceShortageFinder(const LayoutMultiColumnSe t& columnSet, LayoutUnit logicalTopInFlowThread, LayoutUnit logicalBottomInFlowT hread)
235 : ColumnBalancer(columnSet, logicalTopInFlowThread, logicalBottomInFlowThrea d) 238 : ColumnBalancer(columnSet, logicalTopInFlowThread, logicalBottomInFlowThrea d)
236 , m_minimumSpaceShortage(LayoutUnit::max()) 239 , m_minimumSpaceShortage(LayoutUnit::max())
237 , m_pendingStrut(LayoutUnit::min()) 240 , m_pendingStrut(LayoutUnit::min())
238 , m_forcedBreaksCount(0) 241 , m_forcedBreaksCount(0)
239 { 242 {
240 traverse(); 243 traverse();
241 } 244 }
242 245
243 void MinimumSpaceShortageFinder::examineBoxAfterEntering(const LayoutBox& box) 246 void MinimumSpaceShortageFinder::examineBoxAfterEntering(const LayoutBox& box, E Break previousBreakAfterValue)
244 { 247 {
245 LayoutBox::PaginationBreakability breakability = box.getPaginationBreakabili ty(); 248 LayoutBox::PaginationBreakability breakability = box.getPaginationBreakabili ty();
246 249
247 // Look for breaks before the child box. 250 // Look for breaks before the child box.
248 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { 251 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) {
249 if (box.needsForcedBreakBefore(previousBreakAfterValue())) { 252 if (box.needsForcedBreakBefore(previousBreakAfterValue)) {
250 m_forcedBreaksCount++; 253 m_forcedBreaksCount++;
251 } else { 254 } else {
252 ASSERT(isFirstAfterBreak(flowThreadOffset()) || !box.paginationStrut ()); 255 ASSERT(isFirstAfterBreak(flowThreadOffset()) || !box.paginationStrut ());
253 if (isFirstAfterBreak(flowThreadOffset())) { 256 if (isFirstAfterBreak(flowThreadOffset())) {
254 // This box is first after a soft break. 257 // This box is first after a soft break.
255 LayoutUnit strut = box.paginationStrut(); 258 LayoutUnit strut = box.paginationStrut();
256 // Figure out how much more space we would need to prevent it fr om being pushed to the next column. 259 // Figure out how much more space we would need to prevent it fr om being pushed to the next column.
257 recordSpaceShortage(box.logicalHeight() - strut); 260 recordSpaceShortage(box.logicalHeight() - strut);
258 if (breakability != LayoutBox::ForbidBreaks && m_pendingStrut == LayoutUnit::min()) { 261 if (breakability != LayoutBox::ForbidBreaks && m_pendingStrut == LayoutUnit::min()) {
259 // We now want to look for the first piece of unbreakable co ntent (e.g. a line or a 262 // We now want to look for the first piece of unbreakable co ntent (e.g. a line or a
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 // of said overflow ends up in the next column. That counts as space shortag e. 338 // of said overflow ends up in the next column. That counts as space shortag e.
336 const MultiColumnFragmentainerGroup& group = groupAtOffset(lineTopInFlowThre ad); 339 const MultiColumnFragmentainerGroup& group = groupAtOffset(lineTopInFlowThre ad);
337 LayoutUnit lineBottomWithOverflow = lineTopInFlowThread + line.lineBottom() - lineTop; 340 LayoutUnit lineBottomWithOverflow = lineTopInFlowThread + line.lineBottom() - lineTop;
338 if (group.columnLogicalTopForOffset(lineTopInFlowThread) != group.columnLogi calTopForOffset(lineBottomWithOverflow)) { 341 if (group.columnLogicalTopForOffset(lineTopInFlowThread) != group.columnLogi calTopForOffset(lineBottomWithOverflow)) {
339 LayoutUnit shortage = lineBottomWithOverflow - group.columnLogicalTopFor Offset(lineBottomWithOverflow); 342 LayoutUnit shortage = lineBottomWithOverflow - group.columnLogicalTopFor Offset(lineBottomWithOverflow);
340 recordSpaceShortage(shortage); 343 recordSpaceShortage(shortage);
341 } 344 }
342 } 345 }
343 346
344 } // namespace blink 347 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/ColumnBalancer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698