OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2012 Apple Inc. All rights reserved. | 2 * Copyright (C) 2012 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
77 { | 77 { |
78 RenderBlockFlow* multicolBlock = multiColumnBlockFlow(); | 78 RenderBlockFlow* multicolBlock = multiColumnBlockFlow(); |
79 LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderBefore() - multicolBlock->paddingBefore(); | 79 LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderBefore() - multicolBlock->paddingBefore(); |
80 | 80 |
81 height -= contentLogicalTop; | 81 height -= contentLogicalTop; |
82 return max(height, LayoutUnit(1)); // Let's avoid zero height, as that would probably cause an infinite amount of columns to be created. | 82 return max(height, LayoutUnit(1)); // Let's avoid zero height, as that would probably cause an infinite amount of columns to be created. |
83 } | 83 } |
84 | 84 |
85 LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) cons t | 85 LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) cons t |
86 { | 86 { |
87 LayoutUnit portionLogicalTop = (isHorizontalWritingMode() ? flowThreadPortio nRect().y() : flowThreadPortionRect().x()); | |
88 unsigned columnIndex = columnIndexAtOffset(offset, AssumeNewColumns); | 87 unsigned columnIndex = columnIndexAtOffset(offset, AssumeNewColumns); |
89 return portionLogicalTop + columnIndex * computedColumnHeight(); | 88 return logicalTopInFlowThread() + columnIndex * computedColumnHeight(); |
90 } | 89 } |
91 | 90 |
92 void RenderMultiColumnSet::setAndConstrainColumnHeight(LayoutUnit newHeight) | 91 void RenderMultiColumnSet::setAndConstrainColumnHeight(LayoutUnit newHeight) |
93 { | 92 { |
94 m_computedColumnHeight = newHeight; | 93 m_computedColumnHeight = newHeight; |
95 if (m_computedColumnHeight > m_maxColumnHeight) | 94 if (m_computedColumnHeight > m_maxColumnHeight) |
96 m_computedColumnHeight = m_maxColumnHeight; | 95 m_computedColumnHeight = m_maxColumnHeight; |
97 // FIXME: the height may also be affected by the enclosing pagination contex t, if any. | 96 // FIXME: the height may also be affected by the enclosing pagination contex t, if any. |
98 } | 97 } |
99 | 98 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
199 } | 198 } |
200 LayoutUnit newColumnHeight = calculateColumnHeight(initial); | 199 LayoutUnit newColumnHeight = calculateColumnHeight(initial); |
201 setAndConstrainColumnHeight(newColumnHeight); | 200 setAndConstrainColumnHeight(newColumnHeight); |
202 | 201 |
203 // After having calculated an initial column height, the multicol container typically needs at | 202 // After having calculated an initial column height, the multicol container typically needs at |
204 // least one more layout pass with a new column height, but if a height was specified, we only | 203 // least one more layout pass with a new column height, but if a height was specified, we only |
205 // need to do this if we think that we need less space than specified. Conve rsely, if we | 204 // need to do this if we think that we need less space than specified. Conve rsely, if we |
206 // determined that the columns need to be as tall as the specified height of the container, we | 205 // determined that the columns need to be as tall as the specified height of the container, we |
207 // have already laid it out correctly, and there's no need for another pass. | 206 // have already laid it out correctly, and there's no need for another pass. |
208 | 207 |
208 // We can get rid of the content runs now, if we haven't already done so. Th ey are only needed | |
209 // to calculate the initial balanced column height. In fact, we have to get rid of them before | |
210 // the next layout pass, since each pass will rebuild this. | |
211 m_contentRuns.clear(); | |
212 | |
209 if (m_computedColumnHeight == oldColumnHeight) | 213 if (m_computedColumnHeight == oldColumnHeight) |
210 return false; // No change. We're done. | 214 return false; // No change. We're done. |
211 | 215 |
212 m_minSpaceShortage = RenderFlowThread::maxLogicalHeight(); | 216 m_minSpaceShortage = RenderFlowThread::maxLogicalHeight(); |
213 m_contentRuns.clear(); | |
214 return true; // Need another pass. | 217 return true; // Need another pass. |
215 } | 218 } |
216 | 219 |
217 void RenderMultiColumnSet::recordSpaceShortage(LayoutUnit spaceShortage) | 220 void RenderMultiColumnSet::recordSpaceShortage(LayoutUnit spaceShortage) |
218 { | 221 { |
219 if (spaceShortage >= m_minSpaceShortage) | 222 if (spaceShortage >= m_minSpaceShortage) |
220 return; | 223 return; |
221 | 224 |
222 // The space shortage is what we use as our stretch amount. We need a positi ve number here in | 225 // The space shortage is what we use as our stretch amount. We need a positi ve number here in |
223 // order to get anywhere. | 226 // order to get anywhere. |
(...skipping 17 matching lines...) Expand all Loading... | |
241 LayoutUnit minimumContentLogicalWidth = colCount * computedColumnWidth() + ( colCount - 1) * colGap; | 244 LayoutUnit minimumContentLogicalWidth = colCount * computedColumnWidth() + ( colCount - 1) * colGap; |
242 LayoutUnit currentContentLogicalWidth = contentLogicalWidth(); | 245 LayoutUnit currentContentLogicalWidth = contentLogicalWidth(); |
243 LayoutUnit delta = max(LayoutUnit(), minimumContentLogicalWidth - currentCon tentLogicalWidth); | 246 LayoutUnit delta = max(LayoutUnit(), minimumContentLogicalWidth - currentCon tentLogicalWidth); |
244 if (!delta) | 247 if (!delta) |
245 return; | 248 return; |
246 | 249 |
247 // Increase our logical width by the delta. | 250 // Increase our logical width by the delta. |
248 setLogicalWidth(logicalWidth() + delta); | 251 setLogicalWidth(logicalWidth() + delta); |
249 } | 252 } |
250 | 253 |
251 void RenderMultiColumnSet::prepareForLayout() | 254 void RenderMultiColumnSet::prepareForLayout(bool initial) |
Julien - ping for review
2014/05/20 17:03:04
We should replace the first-pass boolean logic wit
mstensho (USE GERRIT)
2014/05/22 15:07:18
Done.
I did the second best thing - removed the p
| |
252 { | 255 { |
253 RenderBlockFlow* multicolBlock = multiColumnBlockFlow(); | 256 RenderBlockFlow* multicolBlock = multiColumnBlockFlow(); |
254 RenderStyle* multicolStyle = multicolBlock->style(); | |
255 | 257 |
256 // Set box logical top. | 258 // Set box logical top. |
257 ASSERT(!previousSiblingBox() || !previousSiblingBox()->isRenderMultiColumnSe t()); // FIXME: multiple set not implemented; need to examine previous set to ca lculate the correct logical top. | 259 ASSERT(!previousSiblingBox() || !previousSiblingBox()->isRenderMultiColumnSe t()); // FIXME: multiple set not implemented; need to examine previous set to ca lculate the correct logical top. |
258 setLogicalTop(multicolBlock->borderBefore() + multicolBlock->paddingBefore() ); | 260 setLogicalTop(multicolBlock->borderAndPaddingBefore()); |
259 | 261 |
260 // Set box width. | 262 if (initial) { |
261 updateLogicalWidth(); | 263 m_maxColumnHeight = calculateMaxColumnHeight(); |
262 | 264 updateLogicalWidth(); |
Julien - ping for review
2014/05/20 17:03:04
It's weird that prepareForLayout actually does wha
mstensho (USE GERRIT)
2014/05/22 15:07:18
Done.
All it really needed from updateLogicalWidt
| |
265 } | |
263 if (multiColumnFlowThread()->requiresBalancing()) { | 266 if (multiColumnFlowThread()->requiresBalancing()) { |
264 // Set maximum column height. We will not stretch beyond this. | 267 if (initial) |
265 m_maxColumnHeight = RenderFlowThread::maxLogicalHeight(); | 268 m_computedColumnHeight = 0; |
266 if (!multicolStyle->logicalHeight().isAuto()) { | |
267 m_maxColumnHeight = multicolBlock->computeContentLogicalHeight(multi colStyle->logicalHeight(), -1); | |
268 if (m_maxColumnHeight == -1) | |
269 m_maxColumnHeight = RenderFlowThread::maxLogicalHeight(); | |
270 } | |
271 if (!multicolStyle->logicalMaxHeight().isUndefined()) { | |
272 LayoutUnit logicalMaxHeight = multicolBlock->computeContentLogicalHe ight(multicolStyle->logicalMaxHeight(), -1); | |
273 if (logicalMaxHeight != -1 && m_maxColumnHeight > logicalMaxHeight) | |
274 m_maxColumnHeight = logicalMaxHeight; | |
275 } | |
276 m_maxColumnHeight = heightAdjustedForSetOffset(m_maxColumnHeight); | |
277 m_computedColumnHeight = 0; // Restart balancing. | |
278 } else { | 269 } else { |
279 setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowTh read()->columnHeightAvailable())); | 270 setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowTh read()->columnHeightAvailable())); |
280 } | 271 } |
281 | 272 |
282 m_contentRuns.clear(); | 273 // Content runs are only needed in the initial layout pass, in order to find an initial column |
274 // height, and should have been deleted afterwards. We're about to rebuild t he content runs, so | |
275 // the list needs to be empty. | |
276 ASSERT(m_contentRuns.isEmpty()); | |
283 | 277 |
284 // Nuke previously stored minimum column height. Contents may have changed f or all we know. | 278 // Nuke previously stored minimum column height. Contents may have changed f or all we know. |
285 m_minimumColumnHeight = 0; | 279 m_minimumColumnHeight = 0; |
280 | |
281 setNeedsLayoutAndFullRepaint(); | |
Julien - ping for review
2014/05/20 17:03:04
There is no branch in prepareForLayout, which mean
mstensho (USE GERRIT)
2014/05/21 09:02:33
No, that looks very unnecessary, apart from being
mstensho (USE GERRIT)
2014/05/22 15:07:18
Done.
We now call setChildNeedsLayout(MarkOnlyThi
| |
286 } | 282 } |
287 | 283 |
288 void RenderMultiColumnSet::expandToEncompassFlowThreadContentsIfNeeded() | 284 void RenderMultiColumnSet::expandToEncompassFlowThreadContentsIfNeeded() |
289 { | 285 { |
290 ASSERT(multiColumnFlowThread()->lastMultiColumnSet() == this); | 286 ASSERT(multiColumnFlowThread()->lastMultiColumnSet() == this); |
291 LayoutRect rect(flowThreadPortionRect()); | 287 LayoutRect rect(flowThreadPortionRect()); |
292 | 288 |
293 // Get the offset within the flow thread in its block progression direction. Then get the | 289 // Get the offset within the flow thread in its block progression direction. Then get the |
294 // flow thread's remaining logical height including its overflow and expand our rect | 290 // flow thread's remaining logical height including its overflow and expand our rect |
295 // to encompass that remaining height and overflow. The idea is that we will generate | 291 // to encompass that remaining height and overflow. The idea is that we will generate |
296 // additional columns and pages to hold that overflow, since people do write bad | 292 // additional columns and pages to hold that overflow, since people do write bad |
297 // content like <body style="height:0px"> in multi-column layouts. | 293 // content like <body style="height:0px"> in multi-column layouts. |
298 bool isHorizontal = flowThread()->isHorizontalWritingMode(); | 294 bool isHorizontal = flowThread()->isHorizontalWritingMode(); |
299 LayoutUnit logicalTopOffset = isHorizontal ? rect.y() : rect.x(); | 295 LayoutUnit logicalTopOffset = isHorizontal ? rect.y() : rect.x(); |
300 LayoutRect layoutRect = flowThread()->layoutOverflowRect(); | 296 LayoutRect layoutRect = flowThread()->layoutOverflowRect(); |
301 LayoutUnit logicalHeightWithOverflow = (isHorizontal ? layoutRect.maxY() : l ayoutRect.maxX()) - logicalTopOffset; | 297 LayoutUnit logicalHeightWithOverflow = (isHorizontal ? layoutRect.maxY() : l ayoutRect.maxX()) - logicalTopOffset; |
302 setFlowThreadPortionRect(LayoutRect(rect.x(), rect.y(), isHorizontal ? rect. width() : logicalHeightWithOverflow, isHorizontal ? logicalHeightWithOverflow : rect.height())); | 298 setFlowThreadPortionRect(LayoutRect(rect.x(), rect.y(), isHorizontal ? rect. width() : logicalHeightWithOverflow, isHorizontal ? logicalHeightWithOverflow : rect.height())); |
303 } | 299 } |
304 | 300 |
305 void RenderMultiColumnSet::layout() | 301 void RenderMultiColumnSet::layout() |
306 { | 302 { |
307 RenderRegion::layout(); | 303 RenderRegion::layout(); |
308 | 304 |
309 if (!nextSiblingMultiColumnSet()) { | 305 // At this point the logical top of the column set is known. Update maximum column height |
310 // This is the last set, i.e. the last region. Seize the opportunity to validate them. | 306 // (multicol height may be constrained, and in order to calculate it, we nee d to know our top). |
311 multiColumnFlowThread()->validateRegions(); | 307 m_maxColumnHeight = calculateMaxColumnHeight(); |
312 } | |
313 } | 308 } |
314 | 309 |
315 void RenderMultiColumnSet::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTo p, LogicalExtentComputedValues& computedValues) const | 310 void RenderMultiColumnSet::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTo p, LogicalExtentComputedValues& computedValues) const |
316 { | 311 { |
317 computedValues.m_extent = m_computedColumnHeight; | 312 computedValues.m_extent = m_computedColumnHeight; |
318 computedValues.m_position = logicalTop; | 313 computedValues.m_position = logicalTop; |
319 } | 314 } |
320 | 315 |
316 LayoutUnit RenderMultiColumnSet::calculateMaxColumnHeight() const | |
317 { | |
318 RenderBlockFlow* multicolBlock = multiColumnBlockFlow(); | |
319 RenderStyle* multicolStyle = multicolBlock->style(); | |
320 LayoutUnit availableHeight = multiColumnFlowThread()->columnHeightAvailable( ); | |
321 LayoutUnit maxColumnHeight = availableHeight ? availableHeight : RenderFlowT hread::maxLogicalHeight(); | |
322 if (!multicolStyle->logicalMaxHeight().isUndefined()) { | |
323 LayoutUnit logicalMaxHeight = multicolBlock->computeContentLogicalHeight (multicolStyle->logicalMaxHeight(), -1); | |
324 if (logicalMaxHeight != -1 && maxColumnHeight > logicalMaxHeight) | |
325 maxColumnHeight = logicalMaxHeight; | |
326 } | |
327 return heightAdjustedForSetOffset(maxColumnHeight); | |
328 } | |
329 | |
321 LayoutUnit RenderMultiColumnSet::columnGap() const | 330 LayoutUnit RenderMultiColumnSet::columnGap() const |
322 { | 331 { |
323 RenderBlockFlow* parentBlock = multiColumnBlockFlow(); | 332 RenderBlockFlow* parentBlock = multiColumnBlockFlow(); |
324 if (parentBlock->style()->hasNormalColumnGap()) | 333 if (parentBlock->style()->hasNormalColumnGap()) |
325 return parentBlock->style()->fontDescription().computedPixelSize(); // " 1em" is recommended as the normal gap setting. Matches <p> margins. | 334 return parentBlock->style()->fontDescription().computedPixelSize(); // " 1em" is recommended as the normal gap setting. Matches <p> margins. |
326 return parentBlock->style()->columnGap(); | 335 return parentBlock->style()->columnGap(); |
327 } | 336 } |
328 | 337 |
329 unsigned RenderMultiColumnSet::columnCount() const | 338 unsigned RenderMultiColumnSet::columnCount() const |
330 { | 339 { |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
630 fragments.append(fragment); | 639 fragments.append(fragment); |
631 } | 640 } |
632 } | 641 } |
633 | 642 |
634 const char* RenderMultiColumnSet::renderName() const | 643 const char* RenderMultiColumnSet::renderName() const |
635 { | 644 { |
636 return "RenderMultiColumnSet"; | 645 return "RenderMultiColumnSet"; |
637 } | 646 } |
638 | 647 |
639 } | 648 } |
OLD | NEW |