 Chromium Code Reviews
 Chromium Code Reviews Issue 2391893004:
  Reformat comments in core/layout up until LayoutBox  (Closed)
    
  
    Issue 2391893004:
  Reformat comments in core/layout up until LayoutBox  (Closed) 
  | 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/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 11 matching lines...) Expand all Loading... | |
| 22 ASSERT(!flowThreadOffset()); | 22 ASSERT(!flowThreadOffset()); | 
| 23 } | 23 } | 
| 24 | 24 | 
| 25 void ColumnBalancer::traverseSubtree(const LayoutBox& box) { | 25 void ColumnBalancer::traverseSubtree(const LayoutBox& box) { | 
| 26 if (box.childrenInline() && box.isLayoutBlockFlow()) { | 26 if (box.childrenInline() && box.isLayoutBlockFlow()) { | 
| 27 // Look for breaks between lines. | 27 // Look for breaks between lines. | 
| 28 for (const RootInlineBox* line = toLayoutBlockFlow(box).firstRootBox(); | 28 for (const RootInlineBox* line = toLayoutBlockFlow(box).firstRootBox(); | 
| 29 line; line = line->nextRootBox()) { | 29 line; line = line->nextRootBox()) { | 
| 30 LayoutUnit lineTopInFlowThread = | 30 LayoutUnit lineTopInFlowThread = | 
| 31 m_flowThreadOffset + line->lineTopWithLeading(); | 31 m_flowThreadOffset + line->lineTopWithLeading(); | 
| 32 if (lineTopInFlowThread < logicalTopInFlowThread()) | 32 if (lineTopInFlowThread < logicalTopInFlowThread()) continue; | 
| 33 continue; | 33 if (lineTopInFlowThread >= logicalBottomInFlowThread()) break; | 
| 34 if (lineTopInFlowThread >= logicalBottomInFlowThread()) | |
| 35 break; | |
| 36 examineLine(*line); | 34 examineLine(*line); | 
| 37 } | 35 } | 
| 38 } | 36 } | 
| 39 | 37 | 
| 40 const LayoutFlowThread* flowThread = columnSet().flowThread(); | 38 const LayoutFlowThread* flowThread = columnSet().flowThread(); | 
| 41 bool isHorizontalWritingMode = flowThread->isHorizontalWritingMode(); | 39 bool isHorizontalWritingMode = flowThread->isHorizontalWritingMode(); | 
| 42 | 40 | 
| 43 // The break-after value from the previous in-flow block-level object to be jo ined with the | 41 // The break-after value from the previous in-flow block-level object to be | 
| 42 // joined with the | |
| 44 // break-before value of the next in-flow block-level sibling. | 43 // break-before value of the next in-flow block-level sibling. | 
| 
ikilpatrick
2016/10/04 16:39:02
bad.
 | |
| 45 EBreak previousBreakAfterValue = BreakAuto; | 44 EBreak previousBreakAfterValue = BreakAuto; | 
| 46 | 45 | 
| 47 // Look for breaks between and inside block-level children. Even if this is a block flow with | 46 // Look for breaks between and inside block-level children. Even if this is a | 
| 47 // block flow with | |
| 48 // inline children, there may be interesting floats to examine here. | 48 // inline children, there may be interesting floats to examine here. | 
| 49 for (const LayoutObject* child = box.slowFirstChild(); child; | 49 for (const LayoutObject* child = box.slowFirstChild(); child; | 
| 50 child = child->nextSibling()) { | 50 child = child->nextSibling()) { | 
| 51 if (!child->isBox() || child->isInline()) | 51 if (!child->isBox() || child->isInline()) continue; | 
| 52 continue; | |
| 53 const LayoutBox& childBox = toLayoutBox(*child); | 52 const LayoutBox& childBox = toLayoutBox(*child); | 
| 54 LayoutRect overflowRect = childBox.layoutOverflowRect(); | 53 LayoutRect overflowRect = childBox.layoutOverflowRect(); | 
| 55 LayoutUnit childLogicalBottomWithOverflow = | 54 LayoutUnit childLogicalBottomWithOverflow = | 
| 56 childBox.logicalTop() + | 55 childBox.logicalTop() + | 
| 57 (isHorizontalWritingMode ? overflowRect.maxY() : overflowRect.maxX()); | 56 (isHorizontalWritingMode ? overflowRect.maxY() : overflowRect.maxX()); | 
| 58 if (m_flowThreadOffset + childLogicalBottomWithOverflow <= | 57 if (m_flowThreadOffset + childLogicalBottomWithOverflow <= | 
| 59 logicalTopInFlowThread()) { | 58 logicalTopInFlowThread()) { | 
| 60 // This child is fully above the flow thread portion we're examining. | 59 // This child is fully above the flow thread portion we're examining. | 
| 61 continue; | 60 continue; | 
| 62 } | 61 } | 
| 63 LayoutUnit childLogicalTopWithOverflow = | 62 LayoutUnit childLogicalTopWithOverflow = | 
| 64 childBox.logicalTop() + | 63 childBox.logicalTop() + | 
| 65 (isHorizontalWritingMode ? overflowRect.y() : overflowRect.x()); | 64 (isHorizontalWritingMode ? overflowRect.y() : overflowRect.x()); | 
| 66 if (m_flowThreadOffset + childLogicalTopWithOverflow >= | 65 if (m_flowThreadOffset + childLogicalTopWithOverflow >= | 
| 67 logicalBottomInFlowThread()) { | 66 logicalBottomInFlowThread()) { | 
| 68 // This child is fully below the flow thread portion we're examining. We c annot just | 67 // This child is fully below the flow thread portion we're examining. We | 
| 68 // cannot just | |
| 
ikilpatrick
2016/10/04 16:39:02
bad.
 | |
| 69 // stop here, though, thanks to negative margins. So keep looking. | 69 // stop here, though, thanks to negative margins. So keep looking. | 
| 70 continue; | 70 continue; | 
| 71 } | 71 } | 
| 72 if (childBox.isOutOfFlowPositioned() || childBox.isColumnSpanAll()) | 72 if (childBox.isOutOfFlowPositioned() || childBox.isColumnSpanAll()) | 
| 73 continue; | 73 continue; | 
| 74 | 74 | 
| 75 // Tables are wicked. Both table rows and table cells are relative to their table section. | 75 // Tables are wicked. Both table rows and table cells are relative to their | 
| 76 // table section. | |
| 76 LayoutUnit offsetForThisChild = | 77 LayoutUnit offsetForThisChild = | 
| 77 childBox.isTableRow() ? LayoutUnit() : childBox.logicalTop(); | 78 childBox.isTableRow() ? LayoutUnit() : childBox.logicalTop(); | 
| 78 m_flowThreadOffset += offsetForThisChild; | 79 m_flowThreadOffset += offsetForThisChild; | 
| 79 | 80 | 
| 80 examineBoxAfterEntering(childBox, previousBreakAfterValue); | 81 examineBoxAfterEntering(childBox, previousBreakAfterValue); | 
| 81 // Unless the child is unsplittable, or if the child establishes an inner mu lticol | 82 // Unless the child is unsplittable, or if the child establishes an inner | 
| 83 // multicol | |
| 
ikilpatrick
2016/10/04 16:39:02
bad.
 | |
| 82 // container, we descend into its subtree for further examination. | 84 // container, we descend into its subtree for further examination. | 
| 83 if (childBox.getPaginationBreakability() != LayoutBox::ForbidBreaks && | 85 if (childBox.getPaginationBreakability() != LayoutBox::ForbidBreaks && | 
| 84 (!childBox.isLayoutBlockFlow() || | 86 (!childBox.isLayoutBlockFlow() || | 
| 85 !toLayoutBlockFlow(childBox).multiColumnFlowThread())) | 87 !toLayoutBlockFlow(childBox).multiColumnFlowThread())) | 
| 86 traverseSubtree(childBox); | 88 traverseSubtree(childBox); | 
| 87 previousBreakAfterValue = childBox.breakAfter(); | 89 previousBreakAfterValue = childBox.breakAfter(); | 
| 88 examineBoxBeforeLeaving(childBox); | 90 examineBoxBeforeLeaving(childBox); | 
| 89 | 91 | 
| 90 m_flowThreadOffset -= offsetForThisChild; | 92 m_flowThreadOffset -= offsetForThisChild; | 
| 91 } | 93 } | 
| 92 } | 94 } | 
| 93 | 95 | 
| 94 InitialColumnHeightFinder::InitialColumnHeightFinder( | 96 InitialColumnHeightFinder::InitialColumnHeightFinder( | 
| 95 const LayoutMultiColumnSet& columnSet, | 97 const LayoutMultiColumnSet& columnSet, LayoutUnit logicalTopInFlowThread, | 
| 96 LayoutUnit logicalTopInFlowThread, | |
| 97 LayoutUnit logicalBottomInFlowThread) | 98 LayoutUnit logicalBottomInFlowThread) | 
| 98 : ColumnBalancer(columnSet, | 99 : ColumnBalancer(columnSet, logicalTopInFlowThread, | 
| 99 logicalTopInFlowThread, | |
| 100 logicalBottomInFlowThread) { | 100 logicalBottomInFlowThread) { | 
| 101 m_shortestStruts.resize(columnSet.usedColumnCount()); | 101 m_shortestStruts.resize(columnSet.usedColumnCount()); | 
| 102 for (auto& strut : m_shortestStruts) | 102 for (auto& strut : m_shortestStruts) strut = LayoutUnit::max() { } | 
| 103 strut = LayoutUnit::max(); | |
| 104 traverse(); | 103 traverse(); | 
| 105 // We have now found each explicit / forced break, and their location. Now we need to figure out | 104 // We have now found each explicit / forced break, and their location. Now we | 
| 106 // how many additional implicit / soft breaks we need and guess where they wil l occur, in order | 105 // need to figure out how many additional implicit / soft breaks we need and | 
| 106 // guess where they will occur, in order | |
| 107 // to provide an initial column height. | 107 // to provide an initial column height. | 
| 108 distributeImplicitBreaks(); | 108 distributeImplicitBreaks(); | 
| 109 } | 109 } | 
| 110 | 110 | 
| 111 LayoutUnit InitialColumnHeightFinder::initialMinimalBalancedHeight() const { | 111 LayoutUnit InitialColumnHeightFinder::initialMinimalBalancedHeight() const { | 
| 112 unsigned index = contentRunIndexWithTallestColumns(); | 112 unsigned index = contentRunIndexWithTallestColumns(); | 
| 113 LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset() | 113 LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset() | 
| 114 : logicalTopInFlowThread(); | 114 : logicalTopInFlowThread(); | 
| 115 return m_contentRuns[index].columnLogicalHeight(startOffset); | 115 return m_contentRuns[index].columnLogicalHeight(startOffset); | 
| 116 } | 116 } | 
| 117 | 117 | 
| 118 void InitialColumnHeightFinder::examineBoxAfterEntering( | 118 void InitialColumnHeightFinder::examineBoxAfterEntering( | 
| 119 const LayoutBox& box, | 119 const LayoutBox& box, EBreak previousBreakAfterValue) { | 
| 120 EBreak previousBreakAfterValue) { | |
| 121 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { | 120 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { | 
| 122 if (box.needsForcedBreakBefore(previousBreakAfterValue)) { | 121 if (box.needsForcedBreakBefore(previousBreakAfterValue)) { | 
| 123 addContentRun(flowThreadOffset()); | 122 addContentRun(flowThreadOffset()); | 
| 124 } else { | 123 } else { | 
| 125 ASSERT(isFirstAfterBreak(flowThreadOffset()) || !box.paginationStrut()); | 124 ASSERT(isFirstAfterBreak(flowThreadOffset()) || !box.paginationStrut()); | 
| 126 if (isFirstAfterBreak(flowThreadOffset())) { | 125 if (isFirstAfterBreak(flowThreadOffset())) { | 
| 127 // This box is first after a soft break. | 126 // This box is first after a soft break. | 
| 128 recordStrutBeforeOffset(flowThreadOffset(), box.paginationStrut()); | 127 recordStrutBeforeOffset(flowThreadOffset(), box.paginationStrut()); | 
| 129 } | 128 } | 
| 130 } | 129 } | 
| 131 } | 130 } | 
| 132 | 131 | 
| 133 if (box.getPaginationBreakability() != LayoutBox::AllowAnyBreaks) { | 132 if (box.getPaginationBreakability() != LayoutBox::AllowAnyBreaks) { | 
| 134 LayoutUnit unsplittableLogicalHeight = box.logicalHeight(); | 133 LayoutUnit unsplittableLogicalHeight = box.logicalHeight(); | 
| 135 if (box.isFloating()) | 134 if (box.isFloating()) | 
| 136 unsplittableLogicalHeight += box.marginBefore() + box.marginAfter(); | 135 unsplittableLogicalHeight += box.marginBefore() + box.marginAfter(); | 
| 137 m_tallestUnbreakableLogicalHeight = | 136 m_tallestUnbreakableLogicalHeight = | 
| 138 std::max(m_tallestUnbreakableLogicalHeight, unsplittableLogicalHeight); | 137 std::max(m_tallestUnbreakableLogicalHeight, unsplittableLogicalHeight); | 
| 139 return; | 138 return; | 
| 140 } | 139 } | 
| 141 // Need to examine inner multicol containers to find their tallest unbreakable piece of content. | 140 // Need to examine inner multicol containers to find their tallest unbreakable | 
| 142 if (!box.isLayoutBlockFlow()) | 141 // piece of content. | 
| 143 return; | 142 if (!box.isLayoutBlockFlow()) return; | 
| 144 LayoutMultiColumnFlowThread* innerFlowThread = | 143 LayoutMultiColumnFlowThread* innerFlowThread = | 
| 145 toLayoutBlockFlow(box).multiColumnFlowThread(); | 144 toLayoutBlockFlow(box).multiColumnFlowThread(); | 
| 146 if (!innerFlowThread || innerFlowThread->isLayoutPagedFlowThread()) | 145 if (!innerFlowThread || innerFlowThread->isLayoutPagedFlowThread()) return; | 
| 147 return; | |
| 148 LayoutUnit offsetInInnerFlowThread = | 146 LayoutUnit offsetInInnerFlowThread = | 
| 149 flowThreadOffset() - | 147 flowThreadOffset() - | 
| 150 innerFlowThread->blockOffsetInEnclosingFragmentationContext(); | 148 innerFlowThread->blockOffsetInEnclosingFragmentationContext(); | 
| 151 LayoutUnit innerUnbreakableHeight = | 149 LayoutUnit innerUnbreakableHeight = | 
| 152 innerFlowThread->tallestUnbreakableLogicalHeight(offsetInInnerFlowThread); | 150 innerFlowThread->tallestUnbreakableLogicalHeight(offsetInInnerFlowThread); | 
| 153 m_tallestUnbreakableLogicalHeight = | 151 m_tallestUnbreakableLogicalHeight = | 
| 154 std::max(m_tallestUnbreakableLogicalHeight, innerUnbreakableHeight); | 152 std::max(m_tallestUnbreakableLogicalHeight, innerUnbreakableHeight); | 
| 155 } | 153 } | 
| 156 | 154 | 
| 157 void InitialColumnHeightFinder::examineBoxBeforeLeaving(const LayoutBox& box) {} | 155 void InitialColumnHeightFinder::examineBoxBeforeLeaving(const LayoutBox& box) {} | 
| 158 | 156 | 
| 159 static inline LayoutUnit columnLogicalHeightRequirementForLine( | 157 static inline LayoutUnit columnLogicalHeightRequirementForLine( | 
| 160 const ComputedStyle& style, | 158 const ComputedStyle& style, const RootInlineBox& lastLine) { | 
| 161 const RootInlineBox& lastLine) { | 159 // We may require a certain minimum number of lines per page in order to | 
| 162 // We may require a certain minimum number of lines per page in order to satis fy | 160 // satisfy | 
| 163 // orphans and widows, and that may affect the minimum page height. | 161 // orphans and widows, and that may affect the minimum page height. | 
| 
ikilpatrick
2016/10/04 16:39:02
bad.
 | |
| 164 unsigned minimumLineCount = | 162 unsigned minimumLineCount = | 
| 165 std::max<unsigned>(style.orphans(), style.widows()); | 163 std::max<unsigned>(style.orphans(), style.widows()); | 
| 166 const RootInlineBox* firstLine = &lastLine; | 164 const RootInlineBox* firstLine = &lastLine; | 
| 167 for (unsigned i = 1; i < minimumLineCount && firstLine->prevRootBox(); i++) | 165 for (unsigned i = 1; i < minimumLineCount && firstLine->prevRootBox(); i++) | 
| 168 firstLine = firstLine->prevRootBox(); | 166 firstLine = firstLine->prevRootBox(); | 
| 169 return lastLine.lineBottomWithLeading() - firstLine->lineTopWithLeading(); | 167 return lastLine.lineBottomWithLeading() - firstLine->lineTopWithLeading(); | 
| 170 } | 168 } | 
| 171 | 169 | 
| 172 void InitialColumnHeightFinder::examineLine(const RootInlineBox& line) { | 170 void InitialColumnHeightFinder::examineLine(const RootInlineBox& line) { | 
| 173 LayoutUnit lineTop = line.lineTopWithLeading(); | 171 LayoutUnit lineTop = line.lineTopWithLeading(); | 
| 174 LayoutUnit lineTopInFlowThread = flowThreadOffset() + lineTop; | 172 LayoutUnit lineTopInFlowThread = flowThreadOffset() + lineTop; | 
| 175 LayoutUnit minimumLogialHeight = | 173 LayoutUnit minimumLogialHeight = | 
| 176 columnLogicalHeightRequirementForLine(line.block().styleRef(), line); | 174 columnLogicalHeightRequirementForLine(line.block().styleRef(), line); | 
| 177 m_tallestUnbreakableLogicalHeight = | 175 m_tallestUnbreakableLogicalHeight = | 
| 178 std::max(m_tallestUnbreakableLogicalHeight, minimumLogialHeight); | 176 std::max(m_tallestUnbreakableLogicalHeight, minimumLogialHeight); | 
| 179 ASSERT( | 177 ASSERT( | 
| 180 isFirstAfterBreak(lineTopInFlowThread) || !line.paginationStrut() || | 178 isFirstAfterBreak(lineTopInFlowThread) || !line.paginationStrut() || | 
| 181 !isLogicalTopWithinBounds(lineTopInFlowThread - line.paginationStrut())); | 179 !isLogicalTopWithinBounds(lineTopInFlowThread - line.paginationStrut())); | 
| 182 if (isFirstAfterBreak(lineTopInFlowThread)) | 180 if (isFirstAfterBreak(lineTopInFlowThread)) | 
| 183 recordStrutBeforeOffset(lineTopInFlowThread, line.paginationStrut()); | 181 recordStrutBeforeOffset(lineTopInFlowThread, line.paginationStrut()); | 
| 184 } | 182 } | 
| 185 | 183 | 
| 186 void InitialColumnHeightFinder::recordStrutBeforeOffset( | 184 void InitialColumnHeightFinder::recordStrutBeforeOffset( | 
| 187 LayoutUnit offsetInFlowThread, | 185 LayoutUnit offsetInFlowThread, LayoutUnit strut) { | 
| 188 LayoutUnit strut) { | |
| 189 ASSERT(columnSet().usedColumnCount() >= 1); | 186 ASSERT(columnSet().usedColumnCount() >= 1); | 
| 190 unsigned columnCount = columnSet().usedColumnCount(); | 187 unsigned columnCount = columnSet().usedColumnCount(); | 
| 191 ASSERT(m_shortestStruts.size() == columnCount); | 188 ASSERT(m_shortestStruts.size() == columnCount); | 
| 192 unsigned index = groupAtOffset(offsetInFlowThread) | 189 unsigned index = groupAtOffset(offsetInFlowThread) | 
| 193 .columnIndexAtOffset(offsetInFlowThread - strut, | 190 .columnIndexAtOffset(offsetInFlowThread - strut, | 
| 194 LayoutBox::AssociateWithLatterPage); | 191 LayoutBox::AssociateWithLatterPage); | 
| 195 if (index >= columnCount) | 192 if (index >= columnCount) return; | 
| 196 return; | |
| 197 m_shortestStruts[index] = std::min(m_shortestStruts[index], strut); | 193 m_shortestStruts[index] = std::min(m_shortestStruts[index], strut); | 
| 198 } | 194 } | 
| 199 | 195 | 
| 200 LayoutUnit InitialColumnHeightFinder::spaceUsedByStrutsAt( | 196 LayoutUnit InitialColumnHeightFinder::spaceUsedByStrutsAt( | 
| 201 LayoutUnit offsetInFlowThread) const { | 197 LayoutUnit offsetInFlowThread) const { | 
| 202 unsigned stopBeforeColumn = | 198 unsigned stopBeforeColumn = | 
| 203 groupAtOffset(offsetInFlowThread) | 199 groupAtOffset(offsetInFlowThread) | 
| 204 .columnIndexAtOffset(offsetInFlowThread, | 200 .columnIndexAtOffset(offsetInFlowThread, | 
| 205 LayoutBox::AssociateWithLatterPage) + | 201 LayoutBox::AssociateWithLatterPage) + | 
| 206 1; | 202 1; | 
| 207 stopBeforeColumn = std::min(stopBeforeColumn, columnSet().usedColumnCount()); | 203 stopBeforeColumn = std::min(stopBeforeColumn, columnSet().usedColumnCount()); | 
| 208 ASSERT(stopBeforeColumn <= m_shortestStruts.size()); | 204 ASSERT(stopBeforeColumn <= m_shortestStruts.size()); | 
| 209 LayoutUnit totalStrutSpace; | 205 LayoutUnit totalStrutSpace; | 
| 210 for (unsigned i = 0; i < stopBeforeColumn; i++) { | 206 for (unsigned i = 0; i < stopBeforeColumn; i++) { | 
| 211 if (m_shortestStruts[i] != LayoutUnit::max()) | 207 if (m_shortestStruts[i] != LayoutUnit::max()) | 
| 212 totalStrutSpace += m_shortestStruts[i]; | 208 totalStrutSpace += m_shortestStruts[i]; | 
| 213 } | 209 } | 
| 214 return totalStrutSpace; | 210 return totalStrutSpace; | 
| 215 } | 211 } | 
| 216 | 212 | 
| 217 void InitialColumnHeightFinder::addContentRun( | 213 void InitialColumnHeightFinder::addContentRun( | 
| 218 LayoutUnit endOffsetInFlowThread) { | 214 LayoutUnit endOffsetInFlowThread) { | 
| 219 endOffsetInFlowThread -= spaceUsedByStrutsAt(endOffsetInFlowThread); | 215 endOffsetInFlowThread -= spaceUsedByStrutsAt(endOffsetInFlowThread); | 
| 220 if (!m_contentRuns.isEmpty() && | 216 if (!m_contentRuns.isEmpty() && | 
| 221 endOffsetInFlowThread <= m_contentRuns.last().breakOffset()) | 217 endOffsetInFlowThread <= m_contentRuns.last().breakOffset()) | 
| 222 return; | 218 return; | 
| 223 // Append another item as long as we haven't exceeded used column count. What ends up in the | 219 // Append another item as long as we haven't exceeded used column count. What | 
| 220 // ends up in the | |
| 224 // overflow area shouldn't affect column balancing. | 221 // overflow area shouldn't affect column balancing. | 
| 
ikilpatrick
2016/10/04 16:39:02
bad.
 | |
| 225 if (m_contentRuns.size() < columnSet().usedColumnCount()) | 222 if (m_contentRuns.size() < columnSet().usedColumnCount()) | 
| 226 m_contentRuns.append(ContentRun(endOffsetInFlowThread)); | 223 m_contentRuns.append(ContentRun(endOffsetInFlowThread)); | 
| 227 } | 224 } | 
| 228 | 225 | 
| 229 unsigned InitialColumnHeightFinder::contentRunIndexWithTallestColumns() const { | 226 unsigned InitialColumnHeightFinder::contentRunIndexWithTallestColumns() const { | 
| 230 unsigned indexWithLargestHeight = 0; | 227 unsigned indexWithLargestHeight = 0; | 
| 231 LayoutUnit largestHeight; | 228 LayoutUnit largestHeight; | 
| 232 LayoutUnit previousOffset = logicalTopInFlowThread(); | 229 LayoutUnit previousOffset = logicalTopInFlowThread(); | 
| 233 size_t runCount = m_contentRuns.size(); | 230 size_t runCount = m_contentRuns.size(); | 
| 234 ASSERT(runCount); | 231 ASSERT(runCount); | 
| 235 for (size_t i = 0; i < runCount; i++) { | 232 for (size_t i = 0; i < runCount; i++) { | 
| 236 const ContentRun& run = m_contentRuns[i]; | 233 const ContentRun& run = m_contentRuns[i]; | 
| 237 LayoutUnit height = run.columnLogicalHeight(previousOffset); | 234 LayoutUnit height = run.columnLogicalHeight(previousOffset); | 
| 238 if (largestHeight < height) { | 235 if (largestHeight < height) { | 
| 239 largestHeight = height; | 236 largestHeight = height; | 
| 240 indexWithLargestHeight = i; | 237 indexWithLargestHeight = i; | 
| 241 } | 238 } | 
| 242 previousOffset = run.breakOffset(); | 239 previousOffset = run.breakOffset(); | 
| 243 } | 240 } | 
| 244 return indexWithLargestHeight; | 241 return indexWithLargestHeight; | 
| 245 } | 242 } | 
| 246 | 243 | 
| 247 void InitialColumnHeightFinder::distributeImplicitBreaks() { | 244 void InitialColumnHeightFinder::distributeImplicitBreaks() { | 
| 248 // Insert a final content run to encompass all content. This will include over flow if we're at | 245 // Insert a final content run to encompass all content. This will include | 
| 246 // overflow if we're at | |
| 249 // the end of the multicol container. | 247 // the end of the multicol container. | 
| 
ikilpatrick
2016/10/04 16:39:02
bad.
 | |
| 250 addContentRun(logicalBottomInFlowThread()); | 248 addContentRun(logicalBottomInFlowThread()); | 
| 251 unsigned columnCount = m_contentRuns.size(); | 249 unsigned columnCount = m_contentRuns.size(); | 
| 252 | 250 | 
| 253 // If there is room for more breaks (to reach the used value of column-count), imagine that we | 251 // If there is room for more breaks (to reach the used value of column-count), | 
| 254 // insert implicit breaks at suitable locations. At any given time, the conten t run with the | 252 // imagine that we insert implicit breaks at suitable locations. At any given | 
| 255 // currently tallest columns will get another implicit break "inserted", which will increase its | 253 // time, the content run with the currently tallest columns will get another | 
| 256 // column count by one and shrink its columns' height. Repeat until we have th e desired total | 254 // implicit break "inserted", which will increase its column count by one and | 
| 257 // number of breaks. The largest column height among the runs will then be the initial column | 255 // shrink its columns' height. Repeat until we have the desired total number | 
| 258 // height for the balancer to use. | 256 // of breaks. The largest column height among the runs will then be the | 
| 257 // initial column height for the balancer to use. | |
| 259 while (columnCount < columnSet().usedColumnCount()) { | 258 while (columnCount < columnSet().usedColumnCount()) { | 
| 260 unsigned index = contentRunIndexWithTallestColumns(); | 259 unsigned index = contentRunIndexWithTallestColumns(); | 
| 261 m_contentRuns[index].assumeAnotherImplicitBreak(); | 260 m_contentRuns[index].assumeAnotherImplicitBreak(); | 
| 262 columnCount++; | 261 columnCount++; | 
| 263 } | 262 } | 
| 264 } | 263 } | 
| 265 | 264 | 
| 266 MinimumSpaceShortageFinder::MinimumSpaceShortageFinder( | 265 MinimumSpaceShortageFinder::MinimumSpaceShortageFinder( | 
| 267 const LayoutMultiColumnSet& columnSet, | 266 const LayoutMultiColumnSet& columnSet, LayoutUnit logicalTopInFlowThread, | 
| 268 LayoutUnit logicalTopInFlowThread, | |
| 269 LayoutUnit logicalBottomInFlowThread) | 267 LayoutUnit logicalBottomInFlowThread) | 
| 270 : ColumnBalancer(columnSet, | 268 : ColumnBalancer(columnSet, logicalTopInFlowThread, | 
| 271 logicalTopInFlowThread, | |
| 272 logicalBottomInFlowThread), | 269 logicalBottomInFlowThread), | 
| 273 m_minimumSpaceShortage(LayoutUnit::max()), | 270 m_minimumSpaceShortage(LayoutUnit::max()), | 
| 274 m_pendingStrut(LayoutUnit::min()), | 271 m_pendingStrut(LayoutUnit::min()), | 
| 275 m_forcedBreaksCount(0) { | 272 m_forcedBreaksCount(0) { | 
| 276 traverse(); | 273 traverse(); | 
| 277 } | 274 } | 
| 278 | 275 | 
| 279 void MinimumSpaceShortageFinder::examineBoxAfterEntering( | 276 void MinimumSpaceShortageFinder::examineBoxAfterEntering( | 
| 280 const LayoutBox& box, | 277 const LayoutBox& box, EBreak previousBreakAfterValue) { | 
| 281 EBreak previousBreakAfterValue) { | |
| 282 LayoutBox::PaginationBreakability breakability = | 278 LayoutBox::PaginationBreakability breakability = | 
| 283 box.getPaginationBreakability(); | 279 box.getPaginationBreakability(); | 
| 284 | 280 | 
| 285 // Look for breaks before the child box. | 281 // Look for breaks before the child box. | 
| 286 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { | 282 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { | 
| 287 if (box.needsForcedBreakBefore(previousBreakAfterValue)) { | 283 if (box.needsForcedBreakBefore(previousBreakAfterValue)) { | 
| 288 m_forcedBreaksCount++; | 284 m_forcedBreaksCount++; | 
| 289 } else { | 285 } else { | 
| 290 ASSERT(isFirstAfterBreak(flowThreadOffset()) || !box.paginationStrut()); | 286 ASSERT(isFirstAfterBreak(flowThreadOffset()) || !box.paginationStrut()); | 
| 291 if (isFirstAfterBreak(flowThreadOffset())) { | 287 if (isFirstAfterBreak(flowThreadOffset())) { | 
| 292 // This box is first after a soft break. | 288 // This box is first after a soft break. | 
| 293 LayoutUnit strut = box.paginationStrut(); | 289 LayoutUnit strut = box.paginationStrut(); | 
| 294 // Figure out how much more space we would need to prevent it from being pushed to the next column. | 290 // Figure out how much more space we would need to prevent it from being | 
| 291 // pushed to the next column. | |
| 295 recordSpaceShortage(box.logicalHeight() - strut); | 292 recordSpaceShortage(box.logicalHeight() - strut); | 
| 296 if (breakability != LayoutBox::ForbidBreaks && | 293 if (breakability != LayoutBox::ForbidBreaks && | 
| 297 m_pendingStrut == LayoutUnit::min()) { | 294 m_pendingStrut == LayoutUnit::min()) { | 
| 298 // We now want to look for the first piece of unbreakable content (e.g . a line or a | 295 // We now want to look for the first piece of unbreakable content | 
| 299 // block-displayed image) inside this block. That ought to be a good c andidate for | 296 // (e.g. a line or a block-displayed image) inside this block. That | 
| 300 // minimum space shortage; a much better one than reporting space shor tage for the | 297 // ought to be a good candidate for minimum space shortage; a much | 
| 301 // entire block (which we'll also do (further down), in case we couldn 't find anything | 298 // better one than reporting space shortage for the entire block | 
| 302 // more suitable). | 299 // (which we'll also do (further down), in case we couldn't find | 
| 300 // anything more suitable). | |
| 303 m_pendingStrut = strut; | 301 m_pendingStrut = strut; | 
| 304 } | 302 } | 
| 305 } | 303 } | 
| 306 } | 304 } | 
| 307 } | 305 } | 
| 308 | 306 | 
| 309 if (breakability != LayoutBox::ForbidBreaks) { | 307 if (breakability != LayoutBox::ForbidBreaks) { | 
| 310 // See if this breakable box crosses column boundaries. | 308 // See if this breakable box crosses column boundaries. | 
| 311 LayoutUnit bottomInFlowThread = flowThreadOffset() + box.logicalHeight(); | 309 LayoutUnit bottomInFlowThread = flowThreadOffset() + box.logicalHeight(); | 
| 312 const MultiColumnFragmentainerGroup& group = | 310 const MultiColumnFragmentainerGroup& group = | 
| 313 groupAtOffset(flowThreadOffset()); | 311 groupAtOffset(flowThreadOffset()); | 
| 314 if (isFirstAfterBreak(flowThreadOffset()) || | 312 if (isFirstAfterBreak(flowThreadOffset()) || | 
| 315 group.columnLogicalTopForOffset(flowThreadOffset()) != | 313 group.columnLogicalTopForOffset(flowThreadOffset()) != | 
| 316 group.columnLogicalTopForOffset(bottomInFlowThread)) { | 314 group.columnLogicalTopForOffset(bottomInFlowThread)) { | 
| 317 // If the child crosses a column boundary, record space shortage, in case nothing | 315 // If the child crosses a column boundary, record space shortage, in case | 
| 318 // inside it has already done so. The column balancer needs to know by how much it | 316 // nothing inside it has already done so. The column balancer needs to | 
| 319 // has to stretch the columns to make more content fit. If no breaks are r eported | 317 // know by how much it has to stretch the columns to make more content | 
| 320 // (but do occur), the balancer will have no clue. Only measure the space after the | 318 // fit. If no breaks are reported (but do occur), the balancer will have | 
| 321 // last column boundary, in case it crosses more than one. | 319 // no clue. Only measure the space after the last column boundary, in case | 
| 320 // it crosses more than one. | |
| 322 LayoutUnit spaceUsedInLastColumn = | 321 LayoutUnit spaceUsedInLastColumn = | 
| 323 bottomInFlowThread - | 322 bottomInFlowThread - | 
| 324 group.columnLogicalTopForOffset(bottomInFlowThread); | 323 group.columnLogicalTopForOffset(bottomInFlowThread); | 
| 325 recordSpaceShortage(spaceUsedInLastColumn); | 324 recordSpaceShortage(spaceUsedInLastColumn); | 
| 326 } | 325 } | 
| 327 } | 326 } | 
| 328 | 327 | 
| 329 // If this is an inner multicol container, look for space shortage inside it. | 328 // If this is an inner multicol container, look for space shortage inside it. | 
| 330 if (!box.isLayoutBlockFlow()) | 329 if (!box.isLayoutBlockFlow()) return; | 
| 331 return; | |
| 332 LayoutMultiColumnFlowThread* flowThread = | 330 LayoutMultiColumnFlowThread* flowThread = | 
| 333 toLayoutBlockFlow(box).multiColumnFlowThread(); | 331 toLayoutBlockFlow(box).multiColumnFlowThread(); | 
| 334 if (!flowThread || flowThread->isLayoutPagedFlowThread()) | 332 if (!flowThread || flowThread->isLayoutPagedFlowThread()) return; | 
| 335 return; | |
| 336 for (const LayoutMultiColumnSet* columnSet = | 333 for (const LayoutMultiColumnSet* columnSet = | 
| 337 flowThread->firstMultiColumnSet(); | 334 flowThread->firstMultiColumnSet(); | 
| 338 columnSet; columnSet = columnSet->nextSiblingMultiColumnSet()) { | 335 columnSet; columnSet = columnSet->nextSiblingMultiColumnSet()) { | 
| 339 // Establish an inner shortage finder for this column set in the inner multi col | 336 // Establish an inner shortage finder for this column set in the inner | 
| 340 // container. We need to let it walk through all fragmentainer groups in one go, or we'd | 337 // multicol container. We need to let it walk through all fragmentainer | 
| 341 // miss the column boundaries between each fragmentainer group. We need to r ecord space | 338 // groups in one go, or we'd miss the column boundaries between each | 
| 342 // shortage there too. | 339 // fragmentainer group. We need to record space shortage there too. | 
| 343 MinimumSpaceShortageFinder innerFinder( | 340 MinimumSpaceShortageFinder innerFinder( | 
| 344 *columnSet, columnSet->logicalTopInFlowThread(), | 341 *columnSet, columnSet->logicalTopInFlowThread(), | 
| 345 columnSet->logicalBottomInFlowThread()); | 342 columnSet->logicalBottomInFlowThread()); | 
| 346 recordSpaceShortage(innerFinder.minimumSpaceShortage()); | 343 recordSpaceShortage(innerFinder.minimumSpaceShortage()); | 
| 347 } | 344 } | 
| 348 } | 345 } | 
| 349 | 346 | 
| 350 void MinimumSpaceShortageFinder::examineBoxBeforeLeaving(const LayoutBox& box) { | 347 void MinimumSpaceShortageFinder::examineBoxBeforeLeaving(const LayoutBox& box) { | 
| 351 if (m_pendingStrut == LayoutUnit::min() || | 348 if (m_pendingStrut == LayoutUnit::min() || | 
| 352 box.getPaginationBreakability() != LayoutBox::ForbidBreaks) | 349 box.getPaginationBreakability() != LayoutBox::ForbidBreaks) | 
| 353 return; | 350 return; | 
| 354 | 351 | 
| 355 // The previous break was before a breakable block. Here's the first piece of unbreakable | 352 // The previous break was before a breakable block. Here's the first piece of | 
| 356 // content after / inside that block. We want to record the distance from the top of the column | 353 // unbreakable content after / inside that block. We want to record the | 
| 357 // to the bottom of this box as space shortage. | 354 // distance from the top of the column to the bottom of this box as space | 
| 355 // shortage. | |
| 358 LayoutUnit logicalOffsetFromCurrentColumn = | 356 LayoutUnit logicalOffsetFromCurrentColumn = | 
| 359 offsetFromColumnLogicalTop(flowThreadOffset()); | 357 offsetFromColumnLogicalTop(flowThreadOffset()); | 
| 360 recordSpaceShortage(logicalOffsetFromCurrentColumn + box.logicalHeight() - | 358 recordSpaceShortage(logicalOffsetFromCurrentColumn + box.logicalHeight() - | 
| 361 m_pendingStrut); | 359 m_pendingStrut); | 
| 362 m_pendingStrut = LayoutUnit::min(); | 360 m_pendingStrut = LayoutUnit::min(); | 
| 363 } | 361 } | 
| 364 | 362 | 
| 365 void MinimumSpaceShortageFinder::examineLine(const RootInlineBox& line) { | 363 void MinimumSpaceShortageFinder::examineLine(const RootInlineBox& line) { | 
| 366 LayoutUnit lineTop = line.lineTopWithLeading(); | 364 LayoutUnit lineTop = line.lineTopWithLeading(); | 
| 367 LayoutUnit lineTopInFlowThread = flowThreadOffset() + lineTop; | 365 LayoutUnit lineTopInFlowThread = flowThreadOffset() + lineTop; | 
| 368 LayoutUnit lineHeight = line.lineBottomWithLeading() - lineTop; | 366 LayoutUnit lineHeight = line.lineBottomWithLeading() - lineTop; | 
| 369 if (m_pendingStrut != LayoutUnit::min()) { | 367 if (m_pendingStrut != LayoutUnit::min()) { | 
| 370 // The previous break was before a breakable block. Here's the first line af ter / inside | 368 // The previous break was before a breakable block. Here's the first line | 
| 371 // that block. We want to record the distance from the top of the column to the bottom of | 369 // after / inside that block. We want to record the distance from the top of | 
| 372 // this box as space shortage. | 370 // the column to the bottom of this box as space shortage. | 
| 373 LayoutUnit logicalOffsetFromCurrentColumn = | 371 LayoutUnit logicalOffsetFromCurrentColumn = | 
| 374 offsetFromColumnLogicalTop(lineTopInFlowThread); | 372 offsetFromColumnLogicalTop(lineTopInFlowThread); | 
| 375 recordSpaceShortage(logicalOffsetFromCurrentColumn + lineHeight - | 373 recordSpaceShortage(logicalOffsetFromCurrentColumn + lineHeight - | 
| 376 m_pendingStrut); | 374 m_pendingStrut); | 
| 377 m_pendingStrut = LayoutUnit::min(); | 375 m_pendingStrut = LayoutUnit::min(); | 
| 378 return; | 376 return; | 
| 379 } | 377 } | 
| 380 ASSERT( | 378 ASSERT( | 
| 381 isFirstAfterBreak(lineTopInFlowThread) || !line.paginationStrut() || | 379 isFirstAfterBreak(lineTopInFlowThread) || !line.paginationStrut() || | 
| 382 !isLogicalTopWithinBounds(lineTopInFlowThread - line.paginationStrut())); | 380 !isLogicalTopWithinBounds(lineTopInFlowThread - line.paginationStrut())); | 
| 383 if (isFirstAfterBreak(lineTopInFlowThread)) | 381 if (isFirstAfterBreak(lineTopInFlowThread)) | 
| 384 recordSpaceShortage(lineHeight - line.paginationStrut()); | 382 recordSpaceShortage(lineHeight - line.paginationStrut()); | 
| 385 | 383 | 
| 386 // Even if the line box itself fits fine inside a column, some content may ove rflow the line | 384 // Even if the line box itself fits fine inside a column, some content may | 
| 387 // box bottom (due to restrictive line-height, for instance). We should check if some portion | 385 // overflow the line box bottom (due to restrictive line-height, for | 
| 388 // of said overflow ends up in the next column. That counts as space shortage. | 386 // instance). We should check if some portion of said overflow ends up in the | 
| 387 // next column. That counts as space shortage. | |
| 389 const MultiColumnFragmentainerGroup& group = | 388 const MultiColumnFragmentainerGroup& group = | 
| 390 groupAtOffset(lineTopInFlowThread); | 389 groupAtOffset(lineTopInFlowThread); | 
| 391 LayoutUnit lineBottomWithOverflow = | 390 LayoutUnit lineBottomWithOverflow = | 
| 392 lineTopInFlowThread + line.lineBottom() - lineTop; | 391 lineTopInFlowThread + line.lineBottom() - lineTop; | 
| 393 if (group.columnLogicalTopForOffset(lineTopInFlowThread) != | 392 if (group.columnLogicalTopForOffset(lineTopInFlowThread) != | 
| 394 group.columnLogicalTopForOffset(lineBottomWithOverflow)) { | 393 group.columnLogicalTopForOffset(lineBottomWithOverflow)) { | 
| 395 LayoutUnit shortage = | 394 LayoutUnit shortage = | 
| 396 lineBottomWithOverflow - | 395 lineBottomWithOverflow - | 
| 397 group.columnLogicalTopForOffset(lineBottomWithOverflow); | 396 group.columnLogicalTopForOffset(lineBottomWithOverflow); | 
| 398 recordSpaceShortage(shortage); | 397 recordSpaceShortage(shortage); | 
| 399 } | 398 } | 
| 400 } | 399 } | 
| 401 | 400 | 
| 402 } // namespace blink | 401 } // namespace blink | 
| OLD | NEW |