| 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 |