Changeset 267637 in webkit
- Timestamp:
- Sep 26, 2020, 2:31:49 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 7 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/fast/layoutformattingcontext/wbr-simple-expected.html (added)
-
LayoutTests/fast/layoutformattingcontext/wbr-simple.html (added)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp (modified) (2 diffs)
-
Source/WebCore/layout/inlineformatting/InlineItem.h (modified) (2 diffs)
-
Source/WebCore/layout/inlineformatting/InlineLine.cpp (modified) (4 diffs)
-
Source/WebCore/layout/inlineformatting/InlineLine.h (modified) (2 diffs)
-
Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r267622 r267637 1 2020-09-26 Zalan Bujtas <zalan@apple.com> 2 3 [LFC][IFC] Add support for <wbr> 4 https://bugs.webkit.org/show_bug.cgi?id=217014 5 6 Reviewed by Antti Koivisto. 7 8 * fast/layoutformattingcontext/wbr-simple-expected.html: Added. 9 * fast/layoutformattingcontext/wbr-simple.html: Added. 10 1 11 2020-09-26 Zalan Bujtas <zalan@apple.com> 2 12 -
trunk/Source/WebCore/ChangeLog
r267625 r267637 1 2020-09-26 Zalan Bujtas <zalan@apple.com> 2 3 [LFC][IFC] Add support for <wbr> 4 https://bugs.webkit.org/show_bug.cgi?id=217014 5 6 Reviewed by Antti Koivisto. 7 8 Introduce the WordBreakOpportunity type of InlineItem and take it into account while searching for word break opportunities. 9 It generates an empty line run but it does not yet have geometry information. 10 11 Test: fast/layoutformattingcontext/wbr-simple.html 12 13 * layout/inlineformatting/InlineFormattingContext.cpp: 14 (WebCore::Layout::InlineFormattingContext::collectInlineContentIfNeeded): 15 * layout/inlineformatting/InlineItem.h: 16 (WebCore::Layout::InlineItem::isWordBreakOpportunity const): 17 * layout/inlineformatting/InlineLine.cpp: 18 (WebCore::Layout::Line::appendWith): 19 (WebCore::Layout::Line::appendTextContent): 20 (WebCore::Layout::Line::appendWordBreakOpportunity): 21 * layout/inlineformatting/InlineLine.h: 22 (WebCore::Layout::Line::Run::isWordBreakOpportunity const): 23 * layout/inlineformatting/InlineLineBuilder.cpp: 24 (WebCore::Layout::nextWrapOpportunity): 25 (WebCore::Layout::LineCandidate::InlineContent::appendInlineItem): 26 (WebCore::Layout::LineBuilder::inlineItemWidth const): 27 (WebCore::Layout::LineBuilder::nextContentForLine): 28 1 29 2020-09-26 Alex Christensen <achristensen@webkit.org> 2 30 -
trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp
r267461 r267637 41 41 #include "LayoutInitialContainingBlock.h" 42 42 #include "LayoutInlineTextBox.h" 43 #include "LayoutLineBreakBox.h" 43 44 #include "LayoutReplacedBox.h" 44 45 #include "LayoutState.h" … … 371 372 while (!layoutQueue.isEmpty()) { 372 373 auto& layoutBox = *layoutQueue.takeLast(); 373 if ( layoutBox.isLineBreakBox()) {374 // FIXME: Treat <wbr> as a word break opportunity instead.375 formattingState.addInlineItem({ layoutBox, InlineItem::Type::HardLineBreak });374 if (is<LineBreakBox>(layoutBox)) { 375 auto& lineBreakBox = downcast<LineBreakBox>(layoutBox); 376 formattingState.addInlineItem({ layoutBox, lineBreakBox.isOptional() ? InlineItem::Type::WordBreakOpportunity : InlineItem::Type::HardLineBreak }); 376 377 } else if (layoutBox.isFloatingPositioned()) 377 378 formattingState.addInlineItem({ layoutBox, InlineItem::Type::Float }); -
trunk/Source/WebCore/layout/inlineformatting/InlineItem.h
r255268 r267637 36 36 class InlineItem { 37 37 public: 38 enum class Type : uint8_t { Text, HardLineBreak, SoftLineBreak, Box, Float, ContainerStart, ContainerEnd };38 enum class Type : uint8_t { Text, HardLineBreak, SoftLineBreak, WordBreakOpportunity, Box, Float, ContainerStart, ContainerEnd }; 39 39 InlineItem(const Box& layoutBox, Type); 40 40 … … 47 47 bool isFloat() const { return type() == Type::Float; } 48 48 bool isLineBreak() const { return isSoftLineBreak() || isHardLineBreak(); } 49 bool isWordBreakOpportunity() const { return type() == Type::WordBreakOpportunity; } 49 50 bool isSoftLineBreak() const { return type() == Type::SoftLineBreak; } 50 51 bool isHardLineBreak() const { return type() == Type::HardLineBreak; } -
trunk/Source/WebCore/layout/inlineformatting/InlineLine.cpp
r267622 r267637 225 225 else if (inlineItem.isLineBreak()) 226 226 appendLineBreak(inlineItem); 227 else if (inlineItem.isWordBreakOpportunity()) 228 appendWordBreakOpportunity(inlineItem); 227 229 else if (inlineItem.isContainerStart()) 228 230 appendInlineContainerStart(inlineItem, inlineRunDetails.logicalWidth); … … 285 287 if (run.isText()) 286 288 return run.hasCollapsibleTrailingWhitespace(); 287 ASSERT(run.isContainerStart() || run.isContainerEnd() );289 ASSERT(run.isContainerStart() || run.isContainerEnd() || run.isWordBreakOpportunity()); 288 290 } 289 291 // Leading whitespace. … … 349 351 } 350 352 353 void Line::appendWordBreakOpportunity(const InlineItem& inlineItem) 354 { 355 m_runs.append({ inlineItem, contentLogicalWidth(), 0_lu }); 356 } 357 351 358 bool Line::isRunVisuallyNonEmpty(const Run& run) const 352 359 { … … 375 382 } 376 383 384 if (run.isWordBreakOpportunity()) 385 return false; 386 377 387 ASSERT_NOT_REACHED(); 378 388 return false; -
trunk/Source/WebCore/layout/inlineformatting/InlineLine.h
r267515 r267637 67 67 bool isBox() const { return m_type == InlineItem::Type::Box; } 68 68 bool isLineBreak() const { return m_type == InlineItem::Type::HardLineBreak || m_type == InlineItem::Type::SoftLineBreak; } 69 bool isWordBreakOpportunity() const { return m_type == InlineItem::Type::WordBreakOpportunity; } 69 70 bool isContainerStart() const { return m_type == InlineItem::Type::ContainerStart; } 70 71 bool isContainerEnd() const { return m_type == InlineItem::Type::ContainerEnd; } … … 144 145 void appendInlineContainerEnd(const InlineItem&, InlineLayoutUnit logicalWidth); 145 146 void appendLineBreak(const InlineItem&); 147 void appendWordBreakOpportunity(const InlineItem&); 146 148 147 149 void removeTrailingTrimmableContent(); -
trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp
r267617 r267637 111 111 static inline size_t nextWrapOpportunity(const InlineItems& inlineContent, size_t startIndex, const LineBuilder::InlineItemRange layoutRange) 112 112 { 113 // 1. Find the start candidate by skipping leading non-content items e.g <span><span>start : skip "<span><span>"114 // 2. Find the end candidate by skipping non-content items inbetween e.g. <span><span>start</span>end: skip "</span>"113 // 1. Find the start candidate by skipping leading non-content items e.g "<span><span>start". Opportunity is after "<span><span>". 114 // 2. Find the end candidate by skipping non-content items inbetween e.g. "<span><span>start</span>end". Opportunity is after "</span>". 115 115 // 3. Check if there's a soft wrap opportunity between the 2 candidate inline items and repeat. 116 // 4. Any force line break inbetween is considered as a wrap opportunity. 117 118 // [ex-][container start][container end][float][ample] (ex-<span></span><div style="float:left"></div>ample) : wrap index is at [ex-]. 119 // [ex][container start][amp-][container start][le] (ex<span>amp-<span>ample) : wrap index is at [amp-]. 120 // [ex-][container start][line break][ample] (ex-<span><br>ample) : wrap index is after [br]. 121 auto isAtLineBreak = false; 122 123 auto inlineItemIndexWithContent = [&] (auto index) { 124 // Note that floats are not part of the inline content. We should treat them as if they were not here as far as wrap opportunities are concerned. 125 // [text][float box][text] is essentially just [text][text] 126 for (; index < layoutRange.end; ++index) { 127 auto& inlineItem = inlineContent[index]; 128 if (inlineItem.isText() || inlineItem.isBox()) 129 return index; 130 if (inlineItem.isLineBreak()) { 131 isAtLineBreak = true; 132 return index; 133 } 134 } 135 return layoutRange.end; 136 }; 137 138 // Start at the first inline item with content. 139 // [container start][ex-] : start at [ex-] 140 auto startContentIndex = inlineItemIndexWithContent(startIndex); 141 if (isAtLineBreak) { 142 // Content starts with a line break. The wrap position is after the line break. 143 return startContentIndex + 1; 144 } 145 146 while (startContentIndex < layoutRange.end) { 147 // 1. Find the next inline item with content. 148 // 2. Check if there's a soft wrap opportunity between the start and the next inline item. 149 auto nextContentIndex = inlineItemIndexWithContent(startContentIndex + 1); 150 if (nextContentIndex == layoutRange.end) 151 return nextContentIndex; 152 if (isAtLineBreak) { 153 // We always stop at line breaks. The wrap position is after the line break. 154 return nextContentIndex + 1; 155 } 156 if (isAtSoftWrapOpportunity(inlineContent[startContentIndex], inlineContent[nextContentIndex])) { 157 // There's a soft wrap opportunity between the start and the nextContent. 116 // 4. Any force line break/explicit wrap content inbetween is considered as wrap opportunity. 117 118 // [ex-][container start][container end][float][ample] (ex-<span></span><div style="float:left"></div>ample). Wrap index is at [ex-]. 119 // [ex][container start][amp-][container start][le] (ex<span>amp-<span>ample). Wrap index is at [amp-]. 120 // [ex-][container start][line break][ample] (ex-<span><br>ample). Wrap index is after [br]. 121 auto previousInlineItemIndex = Optional<size_t> { }; 122 for (auto index = startIndex; index < layoutRange.end; ++index) { 123 auto& inlineItem = inlineContent[index]; 124 if (inlineItem.isLineBreak() || inlineItem.isWordBreakOpportunity()) { 125 // We always stop at explicit wrapping opportunities e.g. <br>. The wrap position is after the opportunity position. 126 return ++index; 127 } 128 if (inlineItem.isFloat()) { 129 // Floats are not part of the inline content. We ignore them as far as wrap opportunities are concerned. 130 // [text][float box][text] is essentially just [text][text] 131 continue; 132 } 133 if (inlineItem.isContainerStart() || inlineItem.isContainerEnd()) { 134 // There's no wrapping opportunity between <span>text, <span></span> or </span>text. 135 continue; 136 } 137 ASSERT(inlineItem.isText() || inlineItem.isBox()); 138 if (!previousInlineItemIndex) { 139 previousInlineItemIndex = index; 140 continue; 141 } 142 if (isAtSoftWrapOpportunity(inlineContent[*previousInlineItemIndex], inlineContent[index])) { 143 // There's a soft wrap opportunity between 'previousInlineItemIndex' and 'index'. 158 144 // Now forward-find from the start position to see where we can actually wrap. 159 145 // [ex-][ample] vs. [ex-][container start][container end][ample] 160 146 // where [ex-] is startContent and [ample] is the nextContent. 161 for (auto candidateIndex = startContentIndex + 1; candidateIndex < nextContentIndex; ++candidateIndex) {147 for (auto candidateIndex = *previousInlineItemIndex + 1; candidateIndex < index; ++candidateIndex) { 162 148 if (inlineContent[candidateIndex].isContainerStart()) { 163 149 // inline content and [container start] and [container end] form unbreakable content. … … 169 155 } 170 156 } 171 return nextContentIndex;172 } 173 startContentIndex = nextContentIndex;157 return index; 158 } 159 previousInlineItemIndex = index; 174 160 } 175 161 return layoutRange.end; … … 248 234 return inlineTextItem.isWhitespace() && !TextUtil::shouldPreserveTrailingWhitespace(inlineTextItem.style()); 249 235 } 250 if (inlineItem.isContainerStart() || inlineItem.isContainerEnd() )236 if (inlineItem.isContainerStart() || inlineItem.isContainerEnd() || inlineItem.isWordBreakOpportunity()) 251 237 return false; 252 238 ASSERT_NOT_REACHED(); … … 311 297 } 312 298 313 if (inlineItem.isLineBreak() )314 return 0;299 if (inlineItem.isLineBreak() || inlineItem.isWordBreakOpportunity()) 300 return { }; 315 301 316 302 auto& layoutBox = inlineItem.layoutBox(); … … 538 524 continue; 539 525 } 540 if (inlineItem.isText() || inlineItem.isContainerStart() || inlineItem.isContainerEnd() || inlineItem.isBox() ) {526 if (inlineItem.isText() || inlineItem.isContainerStart() || inlineItem.isContainerEnd() || inlineItem.isBox() || inlineItem.isWordBreakOpportunity()) { 541 527 auto inlineItenmWidth = inlineItemWidth(inlineItem, currentLogicalRight); 542 528 lineCandidate.inlineContent.appendInlineItem(inlineItem, inlineItenmWidth);
Note:
See TracChangeset
for help on using the changeset viewer.