Remove aForceFit/aRelaxHeightConstraint concept from float reflow, since we now split floats rather than push them to the next page (and correct propagation of nsHTMLReflowState::mFlags::mIsTopOfPage will force fitting when we need to). (Bug 563584, patch 2) r=roc

This commit is contained in:
L. David Baron 2010-08-05 21:59:18 -07:00
parent 367e34d52e
commit bf246f7401
8 changed files with 72 additions and 51 deletions

View File

@ -4201,9 +4201,6 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
return PR_TRUE;
}
// May be needed below
PRBool wasAdjacentWIthTop = aState.IsAdjacentWithTop();
aState.mY = newY;
// Add the already placed current-line floats to the line
@ -4213,8 +4210,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
if (aState.mBelowCurrentLineFloats.NotEmpty()) {
// Reflow the below-current-line floats, then add them to the
// lines float list if there aren't any truncated floats.
if (aState.PlaceBelowCurrentLineFloats(aState.mBelowCurrentLineFloats,
wasAdjacentWIthTop)) {
if (aState.PlaceBelowCurrentLineFloats(aState.mBelowCurrentLineFloats)) {
aLine->AppendFloats(aState.mBelowCurrentLineFloats);
}
else {
@ -6599,7 +6595,7 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState,
// FIXME: aLineTop isn't actually set correctly by some callers, since
// they reposition the line.
nsRect floatAvailSpace =
aState.GetFloatAvailableSpaceWithState(aLineTop, PR_FALSE,
aState.GetFloatAvailableSpaceWithState(aLineTop,
&aState.mFloatManagerStateBefore)
.mRect;
// FIXME (bug 25888): need to check the entire region that the first

View File

@ -325,7 +325,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
nsFlowAreaRect
nsBlockReflowState::GetFloatAvailableSpaceWithState(
nscoord aY, PRBool aRelaxHeightConstraint,
nscoord aY,
nsFloatManager::SavedState *aState) const
{
#ifdef DEBUG
@ -339,9 +339,8 @@ nsBlockReflowState::GetFloatAvailableSpaceWithState(
nsFlowAreaRect result =
mFloatManager->GetFlowArea(aY - BorderPadding().top,
nsFloatManager::BAND_FROM_POINT,
aRelaxHeightConstraint ? nscoord_MAX
: mContentArea.height,
mContentArea.width, aState);
mContentArea.height, mContentArea.width,
aState);
// Keep the width >= 0 for compatibility with nsSpaceManager.
if (result.mRect.width < 0)
result.mRect.width = 0;
@ -578,17 +577,10 @@ nsBlockReflowState::AddFloat(nsLineLayout* aLineLayout,
mFloatManager->PushState(&floatManagerState);
// And then place it
// force it to fit if we're at the top of the block and we can't
// break before this
PRBool forceFit = !aLineLayout ||
(IsAdjacentWithTop() && !aLineLayout->LineIsBreakable());
placed = FlowAndPlaceFloat(aFloat, aReflowStatus, forceFit);
NS_ASSERTION(placed || !forceFit,
"If we asked for force-fit, it should have been placed");
if (forceFit || (placed && !NS_FRAME_IS_TRUNCATED(aReflowStatus))) {
placed = FlowAndPlaceFloat(aFloat, aReflowStatus);
if (placed && !NS_FRAME_IS_TRUNCATED(aReflowStatus)) {
// Pass on updated available space to the current inline reflow engine
nsFlowAreaRect floatAvailSpace =
GetFloatAvailableSpace(mY, forceFit);
nsFlowAreaRect floatAvailSpace = GetFloatAvailableSpace(mY);
nsRect availSpace(nsPoint(floatAvailSpace.mRect.x + BorderPadding().left,
mY),
floatAvailSpace.mRect.Size());
@ -597,9 +589,6 @@ nsBlockReflowState::AddFloat(nsLineLayout* aLineLayout,
// Record this float in the current-line list
mCurrentLineFloats.Append(mFloatCacheFreeList.Alloc(aFloat));
}
// If we can't break here, hide the fact that it's truncated
// XXX We can probably do this more cleanly
aReflowStatus &= ~NS_FRAME_TRUNCATED;
}
else {
if (placed) {
@ -637,8 +626,7 @@ nsBlockReflowState::AddFloat(nsLineLayout* aLineLayout,
PRBool
nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats,
const nsFlowAreaRect& aFloatAvailableSpace,
PRBool aForceFit)
const nsFlowAreaRect& aFloatAvailableSpace)
{
// If the current Y coordinate is not impacted by any floats
// then by definition the float fits.
@ -709,7 +697,7 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats,
}
mY += floatAvailableSpace.mRect.height;
floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit);
floatAvailableSpace = GetFloatAvailableSpace(mY);
if (floatAvailableSpace.mHasFloats) {
if (xa < floatAvailableSpace.mRect.x ||
@ -737,8 +725,7 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats,
PRBool
nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
nsReflowStatus& aReflowStatus,
PRBool aForceFit)
nsReflowStatus& aReflowStatus)
{
aReflowStatus = NS_FRAME_COMPLETE;
// Save away the Y coordinate before placing the float. We will
@ -766,7 +753,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
mY = ClearFloats(mY, floatDisplay->mBreakType);
}
// Get the band of available space
nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit);
nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(mY);
NS_ASSERTION(aFloat->GetParent() == mBlock,
"Float frame has wrong parent");
@ -804,8 +791,8 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
// Can the float fit here?
PRBool keepFloatOnSameLine = PR_FALSE;
while (!CanPlaceFloat(floatSize, floatDisplay->mFloats, floatAvailableSpace,
aForceFit)) {
while (!CanPlaceFloat(floatSize, floatDisplay->mFloats,
floatAvailableSpace)) {
if (floatAvailableSpace.mRect.height <= 0) {
// No space, nowhere to put anything.
mY = saveY;
@ -817,7 +804,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) {
mY += floatAvailableSpace.mRect.height;
floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit);
floatAvailableSpace = GetFloatAvailableSpace(mY);
} else {
// This quirk matches the one in nsBlockFrame::ReflowFloat
// IE handles float tables in a very special way
@ -856,7 +843,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
// the table does not fit anymore in this line so advance to next band
mY += floatAvailableSpace.mRect.height;
floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit);
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
@ -984,7 +971,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat,
* Place below-current-line floats.
*/
PRBool
nsBlockReflowState::PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aList, PRBool aForceFit)
nsBlockReflowState::PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aList)
{
nsFloatCache* fc = aList.Head();
while (fc) {
@ -999,11 +986,9 @@ nsBlockReflowState::PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aList, PRB
#endif
// Place the float
nsReflowStatus reflowStatus;
PRBool placed = FlowAndPlaceFloat(fc->mFloat, reflowStatus, aForceFit);
NS_ASSERTION(placed || !aForceFit,
"If we're in force-fit mode, we should have placed the float");
PRBool placed = FlowAndPlaceFloat(fc->mFloat, reflowStatus);
if (!placed || (NS_FRAME_IS_TRUNCATED(reflowStatus) && !aForceFit)) {
if (!placed || NS_FRAME_IS_TRUNCATED(reflowStatus)) {
// return before processing all of the floats, since the line will be pushed.
return PR_FALSE;
}
@ -1052,8 +1037,7 @@ nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType,
if (aReplacedBlock) {
for (;;) {
nsFlowAreaRect floatAvailableSpace =
GetFloatAvailableSpace(newY, PR_FALSE);
nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(newY);
nsBlockFrame::ReplacedElementWidthToClear replacedWidth =
nsBlockFrame::WidthToClearPastFloats(*this, floatAvailableSpace.mRect,
aReplacedBlock);

View File

@ -87,13 +87,11 @@ public:
* coordinate and within the width of the content rect.
*/
nsFlowAreaRect GetFloatAvailableSpace() const
{ return GetFloatAvailableSpace(mY, PR_FALSE); }
nsFlowAreaRect GetFloatAvailableSpace(nscoord aY,
PRBool aRelaxHeightConstraint) const
{ return GetFloatAvailableSpaceWithState(aY, aRelaxHeightConstraint,
nsnull); }
{ return GetFloatAvailableSpace(mY); }
nsFlowAreaRect GetFloatAvailableSpace(nscoord aY) const
{ return GetFloatAvailableSpaceWithState(aY, nsnull); }
nsFlowAreaRect
GetFloatAvailableSpaceWithState(nscoord aY, PRBool aRelaxHeightConstraint,
GetFloatAvailableSpaceWithState(nscoord aY,
nsFloatManager::SavedState *aState) const;
nsFlowAreaRect
GetFloatAvailableSpaceForHeight(nscoord aY, nscoord aHeight,
@ -111,12 +109,10 @@ public:
nscoord aAvailableWidth,
nsReflowStatus& aReflowStatus);
PRBool CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats,
const nsFlowAreaRect& aFloatAvailableSpace,
PRBool aForceFit);
const nsFlowAreaRect& aFloatAvailableSpace);
PRBool FlowAndPlaceFloat(nsIFrame* aFloat,
nsReflowStatus& aReflowStatus,
PRBool aForceFit);
PRBool PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aFloats, PRBool aForceFit);
nsReflowStatus& aReflowStatus);
PRBool PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aFloats);
// Returns the first coordinate >= aY that clears the
// floats indicated by aBreakType and has enough width between floats

View File

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<title>Testcase for float breaking</title>
<body style="margin: 0">
<div style="position: absolute; top: 0; left: 0; width: 150px; height: 100px; background: blue"></div>
<div style="position: absolute; top: 100px; left: 0; width: 75px; height: 200px; background: aqua"></div>
<div style="position: absolute; top: 0; left: 200px; width: 100px; height: 350px; background: fuchsia"></div>

View File

@ -0,0 +1,9 @@
<!DOCTYPE HTML>
<title>Testcase for float breaking</title>
<body style="-moz-column-count: 2; -moz-column-gap: 0; margin: 0; width: 400px; height: 400px">
<!-- two columns, each 200px wide and 400px tall -->
<div style="float: left; width: 150px; height: 100px; background: blue"></div>
<div style="float: left; width: 75px; height: 200px; background: aqua"></div>
<!-- test to see where this float goes -->
<div style="float: left; width: 100px; height: 350px; background: fuchsia"></div>

View File

@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<html class="reftest-print">
<title>Testcase for float breaking (reference)</title>
<body style="margin: 0">
<div style="width: 3.5in; height: 0.5in; background: blue"></div>
<div>
<div style="display: inline-block; vertical-align: top; height: 1in; width: 1in; background: aqua"></div
><div style="display: inline-block; vertical-align: top; height: 1in; width: 2in; background: fuchsia"></div>
</div>
<div>
<div style="display: inline-block; vertical-align: top; height: 0.5in; width: 1in"></div
><div style="display: inline-block; vertical-align: top; height: 0.5in; width: 2in; background: fuchsia"></div>
</div>
<div style="page-break-before: always">
<!-- FIXME: uncomment this when bug 511551 is fixed
<div style="display: inline-block; vertical-align: top; height: 0.25in; width: 1in"></div
>--><div style="display: inline-block; vertical-align: top; height: 0.25in; width: 2in; background: fuchsia"></div>
</div>

View File

@ -0,0 +1,9 @@
<!DOCTYPE HTML>
<html class="reftest-print">
<title>Testcase for float breaking</title>
<body style="margin: 0">
<div style="float: left; width: 3.5in; height: 0.5in; background: blue"></div>
<div style="float: left; width: 1in; height: 1in; background: aqua"></div>
<!-- test to see where this float goes -->
<div style="float: left; width: 2in; height: 1.75in; background: fuchsia"></div>

View File

@ -1442,6 +1442,8 @@ random-if(!haveTestPlugin) == 546071-1.html 546071-1-ref.html
== 561981-8.html 561981-8-ref.html
== 562835-1.html 562835-ref.html
== 562835-2.html 562835-ref.html
== 563584-6-columns.html 563584-6-columns-ref.html
== 563584-6-printing.html 563584-6-printing-ref.html
== 564054-1.html 564054-1-ref.html
== 564991-1.html 564991-1-ref.html
== 565819-1.html 565819-ref.html