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/MultiColumnFragmentainerGroup.h" | 5 #include "core/layout/LayoutMultiColumnSet.h" |
6 | 6 |
7 namespace blink { | 7 namespace blink { |
8 | 8 |
9 // A column balancer traverses the portion of the subtree of a flow thread that
belongs to a given | 9 // A column balancer traverses a portion of the subtree of a flow thread that be
longs to one or |
10 // fragmentainer group, in order to collect certain data to be used for column b
alancing. This is an | 10 // more fragmentainer groups within one column set, in order to collect certain
data to be used for |
11 // abstract class that just walks the subtree and leaves it to subclasses to act
ualy collect data. | 11 // column balancing. This is an abstract class that just walks the subtree and l
eaves it to |
| 12 // subclasses to actually collect data. |
12 class ColumnBalancer { | 13 class ColumnBalancer { |
13 protected: | 14 protected: |
14 ColumnBalancer(const MultiColumnFragmentainerGroup&); | 15 ColumnBalancer(const LayoutMultiColumnSet&, LayoutUnit logicalTopInFlowThrea
d, LayoutUnit logicalBottomInFlowThread); |
15 | 16 |
16 const MultiColumnFragmentainerGroup& group() const { return m_group; } | 17 const LayoutMultiColumnSet& columnSet() const { return m_columnSet; } |
| 18 |
| 19 // The flow thread portion we're examining. It may be that of the entire col
umn set, or just of |
| 20 // a fragmentainer group. |
| 21 const LayoutUnit logicalTopInFlowThread() const { return m_logicalTopInFlowT
hread; } |
| 22 const LayoutUnit logicalBottomInFlowThread() const { return m_logicalBottomI
nFlowThread; } |
| 23 |
| 24 const MultiColumnFragmentainerGroup& groupAtOffset(LayoutUnit offsetInFlowTh
read) const |
| 25 { |
| 26 return m_columnSet.fragmentainerGroupAtFlowThreadOffset(offsetInFlowThre
ad); |
| 27 } |
| 28 |
| 29 LayoutUnit offsetFromColumnLogicalTop(LayoutUnit offsetInFlowThread) const |
| 30 { |
| 31 return offsetInFlowThread - groupAtOffset(offsetInFlowThread).columnLogi
calTopForOffset(offsetInFlowThread); |
| 32 } |
17 | 33 |
18 // Flow thread offset for the layout object that we're currently examining. | 34 // Flow thread offset for the layout object that we're currently examining. |
19 LayoutUnit flowThreadOffset() const { return m_flowThreadOffset; } | 35 LayoutUnit flowThreadOffset() const { return m_flowThreadOffset; } |
20 | 36 |
21 EBreak previousBreakAfterValue() const { return m_previousBreakAfterValue; } | 37 EBreak previousBreakAfterValue() const { return m_previousBreakAfterValue; } |
22 | 38 |
23 // Return true if the specified offset is at the top of a column, as long as
it's not the first | 39 // Return true if the specified offset is at the top of a column, as long as
it's not the first |
24 // column in the fragmentainer group. | 40 // column in the flow thread portion. |
25 bool isFirstAfterBreak(LayoutUnit flowThreadOffset) const | 41 bool isFirstAfterBreak(LayoutUnit flowThreadOffset) const |
26 { | 42 { |
27 if (flowThreadOffset != m_group.columnLogicalTopForOffset(flowThreadOffs
et)) | 43 if (flowThreadOffset <= m_logicalTopInFlowThread) { |
28 return false; // Not at the top of a column. | 44 // The first column is either not after any break at all, or after a
break in a |
29 // The first column in the fragmentainer group is either not after any b
reak at all, or | 45 // previous fragmentainer group. |
30 // after a break that belongs to the previous fragmentainer group. | 46 return false; |
31 return flowThreadOffset > m_group.logicalTopInFlowThread(); | 47 } |
| 48 return flowThreadOffset == groupAtOffset(flowThreadOffset).columnLogical
TopForOffset(flowThreadOffset); |
32 } | 49 } |
33 | 50 |
34 bool isLogicalTopWithinBounds(LayoutUnit logicalTopInFlowThread) const | 51 bool isLogicalTopWithinBounds(LayoutUnit logicalTopInFlowThread) const |
35 { | 52 { |
36 return logicalTopInFlowThread >= m_group.logicalTopInFlowThread() | 53 return logicalTopInFlowThread >= m_logicalTopInFlowThread |
37 && logicalTopInFlowThread < m_group.logicalBottomInFlowThread(); | 54 && logicalTopInFlowThread < m_logicalBottomInFlowThread; |
38 } | 55 } |
39 | 56 |
40 bool isLogicalBottomWithinBounds(LayoutUnit logicalBottomInFlowThread) const | 57 bool isLogicalBottomWithinBounds(LayoutUnit logicalBottomInFlowThread) const |
41 { | 58 { |
42 return logicalBottomInFlowThread > m_group.logicalTopInFlowThread() | 59 return logicalBottomInFlowThread > m_logicalTopInFlowThread |
43 && logicalBottomInFlowThread <= m_group.logicalBottomInFlowThread(); | 60 && logicalBottomInFlowThread <= m_logicalBottomInFlowThread; |
44 } | 61 } |
45 | 62 |
46 // Examine and collect column balancing data from a layout box that has been
found to intersect | 63 // Examine and collect column balancing data from a layout box that has been
found to intersect |
47 // with this fragmentainer group. Does not recurse into children. flowThread
Offset() will | 64 // with the flow thread portion we're examining. Does not recurse into |
48 // return the offset from |box| to the flow thread. Two hooks are provided h
ere. The first one | 65 // children. flowThreadOffset() will return the offset from |box| to the flo
w thread. Two hooks |
49 // is called right after entering and before traversing the subtree of the b
ox, and the second | 66 // are provided here. The first one is called right after entering and befor
e traversing the |
50 // one right after having traversed the subtree. | 67 // subtree of the box, and the second one right after having traversed the s
ubtree. |
51 virtual void examineBoxAfterEntering(const LayoutBox&) = 0; | 68 virtual void examineBoxAfterEntering(const LayoutBox&) = 0; |
52 virtual void examineBoxBeforeLeaving(const LayoutBox&) = 0; | 69 virtual void examineBoxBeforeLeaving(const LayoutBox&) = 0; |
53 | 70 |
54 // Examine and collect column balancing data from a line that has been found
to intersect with | 71 // Examine and collect column balancing data from a line that has been found
to intersect with |
55 // this fragmentainer group. Does not recurse into layout objects on that li
ne. | 72 // the flow thread portion. Does not recurse into layout objects on that lin
e. |
56 virtual void examineLine(const RootInlineBox&) = 0; | 73 virtual void examineLine(const RootInlineBox&) = 0; |
57 | 74 |
58 // Examine and collect column balancing data for everything in the fragmenta
iner group. Will | 75 // Examine and collect column balancing data for everything in the flow thre
ad portion. Will |
59 // trigger calls to examineBoxAfterEntering(), examineBoxBeforeLeaving() and
examineLine() for | 76 // trigger calls to examineBoxAfterEntering(), examineBoxBeforeLeaving() and
examineLine() for |
60 // interesting boxes and lines. | 77 // interesting boxes and lines. |
61 void traverse(); | 78 void traverse(); |
62 | 79 |
63 private: | 80 private: |
64 void traverseSubtree(const LayoutBox&); | 81 void traverseSubtree(const LayoutBox&); |
65 | 82 |
66 const MultiColumnFragmentainerGroup& m_group; | 83 const LayoutMultiColumnSet& m_columnSet; |
| 84 const LayoutUnit m_logicalTopInFlowThread; |
| 85 const LayoutUnit m_logicalBottomInFlowThread; |
| 86 |
67 LayoutUnit m_flowThreadOffset; | 87 LayoutUnit m_flowThreadOffset; |
68 | 88 |
69 // The break-after value from the previous in-flow block-level object to be
joined with the | 89 // The break-after value from the previous in-flow block-level object to be
joined with the |
70 // break-before value of the next in-flow block-level object. | 90 // break-before value of the next in-flow block-level object. |
71 EBreak m_previousBreakAfterValue; | 91 EBreak m_previousBreakAfterValue; |
72 }; | 92 }; |
73 | 93 |
74 // After an initial layout pass, we know the height of the contents of a flow th
read. Based on | 94 // After an initial layout pass, we know the height of the contents of a flow th
read. Based on |
75 // this, we can estimate an initial minimal column height. This class will colle
ct the necessary | 95 // this, we can estimate an initial minimal column height. This class will colle
ct the necessary |
76 // information from the layout objects to make this estimate. This estimate may
be used to perform | 96 // information from the layout objects to make this estimate. This estimate may
be used to perform |
77 // another layout iteration. If we after such a layout iteration cannot fit the
contents with the | 97 // another layout iteration. If we after such a layout iteration cannot fit the
contents with the |
78 // given column height without creating overflowing columns, we will have to str
etch the columns by | 98 // given column height without creating overflowing columns, we will have to str
etch the columns by |
79 // some amount and lay out again. We may need to do this several times (but typi
cally not more | 99 // some amount and lay out again. We may need to do this several times (but typi
cally not more |
80 // times than the number of columns that we have). The amount to stretch is prov
ided by the sister | 100 // times than the number of columns that we have). The amount to stretch is prov
ided by the sister |
81 // of this class, named MinimumSpaceShortageFinder. | 101 // of this class, named MinimumSpaceShortageFinder. |
82 class InitialColumnHeightFinder final : public ColumnBalancer { | 102 class InitialColumnHeightFinder final : public ColumnBalancer { |
83 public: | 103 public: |
84 InitialColumnHeightFinder(const MultiColumnFragmentainerGroup&); | 104 InitialColumnHeightFinder(const LayoutMultiColumnSet&, LayoutUnit logicalTop
InFlowThread, LayoutUnit logicalBottomInFlowThread); |
85 | 105 |
86 LayoutUnit initialMinimalBalancedHeight() const; | 106 LayoutUnit initialMinimalBalancedHeight() const; |
87 | 107 |
88 // Height of the tallest piece of unbreakable content. This is the minimum c
olumn logical height | 108 // Height of the tallest piece of unbreakable content. This is the minimum c
olumn logical height |
89 // required to avoid fragmentation where it shouldn't occur (inside unbreaka
ble content, between | 109 // required to avoid fragmentation where it shouldn't occur (inside unbreaka
ble content, between |
90 // orphans and widows, etc.). This will be used as a hint to the column bala
ncer to help set a | 110 // orphans and widows, etc.). This will be used as a hint to the column bala
ncer to help set a |
91 // good initial column height. | 111 // good initial column height. |
92 LayoutUnit tallestUnbreakableLogicalHeight() const { return m_tallestUnbreak
ableLogicalHeight; } | 112 LayoutUnit tallestUnbreakableLogicalHeight() const { return m_tallestUnbreak
ableLogicalHeight; } |
93 | 113 |
94 private: | 114 private: |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 | 185 |
166 LayoutUnit m_tallestUnbreakableLogicalHeight; | 186 LayoutUnit m_tallestUnbreakableLogicalHeight; |
167 }; | 187 }; |
168 | 188 |
169 // If we have previously used InitialColumnHeightFinder to estimate an initial c
olumn height, and | 189 // If we have previously used InitialColumnHeightFinder to estimate an initial c
olumn height, and |
170 // that didn't result in tall enough columns, we need subsequent layout passes w
here we increase | 190 // that didn't result in tall enough columns, we need subsequent layout passes w
here we increase |
171 // the column height by the minimum space shortage at column breaks. This class
finds the minimum | 191 // the column height by the minimum space shortage at column breaks. This class
finds the minimum |
172 // space shortage after having laid out with the current column height. | 192 // space shortage after having laid out with the current column height. |
173 class MinimumSpaceShortageFinder final : public ColumnBalancer { | 193 class MinimumSpaceShortageFinder final : public ColumnBalancer { |
174 public: | 194 public: |
175 MinimumSpaceShortageFinder(const MultiColumnFragmentainerGroup&); | 195 MinimumSpaceShortageFinder(const LayoutMultiColumnSet&, LayoutUnit logicalTo
pInFlowThread, LayoutUnit logicalBottomInFlowThread); |
176 | 196 |
177 LayoutUnit minimumSpaceShortage() const { return m_minimumSpaceShortage; } | 197 LayoutUnit minimumSpaceShortage() const { return m_minimumSpaceShortage; } |
178 unsigned forcedBreaksCount() const { return m_forcedBreaksCount; } | 198 unsigned forcedBreaksCount() const { return m_forcedBreaksCount; } |
179 | 199 |
180 private: | 200 private: |
181 void examineBoxAfterEntering(const LayoutBox&); | 201 void examineBoxAfterEntering(const LayoutBox&); |
182 void examineBoxBeforeLeaving(const LayoutBox&); | 202 void examineBoxBeforeLeaving(const LayoutBox&); |
183 void examineLine(const RootInlineBox&); | 203 void examineLine(const RootInlineBox&); |
184 | 204 |
185 void recordSpaceShortage(LayoutUnit shortage) | 205 void recordSpaceShortage(LayoutUnit shortage) |
186 { | 206 { |
187 // Only positive values are interesting (and allowed) here. Zero space s
hortage may | 207 // Only positive values are interesting (and allowed) here. Zero space s
hortage may |
188 // be reported when we're at the top of a column and the element has zer
o | 208 // be reported when we're at the top of a column and the element has zer
o |
189 // height. | 209 // height. |
190 if (shortage > 0) | 210 if (shortage > 0) |
191 m_minimumSpaceShortage = std::min(m_minimumSpaceShortage, shortage); | 211 m_minimumSpaceShortage = std::min(m_minimumSpaceShortage, shortage); |
192 } | 212 } |
193 | 213 |
194 // The smallest amout of space shortage that caused a column break. | 214 // The smallest amout of space shortage that caused a column break. |
195 LayoutUnit m_minimumSpaceShortage; | 215 LayoutUnit m_minimumSpaceShortage; |
196 | 216 |
197 // Set when breaking before a block, and we're looking for the first unbreak
able descendant, in | 217 // Set when breaking before a block, and we're looking for the first unbreak
able descendant, in |
198 // order to report correct space shortage for that one. | 218 // order to report correct space shortage for that one. |
199 LayoutUnit m_pendingStrut; | 219 LayoutUnit m_pendingStrut; |
200 | 220 |
201 unsigned m_forcedBreaksCount; | 221 unsigned m_forcedBreaksCount; |
202 }; | 222 }; |
203 | 223 |
204 } // namespace blink | 224 } // namespace blink |
OLD | NEW |