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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 | 60 |
61 RenderMultiColumnSet* RenderMultiColumnSet::previousSiblingMultiColumnSet() cons
t | 61 RenderMultiColumnSet* RenderMultiColumnSet::previousSiblingMultiColumnSet() cons
t |
62 { | 62 { |
63 for (RenderObject* sibling = previousSibling(); sibling; sibling = sibling->
previousSibling()) { | 63 for (RenderObject* sibling = previousSibling(); sibling; sibling = sibling->
previousSibling()) { |
64 if (sibling->isRenderMultiColumnSet()) | 64 if (sibling->isRenderMultiColumnSet()) |
65 return toRenderMultiColumnSet(sibling); | 65 return toRenderMultiColumnSet(sibling); |
66 } | 66 } |
67 return 0; | 67 return 0; |
68 } | 68 } |
69 | 69 |
| 70 void RenderMultiColumnSet::setLogicalTopInFlowThread(LayoutUnit logicalTop) |
| 71 { |
| 72 LayoutRect rect = flowThreadPortionRect(); |
| 73 if (isHorizontalWritingMode()) |
| 74 rect.setY(logicalTop); |
| 75 else |
| 76 rect.setX(logicalTop); |
| 77 setFlowThreadPortionRect(rect); |
| 78 } |
| 79 |
| 80 void RenderMultiColumnSet::setLogicalBottomInFlowThread(LayoutUnit logicalBottom
) |
| 81 { |
| 82 LayoutRect rect = flowThreadPortionRect(); |
| 83 if (isHorizontalWritingMode()) |
| 84 rect.shiftMaxYEdgeTo(logicalBottom); |
| 85 else |
| 86 rect.shiftMaxXEdgeTo(logicalBottom); |
| 87 setFlowThreadPortionRect(rect); |
| 88 } |
| 89 |
| 90 bool RenderMultiColumnSet::heightIsAuto() const |
| 91 { |
| 92 RenderMultiColumnFlowThread* flowThread = multiColumnFlowThread(); |
| 93 if (!flowThread->isRenderPagedFlowThread()) { |
| 94 if (multiColumnBlockFlow()->style()->columnFill() == ColumnFillBalance) |
| 95 return true; |
| 96 if (RenderBox* next = nextSiblingBox()) { |
| 97 if (next->isRenderMultiColumnSpannerPlaceholder()) { |
| 98 // If we're followed by a spanner, we need to balance. |
| 99 return true; |
| 100 } |
| 101 } |
| 102 } |
| 103 return !flowThread->columnHeightAvailable(); |
| 104 } |
| 105 |
70 LayoutSize RenderMultiColumnSet::flowThreadTranslationAtOffset(LayoutUnit blockO
ffset) const | 106 LayoutSize RenderMultiColumnSet::flowThreadTranslationAtOffset(LayoutUnit blockO
ffset) const |
71 { | 107 { |
72 unsigned columnIndex = columnIndexAtOffset(blockOffset); | 108 unsigned columnIndex = columnIndexAtOffset(blockOffset); |
73 LayoutRect portionRect(flowThreadPortionRectAt(columnIndex)); | 109 LayoutRect portionRect(flowThreadPortionRectAt(columnIndex)); |
74 flipForWritingMode(portionRect); | 110 flipForWritingMode(portionRect); |
75 LayoutRect columnRect(columnRectAt(columnIndex)); | 111 LayoutRect columnRect(columnRectAt(columnIndex)); |
76 flipForWritingMode(columnRect); | 112 flipForWritingMode(columnRect); |
77 return contentBoxRect().location() + columnRect.location() - portionRect.loc
ation(); | 113 return contentBoxRect().location() + columnRect.location() - portionRect.loc
ation(); |
78 } | 114 } |
79 | 115 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 ASSERT(m_minSpaceShortage > 0); // We should never _shrink_ the height! | 219 ASSERT(m_minSpaceShortage > 0); // We should never _shrink_ the height! |
184 ASSERT(m_minSpaceShortage != RenderFlowThread::maxLogicalHeight()); // If th
is happens, we probably have a bug. | 220 ASSERT(m_minSpaceShortage != RenderFlowThread::maxLogicalHeight()); // If th
is happens, we probably have a bug. |
185 if (m_minSpaceShortage == RenderFlowThread::maxLogicalHeight()) | 221 if (m_minSpaceShortage == RenderFlowThread::maxLogicalHeight()) |
186 return m_columnHeight; // So bail out rather than looping infinitely. | 222 return m_columnHeight; // So bail out rather than looping infinitely. |
187 | 223 |
188 return m_columnHeight + m_minSpaceShortage; | 224 return m_columnHeight + m_minSpaceShortage; |
189 } | 225 } |
190 | 226 |
191 void RenderMultiColumnSet::addContentRun(LayoutUnit endOffsetFromFirstPage) | 227 void RenderMultiColumnSet::addContentRun(LayoutUnit endOffsetFromFirstPage) |
192 { | 228 { |
193 if (!multiColumnFlowThread()->heightIsAuto()) | 229 if (!heightIsAuto()) |
194 return; | 230 return; |
195 if (!m_contentRuns.isEmpty() && endOffsetFromFirstPage <= m_contentRuns.last
().breakOffset()) | 231 if (!m_contentRuns.isEmpty() && endOffsetFromFirstPage <= m_contentRuns.last
().breakOffset()) |
196 return; | 232 return; |
197 // Append another item as long as we haven't exceeded used column count. Wha
t ends up in the | 233 // Append another item as long as we haven't exceeded used column count. Wha
t ends up in the |
198 // overflow area shouldn't affect column balancing. | 234 // overflow area shouldn't affect column balancing. |
199 if (m_contentRuns.size() < usedColumnCount()) | 235 if (m_contentRuns.size() < usedColumnCount()) |
200 m_contentRuns.append(ContentRun(endOffsetFromFirstPage)); | 236 m_contentRuns.append(ContentRun(endOffsetFromFirstPage)); |
201 } | 237 } |
202 | 238 |
203 bool RenderMultiColumnSet::recalculateColumnHeight(BalancedHeightCalculation cal
culationMode) | 239 bool RenderMultiColumnSet::recalculateColumnHeight(BalancedHeightCalculation cal
culationMode) |
204 { | 240 { |
205 if (previousSiblingMultiColumnSet()) { | 241 LayoutUnit oldColumnHeight = m_columnHeight; |
206 // FIXME: column spanner layout is not yet implemented. Until it's in pl
ace, we only operate | 242 |
207 // on the first set during layout. We need to ignore the others here, or
assertions will | 243 m_maxColumnHeight = calculateMaxColumnHeight(); |
208 // fail. | 244 |
209 return false; | 245 if (heightIsAuto()) { |
| 246 if (calculationMode == GuessFromFlowThreadPortion) { |
| 247 // Post-process the content runs and find out where the implicit bre
aks will occur. |
| 248 distributeImplicitBreaks(); |
| 249 } |
| 250 LayoutUnit newColumnHeight = calculateColumnHeight(calculationMode); |
| 251 setAndConstrainColumnHeight(newColumnHeight); |
| 252 // After having calculated an initial column height, the multicol contai
ner typically needs at |
| 253 // least one more layout pass with a new column height, but if a height
was specified, we only |
| 254 // need to do this if we think that we need less space than specified. C
onversely, if we |
| 255 // determined that the columns need to be as tall as the specified heigh
t of the container, we |
| 256 // have already laid it out correctly, and there's no need for another p
ass. |
| 257 } else { |
| 258 // The position of the column set may have changed, in which case height
available for |
| 259 // columns may have changed as well. |
| 260 setAndConstrainColumnHeight(m_columnHeight); |
210 } | 261 } |
211 ASSERT(multiColumnFlowThread()->heightIsAuto()); | |
212 | |
213 LayoutUnit oldColumnHeight = m_columnHeight; | |
214 if (calculationMode == GuessFromFlowThreadPortion) { | |
215 // Post-process the content runs and find out where the implicit breaks
will occur. | |
216 distributeImplicitBreaks(); | |
217 } | |
218 LayoutUnit newColumnHeight = calculateColumnHeight(calculationMode); | |
219 setAndConstrainColumnHeight(newColumnHeight); | |
220 | |
221 // After having calculated an initial column height, the multicol container
typically needs at | |
222 // least one more layout pass with a new column height, but if a height was
specified, we only | |
223 // need to do this if we think that we need less space than specified. Conve
rsely, if we | |
224 // determined that the columns need to be as tall as the specified height of
the container, we | |
225 // have already laid it out correctly, and there's no need for another pass. | |
226 | 262 |
227 // We can get rid of the content runs now, if we haven't already done so. Th
ey are only needed | 263 // We can get rid of the content runs now, if we haven't already done so. Th
ey are only needed |
228 // to calculate the initial balanced column height. In fact, we have to get
rid of them before | 264 // to calculate the initial balanced column height. In fact, we have to get
rid of them before |
229 // the next layout pass, since each pass will rebuild this. | 265 // the next layout pass, since each pass will rebuild this. |
230 m_contentRuns.clear(); | 266 m_contentRuns.clear(); |
231 | 267 |
232 if (m_columnHeight == oldColumnHeight) | 268 if (m_columnHeight == oldColumnHeight) |
233 return false; // No change. We're done. | 269 return false; // No change. We're done. |
234 | 270 |
235 m_minSpaceShortage = RenderFlowThread::maxLogicalHeight(); | 271 m_minSpaceShortage = RenderFlowThread::maxLogicalHeight(); |
(...skipping 14 matching lines...) Expand all Loading... |
250 | 286 |
251 void RenderMultiColumnSet::resetColumnHeight() | 287 void RenderMultiColumnSet::resetColumnHeight() |
252 { | 288 { |
253 // Nuke previously stored minimum column height. Contents may have changed f
or all we know. | 289 // Nuke previously stored minimum column height. Contents may have changed f
or all we know. |
254 m_minimumColumnHeight = 0; | 290 m_minimumColumnHeight = 0; |
255 | 291 |
256 m_maxColumnHeight = calculateMaxColumnHeight(); | 292 m_maxColumnHeight = calculateMaxColumnHeight(); |
257 | 293 |
258 LayoutUnit oldColumnHeight = pageLogicalHeight(); | 294 LayoutUnit oldColumnHeight = pageLogicalHeight(); |
259 | 295 |
260 if (multiColumnFlowThread()->heightIsAuto()) | 296 if (heightIsAuto()) |
261 m_columnHeight = 0; | 297 m_columnHeight = 0; |
262 else | 298 else |
263 setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowTh
read()->columnHeightAvailable())); | 299 setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowTh
read()->columnHeightAvailable())); |
264 | 300 |
265 if (pageLogicalHeight() != oldColumnHeight) | 301 if (pageLogicalHeight() != oldColumnHeight) |
266 setChildNeedsLayout(MarkOnlyThis); | 302 setChildNeedsLayout(MarkOnlyThis); |
267 | 303 |
268 // Content runs are only needed in the initial layout pass, in order to find
an initial column | 304 // Content runs are only needed in the initial layout pass, in order to find
an initial column |
269 // height, and should have been deleted afterwards. We're about to rebuild t
he content runs, so | 305 // height, and should have been deleted afterwards. We're about to rebuild t
he content runs, so |
270 // the list needs to be empty. | 306 // the list needs to be empty. |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 | 624 |
589 void RenderMultiColumnSet::detachRegion() | 625 void RenderMultiColumnSet::detachRegion() |
590 { | 626 { |
591 if (m_flowThread) { | 627 if (m_flowThread) { |
592 m_flowThread->removeRegionFromThread(this); | 628 m_flowThread->removeRegionFromThread(this); |
593 m_flowThread = 0; | 629 m_flowThread = 0; |
594 } | 630 } |
595 } | 631 } |
596 | 632 |
597 } | 633 } |
OLD | NEW |