Skip to content

Commit

Permalink
[IFC][hanging punctuation] Line::HangingContent should tell if the tr…
Browse files Browse the repository at this point in the history
…ailing content is conditionally hanging

https://bugs.webkit.org/show_bug.cgi?id=249713

Reviewed by Antti Koivisto.

"Stop or Comma" trailing content is conditionally hanging when hanging-punctuation is set to allow-end. However it is non-conditional when hanging-punctuation says "force-end".
In this patch, we start tracking if the trailing hanging content is conditional or not so that we can reset/trim them accordingly.

* Source/WebCore/layout/formattingContexts/inline/InlineLine.cpp:
(WebCore::Layout::Line::handleTrailingHangingContent):
(WebCore::Layout::Line::appendTextContent):
* Source/WebCore/layout/formattingContexts/inline/InlineLine.h:
(WebCore::Layout::Line::HangingContent::resetTrailingContent):
(WebCore::Layout::Line::HangingContent::isTrailingContentPunctuation const):
(WebCore::Layout::Line::HangingContent::isTrailingContentConditional const):
(WebCore::Layout::Line::HangingContent::isTrailingContentConditionalWhenFollowedByForcedLineBreak const):
(WebCore::Layout::Line::HangingContent::setTrailingPunctuation):
(WebCore::Layout::Line::HangingContent::setTrailingStopOrComma):
(WebCore::Layout::Line::HangingContent::setTrailingWhitespace):
(WebCore::Layout::Line::HangingContent::isTrailingContentWhitespace const): Deleted.
(WebCore::Layout::Line::HangingContent::isTrailingContentStopOrComma const): Deleted.
(WebCore::Layout::Line::HangingContent::trailingWhitespaceWidth const): Deleted.
(WebCore::Layout::Line::HangingContent::resetTrailingPunctuation): Deleted.
* Source/WebCore/layout/formattingContexts/inline/text/TextUtil.cpp:
(WebCore::Layout::TextUtil::hasHangableStopOrCommaEnd):

Canonical link: https://commits.webkit.org/258281@main
  • Loading branch information
alanbaradlay committed Dec 23, 2022
1 parent 3c5823b commit 6a6997c
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 30 deletions.
19 changes: 7 additions & 12 deletions Source/WebCore/layout/formattingContexts/inline/InlineLine.cpp
Expand Up @@ -255,22 +255,16 @@ void Line::handleOverflowingNonBreakingSpace(TrailingContentAction trailingConte

void Line::handleTrailingHangingContent(std::optional<IntrinsicWidthMode> intrinsicWidthMode, InlineLayoutUnit horizontalAvailableSpaceForContent, bool isLastFormattedLine)
{
// https://drafts.csswg.org/css-text/#hanging
if (!m_hangingContent.trailingWidth())
return;

if (!isLastFormattedLine)
m_hangingContent.resetTrailingPunctuation();
if (m_hangingContent.isTrailingContentPunctuation() && !isLastFormattedLine)
m_hangingContent.resetTrailingContent();

// https://drafts.csswg.org/css-text/#hanging
auto hangingTrailingContentIsConditional = [&] {
// 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 lineEndsWithLineBreak = !runs().isEmpty() && runs().last().isLineBreak();
auto hasConditionalTrailingHangingWhitespace = m_hangingContent.isTrailingContentWhitespace() && (isLastFormattedLine || lineEndsWithLineBreak);
// A stop or comma at the end of a line conditionally hangs.
auto hasConditionalTrailingStopOrComma = m_hangingContent.isTrailingContentStopOrComma();
return hasConditionalTrailingHangingWhitespace || hasConditionalTrailingStopOrComma;
auto lineEndsWithForcedLineBreak = isLastFormattedLine || (!runs().isEmpty() && runs().last().isLineBreak());
return m_hangingContent.isTrailingContentConditional() || (m_hangingContent.isTrailingContentConditionalWhenFollowedByForcedLineBreak() && lineEndsWithForcedLineBreak);
}();

if (!intrinsicWidthMode) {
Expand Down Expand Up @@ -528,7 +522,8 @@ void Line::appendTextContent(const InlineTextItem& inlineTextItem, const RenderS
return;
}
if (TextUtil::hasHangableStopOrCommaEnd(inlineTextItem, style)) {
m_hangingContent.setTrailingStopOrComma(TextUtil::hangableStopOrCommaEndWidth(inlineTextItem, style));
auto isConditionalHanging = style.hangingPunctuation().contains(HangingPunctuation::AllowEnd);
m_hangingContent.setTrailingStopOrComma(TextUtil::hangableStopOrCommaEndWidth(inlineTextItem, style), isConditionalHanging);
return;
}
m_hangingContent.resetTrailingContent();
Expand Down
32 changes: 15 additions & 17 deletions Source/WebCore/layout/formattingContexts/inline/InlineLine.h
Expand Up @@ -239,27 +239,29 @@ class Line {
struct HangingContent {
void setLeadingPunctuation(InlineLayoutUnit logicalWidth) { m_leadingPunctuationWidth = logicalWidth; }
void setTrailingPunctuation(InlineLayoutUnit logicalWidth);
void setTrailingStopOrComma(InlineLayoutUnit logicalWidth);
void setTrailingStopOrComma(InlineLayoutUnit logicalWidth, bool isConditional);
void setTrailingWhitespace(size_t length, InlineLayoutUnit logicalWidth);

bool isTrailingContentWhitespace() const { return m_trailingContent && m_trailingContent->type == TrailingContent::Type::Whitespace; }
bool isTrailingContentStopOrComma() const { return m_trailingContent && m_trailingContent->type == TrailingContent::Type::StopOrComma; }

void resetTrailingContent() { m_trailingContent = { }; }
void resetTrailingPunctuation();

InlineLayoutUnit trailingWhitespaceWidth() const { return m_trailingContent && m_trailingContent->type == TrailingContent::Type::Whitespace ? m_trailingContent->width : 0.f; }
InlineLayoutUnit trailingWidth() const { return m_trailingContent ? m_trailingContent->width : 0.f; }
InlineLayoutUnit width() const { return m_leadingPunctuationWidth + trailingWidth(); }

size_t length() const;

bool isTrailingContentPunctuation() const { return m_trailingContent && m_trailingContent->type == TrailingContent::Type::Punctuation; }
bool isTrailingContentConditional() const { return m_trailingContent && m_trailingContent->isConditional == TrailingContent::IsConditional::Yes; }
bool isTrailingContentConditionalWhenFollowedByForcedLineBreak() const { return m_trailingContent && m_trailingContent->isConditional == TrailingContent::IsConditional::WhenFollowedByForcedLineBreak; }

private:
InlineLayoutUnit m_leadingPunctuationWidth { 0.f };
// There's either a whitespace or punctuation trailing content.
struct TrailingContent {
enum class Type : uint8_t { Whitespace, StopOrComma, Punctuation };
Type type { Type::Whitespace };

enum class IsConditional : uint8_t { Yes, No, WhenFollowedByForcedLineBreak };
IsConditional isConditional { IsConditional::No };
size_t length { 0 };
InlineLayoutUnit width { 0.f };
};
Expand Down Expand Up @@ -300,17 +302,20 @@ inline void Line::TrimmableTrailingContent::reset()

inline void Line::HangingContent::setTrailingPunctuation(InlineLayoutUnit logicalWidth)
{
m_trailingContent = { TrailingContent::Type::Punctuation, 1, logicalWidth };
m_trailingContent = { TrailingContent::Type::Punctuation, TrailingContent::IsConditional::No, 1, logicalWidth };
}

inline void Line::HangingContent::setTrailingStopOrComma(InlineLayoutUnit logicalWidth)
inline void Line::HangingContent::setTrailingStopOrComma(InlineLayoutUnit logicalWidth, bool isConditional)
{
m_trailingContent = { TrailingContent::Type::StopOrComma, 1, logicalWidth };
m_trailingContent = { TrailingContent::Type::StopOrComma, isConditional ? TrailingContent::IsConditional::Yes : TrailingContent::IsConditional::No, 1, logicalWidth };
}

inline void Line::HangingContent::setTrailingWhitespace(size_t length, InlineLayoutUnit logicalWidth)
{
m_trailingContent = { TrailingContent::Type::Whitespace, length, logicalWidth };
// 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.
m_trailingContent = { TrailingContent::Type::Whitespace, TrailingContent::IsConditional::WhenFollowedByForcedLineBreak, length, logicalWidth };
}

inline size_t Line::HangingContent::length() const
Expand All @@ -323,13 +328,6 @@ inline size_t Line::HangingContent::length() const
return length;
}

inline void Line::HangingContent::resetTrailingPunctuation()
{
if (!m_trailingContent || m_trailingContent->type != TrailingContent::Type::Punctuation)
return;
m_trailingContent = { };
}

inline void Line::Run::setNeedsHyphen(InlineLayoutUnit hyphenLogicalWidth)
{
ASSERT(m_textContent);
Expand Down
Expand Up @@ -469,7 +469,7 @@ float TextUtil::hangablePunctuationEndWidth(const InlineTextItem& inlineTextItem
bool TextUtil::hasHangableStopOrCommaEnd(const InlineTextItem& inlineTextItem, const RenderStyle& style)
{
ASSERT(inlineTextItem.length());
if (!style.hangingPunctuation().contains(HangingPunctuation::AllowEnd))
if (!style.hangingPunctuation().contains(HangingPunctuation::AllowEnd) && !style.hangingPunctuation().contains(HangingPunctuation::ForceEnd))
return false;
auto trailingPosition = inlineTextItem.end() - 1;
auto trailingCharacter = inlineTextItem.inlineTextBox().content()[trailingPosition];
Expand Down

0 comments on commit 6a6997c

Please sign in to comment.