Changeset 283474 in webkit
- Timestamp:
- Oct 3, 2021, 11:46:15 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 6 edited
-
ChangeLog (modified) (1 diff)
-
layout/formattingContexts/inline/InlineLine.cpp (modified) (3 diffs)
-
layout/formattingContexts/inline/InlineLine.h (modified) (5 diffs)
-
layout/formattingContexts/inline/InlineLineBoxBuilder.cpp (modified) (3 diffs)
-
layout/formattingContexts/inline/InlineLineBuilder.cpp (modified) (1 diff)
-
layout/formattingContexts/inline/InlineLineBuilder.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r283470 r283474 1 2021-10-03 Alan Bujtas <zalan@apple.com> 2 3 [LFC][IFC] Moving hanging whitespace sequence handling to Line 4 https://bugs.webkit.org/show_bug.cgi?id=231126 5 6 Reviewed by Antti Koivisto. 7 8 Let the Line handle the whitespace hanging. Line::HangingTrailingContent will eventually gain more functionality. 9 This is also in preparation for fixing imported/w3c/web-platform-tests/css/css-text/white-space/textarea-pre-wrap-014.html 10 11 * layout/formattingContexts/inline/InlineLine.cpp: 12 (WebCore::Layout::Line::Line): 13 (WebCore::Layout::Line::visuallyCollapseHangingOverflow): 14 (WebCore::Layout::Line::HangingTrailingContent::HangingTrailingContent): 15 (WebCore::Layout::Line::HangingTrailingContent::width const): 16 * layout/formattingContexts/inline/InlineLine.h: 17 (WebCore::Layout::Line::hangingWhitespaceWidth const): 18 (WebCore::Layout::Line::Run::shouldTrailingWhitespaceHang const): 19 (WebCore::Layout::Line::Run::isOverflowWhitespaceHanging const): Deleted. shouldTrailingWhitespaceHang is a more descriptive name. 20 * layout/formattingContexts/inline/InlineLineBoxBuilder.cpp: 21 (WebCore::Layout::horizontalAlignmentOffset): 22 (WebCore::Layout::LineBoxBuilder::build): 23 (WebCore::Layout::hangingGlyphWidth): Deleted. 24 * layout/formattingContexts/inline/InlineLineBuilder.cpp: 25 (WebCore::Layout::LineBuilder::layoutInlineContent): 26 * layout/formattingContexts/inline/InlineLineBuilder.h: 27 1 28 2021-10-03 Simon Fraser <simon.fraser@apple.com> 2 29 -
trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.cpp
r283059 r283474 44 44 : m_inlineFormattingContext(inlineFormattingContext) 45 45 , m_trimmableTrailingContent(m_runs) 46 , m_hangingTrailingContent(m_runs) 46 47 { 47 48 } … … 176 177 auto trimmedContentWidth = InlineLayoutUnit { }; 177 178 for (auto& run : WTF::makeReversedRange(m_runs)) { 178 if (!run. isOverflowWhitespaceHanging())179 if (!run.shouldTrailingWhitespaceHang()) 179 180 break; 180 181 auto visuallyCollapsibleInlineItem = run.isInlineBoxStart() || run.isInlineBoxEnd() || run.hasTrailingWhitespace(); … … 442 443 } 443 444 445 Line::HangingTrailingContent::HangingTrailingContent(const RunList& runs) 446 : m_runs(runs) 447 { 448 } 449 450 InlineLayoutUnit Line::HangingTrailingContent::width() const 451 { 452 // When a glyph at the start or end edge of a line hangs, it is not considered when measuring the line’s contents for fit, alignment, or justification. 453 // Depending on the line’s alignment/justification, this can result in the mark being placed outside the line box. 454 // https://drafts.csswg.org/css-text-3/#hanging 455 auto hangingWidth = InlineLayoutUnit { }; 456 for (auto& run : WTF::makeReversedRange(m_runs)) { 457 if (run.isBox() || run.isLineBreak()) 458 break; 459 if (run.isInlineBoxStart() || run.isInlineBoxEnd()) 460 continue; 461 if (!run.hasTrailingWhitespace() || !run.shouldTrailingWhitespaceHang()) 462 break; 463 hangingWidth += run.trailingWhitespaceWidth(); 464 } 465 return hangingWidth; 466 } 467 444 468 Line::Run::Run(const InlineItem& inlineItem, const RenderStyle& style, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth) 445 469 : m_type(inlineItem.type()) -
trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.h
r283059 r283474 54 54 bool isTrailingRunFullyTrimmable() const { return m_trimmableTrailingContent.isTrailingRunFullyTrimmable(); } 55 55 56 InlineLayoutUnit hangingWhitespaceWidth() const { return m_hangingTrailingContent.width(); } 57 56 58 std::optional<InlineLayoutUnit> trailingSoftHyphenWidth() const { return m_trailingSoftHyphenWidth; } 57 59 void addTrailingHyphen(InlineLayoutUnit hyphenLogicalWidth); … … 88 90 InlineLayoutUnit trailingWhitespaceWidth() const { return m_trailingWhitespaceWidth; } 89 91 90 bool isOverflowWhitespaceHanging() const;92 bool shouldTrailingWhitespaceHang() const; 91 93 TextDirection inlineDirection() const; 92 94 InlineLayoutUnit letterSpacing() const; … … 132 134 InlineDisplay::Box::Expansion m_expansion; 133 135 struct Style { 134 bool isOverflowWhitespaceHanging { false };136 bool shouldTrailingWhitespaceHang { false }; 135 137 TextDirection inlineDirection { TextDirection::RTL }; 136 138 InlineLayoutUnit letterSpacing { 0 }; … … 180 182 }; 181 183 184 struct HangingTrailingContent { 185 HangingTrailingContent(const RunList&); 186 187 InlineLayoutUnit width() const; 188 189 private: 190 const RunList& m_runs; 191 }; 192 182 193 const InlineFormattingContext& m_inlineFormattingContext; 183 194 RunList m_runs; 184 195 TrimmableTrailingContent m_trimmableTrailingContent; 196 HangingTrailingContent m_hangingTrailingContent; 185 197 InlineLayoutUnit m_contentLogicalWidth { 0 }; 186 198 size_t m_nonSpanningInlineLevelBoxCount { 0 }; … … 214 226 } 215 227 216 inline bool Line::Run:: isOverflowWhitespaceHanging() const217 { 218 return m_style. isOverflowWhitespaceHanging;228 inline bool Line::Run::shouldTrailingWhitespaceHang() const 229 { 230 return m_style.shouldTrailingWhitespaceHang; 219 231 } 220 232 -
trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.cpp
r283390 r283474 37 37 namespace Layout { 38 38 39 static InlineLayoutUnit hangingGlyphWidth(InlineLayoutUnit extraHorizontalSpace, const Line::RunList& runs, bool isLastLineWithInlineContent) 40 { 41 // When a glyph at the start or end edge of a line hangs, it is not considered when measuring the line’s contents for fit, alignment, or justification. 42 // Depending on the line’s alignment/justification, this can result in the mark being placed outside the line box. 43 // https://drafts.csswg.org/css-text-3/#hanging 44 auto isConditional = isLastLineWithInlineContent; 45 auto hangingWidth = InlineLayoutUnit { }; 46 for (auto& run : WTF::makeReversedRange(runs)) { 47 if (run.isInlineBoxStart() || run.isInlineBoxEnd()) 48 continue; 49 if (run.isLineBreak()) { 50 isConditional = true; 51 continue; 52 } 53 if (!run.hasTrailingWhitespace()) 54 break; 55 // Check if we have a preserved or hung whitespace. 56 if (!run.isOverflowWhitespaceHanging()) 57 break; 58 // This is either a normal or conditionally hanging trailing whitespace. 59 hangingWidth += run.trailingWhitespaceWidth(); 39 static std::optional<InlineLayoutUnit> horizontalAlignmentOffset(TextAlignMode textAlign, const LineBuilder::LineContent& lineContent) 40 { 41 // Depending on the line’s alignment/justification, the hanging glyph can be placed outside the line box. 42 auto& runs = lineContent.runs; 43 auto contentLogicalWidth = lineContent.contentLogicalWidth; 44 if (lineContent.hangingWhitespaceWidth) { 45 ASSERT(!runs.isEmpty()); 46 // If white-space is set to pre-wrap, the UA must (unconditionally) hang this sequence, unless the sequence is followed 47 // by a forced line break, in which case it must conditionally hang the sequence is instead. 48 // Note that end of last line in a paragraph is considered a forced break. 49 auto isConditionalHanging = runs.last().isLineBreak() || lineContent.isLastLineWithInlineContent; 50 // In some cases, a glyph at the end of a line can conditionally hang: it hangs only if it does not otherwise fit in the line prior to justification. 51 // FIXME: Only the overflowing glyphs should be considered for hanging. 52 if (isConditionalHanging) 53 contentLogicalWidth = std::min(contentLogicalWidth, lineContent.lineLogicalWidth); 54 else 55 contentLogicalWidth -= lineContent.hangingWhitespaceWidth; 60 56 } 61 // In some cases, a glyph at the end of a line can conditionally hang: it hangs only if it does not otherwise fit in the line prior to justification. 62 return !isConditional || extraHorizontalSpace < 0 ? hangingWidth : InlineLayoutUnit { }; 63 } 64 65 static std::optional<InlineLayoutUnit> horizontalAlignmentOffset(const Line::RunList& runs, TextAlignMode textAlign, InlineLayoutUnit lineLogicalWidth, InlineLayoutUnit contentLogicalWidth, bool isLastLine) 66 { 67 auto extraHorizontalSpace = lineLogicalWidth - contentLogicalWidth; 68 // Depending on the line’s alignment/justification, the hanging glyph can be placed outside the line box. 69 extraHorizontalSpace += hangingGlyphWidth(extraHorizontalSpace, runs, isLastLine); 57 auto extraHorizontalSpace = lineContent.lineLogicalWidth - contentLogicalWidth; 70 58 if (extraHorizontalSpace <= 0) 71 59 return { }; … … 77 65 // in order to exactly fill the line box. Unless otherwise specified by text-align-last, 78 66 // the last line before a forced break or the end of the block is start-aligned. 79 if ( isLastLine|| (!runs.isEmpty() && runs.last().isLineBreak()))67 if (lineContent.isLastLineWithInlineContent || (!runs.isEmpty() && runs.last().isLineBreak())) 80 68 return TextAlignMode::Start; 81 69 return TextAlignMode::Justify; … … 112 100 LineBoxBuilder::LineAndLineBox LineBoxBuilder::build(const LineBuilder::LineContent& lineContent, size_t lineIndex) 113 101 { 114 auto& runs = lineContent.runs;115 auto contentLogicalWidth = lineContent.contentLogicalWidth;116 102 auto textAlign = !lineIndex ? rootBox().firstLineStyle().textAlign() : rootBox().style().textAlign(); 117 auto contentLogicalLeft = Layout::horizontalAlignmentOffset( runs, textAlign, lineContent.lineLogicalWidth, contentLogicalWidth, lineContent.isLastLineWithInlineContent).value_or(InlineLayoutUnit { });118 auto lineBox = LineBox { rootBox(), contentLogicalLeft, contentLogicalWidth, lineIndex, lineContent.nonSpanningInlineLevelBoxCount };119 120 auto lineBoxLogicalHeight = constructAndAlignInlineLevelBoxes(lineBox, runs, lineIndex);103 auto contentLogicalLeft = Layout::horizontalAlignmentOffset(textAlign, lineContent).value_or(InlineLayoutUnit { }); 104 auto lineBox = LineBox { rootBox(), contentLogicalLeft, lineContent.contentLogicalWidth, lineIndex, lineContent.nonSpanningInlineLevelBoxCount }; 105 106 auto lineBoxLogicalHeight = constructAndAlignInlineLevelBoxes(lineBox, lineContent.runs, lineIndex); 121 107 122 108 auto line = [&] { -
trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp
r283442 r283474 279 279 , m_lineLogicalRect.width() 280 280 , m_line.contentLogicalWidth() 281 , m_line.hangingWhitespaceWidth() 281 282 , isLastLine 282 283 , m_line.nonSpanningInlineLevelBoxCount() -
trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.h
r283255 r283474 57 57 bool hasIntrusiveFloat { false }; 58 58 InlineLayoutPoint logicalTopLeft; 59 InlineLayoutUnit lineLogicalWidth; 60 InlineLayoutUnit contentLogicalWidth; 59 InlineLayoutUnit lineLogicalWidth { 0 }; 60 InlineLayoutUnit contentLogicalWidth { 0 }; 61 InlineLayoutUnit hangingWhitespaceWidth { 0 }; 61 62 bool isLastLineWithInlineContent { true }; 62 63 size_t nonSpanningInlineLevelBoxCount { 0 };
Note:
See TracChangeset
for help on using the changeset viewer.