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

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

Issue 2403553002: reflow comments in core/layout/[M-Z]*.{cpp,h} (Closed)
Patch Set: Created 4 years, 2 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
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/MultiColumnFragmentainerGroup.h" 5 #include "core/layout/MultiColumnFragmentainerGroup.h"
6 6
7 #include "core/layout/ColumnBalancer.h" 7 #include "core/layout/ColumnBalancer.h"
8 #include "core/layout/FragmentationContext.h" 8 #include "core/layout/FragmentationContext.h"
9 #include "core/layout/LayoutMultiColumnSet.h" 9 #include "core/layout/LayoutMultiColumnSet.h"
10 10
(...skipping 28 matching lines...) Expand all
39 39
40 void MultiColumnFragmentainerGroup::resetColumnHeight() { 40 void MultiColumnFragmentainerGroup::resetColumnHeight() {
41 m_maxColumnHeight = calculateMaxColumnHeight(); 41 m_maxColumnHeight = calculateMaxColumnHeight();
42 42
43 LayoutMultiColumnFlowThread* flowThread = m_columnSet.multiColumnFlowThread(); 43 LayoutMultiColumnFlowThread* flowThread = m_columnSet.multiColumnFlowThread();
44 if (m_columnSet.heightIsAuto()) { 44 if (m_columnSet.heightIsAuto()) {
45 FragmentationContext* enclosingFragmentationContext = 45 FragmentationContext* enclosingFragmentationContext =
46 flowThread->enclosingFragmentationContext(); 46 flowThread->enclosingFragmentationContext();
47 if (enclosingFragmentationContext && 47 if (enclosingFragmentationContext &&
48 enclosingFragmentationContext->isFragmentainerLogicalHeightKnown()) { 48 enclosingFragmentationContext->isFragmentainerLogicalHeightKnown()) {
49 // Even if height is auto, we set an initial height, in order to tell how much content 49 // Even if height is auto, we set an initial height, in order to tell how
50 // this MultiColumnFragmentainerGroup can hold, and when we need to append a new one. 50 // much content this MultiColumnFragmentainerGroup can hold, and when we
51 // need to append a new one.
51 m_columnHeight = m_maxColumnHeight; 52 m_columnHeight = m_maxColumnHeight;
52 } else { 53 } else {
53 m_columnHeight = LayoutUnit(); 54 m_columnHeight = LayoutUnit();
54 } 55 }
55 } else { 56 } else {
56 setAndConstrainColumnHeight( 57 setAndConstrainColumnHeight(
57 heightAdjustedForRowOffset(flowThread->columnHeightAvailable())); 58 heightAdjustedForRowOffset(flowThread->columnHeightAvailable()));
58 } 59 }
59 } 60 }
60 61
61 bool MultiColumnFragmentainerGroup::recalculateColumnHeight( 62 bool MultiColumnFragmentainerGroup::recalculateColumnHeight(
62 LayoutMultiColumnSet& columnSet) { 63 LayoutMultiColumnSet& columnSet) {
63 LayoutUnit oldColumnHeight = m_columnHeight; 64 LayoutUnit oldColumnHeight = m_columnHeight;
64 65
65 m_maxColumnHeight = calculateMaxColumnHeight(); 66 m_maxColumnHeight = calculateMaxColumnHeight();
66 67
67 // Only the last row may have auto height, and thus be balanced. There are no good reasons to 68 // Only the last row may have auto height, and thus be balanced. There are no
68 // balance the preceding rows, and that could potentially lead to an insane nu mber of layout 69 // good reasons to balance the preceding rows, and that could potentially lead
69 // passes as well. 70 // to an insane number of layout passes as well.
70 if (isLastGroup() && columnSet.heightIsAuto()) { 71 if (isLastGroup() && columnSet.heightIsAuto()) {
71 LayoutUnit newColumnHeight; 72 LayoutUnit newColumnHeight;
72 if (!columnSet.isInitialHeightCalculated()) { 73 if (!columnSet.isInitialHeightCalculated()) {
73 // Initial balancing: Start with the lowest imaginable column height. Also calculate the 74 // Initial balancing: Start with the lowest imaginable column height. Also
74 // height of the tallest piece of unbreakable content. Columns should neve r get any 75 // calculate the height of the tallest piece of unbreakable content.
75 // shorter than that (unless constrained by max-height). Propagate this to our 76 // Columns should never get any shorter than that (unless constrained by
76 // containing column set, in case there is an outer multicol container tha t also needs 77 // max-height). Propagate this to our containing column set, in case there
77 // to balance. After having calculated the initial column height, the mult icol container 78 // is an outer multicol container that also needs to balance. After having
78 // needs another layout pass with the column height that we just calculate d. 79 // calculated the initial column height, the multicol container needs
80 // another layout pass with the column height that we just calculated.
79 InitialColumnHeightFinder initialHeightFinder( 81 InitialColumnHeightFinder initialHeightFinder(
80 columnSet, logicalTopInFlowThread(), logicalBottomInFlowThread()); 82 columnSet, logicalTopInFlowThread(), logicalBottomInFlowThread());
81 LayoutUnit tallestUnbreakableLogicalHeight = 83 LayoutUnit tallestUnbreakableLogicalHeight =
82 initialHeightFinder.tallestUnbreakableLogicalHeight(); 84 initialHeightFinder.tallestUnbreakableLogicalHeight();
83 columnSet.propagateTallestUnbreakableLogicalHeight( 85 columnSet.propagateTallestUnbreakableLogicalHeight(
84 tallestUnbreakableLogicalHeight); 86 tallestUnbreakableLogicalHeight);
85 newColumnHeight = 87 newColumnHeight =
86 std::max(initialHeightFinder.initialMinimalBalancedHeight(), 88 std::max(initialHeightFinder.initialMinimalBalancedHeight(),
87 tallestUnbreakableLogicalHeight); 89 tallestUnbreakableLogicalHeight);
88 } else { 90 } else {
89 // Rebalancing: After having laid out again, we'll need to rebalance if th e height 91 // Rebalancing: After having laid out again, we'll need to rebalance if
90 // wasn't enough and we're allowed to stretch it, and then re-lay out. The re are further 92 // the height wasn't enough and we're allowed to stretch it, and then
91 // details on the column balancing machinery in ColumnBalancer and its der ivates. 93 // re-lay out. There are further details on the column balancing
94 // machinery in ColumnBalancer and its derivates.
92 newColumnHeight = rebalanceColumnHeightIfNeeded(); 95 newColumnHeight = rebalanceColumnHeightIfNeeded();
93 } 96 }
94 setAndConstrainColumnHeight(newColumnHeight); 97 setAndConstrainColumnHeight(newColumnHeight);
95 } else { 98 } else {
96 // The position of the column set may have changed, in which case height ava ilable for 99 // The position of the column set may have changed, in which case height
97 // columns may have changed as well. 100 // available for columns may have changed as well.
98 setAndConstrainColumnHeight(m_columnHeight); 101 setAndConstrainColumnHeight(m_columnHeight);
99 } 102 }
100 103
101 if (m_columnHeight == oldColumnHeight) 104 if (m_columnHeight == oldColumnHeight)
102 return false; // No change. We're done. 105 return false; // No change. We're done.
103 106
104 return true; // Need another pass. 107 return true; // Need another pass.
105 } 108 }
106 109
107 LayoutSize MultiColumnFragmentainerGroup::flowThreadTranslationAtOffset( 110 LayoutSize MultiColumnFragmentainerGroup::flowThreadTranslationAtOffset(
108 LayoutUnit offsetInFlowThread, 111 LayoutUnit offsetInFlowThread,
109 LayoutBox::PageBoundaryRule rule, 112 LayoutBox::PageBoundaryRule rule,
110 CoordinateSpaceConversion mode) const { 113 CoordinateSpaceConversion mode) const {
111 LayoutMultiColumnFlowThread* flowThread = m_columnSet.multiColumnFlowThread(); 114 LayoutMultiColumnFlowThread* flowThread = m_columnSet.multiColumnFlowThread();
112 115
113 // A column out of range doesn't have a flow thread portion, so we need to cla mp to make sure 116 // A column out of range doesn't have a flow thread portion, so we need to
114 // that we stay within the actual columns. This means that content in the over flow area will be 117 // clamp to make sure that we stay within the actual columns. This means that
115 // mapped to the last actual column, instead of being mapped to an imaginary c olumn further 118 // content in the overflow area will be mapped to the last actual column,
116 // ahead. 119 // instead of being mapped to an imaginary column further ahead.
117 unsigned columnIndex = offsetInFlowThread >= logicalBottomInFlowThread() 120 unsigned columnIndex = offsetInFlowThread >= logicalBottomInFlowThread()
118 ? actualColumnCount() - 1 121 ? actualColumnCount() - 1
119 : columnIndexAtOffset(offsetInFlowThread, rule); 122 : columnIndexAtOffset(offsetInFlowThread, rule);
120 123
121 LayoutRect portionRect(flowThreadPortionRectAt(columnIndex)); 124 LayoutRect portionRect(flowThreadPortionRectAt(columnIndex));
122 flowThread->flipForWritingMode(portionRect); 125 flowThread->flipForWritingMode(portionRect);
123 portionRect.moveBy(flowThread->topLeftLocation()); 126 portionRect.moveBy(flowThread->topLeftLocation());
124 127
125 LayoutRect columnRect(columnRectAt(columnIndex)); 128 LayoutRect columnRect(columnRectAt(columnIndex));
126 columnRect.move(offsetFromColumnSet()); 129 columnRect.move(offsetFromColumnSet());
127 m_columnSet.flipForWritingMode(columnRect); 130 m_columnSet.flipForWritingMode(columnRect);
128 columnRect.moveBy(m_columnSet.topLeftLocation()); 131 columnRect.moveBy(m_columnSet.topLeftLocation());
129 132
130 LayoutSize translationRelativeToFlowThread = 133 LayoutSize translationRelativeToFlowThread =
131 columnRect.location() - portionRect.location(); 134 columnRect.location() - portionRect.location();
132 if (mode == CoordinateSpaceConversion::Containing) 135 if (mode == CoordinateSpaceConversion::Containing)
133 return translationRelativeToFlowThread; 136 return translationRelativeToFlowThread;
134 137
135 LayoutSize enclosingTranslation; 138 LayoutSize enclosingTranslation;
136 if (LayoutMultiColumnFlowThread* enclosingFlowThread = 139 if (LayoutMultiColumnFlowThread* enclosingFlowThread =
137 flowThread->enclosingFlowThread()) { 140 flowThread->enclosingFlowThread()) {
138 const MultiColumnFragmentainerGroup& firstRow = 141 const MultiColumnFragmentainerGroup& firstRow =
139 flowThread->firstMultiColumnSet()->firstFragmentainerGroup(); 142 flowThread->firstMultiColumnSet()->firstFragmentainerGroup();
140 // Translation that would map points in the coordinate space of the outermos t flow thread to 143 // Translation that would map points in the coordinate space of the
141 // visual points in the first column in the first fragmentainer group (row) in our multicol 144 // outermost flow thread to visual points in the first column in the first
142 // container. 145 // fragmentainer group (row) in our multicol container.
143 LayoutSize enclosingTranslationOrigin = 146 LayoutSize enclosingTranslationOrigin =
144 enclosingFlowThread->flowThreadTranslationAtOffset( 147 enclosingFlowThread->flowThreadTranslationAtOffset(
145 firstRow.blockOffsetInEnclosingFragmentationContext(), 148 firstRow.blockOffsetInEnclosingFragmentationContext(),
146 LayoutBox::AssociateWithLatterPage, mode); 149 LayoutBox::AssociateWithLatterPage, mode);
147 150
148 // Translation that would map points in the coordinate space of the outermos t flow thread to 151 // Translation that would map points in the coordinate space of the
149 // visual points in the first column in this fragmentainer group. 152 // outermost flow thread to visual points in the first column in this
153 // fragmentainer group.
150 enclosingTranslation = enclosingFlowThread->flowThreadTranslationAtOffset( 154 enclosingTranslation = enclosingFlowThread->flowThreadTranslationAtOffset(
151 blockOffsetInEnclosingFragmentationContext(), 155 blockOffsetInEnclosingFragmentationContext(),
152 LayoutBox::AssociateWithLatterPage, mode); 156 LayoutBox::AssociateWithLatterPage, mode);
153 157
154 // What we ultimately return from this method is a translation that maps poi nts in the 158 // What we ultimately return from this method is a translation that maps
155 // coordinate space of our flow thread to a visual point in a certain column in this 159 // points in the coordinate space of our flow thread to a visual point in a
156 // fragmentainer group. We had to go all the way up to the outermost flow th read, since this 160 // certain column in this fragmentainer group. We had to go all the way up
157 // fragmentainer group may be in a different outer column than the first out er column that 161 // to the outermost flow thread, since this fragmentainer group may be in a
158 // this multicol container lives in. It's the visual distance between the fi rst 162 // different outer column than the first outer column that this multicol
159 // fragmentainer group and this fragmentainer group that we need to add to t he translation. 163 // container lives in. It's the visual distance between the first
164 // fragmentainer group and this fragmentainer group that we need to add to
165 // the translation.
160 enclosingTranslation -= enclosingTranslationOrigin; 166 enclosingTranslation -= enclosingTranslationOrigin;
161 } 167 }
162 168
163 return enclosingTranslation + translationRelativeToFlowThread; 169 return enclosingTranslation + translationRelativeToFlowThread;
164 } 170 }
165 171
166 LayoutUnit MultiColumnFragmentainerGroup::columnLogicalTopForOffset( 172 LayoutUnit MultiColumnFragmentainerGroup::columnLogicalTopForOffset(
167 LayoutUnit offsetInFlowThread) const { 173 LayoutUnit offsetInFlowThread) const {
168 unsigned columnIndex = columnIndexAtOffset( 174 unsigned columnIndex = columnIndexAtOffset(
169 offsetInFlowThread, LayoutBox::AssociateWithLatterPage); 175 offsetInFlowThread, LayoutBox::AssociateWithLatterPage);
170 return logicalTopInFlowThreadAt(columnIndex); 176 return logicalTopInFlowThreadAt(columnIndex);
171 } 177 }
172 178
173 LayoutPoint MultiColumnFragmentainerGroup::visualPointToFlowThreadPoint( 179 LayoutPoint MultiColumnFragmentainerGroup::visualPointToFlowThreadPoint(
174 const LayoutPoint& visualPoint) const { 180 const LayoutPoint& visualPoint) const {
175 unsigned columnIndex = columnIndexAtVisualPoint(visualPoint); 181 unsigned columnIndex = columnIndexAtVisualPoint(visualPoint);
176 LayoutRect columnRect = columnRectAt(columnIndex); 182 LayoutRect columnRect = columnRectAt(columnIndex);
177 LayoutPoint localPoint(visualPoint); 183 LayoutPoint localPoint(visualPoint);
178 localPoint.moveBy(-columnRect.location()); 184 localPoint.moveBy(-columnRect.location());
179 // Before converting to a flow thread position, if the block direction coordin ate is outside the 185 // Before converting to a flow thread position, if the block direction
180 // column, snap to the bounds of the column, and reset the inline direction co ordinate to the 186 // coordinate is outside the column, snap to the bounds of the column, and
181 // start position in the column. The effect of this is that if the block posit ion is before the 187 // reset the inline direction coordinate to the start position in the column.
182 // column rectangle, we'll get to the beginning of this column, while if the b lock position is 188 // The effect of this is that if the block position is before the column
183 // after the column rectangle, we'll get to the beginning of the next column. 189 // rectangle, we'll get to the beginning of this column, while if the block
190 // position is after the column rectangle, we'll get to the beginning of the
191 // next column.
184 if (!m_columnSet.isHorizontalWritingMode()) { 192 if (!m_columnSet.isHorizontalWritingMode()) {
185 LayoutUnit columnStart = m_columnSet.style()->isLeftToRightDirection() 193 LayoutUnit columnStart = m_columnSet.style()->isLeftToRightDirection()
186 ? LayoutUnit() 194 ? LayoutUnit()
187 : columnRect.height(); 195 : columnRect.height();
188 if (localPoint.x() < 0) 196 if (localPoint.x() < 0)
189 localPoint = LayoutPoint(LayoutUnit(), columnStart); 197 localPoint = LayoutPoint(LayoutUnit(), columnStart);
190 else if (localPoint.x() > logicalHeight()) 198 else if (localPoint.x() > logicalHeight())
191 localPoint = LayoutPoint(logicalHeight(), columnStart); 199 localPoint = LayoutPoint(logicalHeight(), columnStart);
192 return LayoutPoint(localPoint.x() + logicalTopInFlowThreadAt(columnIndex), 200 return LayoutPoint(localPoint.x() + logicalTopInFlowThreadAt(columnIndex),
193 localPoint.y()); 201 localPoint.y());
(...skipping 16 matching lines...) Expand all
210 LayoutFlowThread* flowThread = m_columnSet.flowThread(); 218 LayoutFlowThread* flowThread = m_columnSet.flowThread();
211 flowThread->flipForWritingMode(flippedBoundingBoxInFlowThread); 219 flowThread->flipForWritingMode(flippedBoundingBoxInFlowThread);
212 bool isHorizontalWritingMode = m_columnSet.isHorizontalWritingMode(); 220 bool isHorizontalWritingMode = m_columnSet.isHorizontalWritingMode();
213 LayoutUnit boundingBoxLogicalTop = isHorizontalWritingMode 221 LayoutUnit boundingBoxLogicalTop = isHorizontalWritingMode
214 ? flippedBoundingBoxInFlowThread.y() 222 ? flippedBoundingBoxInFlowThread.y()
215 : flippedBoundingBoxInFlowThread.x(); 223 : flippedBoundingBoxInFlowThread.x();
216 LayoutUnit boundingBoxLogicalBottom = 224 LayoutUnit boundingBoxLogicalBottom =
217 isHorizontalWritingMode ? flippedBoundingBoxInFlowThread.maxY() 225 isHorizontalWritingMode ? flippedBoundingBoxInFlowThread.maxY()
218 : flippedBoundingBoxInFlowThread.maxX(); 226 : flippedBoundingBoxInFlowThread.maxX();
219 if (boundingBoxLogicalBottom <= logicalTopInFlowThread() || 227 if (boundingBoxLogicalBottom <= logicalTopInFlowThread() ||
220 boundingBoxLogicalTop >= logicalBottomInFlowThread()) 228 boundingBoxLogicalTop >= logicalBottomInFlowThread()) {
221 return LayoutRect(); // The bounding box doesn't intersect this fragmentain er group. 229 // The bounding box doesn't intersect this fragmentainer group.
230 return LayoutRect();
231 }
222 unsigned startColumn; 232 unsigned startColumn;
223 unsigned endColumn; 233 unsigned endColumn;
224 columnIntervalForBlockRangeInFlowThread( 234 columnIntervalForBlockRangeInFlowThread(
225 boundingBoxLogicalTop, boundingBoxLogicalBottom, startColumn, endColumn); 235 boundingBoxLogicalTop, boundingBoxLogicalBottom, startColumn, endColumn);
226 236
227 LayoutRect startColumnFlowThreadOverflowPortion = 237 LayoutRect startColumnFlowThreadOverflowPortion =
228 flowThreadPortionOverflowRectAt(startColumn); 238 flowThreadPortionOverflowRectAt(startColumn);
229 flowThread->flipForWritingMode(startColumnFlowThreadOverflowPortion); 239 flowThread->flipForWritingMode(startColumnFlowThreadOverflowPortion);
230 LayoutRect startColumnRect(boundingBoxInFlowThread); 240 LayoutRect startColumnRect(boundingBoxInFlowThread);
231 startColumnRect.intersect(startColumnFlowThreadOverflowPortion); 241 startColumnRect.intersect(startColumnFlowThreadOverflowPortion);
232 startColumnRect.move(flowThreadTranslationAtOffset( 242 startColumnRect.move(flowThreadTranslationAtOffset(
233 logicalTopInFlowThreadAt(startColumn), LayoutBox::AssociateWithLatterPage, 243 logicalTopInFlowThreadAt(startColumn), LayoutBox::AssociateWithLatterPage,
234 CoordinateSpaceConversion::Containing)); 244 CoordinateSpaceConversion::Containing));
235 if (startColumn == endColumn) 245 if (startColumn == endColumn)
236 return startColumnRect; // It all takes place in one column. We're done. 246 return startColumnRect; // It all takes place in one column. We're done.
237 247
238 LayoutRect endColumnFlowThreadOverflowPortion = 248 LayoutRect endColumnFlowThreadOverflowPortion =
239 flowThreadPortionOverflowRectAt(endColumn); 249 flowThreadPortionOverflowRectAt(endColumn);
240 flowThread->flipForWritingMode(endColumnFlowThreadOverflowPortion); 250 flowThread->flipForWritingMode(endColumnFlowThreadOverflowPortion);
241 LayoutRect endColumnRect(boundingBoxInFlowThread); 251 LayoutRect endColumnRect(boundingBoxInFlowThread);
242 endColumnRect.intersect(endColumnFlowThreadOverflowPortion); 252 endColumnRect.intersect(endColumnFlowThreadOverflowPortion);
243 endColumnRect.move(flowThreadTranslationAtOffset( 253 endColumnRect.move(flowThreadTranslationAtOffset(
244 logicalTopInFlowThreadAt(endColumn), LayoutBox::AssociateWithLatterPage, 254 logicalTopInFlowThreadAt(endColumn), LayoutBox::AssociateWithLatterPage,
245 CoordinateSpaceConversion::Containing)); 255 CoordinateSpaceConversion::Containing));
246 return unionRect(startColumnRect, endColumnRect); 256 return unionRect(startColumnRect, endColumnRect);
247 } 257 }
248 258
249 LayoutRect MultiColumnFragmentainerGroup::calculateOverflow() const { 259 LayoutRect MultiColumnFragmentainerGroup::calculateOverflow() const {
250 // Note that we just return the bounding rectangle of the column boxes here. W e currently don't 260 // Note that we just return the bounding rectangle of the column boxes here.
251 // examine overflow caused by the actual content that ends up in each column. 261 // We currently don't examine overflow caused by the actual content that ends
262 // up in each column.
252 LayoutRect overflowRect; 263 LayoutRect overflowRect;
253 if (unsigned columnCount = actualColumnCount()) { 264 if (unsigned columnCount = actualColumnCount()) {
254 overflowRect = columnRectAt(0); 265 overflowRect = columnRectAt(0);
255 if (columnCount > 1) 266 if (columnCount > 1)
256 overflowRect.uniteEvenIfEmpty(columnRectAt(columnCount - 1)); 267 overflowRect.uniteEvenIfEmpty(columnRectAt(columnCount - 1));
257 } 268 }
258 return overflowRect; 269 return overflowRect;
259 } 270 }
260 271
261 unsigned MultiColumnFragmentainerGroup::actualColumnCount() const { 272 unsigned MultiColumnFragmentainerGroup::actualColumnCount() const {
262 // We must always return a value of 1 or greater. Column count = 0 is a meanin gless situation, 273 // We must always return a value of 1 or greater. Column count = 0 is a
263 // and will confuse and cause problems in other parts of the code. 274 // meaningless situation, and will confuse and cause problems in other parts
275 // of the code.
264 if (!m_columnHeight) 276 if (!m_columnHeight)
265 return 1; 277 return 1;
266 278
267 // Our flow thread portion determines our column count. We have as many column s as needed to fit 279 // Our flow thread portion determines our column count. We have as many
268 // all the content. 280 // columns as needed to fit all the content.
269 LayoutUnit flowThreadPortionHeight = logicalHeightInFlowThread(); 281 LayoutUnit flowThreadPortionHeight = logicalHeightInFlowThread();
270 if (!flowThreadPortionHeight) 282 if (!flowThreadPortionHeight)
271 return 1; 283 return 1;
272 284
273 unsigned count = (flowThreadPortionHeight / m_columnHeight).floor(); 285 unsigned count = (flowThreadPortionHeight / m_columnHeight).floor();
274 // flowThreadPortionHeight may be saturated, so detect the remainder manually. 286 // flowThreadPortionHeight may be saturated, so detect the remainder manually.
275 if (count * m_columnHeight < flowThreadPortionHeight) 287 if (count * m_columnHeight < flowThreadPortionHeight)
276 count++; 288 count++;
277 ASSERT(count >= 1); 289 ASSERT(count >= 1);
278 return count; 290 return count;
279 } 291 }
280 292
281 LayoutUnit MultiColumnFragmentainerGroup::heightAdjustedForRowOffset( 293 LayoutUnit MultiColumnFragmentainerGroup::heightAdjustedForRowOffset(
282 LayoutUnit height) const { 294 LayoutUnit height) const {
283 // Let's avoid zero height, as that would cause an infinite amount of columns to be created. 295 // Let's avoid zero height, as that would cause an infinite amount of columns
296 // to be created.
284 return std::max( 297 return std::max(
285 height - logicalTop() - m_columnSet.logicalTopFromMulticolContentEdge(), 298 height - logicalTop() - m_columnSet.logicalTopFromMulticolContentEdge(),
286 LayoutUnit(1)); 299 LayoutUnit(1));
287 } 300 }
288 301
289 LayoutUnit MultiColumnFragmentainerGroup::calculateMaxColumnHeight() const { 302 LayoutUnit MultiColumnFragmentainerGroup::calculateMaxColumnHeight() const {
290 LayoutMultiColumnFlowThread* flowThread = m_columnSet.multiColumnFlowThread(); 303 LayoutMultiColumnFlowThread* flowThread = m_columnSet.multiColumnFlowThread();
291 LayoutUnit maxColumnHeight = flowThread->maxColumnLogicalHeight(); 304 LayoutUnit maxColumnHeight = flowThread->maxColumnLogicalHeight();
292 LayoutUnit maxHeight = heightAdjustedForRowOffset(maxColumnHeight); 305 LayoutUnit maxHeight = heightAdjustedForRowOffset(maxColumnHeight);
293 if (FragmentationContext* enclosingFragmentationContext = 306 if (FragmentationContext* enclosingFragmentationContext =
294 flowThread->enclosingFragmentationContext()) { 307 flowThread->enclosingFragmentationContext()) {
295 if (enclosingFragmentationContext->isFragmentainerLogicalHeightKnown()) { 308 if (enclosingFragmentationContext->isFragmentainerLogicalHeightKnown()) {
296 // We're nested inside another fragmentation context whose fragmentainer h eights are 309 // We're nested inside another fragmentation context whose fragmentainer
297 // known. This constrains the max height. 310 // heights are known. This constrains the max height.
298 LayoutUnit remainingOuterLogicalHeight = 311 LayoutUnit remainingOuterLogicalHeight =
299 enclosingFragmentationContext->remainingLogicalHeightAt( 312 enclosingFragmentationContext->remainingLogicalHeightAt(
300 blockOffsetInEnclosingFragmentationContext()); 313 blockOffsetInEnclosingFragmentationContext());
301 ASSERT(remainingOuterLogicalHeight > 0); 314 ASSERT(remainingOuterLogicalHeight > 0);
302 if (maxHeight > remainingOuterLogicalHeight) 315 if (maxHeight > remainingOuterLogicalHeight)
303 maxHeight = remainingOuterLogicalHeight; 316 maxHeight = remainingOuterLogicalHeight;
304 } 317 }
305 } 318 }
306 return maxHeight; 319 return maxHeight;
307 } 320 }
308 321
309 void MultiColumnFragmentainerGroup::setAndConstrainColumnHeight( 322 void MultiColumnFragmentainerGroup::setAndConstrainColumnHeight(
310 LayoutUnit newHeight) { 323 LayoutUnit newHeight) {
311 m_columnHeight = newHeight; 324 m_columnHeight = newHeight;
312 if (m_columnHeight > m_maxColumnHeight) 325 if (m_columnHeight > m_maxColumnHeight)
313 m_columnHeight = m_maxColumnHeight; 326 m_columnHeight = m_maxColumnHeight;
314 } 327 }
315 328
316 LayoutUnit MultiColumnFragmentainerGroup::rebalanceColumnHeightIfNeeded() 329 LayoutUnit MultiColumnFragmentainerGroup::rebalanceColumnHeightIfNeeded()
317 const { 330 const {
318 if (actualColumnCount() <= m_columnSet.usedColumnCount()) { 331 if (actualColumnCount() <= m_columnSet.usedColumnCount()) {
319 // With the current column height, the content fits without creating overflo wing columns. We're done. 332 // With the current column height, the content fits without creating
333 // overflowing columns. We're done.
320 return m_columnHeight; 334 return m_columnHeight;
321 } 335 }
322 336
323 if (m_columnHeight >= m_maxColumnHeight) { 337 if (m_columnHeight >= m_maxColumnHeight) {
324 // We cannot stretch any further. We'll just have to live with the overflowi ng columns. This 338 // We cannot stretch any further. We'll just have to live with the
325 // typically happens if the max column height is less than the height of the tallest piece 339 // overflowing columns. This typically happens if the max column height is
326 // of unbreakable content (e.g. lines). 340 // less than the height of the tallest piece of unbreakable content (e.g.
341 // lines).
327 return m_columnHeight; 342 return m_columnHeight;
328 } 343 }
329 344
330 MinimumSpaceShortageFinder shortageFinder( 345 MinimumSpaceShortageFinder shortageFinder(
331 columnSet(), logicalTopInFlowThread(), logicalBottomInFlowThread()); 346 columnSet(), logicalTopInFlowThread(), logicalBottomInFlowThread());
332 347
333 if (shortageFinder.forcedBreaksCount() + 1 >= m_columnSet.usedColumnCount()) { 348 if (shortageFinder.forcedBreaksCount() + 1 >= m_columnSet.usedColumnCount()) {
334 // Too many forced breaks to allow any implicit breaks. Initial balancing sh ould already 349 // Too many forced breaks to allow any implicit breaks. Initial balancing
335 // have set a good height. There's nothing more we should do. 350 // should already have set a good height. There's nothing more we should do.
336 return m_columnHeight; 351 return m_columnHeight;
337 } 352 }
338 353
339 // If the initial guessed column height wasn't enough, stretch it now. Stretch by the lowest 354 // If the initial guessed column height wasn't enough, stretch it now. Stretch
340 // amount of space. 355 // by the lowest amount of space.
341 LayoutUnit minSpaceShortage = shortageFinder.minimumSpaceShortage(); 356 LayoutUnit minSpaceShortage = shortageFinder.minimumSpaceShortage();
342 357
343 ASSERT(minSpaceShortage > 0); // We should never _shrink_ the height! 358 ASSERT(minSpaceShortage > 0); // We should never _shrink_ the height!
344 ASSERT(minSpaceShortage != 359 ASSERT(minSpaceShortage !=
345 LayoutUnit::max()); // If this happens, we probably have a bug. 360 LayoutUnit::max()); // If this happens, we probably have a bug.
346 if (minSpaceShortage == LayoutUnit::max()) 361 if (minSpaceShortage == LayoutUnit::max())
347 return m_columnHeight; // So bail out rather than looping infinitely. 362 return m_columnHeight; // So bail out rather than looping infinitely.
348 363
349 return m_columnHeight + minSpaceShortage; 364 return m_columnHeight + minSpaceShortage;
350 } 365 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 LayoutUnit portionLogicalHeight = logicalBottom - logicalTop; 412 LayoutUnit portionLogicalHeight = logicalBottom - logicalTop;
398 if (m_columnSet.isHorizontalWritingMode()) 413 if (m_columnSet.isHorizontalWritingMode())
399 return LayoutRect(LayoutUnit(), logicalTop, m_columnSet.pageLogicalWidth(), 414 return LayoutRect(LayoutUnit(), logicalTop, m_columnSet.pageLogicalWidth(),
400 portionLogicalHeight); 415 portionLogicalHeight);
401 return LayoutRect(logicalTop, LayoutUnit(), portionLogicalHeight, 416 return LayoutRect(logicalTop, LayoutUnit(), portionLogicalHeight,
402 m_columnSet.pageLogicalWidth()); 417 m_columnSet.pageLogicalWidth());
403 } 418 }
404 419
405 LayoutRect MultiColumnFragmentainerGroup::flowThreadPortionOverflowRectAt( 420 LayoutRect MultiColumnFragmentainerGroup::flowThreadPortionOverflowRectAt(
406 unsigned columnIndex) const { 421 unsigned columnIndex) const {
407 // This function determines the portion of the flow thread that paints for the column. Along the inline axis, columns are 422 // This function determines the portion of the flow thread that paints for the
408 // unclipped at outside edges (i.e., the first and last column in the set), an d they clip to half the column 423 // column. Along the inline axis, columns are unclipped at outside edges
409 // gap along interior edges. 424 // (i.e., the first and last column in the set), and they clip to half the
425 // column gap along interior edges.
410 // 426 //
411 // In the block direction, we will not clip overflow out of the top of the fir st column, or out of the bottom of 427 // In the block direction, we will not clip overflow out of the top of the
412 // the last column. This applies only to the true first column and last column across all column sets. 428 // first column, or out of the bottom of the last column. This applies only to
429 // the true first column and last column across all column sets.
413 // 430 //
414 // FIXME: Eventually we will know overflow on a per-column basis, but we can't do this until we have a painting 431 // FIXME: Eventually we will know overflow on a per-column basis, but we can't
415 // mode that understands not to paint contents from a previous column in the o verflow area of a following column. 432 // do this until we have a painting mode that understands not to paint
433 // contents from a previous column in the overflow area of a following column.
416 bool isFirstColumnInRow = !columnIndex; 434 bool isFirstColumnInRow = !columnIndex;
417 bool isLastColumnInRow = columnIndex == actualColumnCount() - 1; 435 bool isLastColumnInRow = columnIndex == actualColumnCount() - 1;
418 bool isLTR = m_columnSet.style()->isLeftToRightDirection(); 436 bool isLTR = m_columnSet.style()->isLeftToRightDirection();
419 bool isLeftmostColumn = isLTR ? isFirstColumnInRow : isLastColumnInRow; 437 bool isLeftmostColumn = isLTR ? isFirstColumnInRow : isLastColumnInRow;
420 bool isRightmostColumn = isLTR ? isLastColumnInRow : isFirstColumnInRow; 438 bool isRightmostColumn = isLTR ? isLastColumnInRow : isFirstColumnInRow;
421 439
422 LayoutRect portionRect = flowThreadPortionRectAt(columnIndex); 440 LayoutRect portionRect = flowThreadPortionRectAt(columnIndex);
423 bool isFirstColumnInMulticolContainer = 441 bool isFirstColumnInMulticolContainer =
424 isFirstColumnInRow && this == &m_columnSet.firstFragmentainerGroup() && 442 isFirstColumnInRow && this == &m_columnSet.firstFragmentainerGroup() &&
425 !m_columnSet.previousSiblingMultiColumnSet(); 443 !m_columnSet.previousSiblingMultiColumnSet();
426 bool isLastColumnInMulticolContainer = 444 bool isLastColumnInMulticolContainer =
427 isLastColumnInRow && this == &m_columnSet.lastFragmentainerGroup() && 445 isLastColumnInRow && this == &m_columnSet.lastFragmentainerGroup() &&
428 !m_columnSet.nextSiblingMultiColumnSet(); 446 !m_columnSet.nextSiblingMultiColumnSet();
429 // Calculate the overflow rectangle, based on the flow thread's, clipped at co lumn logical 447 // Calculate the overflow rectangle, based on the flow thread's, clipped at
430 // top/bottom unless it's the first/last column. 448 // column logical top/bottom unless it's the first/last column.
431 LayoutRect overflowRect = m_columnSet.overflowRectForFlowThreadPortion( 449 LayoutRect overflowRect = m_columnSet.overflowRectForFlowThreadPortion(
432 portionRect, isFirstColumnInMulticolContainer, 450 portionRect, isFirstColumnInMulticolContainer,
433 isLastColumnInMulticolContainer); 451 isLastColumnInMulticolContainer);
434 452
435 // Avoid overflowing into neighboring columns, by clipping in the middle of ad jacent column 453 // Avoid overflowing into neighboring columns, by clipping in the middle of
436 // gaps. Also make sure that we avoid rounding errors. 454 // adjacent column gaps. Also make sure that we avoid rounding errors.
437 LayoutUnit columnGap = m_columnSet.columnGap(); 455 LayoutUnit columnGap = m_columnSet.columnGap();
438 if (m_columnSet.isHorizontalWritingMode()) { 456 if (m_columnSet.isHorizontalWritingMode()) {
439 if (!isLeftmostColumn) 457 if (!isLeftmostColumn)
440 overflowRect.shiftXEdgeTo(portionRect.x() - columnGap / 2); 458 overflowRect.shiftXEdgeTo(portionRect.x() - columnGap / 2);
441 if (!isRightmostColumn) 459 if (!isRightmostColumn)
442 overflowRect.shiftMaxXEdgeTo(portionRect.maxX() + columnGap - 460 overflowRect.shiftMaxXEdgeTo(portionRect.maxX() + columnGap -
443 columnGap / 2); 461 columnGap / 2);
444 } else { 462 } else {
445 if (!isLeftmostColumn) 463 if (!isLeftmostColumn)
446 overflowRect.shiftYEdgeTo(portionRect.y() - columnGap / 2); 464 overflowRect.shiftYEdgeTo(portionRect.y() - columnGap / 2);
(...skipping 12 matching lines...) Expand all
459 return 0; 477 return 0;
460 478
461 if (!m_columnHeight) 479 if (!m_columnHeight)
462 return 0; 480 return 0;
463 unsigned columnIndex = 481 unsigned columnIndex =
464 ((offsetInFlowThread - m_logicalTopInFlowThread) / m_columnHeight) 482 ((offsetInFlowThread - m_logicalTopInFlowThread) / m_columnHeight)
465 .floor(); 483 .floor();
466 if (pageBoundaryRule == LayoutBox::AssociateWithFormerPage && 484 if (pageBoundaryRule == LayoutBox::AssociateWithFormerPage &&
467 columnIndex > 0 && 485 columnIndex > 0 &&
468 logicalTopInFlowThreadAt(columnIndex) == offsetInFlowThread) { 486 logicalTopInFlowThreadAt(columnIndex) == offsetInFlowThread) {
469 // We are exactly at a column boundary, and we've been told to associate off sets at column 487 // We are exactly at a column boundary, and we've been told to associate
470 // boundaries with the former column, not the latter. 488 // offsets at column boundaries with the former column, not the latter.
471 columnIndex--; 489 columnIndex--;
472 } 490 }
473 return columnIndex; 491 return columnIndex;
474 } 492 }
475 493
476 unsigned MultiColumnFragmentainerGroup::columnIndexAtVisualPoint( 494 unsigned MultiColumnFragmentainerGroup::columnIndexAtVisualPoint(
477 const LayoutPoint& visualPoint) const { 495 const LayoutPoint& visualPoint) const {
478 bool isColumnProgressionInline = 496 bool isColumnProgressionInline =
479 m_columnSet.multiColumnFlowThread()->progressionIsInline(); 497 m_columnSet.multiColumnFlowThread()->progressionIsInline();
480 bool isHorizontalWritingMode = m_columnSet.isHorizontalWritingMode(); 498 bool isHorizontalWritingMode = m_columnSet.isHorizontalWritingMode();
(...skipping 25 matching lines...) Expand all
506 unsigned& firstColumn, 524 unsigned& firstColumn,
507 unsigned& lastColumn) const { 525 unsigned& lastColumn) const {
508 logicalTopInFlowThread = 526 logicalTopInFlowThread =
509 std::max(logicalTopInFlowThread, this->logicalTopInFlowThread()); 527 std::max(logicalTopInFlowThread, this->logicalTopInFlowThread());
510 logicalBottomInFlowThread = 528 logicalBottomInFlowThread =
511 std::min(logicalBottomInFlowThread, this->logicalBottomInFlowThread()); 529 std::min(logicalBottomInFlowThread, this->logicalBottomInFlowThread());
512 ASSERT(logicalTopInFlowThread <= logicalBottomInFlowThread); 530 ASSERT(logicalTopInFlowThread <= logicalBottomInFlowThread);
513 firstColumn = columnIndexAtOffset(logicalTopInFlowThread, 531 firstColumn = columnIndexAtOffset(logicalTopInFlowThread,
514 LayoutBox::AssociateWithLatterPage); 532 LayoutBox::AssociateWithLatterPage);
515 if (logicalBottomInFlowThread == logicalTopInFlowThread) { 533 if (logicalBottomInFlowThread == logicalTopInFlowThread) {
516 // Zero-height block range. There'll be one column in the interval. Set it r ight away. This 534 // Zero-height block range. There'll be one column in the interval. Set it
517 // is important if we're at a column boundary, since calling columnIndexAtOf fset() with the 535 // right away. This is important if we're at a column boundary, since
518 // end-exclusive bottom offset would actually give us the *previous* column. 536 // calling columnIndexAtOffset() with the end-exclusive bottom offset would
537 // actually give us the *previous* column.
519 lastColumn = firstColumn; 538 lastColumn = firstColumn;
520 } else { 539 } else {
521 lastColumn = columnIndexAtOffset(logicalBottomInFlowThread, 540 lastColumn = columnIndexAtOffset(logicalBottomInFlowThread,
522 LayoutBox::AssociateWithFormerPage); 541 LayoutBox::AssociateWithFormerPage);
523 } 542 }
524 } 543 }
525 544
526 void MultiColumnFragmentainerGroup::columnIntervalForVisualRect( 545 void MultiColumnFragmentainerGroup::columnIntervalForVisualRect(
527 const LayoutRect& rect, 546 const LayoutRect& rect,
528 unsigned& firstColumn, 547 unsigned& firstColumn,
(...skipping 22 matching lines...) Expand all
551 } 570 }
552 ASSERT(firstColumn <= lastColumn); 571 ASSERT(firstColumn <= lastColumn);
553 } 572 }
554 573
555 MultiColumnFragmentainerGroupList::MultiColumnFragmentainerGroupList( 574 MultiColumnFragmentainerGroupList::MultiColumnFragmentainerGroupList(
556 LayoutMultiColumnSet& columnSet) 575 LayoutMultiColumnSet& columnSet)
557 : m_columnSet(columnSet) { 576 : m_columnSet(columnSet) {
558 append(MultiColumnFragmentainerGroup(m_columnSet)); 577 append(MultiColumnFragmentainerGroup(m_columnSet));
559 } 578 }
560 579
561 // An explicit empty destructor of MultiColumnFragmentainerGroupList should be i n 580 // An explicit empty destructor of MultiColumnFragmentainerGroupList should be
562 // MultiColumnFragmentainerGroup.cpp, because if an implicit destructor is used, 581 // in MultiColumnFragmentainerGroup.cpp, because if an implicit destructor is
563 // msvc 2015 tries to generate its destructor (because the class is dll-exported class) 582 // used, msvc 2015 tries to generate its destructor (because the class is
564 // and causes a compile error because of lack of MultiColumnFragmentainerGroup:: operator=. 583 // dll-exported class) and causes a compile error because of lack of
565 // Since MultiColumnFragmentainerGroup is non-copyable, we cannot define the ope rator=. 584 // MultiColumnFragmentainerGroup::operator=. Since
585 // MultiColumnFragmentainerGroup is non-copyable, we cannot define the
586 // operator=.
dcheng 2016/10/07 20:42:01 o.O
566 MultiColumnFragmentainerGroupList::~MultiColumnFragmentainerGroupList() {} 587 MultiColumnFragmentainerGroupList::~MultiColumnFragmentainerGroupList() {}
567 588
568 MultiColumnFragmentainerGroup& 589 MultiColumnFragmentainerGroup&
569 MultiColumnFragmentainerGroupList::addExtraGroup() { 590 MultiColumnFragmentainerGroupList::addExtraGroup() {
570 append(MultiColumnFragmentainerGroup(m_columnSet)); 591 append(MultiColumnFragmentainerGroup(m_columnSet));
571 return last(); 592 return last();
572 } 593 }
573 594
574 void MultiColumnFragmentainerGroupList::deleteExtraGroups() { 595 void MultiColumnFragmentainerGroupList::deleteExtraGroups() {
575 shrink(1); 596 shrink(1);
576 } 597 }
577 598
578 } // namespace blink 599 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698