Modified: trunk/Source/WebCore/ChangeLog (267924 => 267925)
--- trunk/Source/WebCore/ChangeLog 2020-10-03 15:12:17 UTC (rev 267924)
+++ trunk/Source/WebCore/ChangeLog 2020-10-03 16:12:16 UTC (rev 267925)
@@ -1,5 +1,24 @@
2020-10-03 Zalan Bujtas <[email protected]>
+ [LFC][IFC][Soft hyphen] Rebuild the line when need to revert to a previous wrap opportunity due to soft hyphens
+ https://bugs.webkit.org/show_bug.cgi?id=217272
+
+ Reviewed by Antti Koivisto.
+
+ This patch reverts the line to a previous wrap opportunity where
+ 1. the trailing soft hyphen fits or
+ 2. no need for soft hyphen (we reverted back to a non-text inline content, where we don't need a hyphen) or
+ 3. reverted all the way back to the beginning of the line.
+ (We still don't paint hyphens at the soft hyphen locations.)
+
+ * layout/inlineformatting/InlineLineBuilder.cpp:
+ (WebCore::Layout::LineBuilder::handleFloatsAndInlineContent):
+ (WebCore::Layout::LineBuilder::rebuildLine):
+ (WebCore::Layout::LineBuilder::rebuildLineForTrailingSoftHyphen):
+ * layout/inlineformatting/InlineLineBuilder.h:
+
+2020-10-03 Zalan Bujtas <[email protected]>
+
[LFC][IFC][Soft hyphen] InlineContentBreaker should return Action::Revert when the trailing soft hyphen does not fit
https://bugs.webkit.org/show_bug.cgi?id=217269
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp (267924 => 267925)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp 2020-10-03 15:12:17 UTC (rev 267924)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp 2020-10-03 16:12:16 UTC (rev 267925)
@@ -613,12 +613,12 @@
ASSERT(result.isEndOfLine == InlineContentBreaker::IsEndOfLine::Yes);
// 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.
ASSERT(!m_wrapOpportunityList.isEmpty());
- return { InlineContentBreaker::IsEndOfLine::Yes, { rebuildLine(layoutRange), true } };
+ return { InlineContentBreaker::IsEndOfLine::Yes, { rebuildLine(layoutRange, *m_wrapOpportunityList.last()), true } };
}
if (result.action == InlineContentBreaker::Result::Action::RevertToLastNonOverflowingWrapOpportunity) {
ASSERT(result.isEndOfLine == InlineContentBreaker::IsEndOfLine::Yes);
- ASSERT_NOT_IMPLEMENTED_YET();
- return { InlineContentBreaker::IsEndOfLine::Yes, { } };
+ ASSERT(!m_wrapOpportunityList.isEmpty());
+ return { InlineContentBreaker::IsEndOfLine::Yes, { rebuildLineForTrailingSoftHyphen(layoutRange), true } };
}
if (result.action == InlineContentBreaker::Result::Action::Break) {
ASSERT(result.isEndOfLine == InlineContentBreaker::IsEndOfLine::Yes);
@@ -664,34 +664,45 @@
}
}
-size_t LineBuilder::rebuildLine(const InlineItemRange& layoutRange)
+size_t LineBuilder::rebuildLine(const InlineItemRange& layoutRange, const InlineItem& lastInlineItemToAdd)
{
ASSERT(!m_wrapOpportunityList.isEmpty());
// We might already have added intrusive floats. They shrink the avilable horizontal space for the line.
// Let's just reuse what the line has at this point.
m_line.initialize(m_line.horizontalConstraint());
- auto* lastWrapOpportunityItem = m_wrapOpportunityList.last();
auto currentItemIndex = layoutRange.start;
- auto logicalRight = InlineLayoutUnit { };
if (m_partialLeadingTextItem) {
- auto logicalWidth = inlineItemWidth(*m_partialLeadingTextItem, logicalRight);
- m_line.append(*m_partialLeadingTextItem, logicalWidth);
- logicalRight += logicalWidth;
- if (&m_partialLeadingTextItem.value() == lastWrapOpportunityItem)
+ m_line.append(*m_partialLeadingTextItem, inlineItemWidth(*m_partialLeadingTextItem, { }));
+ if (&m_partialLeadingTextItem.value() == &lastInlineItemToAdd)
return 1;
++currentItemIndex;
}
for (; currentItemIndex < layoutRange.end; ++currentItemIndex) {
auto& inlineItem = m_inlineItems[currentItemIndex];
- auto logicalWidth = inlineItemWidth(inlineItem, logicalRight);
- m_line.append(inlineItem, logicalWidth);
- logicalRight += logicalWidth;
- if (&inlineItem == lastWrapOpportunityItem)
+ m_line.append(inlineItem, inlineItemWidth(inlineItem, m_line.contentLogicalWidth()));
+ if (&inlineItem == &lastInlineItemToAdd)
return currentItemIndex - layoutRange.start + 1;
}
return layoutRange.size();
}
+size_t LineBuilder::rebuildLineForTrailingSoftHyphen(const InlineItemRange& layoutRange)
+{
+ ASSERT(!m_wrapOpportunityList.isEmpty());
+ // Revert all the way back to a wrap opportunity when either a soft hyphen fits or no hyphen is required.
+ for (auto i = m_wrapOpportunityList.size(); i-- > 1;) {
+ auto& softWrapOpportunityItem = *m_wrapOpportunityList[i];
+ // FIXME: If this turns out to be a perf issue, we could also traverse the wrap list and keep adding the items
+ // while watching the available width very closely.
+ auto index = rebuildLine(layoutRange, softWrapOpportunityItem);
+ auto trailingSoftHyphenWidth = m_line.trailingSoftHyphenWidth();
+ if (!trailingSoftHyphenWidth || trailingSoftHyphenWidth <= m_line.availableWidth())
+ return index;
+ }
+ // Have at least some content on the line.
+ return rebuildLine(layoutRange, *m_wrapOpportunityList.first());
+}
+
bool LineBuilder::isLastLineWithInlineContent(const InlineItemRange& lineRange, size_t lastInlineItemIndex, bool hasPartialTrailingContent) const
{
if (hasPartialTrailingContent)
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h (267924 => 267925)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h 2020-10-03 15:12:17 UTC (rev 267924)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h 2020-10-03 16:12:16 UTC (rev 267925)
@@ -92,7 +92,8 @@
UsedConstraints constraintsForLine(const FormattingContext::ConstraintsForInFlowContent& initialLineConstraints, bool isFirstLine);
void commitFloats(const LineCandidate&, CommitIntrusiveFloatsOnly = CommitIntrusiveFloatsOnly::No);
Result handleFloatsAndInlineContent(InlineContentBreaker&, const InlineItemRange& needsLayoutRange, const LineCandidate&);
- size_t rebuildLine(const InlineItemRange& needsLayoutRange);
+ size_t rebuildLine(const InlineItemRange& needsLayoutRange, const InlineItem& lastInlineItemToAdd);
+ size_t rebuildLineForTrailingSoftHyphen(const InlineItemRange& layoutRange);
void commitPartialContent(const InlineContentBreaker::ContinuousContent::RunList&, const InlineContentBreaker::Result::PartialTrailingContent&);
void initialize(const UsedConstraints&);
struct CommittedContent {