зеркало из https://github.com/mozilla/pjs.git
Make nsBlockReflowState::FlowAndPlaceFloat reflow the float after computing its vertical position, so we know how much height is actually available. (Bug 563584, patch 4) r=roc
Test coverage for this is in the future patch "Add reftests for bug 563584.".
This commit is contained in:
Родитель
4011b9b81d
Коммит
71c39670d6
|
@ -5576,7 +5576,7 @@ nsBlockFrame::ComputeFloatWidth(nsBlockReflowState& aState,
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
||||||
const nsRect& aFloatAvailableSpace,
|
const nsRect& aAdjustedAvailableSpace,
|
||||||
nsIFrame* aFloat,
|
nsIFrame* aFloat,
|
||||||
nsMargin& aFloatMargin,
|
nsMargin& aFloatMargin,
|
||||||
nsReflowStatus& aReflowStatus)
|
nsReflowStatus& aReflowStatus)
|
||||||
|
@ -5594,11 +5594,9 @@ nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nsRect availSpace = AdjustFloatAvailableSpace(aState, aFloatAvailableSpace,
|
|
||||||
aFloat);
|
|
||||||
|
|
||||||
nsHTMLReflowState floatRS(aState.mPresContext, aState.mReflowState, aFloat,
|
nsHTMLReflowState floatRS(aState.mPresContext, aState.mReflowState, aFloat,
|
||||||
nsSize(availSpace.width, availSpace.height));
|
nsSize(aAdjustedAvailableSpace.width,
|
||||||
|
aAdjustedAvailableSpace.height));
|
||||||
|
|
||||||
// Setup a block reflow state to reflow the float.
|
// Setup a block reflow state to reflow the float.
|
||||||
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState);
|
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState);
|
||||||
|
@ -5624,7 +5622,7 @@ nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = brc.ReflowBlock(availSpace, PR_TRUE, margin,
|
rv = brc.ReflowBlock(aAdjustedAvailableSpace, PR_TRUE, margin,
|
||||||
0, isAdjacentWithTop,
|
0, isAdjacentWithTop,
|
||||||
nsnull, floatRS,
|
nsnull, floatRS,
|
||||||
aReflowStatus, aState);
|
aReflowStatus, aState);
|
||||||
|
@ -5633,7 +5631,7 @@ nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
||||||
// An incomplete reflow status means we should split the float
|
// An incomplete reflow status means we should split the float
|
||||||
// if the height is constrained (bug 145305).
|
// if the height is constrained (bug 145305).
|
||||||
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
|
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
|
||||||
(NS_UNCONSTRAINEDSIZE == availSpace.height))
|
(NS_UNCONSTRAINEDSIZE == aAdjustedAvailableSpace.height))
|
||||||
aReflowStatus = NS_FRAME_COMPLETE;
|
aReflowStatus = NS_FRAME_COMPLETE;
|
||||||
|
|
||||||
if (aReflowStatus & NS_FRAME_REFLOW_NEXTINFLOW) {
|
if (aReflowStatus & NS_FRAME_REFLOW_NEXTINFLOW) {
|
||||||
|
|
|
@ -582,8 +582,10 @@ protected:
|
||||||
nsIFrame* aFloat);
|
nsIFrame* aFloat);
|
||||||
// An incomplete aReflowStatus indicates the float should be split
|
// An incomplete aReflowStatus indicates the float should be split
|
||||||
// but only if the available height is constrained.
|
// but only if the available height is constrained.
|
||||||
|
// aAdjustedAvailableSpace is the result of calling
|
||||||
|
// nsBlockFrame::AdjustFloatAvailableSpace.
|
||||||
nsresult ReflowFloat(nsBlockReflowState& aState,
|
nsresult ReflowFloat(nsBlockReflowState& aState,
|
||||||
const nsRect& aFloatAvailableSpace,
|
const nsRect& aAdjustedAvailableSpace,
|
||||||
nsIFrame* aFloat,
|
nsIFrame* aFloat,
|
||||||
nsMargin& aFloatMargin,
|
nsMargin& aFloatMargin,
|
||||||
nsReflowStatus& aReflowStatus);
|
nsReflowStatus& aReflowStatus);
|
||||||
|
|
|
@ -636,6 +636,30 @@ nsBlockReflowState::CanPlaceFloat(nscoord aFloatWidth,
|
||||||
aFloatAvailableSpace.mRect.width >= aFloatWidth;
|
aFloatAvailableSpace.mRect.width >= aFloatWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static nscoord
|
||||||
|
FloatMarginWidth(const nsHTMLReflowState& aCBReflowState,
|
||||||
|
nscoord aFloatAvailableWidth,
|
||||||
|
nsIFrame *aFloat,
|
||||||
|
const nsCSSOffsetState& aFloatOffsetState)
|
||||||
|
{
|
||||||
|
return aFloat->ComputeSize(
|
||||||
|
aCBReflowState.rendContext,
|
||||||
|
nsSize(aCBReflowState.ComputedWidth(),
|
||||||
|
aCBReflowState.ComputedHeight()),
|
||||||
|
aFloatAvailableWidth,
|
||||||
|
nsSize(aFloatOffsetState.mComputedMargin.LeftRight(),
|
||||||
|
aFloatOffsetState.mComputedMargin.TopBottom()),
|
||||||
|
nsSize(aFloatOffsetState.mComputedBorderPadding.LeftRight() -
|
||||||
|
aFloatOffsetState.mComputedPadding.LeftRight(),
|
||||||
|
aFloatOffsetState.mComputedBorderPadding.TopBottom() -
|
||||||
|
aFloatOffsetState.mComputedPadding.TopBottom()),
|
||||||
|
nsSize(aFloatOffsetState.mComputedPadding.LeftRight(),
|
||||||
|
aFloatOffsetState.mComputedPadding.TopBottom()),
|
||||||
|
PR_TRUE).width +
|
||||||
|
aFloatOffsetState.mComputedMargin.LeftRight() +
|
||||||
|
aFloatOffsetState.mComputedBorderPadding.LeftRight();
|
||||||
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
|
nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
|
||||||
nsReflowStatus& aReflowStatus)
|
nsReflowStatus& aReflowStatus)
|
||||||
|
@ -667,32 +691,18 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
|
||||||
}
|
}
|
||||||
// Get the band of available space
|
// Get the band of available space
|
||||||
nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(mY);
|
nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(mY);
|
||||||
|
nsRect adjustedAvailableSpace = mBlock->AdjustFloatAvailableSpace(*this,
|
||||||
|
floatAvailableSpace.mRect, aFloat);
|
||||||
|
|
||||||
NS_ASSERTION(aFloat->GetParent() == mBlock,
|
NS_ASSERTION(aFloat->GetParent() == mBlock,
|
||||||
"Float frame has wrong parent");
|
"Float frame has wrong parent");
|
||||||
|
|
||||||
// Reflow the float
|
nsCSSOffsetState offsets(aFloat, mReflowState.rendContext,
|
||||||
nsMargin floatMargin; // computed margin
|
mReflowState.ComputedWidth());
|
||||||
mBlock->ReflowFloat(*this, floatAvailableSpace.mRect, aFloat,
|
|
||||||
floatMargin, aReflowStatus);
|
|
||||||
if (aFloat->GetPrevInFlow())
|
|
||||||
floatMargin.top = 0;
|
|
||||||
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus))
|
|
||||||
floatMargin.bottom = 0;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
nscoord floatMarginWidth = FloatMarginWidth(mReflowState,
|
||||||
if (nsBlockFrame::gNoisyReflow) {
|
adjustedAvailableSpace.width,
|
||||||
nsRect region = aFloat->GetRect();
|
aFloat, offsets);
|
||||||
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
|
||||||
printf("flowed float: ");
|
|
||||||
nsFrame::ListTag(stdout, aFloat);
|
|
||||||
printf(" (%d,%d,%d,%d)\n",
|
|
||||||
region.x, region.y, region.width, region.height);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
nsSize floatSize = aFloat->GetSize() +
|
|
||||||
nsSize(floatMargin.LeftRight(), floatMargin.TopBottom());
|
|
||||||
|
|
||||||
// Find a place to place the float. The CSS2 spec doesn't want
|
// Find a place to place the float. The CSS2 spec doesn't want
|
||||||
// floats overlapping each other or sticking out of the containing
|
// floats overlapping each other or sticking out of the containing
|
||||||
|
@ -711,7 +721,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CanPlaceFloat(floatSize.width, floatAvailableSpace)) {
|
if (CanPlaceFloat(floatMarginWidth, floatAvailableSpace)) {
|
||||||
// We found an appropriate place.
|
// We found an appropriate place.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -721,9 +731,12 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
|
||||||
eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) {
|
eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) {
|
||||||
|
|
||||||
mY += floatAvailableSpace.mRect.height;
|
mY += floatAvailableSpace.mRect.height;
|
||||||
|
if (adjustedAvailableSpace.height != NS_UNCONSTRAINEDSIZE) {
|
||||||
|
adjustedAvailableSpace.height -= floatAvailableSpace.mRect.height;
|
||||||
|
}
|
||||||
floatAvailableSpace = GetFloatAvailableSpace(mY);
|
floatAvailableSpace = GetFloatAvailableSpace(mY);
|
||||||
} else {
|
} else {
|
||||||
// This quirk matches the one in nsBlockFrame::ReflowFloat
|
// This quirk matches the one in nsBlockFrame::AdjustFloatAvailableSpace
|
||||||
// IE handles float tables in a very special way
|
// IE handles float tables in a very special way
|
||||||
|
|
||||||
// see if the previous float is also a table and has "align"
|
// see if the previous float is also a table and has "align"
|
||||||
|
@ -760,18 +773,17 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
|
||||||
|
|
||||||
// the table does not fit anymore in this line so advance to next band
|
// the table does not fit anymore in this line so advance to next band
|
||||||
mY += floatAvailableSpace.mRect.height;
|
mY += floatAvailableSpace.mRect.height;
|
||||||
|
// To match nsBlockFrame::AdjustFloatAvailableSpace, we have to
|
||||||
|
// get a new width for the new band.
|
||||||
floatAvailableSpace = GetFloatAvailableSpace(mY);
|
floatAvailableSpace = GetFloatAvailableSpace(mY);
|
||||||
// reflow the float again now since we have more space
|
adjustedAvailableSpace = mBlock->AdjustFloatAvailableSpace(*this,
|
||||||
// XXXldb We really don't need to Reflow in a loop, we just need
|
floatAvailableSpace.mRect, aFloat);
|
||||||
// to ComputeSize in a loop (once ComputeSize depends on
|
floatMarginWidth = FloatMarginWidth(mReflowState,
|
||||||
// availableWidth, which should make this work again).
|
adjustedAvailableSpace.width,
|
||||||
mBlock->ReflowFloat(*this, floatAvailableSpace.mRect, aFloat,
|
aFloat, offsets);
|
||||||
floatMargin, aReflowStatus);
|
|
||||||
// Get the floats bounding box and margin information
|
|
||||||
floatSize = aFloat->GetSize() +
|
|
||||||
nsSize(floatMargin.LeftRight(), floatMargin.TopBottom());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the float is continued, it will get the same absolute x value as its prev-in-flow
|
// If the float is continued, it will get the same absolute x value as its prev-in-flow
|
||||||
|
|
||||||
// We don't worry about the geometry of the prev in flow, let the continuation
|
// We don't worry about the geometry of the prev in flow, let the continuation
|
||||||
|
@ -787,7 +799,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!keepFloatOnSameLine) {
|
if (!keepFloatOnSameLine) {
|
||||||
floatX = floatAvailableSpace.mRect.XMost() - floatSize.width;
|
floatX = floatAvailableSpace.mRect.XMost() - floatMarginWidth;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// this is the IE quirk (see few lines above)
|
// this is the IE quirk (see few lines above)
|
||||||
|
@ -807,6 +819,16 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
|
||||||
floatY = 0;
|
floatY = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reflow the float after computing its vertical position so it knows
|
||||||
|
// where to break.
|
||||||
|
nsMargin floatMargin; // computed margin
|
||||||
|
mBlock->ReflowFloat(*this, adjustedAvailableSpace, aFloat,
|
||||||
|
floatMargin, aReflowStatus);
|
||||||
|
if (aFloat->GetPrevInFlow())
|
||||||
|
floatMargin.top = 0;
|
||||||
|
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus))
|
||||||
|
floatMargin.bottom = 0;
|
||||||
|
|
||||||
// Calculate the actual origin of the float frame's border rect
|
// Calculate the actual origin of the float frame's border rect
|
||||||
// relative to the parent block; floatX/Y must be converted from space-manager
|
// relative to the parent block; floatX/Y must be converted from space-manager
|
||||||
// coordinates to parent coordinates, and the margin must be added in
|
// coordinates to parent coordinates, and the margin must be added in
|
||||||
|
|
Загрузка…
Ссылка в новой задаче