<!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>[283549] 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/283549">283549</a></dd>
<dt>Author</dt> <dd>zalan@apple.com</dd>
<dt>Date</dt> <dd>2021-10-05 07:49:52 -0700 (Tue, 05 Oct 2021)</dd>
</dl>
<h3>Log Message</h3>
<pre>[LFC][IFC] Move tryBreaking*Run logic to standalone functions
https://bugs.webkit.org/show_bug.cgi?id=231198
Reviewed by Antti Koivisto.
InlineContentBreaker::processOverflowingContentWithText is getting way to long and while I love keeping logic like this local, the upcoming WordBreak::BreakWord functionality
makes this function body overlap multiple pages.
* layout/formattingContexts/inline/InlineContentBreaker.cpp:
(WebCore::Layout::findTrailingRunIndex):
(WebCore::Layout::isWrappableRun):
(WebCore::Layout::InlineContentBreaker::tryBreakingOverflowingRun const):
(WebCore::Layout::InlineContentBreaker::tryBreakingPreviousNonOverflowingRuns const):
(WebCore::Layout::InlineContentBreaker::tryBreakingNextOverflowingRuns const):
(WebCore::Layout::InlineContentBreaker::processOverflowingContentWithText const):
(): Deleted.
* layout/formattingContexts/inline/InlineContentBreaker.h:</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>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (283548 => 283549)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog 2021-10-05 13:57:34 UTC (rev 283548)
+++ trunk/Source/WebCore/ChangeLog 2021-10-05 14:49:52 UTC (rev 283549)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2021-10-05 Alan Bujtas <zalan@apple.com>
+
+ [LFC][IFC] Move tryBreaking*Run logic to standalone functions
+ https://bugs.webkit.org/show_bug.cgi?id=231198
+
+ Reviewed by Antti Koivisto.
+
+ InlineContentBreaker::processOverflowingContentWithText is getting way to long and while I love keeping logic like this local, the upcoming WordBreak::BreakWord functionality
+ makes this function body overlap multiple pages.
+
+ * layout/formattingContexts/inline/InlineContentBreaker.cpp:
+ (WebCore::Layout::findTrailingRunIndex):
+ (WebCore::Layout::isWrappableRun):
+ (WebCore::Layout::InlineContentBreaker::tryBreakingOverflowingRun const):
+ (WebCore::Layout::InlineContentBreaker::tryBreakingPreviousNonOverflowingRuns const):
+ (WebCore::Layout::InlineContentBreaker::tryBreakingNextOverflowingRuns const):
+ (WebCore::Layout::InlineContentBreaker::processOverflowingContentWithText const):
+ (): Deleted.
+ * layout/formattingContexts/inline/InlineContentBreaker.h:
+
</ins><span class="cx"> 2021-10-05 Chris Lord <clord@igalia.com>
</span><span class="cx">
</span><span class="cx"> [GTK][WPE] REGRESSION: Async scrolling jumps to the top of the page until keyboard-initiated paging
</span></span></pre></div>
<a id="trunkSourceWebCorelayoutformattingContextsinlineInlineContentBreakercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp (283548 => 283549)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp 2021-10-05 13:57:34 UTC (rev 283548)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp 2021-10-05 14:49:52 UTC (rev 283549)
</span><span class="lines">@@ -155,21 +155,6 @@
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-struct OverflowingTextContent {
- size_t runIndex { 0 }; // Overflowing run index. There's always an overflowing run.
- struct BreakingPosition {
- size_t runIndex { 0 };
- struct TrailingContent {
- // Trailing content is either the run's left side (when we break the run somewhere in the middle) or the previous run.
- // Sometimes the breaking position is at the very beginning of the first run, so there's no trailing run at all.
- bool overflows { false };
- std::optional<InlineContentBreaker::PartialRun> partialRun { };
- };
- std::optional<TrailingContent> trailingContent { };
- };
- std::optional<BreakingPosition> breakingPosition { }; // Where we actually break this overflowing content.
-};
-
</del><span class="cx"> InlineContentBreaker::Result InlineContentBreaker::processOverflowingContent(const ContinuousContent& overflowContent, const LineStatus& lineStatus) const
</span><span class="cx"> {
</span><span class="cx"> auto continuousContent = ContinuousContent { overflowContent };
</span><span class="lines">@@ -275,130 +260,140 @@
</span><span class="cx"> return { Result::Action::Keep, IsEndOfLine::No };
</span><span class="cx"> }
</span><span class="cx">
</span><del>-OverflowingTextContent InlineContentBreaker::processOverflowingContentWithText(const ContinuousContent& continuousContent, const LineStatus& lineStatus) const
</del><ins>+static std::optional<size_t> findTrailingRunIndex(const InlineContentBreaker::ContinuousContent::RunList& runs, size_t breakableRunIndex)
</ins><span class="cx"> {
</span><del>- auto& runs = continuousContent.runs();
- ASSERT(!runs.isEmpty());
</del><ins>+ // When the breaking position is at the beginning of the run, the trailing run is the previous one.
+ if (!breakableRunIndex)
+ return { };
+ // Try not break content at inline box boundary
+ // e.g. <span>fits</span><span>overflows</span>
+ // when the text "overflows" completely overflows, let's break the content right before the '<span>'.
+ // FIXME: Add support for subsequent empty inline boxes e.g.
+ auto trailingCandidateIndex = breakableRunIndex - 1;
+ auto isAtInlineBox = runs[trailingCandidateIndex].inlineItem.isInlineBoxStart();
+ return !isAtInlineBox ? trailingCandidateIndex : trailingCandidateIndex ? std::make_optional(trailingCandidateIndex - 1) : std::nullopt;
+}
</ins><span class="cx">
</span><del>- auto isBreakableRun = [] (auto& run) {
- ASSERT(run.inlineItem.isText() || run.inlineItem.isInlineBoxStart() || run.inlineItem.isInlineBoxEnd() || run.inlineItem.layoutBox().isImage());
- if (!run.inlineItem.isText()) {
- // Can't break horizontal spacing -> e.g. <span style="padding-right: 100px;">textcontent</span>, if the [inline box end] is the overflown inline item
- // we need to check if there's another inline item beyond the [inline box end] to split.
- return false;
</del><ins>+static bool isWrappableRun(const InlineContentBreaker::ContinuousContent::Run& run)
+{
+ ASSERT(run.inlineItem.isText() || run.inlineItem.isInlineBoxStart() || run.inlineItem.isInlineBoxEnd() || run.inlineItem.layoutBox().isImage());
+ if (!run.inlineItem.isText()) {
+ // Can't break horizontal spacing -> e.g. <span style="padding-right: 100px;">textcontent</span>, if the [inline box end] is the overflown inline item
+ // we need to check if there's another inline item beyond the [inline box end] to split.
+ return false;
+ }
+ // Check if this text run needs to stay on the current line.
+ return InlineContentBreaker::isWrappingAllowed(run);
+}
+
+std::optional<InlineContentBreaker::OverflowingTextContent::BreakingPosition> InlineContentBreaker::tryBreakingOverflowingRun(const LineStatus& lineStatus, const ContinuousContent::RunList& runs, size_t overflowingRunIndex, InlineLayoutUnit nonOverflowingContentWidth) const
+{
+ auto overflowingRun = runs[overflowingRunIndex];
+ if (!isWrappableRun(overflowingRun))
+ return { };
+ auto partialOverflowingRun = tryBreakingTextRun(overflowingRun, lineStatus.contentLogicalRight + nonOverflowingContentWidth, std::max(0.0f, lineStatus.availableWidth - nonOverflowingContentWidth), lineStatus.hasWrapOpportunityAtPreviousPosition);
+ if (!partialOverflowingRun)
+ return { };
+ if (partialOverflowingRun->length)
+ return OverflowingTextContent::BreakingPosition { overflowingRunIndex, OverflowingTextContent::BreakingPosition::TrailingContent { false, partialOverflowingRun } };
+ // When the breaking position is at the beginning of the run, the trailing run is the previous one.
+ if (auto trailingRunIndex = findTrailingRunIndex(runs, overflowingRunIndex))
+ return OverflowingTextContent::BreakingPosition { *trailingRunIndex, OverflowingTextContent::BreakingPosition::TrailingContent { } };
+ // Sometimes we can't accommodate even the very first character.
+ // Note that this is different from when there's no breakable run in this set.
+ return OverflowingTextContent::BreakingPosition { };
+}
+
+std::optional<InlineContentBreaker::OverflowingTextContent::BreakingPosition> InlineContentBreaker::tryBreakingPreviousNonOverflowingRuns(const LineStatus& lineStatus, const ContinuousContent::RunList& runs, size_t overflowingRunIndex, InlineLayoutUnit nonOverflowingContentWidth) const
+{
+ auto previousContentWidth = nonOverflowingContentWidth;
+ for (auto index = overflowingRunIndex; index--;) {
+ auto& run = runs[index];
+ previousContentWidth -= run.logicalWidth;
+ if (!isWrappableRun(run))
+ continue;
+ ASSERT(run.inlineItem.isText());
+ if (auto partialRun = tryBreakingTextRun(run, lineStatus.contentLogicalRight + previousContentWidth, { }, lineStatus.hasWrapOpportunityAtPreviousPosition)) {
+ // We know this run fits, so if breaking is allowed on the run, it should return a non-empty left-side
+ // since it's either at hyphen position or the entire run is returned.
+ ASSERT(partialRun->length);
+ auto runIsFullyAccommodated = partialRun->length == downcast<InlineTextItem>(run.inlineItem).length();
+ return OverflowingTextContent::BreakingPosition { index, OverflowingTextContent::BreakingPosition::TrailingContent { false, runIsFullyAccommodated ? std::nullopt : partialRun } };
</ins><span class="cx"> }
</span><del>- // Check if this text run needs to stay on the current line.
- return isWrappingAllowed(run);
- };
</del><ins>+ }
+ return { };
+}
</ins><span class="cx">
</span><del>- auto findTrailingRunIndex = [&] (auto breakableRunIndex) -> std::optional<size_t> {
- // When the breaking position is at the beginning of the run, the trailing run is the previous one.
- if (!breakableRunIndex)
- return { };
- // Try not break content at inline box boundary
- // e.g. <span>fits</span><span>overflows</span>
- // when the text "overflows" completely overflows, let's break the content right before the '<span>'.
- // FIXME: Add support for subsequent empty inline boxes e.g.
- auto trailingCandidateIndex = breakableRunIndex - 1;
- auto isAtInlineBox = runs[trailingCandidateIndex].inlineItem.isInlineBoxStart();
- return !isAtInlineBox ? trailingCandidateIndex : trailingCandidateIndex ? std::make_optional(trailingCandidateIndex - 1) : std::nullopt;
- };
</del><ins>+std::optional<InlineContentBreaker::OverflowingTextContent::BreakingPosition> InlineContentBreaker::tryBreakingNextOverflowingRuns(const LineStatus& lineStatus, const ContinuousContent::RunList& runs, size_t overflowingRunIndex, InlineLayoutUnit nonOverflowingContentWidth) const
+{
+ auto nextContentWidth = nonOverflowingContentWidth + runs[overflowingRunIndex].logicalWidth;
+ for (auto index = overflowingRunIndex + 1; index < runs.size(); ++index) {
+ auto& run = runs[index];
+ if (!isWrappableRun(run)) {
+ nextContentWidth += run.logicalWidth;
+ continue;
+ }
+ ASSERT(run.inlineItem.isText());
+ // 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.
+ if (wordBreakBehavior(run.style, lineStatus.hasWrapOpportunityAtPreviousPosition) == WordBreakRule::AtArbitraryPosition) {
+ // We must be on an inline box boundary. Let's go back to the run in front of the inline box start run.
+ // e.g. <span>unbreakable_and_overflow<span style="word-break: break-all">breakable</span>
+ // We are at "breakable", <span> is at index - 1 and the trailing run is at index - 2.
+ ASSERT(runs[index - 1].inlineItem.isInlineBoxStart());
+ auto trailingRunIndex = findTrailingRunIndex(runs, index);
+ if (!trailingRunIndex) {
+ // This continuous content did not fit from the get-go. No trailing run.
+ return OverflowingTextContent::BreakingPosition { };
+ }
+ // At worst we are back to the overflowing run, like in the example above.
+ ASSERT(*trailingRunIndex >= overflowingRunIndex);
+ return OverflowingTextContent::BreakingPosition { *trailingRunIndex, OverflowingTextContent::BreakingPosition::TrailingContent { true } };
+ }
+ if (auto partialRun = tryBreakingTextRun(run, lineStatus.contentLogicalRight + nextContentWidth, { }, lineStatus.hasWrapOpportunityAtPreviousPosition)) {
+ ASSERT(partialRun->length);
+ // We managed to break this text run mid content. It has to be a hyphen break.
+ return OverflowingTextContent::BreakingPosition { index, OverflowingTextContent::BreakingPosition::TrailingContent { true, partialRun } };
+ }
+ nextContentWidth += run.logicalWidth;
+ }
+ return { };
+}
</ins><span class="cx">
</span><del>- // Check where the overflow occurs and use the corresponding style to figure out the breaking behaviour.
</del><ins>+InlineContentBreaker::OverflowingTextContent InlineContentBreaker::processOverflowingContentWithText(const ContinuousContent& continuousContent, const LineStatus& lineStatus) const
+{
+ auto& runs = continuousContent.runs();
+ ASSERT(!runs.isEmpty());
+
+ // Check where the overflow occurs and use the corresponding style to figure out the breaking behavior.
</ins><span class="cx"> // <span style="word-break: normal">first</span><span style="word-break: break-all">second</span><span style="word-break: normal">third</span>
</span><span class="cx">
</span><span class="cx"> // First find the overflowing run.
</span><del>- auto accumulatedContentWidth = InlineLayoutUnit { };
</del><ins>+ auto nonOverflowingContentWidth = InlineLayoutUnit { };
</ins><span class="cx"> auto overflowingRunIndex = runs.size();
</span><span class="cx"> for (size_t index = 0; index < runs.size(); ++index) {
</span><span class="cx"> auto runLogicalWidth = runs[index].logicalWidth;
</span><del>- if (accumulatedContentWidth + runLogicalWidth > lineStatus.availableWidth) {
</del><ins>+ if (nonOverflowingContentWidth + runLogicalWidth > lineStatus.availableWidth) {
</ins><span class="cx"> overflowingRunIndex = index;
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- accumulatedContentWidth += runLogicalWidth;
</del><ins>+ nonOverflowingContentWidth += runLogicalWidth;
</ins><span class="cx"> }
</span><span class="cx"> // We have to have an overflowing run.
</span><span class="cx"> RELEASE_ASSERT(overflowingRunIndex < runs.size());
</span><span class="cx">
</span><del>- auto tryBreakingOverflowingRun = [&]() -> std::optional<OverflowingTextContent::BreakingPosition> {
- auto overflowingRun = runs[overflowingRunIndex];
- if (!isBreakableRun(overflowingRun))
- return { };
- if (auto partialRun = tryBreakingTextRun(overflowingRun, lineStatus.contentLogicalRight + accumulatedContentWidth, std::max(0.0f, lineStatus.availableWidth - accumulatedContentWidth), lineStatus.hasWrapOpportunityAtPreviousPosition)) {
- if (partialRun->length)
- return OverflowingTextContent::BreakingPosition { overflowingRunIndex, OverflowingTextContent::BreakingPosition::TrailingContent { false, partialRun } };
- // When the breaking position is at the beginning of the run, the trailing run is the previous one.
- if (auto trailingRunIndex = findTrailingRunIndex(overflowingRunIndex))
- return OverflowingTextContent::BreakingPosition { *trailingRunIndex, OverflowingTextContent::BreakingPosition::TrailingContent { } };
- // Sometimes we can't accommodate even the very first character.
- // Note that this is different from when there's no breakable run in this set.
- return OverflowingTextContent::BreakingPosition { };
- }
- return { };
- };
</del><span class="cx"> // Check if we actually break this run.
</span><del>- if (auto breakingPosition = tryBreakingOverflowingRun())
</del><ins>+ if (auto breakingPosition = tryBreakingOverflowingRun(lineStatus, runs, overflowingRunIndex, nonOverflowingContentWidth))
</ins><span class="cx"> return { overflowingRunIndex, breakingPosition };
</span><span class="cx">
</span><del>- auto tryBreakingPreviousNonOverflowingRuns = [&]() -> std::optional<OverflowingTextContent::BreakingPosition> {
- auto previousContentWidth = accumulatedContentWidth;
- for (auto index = overflowingRunIndex; index--;) {
- auto& run = runs[index];
- previousContentWidth -= run.logicalWidth;
- if (!isBreakableRun(run))
- continue;
- ASSERT(run.inlineItem.isText());
- if (auto partialRun = tryBreakingTextRun(run, lineStatus.contentLogicalRight + previousContentWidth, { }, lineStatus.hasWrapOpportunityAtPreviousPosition)) {
- // We know this run fits, so if breaking is allowed on the run, it should return a non-empty left-side
- // since it's either at hyphen position or the entire run is returned.
- ASSERT(partialRun->length);
- auto runIsFullyAccommodated = partialRun->length == downcast<InlineTextItem>(run.inlineItem).length();
- return OverflowingTextContent::BreakingPosition { index, OverflowingTextContent::BreakingPosition::TrailingContent { false, runIsFullyAccommodated ? std::nullopt : partialRun } };
- }
- }
- return { };
- };
</del><span class="cx"> // We did not manage to break the run that actually overflows the line.
</span><span class="cx"> // Let's try to find a previous breaking position starting from the overflowing run. It surely fits.
</span><del>- if (auto breakingPosition = tryBreakingPreviousNonOverflowingRuns())
</del><ins>+ if (auto breakingPosition = tryBreakingPreviousNonOverflowingRuns(lineStatus, runs, overflowingRunIndex, nonOverflowingContentWidth))
</ins><span class="cx"> return { overflowingRunIndex, breakingPosition };
</span><span class="cx">
</span><del>- auto tryBreakingNextOverflowingRuns = [&]() -> std::optional<OverflowingTextContent::BreakingPosition> {
- auto nextContentWidth = accumulatedContentWidth + runs[overflowingRunIndex].logicalWidth;
- for (auto index = overflowingRunIndex + 1; index < runs.size(); ++index) {
- auto& run = runs[index];
- if (isBreakableRun(run)) {
- ASSERT(run.inlineItem.isText());
- // 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.
- if (wordBreakBehavior(run.style, lineStatus.hasWrapOpportunityAtPreviousPosition) == WordBreakRule::AtArbitraryPosition) {
- // We must be on an inline box boundary. Let's go back to the run in front of the inline box start run.
- // e.g. <span>unbreakable_and_overflow<span style="word-break: break-all">breakable</span>
- // We are at "breakable", <span> is at index - 1 and the trailing run is at index - 2.
- ASSERT(runs[index - 1].inlineItem.isInlineBoxStart());
- auto trailingRunIndex = findTrailingRunIndex(index);
- if (!trailingRunIndex) {
- // This continuous content did not fit from the get-go. No trailing run.
- return OverflowingTextContent::BreakingPosition { };
- }
- // At worst we are back to the overflowing run, like in the example above.
- ASSERT(*trailingRunIndex >= overflowingRunIndex);
- return OverflowingTextContent::BreakingPosition { *trailingRunIndex, OverflowingTextContent::BreakingPosition::TrailingContent { true } };
- }
- if (auto partialRun = tryBreakingTextRun(run, lineStatus.contentLogicalRight + nextContentWidth, { }, lineStatus.hasWrapOpportunityAtPreviousPosition)) {
- ASSERT(partialRun->length);
- // We managed to break this text run mid content. It has to be a hyphen break.
- return OverflowingTextContent::BreakingPosition { index, OverflowingTextContent::BreakingPosition::TrailingContent { true, partialRun } };
- }
- }
- nextContentWidth += run.logicalWidth;
- }
- return { };
- };
</del><span class="cx"> // At this point we know that there's no breakable run all the way to the overflowing run.
</span><span class="cx"> // Now we need to check if any run after the overflowing content can break.
</span><span class="cx"> // e.g. <span>this_content_overflows_but_not_breakable<span><span style="word-break: break-all">but_this_is_breakable</span>
</span><del>- if (auto breakingPosition = tryBreakingNextOverflowingRuns())
</del><ins>+ if (auto breakingPosition = tryBreakingNextOverflowingRuns(lineStatus, runs, overflowingRunIndex, nonOverflowingContentWidth))
</ins><span class="cx"> return { overflowingRunIndex, breakingPosition };
</span><span class="cx">
</span><span class="cx"> // Give up, there's no breakable run in here.
</span></span></pre></div>
<a id="trunkSourceWebCorelayoutformattingContextsinlineInlineContentBreakerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.h (283548 => 283549)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.h 2021-10-05 13:57:34 UTC (rev 283548)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.h 2021-10-05 14:49:52 UTC (rev 283549)
</span><span class="lines">@@ -34,7 +34,6 @@
</span><span class="cx"> namespace Layout {
</span><span class="cx">
</span><span class="cx"> class InlineItem;
</span><del>-struct OverflowingTextContent;
</del><span class="cx">
</span><span class="cx"> class InlineContentBreaker {
</span><span class="cx"> public:
</span><span class="lines">@@ -119,8 +118,26 @@
</span><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> Result processOverflowingContent(const ContinuousContent&, const LineStatus&) const;
</span><ins>+
+ struct OverflowingTextContent {
+ size_t runIndex { 0 }; // Overflowing run index. There's always an overflowing run.
+ struct BreakingPosition {
+ size_t runIndex { 0 };
+ struct TrailingContent {
+ // Trailing content is either the run's left side (when we break the run somewhere in the middle) or the previous run.
+ // Sometimes the breaking position is at the very beginning of the first run, so there's no trailing run at all.
+ bool overflows { false };
+ std::optional<InlineContentBreaker::PartialRun> partialRun { };
+ };
+ std::optional<TrailingContent> trailingContent { };
+ };
+ std::optional<BreakingPosition> breakingPosition { }; // Where we actually break this overflowing content.
+ };
</ins><span class="cx"> OverflowingTextContent processOverflowingContentWithText(const ContinuousContent&, const LineStatus&) const;
</span><span class="cx"> std::optional<PartialRun> tryBreakingTextRun(const ContinuousContent::Run& overflowRun, InlineLayoutUnit logicalLeft, std::optional<InlineLayoutUnit> availableWidth, bool hasWrapOpportunityAtPreviousPosition) const;
</span><ins>+ std::optional<OverflowingTextContent::BreakingPosition> tryBreakingOverflowingRun(const LineStatus&, const ContinuousContent::RunList&, size_t overflowingRunIndex, InlineLayoutUnit nonOverflowingContentWidth) const;
+ std::optional<OverflowingTextContent::BreakingPosition> tryBreakingPreviousNonOverflowingRuns(const LineStatus&, const ContinuousContent::RunList&, size_t overflowingRunIndex, InlineLayoutUnit nonOverflowingContentWidth) const;
+ std::optional<OverflowingTextContent::BreakingPosition> tryBreakingNextOverflowingRuns(const LineStatus&, const ContinuousContent::RunList&, size_t overflowingRunIndex, InlineLayoutUnit nonOverflowingContentWidth) const;
</ins><span class="cx">
</span><span class="cx"> enum class WordBreakRule {
</span><span class="cx"> AtArbitraryPosition = 1 << 0,
</span></span></pre>
</div>
</div>
</body>
</html>