Changeset 96149 in webkit
- Timestamp:
- Sep 27, 2011 1:39:57 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r96146 r96149 1 2011-09-27 David Hyatt <hyatt@apple.com> 2 3 https://bugs.webkit.org/show_bug.cgi?id=68922 4 5 Paginated floats should not grow the height of a block when they don't end 6 up being tied to a line. 7 8 Reviewed by Dan Bernstein. 9 10 * fast/multicol/float-paginate-empty-lines.html: Added. 11 * fast/regions/webkit-flow-double-pagination-float-push.html: Added. 12 * platform/mac/fast/multicol/float-paginate-empty-lines-expected.png: Added. 13 * platform/mac/fast/regions/webkit-flow-double-pagination-float-push-expected.png: Added. 14 * platform/mac/fast/regions/webkit-flow-double-pagination-float-push-expected.txt: Added. 15 1 16 2011-09-27 Sheriff Bot <webkit.review.bot@gmail.com> 2 17 -
trunk/Source/WebCore/ChangeLog
r96142 r96149 1 2011-09-27 David Hyatt <hyatt@apple.com> 2 3 https://bugs.webkit.org/show_bug.cgi?id=68922 4 5 Paginated floats should not grow the height of a block when they don't end 6 up being tied to a line. Floats encountered in skipLeadingWhitespace that 7 paginate can't immediately grow the height of the block, since there may not 8 end up being any actual line content. We only want to push the height of the 9 block down if we have actual line content that we want to keep with the 10 float. 11 12 Make positionNewFloatOnLine check if the line is empty or not, and if it is, 13 it just puts the desired pagination strut into LineInfo. If and when actual 14 line content is encountered and setEmpty becomes false, we'll grow the block 15 height then. 16 17 Reviewed by Dan Bernstein. 18 19 Added fast/multicol/float-paginate-empty-lines.html and 20 fast/regions/webkit-flow-double-pagination-float-push.html. 21 22 * rendering/RenderBlock.h: 23 * rendering/RenderBlockLineLayout.cpp: 24 (WebCore::LineWidth::LineWidth): 25 (WebCore::LineWidth::fitsOnLine): 26 (WebCore::LineWidth::currentWidth): 27 (WebCore::LineWidth::uncommittedWidth): 28 (WebCore::LineWidth::committedWidth): 29 (WebCore::LineWidth::availableWidth): 30 (WebCore::LineWidth::addUncommittedWidth): 31 (WebCore::LineWidth::commit): 32 (WebCore::LineWidth::computeAvailableWidthFromLeftAndRight): 33 (WebCore::LineWidth::updateAvailableWidth): 34 (WebCore::LineWidth::shrinkAvailableWidthForNewFloatIfNeeded): 35 (WebCore::LineWidth::applyOverhang): 36 (WebCore::LineWidth::fitBelowFloats): 37 (WebCore::LineInfo::LineInfo): 38 (WebCore::LineInfo::floatPaginationStrut): 39 (WebCore::LineInfo::setEmpty): 40 (WebCore::LineInfo::setFloatPaginationStrut): 41 (WebCore::RenderBlock::LineBreaker::skipLeadingWhitespace): 42 (WebCore::RenderBlock::LineBreaker::nextLineBreak): 43 (WebCore::RenderBlock::positionNewFloatOnLine): 44 1 45 2011-09-27 Dean Jackson <dino@apple.com> 2 46 -
trunk/Source/WebCore/rendering/RenderBlock.h
r95856 r96149 579 579 580 580 void skipTrailingWhitespace(InlineIterator&, const LineInfo&); 581 void skipLeadingWhitespace(InlineBidiResolver&, constLineInfo&, FloatingObject* lastFloatFromPreviousLine, LineWidth&);581 void skipLeadingWhitespace(InlineBidiResolver&, LineInfo&, FloatingObject* lastFloatFromPreviousLine, LineWidth&); 582 582 583 583 RenderBlock* m_block; … … 605 605 // Positions new floats and also adjust all floats encountered on the line if any of them 606 606 // have to move to the next page/column. 607 bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, Line Width&);607 bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&); 608 608 void appendFloatingObjectToLastLine(FloatingObject*); 609 609 -
trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp
r95855 r96149 61 61 const unsigned cMaxLineDepth = 200; 62 62 63 class LineWidth { 64 public: 65 LineWidth(RenderBlock* block, bool isFirstLine) 66 : m_block(block) 67 , m_uncommittedWidth(0) 68 , m_committedWidth(0) 69 , m_overhangWidth(0) 70 , m_left(0) 71 , m_right(0) 72 , m_availableWidth(0) 73 , m_isFirstLine(isFirstLine) 74 { 75 ASSERT(block); 76 updateAvailableWidth(); 77 } 78 bool fitsOnLine() const { return currentWidth() <= m_availableWidth; } 79 bool fitsOnLine(float extra) const { return currentWidth() + extra <= m_availableWidth; } 80 float currentWidth() const { return m_committedWidth + m_uncommittedWidth; } 81 82 // FIXME: We should eventually replace these three functions by ones that work on a higher abstraction. 83 float uncommittedWidth() const { return m_uncommittedWidth; } 84 float committedWidth() const { return m_committedWidth; } 85 float availableWidth() const { return m_availableWidth; } 86 87 void updateAvailableWidth(); 88 void shrinkAvailableWidthForNewFloatIfNeeded(RenderBlock::FloatingObject*); 89 void addUncommittedWidth(float delta) { m_uncommittedWidth += delta; } 90 void commit() 91 { 92 m_committedWidth += m_uncommittedWidth; 93 m_uncommittedWidth = 0; 94 } 95 void applyOverhang(RenderRubyRun*, RenderObject* startRenderer, RenderObject* endRenderer); 96 void fitBelowFloats(); 97 98 private: 99 void computeAvailableWidthFromLeftAndRight() 100 { 101 m_availableWidth = max(0, m_right - m_left) + m_overhangWidth; 102 } 103 104 private: 105 RenderBlock* m_block; 106 float m_uncommittedWidth; 107 float m_committedWidth; 108 float m_overhangWidth; // The amount by which |m_availableWidth| has been inflated to account for possible contraction due to ruby overhang. 109 int m_left; 110 int m_right; 111 float m_availableWidth; 112 bool m_isFirstLine; 113 }; 114 115 inline void LineWidth::updateAvailableWidth() 116 { 117 int height = m_block->logicalHeight(); 118 m_left = m_block->logicalLeftOffsetForLine(height, m_isFirstLine); 119 m_right = m_block->logicalRightOffsetForLine(height, m_isFirstLine); 120 121 computeAvailableWidthFromLeftAndRight(); 122 } 123 124 inline void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(RenderBlock::FloatingObject* newFloat) 125 { 126 int height = m_block->logicalHeight(); 127 if (height < m_block->logicalTopForFloat(newFloat) || height >= m_block->logicalBottomForFloat(newFloat)) 128 return; 129 130 if (newFloat->type() == RenderBlock::FloatingObject::FloatLeft) { 131 m_left = m_block->logicalRightForFloat(newFloat); 132 if (m_isFirstLine && m_block->style()->isLeftToRightDirection()) 133 m_left += m_block->textIndentOffset(); 134 } else { 135 m_right = m_block->logicalLeftForFloat(newFloat); 136 if (m_isFirstLine && !m_block->style()->isLeftToRightDirection()) 137 m_right -= m_block->textIndentOffset(); 138 } 139 140 computeAvailableWidthFromLeftAndRight(); 141 } 142 143 void LineWidth::applyOverhang(RenderRubyRun* rubyRun, RenderObject* startRenderer, RenderObject* endRenderer) 144 { 145 int startOverhang; 146 int endOverhang; 147 rubyRun->getOverhang(m_isFirstLine, startRenderer, endRenderer, startOverhang, endOverhang); 148 149 startOverhang = min<int>(startOverhang, m_committedWidth); 150 m_availableWidth += startOverhang; 151 152 endOverhang = max(min<int>(endOverhang, m_availableWidth - currentWidth()), 0); 153 m_availableWidth += endOverhang; 154 m_overhangWidth += startOverhang + endOverhang; 155 } 156 157 void LineWidth::fitBelowFloats() 158 { 159 ASSERT(!m_committedWidth); 160 ASSERT(!fitsOnLine()); 161 162 int floatLogicalBottom; 163 int lastFloatLogicalBottom = m_block->logicalHeight(); 164 float newLineWidth = m_availableWidth; 165 float newLineLeft = m_left; 166 float newLineRight = m_right; 167 while (true) { 168 floatLogicalBottom = m_block->nextFloatLogicalBottomBelow(lastFloatLogicalBottom); 169 if (!floatLogicalBottom) 170 break; 171 172 newLineLeft = m_block->logicalLeftOffsetForLine(floatLogicalBottom, m_isFirstLine); 173 newLineRight = m_block->logicalRightOffsetForLine(floatLogicalBottom, m_isFirstLine); 174 newLineWidth = max(0.0f, newLineRight - newLineLeft); 175 lastFloatLogicalBottom = floatLogicalBottom; 176 if (newLineWidth >= m_uncommittedWidth) 177 break; 178 } 179 180 if (newLineWidth > m_availableWidth) { 181 m_block->setLogicalHeight(lastFloatLogicalBottom); 182 m_availableWidth = newLineWidth + m_overhangWidth; 183 m_left = newLineLeft; 184 m_right = newLineRight; 185 } 186 } 187 63 188 class LineInfo { 64 189 public: … … 68 193 , m_isEmpty(true) 69 194 , m_previousLineBrokeCleanly(true) 195 , m_floatPaginationStrut(0) 70 196 { } 71 197 … … 74 200 bool isEmpty() const { return m_isEmpty; } 75 201 bool previousLineBrokeCleanly() const { return m_previousLineBrokeCleanly; } 202 LayoutUnit floatPaginationStrut() const { return m_floatPaginationStrut; } 76 203 77 204 void setFirstLine(bool firstLine) { m_isFirstLine = firstLine; } 78 205 void setLastLine(bool lastLine) { m_isLastLine = lastLine; } 79 void setEmpty(bool empty) { m_isEmpty = empty; } 206 void setEmpty(bool empty, RenderBlock* block = 0, LineWidth* lineWidth = 0) 207 { 208 if (m_isEmpty == empty) 209 return; 210 m_isEmpty = empty; 211 if (!empty && block && floatPaginationStrut()) { 212 block->setLogicalHeight(block->logicalHeight() + floatPaginationStrut()); 213 setFloatPaginationStrut(0); 214 lineWidth->updateAvailableWidth(); 215 } 216 } 217 80 218 void setPreviousLineBrokeCleanly(bool previousLineBrokeCleanly) { m_previousLineBrokeCleanly = previousLineBrokeCleanly; } 219 void setFloatPaginationStrut(LayoutUnit strut) { m_floatPaginationStrut = strut; } 81 220 82 221 private: … … 85 224 bool m_isEmpty; 86 225 bool m_previousLineBrokeCleanly; 226 LayoutUnit m_floatPaginationStrut; 87 227 }; 88 228 … … 1711 1851 } 1712 1852 1713 void RenderBlock::LineBreaker::skipLeadingWhitespace(InlineBidiResolver& resolver, constLineInfo& lineInfo,1853 void RenderBlock::LineBreaker::skipLeadingWhitespace(InlineBidiResolver& resolver, LineInfo& lineInfo, 1714 1854 FloatingObject* lastFloatFromPreviousLine, LineWidth& width) 1715 1855 { … … 1717 1857 RenderObject* object = resolver.position().m_obj; 1718 1858 if (object->isFloating()) 1719 m_block->positionNewFloatOnLine(m_block->insertFloatingObject(toRenderBox(object)), lastFloatFromPreviousLine, width);1859 m_block->positionNewFloatOnLine(m_block->insertFloatingObject(toRenderBox(object)), lastFloatFromPreviousLine, lineInfo, width); 1720 1860 else if (object->isPositioned()) 1721 1861 setStaticPositions(m_block, toRenderBox(object)); … … 1808 1948 lineBreak.moveTo(text, lastSpace + prefixLength, nextBreakable); 1809 1949 hyphenated = true; 1810 }1811 1812 class LineWidth {1813 public:1814 LineWidth(RenderBlock* block, bool isFirstLine)1815 : m_block(block)1816 , m_uncommittedWidth(0)1817 , m_committedWidth(0)1818 , m_overhangWidth(0)1819 , m_left(0)1820 , m_right(0)1821 , m_availableWidth(0)1822 , m_isFirstLine(isFirstLine)1823 {1824 ASSERT(block);1825 updateAvailableWidth();1826 }1827 bool fitsOnLine() const { return currentWidth() <= m_availableWidth; }1828 bool fitsOnLine(float extra) const { return currentWidth() + extra <= m_availableWidth; }1829 float currentWidth() const { return m_committedWidth + m_uncommittedWidth; }1830 1831 // FIXME: We should eventually replace these three functions by ones that work on a higher abstraction.1832 float uncommittedWidth() const { return m_uncommittedWidth; }1833 float committedWidth() const { return m_committedWidth; }1834 float availableWidth() const { return m_availableWidth; }1835 1836 void updateAvailableWidth();1837 void shrinkAvailableWidthForNewFloatIfNeeded(RenderBlock::FloatingObject*);1838 void addUncommittedWidth(float delta) { m_uncommittedWidth += delta; }1839 void commit()1840 {1841 m_committedWidth += m_uncommittedWidth;1842 m_uncommittedWidth = 0;1843 }1844 void applyOverhang(RenderRubyRun*, RenderObject* startRenderer, RenderObject* endRenderer);1845 void fitBelowFloats();1846 1847 private:1848 void computeAvailableWidthFromLeftAndRight()1849 {1850 m_availableWidth = max(0, m_right - m_left) + m_overhangWidth;1851 }1852 1853 private:1854 RenderBlock* m_block;1855 float m_uncommittedWidth;1856 float m_committedWidth;1857 float m_overhangWidth; // The amount by which |m_availableWidth| has been inflated to account for possible contraction due to ruby overhang.1858 int m_left;1859 int m_right;1860 float m_availableWidth;1861 bool m_isFirstLine;1862 };1863 1864 inline void LineWidth::updateAvailableWidth()1865 {1866 int height = m_block->logicalHeight();1867 m_left = m_block->logicalLeftOffsetForLine(height, m_isFirstLine);1868 m_right = m_block->logicalRightOffsetForLine(height, m_isFirstLine);1869 1870 computeAvailableWidthFromLeftAndRight();1871 }1872 1873 inline void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(RenderBlock::FloatingObject* newFloat)1874 {1875 int height = m_block->logicalHeight();1876 if (height < m_block->logicalTopForFloat(newFloat) || height >= m_block->logicalBottomForFloat(newFloat))1877 return;1878 1879 if (newFloat->type() == RenderBlock::FloatingObject::FloatLeft) {1880 m_left = m_block->logicalRightForFloat(newFloat);1881 if (m_isFirstLine && m_block->style()->isLeftToRightDirection())1882 m_left += m_block->textIndentOffset();1883 } else {1884 m_right = m_block->logicalLeftForFloat(newFloat);1885 if (m_isFirstLine && !m_block->style()->isLeftToRightDirection())1886 m_right -= m_block->textIndentOffset();1887 }1888 1889 computeAvailableWidthFromLeftAndRight();1890 }1891 1892 void LineWidth::applyOverhang(RenderRubyRun* rubyRun, RenderObject* startRenderer, RenderObject* endRenderer)1893 {1894 int startOverhang;1895 int endOverhang;1896 rubyRun->getOverhang(m_isFirstLine, startRenderer, endRenderer, startOverhang, endOverhang);1897 1898 startOverhang = min<int>(startOverhang, m_committedWidth);1899 m_availableWidth += startOverhang;1900 1901 endOverhang = max(min<int>(endOverhang, m_availableWidth - currentWidth()), 0);1902 m_availableWidth += endOverhang;1903 m_overhangWidth += startOverhang + endOverhang;1904 }1905 1906 void LineWidth::fitBelowFloats()1907 {1908 ASSERT(!m_committedWidth);1909 ASSERT(!fitsOnLine());1910 1911 int floatLogicalBottom;1912 int lastFloatLogicalBottom = m_block->logicalHeight();1913 float newLineWidth = m_availableWidth;1914 float newLineLeft = m_left;1915 float newLineRight = m_right;1916 while (true) {1917 floatLogicalBottom = m_block->nextFloatLogicalBottomBelow(lastFloatLogicalBottom);1918 if (!floatLogicalBottom)1919 break;1920 1921 newLineLeft = m_block->logicalLeftOffsetForLine(floatLogicalBottom, m_isFirstLine);1922 newLineRight = m_block->logicalRightOffsetForLine(floatLogicalBottom, m_isFirstLine);1923 newLineWidth = max(0.0f, newLineRight - newLineLeft);1924 lastFloatLogicalBottom = floatLogicalBottom;1925 if (newLineWidth >= m_uncommittedWidth)1926 break;1927 }1928 1929 if (newLineWidth > m_availableWidth) {1930 m_block->setLogicalHeight(lastFloatLogicalBottom);1931 m_availableWidth = newLineWidth + m_overhangWidth;1932 m_left = newLineLeft;1933 m_right = newLineRight;1934 }1935 1950 } 1936 1951 … … 2108 2123 // empty or not. 2109 2124 if (startingNewParagraph) 2110 lineInfo.setEmpty(false );2125 lineInfo.setEmpty(false, m_block, &width); 2111 2126 trailingObjects.clear(); 2112 2127 lineInfo.setPreviousLineBrokeCleanly(true); … … 2125 2140 // it after moving to next line (in newLine() func) 2126 2141 if (floatsFitOnLine && width.fitsOnLine(m_block->logicalWidthForFloat(f))) { 2127 m_block->positionNewFloatOnLine(f, lastFloatFromPreviousLine, width);2142 m_block->positionNewFloatOnLine(f, lastFloatFromPreviousLine, lineInfo, width); 2128 2143 if (lBreak.m_obj == current.m_obj) { 2129 2144 ASSERT(!lBreak.m_pos); … … 2168 2183 // start ignoring spaces. 2169 2184 if (inlineFlowRequiresLineBox(flowBox)) { 2170 lineInfo.setEmpty(false );2185 lineInfo.setEmpty(false, m_block, &width); 2171 2186 if (ignoringSpaces) { 2172 2187 trailingObjects.clear(); … … 2196 2211 addMidpoint(lineMidpointState, InlineIterator(0, current.m_obj, 0)); 2197 2212 2198 lineInfo.setEmpty(false );2213 lineInfo.setEmpty(false, m_block, &width); 2199 2214 ignoringSpaces = false; 2200 2215 currentCharacterIsSpace = false; … … 2268 2283 2269 2284 if (!collapseWhiteSpace || !currentCharacterIsSpace) 2270 lineInfo.setEmpty(false );2285 lineInfo.setEmpty(false, m_block, &width); 2271 2286 2272 2287 if (c == softHyphen && autoWrap && !hyphenWidth && style->hyphens() != HyphensNone) { … … 2632 2647 } 2633 2648 2634 bool RenderBlock::positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, Line Width& width)2649 bool RenderBlock::positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo& lineInfo, LineWidth& width) 2635 2650 { 2636 2651 if (!positionNewFloats()) … … 2648 2663 int paginationStrut = newFloat->m_paginationStrut; 2649 2664 2650 if (floatLogicalTop - paginationStrut != logicalHeight() )2665 if (floatLogicalTop - paginationStrut != logicalHeight() + lineInfo.floatPaginationStrut()) 2651 2666 return true; 2652 2667 … … 2659 2674 if (f == lastFloatFromPreviousLine) 2660 2675 break; 2661 if (logicalTopForFloat(f) == logicalHeight()) { 2662 ASSERT(!f->m_paginationStrut); 2663 f->m_paginationStrut = paginationStrut; 2676 if (logicalTopForFloat(f) == logicalHeight() + lineInfo.floatPaginationStrut()) { 2677 f->m_paginationStrut += paginationStrut; 2664 2678 RenderBox* o = f->m_renderer; 2665 2679 setLogicalTopForChild(o, logicalTopForChild(o) + marginBeforeForChild(o) + paginationStrut); … … 2671 2685 LayoutUnit oldLogicalTop = logicalTopForFloat(f); 2672 2686 m_floatingObjects->removePlacedObject(f); 2673 setLogicalTopForFloat(f, oldLogicalTop + f->m_paginationStrut);2687 setLogicalTopForFloat(f, oldLogicalTop + paginationStrut); 2674 2688 m_floatingObjects->addPlacedObject(f); 2675 2689 } 2676 2690 } 2677 2691 2678 setLogicalHeight(logicalHeight() + paginationStrut); 2679 width.updateAvailableWidth(); 2692 if (lineInfo.isEmpty()) { 2693 // Just update the line info's pagination strut without altering our logical height yet. If the line ends up containing 2694 // no content, then we don't want to improperly grow the height of the block. 2695 lineInfo.setFloatPaginationStrut(lineInfo.floatPaginationStrut() + paginationStrut); 2696 } else { 2697 // The line already has content on it, so we want to go ahead and shift everything down. 2698 setLogicalHeight(logicalHeight() + paginationStrut); 2699 width.updateAvailableWidth(); 2700 } 2680 2701 2681 2702 return true;
Note: See TracChangeset
for help on using the changeset viewer.