Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(601)

Side by Side Diff: Source/core/rendering/RenderMultiColumnSet.cpp

Issue 364233005: [New Multicolumn] Support for paged overflow. (By mstensho). (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Run fast/pagination in virtual/regionbasedmulticol. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « Source/core/rendering/RenderMultiColumnFlowThread.cpp ('k') | Source/core/rendering/RenderPagedFlowThread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698