Changeset 253928 in webkit
- Timestamp:
- Dec 28, 2019 4:19:44 PM (4 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r253926 r253928 1 2019-12-28 Zalan Bujtas <zalan@apple.com> 2 3 [LFC][IFC] Keep track of last line wrap opportunity 4 https://bugs.webkit.org/show_bug.cgi?id=205619 5 <rdar://problem/58227112> 6 7 Reviewed by Antti Koivisto. 8 9 This is in preparation for being able to revert back to an earlier position 10 of the current line as the line wrapping opportunity. 11 (actually the m_lastWrapOpportunity is already taken into use at LineBreaker::wordBreakBehavior) 12 13 * layout/inlineformatting/InlineLineBreaker.cpp: 14 (WebCore::Layout::shouldKeepBeginningOfLineWhitespace): 15 (WebCore::Layout::LineBreaker::shouldWrapInlineContent): 16 (WebCore::Layout::LineBreaker::shouldWrapFloatBox): 17 (WebCore::Layout::LineBreaker::tryWrappingInlineContent const): 18 (WebCore::Layout::LineBreaker::wrapTextContent const): 19 (WebCore::Layout::LineBreaker::wordBreakBehavior const): 20 (WebCore::Layout::LineBreaker::tryBreakingTextRun const): 21 (WebCore::Layout::LineBreaker::ContinousContent::lastWrapOpportunityIndex const): 22 * layout/inlineformatting/InlineLineBreaker.h: 23 1 24 2019-12-25 Dean Jackson <dino@apple.com> 2 25 -
trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp
r253924 r253928 44 44 } 45 45 46 static inline bool shouldKeepBeginningOfLineWhitespace(const RenderStyle& style) 47 { 48 auto whitespace = style.whiteSpace(); 49 return whitespace == WhiteSpace::Pre || whitespace == WhiteSpace::PreWrap || whitespace == WhiteSpace::BreakSpaces; 50 } 51 46 52 bool LineBreaker::isContentWrappingAllowed(const ContinousContent& candidateRuns) const 47 53 { … … 65 71 auto candidateContent = ContinousContent { candidateRuns }; 66 72 ASSERT(!candidateContent.isEmpty()); 73 auto result = tryWrappingInlineContent(candidateContent, lineStatus); 74 // If this is not the end of the line, hold on to the last eligible line wrap opportunity so that we could revert back 75 // to this position if no other line breaking opportunity exists in this content. 76 if (result.isEndOfLine == IsEndOfLine::Yes) 77 return result; 78 if (auto lastLineWrapOpportunityIndex = candidateContent.lastWrapOpportunityIndex()) { 79 auto isEligibleLineWrapOpportunity = [&] (auto& candidateItem) { 80 // Just check for leading collapsible whitespace for now. 81 if (!lineStatus.lineIsEmpty || !candidateItem.isText() || !downcast<InlineTextItem>(candidateItem).isWhitespace()) 82 return true; 83 return shouldKeepBeginningOfLineWhitespace(candidateItem.style()); 84 }; 85 auto& inlineItem = candidateContent.runs()[*lastLineWrapOpportunityIndex].inlineItem; 86 if (isEligibleLineWrapOpportunity(inlineItem)) 87 m_lastWrapOpportunity = &inlineItem; 88 } 89 return result; 90 } 91 92 LineBreaker::Result LineBreaker::tryWrappingInlineContent(const ContinousContent& candidateContent, const LineStatus& lineStatus) const 93 { 67 94 if (candidateContent.width() <= lineStatus.availableWidth) 68 95 return { Result::Action::Keep, IsEndOfLine::No, { } }; … … 114 141 // If we are not allowed to break this content, we still need to decide whether keep it or push it to the next line. 115 142 auto isWrappingAllowed = isContentWrappingAllowed(candidateContent); 116 auto contentOverflows= lineStatus.lineIsEmpty || !isWrappingAllowed;117 if (! contentOverflows)143 auto letContentOverflow = lineStatus.lineIsEmpty || !isWrappingAllowed; 144 if (!letContentOverflow) 118 145 return { Result::Action::Push, IsEndOfLine::Yes, { } }; 119 146 return { Result::Action::Keep, isWrappingAllowed ? IsEndOfLine::Yes : IsEndOfLine::No, { } }; … … 149 176 // When the first span computes longer than the available space, by the time we get to the second span, the adjusted available space becomes negative. 150 177 auto adjustedAvailableWidth = std::max<InlineLayoutUnit>(0, lineStatus.availableWidth - accumulatedRunWidth); 151 if (auto partialRun = tryBreakingTextRun(run, adjustedAvailableWidth, lineStatus.lineIsEmpty)) {178 if (auto partialRun = tryBreakingTextRun(run, adjustedAvailableWidth)) { 152 179 if (partialRun->length) 153 180 return WrappedTextContent { index, false, partialRun }; … … 170 197 if (isContentSplitAllowed(run)) { 171 198 ASSERT(run.inlineItem.isText()); 172 if (auto partialRun = tryBreakingTextRun(run, maxInlineLayoutUnit() , lineStatus.lineIsEmpty)) {199 if (auto partialRun = tryBreakingTextRun(run, maxInlineLayoutUnit())) { 173 200 // We know this run fits, so if wrapping is allowed on the run, it should return a non-empty left-side. 174 201 ASSERT(partialRun->length); … … 181 208 } 182 209 183 LineBreaker::WordBreakRule LineBreaker::wordBreakBehavior(const RenderStyle& style , bool lineIsEmpty) const210 LineBreaker::WordBreakRule LineBreaker::wordBreakBehavior(const RenderStyle& style) const 184 211 { 185 212 // Disregard any prohibition against line breaks mandated by the word-break property. … … 195 222 // For compatibility with legacy content, the word-break property also supports a deprecated break-word keyword. 196 223 // When specified, this has the same effect as word-break: normal and overflow-wrap: anywhere, regardless of the actual value of the overflow-wrap property. 197 if (style.wordBreak() == WordBreak::BreakWord && lineIsEmpty)224 if (style.wordBreak() == WordBreak::BreakWord && !m_lastWrapOpportunity) 198 225 return WordBreakRule::AtArbitraryPosition; 199 226 // OverflowWrap::Break: An otherwise unbreakable sequence of characters may be broken at an arbitrary point if there are no otherwise-acceptable break points in the line. 200 if (style.overflowWrap() == OverflowWrap::Break && lineIsEmpty)227 if (style.overflowWrap() == OverflowWrap::Break && !m_lastWrapOpportunity) 201 228 return WordBreakRule::AtArbitraryPosition; 202 229 … … 207 234 } 208 235 209 Optional<LineBreaker::PartialRun> LineBreaker::tryBreakingTextRun(const Run& overflowRun, InlineLayoutUnit availableWidth , bool lineIsEmpty) const236 Optional<LineBreaker::PartialRun> LineBreaker::tryBreakingTextRun(const Run& overflowRun, InlineLayoutUnit availableWidth) const 210 237 { 211 238 ASSERT(overflowRun.inlineItem.isText()); … … 214 241 auto findLastBreakablePosition = availableWidth == maxInlineLayoutUnit(); 215 242 216 auto breakRule = wordBreakBehavior(style , lineIsEmpty);243 auto breakRule = wordBreakBehavior(style); 217 244 if (breakRule == WordBreakRule::AtArbitraryPosition) { 218 245 if (findLastBreakablePosition) { … … 498 525 } 499 526 527 Optional<size_t> LineBreaker::ContinousContent::lastWrapOpportunityIndex() const 528 { 529 // <span style="white-space: pre">no_wrap</span><span>yes_wrap</span><span style="white-space: pre">no_wrap</span>. 530 // [container start][no_wrap][container end][container start][yes_wrap][container end][container start][no_wrap][container end] 531 // Return #5 as the index where this content can wrap at last. 532 for (auto index = m_runs.size(); index--;) { 533 if (isWrappingAllowed(m_runs[index].inlineItem.style())) 534 return index; 535 } 536 return { }; 537 } 538 500 539 void LineBreaker::ContinousContent::TrailingCollapsibleContent::reset() 501 540 { … … 504 543 } 505 544 506 507 545 } 508 546 } -
trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.h
r253924 r253928 105 105 bool hasTrailingCollapsibleContent() const { return !!m_trailingCollapsibleContent.width; } 106 106 bool isTrailingContentFullyCollapsible() const { return m_trailingCollapsibleContent.isFullyCollapsible; } 107 Optional<size_t> lastWrapOpportunityIndex() const; 107 108 108 109 Optional<unsigned> firstTextRunIndex() const; … … 127 128 }; 128 129 Optional<WrappedTextContent> wrapTextContent(const RunList&, const LineStatus&) const; 129 Optional<PartialRun> tryBreakingTextRun(const Run& overflowRun, InlineLayoutUnit availableWidth, bool lineIsEmpty) const; 130 Result tryWrappingInlineContent(const ContinousContent&, const LineStatus&) const; 131 Optional<PartialRun> tryBreakingTextRun(const Run& overflowRun, InlineLayoutUnit availableWidth) const; 130 132 131 133 enum class WordBreakRule { … … 134 136 OnlyHyphenationAllowed 135 137 }; 136 WordBreakRule wordBreakBehavior(const RenderStyle& , bool lineIsEmpty) const;138 WordBreakRule wordBreakBehavior(const RenderStyle&) const; 137 139 bool shouldKeepEndOfLineWhitespace(const ContinousContent&) const; 138 140 bool isContentWrappingAllowed(const ContinousContent&) const; 139 141 140 142 bool n_hyphenationIsDisabled { false }; 143 const InlineItem* m_lastWrapOpportunity { nullptr }; 141 144 }; 142 145
Note: See TracChangeset
for help on using the changeset viewer.