Changeset 252861 in webkit
- Timestamp:
- Nov 25, 2019 8:13:18 AM (4 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r252859 r252861 1 2019-11-25 Zalan Bujtas <zalan@apple.com> 2 3 [LFC][IFC] Construct only one LineLayout object per inline formatting context 4 https://bugs.webkit.org/show_bug.cgi?id=204561 5 <rdar://problem/57463666> 6 7 Reviewed by Antti Koivisto. 8 9 Let's construct only one LineLayout object per IFC. 10 11 * layout/inlineformatting/InlineFormattingContext.cpp: 12 (WebCore::Layout::InlineFormattingContext::lineLayout): 13 (WebCore::Layout::InlineFormattingContext::computedIntrinsicWidthForConstraint const): 14 * layout/inlineformatting/InlineLineLayout.cpp: 15 (WebCore::Layout::LineLayout::LineLayout): 16 (WebCore::Layout::LineLayout::layout): 17 (WebCore::Layout::LineLayout::close): 18 (WebCore::Layout::LineLayout::LineInput::LineInput): Deleted. 19 * layout/inlineformatting/InlineLineLayout.h: 20 1 21 2019-11-25 Zalan Bujtas <zalan@apple.com> 2 22 -
trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp
r252859 r252861 97 97 Optional<LineLayout::PartialContent> leadingPartialContent; 98 98 auto line = Line { *this, root().style().textAlign(), Line::SkipAlignment::No }; 99 auto lineLayout = LineLayout { *this, inlineItems }; 99 100 100 101 while (leadingInlineItemIndex < inlineItems.size()) { 101 102 line.initialize(constraintsForLine(usedHorizontalValues, lineLogicalTop)); 102 auto lineInput = LineLayout::LineInput { inlineItems, leadingInlineItemIndex, leadingPartialContent }; 103 auto lineLayout = LineLayout { *this, lineInput, line }; 104 105 auto lineContent = lineLayout.layout(); 103 auto lineContent = lineLayout.layout(line, leadingInlineItemIndex, leadingPartialContent); 106 104 setDisplayBoxesForLine(lineContent, usedHorizontalValues); 107 105 … … 237 235 unsigned leadingInlineItemIndex = 0; 238 236 auto line = Line { *this, root().style().textAlign(), Line::SkipAlignment::Yes }; 237 auto lineLayout = LineLayout { *this, inlineItems }; 239 238 while (leadingInlineItemIndex < inlineItems.size()) { 240 239 // Only the horiztonal available width is constrained when computing intrinsic width. 241 240 line.initialize(Line::Constraints { { }, usedHorizontalValues.constraints.width, false, { } }); 242 auto lineInput = LineLayout::LineInput { inlineItems, leadingInlineItemIndex, { } }; 243 244 auto lineContent = LineLayout(*this, lineInput, line).layout(); 241 auto lineContent = lineLayout.layout(line, leadingInlineItemIndex, { }); 245 242 246 243 leadingInlineItemIndex = *lineContent.trailingInlineItemIndex + 1; -
trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.cpp
r252859 r252861 68 68 } 69 69 70 LineLayout::LineInput::LineInput(const InlineItems& inlineItems, unsigned leadingInlineItemIndex, Optional<PartialContent> leadingPartialContent)71 : inlineItems(inlineItems)72 , leadingInlineItemIndex(leadingInlineItemIndex)73 , leadingPartialContent(leadingPartialContent)74 {75 }76 77 70 void LineLayout::UncommittedContent::add(const InlineItem& inlineItem, LayoutUnit logicalWidth) 78 71 { … … 87 80 } 88 81 89 LineLayout::LineLayout(const InlineFormattingContext& inlineFormattingContext, const LineInput& lineInput, Line& line)82 LineLayout::LineLayout(const InlineFormattingContext& inlineFormattingContext, const InlineItems& inlineItems) 90 83 : m_inlineFormattingContext(inlineFormattingContext) 91 , m_lineInput(lineInput) 92 , m_line(line) 93 { 94 } 95 96 LineLayout::LineContent LineLayout::layout() 97 { 84 , m_inlineItems(inlineItems) 85 { 86 } 87 88 LineLayout::LineContent LineLayout::layout(Line& line, unsigned leadingInlineItemIndex, Optional<PartialContent> leadingPartialContent) 89 { 90 auto initialize = [&] { 91 m_committedInlineItemCount = 0; 92 m_uncommittedContent.reset(); 93 m_leadingPartialTextItem = { }; 94 m_trailingPartialTextItem = { }; 95 m_overflowTextLength = { }; 96 }; 97 initialize(); 98 98 // Iterate through the inline content and place the inline boxes on the current line. 99 99 // Start with the partial leading text from the previous line. 100 auto firstNonPartialInlineItemIndex = m_lineInput.leadingInlineItemIndex;101 if ( m_lineInput.leadingPartialContent) {100 auto firstNonPartialInlineItemIndex = leadingInlineItemIndex; 101 if (leadingPartialContent) { 102 102 // Handle partial inline item (split text from the previous line). 103 auto& leadingTextItem = m_ lineInput.inlineItems[m_lineInput.leadingInlineItemIndex];103 auto& leadingTextItem = m_inlineItems[leadingInlineItemIndex]; 104 104 RELEASE_ASSERT(leadingTextItem->isText()); 105 105 // Construct a partial leading inline item. 106 106 ASSERT(!m_leadingPartialTextItem); 107 m_leadingPartialTextItem = downcast<InlineTextItem>(*leadingTextItem).right( m_lineInput.leadingPartialContent->length);108 if (placeInlineItem( *m_leadingPartialTextItem) == IsEndOfLine::Yes)109 return close( );107 m_leadingPartialTextItem = downcast<InlineTextItem>(*leadingTextItem).right(leadingPartialContent->length); 108 if (placeInlineItem(line, *m_leadingPartialTextItem) == IsEndOfLine::Yes) 109 return close(line, leadingInlineItemIndex); 110 110 ++firstNonPartialInlineItemIndex; 111 111 } 112 112 113 for (auto inlineItemIndex = firstNonPartialInlineItemIndex; inlineItemIndex < m_ lineInput.inlineItems.size(); ++inlineItemIndex) {113 for (auto inlineItemIndex = firstNonPartialInlineItemIndex; inlineItemIndex < m_inlineItems.size(); ++inlineItemIndex) { 114 114 // FIXME: We should not need to re-measure the dropped, uncommitted content when re-using them on the next line. 115 if (placeInlineItem( *m_lineInput.inlineItems[inlineItemIndex]) == IsEndOfLine::Yes)116 return close( );115 if (placeInlineItem(line, *m_inlineItems[inlineItemIndex]) == IsEndOfLine::Yes) 116 return close(line, leadingInlineItemIndex); 117 117 } 118 118 // Check the uncommitted content whether they fit now that we know we are at a commit boundary. 119 119 if (!m_uncommittedContent.isEmpty()) 120 processUncommittedContent( );121 return close( );122 } 123 124 void LineLayout::commitPendingContent( )120 processUncommittedContent(line); 121 return close(line, leadingInlineItemIndex); 122 } 123 124 void LineLayout::commitPendingContent(Line& line) 125 125 { 126 126 if (m_uncommittedContent.isEmpty()) … … 128 128 m_committedInlineItemCount += m_uncommittedContent.size(); 129 129 for (auto& uncommittedRun : m_uncommittedContent.runs()) 130 m_line.append(uncommittedRun.inlineItem, uncommittedRun.logicalWidth);130 line.append(uncommittedRun.inlineItem, uncommittedRun.logicalWidth); 131 131 m_uncommittedContent.reset(); 132 132 } 133 133 134 LineLayout::LineContent LineLayout::close( )135 { 136 ASSERT(m_committedInlineItemCount || m_line.hasIntrusiveFloat());134 LineLayout::LineContent LineLayout::close(Line& line, unsigned leadingInlineItemIndex) 135 { 136 ASSERT(m_committedInlineItemCount || line.hasIntrusiveFloat()); 137 137 m_uncommittedContent.reset(); 138 138 if (!m_committedInlineItemCount) 139 return LineContent { { }, { }, WTFMove(m_floats), m_line.close(), m_line.lineBox() };139 return LineContent { { }, { }, WTFMove(m_floats), line.close(), line.lineBox() }; 140 140 141 141 Optional<PartialContent> overflowContent; 142 142 if (m_overflowTextLength) 143 143 overflowContent = PartialContent { *m_overflowTextLength }; 144 auto trailingInlineItemIndex = m_lineInput.leadingInlineItemIndex + m_committedInlineItemCount - 1;144 auto trailingInlineItemIndex = leadingInlineItemIndex + m_committedInlineItemCount - 1; 145 145 146 146 auto isLastLineWithInlineContent = [&] { … … 148 148 return Line::IsLastLineWithInlineContent::No; 149 149 // Skip floats backwards to see if this is going to be the last line with inline content. 150 for (auto i = m_ lineInput.inlineItems.size(); i--;) {151 if (!m_ lineInput.inlineItems[i]->isFloat())150 for (auto i = m_inlineItems.size(); i--;) { 151 if (!m_inlineItems[i]->isFloat()) 152 152 return i == trailingInlineItemIndex ? Line::IsLastLineWithInlineContent::Yes : Line::IsLastLineWithInlineContent::No; 153 153 } … … 157 157 }; 158 158 159 return LineContent { trailingInlineItemIndex, overflowContent, WTFMove(m_floats), m_line.close(isLastLineWithInlineContent()), m_line.lineBox() };160 } 161 162 LineLayout::IsEndOfLine LineLayout::placeInlineItem( const InlineItem& inlineItem)163 { 164 auto currentLogicalRight = m_line.lineBox().logicalRight();159 return LineContent { trailingInlineItemIndex, overflowContent, WTFMove(m_floats), line.close(isLastLineWithInlineContent()), line.lineBox() }; 160 } 161 162 LineLayout::IsEndOfLine LineLayout::placeInlineItem(Line& line, const InlineItem& inlineItem) 163 { 164 auto currentLogicalRight = line.lineBox().logicalRight(); 165 165 auto itemLogicalWidth = inlineItemWidth(formattingContext(), inlineItem, currentLogicalRight); 166 166 … … 172 172 // Let's just commit the pending content and try placing the float for now. 173 173 if (!m_uncommittedContent.isEmpty()) { 174 if (processUncommittedContent( ) == IsEndOfLine::Yes)174 if (processUncommittedContent(line) == IsEndOfLine::Yes) 175 175 return IsEndOfLine::Yes; 176 176 } 177 auto lineIsConsideredEmpty = m_line.isVisuallyEmpty() && !m_line.hasIntrusiveFloat();178 if (LineBreaker().shouldWrapFloatBox(itemLogicalWidth, m_line.availableWidth() + m_line.trailingTrimmableWidth(), lineIsConsideredEmpty))177 auto lineIsConsideredEmpty = line.isVisuallyEmpty() && !line.hasIntrusiveFloat(); 178 if (LineBreaker().shouldWrapFloatBox(itemLogicalWidth, line.availableWidth() + line.trailingTrimmableWidth(), lineIsConsideredEmpty)) 179 179 return IsEndOfLine::Yes; 180 180 … … 182 182 auto& floatBox = inlineItem.layoutBox(); 183 183 // Shrink available space for current line and move existing inline runs. 184 floatBox.isLeftFloatingPositioned() ? m_line.moveLogicalLeft(itemLogicalWidth) : m_line.moveLogicalRight(itemLogicalWidth);184 floatBox.isLeftFloatingPositioned() ? line.moveLogicalLeft(itemLogicalWidth) : line.moveLogicalRight(itemLogicalWidth); 185 185 m_floats.append(makeWeakPtr(inlineItem)); 186 186 ++m_committedInlineItemCount; 187 m_line.setHasIntrusiveFloat();187 line.setHasIntrusiveFloat(); 188 188 return IsEndOfLine::No; 189 189 } 190 190 // Forced line breaks are also special. 191 191 if (inlineItem.isForcedLineBreak()) { 192 auto isEndOfLine = !m_uncommittedContent.isEmpty() ? processUncommittedContent( ) : IsEndOfLine::No;192 auto isEndOfLine = !m_uncommittedContent.isEmpty() ? processUncommittedContent(line) : IsEndOfLine::No; 193 193 // When the uncommitted content fits(or the line is empty), add the line break to this line as well. 194 194 if (isEndOfLine == IsEndOfLine::No) { 195 195 m_uncommittedContent.add(inlineItem, itemLogicalWidth); 196 commitPendingContent( );196 commitPendingContent(line); 197 197 } 198 198 return IsEndOfLine::Yes; … … 201 201 auto isEndOfLine = IsEndOfLine::No; 202 202 if (!m_uncommittedContent.isEmpty() && shouldProcessUncommittedContent(inlineItem)) 203 isEndOfLine = processUncommittedContent( );203 isEndOfLine = processUncommittedContent(line); 204 204 // The current item might fit as well. 205 205 if (isEndOfLine == IsEndOfLine::No) … … 208 208 } 209 209 210 LineLayout::IsEndOfLine LineLayout::processUncommittedContent( )210 LineLayout::IsEndOfLine LineLayout::processUncommittedContent(Line& line) 211 211 { 212 212 // Check if the pending content fits. 213 auto lineIsConsideredEmpty = m_line.isVisuallyEmpty() && !m_line.hasIntrusiveFloat();214 auto breakingContext = LineBreaker().breakingContextForInlineContent(m_uncommittedContent.runs(), m_uncommittedContent.width(), m_line.availableWidth(), lineIsConsideredEmpty);213 auto lineIsConsideredEmpty = line.isVisuallyEmpty() && !line.hasIntrusiveFloat(); 214 auto breakingContext = LineBreaker().breakingContextForInlineContent(m_uncommittedContent.runs(), m_uncommittedContent.width(), line.availableWidth(), lineIsConsideredEmpty); 215 215 // The uncommitted content can fully, partially fit the current line (commit/partial commit) or not at all (reset). 216 216 if (breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Keep) 217 commitPendingContent( );217 commitPendingContent(line); 218 218 else if (breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Split) { 219 219 ASSERT(breakingContext.trailingPartialContent); … … 231 231 m_uncommittedContent.trim(overflowInlineTextItemIndex); 232 232 m_uncommittedContent.add(*m_trailingPartialTextItem, breakingContext.trailingPartialContent->logicalWidth); 233 commitPendingContent( );233 commitPendingContent(line); 234 234 } else if (breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Wrap) 235 235 m_uncommittedContent.reset(); -
trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.h
r252859 r252861 36 36 class LineLayout { 37 37 public: 38 struct LineInput; 39 LineLayout(const InlineFormattingContext&, const LineInput&, Line&); 40 41 struct LineContent; 42 LineContent layout(); 38 LineLayout(const InlineFormattingContext&, const InlineItems&); 43 39 44 40 struct PartialContent { … … 46 42 unsigned length; 47 43 }; 48 struct LineInput {49 LineInput(const InlineItems&, unsigned leadingInlineItemIndex, Optional<PartialContent> leadingPartialContent);50 51 const InlineItems& inlineItems;52 unsigned leadingInlineItemIndex { 0 };53 Optional<PartialContent> leadingPartialContent;54 Optional<LayoutUnit> floatMinimumLogicalBottom;55 };56 57 44 struct LineContent { 58 45 Optional<unsigned> trailingInlineItemIndex; … … 62 49 const LineBox lineBox; 63 50 }; 51 LineContent layout(Line&, unsigned leadingInlineItemIndex, Optional<PartialContent> leadingPartialContent); 64 52 65 53 struct Run { … … 73 61 const InlineFormattingContext& formattingContext() const { return m_inlineFormattingContext; } 74 62 enum class IsEndOfLine { No, Yes }; 75 IsEndOfLine placeInlineItem( const InlineItem&);76 void commitPendingContent( );77 LineContent close( );63 IsEndOfLine placeInlineItem(Line&, const InlineItem&); 64 void commitPendingContent(Line&); 65 LineContent close(Line&, unsigned leadingInlineItemIndex); 78 66 bool shouldProcessUncommittedContent(const InlineItem&) const; 79 IsEndOfLine processUncommittedContent( );67 IsEndOfLine processUncommittedContent(Line&); 80 68 81 69 struct UncommittedContent { … … 96 84 97 85 const InlineFormattingContext& m_inlineFormattingContext; 98 const LineInput& m_lineInput; 99 Line& m_line; 86 const InlineItems& m_inlineItems; 100 87 UncommittedContent m_uncommittedContent; 101 88 unsigned m_committedInlineItemCount { 0 };
Note: See TracChangeset
for help on using the changeset viewer.