From ca3361fb57b33d97ce333a4662e2cdd1974837b8 Mon Sep 17 00:00:00 2001 From: Job Bautista Date: Sat, 24 Dec 2022 17:41:31 +0800 Subject: [PATCH] Issue #2068 - Only wrap the last line of inline elements when positively padding to the right. This fixes the 21 year old Mozilla bug 122795. Co-authored-by: Jonathan Kew --- layout/generic/nsInlineFrame.cpp | 5 +++-- layout/generic/nsLineLayout.cpp | 17 +++++++++++++---- layout/generic/nsLineLayout.h | 3 ++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index fb77422a34..8f24af73c1 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -580,9 +580,10 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, nscoord availableISize = aReflowInput.AvailableISize(); NS_ASSERTION(availableISize != NS_UNCONSTRAINEDSIZE, "should no longer use available widths"); - // Subtract off inline axis border+padding from availableISize + // Subtract off inline axis border+padding from availableISize; + // we don't subtract the end border+padding as we don't yet know whether + // the end of the element will occur on the same line. availableISize -= startEdge; - availableISize -= framePadding.IEnd(frameWM); lineLayout->BeginSpan(this, &aReflowInput, startEdge, startEdge + availableISize, &mBaseline); diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index 8cac02d603..579c4ae0b0 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -1101,7 +1101,8 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, "The frame ctor should've dealt with this."); if (CanPlaceFrame(pfd, notSafeToBreak, continuingTextRun, savedOptionalBreakFrame != nullptr, reflowOutput, - aReflowStatus, &optionalBreakAfterFits)) { + aReflowStatus, &optionalBreakAfterFits, + isText && availableSpaceOnLine < 0)) { if (!isEmpty) { psd->mHasNonemptyContent = true; mLineIsEmpty = false; @@ -1259,6 +1260,10 @@ nsLineLayout::SyncAnnotationBounds(PerFrameData* aRubyFrame) * ReflowFrame above would have returned false, preventing this method * from being called. The logic in this method assumes that. * + * We can always place an empty frame *unless* aAlreadyOverflowed is true, + * in which case the line has already overflowed and we'd rather back up + * to an earlier break (if available). + * * Note that there is no check against the Y coordinate because we * assume that the caller will take care of that. */ @@ -1269,7 +1274,8 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd, bool aCanRollBackBeforeFrame, ReflowOutput& aMetrics, nsReflowStatus& aStatus, - bool* aOptionalBreakAfterFits) + bool* aOptionalBreakAfterFits, + bool aAlreadyOverflowed) { NS_PRECONDITION(pfd && pfd->mFrame, "bad args, null pointers for frame data"); @@ -1340,8 +1346,11 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd, // When it doesn't fit, check for a few special conditions where we // allow it to fit anyway. - if (0 == startMargin + pfd->mBounds.ISize(lineWM) + endMargin) { - // Empty frames always fit right where they are + if (0 == startMargin + pfd->mBounds.ISize(lineWM) + endMargin && + !aAlreadyOverflowed) { + // Empty frames always fit right where they are, unless we have text that + // has already overflowed the line width, in which case we should try to + // back up to an earlier break. #ifdef NOISY_CAN_PLACE_FRAME printf(" ==> empty frame fits\n"); #endif diff --git a/layout/generic/nsLineLayout.h b/layout/generic/nsLineLayout.h index a612a96668..7f3750fd88 100644 --- a/layout/generic/nsLineLayout.h +++ b/layout/generic/nsLineLayout.h @@ -677,7 +677,8 @@ protected: bool aCanRollBackBeforeFrame, ReflowOutput& aMetrics, nsReflowStatus& aStatus, - bool* aOptionalBreakAfterFits); + bool* aOptionalBreakAfterFits, + bool aAlreadyOverflowed); void PlaceFrame(PerFrameData* pfd, ReflowOutput& aMetrics);