Changeset 207219 in webkit
- Timestamp:
- Oct 12, 2016 9:45:55 AM (8 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r207216 r207219 1 2016-10-12 Zalan Bujtas <zalan@apple.com> 2 3 Refactor LineLayoutState's float box handling. 4 https://bugs.webkit.org/show_bug.cgi?id=163286 5 6 Reviewed by David Hyatt. 7 8 We keep track of float boxes both per line (RootInlineBox::m_floats) and 9 per flow block (LineLayoutState::m_floats) during layout. 10 As we lay out the lines and iterate through RootInlineBox::m_floats, we 11 increment LineLayoutState::m_floatIndex. This LineLayoutState::m_floatIndex is 12 later used to find the matching float box in the per-block-flow float list. 13 This logic works fine as long as the lists and the index manipulation are tightly coded. 14 However due to the complexity of the line/float layout code, this is no longer the case. 15 16 This patch makes float box handling more secure by changing this index based setup 17 to a list iterator. It helps to eliminate potential vector overflow issues. 18 19 LineLayoutState::FloatList (new class) keeps track of all the floats for the block flow. 20 It groups the float box related functions/members and provides an iterator interface to ensure safer 21 syncing between this and the line based floats. 22 23 No change in functionality. 24 25 * rendering/RenderBlockFlow.h: 26 * rendering/RenderBlockLineLayout.cpp: 27 (WebCore::RenderBlockFlow::appendFloatingObjectToLastLine): 28 (WebCore::repaintDirtyFloats): 29 (WebCore::RenderBlockFlow::layoutRunsAndFloats): 30 (WebCore::RenderBlockFlow::layoutRunsAndFloatsInRange): 31 (WebCore::RenderBlockFlow::linkToEndLineIfNeeded): 32 (WebCore::RenderBlockFlow::layoutLineBoxes): 33 (WebCore::RenderBlockFlow::checkFloatInCleanLine): 34 (WebCore::RenderBlockFlow::determineStartPosition): 35 (WebCore::RenderBlockFlow::determineEndPosition): 36 (WebCore::RenderBlockFlow::repaintDirtyFloats): Deleted. 37 (WebCore::RenderBlockFlow::checkFloatsInCleanLine): Deleted. 38 * rendering/line/LineLayoutState.h: 39 (WebCore::FloatWithRect::create): 40 (WebCore::FloatWithRect::renderer): 41 (WebCore::FloatWithRect::rect): 42 (WebCore::FloatWithRect::everHadLayout): 43 (WebCore::FloatWithRect::adjustRect): 44 (WebCore::FloatWithRect::FloatWithRect): 45 (WebCore::LineLayoutState::FloatList::append): 46 (WebCore::LineLayoutState::FloatList::setLastFloat): 47 (WebCore::LineLayoutState::FloatList::lastFloat): 48 (WebCore::LineLayoutState::FloatList::setLastCleanFloat): 49 (WebCore::LineLayoutState::FloatList::lastCleanFloat): 50 (WebCore::LineLayoutState::FloatList::floatWithRect): 51 (WebCore::LineLayoutState::FloatList::begin): 52 (WebCore::LineLayoutState::FloatList::end): 53 (WebCore::LineLayoutState::FloatList::find): 54 (WebCore::LineLayoutState::FloatList::isEmpty): 55 (WebCore::LineLayoutState::LineLayoutState): 56 (WebCore::LineLayoutState::floatList): 57 (WebCore::LineLayoutState::lastFloat): Deleted. 58 (WebCore::LineLayoutState::setLastFloat): Deleted. 59 (WebCore::LineLayoutState::floats): Deleted. 60 (WebCore::LineLayoutState::floatIndex): Deleted. 61 (WebCore::LineLayoutState::setFloatIndex): Deleted. 62 1 63 2016-10-12 Said Abou-Hallawa <sabouhallawa@apple.com> 2 64 -
trunk/Source/WebCore/rendering/RenderBlockFlow.h
r206395 r207219 34 34 namespace WebCore { 35 35 36 class FloatWithRect; 36 37 class LayoutStateMaintainer; 37 38 class LineBreaker; … … 42 43 class RenderRubyRun; 43 44 44 struct FloatWithRect;45 45 struct WordMeasurement; 46 46 … … 567 567 void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&); 568 568 BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*); 569 void appendFloatingObjectToLastLine(FloatingObject *);569 void appendFloatingObjectToLastLine(FloatingObject&); 570 570 // Helper function for layoutInlineChildren() 571 571 RootInlineBox* createLineBoxesFromBidiRuns(unsigned bidiLevel, BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&); … … 575 575 void reattachCleanLineFloats(RootInlineBox& cleanLine, LayoutUnit delta, bool isFirstCleanLine); 576 576 void linkToEndLineIfNeeded(LineLayoutState&); 577 static void repaintDirtyFloats(Vector<FloatWithRect>& floats);578 void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex,bool& encounteredNewFloat, bool& dirtiedByFloat);577 void checkFloatInCleanLine(RootInlineBox& cleanLine, RenderBox& floatBoxOnCleanLine, FloatWithRect& matchingFloatWithRect, 578 bool& encounteredNewFloat, bool& dirtiedByFloat); 579 579 RootInlineBox* determineStartPosition(LineLayoutState&, InlineBidiResolver&); 580 580 void determineEndPosition(LineLayoutState&, RootInlineBox* startBox, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus); -
trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp
r205186 r207219 1101 1101 } 1102 1102 1103 void RenderBlockFlow::appendFloatingObjectToLastLine(FloatingObject *floatingObject)1104 { 1105 ASSERT_WITH_SECURITY_IMPLICATION(!floatingObject ->originatingLine());1106 floatingObject ->setOriginatingLine(lastRootBox());1107 lastRootBox()->appendFloat(floatingObject ->renderer());1103 void RenderBlockFlow::appendFloatingObjectToLastLine(FloatingObject& floatingObject) 1104 { 1105 ASSERT_WITH_SECURITY_IMPLICATION(!floatingObject.originatingLine()); 1106 floatingObject.setOriginatingLine(lastRootBox()); 1107 lastRootBox()->appendFloat(floatingObject.renderer()); 1108 1108 } 1109 1109 … … 1250 1250 } 1251 1251 1252 static void repaintDirtyFloats(LineLayoutState::FloatList& floats) 1253 { 1254 // Floats that did not have layout did not repaint when we laid them out. They would have 1255 // painted by now if they had moved, but if they stayed at (0, 0), they still need to be 1256 // painted. 1257 for (auto& floatBox : floats) { 1258 if (floatBox->everHadLayout()) 1259 continue; 1260 auto& box = floatBox->renderer(); 1261 if (!box.x() && !box.y() && box.checkForRepaintDuringLayout()) 1262 box.repaint(); 1263 } 1264 } 1265 1252 1266 void RenderBlockFlow::layoutRunsAndFloats(LineLayoutState& layoutState, bool hasInlineChild) 1253 1267 { … … 1280 1294 1281 1295 if (containsFloats()) 1282 layoutState. setLastFloat(m_floatingObjects->set().last().get());1296 layoutState.floatList().setLastFloat(m_floatingObjects->set().last().get()); 1283 1297 1284 1298 // We also find the first clean line and extract these lines. We will add them back … … 1313 1327 layoutRunsAndFloatsInRange(layoutState, resolver, cleanLineStart, cleanLineBidiStatus, consecutiveHyphenatedLines); 1314 1328 linkToEndLineIfNeeded(layoutState); 1315 repaintDirtyFloats(layoutState.float s());1329 repaintDirtyFloats(layoutState.floatList()); 1316 1330 } 1317 1331 … … 1480 1494 auto it = floatingObjectSet.begin(); 1481 1495 auto end = floatingObjectSet.end(); 1482 if ( layoutState.lastFloat()) {1483 auto lastFloatIterator = floatingObjectSet.find<FloatingObject&, FloatingObjectHashTranslator>(*la youtState.lastFloat());1496 if (auto* lastFloat = layoutState.floatList().lastFloat()) { 1497 auto lastFloatIterator = floatingObjectSet.find<FloatingObject&, FloatingObjectHashTranslator>(*lastFloat); 1484 1498 ASSERT(lastFloatIterator != end); 1485 1499 ++lastFloatIterator; … … 1487 1501 } 1488 1502 for (; it != end; ++it) { 1489 FloatingObject* f = it->get(); 1490 appendFloatingObjectToLastLine(f); 1491 ASSERT(&f->renderer() == &layoutState.floats()[layoutState.floatIndex()].object); 1503 auto& floatingObject = *it; 1504 appendFloatingObjectToLastLine(*floatingObject); 1492 1505 // If a float's geometry has changed, give up on syncing with clean lines. 1493 if (layoutState.floats()[layoutState.floatIndex()].rect != f->frameRect()) 1506 auto* floatWithRect = layoutState.floatList().floatWithRect(floatingObject->renderer()); 1507 if (!floatWithRect || floatWithRect->rect() != floatingObject->frameRect()) 1494 1508 checkForEndLineMatch = false; 1495 layoutState.setFloatIndex(layoutState.floatIndex() + 1); 1496 } 1497 layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : nullptr); 1509 } 1510 layoutState.floatList().setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : nullptr); 1498 1511 } 1499 1512 … … 1642 1655 auto it = floatingObjectSet.begin(); 1643 1656 auto end = floatingObjectSet.end(); 1644 if ( layoutState.lastFloat()) {1645 auto lastFloatIterator = floatingObjectSet.find<FloatingObject&, FloatingObjectHashTranslator>(*la youtState.lastFloat());1657 if (auto* lastFloat = layoutState.floatList().lastFloat()) { 1658 auto lastFloatIterator = floatingObjectSet.find<FloatingObject&, FloatingObjectHashTranslator>(*lastFloat); 1646 1659 ASSERT(lastFloatIterator != end); 1647 1660 ++lastFloatIterator; … … 1649 1662 } 1650 1663 for (; it != end; ++it) 1651 appendFloatingObjectToLastLine(it->get()); 1652 layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : nullptr); 1653 } 1654 } 1655 1656 void RenderBlockFlow::repaintDirtyFloats(Vector<FloatWithRect>& floats) 1657 { 1658 size_t floatCount = floats.size(); 1659 // Floats that did not have layout did not repaint when we laid them out. They would have 1660 // painted by now if they had moved, but if they stayed at (0, 0), they still need to be 1661 // painted. 1662 for (size_t i = 0; i < floatCount; ++i) { 1663 if (!floats[i].everHadLayout) { 1664 RenderBox& box = floats[i].object; 1665 if (!box.x() && !box.y() && box.checkForRepaintDuringLayout()) 1666 box.repaint(); 1667 } 1664 appendFloatingObjectToLastLine(**it); 1665 layoutState.floatList().setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : nullptr); 1668 1666 } 1669 1667 } … … 1730 1728 box.containingBlock()->insertPositionedObject(box); 1731 1729 else if (box.isFloating()) 1732 layoutState.float s().append(FloatWithRect(box));1730 layoutState.floatList().append(FloatWithRect::create(box)); 1733 1731 else if (isFullLayout || box.needsLayout()) { 1734 1732 // Replaced element. … … 1786 1784 } 1787 1785 1788 void RenderBlockFlow::checkFloatsInCleanLine(RootInlineBox* line, Vector<FloatWithRect>& floats, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat) 1789 { 1790 Vector<RenderBox*>* cleanLineFloats = line->floatsPtr(); 1791 if (!cleanLineFloats) 1792 return; 1793 1794 if (!floats.size()) { 1786 void RenderBlockFlow::checkFloatInCleanLine(RootInlineBox& cleanLine, RenderBox& floatBoxOnCleanLine, FloatWithRect& matchingFloatWithRect, 1787 bool& encounteredNewFloat, bool& dirtiedByFloat) 1788 { 1789 ASSERT_WITH_SECURITY_IMPLICATION(!floatBoxOnCleanLine.style().deletionHasBegun()); 1790 if (&matchingFloatWithRect.renderer() != &floatBoxOnCleanLine) { 1795 1791 encounteredNewFloat = true; 1796 1792 return; 1797 1793 } 1798 1799 for (auto it = cleanLineFloats->begin(), end = cleanLineFloats->end(); it != end; ++it) { 1800 RenderBox* floatingBox = *it; 1801 ASSERT_WITH_SECURITY_IMPLICATION(!floatingBox->style().deletionHasBegun()); 1802 floatingBox->layoutIfNeeded(); 1803 LayoutSize newSize(floatingBox->width() + floatingBox->horizontalMarginExtent(), floatingBox->height() + floatingBox->verticalMarginExtent()); 1804 ASSERT_WITH_SECURITY_IMPLICATION(floatIndex < floats.size()); 1805 if (&floats[floatIndex].object != floatingBox) { 1806 encounteredNewFloat = true; 1807 return; 1808 } 1794 floatBoxOnCleanLine.layoutIfNeeded(); 1795 LayoutRect originalFloatRect = matchingFloatWithRect.rect(); 1796 LayoutSize newSize( 1797 floatBoxOnCleanLine.width() + floatBoxOnCleanLine.horizontalMarginExtent(), 1798 floatBoxOnCleanLine.height() + floatBoxOnCleanLine.verticalMarginExtent()); 1809 1799 1810 // We have to reset the cap-height alignment done by the first-letter floats when initial-letter is set, so just always treat first-letter floats 1811 // as dirty. 1812 if (floats[floatIndex].rect.size() != newSize || (floatingBox->style().styleType() == FIRST_LETTER && floatingBox->style().initialLetterDrop() > 0)) { 1813 LayoutUnit floatTop = isHorizontalWritingMode() ? floats[floatIndex].rect.y() : floats[floatIndex].rect.x(); 1814 LayoutUnit floatHeight = isHorizontalWritingMode() ? std::max(floats[floatIndex].rect.height(), newSize.height()) : std::max(floats[floatIndex].rect.width(), newSize.width()); 1815 floatHeight = std::min(floatHeight, LayoutUnit::max() - floatTop); 1816 line->markDirty(); 1817 markLinesDirtyInBlockRange(line->lineBottomWithLeading(), floatTop + floatHeight, line); 1818 floats[floatIndex].rect.setSize(newSize); 1819 dirtiedByFloat = true; 1820 } 1821 floatIndex++; 1822 } 1800 // We have to reset the cap-height alignment done by the first-letter floats when initial-letter is set, so just always treat first-letter floats as dirty. 1801 if (originalFloatRect.size() == newSize && (floatBoxOnCleanLine.style().styleType() != FIRST_LETTER || !floatBoxOnCleanLine.style().initialLetterDrop())) 1802 return; 1803 1804 LayoutUnit floatTop = isHorizontalWritingMode() ? originalFloatRect.y() : originalFloatRect.x(); 1805 LayoutUnit floatHeight = isHorizontalWritingMode() ? std::max(originalFloatRect.height(), newSize.height()) 1806 : std::max(originalFloatRect.width(), newSize.width()); 1807 floatHeight = std::min(floatHeight, LayoutUnit::max() - floatTop); 1808 cleanLine.markDirty(); 1809 markLinesDirtyInBlockRange(cleanLine.lineBottomWithLeading(), floatTop + floatHeight, &cleanLine); 1810 LayoutRect newFloatRect = originalFloatRect; 1811 newFloatRect.setSize(newSize); 1812 matchingFloatWithRect.adjustRect(newFloatRect); 1813 dirtiedByFloat = true; 1823 1814 } 1824 1815 1825 1816 RootInlineBox* RenderBlockFlow::determineStartPosition(LineLayoutState& layoutState, InlineBidiResolver& resolver) 1826 1817 { 1827 RootInlineBox* curr = 0;1828 RootInlineBox* last = 0;1818 RootInlineBox* currentLine = nullptr; 1819 RootInlineBox* lastLine = nullptr; 1829 1820 1830 1821 // FIXME: This entire float-checking block needs to be broken into a new function. 1822 auto& floats = layoutState.floatList(); 1831 1823 bool dirtiedByFloat = false; 1832 1824 if (!layoutState.isFullLayout()) { … … 1834 1826 bool paginated = view().layoutState() && view().layoutState()->isPaginated(); 1835 1827 LayoutUnit paginationDelta = 0; 1836 size_t floatIndex = 0; 1837 for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox()) { 1828 auto floatsIterator = floats.begin(); 1829 auto end = floats.end(); 1830 for (currentLine = firstRootBox(); currentLine && !currentLine->isDirty(); currentLine = currentLine->nextRootBox()) { 1838 1831 if (paginated) { 1839 if (lineWidthForPaginatedLineChanged(curr , 0, layoutState.flowThread())) {1840 curr ->markDirty();1832 if (lineWidthForPaginatedLineChanged(currentLine, 0, layoutState.flowThread())) { 1833 currentLine->markDirty(); 1841 1834 break; 1842 1835 } 1843 paginationDelta -= curr ->paginationStrut();1836 paginationDelta -= currentLine->paginationStrut(); 1844 1837 bool overflowsRegion; 1845 adjustLinePositionForPagination(curr , paginationDelta, overflowsRegion, layoutState.flowThread());1838 adjustLinePositionForPagination(currentLine, paginationDelta, overflowsRegion, layoutState.flowThread()); 1846 1839 if (paginationDelta) { 1847 if (containsFloats() || ! layoutState.floats().isEmpty()) {1840 if (containsFloats() || !floats.isEmpty()) { 1848 1841 // FIXME: Do better eventually. For now if we ever shift because of pagination and floats are present just go to a full layout. 1849 1842 layoutState.markForFullLayout(); … … 1851 1844 } 1852 1845 1853 layoutState.updateRepaintRangeFromBox(curr , paginationDelta);1854 curr ->adjustBlockDirectionPosition(paginationDelta);1846 layoutState.updateRepaintRangeFromBox(currentLine, paginationDelta); 1847 currentLine->adjustBlockDirectionPosition(paginationDelta); 1855 1848 } 1856 1849 if (layoutState.flowThread()) 1857 updateRegionForLine(curr); 1858 } 1859 1860 // If a new float has been inserted before this line or before its last known float, just do a full layout. 1861 bool encounteredNewFloat = false; 1862 checkFloatsInCleanLine(curr, layoutState.floats(), floatIndex, encounteredNewFloat, dirtiedByFloat); 1863 if (encounteredNewFloat) 1864 layoutState.markForFullLayout(); 1865 1866 if (dirtiedByFloat || layoutState.isFullLayout()) 1867 break; 1850 updateRegionForLine(currentLine); 1851 } 1852 1853 if (auto* cleanLineFloats = currentLine->floatsPtr()) { 1854 // If a new float has been inserted before this line or before its last known float, just do a full layout. 1855 bool encounteredNewFloat = false; 1856 for (auto* floatBoxOnCleanLine : *cleanLineFloats) { 1857 ASSERT(floatsIterator != end); 1858 checkFloatInCleanLine(*currentLine, *floatBoxOnCleanLine, *floatsIterator, encounteredNewFloat, dirtiedByFloat); 1859 ++floatsIterator; 1860 if (floatsIterator == end || encounteredNewFloat) { 1861 layoutState.markForFullLayout(); 1862 break; 1863 } 1864 } 1865 if (dirtiedByFloat || encounteredNewFloat) 1866 break; 1867 } 1868 1868 } 1869 1869 // Check if a new float has been inserted after the last known float. 1870 if (!curr && floatIndex < layoutState.floats().size())1870 if (!currentLine && floatsIterator != end) 1871 1871 layoutState.markForFullLayout(); 1872 1872 } … … 1874 1874 if (layoutState.isFullLayout()) { 1875 1875 m_lineBoxes.deleteLineBoxTree(); 1876 curr = 0; 1877 1876 currentLine = nullptr; 1878 1877 ASSERT(!firstRootBox() && !lastRootBox()); 1879 1878 } else { 1880 if (curr ) {1879 if (currentLine) { 1881 1880 // We have a dirty line. 1882 if (RootInlineBox* prevRootBox = curr ->prevRootBox()) {1881 if (RootInlineBox* prevRootBox = currentLine->prevRootBox()) { 1883 1882 // We have a previous line. 1884 if (!dirtiedByFloat && !curr->hasAnonymousInlineBlock() && (!prevRootBox->endsWithBreak() || !prevRootBox->lineBreakObj() || (is<RenderText>(*prevRootBox->lineBreakObj()) && prevRootBox->lineBreakPos() >= downcast<RenderText>(*prevRootBox->lineBreakObj()).textLength()))) { 1883 if (!dirtiedByFloat && !currentLine->hasAnonymousInlineBlock() && (!prevRootBox->endsWithBreak() 1884 || !prevRootBox->lineBreakObj() 1885 || (is<RenderText>(*prevRootBox->lineBreakObj()) 1886 && prevRootBox->lineBreakPos() >= downcast<RenderText>(*prevRootBox->lineBreakObj()).textLength()))) { 1885 1887 // The previous line didn't break cleanly or broke at a newline 1886 1888 // that has been deleted, so treat it as dirty too. 1887 curr = prevRootBox;1889 currentLine = prevRootBox; 1888 1890 } 1889 1891 } 1890 1892 } 1891 1893 // If we have no dirty lines, then last is just the last root box. 1892 last = curr ? curr->prevRootBox() : lastRootBox(); 1893 } 1894 1895 unsigned numCleanFloats = 0; 1896 if (!layoutState.floats().isEmpty()) { 1894 lastLine = currentLine ? currentLine->prevRootBox() : lastRootBox(); 1895 } 1896 1897 if (!floats.isEmpty()) { 1897 1898 LayoutUnit savedLogicalHeight = logicalHeight(); 1898 1899 // Restore floats from clean lines. 1899 1900 RootInlineBox* line = firstRootBox(); 1900 while (line != curr ) {1901 while (line != currentLine) { 1901 1902 if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) { 1902 1903 for (auto it = cleanLineFloats->begin(), end = cleanLineFloats->end(); it != end; ++it) { 1903 RenderBox* floatingBox = *it;1904 FloatingObject* floatingObject = insertFloatingObject(*floatingBox);1904 auto* floatingBox = *it; 1905 auto* floatingObject = insertFloatingObject(*floatingBox); 1905 1906 ASSERT_WITH_SECURITY_IMPLICATION(!floatingObject->originatingLine()); 1906 1907 floatingObject->setOriginatingLine(line); 1907 1908 setLogicalHeight(logicalTopForChild(*floatingBox) - marginBeforeForChild(*floatingBox)); 1908 1909 positionNewFloats(); 1909 ASSERT(&layoutState.floats()[numCleanFloats].object == floatingBox); 1910 numCleanFloats++; 1910 floats.setLastCleanFloat(*floatingBox); 1911 1911 } 1912 1912 } … … 1915 1915 setLogicalHeight(savedLogicalHeight); 1916 1916 } 1917 layoutState.setFloatIndex(numCleanFloats); 1918 1919 layoutState.lineInfo().setFirstLine(!last); 1920 layoutState.lineInfo().setPreviousLineBrokeCleanly(!last || last->endsWithBreak()); 1921 1922 if (last) { 1923 setLogicalHeight(last->lineBottomWithLeading()); 1924 InlineIterator iter = InlineIterator(this, last->lineBreakObj(), last->lineBreakPos()); 1917 1918 layoutState.lineInfo().setFirstLine(!lastLine); 1919 layoutState.lineInfo().setPreviousLineBrokeCleanly(!lastLine || lastLine->endsWithBreak()); 1920 1921 if (lastLine) { 1922 setLogicalHeight(lastLine->lineBottomWithLeading()); 1923 InlineIterator iter = InlineIterator(this, lastLine->lineBreakObj(), lastLine->lineBreakPos()); 1925 1924 resolver.setPosition(iter, numberOfIsolateAncestors(iter)); 1926 resolver.setStatus(last ->lineBreakBidiStatus());1925 resolver.setStatus(lastLine->lineBreakBidiStatus()); 1927 1926 } else { 1928 1927 TextDirection direction = style().direction(); … … 1933 1932 resolver.setPosition(iter, numberOfIsolateAncestors(iter)); 1934 1933 } 1935 return curr ;1934 return currentLine; 1936 1935 } 1937 1936 1938 1937 void RenderBlockFlow::determineEndPosition(LineLayoutState& layoutState, RootInlineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus) 1939 1938 { 1939 auto iteratorForFirstDirtyFloat = [](LineLayoutState::FloatList& floats) { 1940 auto lastCleanFloat = floats.lastCleanFloat(); 1941 if (!lastCleanFloat) 1942 return floats.begin(); 1943 auto* lastCleanFloatWithRect = floats.floatWithRect(*lastCleanFloat); 1944 ASSERT(lastCleanFloatWithRect); 1945 return ++floats.find(*lastCleanFloatWithRect); 1946 }; 1947 1940 1948 ASSERT(!layoutState.endLine()); 1941 size_t floatIndex = layoutState.floatIndex(); 1942 RootInlineBox* last = 0; 1943 for (RootInlineBox* curr = startLine->nextRootBox(); curr; curr = curr->nextRootBox()) { 1944 if (!curr->isDirty()) { 1945 bool encounteredNewFloat = false; 1946 bool dirtiedByFloat = false; 1947 checkFloatsInCleanLine(curr, layoutState.floats(), floatIndex, encounteredNewFloat, dirtiedByFloat); 1948 if (encounteredNewFloat) 1949 return; 1950 } 1951 if (curr->isDirty()) 1952 last = 0; 1953 else if (!last) 1954 last = curr; 1955 } 1956 1957 if (!last) 1949 auto floatsIterator = iteratorForFirstDirtyFloat(layoutState.floatList()); 1950 auto end = layoutState.floatList().end(); 1951 RootInlineBox* lastLine = nullptr; 1952 for (RootInlineBox* currentLine = startLine->nextRootBox(); currentLine; currentLine = currentLine->nextRootBox()) { 1953 if (!currentLine->isDirty()) { 1954 if (auto* cleanLineFloats = currentLine->floatsPtr()) { 1955 bool encounteredNewFloat = false; 1956 bool dirtiedByFloat = false; 1957 for (auto* floatBoxOnCleanLine : *cleanLineFloats) { 1958 ASSERT(floatsIterator != end); 1959 checkFloatInCleanLine(*currentLine, *floatBoxOnCleanLine, *floatsIterator, encounteredNewFloat, dirtiedByFloat); 1960 ++floatsIterator; 1961 if (floatsIterator == end || encounteredNewFloat) 1962 return; 1963 } 1964 } 1965 } 1966 if (currentLine->isDirty()) 1967 lastLine = nullptr; 1968 else if (!lastLine) 1969 lastLine = currentLine; 1970 } 1971 1972 if (!lastLine) 1958 1973 return; 1959 1974 1960 1975 // At this point, |last| is the first line in a run of clean lines that ends with the last line 1961 1976 // in the block. 1962 1963 RootInlineBox* prev = last->prevRootBox(); 1964 cleanLineStart = InlineIterator(this, prev->lineBreakObj(), prev->lineBreakPos()); 1965 cleanLineBidiStatus = prev->lineBreakBidiStatus(); 1966 layoutState.setEndLineLogicalTop(prev->lineBottomWithLeading()); 1967 1968 for (RootInlineBox* line = last; line; line = line->nextRootBox()) 1969 line->extractLine(); // Disconnect all line boxes from their render objects while preserving 1970 // their connections to one another. 1971 1972 layoutState.setEndLine(last); 1977 RootInlineBox* previousLine = lastLine->prevRootBox(); 1978 cleanLineStart = InlineIterator(this, previousLine->lineBreakObj(), previousLine->lineBreakPos()); 1979 cleanLineBidiStatus = previousLine->lineBreakBidiStatus(); 1980 layoutState.setEndLineLogicalTop(previousLine->lineBottomWithLeading()); 1981 1982 for (RootInlineBox* line = lastLine; line; line = line->nextRootBox()) { 1983 // Disconnect all line boxes from their render objects while preserving their connections to one another. 1984 line->extractLine(); 1985 } 1986 layoutState.setEndLine(lastLine); 1973 1987 } 1974 1988 -
trunk/Source/WebCore/rendering/line/LineLayoutState.h
r189817 r207219 37 37 #include "LayoutRect.h" 38 38 #include "RenderBlockFlow.h" 39 #include <wtf/RefCounted.h> 39 40 40 41 namespace WebCore { 41 42 42 struct FloatWithRect { 43 FloatWithRect(RenderBox& f) 44 : object(f) 45 , rect(LayoutRect(f.x() - f.marginLeft(), f.y() - f.marginTop(), f.width() + f.horizontalMarginExtent(), f.height() + f.verticalMarginExtent())) 46 , everHadLayout(f.everHadLayout()) 43 class FloatWithRect : public RefCounted<FloatWithRect> { 44 WTF_MAKE_FAST_ALLOCATED; 45 public: 46 static Ref<FloatWithRect> create(RenderBox& renderer) 47 { 48 return adoptRef(*new FloatWithRect(renderer)); 49 } 50 51 RenderBox& renderer() const { return m_renderer; } 52 LayoutRect rect() const { return m_rect; } 53 bool everHadLayout() const { return m_everHadLayout; } 54 55 void adjustRect(const LayoutRect& rect) { m_rect = rect; } 56 57 private: 58 FloatWithRect() = default; 59 60 FloatWithRect(RenderBox& renderer) 61 : m_renderer(renderer) 62 , m_rect(LayoutRect(renderer.x() - renderer.marginLeft(), renderer.y() - renderer.marginTop(), renderer.width() + renderer.horizontalMarginExtent(), renderer.height() + renderer.verticalMarginExtent())) 63 , m_everHadLayout(renderer.everHadLayout()) 47 64 { 48 65 } 49 50 RenderBox& object;51 LayoutRect rect;52 bool everHadLayout;66 67 RenderBox& m_renderer; 68 LayoutRect m_rect; 69 bool m_everHadLayout { false }; 53 70 }; 54 71 … … 57 74 class LineLayoutState { 58 75 public: 76 class FloatList { 77 public: 78 void append(Ref<FloatWithRect>&& floatWithRect) 79 { 80 m_floats.add(floatWithRect.copyRef()); 81 m_floatWithRectMap.add(&floatWithRect->renderer(), WTFMove(floatWithRect)); 82 } 83 void setLastFloat(FloatingObject* lastFloat) { m_lastFloat = lastFloat; } 84 FloatingObject* lastFloat() const { return m_lastFloat; } 85 86 void setLastCleanFloat(RenderBox& floatBox) { m_lastCleanFloat = &floatBox; } 87 RenderBox* lastCleanFloat() const { return m_lastCleanFloat; } 88 89 FloatWithRect* floatWithRect(RenderBox& floatBox) const { return m_floatWithRectMap.get(&floatBox); } 90 91 using Iterator = ListHashSet<Ref<FloatWithRect>>::iterator; 92 Iterator begin() { return m_floats.begin(); } 93 Iterator end() { return m_floats.end(); } 94 Iterator find(FloatWithRect& floatBoxWithRect) { return m_floats.find(floatBoxWithRect); } 95 bool isEmpty() const { return m_floats.isEmpty(); } 96 97 private: 98 ListHashSet<Ref<FloatWithRect>> m_floats; 99 HashMap<RenderBox*, Ref<FloatWithRect>> m_floatWithRectMap; 100 FloatingObject* m_lastFloat { nullptr }; 101 RenderBox* m_lastCleanFloat { nullptr }; 102 }; 103 59 104 LineLayoutState(const RenderBlockFlow& blockFlow, bool fullLayout, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom, RenderFlowThread* flowThread) 60 : m_endLineLogicalTop(0) 61 , m_endLine(0) 62 , m_lastFloat(0) 63 , m_floatIndex(0) 64 , m_adjustedLogicalLineTop(0) 65 , m_flowThread(flowThread) 105 : m_flowThread(flowThread) 66 106 , m_repaintLogicalTop(repaintLogicalTop) 67 107 , m_repaintLogicalBottom(repaintLogicalBottom) … … 82 122 RootInlineBox* endLine() const { return m_endLine; } 83 123 void setEndLine(RootInlineBox* line) { m_endLine = line; } 84 85 FloatingObject* lastFloat() const { return m_lastFloat; }86 void setLastFloat(FloatingObject* lastFloat) { m_lastFloat = lastFloat; }87 88 Vector<FloatWithRect>& floats() { return m_floats; }89 90 unsigned floatIndex() const { return m_floatIndex; }91 void setFloatIndex(unsigned floatIndex) { m_floatIndex = floatIndex; }92 124 93 125 LayoutUnit adjustedLogicalLineTop() const { return m_adjustedLogicalLineTop; } … … 125 157 LayoutUnit& maxFloatBottomFromAnonymousInlineBlock() { return m_maxFloatBottomFromAnonymousInlineBlock; } 126 158 159 FloatList& floatList() { return m_floatList; } 160 127 161 private: 128 162 LineInfo m_lineInfo; 129 163 LayoutUnit m_endLineLogicalTop; 130 RootInlineBox* m_endLine; 131 132 FloatingObject* m_lastFloat; 133 Vector<FloatWithRect> m_floats; 134 unsigned m_floatIndex; 164 RootInlineBox* m_endLine { nullptr }; 135 165 136 166 LayoutUnit m_adjustedLogicalLineTop; 137 167 138 RenderFlowThread* m_flowThread ;168 RenderFlowThread* m_flowThread { nullptr }; 139 169 170 FloatList m_floatList; 140 171 // FIXME: Should this be a range object instead of two ints? 141 172 LayoutUnit& m_repaintLogicalTop;
Note: See TracChangeset
for help on using the changeset viewer.