| 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 11 matching lines...) Expand all Loading... |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "config.h" | 26 #include "config.h" |
| 27 #include "core/rendering/RenderMultiColumnSet.h" | 27 #include "core/rendering/RenderMultiColumnSet.h" |
| 28 | 28 |
| 29 #include "core/rendering/PaintInfo.h" | 29 #include "core/rendering/PaintInfo.h" |
| 30 #include "core/rendering/RenderLayer.h" | 30 #include "core/rendering/RenderLayer.h" |
| 31 #include "core/rendering/RenderMultiColumnFlowThread.h" | 31 #include "core/rendering/RenderMultiColumnFlowThread.h" |
| 32 #include "core/rendering/RenderMultiColumnSpannerPlaceholder.h" |
| 32 | 33 |
| 33 namespace blink { | 34 namespace blink { |
| 34 | 35 |
| 35 RenderMultiColumnSet::RenderMultiColumnSet(RenderFlowThread* flowThread) | 36 RenderMultiColumnSet::RenderMultiColumnSet(RenderFlowThread* flowThread) |
| 36 : RenderRegion(0, flowThread) | 37 : RenderRegion(0, flowThread) |
| 37 , m_columnHeight(0) | 38 , m_columnHeight(0) |
| 38 , m_maxColumnHeight(RenderFlowThread::maxLogicalHeight()) | 39 , m_maxColumnHeight(RenderFlowThread::maxLogicalHeight()) |
| 39 , m_minSpaceShortage(RenderFlowThread::maxLogicalHeight()) | 40 , m_minSpaceShortage(RenderFlowThread::maxLogicalHeight()) |
| 40 , m_minimumColumnHeight(0) | 41 , m_minimumColumnHeight(0) |
| 41 { | 42 { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 61 | 62 |
| 62 RenderMultiColumnSet* RenderMultiColumnSet::previousSiblingMultiColumnSet() cons
t | 63 RenderMultiColumnSet* RenderMultiColumnSet::previousSiblingMultiColumnSet() cons
t |
| 63 { | 64 { |
| 64 for (RenderObject* sibling = previousSibling(); sibling; sibling = sibling->
previousSibling()) { | 65 for (RenderObject* sibling = previousSibling(); sibling; sibling = sibling->
previousSibling()) { |
| 65 if (sibling->isRenderMultiColumnSet()) | 66 if (sibling->isRenderMultiColumnSet()) |
| 66 return toRenderMultiColumnSet(sibling); | 67 return toRenderMultiColumnSet(sibling); |
| 67 } | 68 } |
| 68 return 0; | 69 return 0; |
| 69 } | 70 } |
| 70 | 71 |
| 72 void RenderMultiColumnSet::setLogicalTopInFlowThread(LayoutUnit logicalTop) |
| 73 { |
| 74 LayoutRect rect = flowThreadPortionRect(); |
| 75 if (isHorizontalWritingMode()) |
| 76 rect.setY(logicalTop); |
| 77 else |
| 78 rect.setX(logicalTop); |
| 79 setFlowThreadPortionRect(rect); |
| 80 } |
| 81 |
| 82 void RenderMultiColumnSet::setLogicalBottomInFlowThread(LayoutUnit logicalBottom
) |
| 83 { |
| 84 LayoutRect rect = flowThreadPortionRect(); |
| 85 if (isHorizontalWritingMode()) |
| 86 rect.shiftMaxYEdgeTo(logicalBottom); |
| 87 else |
| 88 rect.shiftMaxXEdgeTo(logicalBottom); |
| 89 setFlowThreadPortionRect(rect); |
| 90 } |
| 91 |
| 92 bool RenderMultiColumnSet::heightIsAuto() const |
| 93 { |
| 94 RenderMultiColumnFlowThread* flowThread = multiColumnFlowThread(); |
| 95 if (!flowThread->isRenderPagedFlowThread()) { |
| 96 if (RenderBox* next = RenderMultiColumnFlowThread::nextColumnSetOrSpanne
rSiblingOf(this)) { |
| 97 if (!next->isRenderMultiColumnSet()) { |
| 98 // If we're followed by a spanner, we need to balance. |
| 99 ASSERT(flowThread->findColumnSpannerPlaceholder(next)); |
| 100 return true; |
| 101 } |
| 102 } |
| 103 if (multiColumnBlockFlow()->style()->columnFill() == ColumnFillBalance) |
| 104 return true; |
| 105 } |
| 106 return !flowThread->columnHeightAvailable(); |
| 107 } |
| 108 |
| 71 LayoutSize RenderMultiColumnSet::flowThreadTranslationAtOffset(LayoutUnit blockO
ffset) const | 109 LayoutSize RenderMultiColumnSet::flowThreadTranslationAtOffset(LayoutUnit blockO
ffset) const |
| 72 { | 110 { |
| 73 unsigned columnIndex = columnIndexAtOffset(blockOffset); | 111 unsigned columnIndex = columnIndexAtOffset(blockOffset); |
| 74 LayoutRect portionRect(flowThreadPortionRectAt(columnIndex)); | 112 LayoutRect portionRect(flowThreadPortionRectAt(columnIndex)); |
| 75 flipForWritingMode(portionRect); | 113 flipForWritingMode(portionRect); |
| 76 LayoutRect columnRect(columnRectAt(columnIndex)); | 114 LayoutRect columnRect(columnRectAt(columnIndex)); |
| 77 flipForWritingMode(columnRect); | 115 flipForWritingMode(columnRect); |
| 78 return contentBoxRect().location() + columnRect.location() - portionRect.loc
ation(); | 116 return contentBoxRect().location() + columnRect.location() - portionRect.loc
ation(); |
| 79 } | 117 } |
| 80 | 118 |
| 81 LayoutUnit RenderMultiColumnSet::heightAdjustedForSetOffset(LayoutUnit height) c
onst | 119 LayoutUnit RenderMultiColumnSet::heightAdjustedForSetOffset(LayoutUnit height) c
onst |
| 82 { | 120 { |
| 83 // Adjust for the top offset within the content box of the multicol containe
r (containing | 121 // Adjust for the top offset within the content box of the multicol containe
r (containing |
| 84 // block), unless this is the first set. We know that the top offset for the
first set will be | 122 // block), unless this is the first set. We know that the top offset for the
first set will be |
| 85 // zero, but if the multicol container has non-zero top border or padding, t
he set's top offset | 123 // zero, but if the multicol container has non-zero top border or padding, t
he set's top offset |
| 86 // (initially being 0 and relative to the border box) will be negative until
it has been laid | 124 // (initially being 0 and relative to the border box) will be negative until
it has been laid |
| 87 // out. Had we used this bogus offset, we would calculate the wrong height,
and risk performing | 125 // out. Had we used this bogus offset, we would calculate the wrong height,
and risk performing |
| 88 // a wasted layout iteration. Of course all other sets (if any) have this pr
oblem in the first | 126 // a wasted layout iteration. Of course all other sets (if any) have this pr
oblem in the first |
| 89 // layout pass too, but there's really nothing we can do there until the flo
w thread has been | 127 // layout pass too, but there's really nothing we can do there until the flo
w thread has been |
| 90 // laid out anyway. | 128 // laid out anyway. |
| 91 if (previousSiblingMultiColumnSet()) { | 129 if (RenderMultiColumnFlowThread::previousColumnSetOrSpannerSiblingOf(this))
{ |
| 92 RenderBlockFlow* multicolBlock = multiColumnBlockFlow(); | 130 RenderBlockFlow* multicolBlock = multiColumnBlockFlow(); |
| 93 LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderAndPa
ddingBefore(); | 131 LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderAndPa
ddingBefore(); |
| 94 height -= contentLogicalTop; | 132 height -= contentLogicalTop; |
| 95 } | 133 } |
| 96 return max(height, LayoutUnit(1)); // Let's avoid zero height, as that would
probably cause an infinite amount of columns to be created. | 134 return max(height, LayoutUnit(1)); // Let's avoid zero height, as that would
probably cause an infinite amount of columns to be created. |
| 97 } | 135 } |
| 98 | 136 |
| 99 LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) cons
t | 137 LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) cons
t |
| 100 { | 138 { |
| 101 unsigned columnIndex = columnIndexAtOffset(offset, AssumeNewColumns); | 139 unsigned columnIndex = columnIndexAtOffset(offset, AssumeNewColumns); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 ASSERT(m_minSpaceShortage > 0); // We should never _shrink_ the height! | 222 ASSERT(m_minSpaceShortage > 0); // We should never _shrink_ the height! |
| 185 ASSERT(m_minSpaceShortage != RenderFlowThread::maxLogicalHeight()); // If th
is happens, we probably have a bug. | 223 ASSERT(m_minSpaceShortage != RenderFlowThread::maxLogicalHeight()); // If th
is happens, we probably have a bug. |
| 186 if (m_minSpaceShortage == RenderFlowThread::maxLogicalHeight()) | 224 if (m_minSpaceShortage == RenderFlowThread::maxLogicalHeight()) |
| 187 return m_columnHeight; // So bail out rather than looping infinitely. | 225 return m_columnHeight; // So bail out rather than looping infinitely. |
| 188 | 226 |
| 189 return m_columnHeight + m_minSpaceShortage; | 227 return m_columnHeight + m_minSpaceShortage; |
| 190 } | 228 } |
| 191 | 229 |
| 192 void RenderMultiColumnSet::addContentRun(LayoutUnit endOffsetFromFirstPage) | 230 void RenderMultiColumnSet::addContentRun(LayoutUnit endOffsetFromFirstPage) |
| 193 { | 231 { |
| 194 if (!multiColumnFlowThread()->heightIsAuto()) | 232 if (!heightIsAuto()) |
| 195 return; | 233 return; |
| 196 if (!m_contentRuns.isEmpty() && endOffsetFromFirstPage <= m_contentRuns.last
().breakOffset()) | 234 if (!m_contentRuns.isEmpty() && endOffsetFromFirstPage <= m_contentRuns.last
().breakOffset()) |
| 197 return; | 235 return; |
| 198 // Append another item as long as we haven't exceeded used column count. Wha
t ends up in the | 236 // Append another item as long as we haven't exceeded used column count. Wha
t ends up in the |
| 199 // overflow area shouldn't affect column balancing. | 237 // overflow area shouldn't affect column balancing. |
| 200 if (m_contentRuns.size() < usedColumnCount()) | 238 if (m_contentRuns.size() < usedColumnCount()) |
| 201 m_contentRuns.append(ContentRun(endOffsetFromFirstPage)); | 239 m_contentRuns.append(ContentRun(endOffsetFromFirstPage)); |
| 202 } | 240 } |
| 203 | 241 |
| 204 bool RenderMultiColumnSet::recalculateColumnHeight(BalancedHeightCalculation cal
culationMode) | 242 bool RenderMultiColumnSet::recalculateColumnHeight(BalancedHeightCalculation cal
culationMode) |
| 205 { | 243 { |
| 206 ASSERT(multiColumnFlowThread()->heightIsAuto()); | 244 LayoutUnit oldColumnHeight = m_columnHeight; |
| 207 | 245 |
| 208 LayoutUnit oldColumnHeight = m_columnHeight; | 246 m_maxColumnHeight = calculateMaxColumnHeight(); |
| 209 if (calculationMode == GuessFromFlowThreadPortion) { | 247 |
| 210 // Post-process the content runs and find out where the implicit breaks
will occur. | 248 if (heightIsAuto()) { |
| 211 distributeImplicitBreaks(); | 249 if (calculationMode == GuessFromFlowThreadPortion) { |
| 250 // Post-process the content runs and find out where the implicit bre
aks will occur. |
| 251 distributeImplicitBreaks(); |
| 252 } |
| 253 LayoutUnit newColumnHeight = calculateColumnHeight(calculationMode); |
| 254 setAndConstrainColumnHeight(newColumnHeight); |
| 255 // After having calculated an initial column height, the multicol contai
ner typically needs at |
| 256 // least one more layout pass with a new column height, but if a height
was specified, we only |
| 257 // need to do this if we think that we need less space than specified. C
onversely, if we |
| 258 // determined that the columns need to be as tall as the specified heigh
t of the container, we |
| 259 // have already laid it out correctly, and there's no need for another p
ass. |
| 260 } else { |
| 261 // The position of the column set may have changed, in which case height
available for |
| 262 // columns may have changed as well. |
| 263 setAndConstrainColumnHeight(m_columnHeight); |
| 212 } | 264 } |
| 213 LayoutUnit newColumnHeight = calculateColumnHeight(calculationMode); | |
| 214 setAndConstrainColumnHeight(newColumnHeight); | |
| 215 | |
| 216 // After having calculated an initial column height, the multicol container
typically needs at | |
| 217 // least one more layout pass with a new column height, but if a height was
specified, we only | |
| 218 // need to do this if we think that we need less space than specified. Conve
rsely, if we | |
| 219 // determined that the columns need to be as tall as the specified height of
the container, we | |
| 220 // have already laid it out correctly, and there's no need for another pass. | |
| 221 | 265 |
| 222 // We can get rid of the content runs now, if we haven't already done so. Th
ey are only needed | 266 // We can get rid of the content runs now, if we haven't already done so. Th
ey are only needed |
| 223 // to calculate the initial balanced column height. In fact, we have to get
rid of them before | 267 // to calculate the initial balanced column height. In fact, we have to get
rid of them before |
| 224 // the next layout pass, since each pass will rebuild this. | 268 // the next layout pass, since each pass will rebuild this. |
| 225 m_contentRuns.clear(); | 269 m_contentRuns.clear(); |
| 226 | 270 |
| 227 if (m_columnHeight == oldColumnHeight) | 271 if (m_columnHeight == oldColumnHeight) |
| 228 return false; // No change. We're done. | 272 return false; // No change. We're done. |
| 229 | 273 |
| 230 m_minSpaceShortage = RenderFlowThread::maxLogicalHeight(); | 274 m_minSpaceShortage = RenderFlowThread::maxLogicalHeight(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 245 | 289 |
| 246 void RenderMultiColumnSet::resetColumnHeight() | 290 void RenderMultiColumnSet::resetColumnHeight() |
| 247 { | 291 { |
| 248 // Nuke previously stored minimum column height. Contents may have changed f
or all we know. | 292 // Nuke previously stored minimum column height. Contents may have changed f
or all we know. |
| 249 m_minimumColumnHeight = 0; | 293 m_minimumColumnHeight = 0; |
| 250 | 294 |
| 251 m_maxColumnHeight = calculateMaxColumnHeight(); | 295 m_maxColumnHeight = calculateMaxColumnHeight(); |
| 252 | 296 |
| 253 LayoutUnit oldColumnHeight = pageLogicalHeight(); | 297 LayoutUnit oldColumnHeight = pageLogicalHeight(); |
| 254 | 298 |
| 255 if (multiColumnFlowThread()->heightIsAuto()) | 299 if (heightIsAuto()) |
| 256 m_columnHeight = 0; | 300 m_columnHeight = 0; |
| 257 else | 301 else |
| 258 setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowTh
read()->columnHeightAvailable())); | 302 setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowTh
read()->columnHeightAvailable())); |
| 259 | 303 |
| 260 if (pageLogicalHeight() != oldColumnHeight) | 304 if (pageLogicalHeight() != oldColumnHeight) |
| 261 setChildNeedsLayout(MarkOnlyThis); | 305 setChildNeedsLayout(MarkOnlyThis); |
| 262 | 306 |
| 263 // Content runs are only needed in the initial layout pass, in order to find
an initial column | 307 // Content runs are only needed in the initial layout pass, in order to find
an initial column |
| 264 // height, and should have been deleted afterwards. We're about to rebuild t
he content runs, so | 308 // height, and should have been deleted afterwards. We're about to rebuild t
he content runs, so |
| 265 // the list needs to be empty. | 309 // the list needs to be empty. |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 | 728 |
| 685 void RenderMultiColumnSet::detachRegion() | 729 void RenderMultiColumnSet::detachRegion() |
| 686 { | 730 { |
| 687 if (m_flowThread) { | 731 if (m_flowThread) { |
| 688 m_flowThread->removeRegionFromThread(this); | 732 m_flowThread->removeRegionFromThread(this); |
| 689 m_flowThread = 0; | 733 m_flowThread = 0; |
| 690 } | 734 } |
| 691 } | 735 } |
| 692 | 736 |
| 693 } | 737 } |
| OLD | NEW |