Skip to content

Commit

Permalink
[Legacy line layout] Make callers of RenderStyle::whitespace use Rend…
Browse files Browse the repository at this point in the history
…erStyle::whiteSpaceCollapse/textWrap

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

Reviewed by Antti Koivisto.

In some cases we only need one of the longhand values e.g. when we care only about whitespace collapsing.

* Source/WebCore/display/css/DisplayStyle.cpp:
(WebCore::Display::Style::Style):
(WebCore::Display::Style::autoWrap const):
(WebCore::Display::Style::preserveNewline const):
(WebCore::Display::Style::collapseWhiteSpace const):
* Source/WebCore/display/css/DisplayStyle.h:
(WebCore::Display::Style::whiteSpace const): Deleted.
* Source/WebCore/rendering/RenderBlock.cpp:
(WebCore::RenderBlock::computeBlockPreferredLogicalWidths const):
* Source/WebCore/rendering/RenderText.cpp:
(WebCore::RenderText::computePreferredLogicalWidths):
* Source/WebCore/rendering/line/BreakingContext.h:
(WebCore::BreakingContext::BreakingContext):
(WebCore::BreakingContext::clearLineBreakIfFitsOnLine):
(WebCore::BreakingContext::initializeForCurrentObject):
(WebCore::BreakingContext::handleReplaced):
(WebCore::BreakingContext::handleText):
(WebCore::BreakingContext::trailingSpacesHang):
(WebCore::BreakingContext::canBreakAtThisPosition):
(WebCore::BreakingContext::handleEndOfLine):
* Source/WebCore/rendering/style/TextSizeAdjustment.cpp:
(WebCore::AutosizeStatus::computeStatus):

Canonical link: https://commits.webkit.org/267730@main
  • Loading branch information
alanbaradlay committed Sep 7, 2023
1 parent 3a527bf commit 862b74a
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 29 deletions.
10 changes: 6 additions & 4 deletions Source/WebCore/display/css/DisplayStyle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ Style::Style(const RenderStyle& style, const RenderStyle* styleForBackground)
, m_overflowX(style.overflowX())
, m_overflowY(style.overflowY())
, m_fontCascade(style.fontCascade())
, m_whiteSpace(style.whiteSpace())
, m_tabSize(style.tabSize())
, m_opacity(style.opacity())
{
Expand Down Expand Up @@ -144,17 +143,20 @@ bool Style::backgroundHasOpaqueTopLayer() const

bool Style::autoWrap() const
{
return RenderStyle::autoWrap(whiteSpace());
ASSERT_NOT_IMPLEMENTED_YET();
return true;
}

bool Style::preserveNewline() const
{
return RenderStyle::preserveNewline(whiteSpace());
ASSERT_NOT_IMPLEMENTED_YET();
return false;
}

bool Style::collapseWhiteSpace() const
{
return RenderStyle::collapseWhiteSpace(whiteSpace());
ASSERT_NOT_IMPLEMENTED_YET();
return true;
}

} // namespace Display
Expand Down
2 changes: 0 additions & 2 deletions Source/WebCore/display/css/DisplayStyle.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ class Style {
Overflow overflowY() const;
bool hasClippedOverflow() const { return m_overflowX != Overflow::Visible || m_overflowY != Overflow::Visible; }

WhiteSpace whiteSpace() const { return m_whiteSpace; }
bool autoWrap() const;
bool preserveNewline() const;
bool collapseWhiteSpace() const;
Expand All @@ -117,7 +116,6 @@ class Style {
Overflow m_overflowY;

FontCascade m_fontCascade;
WhiteSpace m_whiteSpace;
TabSize m_tabSize;

float m_opacity;
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/rendering/RenderBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2277,7 +2277,7 @@ void RenderBlock::computeBlockPreferredLogicalWidths(LayoutUnit& minLogicalWidth
ASSERT(!shouldApplyInlineSizeContainment());

const RenderStyle& styleToUse = style();
bool nowrap = styleToUse.whiteSpace() == WhiteSpace::NoWrap;
auto nowrap = styleToUse.textWrap() == TextWrap::NoWrap && styleToUse.whiteSpaceCollapse() == WhiteSpaceCollapse::Collapse;

RenderObject* child = firstChild();
RenderBlock* containingBlock = this->containingBlock();
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/rendering/RenderText.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1344,7 +1344,7 @@ void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Fo
if (!style.autoWrap())
m_minWidth = m_maxWidth;

if (style.whiteSpace() == WhiteSpace::Pre) {
if (style.whiteSpaceCollapse() == WhiteSpaceCollapse::Preserve && style.textWrap() == TextWrap::NoWrap) {
if (firstLine)
m_beginMinWidth = *m_maxWidth;
m_endMinWidth = currMaxWidth;
Expand Down
46 changes: 26 additions & 20 deletions Source/WebCore/rendering/line/BreakingContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@ class BreakingContext {
, m_renderTextInfo(inRenderTextInfo)
, m_lastFloatFromPreviousLine(inLastFloatFromPreviousLine)
, m_width(lineWidth)
, m_currWS(WhiteSpace::Normal)
, m_lastWS(WhiteSpace::Normal)
, m_preservesNewline(false)
, m_atStart(true)
, m_ignoringSpaces(false)
Expand Down Expand Up @@ -135,7 +133,7 @@ class BreakingContext {

void clearLineBreakIfFitsOnLine(bool ignoringTrailingSpace = false)
{
if (m_width.fitsOnLine(ignoringTrailingSpace) || m_lastWS == WhiteSpace::NoWrap || m_hangsAtEnd)
if (m_width.fitsOnLine(ignoringTrailingSpace) || (m_lastObjectTextWrap == TextWrap::NoWrap && m_lastObjectWhitespaceCollapse == WhiteSpaceCollapse::Collapse) || m_hangsAtEnd)
m_lineBreak.clear();
m_hangsAtEnd = false;
}
Expand Down Expand Up @@ -179,8 +177,11 @@ class BreakingContext {

LineWidth m_width;

WhiteSpace m_currWS;
WhiteSpace m_lastWS;
TextWrap m_currentTextWrap { TextWrap::Wrap };
TextWrap m_lastObjectTextWrap { TextWrap::Wrap };

WhiteSpaceCollapse m_currentWhitespaceCollapse { WhiteSpaceCollapse::Collapse };
WhiteSpaceCollapse m_lastObjectWhitespaceCollapse { WhiteSpaceCollapse::Collapse };

bool m_preservesNewline;
bool m_atStart;
Expand Down Expand Up @@ -222,16 +223,19 @@ inline void BreakingContext::initializeForCurrentObject()
if (m_nextObject && m_nextObject->parent() && !m_nextObject->parent()->isDescendantOf(renderer.parent()))
m_includeEndWidth = true;

m_currWS = renderer.isReplacedOrInlineBlock() ? renderer.parent()->style().whiteSpace() : renderer.style().whiteSpace();
m_lastWS = m_lastObject->isReplacedOrInlineBlock() ? m_lastObject->parent()->style().whiteSpace() : m_lastObject->style().whiteSpace();
m_currentTextWrap = renderer.isReplacedOrInlineBlock() ? renderer.parent()->style().textWrap() : renderer.style().textWrap();
m_currentWhitespaceCollapse = renderer.isReplacedOrInlineBlock() ? renderer.parent()->style().whiteSpaceCollapse() : renderer.style().whiteSpaceCollapse();

m_lastObjectTextWrap = m_lastObject->isReplacedOrInlineBlock() ? m_lastObject->parent()->style().textWrap() : m_lastObject->style().textWrap();
m_lastObjectWhitespaceCollapse = m_lastObject->isReplacedOrInlineBlock() ? m_lastObject->parent()->style().whiteSpaceCollapse() : m_lastObject->style().whiteSpaceCollapse();

bool isSVGText = renderer.isSVGInlineText();
m_autoWrap = !isSVGText && RenderStyle::autoWrap(m_currWS);
m_autoWrap = !isSVGText && m_currentTextWrap != TextWrap::NoWrap;
m_autoWrapWasEverTrueOnLine = m_autoWrapWasEverTrueOnLine || m_autoWrap;

m_preservesNewline = !isSVGText && RenderStyle::preserveNewline(m_currWS);
m_preservesNewline = !isSVGText && m_currentWhitespaceCollapse != WhiteSpaceCollapse::Collapse;

m_collapseWhiteSpace = RenderStyle::collapseWhiteSpace(m_currWS);
m_collapseWhiteSpace = m_currentWhitespaceCollapse == WhiteSpaceCollapse::Collapse || m_currentWhitespaceCollapse == WhiteSpaceCollapse::PreserveBreaks;
}

inline void BreakingContext::increment()
Expand Down Expand Up @@ -468,7 +472,7 @@ inline void BreakingContext::handleReplaced()
m_width.updateAvailableWidth(replacedBox.logicalHeight());

// Break on replaced elements if either has normal white-space.
if ((m_autoWrap || RenderStyle::autoWrap(m_lastWS)) && (!replacedBox.isImage() || m_allowImagesToBreak)
if ((m_autoWrap || m_lastObjectTextWrap != TextWrap::NoWrap) && (!replacedBox.isImage() || m_allowImagesToBreak)
&& (!is<RenderRubyRun>(replacedBox) || downcast<RenderRubyRun>(replacedBox).canBreakBefore(m_renderTextInfo.lineBreakIteratorFactory))) {
if (auto* renderer = m_current.renderer())
commitLineBreakAtCurrentWidth(*renderer);
Expand Down Expand Up @@ -660,7 +664,7 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool

// If we have left a no-wrap inline and entered an autowrap inline while ignoring spaces
// then we need to mark the start of the autowrap inline as a potential linebreak now.
if (m_autoWrap && !RenderStyle::autoWrap(m_lastWS) && m_ignoringSpaces)
if (m_autoWrap && m_lastObjectTextWrap == TextWrap::NoWrap && m_ignoringSpaces)
commitLineBreakAtCurrentWidth(renderer);

if (renderer.style().hasTextCombine() && is<RenderCombineText>(renderer)) {
Expand Down Expand Up @@ -693,7 +697,7 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
bool breakNBSP = m_autoWrap && style.nbspMode() == NBSPMode::Space;
// Auto-wrapping text should wrap in the middle of a word only if it could not wrap before the word,
// which is only possible if the word is the first thing on the line.
auto isWrappingAllowed = !(m_currWS == WhiteSpace::Pre || m_currWS == WhiteSpace::NoWrap);
auto isWrappingAllowed = m_currentTextWrap != TextWrap::NoWrap;
bool breakWords = isWrappingAllowed && style.breakWords() && !m_width.committedWidth() && !m_width.hasCommittedReplaced();
bool midWordBreak = false;
bool breakAnywhere = style.lineBreak() == LineBreak::Anywhere && m_autoWrap;
Expand Down Expand Up @@ -767,7 +771,7 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool

m_currentCharacterIsWS = m_currentCharacterIsSpace || (breakNBSP && c == noBreakSpace);

if (canBreakMidWord && !midWordBreak && (!m_currentCharacterIsSpace || m_atStart || style.whiteSpace() != WhiteSpace::PreWrap)) {
if (canBreakMidWord && !midWordBreak && (!m_currentCharacterIsSpace || m_atStart || !(m_currentWhitespaceCollapse == WhiteSpaceCollapse::Preserve && m_currentTextWrap == TextWrap::Wrap))) {
// FIXME: This code is ultra wrong.
// The spec says "word-break: break-all: Any typographic letter units are treated as ID(“ideographic characters”) for the purpose of line-breaking."
// The spec describes how a "typographic letter unit" is a cluster, not a code point: https://drafts.csswg.org/css-text-3/#typographic-character-unit
Expand All @@ -778,7 +782,8 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
}

std::optional<unsigned> nextBreakablePosition = m_current.nextBreakablePosition();
bool betweenWords = c == newlineCharacter || (m_currWS != WhiteSpace::Pre && !m_atStart && isBreakable(m_renderTextInfo.lineBreakIteratorFactory, m_current.offset(), nextBreakablePosition, breakNBSP, canUseLineBreakShortcut, keepAllWords, breakAnywhere)
auto mayBreakHere = !(m_currentWhitespaceCollapse == WhiteSpaceCollapse::Preserve && m_currentTextWrap == TextWrap::NoWrap);
bool betweenWords = c == newlineCharacter || (mayBreakHere && !m_atStart && isBreakable(m_renderTextInfo.lineBreakIteratorFactory, m_current.offset(), nextBreakablePosition, breakNBSP, canUseLineBreakShortcut, keepAllWords, breakAnywhere)
&& (style.hyphens() != Hyphens::None || (m_current.previousInSameNode() != softHyphen)));
m_current.setNextBreakablePosition(nextBreakablePosition);

Expand Down Expand Up @@ -842,7 +847,8 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
// If we break only after white-space, consider the current character
// as candidate width for this line.
bool lineWasTooWide = false;
if (fitsOnLineOrHangsAtEnd() && m_currentCharacterIsWS && style.breakOnlyAfterWhiteSpace() && (!midWordBreak || m_currWS == WhiteSpace::BreakSpaces)) {
auto mayBreakSpaces = m_currentWhitespaceCollapse == WhiteSpaceCollapse::BreakSpaces && m_currentTextWrap == TextWrap::Wrap;
if (fitsOnLineOrHangsAtEnd() && m_currentCharacterIsWS && style.breakOnlyAfterWhiteSpace() && (!midWordBreak || mayBreakSpaces)) {
float charWidth = textWidth(renderer, m_current.offset(), 1, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout) + (applyWordSpacing ? wordSpacing : 0);
// Check if line is too big even without the extra space
// at the end of the line. If it is not, do nothing.
Expand All @@ -851,7 +857,7 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
// additional whitespace.
if (!m_width.fitsOnLineIncludingExtraWidth(charWidth)) {
lineWasTooWide = true;
if (m_currWS == WhiteSpace::BreakSpaces)
if (mayBreakSpaces)
trailingSpacesHang(m_lineBreak, renderer, canBreakMidWord, previousCharacterIsSpace);
else {
m_lineBreak.moveTo(renderer, m_current.offset(), m_current.nextBreakablePosition());
Expand Down Expand Up @@ -1077,7 +1083,7 @@ inline bool textBeginsWithBreakablePosition(RenderText& nextText)

inline void BreakingContext::trailingSpacesHang(LegacyInlineIterator& lineBreak, RenderObject& renderObject, bool canBreakMidWord, bool previousCharacterIsSpace)
{
ASSERT(m_currWS == WhiteSpace::BreakSpaces);
ASSERT(m_currentWhitespaceCollapse == WhiteSpaceCollapse::BreakSpaces && m_currentTextWrap == TextWrap::Wrap);
// Avoid breaking before the first white-space after a word if there is a
// breaking opportunity before.
if (m_hasFormerOpportunity && !previousCharacterIsSpace)
Expand All @@ -1094,7 +1100,7 @@ inline void BreakingContext::trailingSpacesHang(LegacyInlineIterator& lineBreak,
inline bool BreakingContext::canBreakAtThisPosition()
{
// If we are no-wrap and have found a line-breaking opportunity already then we should take it.
if (m_width.committedWidth() && !m_width.fitsOnLine(m_currentCharacterIsSpace) && m_currWS == WhiteSpace::NoWrap)
if (m_width.committedWidth() && !m_width.fitsOnLine(m_currentCharacterIsSpace) && m_currentWhitespaceCollapse == WhiteSpaceCollapse::Collapse && m_currentTextWrap == TextWrap::NoWrap)
return true;

// Avoid breaking on empty inlines.
Expand Down Expand Up @@ -1204,7 +1210,7 @@ inline LegacyInlineIterator BreakingContext::handleEndOfLine()
if (m_lineBreak == m_resolver.position()) {
if (!m_lineBreak.renderer() || !m_lineBreak.renderer()->isBR()) {
// we just add as much as possible
if (m_blockStyle.whiteSpace() == WhiteSpace::Pre && !m_current.offset()) {
if (m_blockStyle.whiteSpaceCollapse() == WhiteSpaceCollapse::Preserve && m_blockStyle.textWrap() == TextWrap::NoWrap && !m_current.offset()) {
if (m_lastObject)
commitLineBreakAtCurrentWidth(*m_lastObject, m_lastObject->isText() ? m_lastObject->length() : 0);
else
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/rendering/style/TextSizeAdjustment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ auto AutosizeStatus::computeStatus(const RenderStyle& style) -> AutosizeStatus
if (lineHeight.isFixed() && lineHeight.value() - style.specifiedFontSize() > maximumDifferenceBetweenFixedLineHeightAndFontSize)
return false;

if (style.whiteSpace() == WhiteSpace::NoWrap)
if (style.whiteSpaceCollapse() == WhiteSpaceCollapse::Collapse && style.textWrap() == TextWrap::NoWrap)
return false;

return probablyContainsASmallFixedNumberOfLines(style);
Expand Down

0 comments on commit 862b74a

Please sign in to comment.