WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-284104-20241205053902.patch (text/plain), 16.04 KB, created by
alan
on 2024-12-05 05:39:03 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
alan
Created:
2024-12-05 05:39:03 PST
Size:
16.04 KB
patch
obsolete
>From 2172e3167046f65c1eec6299183192e876829581 Mon Sep 17 00:00:00 2001 >From: Alan Baradlay <zalan@apple.com> >Date: Thu, 5 Dec 2024 05:33:22 -0800 >Subject: [PATCH] [line-clamp] Number of contentful lines does not always match > the number of lines with inline content > https://bugs.webkit.org/show_bug.cgi?id=284104 > >Reviewed by NOBODY (OOPS!). > >Let's track the number of _contentful_ lines for line clamping. > >In some cases (trailing out-of-flow boxes or non-contentful inline content after the final <br>) we end up creating >a display line with no display box other than the root inline display box. Such "empty" lines should not be >taken into account when counting the lines for line-clamp. > >examples: ><div>this line is contentful<br><div style="position: absolute"></div> <- out of flow box after last contentful line ><div>this line is contenful<br><span></span></div> <- non-contentful trailing inline content > >* Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp: >(WebCore::Layout::InlineFormattingContext::lineLayout): >(WebCore::Layout::InlineFormattingContext::createDisplayContentForInlineContent): >(WebCore::Layout::InlineFormattingContext::createDisplayContentForLineFromCachedContent): >(WebCore::Layout::InlineFormattingContext::createDisplayContentForEmptyInlineContent): >* Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.h: >* Source/WebCore/layout/formattingContexts/inline/InlineFormattingUtils.cpp: >(WebCore::Layout::InlineFormattingUtils::lineEndingTruncationPolicy): >* Source/WebCore/layout/formattingContexts/inline/InlineFormattingUtils.h: >* Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayLineBuilder.cpp: >(WebCore::Layout::moveDisplayBoxToClampedLine): >* Source/WebCore/layout/integration/inline/LayoutIntegrationInlineContentBuilder.cpp: >(WebCore::LayoutIntegration::InlineContentBuilder::adjustDisplayLines const): >--- > .../inline/InlineFormattingContext.cpp | 27 +++++++++++-------- > .../inline/InlineFormattingContext.h | 2 +- > .../inline/InlineFormattingUtils.cpp | 6 ++--- > .../inline/InlineFormattingUtils.h | 2 +- > .../display/InlineDisplayLineBuilder.cpp | 4 +++ > .../LayoutIntegrationInlineContentBuilder.cpp | 2 +- > 6 files changed, 26 insertions(+), 17 deletions(-) > >diff --git a/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp b/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp >index ca4430f1396f..ae2366bd8847 100644 >--- a/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp >+++ b/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp >@@ -294,7 +294,7 @@ InlineLayoutResult InlineFormattingContext::lineLayout(AbstractLineBuilder& line > auto previousLineEnd = std::optional<InlineItemPosition> { }; > auto leadingInlineItemPosition = needsLayoutRange.start; > auto partialLayoutStartIndex = previousLine ? std::make_optional(previousLine->lineIndex) : std::nullopt; >- size_t numberOfLinesWithInlineContent = 0; >+ size_t numberOfContentfulLines = partialLayoutStartIndex.value_or(0lu); > while (true) { > > auto lineInitialRect = InlineRect { lineLogicalTop, constraints.horizontal().logicalLeft, constraints.horizontal().logicalWidth, formattingUtils().initialLineHeight(!previousLine.has_value()) }; >@@ -303,7 +303,7 @@ InlineLayoutResult InlineFormattingContext::lineLayout(AbstractLineBuilder& line > > auto lineLayoutResult = lineBuilder.layoutInlineContent(lineInput, previousLine); > auto lineBox = LineBoxBuilder { *this, lineLayoutResult }.build(lineIndex); >- auto lineLogicalRect = createDisplayContentForInlineContent(lineBox, lineLayoutResult, constraints, layoutResult.displayContent, numberOfLinesWithInlineContent); >+ auto lineLogicalRect = createDisplayContentForInlineContent(lineBox, lineLayoutResult, constraints, layoutResult.displayContent, numberOfContentfulLines); > updateBoxGeometryForPlacedFloats(lineLayoutResult.floatContent.placedFloats); > updateInlineLayoutStateWithLineLayoutResult(lineLayoutResult, lineLogicalRect, floatingContext); > >@@ -320,14 +320,13 @@ InlineLayoutResult InlineFormattingContext::lineLayout(AbstractLineBuilder& line > break; > } > >- auto lineHasInlineContent = !lineLayoutResult.inlineContent.isEmpty(); >- numberOfLinesWithInlineContent += lineHasInlineContent ? 1 : 0; >- if (formattingUtils().shouldDiscardRemainingContentInBlockDirection(partialLayoutStartIndex.value_or(0) + numberOfLinesWithInlineContent)) { >+ if (formattingUtils().shouldDiscardRemainingContentInBlockDirection(numberOfContentfulLines)) { > resetBoxGeometriesForDiscardedContent({ leadingInlineItemPosition, needsLayoutRange.end }, lineLayoutResult.floatContent.suspendedFloats); > layoutResult.range = !isPartialLayout ? InlineLayoutResult::Range::Full : InlineLayoutResult::Range::FullFromDamage; > break; > } > >+ auto lineHasInlineContent = !lineLayoutResult.inlineContent.isEmpty(); > auto hasEverSeenInlineContent = lineHasInlineContent || (previousLine && previousLine->hasInlineContent); > previousLine = PreviousLine { lineIndex, lineLayoutResult.contentGeometry.trailingOverflowingContentWidth, lineHasInlineContent && lineLayoutResult.inlineContent.last().isLineBreak(), hasEverSeenInlineContent, lineLayoutResult.directionality.inlineBaseDirection, WTFMove(lineLayoutResult.floatContent.suspendedFloats) }; > previousLineEnd = lineContentEnd; >@@ -398,18 +397,22 @@ void InlineFormattingContext::updateBoxGeometryForPlacedFloats(const LineLayoutR > } > } > >-InlineRect InlineFormattingContext::createDisplayContentForInlineContent(const LineBox& lineBox, const LineLayoutResult& lineLayoutResult, const ConstraintsForInlineContent& constraints, InlineDisplay::Content& displayContent, size_t numberOfPreviousLinesWithInlineContent) >+InlineRect InlineFormattingContext::createDisplayContentForInlineContent(const LineBox& lineBox, const LineLayoutResult& lineLayoutResult, const ConstraintsForInlineContent& constraints, InlineDisplay::Content& displayContent, size_t& numberOfPreviousLContentfulLines) > { > auto lineClamp = layoutState().parentBlockLayoutState().lineClamp(); > auto isLegacyLineClamp = lineClamp && lineClamp->isLegacy; > auto numberOfVisibleLinesAllowed = lineClamp ? std::make_optional(lineClamp->maximumLines) : std::nullopt; > >- auto numberOfLinesWithInlineContent = numberOfPreviousLinesWithInlineContent + (!lineLayoutResult.inlineContent.isEmpty() ? 1 : 0); >- auto lineIsFullyTruncatedInBlockDirection = numberOfVisibleLinesAllowed && numberOfLinesWithInlineContent > *numberOfVisibleLinesAllowed; >+ auto numberOfLinesWithInlineContent = numberOfPreviousLContentfulLines + (!lineLayoutResult.inlineContent.isEmpty() ? 1 : 0); >+ auto lineIsFullyTruncatedInBlockDirection = numberOfLinesWithInlineContent > numberOfVisibleLinesAllowed.value_or(numberOfLinesWithInlineContent); > auto displayLine = InlineDisplayLineBuilder { *this, constraints }.build(lineLayoutResult, lineBox, lineIsFullyTruncatedInBlockDirection); > auto boxes = InlineDisplayContentBuilder { *this, constraints, lineBox, displayLine }.build(lineLayoutResult); >+ displayLine.setBoxCount(boxes.size()); > >- auto truncationPolicy = InlineFormattingUtils::lineEndingTruncationPolicy(root().style(), numberOfLinesWithInlineContent, numberOfVisibleLinesAllowed, !lineLayoutResult.inlineContent.isEmpty()); >+ // Non-contentful lines are produced by certain trailing content like <div>contentful line<br><span></span></div> where <span></span> creates a display line with nothing but the root inline box. >+ auto isCurrentLineContentful = boxes.size() > 1; >+ numberOfPreviousLContentfulLines += (isCurrentLineContentful ? 1 : 0); >+ auto truncationPolicy = InlineFormattingUtils::lineEndingTruncationPolicy(root().style(), numberOfPreviousLContentfulLines, numberOfVisibleLinesAllowed, isCurrentLineContentful); > InlineDisplayLineBuilder::applyEllipsisIfNeeded(truncationPolicy, displayLine, boxes, lineLayoutResult.isFirstLast.isLastLineWithInlineContent, isLegacyLineClamp); > auto lineHasLegacyLineClamp = isLegacyLineClamp && displayLine.hasEllipsis() && truncationPolicy == LineEndingTruncationPolicy::WhenContentOverflowsInBlockDirection; > if (lineHasLegacyLineClamp) >@@ -482,7 +485,8 @@ bool InlineFormattingContext::createDisplayContentForLineFromCachedContent(const > lineContent.lineGeometry.logicalWidth = constraints.horizontal().logicalWidth; > lineContent.contentGeometry.logicalLeft = InlineFormattingUtils::horizontalAlignmentOffset(root().style(), lineContent.contentGeometry.logicalWidth, lineContent.lineGeometry.logicalWidth, lineContent.hangingContent.logicalWidth, lineContent.inlineContent, true); > auto lineBox = LineBoxBuilder { *this, lineContent }.build({ }); >- createDisplayContentForInlineContent(lineBox, lineContent, constraints, layoutResult.displayContent); >+ size_t numberOfContentfulLines = 0; >+ createDisplayContentForInlineContent(lineBox, lineContent, constraints, layoutResult.displayContent, numberOfContentfulLines); > return true; > } > >@@ -491,7 +495,8 @@ void InlineFormattingContext::createDisplayContentForEmptyInlineContent(const Co > auto emptyLineBreakingResult = LineLayoutResult { }; > emptyLineBreakingResult.lineGeometry = { { constraints.horizontal().logicalLeft, constraints.logicalTop() }, { constraints.horizontal().logicalWidth } }; > auto lineBox = LineBoxBuilder { *this, emptyLineBreakingResult }.build({ }); >- createDisplayContentForInlineContent(lineBox, emptyLineBreakingResult, constraints, layoutResult.displayContent); >+ size_t numberOfContentfulLines = 0; >+ createDisplayContentForInlineContent(lineBox, emptyLineBreakingResult, constraints, layoutResult.displayContent, numberOfContentfulLines); > } > > void InlineFormattingContext::initializeInlineLayoutState(const LayoutState& globalLayoutState) >diff --git a/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.h b/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.h >index fb9f1332b00a..e3500b499d6e 100644 >--- a/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.h >+++ b/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.h >@@ -85,7 +85,7 @@ private: > void layoutFloatContentOnly(const ConstraintsForInlineContent&); > > void collectContentIfNeeded(); >- InlineRect createDisplayContentForInlineContent(const LineBox&, const LineLayoutResult&, const ConstraintsForInlineContent&, InlineDisplay::Content&, size_t numberOfPreviousLinesWithInlineContent = 0); >+ InlineRect createDisplayContentForInlineContent(const LineBox&, const LineLayoutResult&, const ConstraintsForInlineContent&, InlineDisplay::Content&, size_t& numberOfPreviousLContentfulLines); > void updateInlineLayoutStateWithLineLayoutResult(const LineLayoutResult&, const InlineRect& lineLogicalRect, const FloatingContext&); > void updateBoxGeometryForPlacedFloats(const LineLayoutResult::PlacedFloatList&); > void resetBoxGeometriesForDiscardedContent(const InlineItemRange& discardedRange, const LineLayoutResult::SuspendedFloatList& suspendedFloats); >diff --git a/Source/WebCore/layout/formattingContexts/inline/InlineFormattingUtils.cpp b/Source/WebCore/layout/formattingContexts/inline/InlineFormattingUtils.cpp >index a2a025305fc7..20220c7de566 100644 >--- a/Source/WebCore/layout/formattingContexts/inline/InlineFormattingUtils.cpp >+++ b/Source/WebCore/layout/formattingContexts/inline/InlineFormattingUtils.cpp >@@ -591,15 +591,15 @@ std::pair<InlineLayoutUnit, InlineLayoutUnit> InlineFormattingUtils::textEmphasi > return { hasAboveTextEmphasis ? annotationSize : 0.f, hasAboveTextEmphasis ? 0.f : annotationSize }; > } > >-LineEndingTruncationPolicy InlineFormattingUtils::lineEndingTruncationPolicy(const RenderStyle& rootStyle, size_t numberOfLinesWithInlineContent, std::optional<size_t> numberOfVisibleLinesAllowed, bool currentLineHasInlineContent) >+LineEndingTruncationPolicy InlineFormattingUtils::lineEndingTruncationPolicy(const RenderStyle& rootStyle, size_t numberOfContentfulLines, std::optional<size_t> numberOfVisibleLinesAllowed, bool currentLineIsContentful) > { > if (numberOfVisibleLinesAllowed) { > // text-overflow: ellipsis should not apply inside clamping content. >- if (!currentLineHasInlineContent) { >+ if (!currentLineIsContentful) { > // Content with no inline should never ever receive ellipsis. > return LineEndingTruncationPolicy::NoTruncation; > } >- return *numberOfVisibleLinesAllowed == numberOfLinesWithInlineContent ? LineEndingTruncationPolicy::WhenContentOverflowsInBlockDirection : LineEndingTruncationPolicy::NoTruncation; >+ return *numberOfVisibleLinesAllowed == numberOfContentfulLines ? LineEndingTruncationPolicy::WhenContentOverflowsInBlockDirection : LineEndingTruncationPolicy::NoTruncation; > } > > // Truncation is in effect when the block container has overflow other than visible. >diff --git a/Source/WebCore/layout/formattingContexts/inline/InlineFormattingUtils.h b/Source/WebCore/layout/formattingContexts/inline/InlineFormattingUtils.h >index efa2edbfd4cb..c19d5f8d5577 100644 >--- a/Source/WebCore/layout/formattingContexts/inline/InlineFormattingUtils.h >+++ b/Source/WebCore/layout/formattingContexts/inline/InlineFormattingUtils.h >@@ -66,7 +66,7 @@ public: > > static std::pair<InlineLayoutUnit, InlineLayoutUnit> textEmphasisForInlineBox(const Box&, const ElementBox& rootBox); > >- static LineEndingTruncationPolicy lineEndingTruncationPolicy(const RenderStyle& rootStyle, size_t numberOfLinesWithInlineContent, std::optional<size_t> numberOfVisibleLinesAllowed, bool currentLineHasInlineContent); >+ static LineEndingTruncationPolicy lineEndingTruncationPolicy(const RenderStyle& rootStyle, size_t numberOfContentfulLines, std::optional<size_t> numberOfVisibleLinesAllowed, bool currentLineIsContentful); > > bool shouldDiscardRemainingContentInBlockDirection(size_t numberOfLinesWithInlineContent) const; > >diff --git a/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayLineBuilder.cpp b/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayLineBuilder.cpp >index 0d980fa180d6..1a09f4bb02cb 100644 >--- a/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayLineBuilder.cpp >+++ b/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayLineBuilder.cpp >@@ -385,7 +385,11 @@ static inline void moveDisplayBoxToClampedLine(auto& displayLines, auto clampedL > displayBox.setLeft(clampedLine.ellipsis()->visualRect.maxX() + horizontalOffset + legacyMatchingLinkBoxOffset); > // Assume baseline alignment here. > displayBox.moveVertically((clampedLine.top() + clampedLine.baseline()) - (displayLines.last().top() + displayLines.last().baseline())); >+ >+ auto& originalLine = displayLines[displayBox.lineIndex()]; >+ originalLine.setBoxCount(originalLine.boxCount() - 1); > displayBox.moveToLine(clampedLineIndex); >+ clampedLine.setBoxCount(clampedLine.boxCount() + 1); > } > > void InlineDisplayLineBuilder::addLegacyLineClampTrailingLinkBoxIfApplicable(const InlineFormattingContext& inlineFormattingContext, const InlineLayoutState& inlineLayoutState, InlineDisplay::Content& displayContent) >diff --git a/Source/WebCore/layout/integration/inline/LayoutIntegrationInlineContentBuilder.cpp b/Source/WebCore/layout/integration/inline/LayoutIntegrationInlineContentBuilder.cpp >index f2c35c36c1b2..1af19032b8e7 100644 >--- a/Source/WebCore/layout/integration/inline/LayoutIntegrationInlineContentBuilder.cpp >+++ b/Source/WebCore/layout/integration/inline/LayoutIntegrationInlineContentBuilder.cpp >@@ -308,7 +308,7 @@ void InlineContentBuilder::adjustDisplayLines(InlineContent& inlineContent, size > line.setScrollableOverflow(scrollableOverflowRect); > line.setInkOverflow(inkOverflowRect); > line.setFirstBoxIndex(firstBoxIndex); >- line.setBoxCount(boxIndex - firstBoxIndex); >+ ASSERT(line.boxCount() == boxIndex - firstBoxIndex); > > if (lineIndex) { > auto& lastInkOverflow = lines[lineIndex - 1].inkOverflow();
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 284104
:
473467
|
473468
|
473469
|
473470
|
473471