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 |