зеркало из 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
|
||||
nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
||||
const nsRect& aFloatAvailableSpace,
|
||||
const nsRect& aAdjustedAvailableSpace,
|
||||
nsIFrame* aFloat,
|
||||
nsMargin& aFloatMargin,
|
||||
nsReflowStatus& aReflowStatus)
|
||||
|
@ -5594,11 +5594,9 @@ nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
|||
);
|
||||
#endif
|
||||
|
||||
nsRect availSpace = AdjustFloatAvailableSpace(aState, aFloatAvailableSpace,
|
||||
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.
|
||||
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,
|
||||
nsnull, floatRS,
|
||||
aReflowStatus, aState);
|
||||
|
@ -5633,7 +5631,7 @@ nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
|||
// An incomplete reflow status means we should split the float
|
||||
// if the height is constrained (bug 145305).
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
|
||||
(NS_UNCONSTRAINEDSIZE == availSpace.height))
|
||||
(NS_UNCONSTRAINEDSIZE == aAdjustedAvailableSpace.height))
|
||||
aReflowStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
if (aReflowStatus & NS_FRAME_REFLOW_NEXTINFLOW) {
|
||||
|
|
|
@ -582,8 +582,10 @@ protected:
|
|||
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.
|
||||
nsresult ReflowFloat(nsBlockReflowState& aState,
|
||||
const nsRect& aFloatAvailableSpace,
|
||||
const nsRect& aAdjustedAvailableSpace,
|
||||
nsIFrame* aFloat,
|
||||
nsMargin& aFloatMargin,
|
||||
nsReflowStatus& aReflowStatus);
|
||||
|
|
|
@ -636,6 +636,30 @@ nsBlockReflowState::CanPlaceFloat(nscoord 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
|
||||
nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
|
||||
nsReflowStatus& aReflowStatus)
|
||||
|
@ -667,32 +691,18 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
|
|||
}
|
||||
// Get the band of available space
|
||||
nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(mY);
|
||||
nsRect adjustedAvailableSpace = mBlock->AdjustFloatAvailableSpace(*this,
|
||||
floatAvailableSpace.mRect, aFloat);
|
||||
|
||||
NS_ASSERTION(aFloat->GetParent() == mBlock,
|
||||
"Float frame has wrong parent");
|
||||
|
||||
// Reflow the float
|
||||
nsMargin floatMargin; // computed margin
|
||||
mBlock->ReflowFloat(*this, floatAvailableSpace.mRect, aFloat,
|
||||
floatMargin, aReflowStatus);
|
||||
if (aFloat->GetPrevInFlow())
|
||||
floatMargin.top = 0;
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus))
|
||||
floatMargin.bottom = 0;
|
||||
nsCSSOffsetState offsets(aFloat, mReflowState.rendContext,
|
||||
mReflowState.ComputedWidth());
|
||||
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyReflow) {
|
||||
nsRect region = aFloat->GetRect();
|
||||
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());
|
||||
nscoord floatMarginWidth = FloatMarginWidth(mReflowState,
|
||||
adjustedAvailableSpace.width,
|
||||
aFloat, offsets);
|
||||
|
||||
// Find a place to place the float. The CSS2 spec doesn't want
|
||||
// floats overlapping each other or sticking out of the containing
|
||||
|
@ -711,7 +721,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (CanPlaceFloat(floatSize.width, floatAvailableSpace)) {
|
||||
if (CanPlaceFloat(floatMarginWidth, floatAvailableSpace)) {
|
||||
// We found an appropriate place.
|
||||
break;
|
||||
}
|
||||
|
@ -721,9 +731,12 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
|
|||
eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) {
|
||||
|
||||
mY += floatAvailableSpace.mRect.height;
|
||||
if (adjustedAvailableSpace.height != NS_UNCONSTRAINEDSIZE) {
|
||||
adjustedAvailableSpace.height -= floatAvailableSpace.mRect.height;
|
||||
}
|
||||
floatAvailableSpace = GetFloatAvailableSpace(mY);
|
||||
} 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
|
||||
|
||||
// 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
|
||||
mY += floatAvailableSpace.mRect.height;
|
||||
// To match nsBlockFrame::AdjustFloatAvailableSpace, we have to
|
||||
// get a new width for the new band.
|
||||
floatAvailableSpace = GetFloatAvailableSpace(mY);
|
||||
// reflow the float again now since we have more space
|
||||
// XXXldb We really don't need to Reflow in a loop, we just need
|
||||
// to ComputeSize in a loop (once ComputeSize depends on
|
||||
// availableWidth, which should make this work again).
|
||||
mBlock->ReflowFloat(*this, floatAvailableSpace.mRect, aFloat,
|
||||
floatMargin, aReflowStatus);
|
||||
// Get the floats bounding box and margin information
|
||||
floatSize = aFloat->GetSize() +
|
||||
nsSize(floatMargin.LeftRight(), floatMargin.TopBottom());
|
||||
adjustedAvailableSpace = mBlock->AdjustFloatAvailableSpace(*this,
|
||||
floatAvailableSpace.mRect, aFloat);
|
||||
floatMarginWidth = FloatMarginWidth(mReflowState,
|
||||
adjustedAvailableSpace.width,
|
||||
aFloat, offsets);
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -787,7 +799,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
|
|||
}
|
||||
else {
|
||||
if (!keepFloatOnSameLine) {
|
||||
floatX = floatAvailableSpace.mRect.XMost() - floatSize.width;
|
||||
floatX = floatAvailableSpace.mRect.XMost() - floatMarginWidth;
|
||||
}
|
||||
else {
|
||||
// this is the IE quirk (see few lines above)
|
||||
|
@ -807,6 +819,16 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
|
|||
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
|
||||
// relative to the parent block; floatX/Y must be converted from space-manager
|
||||
// coordinates to parent coordinates, and the margin must be added in
|
||||
|
|
Загрузка…
Ссылка в новой задаче