Bug 1778931 Part 1 - Create a float's ReflowInput in FlowAndPlaceFloat() and pass it into ReflowFloat(). r=dholbert

There is some advantage to creating the float's ReflowInput in
FlowAndPlaceFloat().

1. ReflowFloat() doesn't need to output the float's margin and offset via the
   output arguments. FlowAndPlaceFloat() can get them from the local ReflowInput
   directly.

2. Since we are going to reflow the float, we have to create a ReflowInput
   anyway. FloatMarginISize() can take the ReflowInput and be simplified. No need
   to waste time to create a separate SizeComputationInput.

Also, delete the comment "Pass floatRS so the frame hierarchy can be
used (redoFloatRS has the same hierarchy)" because I believe it is obsolete.

This patch also lays the foundation for other improvements in the later patches.

Differential Revision: https://phabricator.services.mozilla.com/D151455
This commit is contained in:
Ting-Yu Lin 2022-07-26 04:54:36 +00:00
Родитель fd92081aec
Коммит 82c88e59cb
4 изменённых файлов: 39 добавлений и 58 удалений

Просмотреть файл

@ -648,28 +648,12 @@ bool BlockReflowState::CanPlaceFloat(
// NS_UNCONSTRAINEDSIZE, we're dealing with an orthogonal block that
// has block-size:auto, and we'll need to actually reflow it to find out
// how much inline-size it will occupy in the containing block's mode.
static nscoord FloatMarginISize(const ReflowInput& aCBReflowInput,
nscoord aFloatAvailableISize, nsIFrame* aFloat,
const SizeComputationInput& aFloatSizingInput) {
AutoMaybeDisableFontInflation an(aFloat);
WritingMode wm = aFloatSizingInput.GetWritingMode();
auto floatSize = aFloat->ComputeSize(
aCBReflowInput.mRenderingContext, wm, aCBReflowInput.ComputedSize(wm),
aFloatAvailableISize,
aFloatSizingInput.ComputedLogicalMargin(wm).Size(wm),
aFloatSizingInput.ComputedLogicalBorderPadding(wm).Size(wm), {},
ComputeSizeFlag::ShrinkWrap);
WritingMode cbwm = aCBReflowInput.GetWritingMode();
nscoord floatISize = floatSize.mLogicalSize.ConvertTo(cbwm, wm).ISize(cbwm);
if (floatISize == NS_UNCONSTRAINEDSIZE) {
static nscoord FloatMarginISize(WritingMode aCBWM,
const ReflowInput& aFloatRI) {
if (aFloatRI.ComputedSize(aCBWM).ISize(aCBWM) == NS_UNCONSTRAINEDSIZE) {
return NS_UNCONSTRAINEDSIZE; // reflow is needed to get the true size
}
return floatISize +
aFloatSizingInput.ComputedLogicalMargin(cbwm).IStartEnd(cbwm) +
aFloatSizingInput.ComputedLogicalBorderPadding(cbwm).IStartEnd(cbwm);
return aFloatRI.ComputedSizeWithMarginBorderPadding(aCBWM).ISize(aCBWM);
}
// A frame property that stores the last shape source / margin / etc. if there's
@ -753,14 +737,12 @@ BlockReflowState::PlaceFloatResult BlockReflowState::FlowAndPlaceFloat(
}
LogicalSize availSize = ComputeAvailableSizeForFloat();
SizeComputationInput sizingInput(aFloat, mReflowInput.mRenderingContext, wm,
mReflowInput.ComputedISize());
const WritingMode floatWM = aFloat->GetWritingMode();
Maybe<ReflowInput> floatRI(std::in_place, mPresContext, mReflowInput, aFloat,
availSize.ConvertTo(floatWM, wm));
nscoord floatMarginISize =
FloatMarginISize(mReflowInput, availSize.ISize(wm), aFloat, sizingInput);
LogicalMargin floatMargin(wm); // computed margin
LogicalMargin floatOffsets(wm);
nscoord floatMarginISize = FloatMarginISize(wm, *floatRI);
LogicalMargin floatMargin = floatRI->ComputedLogicalMargin(wm);
nsReflowStatus reflowStatus;
// If it's a floating first-letter, we need to reflow it before we
@ -772,8 +754,8 @@ BlockReflowState::PlaceFloatResult BlockReflowState::FlowAndPlaceFloat(
bool earlyFloatReflow =
aFloat->IsLetterFrame() || floatMarginISize == NS_UNCONSTRAINEDSIZE;
if (earlyFloatReflow) {
mBlock->ReflowFloat(*this, availSize, aFloat, floatMargin, floatOffsets,
false, reflowStatus);
mBlock->ReflowFloat(*this, *floatRI, availSize, aFloat, false,
reflowStatus);
floatMarginISize = aFloat->ISize(wm) + floatMargin.IStartEnd(wm);
NS_ASSERTION(reflowStatus.IsComplete(),
"letter frames and orthogonal floats with auto block-size "
@ -853,9 +835,16 @@ BlockReflowState::PlaceFloatResult BlockReflowState::FlowAndPlaceFloat(
// Reflow the float after computing its vertical position so it knows
// where to break.
if (!earlyFloatReflow) {
const LogicalSize oldAvailSize = availSize;
availSize = ComputeAvailableSizeForFloat();
if (oldAvailSize != availSize) {
floatRI.reset();
floatRI.emplace(mPresContext, mReflowInput, aFloat,
availSize.ConvertTo(floatWM, wm));
}
bool pushedDown = mBCoord != restoreBCoord.SavedValue();
mBlock->ReflowFloat(*this, ComputeAvailableSizeForFloat(), aFloat,
floatMargin, floatOffsets, pushedDown, reflowStatus);
mBlock->ReflowFloat(*this, *floatRI, availSize, aFloat, pushedDown,
reflowStatus);
}
if (aFloat->GetPrevInFlow()) {
floatMargin.BStart(wm) = 0;
@ -892,6 +881,7 @@ BlockReflowState::PlaceFloatResult BlockReflowState::FlowAndPlaceFloat(
floatMargin.BStart(wm) + floatPos.B(wm));
// If float is relatively positioned, factor that in as well
const LogicalMargin floatOffsets = floatRI->ComputedLogicalOffsets(wm);
ReflowInput::ApplyRelativePositioning(aFloat, wm, floatOffsets, &origin,
ContainerSize());

Просмотреть файл

@ -327,6 +327,12 @@ struct ReflowInput : public SizeComputationInput {
return mComputedMaxSize.BSize(mWritingMode);
}
// WARNING: In general, adjusting available inline-size or block-size is not
// safe because ReflowInput has members whose values depend on the available
// size passing through the constructor. For example,
// CalculateBlockSideMargins() is called during initialization, and uses
// AvailableSize(). Make sure your use case doesn't lead to stale member
// values in ReflowInput!
void SetAvailableISize(nscoord aAvailableISize) {
mAvailableSize.ISize(mWritingMode) = aAvailableISize;
}

Просмотреть файл

@ -6617,11 +6617,9 @@ const nsStyleText* nsBlockFrame::StyleTextForLineLayout() {
return StyleText();
}
void nsBlockFrame::ReflowFloat(BlockReflowState& aState,
void nsBlockFrame::ReflowFloat(BlockReflowState& aState, ReflowInput& aFloatRI,
const LogicalSize& aAvailableSize,
nsIFrame* aFloat, LogicalMargin& aFloatMargin,
LogicalMargin& aFloatOffsets,
bool aFloatPushedDown,
nsIFrame* aFloat, bool aFloatPushedDown,
nsReflowStatus& aReflowStatus) {
MOZ_ASSERT(aReflowStatus.IsEmpty(),
"Caller should pass a fresh reflow status!");
@ -6630,16 +6628,13 @@ void nsBlockFrame::ReflowFloat(BlockReflowState& aState,
WritingMode wm = aState.mReflowInput.GetWritingMode();
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 &&
if (aFloatRI.mFlags.mIsTopOfPage &&
(aFloatPushedDown || aAvailableSize.ISize(wm) != aState.ContentISize())) {
floatRS.mFlags.mIsTopOfPage = false;
aFloatRI.mFlags.mIsTopOfPage = false;
}
// Setup a block reflow context to reflow the float.
@ -6649,14 +6644,14 @@ void nsBlockFrame::ReflowFloat(BlockReflowState& aState,
do {
nsCollapsingMargin margin;
bool mayNeedRetry = false;
floatRS.mDiscoveredClearance = nullptr;
aFloatRI.mDiscoveredClearance = nullptr;
// Only first in flow gets a block-start margin.
if (!aFloat->GetPrevInFlow()) {
brc.ComputeCollapsedBStartMargin(floatRS, &margin, clearanceFrame,
brc.ComputeCollapsedBStartMargin(aFloatRI, &margin, clearanceFrame,
&mayNeedRetry);
if (mayNeedRetry && !clearanceFrame) {
floatRS.mDiscoveredClearance = &clearanceFrame;
aFloatRI.mDiscoveredClearance = &clearanceFrame;
// We don't need to push the float manager state because the the block
// has its own float manager that will be destroyed and recreated
}
@ -6665,7 +6660,7 @@ void nsBlockFrame::ReflowFloat(BlockReflowState& aState,
// When reflowing a float, aSpace argument doesn't matter because we pass
// nullptr to aLine and we don't call nsBlockReflowContext::PlaceBlock()
// later.
brc.ReflowBlock(LogicalRect(wm), true, margin, 0, nullptr, floatRS,
brc.ReflowBlock(LogicalRect(wm), true, margin, 0, nullptr, aFloatRI,
aReflowStatus, aState);
} while (clearanceFrame);
@ -6678,7 +6673,7 @@ void nsBlockFrame::ReflowFloat(BlockReflowState& aState,
}
}
if (!aReflowStatus.IsFullyComplete() && ShouldAvoidBreakInside(floatRS)) {
if (!aReflowStatus.IsFullyComplete() && ShouldAvoidBreakInside(aFloatRI)) {
aReflowStatus.SetInlineLineBreakBeforeAndReset();
} else if (aReflowStatus.IsIncomplete() &&
aAvailableSize.BSize(wm) == NS_UNCONSTRAINEDSIZE) {
@ -6691,12 +6686,6 @@ void nsBlockFrame::ReflowFloat(BlockReflowState& aState,
aState.mReflowStatus.SetNextInFlowNeedsReflow();
}
// Capture the margin and offsets information for the caller
aFloatMargin =
// float margins don't collapse
floatRS.ComputedLogicalMargin(wm);
aFloatOffsets = floatRS.ComputedLogicalOffsets(wm);
const ReflowOutput& metrics = brc.GetMetrics();
// Set the rect, make sure the view is properly sized and positioned,
@ -6712,9 +6701,7 @@ void nsBlockFrame::ReflowFloat(BlockReflowState& aState,
aState.mPresContext, aFloat, aFloat->GetView(), metrics.InkOverflow(),
ReflowChildFlags::NoMoveView);
}
// Pass floatRS so the frame hierarchy can be used (redoFloatRS has the same
// hierarchy)
aFloat->DidReflow(aState.mPresContext, &floatRS);
aFloat->DidReflow(aState.mPresContext, &aFloatRI);
}
StyleClear nsBlockFrame::FindTrailingClear() {

Просмотреть файл

@ -785,11 +785,9 @@ class nsBlockFrame : public nsContainerFrame {
// 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,
void ReflowFloat(BlockReflowState& aState, ReflowInput& aFloatRI,
const mozilla::LogicalSize& aAvailableSize, nsIFrame* aFloat,
mozilla::LogicalMargin& aFloatMargin,
mozilla::LogicalMargin& aFloatOffsets, bool aFloatPushedDown,
nsReflowStatus& aReflowStatus);
bool aFloatPushedDown, nsReflowStatus& aReflowStatus);
//----------------------------------------
// Methods for pushing/pulling lines/frames