| 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 10 matching lines...) Expand all Loading... |
| 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 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/RenderMultiColumnBlock.h" | |
| 32 #include "core/rendering/RenderMultiColumnFlowThread.h" | 31 #include "core/rendering/RenderMultiColumnFlowThread.h" |
| 33 | 32 |
| 34 using namespace std; | 33 using namespace std; |
| 35 | 34 |
| 36 namespace WebCore { | 35 namespace WebCore { |
| 37 | 36 |
| 38 RenderMultiColumnSet::RenderMultiColumnSet(RenderFlowThread* flowThread) | 37 RenderMultiColumnSet::RenderMultiColumnSet(RenderFlowThread* flowThread) |
| 39 : RenderRegionSet(0, flowThread) | 38 : RenderRegionSet(0, flowThread) |
| 40 , m_computedColumnCount(1) | 39 , m_computedColumnCount(1) |
| 41 , m_computedColumnWidth(0) | 40 , m_computedColumnWidth(0) |
| 42 , m_computedColumnHeight(0) | 41 , m_computedColumnHeight(0) |
| 43 , m_maxColumnHeight(RenderFlowThread::maxLogicalHeight()) | 42 , m_maxColumnHeight(RenderFlowThread::maxLogicalHeight()) |
| 44 , m_minSpaceShortage(RenderFlowThread::maxLogicalHeight()) | 43 , m_minSpaceShortage(RenderFlowThread::maxLogicalHeight()) |
| 45 , m_minimumColumnHeight(0) | 44 , m_minimumColumnHeight(0) |
| 46 { | 45 { |
| 47 } | 46 } |
| 48 | 47 |
| 49 RenderMultiColumnSet* RenderMultiColumnSet::createAnonymous(RenderFlowThread* fl
owThread) | 48 RenderMultiColumnSet* RenderMultiColumnSet::createAnonymous(RenderFlowThread* fl
owThread) |
| 50 { | 49 { |
| 51 Document& document = flowThread->document(); | 50 Document& document = flowThread->document(); |
| 52 RenderMultiColumnSet* renderer = new RenderMultiColumnSet(flowThread); | 51 RenderMultiColumnSet* renderer = new RenderMultiColumnSet(flowThread); |
| 53 renderer->setDocumentForAnonymous(&document); | 52 renderer->setDocumentForAnonymous(&document); |
| 54 return renderer; | 53 return renderer; |
| 55 } | 54 } |
| 56 | 55 |
| 57 LayoutUnit RenderMultiColumnSet::heightAdjustedForSetOffset(LayoutUnit height) c
onst | 56 LayoutUnit RenderMultiColumnSet::heightAdjustedForSetOffset(LayoutUnit height) c
onst |
| 58 { | 57 { |
| 59 RenderMultiColumnBlock* multicolBlock = toRenderMultiColumnBlock(parent()); | 58 RenderBlockFlow* multicolBlock = multiColumnBlockFlow(); |
| 60 LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderBefore()
- multicolBlock->paddingBefore(); | 59 LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderBefore()
- multicolBlock->paddingBefore(); |
| 61 | 60 |
| 62 height -= contentLogicalTop; | 61 height -= contentLogicalTop; |
| 63 return max(height, LayoutUnit(1)); // Let's avoid zero height, as that would
probably cause an infinite amount of columns to be created. | 62 return max(height, LayoutUnit(1)); // Let's avoid zero height, as that would
probably cause an infinite amount of columns to be created. |
| 64 } | 63 } |
| 65 | 64 |
| 66 LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) cons
t | 65 LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) cons
t |
| 67 { | 66 { |
| 68 LayoutUnit portionLogicalTop = (isHorizontalWritingMode() ? flowThreadPortio
nRect().y() : flowThreadPortionRect().x()); | 67 LayoutUnit portionLogicalTop = (isHorizontalWritingMode() ? flowThreadPortio
nRect().y() : flowThreadPortionRect().x()); |
| 69 unsigned columnIndex = columnIndexAtOffset(offset, AssumeNewColumns); | 68 unsigned columnIndex = columnIndexAtOffset(offset, AssumeNewColumns); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 return m_computedColumnHeight + m_minSpaceShortage; | 154 return m_computedColumnHeight + m_minSpaceShortage; |
| 156 } | 155 } |
| 157 | 156 |
| 158 void RenderMultiColumnSet::clearForcedBreaks() | 157 void RenderMultiColumnSet::clearForcedBreaks() |
| 159 { | 158 { |
| 160 m_contentRuns.clear(); | 159 m_contentRuns.clear(); |
| 161 } | 160 } |
| 162 | 161 |
| 163 void RenderMultiColumnSet::addForcedBreak(LayoutUnit offsetFromFirstPage) | 162 void RenderMultiColumnSet::addForcedBreak(LayoutUnit offsetFromFirstPage) |
| 164 { | 163 { |
| 165 if (!toRenderMultiColumnBlock(parent())->requiresBalancing()) | 164 if (!multiColumnFlowThread()->requiresBalancing()) |
| 166 return; | 165 return; |
| 167 if (!m_contentRuns.isEmpty() && offsetFromFirstPage <= m_contentRuns.last().
breakOffset()) | 166 if (!m_contentRuns.isEmpty() && offsetFromFirstPage <= m_contentRuns.last().
breakOffset()) |
| 168 return; | 167 return; |
| 169 // Append another item as long as we haven't exceeded used column count. Wha
t ends up in the | 168 // Append another item as long as we haven't exceeded used column count. Wha
t ends up in the |
| 170 // overflow area shouldn't affect column balancing. | 169 // overflow area shouldn't affect column balancing. |
| 171 if (m_contentRuns.size() < m_computedColumnCount) | 170 if (m_contentRuns.size() < m_computedColumnCount) |
| 172 m_contentRuns.append(ContentRun(offsetFromFirstPage)); | 171 m_contentRuns.append(ContentRun(offsetFromFirstPage)); |
| 173 } | 172 } |
| 174 | 173 |
| 175 bool RenderMultiColumnSet::recalculateBalancedHeight(bool initial) | 174 bool RenderMultiColumnSet::recalculateBalancedHeight(bool initial) |
| 176 { | 175 { |
| 177 ASSERT(toRenderMultiColumnBlock(parent())->requiresBalancing()); | 176 ASSERT(multiColumnFlowThread()->requiresBalancing()); |
| 178 | 177 |
| 179 LayoutUnit oldColumnHeight = m_computedColumnHeight; | 178 LayoutUnit oldColumnHeight = m_computedColumnHeight; |
| 180 if (initial) | 179 if (initial) |
| 181 distributeImplicitBreaks(); | 180 distributeImplicitBreaks(); |
| 182 LayoutUnit newColumnHeight = calculateBalancedHeight(initial); | 181 LayoutUnit newColumnHeight = calculateBalancedHeight(initial); |
| 183 setAndConstrainColumnHeight(newColumnHeight); | 182 setAndConstrainColumnHeight(newColumnHeight); |
| 184 | 183 |
| 185 // After having calculated an initial column height, the multicol container
typically needs at | 184 // After having calculated an initial column height, the multicol container
typically needs at |
| 186 // least one more layout pass with a new column height, but if a height was
specified, we only | 185 // least one more layout pass with a new column height, but if a height was
specified, we only |
| 187 // need to do this if we think that we need less space than specified. Conve
rsely, if we | 186 // need to do this if we think that we need less space than specified. Conve
rsely, if we |
| (...skipping 15 matching lines...) Expand all Loading... |
| 203 | 202 |
| 204 // The space shortage is what we use as our stretch amount. We need a positi
ve number here in | 203 // The space shortage is what we use as our stretch amount. We need a positi
ve number here in |
| 205 // order to get anywhere. | 204 // order to get anywhere. |
| 206 ASSERT(spaceShortage > 0); | 205 ASSERT(spaceShortage > 0); |
| 207 | 206 |
| 208 m_minSpaceShortage = spaceShortage; | 207 m_minSpaceShortage = spaceShortage; |
| 209 } | 208 } |
| 210 | 209 |
| 211 void RenderMultiColumnSet::updateLogicalWidth() | 210 void RenderMultiColumnSet::updateLogicalWidth() |
| 212 { | 211 { |
| 213 RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent()); | 212 RenderMultiColumnFlowThread* flowThread = multiColumnFlowThread(); |
| 214 setComputedColumnWidthAndCount(parentBlock->columnWidth(), parentBlock->colu
mnCount()); // FIXME: This will eventually vary if we are contained inside regio
ns. | 213 setComputedColumnWidthAndCount(flowThread->columnWidth(), flowThread->column
Count()); |
| 215 | 214 |
| 216 // FIXME: When we add regions support, we'll start it off at the width of th
e multi-column | 215 // FIXME: When we add regions support, we'll start it off at the width of th
e multi-column |
| 217 // block in that particular region. | 216 // block in that particular region. |
| 218 setLogicalWidth(parentBox()->contentLogicalWidth()); | 217 setLogicalWidth(parentBox()->contentLogicalWidth()); |
| 219 | 218 |
| 220 // If we overflow, increase our logical width. | 219 // If we overflow, increase our logical width. |
| 221 unsigned colCount = columnCount(); | 220 unsigned colCount = columnCount(); |
| 222 LayoutUnit colGap = columnGap(); | 221 LayoutUnit colGap = columnGap(); |
| 223 LayoutUnit minimumContentLogicalWidth = colCount * computedColumnWidth() + (
colCount - 1) * colGap; | 222 LayoutUnit minimumContentLogicalWidth = colCount * computedColumnWidth() + (
colCount - 1) * colGap; |
| 224 LayoutUnit currentContentLogicalWidth = contentLogicalWidth(); | 223 LayoutUnit currentContentLogicalWidth = contentLogicalWidth(); |
| 225 LayoutUnit delta = max(LayoutUnit(), minimumContentLogicalWidth - currentCon
tentLogicalWidth); | 224 LayoutUnit delta = max(LayoutUnit(), minimumContentLogicalWidth - currentCon
tentLogicalWidth); |
| 226 if (!delta) | 225 if (!delta) |
| 227 return; | 226 return; |
| 228 | 227 |
| 229 // Increase our logical width by the delta. | 228 // Increase our logical width by the delta. |
| 230 setLogicalWidth(logicalWidth() + delta); | 229 setLogicalWidth(logicalWidth() + delta); |
| 231 } | 230 } |
| 232 | 231 |
| 233 void RenderMultiColumnSet::prepareForLayout() | 232 void RenderMultiColumnSet::prepareForLayout() |
| 234 { | 233 { |
| 235 RenderMultiColumnBlock* multicolBlock = toRenderMultiColumnBlock(parent()); | 234 RenderBlockFlow* multicolBlock = multiColumnBlockFlow(); |
| 236 RenderStyle* multicolStyle = multicolBlock->style(); | 235 RenderStyle* multicolStyle = multicolBlock->style(); |
| 237 | 236 |
| 238 // Set box logical top. | 237 // Set box logical top. |
| 239 ASSERT(!previousSiblingBox() || !previousSiblingBox()->isRenderMultiColumnSe
t()); // FIXME: multiple set not implemented; need to examine previous set to ca
lculate the correct logical top. | 238 ASSERT(!previousSiblingBox() || !previousSiblingBox()->isRenderMultiColumnSe
t()); // FIXME: multiple set not implemented; need to examine previous set to ca
lculate the correct logical top. |
| 240 setLogicalTop(multicolBlock->borderBefore() + multicolBlock->paddingBefore()
); | 239 setLogicalTop(multicolBlock->borderBefore() + multicolBlock->paddingBefore()
); |
| 241 | 240 |
| 242 // Set box width. | 241 // Set box width. |
| 243 updateLogicalWidth(); | 242 updateLogicalWidth(); |
| 244 | 243 |
| 245 if (multicolBlock->requiresBalancing()) { | 244 if (multicolBlock->multiColumnFlowThread()->requiresBalancing()) { |
| 246 // Set maximum column height. We will not stretch beyond this. | 245 // Set maximum column height. We will not stretch beyond this. |
| 247 m_maxColumnHeight = RenderFlowThread::maxLogicalHeight(); | 246 m_maxColumnHeight = RenderFlowThread::maxLogicalHeight(); |
| 248 if (!multicolStyle->logicalHeight().isAuto()) { | 247 if (!multicolStyle->logicalHeight().isAuto()) { |
| 249 m_maxColumnHeight = multicolBlock->computeContentLogicalHeight(multi
colStyle->logicalHeight(), -1); | 248 m_maxColumnHeight = multicolBlock->computeContentLogicalHeight(multi
colStyle->logicalHeight(), -1); |
| 250 if (m_maxColumnHeight == -1) | 249 if (m_maxColumnHeight == -1) |
| 251 m_maxColumnHeight = RenderFlowThread::maxLogicalHeight(); | 250 m_maxColumnHeight = RenderFlowThread::maxLogicalHeight(); |
| 252 } | 251 } |
| 253 if (!multicolStyle->logicalMaxHeight().isUndefined()) { | 252 if (!multicolStyle->logicalMaxHeight().isUndefined()) { |
| 254 LayoutUnit logicalMaxHeight = multicolBlock->computeContentLogicalHe
ight(multicolStyle->logicalMaxHeight(), -1); | 253 LayoutUnit logicalMaxHeight = multicolBlock->computeContentLogicalHe
ight(multicolStyle->logicalMaxHeight(), -1); |
| 255 if (logicalMaxHeight != -1 && m_maxColumnHeight > logicalMaxHeight) | 254 if (logicalMaxHeight != -1 && m_maxColumnHeight > logicalMaxHeight) |
| 256 m_maxColumnHeight = logicalMaxHeight; | 255 m_maxColumnHeight = logicalMaxHeight; |
| 257 } | 256 } |
| 258 m_maxColumnHeight = heightAdjustedForSetOffset(m_maxColumnHeight); | 257 m_maxColumnHeight = heightAdjustedForSetOffset(m_maxColumnHeight); |
| 259 m_computedColumnHeight = 0; // Restart balancing. | 258 m_computedColumnHeight = 0; // Restart balancing. |
| 260 } else { | 259 } else { |
| 261 setAndConstrainColumnHeight(heightAdjustedForSetOffset(multicolBlock->co
lumnHeightAvailable())); | 260 setAndConstrainColumnHeight(heightAdjustedForSetOffset(multicolBlock->mu
ltiColumnFlowThread()->columnHeightAvailable())); |
| 262 } | 261 } |
| 263 | 262 |
| 264 clearForcedBreaks(); | 263 clearForcedBreaks(); |
| 265 | 264 |
| 266 // Nuke previously stored minimum column height. Contents may have changed f
or all we know. | 265 // Nuke previously stored minimum column height. Contents may have changed f
or all we know. |
| 267 m_minimumColumnHeight = 0; | 266 m_minimumColumnHeight = 0; |
| 268 } | 267 } |
| 269 | 268 |
| 270 void RenderMultiColumnSet::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTo
p, LogicalExtentComputedValues& computedValues) const | 269 void RenderMultiColumnSet::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTo
p, LogicalExtentComputedValues& computedValues) const |
| 271 { | 270 { |
| 272 computedValues.m_extent = m_computedColumnHeight; | 271 computedValues.m_extent = m_computedColumnHeight; |
| 273 computedValues.m_position = logicalTop; | 272 computedValues.m_position = logicalTop; |
| 274 } | 273 } |
| 275 | 274 |
| 276 LayoutUnit RenderMultiColumnSet::columnGap() const | 275 LayoutUnit RenderMultiColumnSet::columnGap() const |
| 277 { | 276 { |
| 278 // FIXME: Eventually we will cache the column gap when the widths of columns
start varying, but for now we just | 277 RenderBlockFlow* parentBlock = multiColumnBlockFlow(); |
| 279 // go to the parent block to get the gap. | |
| 280 RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent()); | |
| 281 if (parentBlock->style()->hasNormalColumnGap()) | 278 if (parentBlock->style()->hasNormalColumnGap()) |
| 282 return parentBlock->style()->fontDescription().computedPixelSize(); // "
1em" is recommended as the normal gap setting. Matches <p> margins. | 279 return parentBlock->style()->fontDescription().computedPixelSize(); // "
1em" is recommended as the normal gap setting. Matches <p> margins. |
| 283 return parentBlock->style()->columnGap(); | 280 return parentBlock->style()->columnGap(); |
| 284 } | 281 } |
| 285 | 282 |
| 286 unsigned RenderMultiColumnSet::columnCount() const | 283 unsigned RenderMultiColumnSet::columnCount() const |
| 287 { | 284 { |
| 288 // We must always return a value of 1 or greater. Column count = 0 is a mean
ingless situation, | 285 // We must always return a value of 1 or greater. Column count = 0 is a mean
ingless situation, |
| 289 // and will confuse and cause problems in other parts of the code. | 286 // and will confuse and cause problems in other parts of the code. |
| 290 if (!computedColumnHeight()) | 287 if (!computedColumnHeight()) |
| 291 return 1; | 288 return 1; |
| 292 | 289 |
| 293 // Our portion rect determines our column count. We have as many columns as
needed to fit all the content. | 290 // Our portion rect determines our column count. We have as many columns as
needed to fit all the content. |
| 294 LayoutUnit logicalHeightInColumns = flowThread()->isHorizontalWritingMode()
? flowThreadPortionRect().height() : flowThreadPortionRect().width(); | 291 LayoutUnit logicalHeightInColumns = flowThread()->isHorizontalWritingMode()
? flowThreadPortionRect().height() : flowThreadPortionRect().width(); |
| 292 if (!logicalHeightInColumns) |
| 293 return 1; |
| 294 |
| 295 unsigned count = ceil(static_cast<float>(logicalHeightInColumns) / computedC
olumnHeight()); | 295 unsigned count = ceil(static_cast<float>(logicalHeightInColumns) / computedC
olumnHeight()); |
| 296 ASSERT(count >= 1); | 296 ASSERT(count >= 1); |
| 297 return count; | 297 return count; |
| 298 } | 298 } |
| 299 | 299 |
| 300 LayoutRect RenderMultiColumnSet::columnRectAt(unsigned index) const | 300 LayoutRect RenderMultiColumnSet::columnRectAt(unsigned index) const |
| 301 { | 301 { |
| 302 LayoutUnit colLogicalWidth = computedColumnWidth(); | 302 LayoutUnit colLogicalWidth = computedColumnWidth(); |
| 303 LayoutUnit colLogicalHeight = computedColumnHeight(); | 303 LayoutUnit colLogicalHeight = computedColumnHeight(); |
| 304 LayoutUnit colLogicalTop = borderBefore() + paddingBefore(); | 304 LayoutUnit colLogicalTop = borderBefore() + paddingBefore(); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 return; | 397 return; |
| 398 | 398 |
| 399 paintColumnRules(paintInfo, paintOffset); | 399 paintColumnRules(paintInfo, paintOffset); |
| 400 } | 400 } |
| 401 | 401 |
| 402 void RenderMultiColumnSet::paintColumnRules(PaintInfo& paintInfo, const LayoutPo
int& paintOffset) | 402 void RenderMultiColumnSet::paintColumnRules(PaintInfo& paintInfo, const LayoutPo
int& paintOffset) |
| 403 { | 403 { |
| 404 if (paintInfo.context->paintingDisabled()) | 404 if (paintInfo.context->paintingDisabled()) |
| 405 return; | 405 return; |
| 406 | 406 |
| 407 RenderStyle* blockStyle = toRenderMultiColumnBlock(parent())->style(); | 407 RenderStyle* blockStyle = multiColumnBlockFlow()->style(); |
| 408 const Color& ruleColor = resolveColor(blockStyle, CSSPropertyWebkitColumnRul
eColor); | 408 const Color& ruleColor = resolveColor(blockStyle, CSSPropertyWebkitColumnRul
eColor); |
| 409 bool ruleTransparent = blockStyle->columnRuleIsTransparent(); | 409 bool ruleTransparent = blockStyle->columnRuleIsTransparent(); |
| 410 EBorderStyle ruleStyle = blockStyle->columnRuleStyle(); | 410 EBorderStyle ruleStyle = blockStyle->columnRuleStyle(); |
| 411 LayoutUnit ruleThickness = blockStyle->columnRuleWidth(); | 411 LayoutUnit ruleThickness = blockStyle->columnRuleWidth(); |
| 412 LayoutUnit colGap = columnGap(); | 412 LayoutUnit colGap = columnGap(); |
| 413 bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent; | 413 bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent; |
| 414 if (!renderRule) | 414 if (!renderRule) |
| 415 return; | 415 return; |
| 416 | 416 |
| 417 unsigned colCount = columnCount(); | 417 unsigned colCount = columnCount(); |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 fragments.append(fragment); | 584 fragments.append(fragment); |
| 585 } | 585 } |
| 586 } | 586 } |
| 587 | 587 |
| 588 const char* RenderMultiColumnSet::renderName() const | 588 const char* RenderMultiColumnSet::renderName() const |
| 589 { | 589 { |
| 590 return "RenderMultiColumnSet"; | 590 return "RenderMultiColumnSet"; |
| 591 } | 591 } |
| 592 | 592 |
| 593 } | 593 } |
| OLD | NEW |