<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[283047] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/283047">283047</a></dd>
<dt>Author</dt> <dd>zalan@apple.com</dd>
<dt>Date</dt> <dd>2021-09-24 10:44:14 -0700 (Fri, 24 Sep 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>[LFC][IFC] Line breaking only uses a few style properties
https://bugs.webkit.org/show_bug.cgi?id=230757

Reviewed by Antti Koivisto.

The continuous runs, input to the line breaking, should only contain style properties that line breaking actually uses.
This is in preparation for supporting first-line.

* layout/formattingContexts/inline/InlineContentBreaker.cpp:
(WebCore::Layout::InlineContentBreaker::isWrappingAllowed):
(WebCore::Layout::InlineContentBreaker::shouldKeepEndOfLineWhitespace const):
(WebCore::Layout::InlineContentBreaker::processOverflowingContent const):
(WebCore::Layout::InlineContentBreaker::processOverflowingContentWithText const):
(WebCore::Layout::InlineContentBreaker::wordBreakBehavior const):
(WebCore::Layout::InlineContentBreaker::tryBreakingTextRun const):
(WebCore::Layout::InlineContentBreaker::ContinuousContent::append):
(WebCore::Layout::InlineContentBreaker::ContinuousContent::reset):
* layout/formattingContexts/inline/InlineContentBreaker.h:
(WebCore::Layout::InlineContentBreaker::ContinuousContent::Run::Run):
* layout/formattingContexts/inline/InlineLineBuilder.cpp:
(WebCore::Layout::LineCandidate::InlineContent::appendInlineItem):
(WebCore::Layout::LineBuilder::handleInlineContent):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorelayoutformattingContextsinlineInlineContentBreakercpp">trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp</a></li>
<li><a href="#trunkSourceWebCorelayoutformattingContextsinlineInlineContentBreakerh">trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.h</a></li>
<li><a href="#trunkSourceWebCorelayoutformattingContextsinlineInlineLineBuildercpp">trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (283046 => 283047)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2021-09-24 17:31:26 UTC (rev 283046)
+++ trunk/Source/WebCore/ChangeLog      2021-09-24 17:44:14 UTC (rev 283047)
</span><span class="lines">@@ -1,3 +1,28 @@
</span><ins>+2021-09-24  Alan Bujtas  <zalan@apple.com>
+
+        [LFC][IFC] Line breaking only uses a few style properties
+        https://bugs.webkit.org/show_bug.cgi?id=230757
+
+        Reviewed by Antti Koivisto.
+
+        The continuous runs, input to the line breaking, should only contain style properties that line breaking actually uses. 
+        This is in preparation for supporting first-line.
+
+        * layout/formattingContexts/inline/InlineContentBreaker.cpp:
+        (WebCore::Layout::InlineContentBreaker::isWrappingAllowed):
+        (WebCore::Layout::InlineContentBreaker::shouldKeepEndOfLineWhitespace const):
+        (WebCore::Layout::InlineContentBreaker::processOverflowingContent const):
+        (WebCore::Layout::InlineContentBreaker::processOverflowingContentWithText const):
+        (WebCore::Layout::InlineContentBreaker::wordBreakBehavior const):
+        (WebCore::Layout::InlineContentBreaker::tryBreakingTextRun const):
+        (WebCore::Layout::InlineContentBreaker::ContinuousContent::append):
+        (WebCore::Layout::InlineContentBreaker::ContinuousContent::reset):
+        * layout/formattingContexts/inline/InlineContentBreaker.h:
+        (WebCore::Layout::InlineContentBreaker::ContinuousContent::Run::Run):
+        * layout/formattingContexts/inline/InlineLineBuilder.cpp:
+        (WebCore::Layout::LineCandidate::InlineContent::appendInlineItem):
+        (WebCore::Layout::LineBuilder::handleInlineContent):
+
</ins><span class="cx"> 2021-09-24  Youenn Fablet  <youenn@apple.com>
</span><span class="cx"> 
</span><span class="cx">         RTCDataChannelHandlerClient does not need to be ref counted
</span></span></pre></div>
<a id="trunkSourceWebCorelayoutformattingContextsinlineInlineContentBreakercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp (283046 => 283047)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp   2021-09-24 17:31:26 UTC (rev 283046)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp      2021-09-24 17:44:14 UTC (rev 283047)
</span><span class="lines">@@ -112,11 +112,10 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool InlineContentBreaker::isWrappingAllowed(const InlineItem& inlineItem)
</del><ins>+bool InlineContentBreaker::isWrappingAllowed(const ContinuousContent::Run& run)
</ins><span class="cx"> {
</span><del>-    auto& styleToUse = inlineItem.isBox() ? inlineItem.layoutBox().parent().style() : inlineItem.layoutBox().style(); 
</del><span class="cx">     // Do not try to wrap overflown 'pre' and 'no-wrap' content to next line.
</span><del>-    return styleToUse.whiteSpace() != WhiteSpace::Pre && styleToUse.whiteSpace() != WhiteSpace::NoWrap;
</del><ins>+    return run.style.whiteSpace != WhiteSpace::Pre && run.style.whiteSpace != WhiteSpace::NoWrap;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool InlineContentBreaker::shouldKeepEndOfLineWhitespace(const ContinuousContent& continuousContent) const
</span><span class="lines">@@ -125,7 +124,7 @@
</span><span class="cx">     // Note that the "keep" in this context means we let the whitespace content sit on the current line.
</span><span class="cx">     // It might very well get collapsed when we close the line (normal/nowrap/pre-line).
</span><span class="cx">     // See https://www.w3.org/TR/css-text-3/#white-space-property
</span><del>-    auto whitespace = continuousContent.runs()[*firstTextRunIndex(continuousContent)].inlineItem.style().whiteSpace();
</del><ins>+    auto whitespace = continuousContent.runs()[*firstTextRunIndex(continuousContent)].style.whiteSpace;
</ins><span class="cx">     return whitespace == WhiteSpace::Normal || whitespace == WhiteSpace::NoWrap || whitespace == WhiteSpace::PreWrap || whitespace == WhiteSpace::PreLine;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -266,7 +265,7 @@
</span><span class="cx">         // Parent style drives the wrapping behavior here.
</span><span class="cx">         // e.g. <div style="white-space: nowrap">some text<div style="display: inline-block; white-space: pre-wrap"></div></div>.
</span><span class="cx">         // While the inline-block has pre-wrap which allows wrapping, the content lives in a nowrap context.
</span><del>-        return isWrappingAllowed(continuousContent.runs()[overflowingRunIndex].inlineItem);
</del><ins>+        return isWrappingAllowed(continuousContent.runs()[overflowingRunIndex]);
</ins><span class="cx">     };
</span><span class="cx">     if (shouldWrapUnbreakableContentToNextLine())
</span><span class="cx">         return { Result::Action::Wrap, IsEndOfLine::Yes };
</span><span class="lines">@@ -288,7 +287,7 @@
</span><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="cx">         // Check if this text run needs to stay on the current line.  
</span><del>-        return isWrappingAllowed(run.inlineItem);
</del><ins>+        return isWrappingAllowed(run);
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     auto findTrailingRunIndex = [&] (auto breakableRunIndex) -> std::optional<size_t> {
</span><span class="lines">@@ -371,7 +370,7 @@
</span><span class="cx">             if (isBreakableRun(run)) {
</span><span class="cx">                 ASSERT(run.inlineItem.isText());
</span><span class="cx">                 // We know that this run does not fit the available space. If we can break it at any position, let's just use the start of the run.
</span><del>-                if (wordBreakBehavior(run.inlineItem.style(), lineStatus.hasWrapOpportunityAtPreviousPosition) == WordBreakRule::AtArbitraryPosition) {
</del><ins>+                if (wordBreakBehavior(run.style, lineStatus.hasWrapOpportunityAtPreviousPosition) == WordBreakRule::AtArbitraryPosition) {
</ins><span class="cx">                     // We must be on an inline box boundary. Let's go back to the run in front of the inline box start run.
</span><span class="cx">                     // e.g. <span>unbreakable_and_overflow<span style="word-break: break-all">breakable</span>
</span><span class="cx">                     // We are at "breakable", <span> is at index - 1 and the trailing run is at index - 2.
</span><span class="lines">@@ -405,16 +404,16 @@
</span><span class="cx">     return { overflowingRunIndex };
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-OptionSet<InlineContentBreaker::WordBreakRule> InlineContentBreaker::wordBreakBehavior(const RenderStyle& style, bool hasWrapOpportunityAtPreviousPosition) const
</del><ins>+OptionSet<InlineContentBreaker::WordBreakRule> InlineContentBreaker::wordBreakBehavior(const ContinuousContent::Run::Style& style, bool hasWrapOpportunityAtPreviousPosition) const
</ins><span class="cx"> {
</span><span class="cx">     // Disregard any prohibition against line breaks mandated by the word-break property.
</span><span class="cx">     // The different wrapping opportunities must not be prioritized.
</span><span class="cx">     // Note hyphenation is not applied.
</span><del>-    if (style.lineBreak() == LineBreak::Anywhere)
</del><ins>+    if (style.lineBreak == LineBreak::Anywhere)
</ins><span class="cx">         return { WordBreakRule::AtArbitraryPosition };
</span><span class="cx"> 
</span><span class="cx">     auto includeHyphenationIfAllowed = [&](std::optional<InlineContentBreaker::WordBreakRule> wordBreakRule) -> OptionSet<InlineContentBreaker::WordBreakRule> {
</span><del>-        auto hyphenationIsAllowed = !n_hyphenationIsDisabled && style.hyphens() == Hyphens::Auto && canHyphenate(style.computedLocale());
</del><ins>+        auto hyphenationIsAllowed = !n_hyphenationIsDisabled && style.hyphens == Hyphens::Auto && canHyphenate(style.locale);
</ins><span class="cx">         if (hyphenationIsAllowed) {
</span><span class="cx">             if (wordBreakRule)
</span><span class="cx">                 return { *wordBreakRule, WordBreakRule::AtHyphenationOpportunities };
</span><span class="lines">@@ -425,18 +424,18 @@
</span><span class="cx">         return { };
</span><span class="cx">     };
</span><span class="cx">     // Breaking is allowed within “words”.
</span><del>-    if (style.wordBreak() == WordBreak::BreakAll)
</del><ins>+    if (style.wordBreak == WordBreak::BreakAll)
</ins><span class="cx">         return includeHyphenationIfAllowed(WordBreakRule::AtArbitraryPosition);
</span><span class="cx">     // For compatibility with legacy content, the word-break property also supports a deprecated break-word keyword.
</span><span class="cx">     // When specified, this has the same effect as word-break: normal and overflow-wrap: anywhere, regardless of the actual value of the overflow-wrap property.
</span><del>-    if (style.wordBreak() == WordBreak::BreakWord && !hasWrapOpportunityAtPreviousPosition)
</del><ins>+    if (style.wordBreak == WordBreak::BreakWord && !hasWrapOpportunityAtPreviousPosition)
</ins><span class="cx">         return includeHyphenationIfAllowed(WordBreakRule::AtArbitraryPosition);
</span><span class="cx">     // OverflowWrap::BreakWord/Anywhere An otherwise unbreakable sequence of characters may be broken at an arbitrary point if there are no otherwise-acceptable break points in the line.
</span><span class="cx">     // Note that this applies to content where CSS properties (e.g. WordBreak::KeepAll) make it unbreakable. 
</span><del>-    if ((style.overflowWrap() == OverflowWrap::BreakWord || style.overflowWrap() == OverflowWrap::Anywhere) && !hasWrapOpportunityAtPreviousPosition)
</del><ins>+    if ((style.overflowWrap == OverflowWrap::BreakWord || style.overflowWrap == OverflowWrap::Anywhere) && !hasWrapOpportunityAtPreviousPosition)
</ins><span class="cx">         return includeHyphenationIfAllowed(WordBreakRule::AtArbitraryPosition);
</span><span class="cx">     // Breaking is forbidden within “words”.
</span><del>-    if (style.wordBreak() == WordBreak::KeepAll)
</del><ins>+    if (style.wordBreak == WordBreak::KeepAll)
</ins><span class="cx">         return { };
</span><span class="cx">     return includeHyphenationIfAllowed({ });
</span><span class="cx"> }
</span><span class="lines">@@ -445,7 +444,7 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(overflowingRun.inlineItem.isText());
</span><span class="cx">     auto& inlineTextItem = downcast<InlineTextItem>(overflowingRun.inlineItem);
</span><del>-    auto& style = inlineTextItem.style();
</del><ins>+    auto& style = overflowingRun.style;
</ins><span class="cx">     auto availableSpaceIsInfinite = !availableWidth.has_value();
</span><span class="cx"> 
</span><span class="cx">     auto breakRules = wordBreakBehavior(style, hasWrapOpportunityAtPreviousPosition);
</span><span class="lines">@@ -462,18 +461,17 @@
</span><span class="cx">                 return { };
</span><span class="cx">             }
</span><span class="cx">             auto runLength = inlineTextItem.length();
</span><del>-            unsigned limitBefore = style.hyphenationLimitBefore() == RenderStyle::initialHyphenationLimitBefore() ? 0 : style.hyphenationLimitBefore();
-            unsigned limitAfter = style.hyphenationLimitAfter() == RenderStyle::initialHyphenationLimitAfter() ? 0 : style.hyphenationLimitAfter();
</del><ins>+            auto limitBefore = style.hyphenationLimitBefore.value_or(0);
+            auto limitAfter = style.hyphenationLimitAfter.value_or(0);
</ins><span class="cx">             // Check if this run can accommodate the before/after limits at all before start measuring text.
</span><span class="cx">             if (limitBefore >= runLength || limitAfter >= runLength || limitBefore + limitAfter > runLength)
</span><span class="cx">                 return { };
</span><span class="cx"> 
</span><span class="cx">             unsigned leftSideLength = runLength;
</span><del>-            auto& fontCascade = style.fontCascade();
-            auto hyphenWidth = InlineLayoutUnit { fontCascade.width(TextRun { StringView { style.hyphenString() } }) };
</del><ins>+            auto hyphenWidth = InlineLayoutUnit { style.fontCascade.width(TextRun { StringView { style.hyphenString } }) };
</ins><span class="cx">             if (!availableSpaceIsInfinite) {
</span><span class="cx">                 auto availableWidthExcludingHyphen = *availableWidth - hyphenWidth;
</span><del>-                if (availableWidthExcludingHyphen <= 0 || !enoughWidthForHyphenation(availableWidthExcludingHyphen, fontCascade.pixelSize()))
</del><ins>+                if (availableWidthExcludingHyphen <= 0 || !enoughWidthForHyphenation(availableWidthExcludingHyphen, style.fontCascade.pixelSize()))
</ins><span class="cx">                     return { };
</span><span class="cx">                 leftSideLength = TextUtil::midWordBreak(inlineTextItem, overflowingRun.logicalWidth, availableWidthExcludingHyphen, logicalLeft).length;
</span><span class="cx">             }
</span><span class="lines">@@ -481,7 +479,7 @@
</span><span class="cx">                 return { };
</span><span class="cx">             // Adjust before index to accommodate the limit-after value (it's the last potential hyphen location in this run).
</span><span class="cx">             auto hyphenBefore = std::min(leftSideLength, runLength - limitAfter) + 1;
</span><del>-            unsigned hyphenLocation = lastHyphenLocation(StringView(inlineTextItem.inlineTextBox().content()).substring(inlineTextItem.start(), inlineTextItem.length()), hyphenBefore, style.computedLocale());
</del><ins>+            unsigned hyphenLocation = lastHyphenLocation(StringView(inlineTextItem.inlineTextBox().content()).substring(inlineTextItem.start(), inlineTextItem.length()), hyphenBefore, style.locale);
</ins><span class="cx">             if (!hyphenLocation || hyphenLocation < limitBefore)
</span><span class="cx">                 return { };
</span><span class="cx">             // hyphenLocation is relative to the start of this InlineItemText.
</span><span class="lines">@@ -518,9 +516,9 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void InlineContentBreaker::ContinuousContent::append(const InlineItem& inlineItem, InlineLayoutUnit logicalWidth, std::optional<InlineLayoutUnit> collapsibleWidth)
</del><ins>+void InlineContentBreaker::ContinuousContent::append(const InlineItem& inlineItem, const RenderStyle& style, InlineLayoutUnit logicalWidth, std::optional<InlineLayoutUnit> collapsibleWidth)
</ins><span class="cx"> {
</span><del>-    m_runs.append({ inlineItem, logicalWidth });
</del><ins>+    m_runs.append({ inlineItem, style, logicalWidth });
</ins><span class="cx">     m_logicalWidth = clampTo<InlineLayoutUnit>(m_logicalWidth + logicalWidth);
</span><span class="cx">     if (!collapsibleWidth) {
</span><span class="cx">         m_collapsibleLogicalWidth = { };
</span><span class="lines">@@ -543,7 +541,6 @@
</span><span class="cx">     m_collapsibleLogicalWidth = { };
</span><span class="cx">     m_runs.clear();
</span><span class="cx"> }
</span><del>-
</del><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCorelayoutformattingContextsinlineInlineContentBreakerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.h (283046 => 283047)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.h     2021-09-24 17:31:26 UTC (rev 283046)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.h        2021-09-24 17:44:14 UTC (rev 283047)
</span><span class="lines">@@ -28,11 +28,9 @@
</span><span class="cx"> #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
</span><span class="cx"> 
</span><span class="cx"> #include "LayoutUnits.h"
</span><ins>+#include "RenderStyle.h"
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><del>-
-class RenderStyle;
-
</del><span class="cx"> namespace Layout {
</span><span class="cx"> 
</span><span class="cx"> class InlineItem;
</span><span class="lines">@@ -84,15 +82,28 @@
</span><span class="cx">         bool hasTrailingCollapsibleContent() const { return !!collapsibleLogicalWidth(); }
</span><span class="cx">         bool isFullyCollapsible() const { return logicalWidth() == collapsibleLogicalWidth(); }
</span><span class="cx"> 
</span><del>-        void append(const InlineItem&, InlineLayoutUnit logicalWidth, std::optional<InlineLayoutUnit> collapsibleWidth);
</del><ins>+        void append(const InlineItem&, const RenderStyle&, InlineLayoutUnit logicalWidth, std::optional<InlineLayoutUnit> collapsibleWidth);
</ins><span class="cx">         void reset();
</span><span class="cx"> 
</span><span class="cx">         struct Run {
</span><del>-            Run(const InlineItem&, InlineLayoutUnit logicalWidth);
</del><ins>+            Run(const InlineItem&, const RenderStyle&, InlineLayoutUnit logicalWidth);
</ins><span class="cx">             Run(const Run&);
</span><span class="cx">             Run& operator=(const Run&);
</span><span class="cx"> 
</span><span class="cx">             const InlineItem& inlineItem;
</span><ins>+            struct Style {
+                WhiteSpace whiteSpace { WhiteSpace::Normal };
+                LineBreak lineBreak { LineBreak::Auto };
+                WordBreak wordBreak { WordBreak::Normal };
+                OverflowWrap overflowWrap { OverflowWrap::Normal };
+                Hyphens hyphens { Hyphens::None };
+                std::optional<unsigned> hyphenationLimitBefore;
+                std::optional<unsigned> hyphenationLimitAfter;
+                const FontCascade& fontCascade;
+                const AtomString& hyphenString;
+                const AtomString& locale;
+            };
+            Style style;
</ins><span class="cx">             InlineLayoutUnit logicalWidth { 0 };
</span><span class="cx">         };
</span><span class="cx">         using RunList = Vector<Run, 3>;
</span><span class="lines">@@ -116,7 +127,7 @@
</span><span class="cx">     Result processInlineContent(const ContinuousContent&, const LineStatus&);
</span><span class="cx">     void setHyphenationDisabled() { n_hyphenationIsDisabled = true; }
</span><span class="cx"> 
</span><del>-    static bool isWrappingAllowed(const InlineItem&);
</del><ins>+    static bool isWrappingAllowed(const ContinuousContent::Run&);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     Result processOverflowingContent(const ContinuousContent&, const LineStatus&) const;
</span><span class="lines">@@ -127,14 +138,24 @@
</span><span class="cx">         AtArbitraryPosition        = 1 << 0,
</span><span class="cx">         AtHyphenationOpportunities = 1 << 1
</span><span class="cx">     };
</span><del>-    OptionSet<WordBreakRule> wordBreakBehavior(const RenderStyle&, bool hasWrapOpportunityAtPreviousPosition) const;
</del><ins>+    OptionSet<WordBreakRule> wordBreakBehavior(const ContinuousContent::Run::Style&, bool hasWrapOpportunityAtPreviousPosition) const;
</ins><span class="cx">     bool shouldKeepEndOfLineWhitespace(const ContinuousContent&) const;
</span><span class="cx"> 
</span><span class="cx">     bool n_hyphenationIsDisabled { false };
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-inline InlineContentBreaker::ContinuousContent::Run::Run(const InlineItem& inlineItem, InlineLayoutUnit logicalWidth)
</del><ins>+inline InlineContentBreaker::ContinuousContent::Run::Run(const InlineItem& inlineItem, const RenderStyle& style, InlineLayoutUnit logicalWidth)
</ins><span class="cx">     : inlineItem(inlineItem)
</span><ins>+    , style({ style.whiteSpace()
+        , style.lineBreak()
+        , style.wordBreak()
+        , style.overflowWrap()
+        , style.hyphens()
+        , style.hyphenationLimitBefore() != style.initialHyphenationLimitBefore() ? std::make_optional(style.hyphenationLimitBefore()) : std::nullopt
+        , style.hyphenationLimitAfter() != style.initialHyphenationLimitAfter() ? std::make_optional(style.hyphenationLimitAfter()) : std::nullopt
+        , style.fontCascade()
+        , style.hyphenString()
+        , style.fontDescription().computedLocale() })
</ins><span class="cx">     , logicalWidth(logicalWidth)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -141,6 +162,7 @@
</span><span class="cx"> 
</span><span class="cx"> inline InlineContentBreaker::ContinuousContent::Run::Run(const Run& other)
</span><span class="cx">     : inlineItem(other.inlineItem)
</span><ins>+    , style(other.style)
</ins><span class="cx">     , logicalWidth(other.logicalWidth)
</span><span class="cx"> {
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorelayoutformattingContextsinlineInlineLineBuildercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp (283046 => 283047)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp      2021-09-24 17:31:26 UTC (rev 283046)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp 2021-09-24 17:44:14 UTC (rev 283047)
</span><span class="lines">@@ -195,7 +195,8 @@
</span><span class="cx">         ASSERT(logicalWidth > letterSpacing);
</span><span class="cx">         return letterSpacing;
</span><span class="cx">     };
</span><del>-    m_continuousContent.append(inlineItem, logicalWidth, collapsibleWidth());
</del><ins>+    // FIXME: While the line breaking related properties for atomic level boxes do not depend on the line index (first line style) it'd be great to figure out the correct style to pass in.
+    m_continuousContent.append(inlineItem, !inlineItem.isBox() ? inlineItem.style() : inlineItem.layoutBox().parent().style(), logicalWidth, collapsibleWidth());
</ins><span class="cx">     m_hasInlineLevelBox = m_hasInlineLevelBox || inlineItem.isBox() || inlineItem.isInlineBoxStart();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -692,11 +693,11 @@
</span><span class="cx">             m_line.append(run.inlineItem, run.logicalWidth);
</span><span class="cx">         if (lineCandidate.inlineContent.hasTrailingSoftWrapOpportunity()) {
</span><span class="cx">             // Check if we are allowed to wrap at this position.
</span><del>-            auto& trailingItem = candidateRuns.last().inlineItem;
</del><ins>+            auto& trailingRun = candidateRuns.last();
</ins><span class="cx">             // FIXME: There must be a way to decide if the trailing run actually ended up on the line.
</span><span class="cx">             // Let's just deal with collapsed leading whitespace for now.
</span><del>-            if (!m_line.runs().isEmpty() && InlineContentBreaker::isWrappingAllowed(trailingItem))
-                m_wrapOpportunityList.append(&trailingItem);
</del><ins>+            if (!m_line.runs().isEmpty() && InlineContentBreaker::isWrappingAllowed(trailingRun))
+                m_wrapOpportunityList.append(&trailingRun.inlineItem);
</ins><span class="cx">         }
</span><span class="cx">         return { result.isEndOfLine, { candidateRuns.size(), false } };
</span><span class="cx">     }
</span></span></pre>
</div>
</div>

</body>
</html>