Diff
Modified: trunk/Source/WebCore/ChangeLog (253947 => 253948)
--- trunk/Source/WebCore/ChangeLog 2019-12-30 17:17:00 UTC (rev 253947)
+++ trunk/Source/WebCore/ChangeLog 2019-12-30 18:25:36 UTC (rev 253948)
@@ -1,3 +1,32 @@
+2019-12-30 Zalan Bujtas <[email protected]>
+
+ [LFC][IFC] Fix imported/w3c/web-platform-tests/css/css-text/white-space/white-space-wrap-after-nowrap-001.html
+ https://bugs.webkit.org/show_bug.cgi?id=205633
+ <rdar://problem/58234239>
+
+ Reviewed by Antti Koivisto.
+
+ When the LineBreaker comes back with Action::Revert (meaning that the line
+ needs to be reverted back to an earlier line wrap opportunity), call LineBuilder::revert and
+ close the line.
+
+ * layout/inlineformatting/InlineLineBreaker.cpp:
+ (WebCore::Layout::LineBreaker::tryWrappingInlineContent const): Return push when the current content can be wrapped.
+ (WebCore::Layout::ContinousContent::ContinousContent):
+ (WebCore::Layout::ContinousContent::lastWrapOpportunityIndex const): Fix the last position logic.
+ * layout/inlineformatting/InlineLineBuilder.cpp:
+ (WebCore::Layout::LineBuilder::revert):
+ (WebCore::Layout::LineBuilder::collectHangingContent):
+ * layout/inlineformatting/InlineLineBuilder.h:
+ * layout/inlineformatting/LineLayoutContext.cpp:
+ (WebCore::Layout::endsWithSoftWrapOpportunity):
+ (WebCore::Layout::LineLayoutContext::layoutLine):
+ (WebCore::Layout::LineLayoutContext::tryAddingFloatItems):
+ (WebCore::Layout::LineLayoutContext::tryAddingInlineItems):
+ (WebCore::Layout::LineLayoutContext::addFloatItems): Deleted.
+ (WebCore::Layout::LineLayoutContext::checkForLineWrapAndCommit): Deleted.
+ * layout/inlineformatting/LineLayoutContext.h:
+
2019-12-30 youenn fablet <[email protected]>
Ignore URL host for schemes that are not using host information
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp (253947 => 253948)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp 2019-12-30 17:17:00 UTC (rev 253947)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp 2019-12-30 18:25:36 UTC (rev 253948)
@@ -138,7 +138,7 @@
return { Result::Action::Keep, IsEndOfLine };
// Now check if we can trim the line too.
if (lineStatus.lineHasFullyCollapsibleTrailingRun && candidateContent.isTrailingContentFullyCollapsible()) {
- // If this new content is fully collapsible, it shoud surely fit.
+ // If this new content is fully collapsible, it should surely fit.
return { Result::Action::Keep, IsEndOfLine };
}
} else if (lineStatus.collapsibleWidth && candidateContent.hasNonContentRunsOnly()) {
@@ -148,7 +148,7 @@
return { Result::Action::Keep };
}
if (candidateContent.isVisuallyEmptyWhitespaceContentOnly() && shouldKeepEndOfLineWhitespace(candidateContent)) {
- // This overflowing content apparently falls into the remove/hang end-of-line-spaces catergory.
+ // This overflowing content apparently falls into the remove/hang end-of-line-spaces category.
// see https://www.w3.org/TR/css-text-3/#white-space-property matrix
return { Result::Action::Keep };
}
@@ -175,14 +175,17 @@
return { Result::Action::Split, IsEndOfLine::Yes, splitContent };
}
}
- // If we are not allowed to break this content, we still need to decide whether keep it or push it to the next line.
+ // If we are not allowed to break this overflowing content, we still need to decide whether keep it or push it to the next line.
if (lineStatus.lineIsEmpty) {
ASSERT(!m_lastWrapOpportunity);
- return { Result::Action::Keep, IsEndOfLine::Yes };
+ return { Result::Action::Keep, IsEndOfLine::No };
}
+ // Now either wrap here or at an earlier position, or not wrap at all.
+ if (isContentWrappingAllowed(candidateContent))
+ return { Result::Action::Push, IsEndOfLine::Yes };
if (m_lastWrapOpportunity)
return { Result::Action::Revert, IsEndOfLine::Yes, { }, m_lastWrapOpportunity };
- return { Result::Action::Keep, isContentWrappingAllowed(candidateContent) ? IsEndOfLine::Yes : IsEndOfLine::No };
+ return { Result::Action::Keep, IsEndOfLine::No };
}
bool LineBreaker::shouldWrapFloatBox(InlineLayoutUnit floatLogicalWidth, InlineLayoutUnit availableWidth, bool lineIsEmpty)
@@ -354,7 +357,7 @@
m_trailingCollapsibleContent.width += collapsibleWidth;
m_trailingCollapsibleContent.isFullyCollapsible = false;
}
- // End of whitspace content.
+ // End of whitespace content.
break;
}
}
@@ -427,14 +430,13 @@
Optional<size_t> ContinousContent::lastWrapOpportunityIndex() const
{
- // <span style="white-space: pre">no_wrap</span><span>yes_wrap</span><span style="white-space: pre">no_wrap</span>.
- // [container start][no_wrap][container end][container start][yes_wrap][container end][container start][no_wrap][container end]
- // Return #5 as the index where this content can wrap at last.
- for (auto index = m_runs.size(); index--;) {
- if (isWrappingAllowed(m_runs[index].inlineItem.style()))
- return index;
- }
- return { };
+ // <span style="white-space: pre">no_wrap</span><span>yes wrap</span><span style="white-space: pre">no_wrap</span>.
+ // [container start][no_wrap][container end][container start][yes] <- continuous content
+ // [ ] <- continuous content
+ // [wrap][container end][container start][no_wrap][container end] <- continuous content
+ // Return #0 as the index where the second continuous content can wrap at.
+ auto lastItemIndex = m_runs.size() - 1;
+ return isWrappingAllowed(m_runs[lastItemIndex].inlineItem.style()) ? makeOptional(lastItemIndex) : WTF::nullopt;
}
void ContinousContent::TrailingCollapsibleContent::reset()
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp (253947 => 253948)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp 2019-12-30 17:17:00 UTC (rev 253947)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp 2019-12-30 18:25:36 UTC (rev 253948)
@@ -263,14 +263,19 @@
return runList;
}
-void LineBuilder::revert(const InlineItem& revertTo)
+size_t LineBuilder::revert(const InlineItem& revertTo)
{
+ if (m_inlineItemRuns.last() == revertTo) {
+ // Since the LineBreaker does not know what has been pushed on the current line
+ // in some cases revert() is called with the last item on the line.
+ return { };
+ }
// 1. Remove and shrink the trailing content.
// 2. Rebuild collapsible trailing whitespace content.
ASSERT(!m_inlineItemRuns.isEmpty());
- ASSERT(m_inlineItemRuns.last() != revertTo);
auto revertedWidth = InlineLayoutUnit { };
- int64_t index = static_cast<int64_t>(m_inlineItemRuns.size() - 1);
+ auto originalSize = m_inlineItemRuns.size();
+ int64_t index = static_cast<int64_t>(originalSize - 1);
while (index >= 0 && m_inlineItemRuns[index] != revertTo)
revertedWidth += m_inlineItemRuns[index--].logicalWidth();
m_lineBox.shrinkHorizontally(revertedWidth);
@@ -310,7 +315,8 @@
m_collapsibleContent.append(index);
}
}
- // Consider alternative solutions if the (edge case)revert gets overly complicated.
+ // Consider alternative solutions if the (edge case)revert gets overly complicated.
+ return originalSize - m_inlineItemRuns.size();
}
void LineBuilder::alignContentVertically(RunList& runList)
@@ -482,7 +488,7 @@
HangingContent LineBuilder::collectHangingContent(IsLastLineWithInlineContent isLastLineWithInlineContent)
{
auto hangingContent = HangingContent { };
- // Can't setup hanging content with removable trailing whitspaces.
+ // Can't setup hanging content with removable trailing whitespace.
ASSERT(m_collapsibleContent.isEmpty());
if (isLastLineWithInlineContent == IsLastLineWithInlineContent::Yes)
hangingContent.setIsConditional();
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h (253947 => 253948)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h 2019-12-30 17:17:00 UTC (rev 253947)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h 2019-12-30 18:25:36 UTC (rev 253948)
@@ -115,7 +115,7 @@
using RunList = Vector<Run, 50>;
enum class IsLastLineWithInlineContent { No, Yes };
RunList close(IsLastLineWithInlineContent = IsLastLineWithInlineContent::No);
- void revert(const InlineItem& revertTo);
+ size_t revert(const InlineItem& revertTo);
static Display::LineBox::Baseline halfLeadingMetrics(const FontMetrics&, InlineLayoutUnit lineLogicalHeight);
Modified: trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp (253947 => 253948)
--- trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp 2019-12-30 17:17:00 UTC (rev 253947)
+++ trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp 2019-12-30 18:25:36 UTC (rev 253948)
@@ -44,7 +44,7 @@
// they are split at a soft breaking opportunity. See InlineTextItem::moveToNextBreakablePosition.
if (¤tTextItem.layoutBox() == &nextInlineTextItem.layoutBox())
return true;
- // Now we need to collect at least 3 adjacent characters to be able to make a descision whether the previous text item ends with breaking opportunity.
+ // Now we need to collect at least 3 adjacent characters to be able to make a decision whether the previous text item ends with breaking opportunity.
// [ex-][ample] <- second to last[x] last[-] current[a]
// We need at least 1 character in the current inline text item and 2 more from previous inline items.
auto previousContent = currentTextItem.layoutBox().textContext()->content;
@@ -269,9 +269,9 @@
}
if (candidateContent.hasIntrusiveFloats()) {
// Add floats first because they shrink the available horizontal space for the rest of the content.
- auto floatContent = addFloatItems(line, candidateContent.floats());
- committedInlineItemCount += floatContent.count;
- if (floatContent.isEndOfLine == LineBreaker::IsEndOfLine::Yes) {
+ auto result = tryAddingFloatItems(line, candidateContent.floats());
+ committedInlineItemCount += result.committedCount;
+ if (result.isEndOfLine == LineBreaker::IsEndOfLine::Yes) {
// Floats take up all the horizontal space.
return close(line, leadingInlineItemIndex, committedInlineItemCount, { });
}
@@ -278,11 +278,17 @@
}
if (!candidateContent.runs().isEmpty()) {
// Now check if we can put this content on the current line.
- auto committedContent = checkForLineWrapAndCommit(lineBreaker, line, candidateContent.runs());
- committedInlineItemCount += committedContent.count;
- if (committedContent.isEndOfLine == LineBreaker::IsEndOfLine::Yes) {
+ auto result = tryAddingInlineItems(lineBreaker, line, candidateContent.runs());
+ if (result.revertTo) {
+ ASSERT(!result.committedCount);
+ ASSERT(result.isEndOfLine == LineBreaker::IsEndOfLine::Yes);
+ // An earlier line wrapping opportunity turned out to be the final breaking position.
+ committedInlineItemCount -= line.revert(*result.revertTo);
+ }
+ committedInlineItemCount += result.committedCount;
+ if (result.isEndOfLine == LineBreaker::IsEndOfLine::Yes) {
// We can't place any more items on the current line.
- return close(line, leadingInlineItemIndex, committedInlineItemCount, committedContent.partialContent);
+ return close(line, leadingInlineItemIndex, committedInlineItemCount, result.partialContent);
}
}
currentItemIndex = leadingInlineItemIndex + committedInlineItemCount;
@@ -366,7 +372,7 @@
return candidateContent;
}
-LineLayoutContext::CommittedContent LineLayoutContext::addFloatItems(LineBuilder& line, const FloatList& floats)
+LineLayoutContext::Result LineLayoutContext::tryAddingFloatItems(LineBuilder& line, const FloatList& floats)
{
size_t committedFloatItemCount = 0;
for (auto& floatItem : floats) {
@@ -374,7 +380,7 @@
auto lineIsConsideredEmpty = line.isVisuallyEmpty() && !line.hasIntrusiveFloat();
if (LineBreaker().shouldWrapFloatBox(logicalWidth, line.availableWidth() + line.trailingCollapsibleWidth(), lineIsConsideredEmpty))
- return { LineBreaker::IsEndOfLine::Yes, committedFloatItemCount, { } };
+ return { LineBreaker::IsEndOfLine::Yes, committedFloatItemCount };
// This float can sit on the current line.
++committedFloatItemCount;
auto& floatBox = floatItem->layoutBox();
@@ -386,10 +392,10 @@
line.moveLogicalRight(logicalWidth);
m_floats.append(floatItem);
}
- return { LineBreaker::IsEndOfLine::No, committedFloatItemCount, { } };
+ return { LineBreaker::IsEndOfLine::No, committedFloatItemCount };
}
-LineLayoutContext::CommittedContent LineLayoutContext::checkForLineWrapAndCommit(LineBreaker& lineBreaker, LineBuilder& line, const LineBreaker::RunList& candidateRuns)
+LineLayoutContext::Result LineLayoutContext::tryAddingInlineItems(LineBreaker& lineBreaker, LineBuilder& line, const LineBreaker::RunList& candidateRuns)
{
auto shouldDisableHyphenation = [&] {
auto& style = root().style();
@@ -406,15 +412,15 @@
if (result.action == LineBreaker::Result::Action::Keep) {
// This continuous content can be fully placed on the current line.
commitContent(line, candidateRuns, { });
- return { result.isEndOfLine, candidateRuns.size(), { } };
+ return { result.isEndOfLine, candidateRuns.size() };
}
if (result.action == LineBreaker::Result::Action::Push) {
// This continuous content can't be placed on the current line. Nothing to commit at this time.
- return { result.isEndOfLine, 0, { } };
+ return { result.isEndOfLine };
}
if (result.action == LineBreaker::Result::Action::Revert) {
- ASSERT_NOT_IMPLEMENTED_YET();
- return { result.isEndOfLine, 0, { } };
+ // Not only this content can't be placed on the current line, but we even need to revert the line back to an earlier position.
+ return { result.isEndOfLine, 0, { }, result.revertTo };
}
if (result.action == LineBreaker::Result::Action::Split) {
// Commit the combination of full and partial content on the current line.
@@ -425,7 +431,7 @@
auto trailingRunIndex = result.partialTrailingContent->trailingRunIndex;
auto committedInlineItemCount = trailingRunIndex + 1;
if (!result.partialTrailingContent->partialRun)
- return { result.isEndOfLine, committedInlineItemCount, { } };
+ return { result.isEndOfLine, committedInlineItemCount };
auto partialRun = *result.partialTrailingContent->partialRun;
auto& trailingInlineTextItem = downcast<InlineTextItem>(candidateRuns[trailingRunIndex].inlineItem);
@@ -433,7 +439,7 @@
return { result.isEndOfLine, committedInlineItemCount, LineContent::PartialContent { partialRun.needsHyphen, overflowLength } };
}
ASSERT_NOT_REACHED();
- return { LineBreaker::IsEndOfLine::No, 0, { } };
+ return { LineBreaker::IsEndOfLine::No };
}
void LineLayoutContext::commitContent(LineBuilder& line, const LineBreaker::RunList& runs, Optional<LineBreaker::Result::PartialTrailingContent> partialTrailingContent)
Modified: trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h (253947 => 253948)
--- trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h 2019-12-30 17:17:00 UTC (rev 253947)
+++ trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h 2019-12-30 18:25:36 UTC (rev 253948)
@@ -54,14 +54,15 @@
using FloatList = Vector<WeakPtr<InlineItem>>;
private:
- struct CommittedContent {
+ LineCandidateContent nextContentForLine(unsigned inlineItemIndex, Optional<unsigned> overflowLength, InlineLayoutUnit currentLogicalRight);
+ struct Result {
LineBreaker::IsEndOfLine isEndOfLine { LineBreaker::IsEndOfLine::No };
- size_t count { 0 };
- Optional <LineContent::PartialContent> partialContent;
+ size_t committedCount { 0 };
+ Optional <LineContent::PartialContent> partialContent { };
+ const InlineItem* revertTo { nullptr };
};
- LineCandidateContent nextContentForLine(unsigned inlineItemIndex, Optional<unsigned> overflowLength, InlineLayoutUnit currentLogicalRight);
- CommittedContent addFloatItems(LineBuilder&, const FloatList&);
- CommittedContent checkForLineWrapAndCommit(LineBreaker&, LineBuilder&, const LineBreaker::RunList&);
+ Result tryAddingFloatItems(LineBuilder&, const FloatList&);
+ Result tryAddingInlineItems(LineBreaker&, LineBuilder&, const LineBreaker::RunList&);
void commitContent(LineBuilder&, const LineBreaker::RunList&, Optional<LineBreaker::Result::PartialTrailingContent>);
LineContent close(LineBuilder&, unsigned leadingInlineItemIndex, unsigned committedInlineItemCount, Optional<LineContent::PartialContent>);