From 48a466967c1dcdb75e2dd503050ffcb0380ba3da Mon Sep 17 00:00:00 2001 From: Ting-Yu Lin Date: Thu, 7 Jul 2022 19:01:56 +0000 Subject: [PATCH] Bug 1323517 Part 5 - Improve the available size computation for reflowing a float. r=jfkthame First of all, `nsBlockFrame::AdjustFloatAvailableSpace()` is misleading. It doesn't adjust the argument `aFloatAvailableSpace` at all, nor does it use any fields in nsBlockFrame. It simply returns the available space in the parent block's content area. Thus, I move it into BlockReflowState, and have it return the available size rather than a rect because a size is sufficient for reflowing a float. Also, nsBlockFrame::ReflowFloat() only cares about the available size, but not the position of the available space, so it is sufficient to pass a LogicalSize computed by the new method ComputeAvailableSizeForFloat(). In FlowAndPlaceFloat(), there is a loop searching for a wide enough band to place the float. We don't need to adjust availSize every time mBCoord is changed in the loop. We can just call ComputeAvailableSizeForFloat() to get a new available size before reflowing the float in the `!earlyFloatReflow` branch. This patch shouldn't change the behavior. Differential Revision: https://phabricator.services.mozilla.com/D151207 --- layout/generic/BlockReflowState.cpp | 34 ++++++++++++++++------------- layout/generic/BlockReflowState.h | 2 ++ layout/generic/nsBlockFrame.cpp | 34 ++++++----------------------- layout/generic/nsBlockFrame.h | 27 ++++++++++------------- 4 files changed, 40 insertions(+), 57 deletions(-) diff --git a/layout/generic/BlockReflowState.cpp b/layout/generic/BlockReflowState.cpp index 7407e59c44fa..6b1f8668bf49 100644 --- a/layout/generic/BlockReflowState.cpp +++ b/layout/generic/BlockReflowState.cpp @@ -265,6 +265,14 @@ LogicalRect BlockReflowState::ComputeBlockAvailSpace( return result; } +LogicalSize BlockReflowState::ComputeAvailableSizeForFloat() const { + const auto wm = mReflowInput.GetWritingMode(); + const nscoord availBSize = ContentBSize() == NS_UNCONSTRAINEDSIZE + ? NS_UNCONSTRAINEDSIZE + : std::max(0, ContentBEnd() - mBCoord); + return LogicalSize(wm, ContentISize(), availBSize); +} + bool BlockReflowState::FloatAvoidingBlockFitsInAvailSpace( nsIFrame* aFloatAvoidingBlock, const nsFlowAreaRect& aFloatAvailableSpace) const { @@ -735,17 +743,12 @@ bool BlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat) { mBCoord = bCoord; } - // Get the band of available space with respect to margin box. - nsFlowAreaRect floatAvailableSpace = - GetFloatAvailableSpaceForPlacingFloat(mBCoord); - LogicalRect adjustedAvailableSpace = - mBlock->AdjustFloatAvailableSpace(*this, floatAvailableSpace.mRect); - + LogicalSize availSize = ComputeAvailableSizeForFloat(); SizeComputationInput sizingInput(aFloat, mReflowInput.mRenderingContext, wm, mReflowInput.ComputedISize()); - nscoord floatMarginISize = FloatMarginISize( - mReflowInput, adjustedAvailableSpace.ISize(wm), aFloat, sizingInput); + nscoord floatMarginISize = + FloatMarginISize(mReflowInput, availSize.ISize(wm), aFloat, sizingInput); LogicalMargin floatMargin(wm); // computed margin LogicalMargin floatOffsets(wm); @@ -760,8 +763,8 @@ bool BlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat) { bool earlyFloatReflow = aFloat->IsLetterFrame() || floatMarginISize == NS_UNCONSTRAINEDSIZE; if (earlyFloatReflow) { - mBlock->ReflowFloat(*this, adjustedAvailableSpace, aFloat, floatMargin, - floatOffsets, false, reflowStatus); + mBlock->ReflowFloat(*this, availSize, aFloat, floatMargin, floatOffsets, + false, reflowStatus); floatMarginISize = aFloat->ISize(wm) + floatMargin.IStartEnd(wm); NS_ASSERTION(reflowStatus.IsComplete(), "letter frames and orthogonal floats with auto block-size " @@ -782,6 +785,10 @@ bool BlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat) { bool mustPlaceFloat = mReflowInput.mFlags.mIsTopOfPage && IsAdjacentWithBStart(); + // Get the band of available space with respect to margin box. + nsFlowAreaRect floatAvailableSpace = + GetFloatAvailableSpaceForPlacingFloat(mBCoord); + for (;;) { if (mReflowInput.AvailableHeight() != NS_UNCONSTRAINEDSIZE && floatAvailableSpace.mRect.BSize(wm) <= 0 && !mustPlaceFloat) { @@ -797,9 +804,6 @@ bool BlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat) { // Nope. try to advance to the next band. mBCoord += floatAvailableSpace.mRect.BSize(wm); - if (adjustedAvailableSpace.BSize(wm) != NS_UNCONSTRAINEDSIZE) { - adjustedAvailableSpace.BSize(wm) -= floatAvailableSpace.mRect.BSize(wm); - } floatAvailableSpace = GetFloatAvailableSpaceForPlacingFloat(mBCoord); mustPlaceFloat = false; } @@ -832,8 +836,8 @@ bool BlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat) { // where to break. if (!earlyFloatReflow) { bool pushedDown = mBCoord != restoreBCoord.SavedValue(); - mBlock->ReflowFloat(*this, adjustedAvailableSpace, aFloat, floatMargin, - floatOffsets, pushedDown, reflowStatus); + mBlock->ReflowFloat(*this, ComputeAvailableSizeForFloat(), aFloat, + floatMargin, floatOffsets, pushedDown, reflowStatus); } if (aFloat->GetPrevInFlow()) { floatMargin.BStart(wm) = 0; diff --git a/layout/generic/BlockReflowState.h b/layout/generic/BlockReflowState.h index 1499807db79b..bc14b9751436 100644 --- a/layout/generic/BlockReflowState.h +++ b/layout/generic/BlockReflowState.h @@ -219,6 +219,8 @@ class BlockReflowState { const nsFlowAreaRect& aFloatAvailableSpace, bool aBlockAvoidsFloats); + LogicalSize ComputeAvailableSizeForFloat() const; + void RecoverStateFrom(nsLineList::iterator aLine, nscoord aDeltaBCoord); void AdvanceToNextLine() { diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index ac2170954d21..1026fcc4f969 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -6613,41 +6613,23 @@ const nsStyleText* nsBlockFrame::StyleTextForLineLayout() { return StyleText(); } -//////////////////////////////////////////////////////////////////////// -// Float support - -LogicalRect nsBlockFrame::AdjustFloatAvailableSpace( - BlockReflowState& aState, const LogicalRect& aFloatAvailableSpace) { - WritingMode wm = aState.mReflowInput.GetWritingMode(); - - nscoord availBSize = NS_UNCONSTRAINEDSIZE == aState.ContentBSize() - ? NS_UNCONSTRAINEDSIZE - : std::max(0, aState.ContentBEnd() - aState.mBCoord); - - return LogicalRect(wm, aState.ContentIStart(), aState.ContentBStart(), - aState.ContentISize(), availBSize); -} - nscoord nsBlockFrame::ComputeFloatISize(BlockReflowState& aState, const LogicalRect& aFloatAvailableSpace, nsIFrame* aFloat) { MOZ_ASSERT(aFloat->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW), "aFloat must be an out-of-flow frame"); - // Reflow the float. - LogicalRect availSpace = - AdjustFloatAvailableSpace(aState, aFloatAvailableSpace); - + LogicalSize availSize = aState.ComputeAvailableSizeForFloat(); WritingMode blockWM = aState.mReflowInput.GetWritingMode(); WritingMode floatWM = aFloat->GetWritingMode(); ReflowInput floatRS(aState.mPresContext, aState.mReflowInput, aFloat, - availSpace.Size(blockWM).ConvertTo(floatWM, blockWM)); + availSize.ConvertTo(floatWM, blockWM)); return floatRS.ComputedSizeWithMarginBorderPadding(blockWM).ISize(blockWM); } void nsBlockFrame::ReflowFloat(BlockReflowState& aState, - const LogicalRect& aAdjustedAvailableSpace, + const LogicalSize& aAvailableSize, nsIFrame* aFloat, LogicalMargin& aFloatMargin, LogicalMargin& aFloatOffsets, bool aFloatPushedDown, @@ -6659,17 +6641,15 @@ void nsBlockFrame::ReflowFloat(BlockReflowState& aState, WritingMode wm = aState.mReflowInput.GetWritingMode(); - ReflowInput floatRS( - aState.mPresContext, aState.mReflowInput, aFloat, - aAdjustedAvailableSpace.Size(wm).ConvertTo(aFloat->GetWritingMode(), wm)); + ReflowInput floatRS(aState.mPresContext, aState.mReflowInput, aFloat, + aAvailableSize.ConvertTo(aFloat->GetWritingMode(), wm)); // Normally the mIsTopOfPage state is copied from the parent reflow // input. However, when reflowing a float, if we've placed other // floats that force this float *down* or *narrower*, we should unset // the mIsTopOfPage state. if (floatRS.mFlags.mIsTopOfPage && - (aFloatPushedDown || - aAdjustedAvailableSpace.ISize(wm) != aState.ContentISize())) { + (aFloatPushedDown || aAvailableSize.ISize(wm) != aState.ContentISize())) { floatRS.mFlags.mIsTopOfPage = false; } @@ -6712,7 +6692,7 @@ void nsBlockFrame::ReflowFloat(BlockReflowState& aState, if (!aReflowStatus.IsFullyComplete() && ShouldAvoidBreakInside(floatRS)) { aReflowStatus.SetInlineLineBreakBeforeAndReset(); } else if (aReflowStatus.IsIncomplete() && - (NS_UNCONSTRAINEDSIZE == aAdjustedAvailableSpace.BSize(wm))) { + aAvailableSize.BSize(wm) == NS_UNCONSTRAINEDSIZE) { // An incomplete reflow status means we should split the float // if the height is constrained (bug 145305). aReflowStatus.Reset(); diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h index 9438bc60dc77..ca77d58691a4 100644 --- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -778,26 +778,23 @@ class nsBlockFrame : public nsContainerFrame { LineIterator aLine, nsIFrame* aFrame, LineReflowStatus* aLineReflowStatus); - // Compute the available size for a float. - mozilla::LogicalRect AdjustFloatAvailableSpace( - BlockReflowState& aState, - const mozilla::LogicalRect& aFloatAvailableSpace); // Computes the border-box inline size of the float nscoord ComputeFloatISize(BlockReflowState& aState, const mozilla::LogicalRect& aFloatAvailableSpace, nsIFrame* aFloat); - // An incomplete aReflowStatus indicates the float should be split - // but only if the available height is constrained. - // aAdjustedAvailableSpace is the result of calling - // nsBlockFrame::AdjustFloatAvailableSpace. + + // @param aAvailableSize the result of + // BlockReflowState::ComputeAvailableSizeForFloat(). + // @param aFloatPushedDown whether the block-direction position available to + // place a float has been pushed down due to the presence of other + // floats. + // @param aReflowStatus an incomplete status indicates the float should be + // split but only if the available block-size is constrained. void ReflowFloat(BlockReflowState& aState, - const mozilla::LogicalRect& aAdjustedAvailableSpace, - nsIFrame* aFloat, mozilla::LogicalMargin& aFloatMargin, - mozilla::LogicalMargin& aFloatOffsets, - // Whether the float's position - // (aAdjustedAvailableSpace) has been pushed down - // due to the presence of other floats. - bool aFloatPushedDown, nsReflowStatus& aReflowStatus); + const mozilla::LogicalSize& aAvailableSize, nsIFrame* aFloat, + mozilla::LogicalMargin& aFloatMargin, + mozilla::LogicalMargin& aFloatOffsets, bool aFloatPushedDown, + nsReflowStatus& aReflowStatus); //---------------------------------------- // Methods for pushing/pulling lines/frames