mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 18:08:58 +00:00
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
This commit is contained in:
parent
70e03e7368
commit
48a466967c
@ -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;
|
||||
|
@ -219,6 +219,8 @@ class BlockReflowState {
|
||||
const nsFlowAreaRect& aFloatAvailableSpace,
|
||||
bool aBlockAvoidsFloats);
|
||||
|
||||
LogicalSize ComputeAvailableSizeForFloat() const;
|
||||
|
||||
void RecoverStateFrom(nsLineList::iterator aLine, nscoord aDeltaBCoord);
|
||||
|
||||
void AdvanceToNextLine() {
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user