Changeset 140014 in webkit
- Timestamp:
- Jan 17, 2013 11:35:41 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 18 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r140010 r140014 1 2013-01-17 Andrei Bucur <abucur@adobe.com> 2 3 [CSS Regions] Content flows incorrectly in autoheight regions with min/max-height set 4 https://bugs.webkit.org/show_bug.cgi?id=102099 5 6 Reviewed by David Hyatt. 7 8 All the tests have a description about how the breaking should happen. They pass if the height of the region chain is 9 correctly computed by using the max-height, min-height, height and writing mode conditions. 10 11 * fast/regions/autoheight-maxheight-mixed-break-expected.txt: Added. 12 * fast/regions/autoheight-maxheight-mixed-break.html: Added. 13 * fast/regions/autoheight-maxheight-simple-break-expected.txt: Added. 14 * fast/regions/autoheight-maxheight-simple-break.html: Added. 15 * fast/regions/autoheight-maxheight-simple-nobreak-expected.txt: Added. 16 * fast/regions/autoheight-maxheight-simple-nobreak.html: Added. 17 * fast/regions/autoheight-minmaxheight-mixed-break-expected.txt: Added. 18 * fast/regions/autoheight-minmaxheight-mixed-break-hbt-expected.txt: Added. 19 * fast/regions/autoheight-minmaxheight-mixed-break-hbt.html: Added. 20 * fast/regions/autoheight-minmaxheight-mixed-break-vlr-expected.txt: Added. 21 * fast/regions/autoheight-minmaxheight-mixed-break-vlr.html: Added. 22 * fast/regions/autoheight-minmaxheight-mixed-break-vrl-expected.txt: Added. 23 * fast/regions/autoheight-minmaxheight-mixed-break-vrl.html: Added. 24 * fast/regions/autoheight-minmaxheight-mixed-break.html: Added. 25 * fast/regions/autoheight-minmaxheight-simple-break-expected.txt: Added. 26 * fast/regions/autoheight-minmaxheight-simple-break.html: Added. 27 * fast/regions/autoheight-minmaxheight-simple-nobreak-expected.txt: Added. 28 * fast/regions/autoheight-minmaxheight-simple-nobreak.html: Added. 29 1 30 2013-01-17 Alexis Menard <alexis@webkit.org> 2 31 -
trunk/Source/WebCore/ChangeLog
r140012 r140014 1 2013-01-17 Andrei Bucur <abucur@adobe.com> 2 3 [CSS Regions] Content flows incorrectly in autoheight regions with min/max-height set 4 https://bugs.webkit.org/show_bug.cgi?id=102099 5 6 Reviewed by David Hyatt. 7 8 The current layout algorithm for auto-height regions is gives wrong results when the max-height property is set on them. The reason is we 9 consider the max-height restriction too late in the layout, when applying a forced break. This is what happens when content is laid out 10 in an auto-height region. 11 1. The content flows without a limit until a forced break appears. If there's no forced break in the content, one is forced anyway at the end 12 of the layout. 13 2. The region where the forced break is placed is not always the one where content is laid out because of max-height restrictions. 14 3. All the regions with max-height are iterated and their height accumulated until the break offset is reached and the region at that point is ended. 15 This gives wrong results because the forced break position in the content was computed assuming there's only one region where the content is laid out. 16 The regions with max-height could have generated unforced breaks at their height and the forced break actually should have a different position. 17 18 This patch changes the algorithm in this way: 19 1. From the flow thread perspective all the regions start with a height: max-height for auto-height regions (or LayoutSize.max()/2 if not defined) 20 or the fixed height value when specified. 21 2. When the content is laid out, if there's no forced break, the height of the content is correctly estimated because the layout sees unforced breaks 22 at the max-height values. 23 3. If a forced break appears, the affected region can be obtained only by looking at the break offset in the region chain. If the region has auto-height, 24 its height is updated by the forced break. 25 4. At the end of the layout, there's the additional task to clear the height of all the regions that didn't receive content. This can be done optimally 26 without adding a new iteration through the regions by attaching to the RegionOverset computation loop. 27 28 Tests: fast/regions/autoheight-maxheight-mixed-break.html 29 fast/regions/autoheight-maxheight-simple-break.html 30 fast/regions/autoheight-maxheight-simple-nobreak.html 31 fast/regions/autoheight-minmaxheight-mixed-break-hbt.html 32 fast/regions/autoheight-minmaxheight-mixed-break-vlr.html 33 fast/regions/autoheight-minmaxheight-mixed-break-vrl.html 34 fast/regions/autoheight-minmaxheight-mixed-break.html 35 fast/regions/autoheight-minmaxheight-simple-break.html 36 fast/regions/autoheight-minmaxheight-simple-nobreak.html 37 38 * rendering/RenderFlowThread.cpp: 39 (WebCore::RenderFlowThread::layout): 40 (WebCore::RenderFlowThread::computeLogicalHeight): 41 (WebCore::RenderFlowThread::regionAtBlockOffset): 42 (WebCore::RenderFlowThread::pageLogicalHeightForOffset): 43 (WebCore::RenderFlowThread::pageRemainingLogicalHeightForOffset): 44 (WebCore::RenderFlowThread::computeOverflowStateForRegions): Attach to the loop in this function to clear the overrideLogicalHeight on empty regions. 45 (WebCore): 46 (WebCore::RenderFlowThread::updateRegionsFlowThreadPortionRect): Add an ASSERT that a region always has overrideLogicalHeight or a fixed height. 47 (WebCore::RenderFlowThread::initializeRegionsOverrideLogicalContentHeight): A new function that updates the region chain height to use the max-height value 48 for auto-height regions. 49 (WebCore::RenderFlowThread::addForcedRegionBreak): 50 * rendering/RenderFlowThread.h: 51 * rendering/RenderRegion.cpp: 52 (WebCore::RenderRegion::pageLogicalHeight): the decorations size is incorrectly considered in the page height. 53 (WebCore): 54 (WebCore::RenderRegion::maxPageLogicalHeight): new function that returns the max page size for a region. It shouldn't be called too often 55 or the returned value can be cached 56 (WebCore::RenderRegion::logicalHeightOfAllFlowThreadContent): the decorations size is incorrectly considered in the logical height of 57 the flow thread content. 58 * rendering/RenderRegion.h: 59 (RenderRegion): 60 61 1 62 2013-01-17 Vsevolod Vlasov <vsevik@chromium.org> 2 63 -
trunk/Source/WebCore/rendering/RenderFlowThread.cpp
r139920 r140014 154 154 region->deleteAllRenderBoxRegionInfo(); 155 155 156 // In the normal layout phase we need to initialize the overrideLogicalContentHeight for auto-height regions. 157 // See initializeRegionsOverrideLogicalContentHeight for the explanation. 158 // Also, if we have auto-height regions we can't assume m_regionsHaveUniformLogicalHeight to be true in the first phase 159 // because the auto-height regions don't have their height computed yet. 160 if (view()->normalLayoutPhase() && region->hasAutoLogicalHeight()) { 161 region->setOverrideLogicalContentHeight(region->maxPageLogicalHeight()); 162 m_regionsHaveUniformLogicalHeight = false; 163 } 164 156 165 LayoutUnit regionLogicalWidth = region->pageLogicalWidth(); 157 166 LayoutUnit regionLogicalHeight = region->pageLogicalHeight(); … … 215 224 RenderRegion* region = *iter; 216 225 ASSERT(!region->needsLayout()); 217 218 if (region->needsOverrideLogicalContentHeightComputation()) {219 // If we have an auto logical height region for which we did not compute a height yet,220 // then we cannot compute and update the height of this flow.221 return;222 }223 226 224 227 computedValues.m_extent += region->logicalHeightOfAllFlowThreadContent(); … … 347 350 lastValidRegion = region; 348 351 349 // If we did not compute the region's height, we should consider this region350 // tall enough to accomodate all content.351 if (region->needsOverrideLogicalContentHeightComputation())352 return region;353 354 352 if (region->hasOverrideHeight() && view()->normalLayoutPhase()) { 355 353 accumulatedLogicalHeight += region->overrideLogicalContentHeight(); … … 385 383 if (!region) 386 384 return 0; 387 if (region->needsOverrideLogicalContentHeightComputation()) 388 return LayoutUnit::max() / 2; 385 389 386 return region->pageLogicalHeight(); 390 387 } … … 395 392 if (!region) 396 393 return 0; 397 if (region->needsOverrideLogicalContentHeightComputation())398 return LayoutUnit::max() / 2;399 394 400 395 LayoutUnit pageLogicalTop = region->pageLogicalTopForOffset(offset); … … 615 610 LayoutUnit height = oldClientAfterEdge; 616 611 612 LayoutUnit offsetBreakAdjustment = 0; 617 613 // Simulate a region break at height. If it points inside an auto logical height region, 618 614 // then it may determine the region override logical content height. 619 addForcedRegionBreak(height, this, false); 615 addForcedRegionBreak(height, this, false, &offsetBreakAdjustment); 616 617 // During the normal layout phase of the flow thread all the auto-height regions have the overrideLogicalContentHeight set to max height. 618 // We need to clear the overrideLogicalContentHeight for all the regions that didn't receive any content, starting with firstEmptyRegion. 619 RenderRegion* firstEmptyRegion = 0; 620 if (view()->normalLayoutPhase()) 621 firstEmptyRegion = regionAtBlockOffset(height + offsetBreakAdjustment); 620 622 621 623 // FIXME: the visual overflow of middle region (if it is the last one to contain any content in a render flow thread) … … 628 630 height = isHorizontalWritingMode() ? visualOverflowRect().maxY() : visualOverflowRect().maxX(); 629 631 632 bool inEmptyRegionsSection = false; 630 633 RenderRegion* lastReg = lastRegion(); 631 634 for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) { … … 647 650 || state == RenderRegion::RegionOverset) 648 651 setDispatchRegionLayoutUpdateEvent(true); 652 653 if (region == firstEmptyRegion) 654 inEmptyRegionsSection = true; 655 656 // Clear the overrideLogicalContentHeight value for autoheight regions that didn't receive any content. 657 if (inEmptyRegionsSection && region->hasAutoLogicalHeight()) 658 region->clearOverrideLogicalContentHeight(); 649 659 } 650 660 … … 771 781 } 772 782 783 // During the normal layout phase of the named flow the regions are initialized with a height equal to their max-height. 784 // This way unforced breaks are automatically placed when a region is full and the content height/position correctly estimated. 785 // Also, the region where a forced break falls is exactly the region found at the forced break offset inside the flow content. 786 void RenderFlowThread::initializeRegionsOverrideLogicalContentHeight(RenderRegion* startRegion) 787 { 788 ASSERT(view()->normalLayoutPhase()); 789 RenderRegionList::iterator regionIter = startRegion ? m_regionList.find(startRegion) : m_regionList.begin(); 790 for (; regionIter != m_regionList.end(); ++regionIter) { 791 RenderRegion* region = *regionIter; 792 if (region->hasAutoLogicalHeight()) 793 region->setOverrideLogicalContentHeight(region->maxPageLogicalHeight()); 794 } 795 } 796 773 797 void RenderFlowThread::markAutoLogicalHeightRegionsForLayout() 774 798 { … … 810 834 // logical height region, will be able to fragment the right part of their 811 835 // associated flow thread content (and compute their overrideComputedLogicalHeight properly). 812 if (region->hasOverrideHeight() && view()->normalLayoutPhase()) { 813 regionLogicalHeight = region->overrideLogicalContentHeight(); 836 if (view()->normalLayoutPhase()) { 837 ASSERT(region->hasOverrideHeight() || !region->hasAutoLogicalHeight()); 838 if (region->hasOverrideHeight()) 839 regionLogicalHeight = region->overrideLogicalContentHeight(); 840 814 841 regionRect.setHeight(regionLogicalHeight); 815 842 } … … 817 844 region->setFlowThreadPortionRect(isHorizontalWritingMode() ? regionRect : regionRect.transposedRect()); 818 845 logicalHeight += regionLogicalHeight; 819 }820 }821 822 void RenderFlowThread::clearOverrideLogicalContentHeightInRegions(RenderRegion* startRegion)823 {824 RenderRegionList::iterator regionIter = startRegion ? m_regionList.find(startRegion) : m_regionList.begin();825 for (; regionIter != m_regionList.end(); ++regionIter) {826 RenderRegion* region = *regionIter;827 if (region->hasAutoLogicalHeight())828 region->clearOverrideLogicalContentHeight();829 846 } 830 847 } … … 851 868 ASSERT(regionIter != m_regionList.end()); 852 869 ASSERT((*regionIter)->hasAutoLogicalHeight()); 853 clearOverrideLogicalContentHeightInRegions(*regionIter);870 initializeRegionsOverrideLogicalContentHeight(*regionIter); 854 871 855 872 // We need to update the regions flow thread portion rect because we are going to process … … 864 881 return false; 865 882 866 // We want to distribute the offsetBreakInFlowThread content among the regions starting with the found region.867 883 bool overrideLogicalContentHeightComputed = false; 868 884 … … 870 886 LayoutUnit offsetBreakInCurrentRegion = offsetBreakInFlowThread - currentRegionOffsetInFlowThread; 871 887 872 RenderRegionList::iterator regionIter = m_regionList.find(region); 873 ASSERT(regionIter != m_regionList.end()); 874 for (; regionIter != m_regionList.end(); ++regionIter) { 875 RenderRegion* region = *regionIter; 876 if (region->needsOverrideLogicalContentHeightComputation()) { 877 mapToUse.set(breakChild, region); 878 879 overrideLogicalContentHeightComputed = true; 880 881 // Compute the region height pretending that the offsetBreakInCurrentRegion is the logicalHeight for the auto-height region. 882 LayoutUnit regionOverrideLogicalContentHeight = region->computeReplacedLogicalHeightRespectingMinMaxHeight(offsetBreakInCurrentRegion); 883 region->setOverrideLogicalContentHeight(regionOverrideLogicalContentHeight); 884 885 offsetBreakInCurrentRegion -= regionOverrideLogicalContentHeight; 886 currentRegionOffsetInFlowThread += regionOverrideLogicalContentHeight; 887 } else 888 currentRegionOffsetInFlowThread += isHorizontalWritingMode() ? region->flowThreadPortionRect().height() : region->flowThreadPortionRect().width(); 889 890 // If the current offset if greater than the break offset, bail out and skip the current region. 891 if (currentRegionOffsetInFlowThread >= offsetBreakInFlowThread) { 892 ++regionIter; 893 break; 894 } 895 } 896 897 // The remaining auto logical height regions in the chain that were unable to receive content 898 // and set their overrideLogicalContentHeight should have their associated values cleared. 899 if (regionIter != m_regionList.end()) 900 clearOverrideLogicalContentHeightInRegions(*regionIter); 901 888 if (region->hasAutoLogicalHeight()) { 889 // A forced break can appear only in an auto-height region that didn't have a forced break before. 890 // This ASSERT is a good-enough heuristic to verify the above condition. 891 ASSERT(region->maxPageLogicalHeight() == region->overrideLogicalContentHeight()); 892 893 mapToUse.set(breakChild, region); 894 895 overrideLogicalContentHeightComputed = true; 896 897 // Compute the region height pretending that the offsetBreakInCurrentRegion is the logicalHeight for the auto-height region. 898 LayoutUnit regionOverrideLogicalContentHeight = region->computeReplacedLogicalHeightRespectingMinMaxHeight(offsetBreakInCurrentRegion); 899 900 // The new height of this region needs to be smaller than the initial value, the max height. A forced break is the only way to change the initial 901 // height of an auto-height region besides content ending. 902 ASSERT(regionOverrideLogicalContentHeight <= region->maxPageLogicalHeight()); 903 904 region->setOverrideLogicalContentHeight(regionOverrideLogicalContentHeight); 905 906 currentRegionOffsetInFlowThread += regionOverrideLogicalContentHeight; 907 } else 908 currentRegionOffsetInFlowThread += isHorizontalWritingMode() ? region->flowThreadPortionRect().height() : region->flowThreadPortionRect().width(); 909 910 // If the break was found inside an auto-height region its size changed so we need to recompute the flow thread portion rectangles. 902 911 if (overrideLogicalContentHeightComputed) 903 912 updateRegionsFlowThreadPortionRect(); -
trunk/Source/WebCore/rendering/RenderFlowThread.h
r139920 r140014 155 155 virtual void dispatchRegionLayoutUpdateEvent() { m_dispatchRegionLayoutUpdateEvent = false; } 156 156 157 void clearOverrideLogicalContentHeightInRegions(RenderRegion* startRegion= 0);157 void initializeRegionsOverrideLogicalContentHeight(RenderRegion* = 0); 158 158 159 159 RenderRegionList m_regionList; -
trunk/Source/WebCore/rendering/RenderRegion.cpp
r139920 r140014 63 63 { 64 64 if (hasOverrideHeight() && view()->normalLayoutPhase()) 65 return overrideLogicalContentHeight() + borderAndPaddingLogicalHeight();65 return overrideLogicalContentHeight(); 66 66 return m_flowThread->isHorizontalWritingMode() ? contentHeight() : contentWidth(); 67 67 } 68 68 69 // This method returns the maximum page size of a region with auto-height. This is the initial 70 // height value for auto-height regions in the first layout phase of the parent named flow. 71 LayoutUnit RenderRegion::maxPageLogicalHeight() const 72 { 73 ASSERT(hasAutoLogicalHeight() && view()->normalLayoutPhase()); 74 return style()->logicalMaxHeight().isUndefined() ? LayoutUnit::max() / 2 : computeReplacedLogicalHeightUsing(MaxSize, style()->logicalMaxHeight()); 75 } 76 69 77 LayoutUnit RenderRegion::logicalHeightOfAllFlowThreadContent() const 70 78 { 71 79 if (hasOverrideHeight() && view()->normalLayoutPhase()) 72 return overrideLogicalContentHeight() + borderAndPaddingLogicalHeight();80 return overrideLogicalContentHeight(); 73 81 return m_flowThread->isHorizontalWritingMode() ? contentHeight() : contentWidth(); 74 82 } … … 613 621 } 614 622 615 bool RenderRegion::needsOverrideLogicalContentHeightComputation() const616 {617 return hasAutoLogicalHeight() && view()->normalLayoutPhase() && !hasOverrideHeight();618 }619 620 623 } // namespace WebCore -
trunk/Source/WebCore/rendering/RenderRegion.h
r139920 r140014 99 99 virtual LayoutUnit pageLogicalWidth() const; 100 100 virtual LayoutUnit pageLogicalHeight() const; 101 LayoutUnit maxPageLogicalHeight() const; 101 102 102 103 virtual LayoutUnit minPreferredLogicalWidth() const OVERRIDE; … … 116 117 117 118 bool hasAutoLogicalHeight() const { return m_hasAutoLogicalHeight; } 118 119 bool needsOverrideLogicalContentHeightComputation() const;120 119 121 120 virtual void updateLogicalHeight() OVERRIDE;
Note: See TracChangeset
for help on using the changeset viewer.