| 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 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 ASSERT(m_minSpaceShortage > 0); // We should never _shrink_ the height! | 184 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. | 185 ASSERT(m_minSpaceShortage != RenderFlowThread::maxLogicalHeight()); // If th
is happens, we probably have a bug. |
| 186 if (m_minSpaceShortage == RenderFlowThread::maxLogicalHeight()) | 186 if (m_minSpaceShortage == RenderFlowThread::maxLogicalHeight()) |
| 187 return m_columnHeight; // So bail out rather than looping infinitely. | 187 return m_columnHeight; // So bail out rather than looping infinitely. |
| 188 | 188 |
| 189 return m_columnHeight + m_minSpaceShortage; | 189 return m_columnHeight + m_minSpaceShortage; |
| 190 } | 190 } |
| 191 | 191 |
| 192 void RenderMultiColumnSet::addContentRun(LayoutUnit endOffsetFromFirstPage) | 192 void RenderMultiColumnSet::addContentRun(LayoutUnit endOffsetFromFirstPage) |
| 193 { | 193 { |
| 194 if (!multiColumnFlowThread()->requiresBalancing()) | 194 if (!multiColumnFlowThread()->heightIsAuto()) |
| 195 return; | 195 return; |
| 196 if (!m_contentRuns.isEmpty() && endOffsetFromFirstPage <= m_contentRuns.last
().breakOffset()) | 196 if (!m_contentRuns.isEmpty() && endOffsetFromFirstPage <= m_contentRuns.last
().breakOffset()) |
| 197 return; | 197 return; |
| 198 // Append another item as long as we haven't exceeded used column count. Wha
t ends up in the | 198 // 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. | 199 // overflow area shouldn't affect column balancing. |
| 200 if (m_contentRuns.size() < usedColumnCount()) | 200 if (m_contentRuns.size() < usedColumnCount()) |
| 201 m_contentRuns.append(ContentRun(endOffsetFromFirstPage)); | 201 m_contentRuns.append(ContentRun(endOffsetFromFirstPage)); |
| 202 } | 202 } |
| 203 | 203 |
| 204 bool RenderMultiColumnSet::recalculateColumnHeight(BalancedHeightCalculation cal
culationMode) | 204 bool RenderMultiColumnSet::recalculateColumnHeight(BalancedHeightCalculation cal
culationMode) |
| 205 { | 205 { |
| 206 ASSERT(multiColumnFlowThread()->requiresBalancing()); | 206 ASSERT(multiColumnFlowThread()->heightIsAuto()); |
| 207 | 207 |
| 208 LayoutUnit oldColumnHeight = m_columnHeight; | 208 LayoutUnit oldColumnHeight = m_columnHeight; |
| 209 if (calculationMode == GuessFromFlowThreadPortion) { | 209 if (calculationMode == GuessFromFlowThreadPortion) { |
| 210 // Post-process the content runs and find out where the implicit breaks
will occur. | 210 // Post-process the content runs and find out where the implicit breaks
will occur. |
| 211 distributeImplicitBreaks(); | 211 distributeImplicitBreaks(); |
| 212 } | 212 } |
| 213 LayoutUnit newColumnHeight = calculateColumnHeight(calculationMode); | 213 LayoutUnit newColumnHeight = calculateColumnHeight(calculationMode); |
| 214 setAndConstrainColumnHeight(newColumnHeight); | 214 setAndConstrainColumnHeight(newColumnHeight); |
| 215 | 215 |
| 216 // After having calculated an initial column height, the multicol container
typically needs at | 216 // After having calculated an initial column height, the multicol container
typically needs at |
| (...skipping 28 matching lines...) Expand all Loading... |
| 245 | 245 |
| 246 void RenderMultiColumnSet::resetColumnHeight() | 246 void RenderMultiColumnSet::resetColumnHeight() |
| 247 { | 247 { |
| 248 // Nuke previously stored minimum column height. Contents may have changed f
or all we know. | 248 // Nuke previously stored minimum column height. Contents may have changed f
or all we know. |
| 249 m_minimumColumnHeight = 0; | 249 m_minimumColumnHeight = 0; |
| 250 | 250 |
| 251 m_maxColumnHeight = calculateMaxColumnHeight(); | 251 m_maxColumnHeight = calculateMaxColumnHeight(); |
| 252 | 252 |
| 253 LayoutUnit oldColumnHeight = pageLogicalHeight(); | 253 LayoutUnit oldColumnHeight = pageLogicalHeight(); |
| 254 | 254 |
| 255 if (multiColumnFlowThread()->requiresBalancing()) | 255 if (multiColumnFlowThread()->heightIsAuto()) |
| 256 m_columnHeight = 0; | 256 m_columnHeight = 0; |
| 257 else | 257 else |
| 258 setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowTh
read()->columnHeightAvailable())); | 258 setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowTh
read()->columnHeightAvailable())); |
| 259 | 259 |
| 260 if (pageLogicalHeight() != oldColumnHeight) | 260 if (pageLogicalHeight() != oldColumnHeight) |
| 261 setChildNeedsLayout(MarkOnlyThis); | 261 setChildNeedsLayout(MarkOnlyThis); |
| 262 | 262 |
| 263 // Content runs are only needed in the initial layout pass, in order to find
an initial column | 263 // 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 | 264 // height, and should have been deleted afterwards. We're about to rebuild t
he content runs, so |
| 265 // the list needs to be empty. | 265 // the list needs to be empty. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 return count; | 328 return count; |
| 329 } | 329 } |
| 330 | 330 |
| 331 LayoutRect RenderMultiColumnSet::columnRectAt(unsigned index) const | 331 LayoutRect RenderMultiColumnSet::columnRectAt(unsigned index) const |
| 332 { | 332 { |
| 333 LayoutUnit colLogicalWidth = pageLogicalWidth(); | 333 LayoutUnit colLogicalWidth = pageLogicalWidth(); |
| 334 LayoutUnit colLogicalHeight = pageLogicalHeight(); | 334 LayoutUnit colLogicalHeight = pageLogicalHeight(); |
| 335 LayoutUnit colLogicalTop = borderBefore() + paddingBefore(); | 335 LayoutUnit colLogicalTop = borderBefore() + paddingBefore(); |
| 336 LayoutUnit colLogicalLeft = borderAndPaddingLogicalLeft(); | 336 LayoutUnit colLogicalLeft = borderAndPaddingLogicalLeft(); |
| 337 LayoutUnit colGap = columnGap(); | 337 LayoutUnit colGap = columnGap(); |
| 338 if (style()->isLeftToRightDirection()) | 338 |
| 339 colLogicalLeft += index * (colLogicalWidth + colGap); | 339 if (multiColumnFlowThread()->progressionIsInline()) { |
| 340 else | 340 if (style()->isLeftToRightDirection()) |
| 341 colLogicalLeft += contentLogicalWidth() - colLogicalWidth - index * (col
LogicalWidth + colGap); | 341 colLogicalLeft += index * (colLogicalWidth + colGap); |
| 342 else |
| 343 colLogicalLeft += contentLogicalWidth() - colLogicalWidth - index *
(colLogicalWidth + colGap); |
| 344 } else { |
| 345 colLogicalTop += index * (colLogicalHeight + colGap); |
| 346 } |
| 342 | 347 |
| 343 if (isHorizontalWritingMode()) | 348 if (isHorizontalWritingMode()) |
| 344 return LayoutRect(colLogicalLeft, colLogicalTop, colLogicalWidth, colLog
icalHeight); | 349 return LayoutRect(colLogicalLeft, colLogicalTop, colLogicalWidth, colLog
icalHeight); |
| 345 return LayoutRect(colLogicalTop, colLogicalLeft, colLogicalHeight, colLogica
lWidth); | 350 return LayoutRect(colLogicalTop, colLogicalLeft, colLogicalHeight, colLogica
lWidth); |
| 346 } | 351 } |
| 347 | 352 |
| 348 unsigned RenderMultiColumnSet::columnIndexAtOffset(LayoutUnit offset, ColumnInde
xCalculationMode mode) const | 353 unsigned RenderMultiColumnSet::columnIndexAtOffset(LayoutUnit offset, ColumnInde
xCalculationMode mode) const |
| 349 { | 354 { |
| 350 LayoutRect portionRect(flowThreadPortionRect()); | 355 LayoutRect portionRect(flowThreadPortionRect()); |
| 351 | 356 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 return; | 433 return; |
| 429 | 434 |
| 430 paintColumnRules(paintInfo, paintOffset); | 435 paintColumnRules(paintInfo, paintOffset); |
| 431 } | 436 } |
| 432 | 437 |
| 433 void RenderMultiColumnSet::paintColumnRules(PaintInfo& paintInfo, const LayoutPo
int& paintOffset) | 438 void RenderMultiColumnSet::paintColumnRules(PaintInfo& paintInfo, const LayoutPo
int& paintOffset) |
| 434 { | 439 { |
| 435 if (paintInfo.context->paintingDisabled()) | 440 if (paintInfo.context->paintingDisabled()) |
| 436 return; | 441 return; |
| 437 | 442 |
| 443 if (flowThread()->isRenderPagedFlowThread()) |
| 444 return; |
| 445 |
| 438 RenderStyle* blockStyle = multiColumnBlockFlow()->style(); | 446 RenderStyle* blockStyle = multiColumnBlockFlow()->style(); |
| 439 const Color& ruleColor = resolveColor(blockStyle, CSSPropertyWebkitColumnRul
eColor); | 447 const Color& ruleColor = resolveColor(blockStyle, CSSPropertyWebkitColumnRul
eColor); |
| 440 bool ruleTransparent = blockStyle->columnRuleIsTransparent(); | 448 bool ruleTransparent = blockStyle->columnRuleIsTransparent(); |
| 441 EBorderStyle ruleStyle = blockStyle->columnRuleStyle(); | 449 EBorderStyle ruleStyle = blockStyle->columnRuleStyle(); |
| 442 LayoutUnit ruleThickness = blockStyle->columnRuleWidth(); | 450 LayoutUnit ruleThickness = blockStyle->columnRuleWidth(); |
| 443 LayoutUnit colGap = columnGap(); | 451 LayoutUnit colGap = columnGap(); |
| 444 bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent; | 452 bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent; |
| 445 if (!renderRule) | 453 if (!renderRule) |
| 446 return; | 454 return; |
| 447 | 455 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 | 565 |
| 558 // Figure out the start and end columns and only check within that range so
that we don't walk the | 566 // Figure out the start and end columns and only check within that range so
that we don't walk the |
| 559 // entire column set. | 567 // entire column set. |
| 560 unsigned startColumn = columnIndexAtOffset(layerLogicalTop); | 568 unsigned startColumn = columnIndexAtOffset(layerLogicalTop); |
| 561 unsigned endColumn = columnIndexAtOffset(layerLogicalBottom); | 569 unsigned endColumn = columnIndexAtOffset(layerLogicalBottom); |
| 562 | 570 |
| 563 LayoutUnit colLogicalWidth = pageLogicalWidth(); | 571 LayoutUnit colLogicalWidth = pageLogicalWidth(); |
| 564 LayoutUnit colGap = columnGap(); | 572 LayoutUnit colGap = columnGap(); |
| 565 unsigned colCount = actualColumnCount(); | 573 unsigned colCount = actualColumnCount(); |
| 566 | 574 |
| 575 RenderMultiColumnFlowThread* flowThread = multiColumnFlowThread(); |
| 576 bool progressionIsInline = flowThread->progressionIsInline(); |
| 577 bool leftToRight = style()->isLeftToRightDirection(); |
| 578 |
| 579 LayoutUnit initialBlockOffset = logicalTop() - flowThread->logicalTop(); |
| 580 |
| 567 for (unsigned i = startColumn; i <= endColumn; i++) { | 581 for (unsigned i = startColumn; i <= endColumn; i++) { |
| 568 // Get the portion of the flow thread that corresponds to this column. | 582 // Get the portion of the flow thread that corresponds to this column. |
| 569 LayoutRect flowThreadPortion = flowThreadPortionRectAt(i); | 583 LayoutRect flowThreadPortion = flowThreadPortionRectAt(i); |
| 570 | 584 |
| 571 // Now get the overflow rect that corresponds to the column. | 585 // Now get the overflow rect that corresponds to the column. |
| 572 LayoutRect flowThreadOverflowPortion = flowThreadPortionOverflowRect(flo
wThreadPortion, i, colCount, colGap); | 586 LayoutRect flowThreadOverflowPortion = flowThreadPortionOverflowRect(flo
wThreadPortion, i, colCount, colGap); |
| 573 | 587 |
| 574 // In order to create a fragment we must intersect the portion painted b
y this column. | 588 // In order to create a fragment we must intersect the portion painted b
y this column. |
| 575 LayoutRect clippedRect(layerBoundsInFlowThread); | 589 LayoutRect clippedRect(layerBoundsInFlowThread); |
| 576 clippedRect.intersect(flowThreadOverflowPortion); | 590 clippedRect.intersect(flowThreadOverflowPortion); |
| 577 if (clippedRect.isEmpty()) | 591 if (clippedRect.isEmpty()) |
| 578 continue; | 592 continue; |
| 579 | 593 |
| 580 // We also need to intersect the dirty rect. We have to apply a translat
ion and shift based off | 594 // We also need to intersect the dirty rect. We have to apply a translat
ion and shift based off |
| 581 // our column index. | 595 // our column index. |
| 582 LayoutPoint translationOffset; | 596 LayoutPoint translationOffset; |
| 583 LayoutUnit inlineOffset = i * (colLogicalWidth + colGap); | 597 LayoutUnit inlineOffset = progressionIsInline ? i * (colLogicalWidth + c
olGap) : LayoutUnit(); |
| 584 if (!style()->isLeftToRightDirection()) | 598 if (!leftToRight) |
| 585 inlineOffset = -inlineOffset; | 599 inlineOffset = -inlineOffset; |
| 586 translationOffset.setX(inlineOffset); | 600 translationOffset.setX(inlineOffset); |
| 587 LayoutUnit blockOffset = isHorizontalWritingMode() ? -flowThreadPortion.
y() : -flowThreadPortion.x(); | 601 LayoutUnit blockOffset; |
| 602 if (progressionIsInline) { |
| 603 blockOffset = initialBlockOffset + (isHorizontalWritingMode() ? -flo
wThreadPortion.y() : -flowThreadPortion.x()); |
| 604 } else { |
| 605 // Column gap can apply in the block direction for page fragmentaine
rs. |
| 606 // There is currently no spec which calls for column-gap to apply |
| 607 // for page fragmentainers at all, but it's applied here for compati
bility |
| 608 // with the old multicolumn implementation. |
| 609 blockOffset = i * colGap; |
| 610 } |
| 588 if (isFlippedBlocksWritingMode(style()->writingMode())) | 611 if (isFlippedBlocksWritingMode(style()->writingMode())) |
| 589 blockOffset = -blockOffset; | 612 blockOffset = -blockOffset; |
| 590 translationOffset.setY(blockOffset); | 613 translationOffset.setY(blockOffset); |
| 591 if (!isHorizontalWritingMode()) | 614 if (!isHorizontalWritingMode()) |
| 592 translationOffset = translationOffset.transposedPoint(); | 615 translationOffset = translationOffset.transposedPoint(); |
| 593 // FIXME: The translation needs to include the multicolumn set's content
offset within the | 616 // FIXME: The translation needs to include the multicolumn set's content
offset within the |
| 594 // multicolumn block as well. This won't be an issue until we start crea
ting multiple multicolumn sets. | 617 // multicolumn block as well. This won't be an issue until we start crea
ting multiple multicolumn sets. |
| 595 | 618 |
| 596 // Shift the dirty rect to be in flow thread coordinates with this trans
lation applied. | 619 // Shift the dirty rect to be in flow thread coordinates with this trans
lation applied. |
| 597 LayoutRect translatedDirtyRect(dirtyRect); | 620 LayoutRect translatedDirtyRect(dirtyRect); |
| 598 translatedDirtyRect.moveBy(-translationOffset); | 621 translatedDirtyRect.moveBy(-translationOffset); |
| 599 | 622 |
| 600 // See if we intersect the dirty rect. | 623 // See if we intersect the dirty rect. |
| 601 clippedRect = layerBoundingBox; | 624 clippedRect = layerBoundingBox; |
| 602 clippedRect.intersect(translatedDirtyRect); | 625 clippedRect.intersect(translatedDirtyRect); |
| 603 if (clippedRect.isEmpty()) | 626 if (clippedRect.isEmpty()) |
| 604 continue; | 627 continue; |
| 605 | 628 |
| 606 // Something does need to paint in this column. Make a fragment now and
supply the physical translation | 629 // Something does need to paint in this column. Make a fragment now and
supply the physical translation |
| 607 // offset and the clip rect for the column with that offset applied. | 630 // offset and the clip rect for the column with that offset applied. |
| 608 LayerFragment fragment; | 631 LayerFragment fragment; |
| 609 fragment.paginationOffset = translationOffset; | 632 fragment.paginationOffset = translationOffset; |
| 610 | 633 |
| 611 LayoutRect flippedFlowThreadOverflowPortion(flowThreadOverflowPortion); | 634 LayoutRect flippedFlowThreadOverflowPortion(flowThreadOverflowPortion); |
| 612 // Flip it into more a physical (RenderLayer-style) rectangle. | 635 // Flip it into more a physical (RenderLayer-style) rectangle. |
| 613 flowThread()->flipForWritingMode(flippedFlowThreadOverflowPortion); | 636 flowThread->flipForWritingMode(flippedFlowThreadOverflowPortion); |
| 614 fragment.paginationClip = flippedFlowThreadOverflowPortion; | 637 fragment.paginationClip = flippedFlowThreadOverflowPortion; |
| 615 fragments.append(fragment); | 638 fragments.append(fragment); |
| 616 } | 639 } |
| 617 } | 640 } |
| 618 | 641 |
| 619 void RenderMultiColumnSet::addOverflowFromChildren() | 642 void RenderMultiColumnSet::addOverflowFromChildren() |
| 620 { | 643 { |
| 621 unsigned colCount = actualColumnCount(); | 644 unsigned colCount = actualColumnCount(); |
| 622 if (!colCount) | 645 if (!colCount) |
| 623 return; | 646 return; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 | 687 |
| 665 void RenderMultiColumnSet::detachRegion() | 688 void RenderMultiColumnSet::detachRegion() |
| 666 { | 689 { |
| 667 if (m_flowThread) { | 690 if (m_flowThread) { |
| 668 m_flowThread->removeRegionFromThread(this); | 691 m_flowThread->removeRegionFromThread(this); |
| 669 m_flowThread = 0; | 692 m_flowThread = 0; |
| 670 } | 693 } |
| 671 } | 694 } |
| 672 | 695 |
| 673 } | 696 } |
| OLD | NEW |