Diff
Modified: trunk/Source/WebCore/ChangeLog (283473 => 283474)
--- trunk/Source/WebCore/ChangeLog 2021-10-03 18:41:35 UTC (rev 283473)
+++ trunk/Source/WebCore/ChangeLog 2021-10-03 18:46:15 UTC (rev 283474)
@@ -1,3 +1,30 @@
+2021-10-03 Alan Bujtas <[email protected]>
+
+ [LFC][IFC] Moving hanging whitespace sequence handling to Line
+ https://bugs.webkit.org/show_bug.cgi?id=231126
+
+ Reviewed by Antti Koivisto.
+
+ Let the Line handle the whitespace hanging. Line::HangingTrailingContent will eventually gain more functionality.
+ This is also in preparation for fixing imported/w3c/web-platform-tests/css/css-text/white-space/textarea-pre-wrap-014.html
+
+ * layout/formattingContexts/inline/InlineLine.cpp:
+ (WebCore::Layout::Line::Line):
+ (WebCore::Layout::Line::visuallyCollapseHangingOverflow):
+ (WebCore::Layout::Line::HangingTrailingContent::HangingTrailingContent):
+ (WebCore::Layout::Line::HangingTrailingContent::width const):
+ * layout/formattingContexts/inline/InlineLine.h:
+ (WebCore::Layout::Line::hangingWhitespaceWidth const):
+ (WebCore::Layout::Line::Run::shouldTrailingWhitespaceHang const):
+ (WebCore::Layout::Line::Run::isOverflowWhitespaceHanging const): Deleted. shouldTrailingWhitespaceHang is a more descriptive name.
+ * layout/formattingContexts/inline/InlineLineBoxBuilder.cpp:
+ (WebCore::Layout::horizontalAlignmentOffset):
+ (WebCore::Layout::LineBoxBuilder::build):
+ (WebCore::Layout::hangingGlyphWidth): Deleted.
+ * layout/formattingContexts/inline/InlineLineBuilder.cpp:
+ (WebCore::Layout::LineBuilder::layoutInlineContent):
+ * layout/formattingContexts/inline/InlineLineBuilder.h:
+
2021-10-03 Simon Fraser <[email protected]>
WebCore::Length incorrectly uses memcpy() for copy constructors/operator and IPC encoding/decoding
Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.cpp (283473 => 283474)
--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.cpp 2021-10-03 18:41:35 UTC (rev 283473)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.cpp 2021-10-03 18:46:15 UTC (rev 283474)
@@ -43,6 +43,7 @@
Line::Line(const InlineFormattingContext& inlineFormattingContext)
: m_inlineFormattingContext(inlineFormattingContext)
, m_trimmableTrailingContent(m_runs)
+ , m_hangingTrailingContent(m_runs)
{
}
@@ -175,7 +176,7 @@
// different set of white-space values and decide if the in-between pre-wrap content should be collapsed as well.)
auto trimmedContentWidth = InlineLayoutUnit { };
for (auto& run : WTF::makeReversedRange(m_runs)) {
- if (!run.isOverflowWhitespaceHanging())
+ if (!run.shouldTrailingWhitespaceHang())
break;
auto visuallyCollapsibleInlineItem = run.isInlineBoxStart() || run.isInlineBoxEnd() || run.hasTrailingWhitespace();
if (!visuallyCollapsibleInlineItem)
@@ -441,6 +442,29 @@
return remove();
}
+Line::HangingTrailingContent::HangingTrailingContent(const RunList& runs)
+ : m_runs(runs)
+{
+}
+
+InlineLayoutUnit Line::HangingTrailingContent::width() const
+{
+ // 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.
+ // Depending on the line’s alignment/justification, this can result in the mark being placed outside the line box.
+ // https://drafts.csswg.org/css-text-3/#hanging
+ auto hangingWidth = InlineLayoutUnit { };
+ for (auto& run : WTF::makeReversedRange(m_runs)) {
+ if (run.isBox() || run.isLineBreak())
+ break;
+ if (run.isInlineBoxStart() || run.isInlineBoxEnd())
+ continue;
+ if (!run.hasTrailingWhitespace() || !run.shouldTrailingWhitespaceHang())
+ break;
+ hangingWidth += run.trailingWhitespaceWidth();
+ }
+ return hangingWidth;
+}
+
Line::Run::Run(const InlineItem& inlineItem, const RenderStyle& style, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth)
: m_type(inlineItem.type())
, m_layoutBox(&inlineItem.layoutBox())
Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.h (283473 => 283474)
--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.h 2021-10-03 18:41:35 UTC (rev 283473)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.h 2021-10-03 18:46:15 UTC (rev 283474)
@@ -53,6 +53,8 @@
InlineLayoutUnit trimmableTrailingWidth() const { return m_trimmableTrailingContent.width(); }
bool isTrailingRunFullyTrimmable() const { return m_trimmableTrailingContent.isTrailingRunFullyTrimmable(); }
+ InlineLayoutUnit hangingWhitespaceWidth() const { return m_hangingTrailingContent.width(); }
+
std::optional<InlineLayoutUnit> trailingSoftHyphenWidth() const { return m_trailingSoftHyphenWidth; }
void addTrailingHyphen(InlineLayoutUnit hyphenLogicalWidth);
@@ -87,7 +89,7 @@
bool hasTrailingWhitespace() const { return m_trailingWhitespaceType != TrailingWhitespace::None; }
InlineLayoutUnit trailingWhitespaceWidth() const { return m_trailingWhitespaceWidth; }
- bool isOverflowWhitespaceHanging() const;
+ bool shouldTrailingWhitespaceHang() const;
TextDirection inlineDirection() const;
InlineLayoutUnit letterSpacing() const;
bool hasTextCombine() const;
@@ -131,7 +133,7 @@
std::optional<Text> m_textContent;
InlineDisplay::Box::Expansion m_expansion;
struct Style {
- bool isOverflowWhitespaceHanging { false };
+ bool shouldTrailingWhitespaceHang { false };
TextDirection inlineDirection { TextDirection::RTL };
InlineLayoutUnit letterSpacing { 0 };
bool hasTextCombine { false };
@@ -179,9 +181,19 @@
InlineLayoutUnit m_partiallyTrimmableWidth { 0 };
};
+ struct HangingTrailingContent {
+ HangingTrailingContent(const RunList&);
+
+ InlineLayoutUnit width() const;
+
+ private:
+ const RunList& m_runs;
+ };
+
const InlineFormattingContext& m_inlineFormattingContext;
RunList m_runs;
TrimmableTrailingContent m_trimmableTrailingContent;
+ HangingTrailingContent m_hangingTrailingContent;
InlineLayoutUnit m_contentLogicalWidth { 0 };
size_t m_nonSpanningInlineLevelBoxCount { 0 };
std::optional<InlineLayoutUnit> m_trailingSoftHyphenWidth { 0 };
@@ -213,9 +225,9 @@
m_logicalWidth += hyphenLogicalWidth;
}
-inline bool Line::Run::isOverflowWhitespaceHanging() const
+inline bool Line::Run::shouldTrailingWhitespaceHang() const
{
- return m_style.isOverflowWhitespaceHanging;
+ return m_style.shouldTrailingWhitespaceHang;
}
inline TextDirection Line::Run::inlineDirection() const
Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.cpp (283473 => 283474)
--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.cpp 2021-10-03 18:41:35 UTC (rev 283473)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.cpp 2021-10-03 18:46:15 UTC (rev 283474)
@@ -36,37 +36,25 @@
namespace WebCore {
namespace Layout {
-static InlineLayoutUnit hangingGlyphWidth(InlineLayoutUnit extraHorizontalSpace, const Line::RunList& runs, bool isLastLineWithInlineContent)
+static std::optional<InlineLayoutUnit> horizontalAlignmentOffset(TextAlignMode textAlign, const LineBuilder::LineContent& lineContent)
{
- // 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.
- // Depending on the line’s alignment/justification, this can result in the mark being placed outside the line box.
- // https://drafts.csswg.org/css-text-3/#hanging
- auto isConditional = isLastLineWithInlineContent;
- auto hangingWidth = InlineLayoutUnit { };
- for (auto& run : WTF::makeReversedRange(runs)) {
- if (run.isInlineBoxStart() || run.isInlineBoxEnd())
- continue;
- if (run.isLineBreak()) {
- isConditional = true;
- continue;
- }
- if (!run.hasTrailingWhitespace())
- break;
- // Check if we have a preserved or hung whitespace.
- if (!run.isOverflowWhitespaceHanging())
- break;
- // This is either a normal or conditionally hanging trailing whitespace.
- hangingWidth += run.trailingWhitespaceWidth();
+ // Depending on the line’s alignment/justification, the hanging glyph can be placed outside the line box.
+ auto& runs = lineContent.runs;
+ auto contentLogicalWidth = lineContent.contentLogicalWidth;
+ if (lineContent.hangingWhitespaceWidth) {
+ ASSERT(!runs.isEmpty());
+ // If white-space is set to pre-wrap, the UA must (unconditionally) hang this sequence, unless the sequence is followed
+ // by a forced line break, in which case it must conditionally hang the sequence is instead.
+ // Note that end of last line in a paragraph is considered a forced break.
+ auto isConditionalHanging = runs.last().isLineBreak() || lineContent.isLastLineWithInlineContent;
+ // 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.
+ // FIXME: Only the overflowing glyphs should be considered for hanging.
+ if (isConditionalHanging)
+ contentLogicalWidth = std::min(contentLogicalWidth, lineContent.lineLogicalWidth);
+ else
+ contentLogicalWidth -= lineContent.hangingWhitespaceWidth;
}
- // 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.
- return !isConditional || extraHorizontalSpace < 0 ? hangingWidth : InlineLayoutUnit { };
-}
-
-static std::optional<InlineLayoutUnit> horizontalAlignmentOffset(const Line::RunList& runs, TextAlignMode textAlign, InlineLayoutUnit lineLogicalWidth, InlineLayoutUnit contentLogicalWidth, bool isLastLine)
-{
- auto extraHorizontalSpace = lineLogicalWidth - contentLogicalWidth;
- // Depending on the line’s alignment/justification, the hanging glyph can be placed outside the line box.
- extraHorizontalSpace += hangingGlyphWidth(extraHorizontalSpace, runs, isLastLine);
+ auto extraHorizontalSpace = lineContent.lineLogicalWidth - contentLogicalWidth;
if (extraHorizontalSpace <= 0)
return { };
@@ -76,7 +64,7 @@
// Text is justified according to the method specified by the text-justify property,
// in order to exactly fill the line box. Unless otherwise specified by text-align-last,
// the last line before a forced break or the end of the block is start-aligned.
- if (isLastLine || (!runs.isEmpty() && runs.last().isLineBreak()))
+ if (lineContent.isLastLineWithInlineContent || (!runs.isEmpty() && runs.last().isLineBreak()))
return TextAlignMode::Start;
return TextAlignMode::Justify;
};
@@ -111,13 +99,11 @@
LineBoxBuilder::LineAndLineBox LineBoxBuilder::build(const LineBuilder::LineContent& lineContent, size_t lineIndex)
{
- auto& runs = lineContent.runs;
- auto contentLogicalWidth = lineContent.contentLogicalWidth;
auto textAlign = !lineIndex ? rootBox().firstLineStyle().textAlign() : rootBox().style().textAlign();
- auto contentLogicalLeft = Layout::horizontalAlignmentOffset(runs, textAlign, lineContent.lineLogicalWidth, contentLogicalWidth, lineContent.isLastLineWithInlineContent).value_or(InlineLayoutUnit { });
- auto lineBox = LineBox { rootBox(), contentLogicalLeft, contentLogicalWidth, lineIndex, lineContent.nonSpanningInlineLevelBoxCount };
+ auto contentLogicalLeft = Layout::horizontalAlignmentOffset(textAlign, lineContent).value_or(InlineLayoutUnit { });
+ auto lineBox = LineBox { rootBox(), contentLogicalLeft, lineContent.contentLogicalWidth, lineIndex, lineContent.nonSpanningInlineLevelBoxCount };
- auto lineBoxLogicalHeight = constructAndAlignInlineLevelBoxes(lineBox, runs, lineIndex);
+ auto lineBoxLogicalHeight = constructAndAlignInlineLevelBoxes(lineBox, lineContent.runs, lineIndex);
auto line = [&] {
auto lineBoxLogicalRect = InlineRect { lineContent.logicalTopLeft, lineContent.lineLogicalWidth, lineBoxLogicalHeight };
Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp (283473 => 283474)
--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp 2021-10-03 18:41:35 UTC (rev 283473)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp 2021-10-03 18:46:15 UTC (rev 283474)
@@ -278,6 +278,7 @@
, m_lineLogicalRect.topLeft()
, m_lineLogicalRect.width()
, m_line.contentLogicalWidth()
+ , m_line.hangingWhitespaceWidth()
, isLastLine
, m_line.nonSpanningInlineLevelBoxCount()
, m_line.runs()};
Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.h (283473 => 283474)
--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.h 2021-10-03 18:41:35 UTC (rev 283473)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.h 2021-10-03 18:46:15 UTC (rev 283474)
@@ -56,8 +56,9 @@
const FloatList& floats;
bool hasIntrusiveFloat { false };
InlineLayoutPoint logicalTopLeft;
- InlineLayoutUnit lineLogicalWidth;
- InlineLayoutUnit contentLogicalWidth;
+ InlineLayoutUnit lineLogicalWidth { 0 };
+ InlineLayoutUnit contentLogicalWidth { 0 };
+ InlineLayoutUnit hangingWhitespaceWidth { 0 };
bool isLastLineWithInlineContent { true };
size_t nonSpanningInlineLevelBoxCount { 0 };
const Line::RunList& runs;