Changeset 256524 in webkit
- Timestamp:
- Feb 13, 2020 11:05:29 AM (4 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r256514 r256524 1 2020-02-13 Zalan Bujtas <zalan@apple.com> 2 3 [LFC][IFC] LineBreaker should not hold on to the lastWrapOpportunity inline item 4 https://bugs.webkit.org/show_bug.cgi?id=207707 5 <rdar://problem/59427376> 6 7 Reviewed by Antti Koivisto. 8 9 LineBreaker only needs a flag indicating that there's a wrapping opportunity on the line. 10 LineLayoutContext needs to know what the position is (as an InlineItem) so that it could initiate a revert if needed. 11 12 * layout/inlineformatting/InlineLineBreaker.cpp: 13 (WebCore::Layout::LineBreaker::shouldWrapInlineContent): 14 (WebCore::Layout::LineBreaker::tryWrappingInlineContent const): 15 (WebCore::Layout::LineBreaker::wordBreakBehavior const): 16 * layout/inlineformatting/InlineLineBreaker.h: 17 * layout/inlineformatting/LineLayoutContext.cpp: 18 (WebCore::Layout::LineLayoutContext::layoutLine): 19 (WebCore::Layout::LineLayoutContext::tryAddingFloatItem): 20 (WebCore::Layout::LineLayoutContext::tryAddingInlineItems): 21 (WebCore::Layout::LineLayoutContext::rebuildLine): 22 (WebCore::Layout::LineLayoutContext::rebuildLineForRevert): Deleted. 23 * layout/inlineformatting/LineLayoutContext.h: 24 (WebCore::Layout::LineLayoutContext::InlineItemRange::size const): 25 1 26 2020-02-13 Adrian Perez de Castro <aperez@igalia.com> 2 27 -
trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp
r256304 r256524 140 140 return shouldKeepBeginningOfLineWhitespace(candidateItem.style()); 141 141 }; 142 auto& inlineItem = candidateRuns[*lastLineWrapOpportunityIndex].inlineItem; 143 if (isEligibleLineWrapOpportunity(inlineItem)) 144 m_lastWrapOpportunity = &inlineItem; 142 auto& lastWrapOpportunityCandidateItem = candidateRuns[*lastLineWrapOpportunityIndex].inlineItem; 143 if (isEligibleLineWrapOpportunity(lastWrapOpportunityCandidateItem)) { 144 result.lastWrapOpportunityItem = &lastWrapOpportunityCandidateItem; 145 m_hasWrapOpportunityAtPreviousPosition = true; 146 } 145 147 } 146 148 } … … 201 203 // If we are not allowed to break this overflowing content, we still need to decide whether keep it or push it to the next line. 202 204 if (lineStatus.lineIsEmpty) { 203 ASSERT(!m_ lastWrapOpportunity);205 ASSERT(!m_hasWrapOpportunityAtPreviousPosition); 204 206 return { Result::Action::Keep, IsEndOfLine::No }; 205 207 } … … 207 209 if (isContentWrappingAllowed(candidateContent)) 208 210 return { Result::Action::Push, IsEndOfLine::Yes }; 209 if (m_ lastWrapOpportunity)210 return { Result::Action::Revert , IsEndOfLine::Yes, { }, m_lastWrapOpportunity};211 if (m_hasWrapOpportunityAtPreviousPosition) 212 return { Result::Action::RevertToLastWrapOpportunity, IsEndOfLine::Yes }; 211 213 return { Result::Action::Keep, IsEndOfLine::No }; 212 214 } … … 287 289 // For compatibility with legacy content, the word-break property also supports a deprecated break-word keyword. 288 290 // 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. 289 if (style.wordBreak() == WordBreak::BreakWord && !m_ lastWrapOpportunity)291 if (style.wordBreak() == WordBreak::BreakWord && !m_hasWrapOpportunityAtPreviousPosition) 290 292 return WordBreakRule::AtArbitraryPosition; 291 293 // 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. 292 if (style.overflowWrap() == OverflowWrap::Break && !m_ lastWrapOpportunity)294 if (style.overflowWrap() == OverflowWrap::Break && !m_hasWrapOpportunityAtPreviousPosition) 293 295 return WordBreakRule::AtArbitraryPosition; 294 296 -
trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.h
r254721 r256524 54 54 Split, // Partial content is on the current line. 55 55 Push, // Content is pushed to the next line. 56 Revert // The current content overflows and can't get wrapped. The line needs to be reverted back to the last line wrapping opportunity.56 RevertToLastWrapOpportunity // The current content overflows and can't get wrapped. The line needs to be reverted back to the last line wrapping opportunity. 57 57 }; 58 58 struct PartialTrailingContent { … … 64 64 IsEndOfLine isEndOfLine { IsEndOfLine::No }; 65 65 Optional<PartialTrailingContent> partialTrailingContent { }; 66 const InlineItem* revertTo{ nullptr };66 const InlineItem* lastWrapOpportunityItem { nullptr }; 67 67 }; 68 68 … … 112 112 113 113 bool n_hyphenationIsDisabled { false }; 114 const InlineItem* m_lastWrapOpportunity { nullptr};114 bool m_hasWrapOpportunityAtPreviousPosition { false }; 115 115 }; 116 116 -
trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp
r256507 r256524 263 263 ASSERT(m_floats.isEmpty()); 264 264 m_partialLeadingTextItem = { }; 265 m_lastWrapOpportunityItem = { }; 265 266 auto lineBreaker = LineBreaker { }; 266 267 auto currentItemIndex = layoutRange.start; … … 276 277 // Floats shrink the available horizontal space for the rest of the content, but they are not added on the line. 277 278 auto result = tryAddingFloatItem(line, *lineCandidate.floatItem); 278 committedInlineItemCount += result.committedCount ;279 committedInlineItemCount += result.committedCount.value; 279 280 if (result.isEndOfLine == LineBreaker::IsEndOfLine::Yes) { 280 281 // This float takes up all the horizontal space. … … 286 287 if (!inlineContent.runs().isEmpty()) { 287 288 // Now check if we can put this content on the current line. 288 auto result = tryAddingInlineItems(lineBreaker, line, lineCandidate); 289 if (result.revertTo) { 290 ASSERT(!result.committedCount); 291 ASSERT(result.isEndOfLine == LineBreaker::IsEndOfLine::Yes); 292 // An earlier line wrapping opportunity turned out to be the final breaking position. 293 rebuildLineForRevert(line, *result.revertTo, layoutRange); 294 } 295 committedInlineItemCount += result.committedCount; 289 auto result = tryAddingInlineItems(lineBreaker, line, layoutRange, lineCandidate); 290 committedInlineItemCount = result.committedCount.isRevert ? result.committedCount.value : committedInlineItemCount + result.committedCount.value; 296 291 if (result.isEndOfLine == LineBreaker::IsEndOfLine::Yes) { 297 292 // We can't place any more items on the current line. … … 402 397 line.moveLogicalRight(logicalWidth); 403 398 m_floats.append(&floatItem); 404 return { LineBreaker::IsEndOfLine::No, 1};405 } 406 407 LineLayoutContext::Result LineLayoutContext::tryAddingInlineItems(LineBreaker& lineBreaker, LineBuilder& line, const LineCandidate& lineCandidate)399 return { LineBreaker::IsEndOfLine::No, { 1, false } }; 400 } 401 402 LineLayoutContext::Result LineLayoutContext::tryAddingInlineItems(LineBreaker& lineBreaker, LineBuilder& line, const InlineItemRange& layoutRange, const LineCandidate& lineCandidate) 408 403 { 409 404 auto shouldDisableHyphenation = [&] { … … 421 416 auto& candidateRuns = inlineContent.runs(); 422 417 auto result = lineBreaker.shouldWrapInlineContent(candidateRuns, inlineContent.logicalWidth(), lineStatus); 418 if (result.lastWrapOpportunityItem) 419 m_lastWrapOpportunityItem = result.lastWrapOpportunityItem; 423 420 if (result.action == LineBreaker::Result::Action::Keep) { 424 421 // This continuous content can be fully placed on the current line. … … 428 425 if (auto* lineBreakItem = inlineContent.trailingLineBreak()) { 429 426 line.append(*lineBreakItem, 0); 430 return { LineBreaker::IsEndOfLine::Yes, candidateRuns.size() + 1};431 } 432 return { result.isEndOfLine, candidateRuns.size()};427 return { LineBreaker::IsEndOfLine::Yes, { candidateRuns.size() + 1, false } }; 428 } 429 return { result.isEndOfLine, { candidateRuns.size(), false } }; 433 430 } 434 431 if (result.action == LineBreaker::Result::Action::Push) { 432 ASSERT(result.isEndOfLine == LineBreaker::IsEndOfLine::Yes); 435 433 // This continuous content can't be placed on the current line. Nothing to commit at this time. 436 434 return { result.isEndOfLine }; 437 435 } 438 if (result.action == LineBreaker::Result::Action::Revert) { 436 if (result.action == LineBreaker::Result::Action::RevertToLastWrapOpportunity) { 437 ASSERT(result.isEndOfLine == LineBreaker::IsEndOfLine::Yes); 439 438 // Not only this content can't be placed on the current line, but we even need to revert the line back to an earlier position. 440 return { result.isEndOfLine, 0, { }, result.revertTo }; 439 ASSERT(m_lastWrapOpportunityItem); 440 return { result.isEndOfLine, { rebuildLine(line, layoutRange), true } }; 441 441 } 442 442 if (result.action == LineBreaker::Result::Action::Split) { 443 ASSERT(result.isEndOfLine == LineBreaker::IsEndOfLine::Yes); 443 444 // Commit the combination of full and partial content on the current line. 444 445 ASSERT(result.partialTrailingContent); … … 449 450 auto committedInlineItemCount = trailingRunIndex + 1; 450 451 if (!result.partialTrailingContent->partialRun) 451 return { result.isEndOfLine, committedInlineItemCount};452 return { result.isEndOfLine, { committedInlineItemCount, false } }; 452 453 453 454 auto partialRun = *result.partialTrailingContent->partialRun; 454 455 auto& trailingInlineTextItem = downcast<InlineTextItem>(candidateRuns[trailingRunIndex].inlineItem); 455 456 auto overflowLength = trailingInlineTextItem.length() - partialRun.length; 456 return { result.isEndOfLine, committedInlineItemCount, LineContent::PartialContent { partialRun.needsHyphen, overflowLength } };457 return { result.isEndOfLine, { committedInlineItemCount, false }, LineContent::PartialContent { partialRun.needsHyphen, overflowLength } }; 457 458 } 458 459 ASSERT_NOT_REACHED(); … … 481 482 } 482 483 483 void LineLayoutContext::rebuildLineForRevert(LineBuilder& line, const InlineItem& revertTo, const InlineItemRangelayoutRange)484 { 485 // This is the rare case when the line needs to be reverted to an earlier position.484 size_t LineLayoutContext::rebuildLine(LineBuilder& line, const InlineItemRange& layoutRange) 485 { 486 // Clear the line and start appending the inline items closing with the last wrap opportunity run. 486 487 line.resetContent(); 487 auto inlineItemIndex = layoutRange.start;488 InlineLayoutUnit logicalRight ={ };488 auto currentItemIndex = layoutRange.start; 489 auto logicalRight = InlineLayoutUnit { }; 489 490 if (m_partialLeadingTextItem) { 490 491 auto logicalWidth = inlineItemWidth(*m_partialLeadingTextItem, logicalRight); 491 492 line.append(*m_partialLeadingTextItem, logicalWidth); 492 493 logicalRight += logicalWidth; 493 if (&revertTo == &m_partialLeadingTextItem.value()) 494 return; 495 ++inlineItemIndex; 496 } 497 498 for (; inlineItemIndex < layoutRange.end; ++inlineItemIndex) { 499 auto& inlineItem = m_inlineItems[inlineItemIndex]; 494 if (&m_partialLeadingTextItem.value() == m_lastWrapOpportunityItem) 495 return 1; 496 ++currentItemIndex; 497 } 498 for (; currentItemIndex < layoutRange.end; ++currentItemIndex) { 499 auto& inlineItem = m_inlineItems[currentItemIndex]; 500 500 auto logicalWidth = inlineItemWidth(inlineItem, logicalRight); 501 501 line.append(inlineItem, logicalWidth); 502 502 logicalRight += logicalWidth; 503 if (&inlineItem == &revertTo) 504 break; 505 } 503 if (&inlineItem == m_lastWrapOpportunityItem) 504 return currentItemIndex - layoutRange.start + 1; 505 } 506 return layoutRange.size(); 506 507 } 507 508 -
trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h
r256507 r256524 53 53 struct InlineItemRange { 54 54 bool isEmpty() const { return start == end; } 55 size_t size() const { return end - start; } 55 56 size_t start { 0 }; 56 57 size_t end { 0 }; … … 62 63 struct Result { 63 64 LineBreaker::IsEndOfLine isEndOfLine { LineBreaker::IsEndOfLine::No }; 64 size_t committedCount { 0 }; 65 struct CommittedContentCount { 66 size_t value { 0 }; 67 bool isRevert { false }; 68 }; 69 CommittedContentCount committedCount { }; 65 70 Optional <LineContent::PartialContent> partialContent { }; 66 const InlineItem* revertTo { nullptr };67 71 }; 68 72 Result tryAddingFloatItem(LineBuilder&, const InlineItem& floatItem); 69 Result tryAddingInlineItems(LineBreaker&, LineBuilder&, const LineCandidate&);70 void rebuildLineForRevert(LineBuilder&, const InlineItem& revertTo, const InlineItemRangelayoutRange);73 Result tryAddingInlineItems(LineBreaker&, LineBuilder&, const InlineItemRange& layoutRange, const LineCandidate&); 74 size_t rebuildLine(LineBuilder&, const InlineItemRange& layoutRange); 71 75 void commitPartialContent(LineBuilder&, const LineBreaker::RunList&, const LineBreaker::Result::PartialTrailingContent&); 72 76 LineContent close(LineBuilder&, const InlineItemRange layoutRange, unsigned committedInlineItemCount, Optional<LineContent::PartialContent>); … … 83 87 FloatList m_floats; 84 88 Optional<InlineTextItem> m_partialLeadingTextItem; 89 const InlineItem* m_lastWrapOpportunityItem { nullptr }; 85 90 unsigned m_successiveHyphenatedLineCount { 0 }; 86 91 };
Note: See TracChangeset
for help on using the changeset viewer.