COMMIT_MESSAGE

 1[block-in-inline] Trailing whitespace is not collapsed before a block nested in an inline box
 2https://bugs.webkit.org/show_bug.cgi?id=321088
 3
 4Reviewed by NOBODY (OOPS!).
 5
 6isLastLineWithInlineContent() looks past the line's own content for more inline items to decide whether
 7this is the last line with inline content. A block level box is not "contentful" per
 8isContentfulOrHasDecoration(), which only accepts atomic inline level boxes and line breaks, so the scan
 9stepped straight over it, found the content after the block and concluded the line was not last.
 10
 11* Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp:
 12(WebCore::Layout::LineBuilder::isLastLineWithInlineContent):
 13(WebCore::Layout::LineBuilder::isLastLineWithInlineContent const):
 14* LayoutTests/imported/w3c/web-platform-tests/css/css-text/white-space/trailing-space-before-block-in-inline-001-expected.txt: Added.
 15* LayoutTests/imported/w3c/web-platform-tests/css/css-text/white-space/trailing-space-before-block-in-inline-001.html: Added.

Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp

@@bool LineBuilder::isLastLineWithInlineContent(const LineContent& lineContent, si
19321932 }
19331933 // Look ahead to see if there's more inline type of inline items.
19341934 for (auto i = lineContent.range.endIndex(); i < needsLayoutEnd && i < m_inlineItemList.size(); ++i) {
 1935 // A block level box (block-in-inline) closes the inline content: whatever follows it starts after the block and can't extend this line, so this is the line's last inline content.
 1936 if (m_inlineItemList[i].isBlock())
 1937 return true;
19351938 if (isContentfulOrHasDecoration(m_inlineItemList[i], formattingContext))
19361939 return false;
19371940 }

LayoutTests/imported/w3c/web-platform-tests/css/css-text/white-space/trailing-space-before-block-in-inline-001-expected.txt

 11
 22
 32
 41
 52
 62
 71 2
 8
 9PASS Trailing white space before a block level box collapses (nested)
 10PASS Trailing white space before a block level box collapses (sibling)
 11PASS White space between two characters on the same line is preserved
 12PASS The trailing white space collapses the same whether the block level box is nested in an inline box or a sibling of inline content
 13

LayoutTests/imported/w3c/web-platform-tests/css/css-text/white-space/trailing-space-before-block-in-inline-001.html

 1<!DOCTYPE html>
 2<meta charset="utf-8">
 3<title>CSS Test: trailing white space collapses at the end of a line that is followed by a block level box</title>
 4<link rel="help" href="https://www.w3.org/TR/css-text-3/#white-space-phase-2">
 5<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#anonymous-block-level">
 6<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#inline-formatting">
 7<meta name="assert" content="A block level box in inline content ends the line before it, so white space at the end of that line is at a line edge and collapses away. Content following the block level box cannot extend that line and so cannot keep the white space alive.">
 8<script src="/resources/testharness.js"></script>
 9<script src="/resources/testharnessreport.js"></script>
 10<link rel="stylesheet" href="/fonts/ahem.css">
 11<style>
 12body { margin: 0; }
 13.container { font: 20px/20px Ahem; }
 14</style>
 15
 16<div class="container" contenteditable id="nested">1 <span><div class="block">2</div></span>2</div>
 17<div class="container" contenteditable id="sibling">1 <div class="block">2</div>2</div>
 18<div class="container" contenteditable id="midline">1 2</div>
 19
 20<script>
 21// The width of the leading text node, in characters. "1 " is one character plus a trailing space: the space
 22// is at the end of the line the block level box closes, so it collapses and the run is 1 character wide.
 23// In the control the space sits between two characters on the same line, so the run is 3 characters wide.
 24const expected = { nested: 1, sibling: 1, midline: 3 };
 25
 26const range = document.createRange();
 27const widthOf = node => {
 28 range.selectNodeContents(node);
 29 return range.getBoundingClientRect().width;
 30};
 31
 32const characterWidth = widthOf(document.getElementById("midline").firstChild) / expected.midline;
 33
 34for (const id of ["nested", "sibling", "midline"]) {
 35 test(() => {
 36 assert_greater_than(characterWidth, 0, "the character width could be measured");
 37 const characters = widthOf(document.getElementById(id).firstChild) / characterWidth;
 38 assert_equals(characters, expected[id], "width of the leading text run, in characters");
 39 }, id === "midline"
 40 ? "White space between two characters on the same line is preserved"
 41 : `Trailing white space before a block level box collapses (${id})`);
 42}
 43
 44test(() => {
 45 assert_equals(widthOf(document.getElementById("nested").firstChild),
 46 widthOf(document.getElementById("sibling").firstChild));
 47}, "The trailing white space collapses the same whether the block level box is nested in an inline box or a "
 48 + "sibling of inline content");
 49</script>