Fix bug 25888 for inline frames other than bullets: redo line reflow when the line's height pushes it into the way of other floats. (Bug 25888) r+sr=roc

This commit is contained in:
L. David Baron 2009-05-20 07:21:34 -04:00
parent bedec9616e
commit 7c71744210
20 changed files with 282 additions and 63 deletions

View File

@ -0,0 +1,6 @@
<title>Hang while developing patch for bug 25888</title>
<div style="width:500px">
<div style="float:left;width:600px;height:30px"></div>
Hello
</div>

View File

@ -0,0 +1,8 @@
<!DOCTYPE HTML>
<title>Testcase for hang while developing bug 25888 (hit on www.flightaware.com)</title>
<div style="border: solid 1em; width: 500px; height: 500px">
<div style="float:right; width: 300px; height: 3px;background:yellow;"></div>
<div style="float:left; width: 220px; height: 100px;background:aqua;"></div>
hi
</div>

View File

@ -1,3 +1,5 @@
load 25888-1.html
load 25888-2.html
load 37757-1.html load 37757-1.html
load 225868-1.html load 225868-1.html
load 264937-1.html load 264937-1.html

View File

@ -783,6 +783,20 @@ nsBlockFrame::ComputeTightBounds(gfxContext* aContext) const
return ComputeSimpleTightBounds(aContext); return ComputeSimpleTightBounds(aContext);
} }
static PRBool
AvailableSpaceShrunk(const nsRect& aOldAvailableSpace,
const nsRect& aNewAvailableSpace)
{
if (aNewAvailableSpace.width == 0) {
// Positions are not significant if the width is zero.
return aOldAvailableSpace.width != 0;
}
NS_ASSERTION(aOldAvailableSpace.x <= aNewAvailableSpace.x &&
aOldAvailableSpace.XMost() >= aNewAvailableSpace.XMost(),
"available space should never grow");
return aOldAvailableSpace.width != aNewAvailableSpace.width;
}
static nsSize static nsSize
CalculateContainingBlockSizeForAbsolutes(const nsHTMLReflowState& aReflowState, CalculateContainingBlockSizeForAbsolutes(const nsHTMLReflowState& aReflowState,
nsSize aFrameSize) nsSize aFrameSize)
@ -1663,11 +1677,11 @@ nsBlockFrame::PropagateFloatDamage(nsBlockReflowState& aState,
// decide what it needs to reflow. // decide what it needs to reflow.
aLine->MarkDirty(); aLine->MarkDirty();
} else { } else {
// Note that this check will become incorrect once bug 25888 is fixed
// because we are only checking the top of the line
PRBool wasImpactedByFloat = aLine->IsImpactedByFloat(); PRBool wasImpactedByFloat = aLine->IsImpactedByFloat();
nsFlowAreaRect floatAvailableSpace = nsFlowAreaRect floatAvailableSpace =
aState.GetFloatAvailableSpace(aLine->mBounds.y + aDeltaY, PR_FALSE); aState.GetFloatAvailableSpaceForHeight(aLine->mBounds.y + aDeltaY,
aLine->mBounds.height,
nsnull);
#ifdef REALLY_NOISY_REFLOW #ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::PropagateFloatDamage %p was = %d, is=%d\n", printf("nsBlockFrame::PropagateFloatDamage %p was = %d, is=%d\n",
@ -3320,11 +3334,19 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
nsresult rv = NS_OK; nsresult rv = NS_OK;
*aKeepReflowGoing = PR_TRUE; *aKeepReflowGoing = PR_TRUE;
aLine->SetLineIsImpactedByFloat(PR_FALSE);
// Setup initial coordinate system for reflowing the inline frames
// into. Apply a previous block frame's bottom margin first.
if (ShouldApplyTopMargin(aState, aLine)) {
aState.mY += aState.mPrevBottomMargin.get();
}
nsFlowAreaRect floatAvailableSpace = aState.GetFloatAvailableSpace();
#ifdef DEBUG #ifdef DEBUG
PRInt32 spins = 0; PRInt32 spins = 0;
#endif #endif
LineReflowStatus lineReflowStatus = LINE_REFLOW_REDO_NEXT_BAND; LineReflowStatus lineReflowStatus = LINE_REFLOW_REDO_NEXT_BAND;
PRBool movedPastFloat = PR_FALSE;
do { do {
PRBool allowPullUp = PR_TRUE; PRBool allowPullUp = PR_TRUE;
nsIContent* forceBreakInContent = nsnull; nsIContent* forceBreakInContent = nsnull;
@ -3349,11 +3371,13 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
lineLayout.ForceBreakAtPosition(forceBreakInContent, forceBreakOffset); lineLayout.ForceBreakAtPosition(forceBreakInContent, forceBreakOffset);
} }
rv = DoReflowInlineFrames(aState, lineLayout, aLine, rv = DoReflowInlineFrames(aState, lineLayout, aLine,
floatAvailableSpace, &floatManagerState,
aKeepReflowGoing, &lineReflowStatus, aKeepReflowGoing, &lineReflowStatus,
allowPullUp); allowPullUp);
lineLayout.EndLineReflow(); lineLayout.EndLineReflow();
if (LINE_REFLOW_REDO_NO_PULL == lineReflowStatus || if (LINE_REFLOW_REDO_NO_PULL == lineReflowStatus ||
LINE_REFLOW_REDO_MORE_FLOATS == lineReflowStatus ||
LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus) { LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus) {
if (lineLayout.NeedsBackup()) { if (lineLayout.NeedsBackup()) {
NS_ASSERTION(!forceBreakInContent, "Backing up twice; this should never be necessary"); NS_ASSERTION(!forceBreakInContent, "Backing up twice; this should never be necessary");
@ -3383,17 +3407,9 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
// Don't allow pullup on a subsequent LINE_REFLOW_REDO_NO_PULL pass // Don't allow pullup on a subsequent LINE_REFLOW_REDO_NO_PULL pass
allowPullUp = PR_FALSE; allowPullUp = PR_FALSE;
} while (NS_SUCCEEDED(rv) && LINE_REFLOW_REDO_NO_PULL == lineReflowStatus); } while (NS_SUCCEEDED(rv) && LINE_REFLOW_REDO_NO_PULL == lineReflowStatus);
} while (NS_SUCCEEDED(rv) &&
if (LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus) { (LINE_REFLOW_REDO_MORE_FLOATS == lineReflowStatus ||
movedPastFloat = PR_TRUE; LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus));
}
} while (NS_SUCCEEDED(rv) && LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus);
// If we did at least one REDO_FOR_FLOAT, then the line did not fit next to some float.
// Mark it as impacted by a float, even if it no longer is next to a float.
if (movedPastFloat) {
aLine->SetLineIsImpactedByFloat(PR_TRUE);
}
return rv; return rv;
} }
@ -3417,6 +3433,7 @@ nsBlockFrame::PushTruncatedPlaceholderLine(nsBlockReflowState& aState,
#ifdef DEBUG #ifdef DEBUG
static const char* LineReflowStatusNames[] = { static const char* LineReflowStatusNames[] = {
"LINE_REFLOW_OK", "LINE_REFLOW_STOP", "LINE_REFLOW_REDO_NO_PULL", "LINE_REFLOW_OK", "LINE_REFLOW_STOP", "LINE_REFLOW_REDO_NO_PULL",
"LINE_REFLOW_REDO_MORE_FLOATS",
"LINE_REFLOW_REDO_NEXT_BAND", "LINE_REFLOW_TRUNCATED" "LINE_REFLOW_REDO_NEXT_BAND", "LINE_REFLOW_TRUNCATED"
}; };
#endif #endif
@ -3425,6 +3442,9 @@ nsresult
nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
nsLineLayout& aLineLayout, nsLineLayout& aLineLayout,
line_iterator aLine, line_iterator aLine,
nsFlowAreaRect& aFloatAvailableSpace,
nsFloatManager::SavedState*
aFloatStateBeforeLine,
PRBool* aKeepReflowGoing, PRBool* aKeepReflowGoing,
LineReflowStatus* aLineReflowStatus, LineReflowStatus* aLineReflowStatus,
PRBool aAllowPullUp) PRBool aAllowPullUp)
@ -3433,28 +3453,25 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
aLine->FreeFloats(aState.mFloatCacheFreeList); aLine->FreeFloats(aState.mFloatCacheFreeList);
aState.mFloatCombinedArea.SetRect(0, 0, 0, 0); aState.mFloatCombinedArea.SetRect(0, 0, 0, 0);
// Setup initial coordinate system for reflowing the inline frames // We need to set this flag on the line if any of our reflow passes
// into. Apply a previous block frame's bottom margin first. // are impacted by floats.
if (ShouldApplyTopMargin(aState, aLine)) { if (aFloatAvailableSpace.mHasFloats)
aState.mY += aState.mPrevBottomMargin.get(); aLine->SetLineIsImpactedByFloat(PR_TRUE);
}
nsFlowAreaRect floatAvailableSpace = aState.GetFloatAvailableSpace();
aLine->SetLineIsImpactedByFloat(floatAvailableSpace.mHasFloats);
#ifdef REALLY_NOISY_REFLOW #ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n", printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n",
this, floatAvailableSpace.mHasFloats); this, aFloatAvailableSpace.mHasFloats);
#endif #endif
const nsMargin& borderPadding = aState.BorderPadding(); const nsMargin& borderPadding = aState.BorderPadding();
nscoord x = floatAvailableSpace.mRect.x + borderPadding.left; nscoord x = aFloatAvailableSpace.mRect.x + borderPadding.left;
nscoord availWidth = floatAvailableSpace.mRect.width; nscoord availWidth = aFloatAvailableSpace.mRect.width;
nscoord availHeight; nscoord availHeight;
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) { if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
availHeight = NS_UNCONSTRAINEDSIZE; availHeight = NS_UNCONSTRAINEDSIZE;
} }
else { else {
/* XXX get the height right! */ /* XXX get the height right! */
availHeight = floatAvailableSpace.mRect.height; availHeight = aFloatAvailableSpace.mRect.height;
} }
// Make sure to enable resize optimization before we call BeginLineReflow // Make sure to enable resize optimization before we call BeginLineReflow
@ -3463,7 +3480,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
aLineLayout.BeginLineReflow(x, aState.mY, aLineLayout.BeginLineReflow(x, aState.mY,
availWidth, availHeight, availWidth, availHeight,
floatAvailableSpace.mHasFloats, aFloatAvailableSpace.mHasFloats,
PR_FALSE /*XXX isTopOfPage*/); PR_FALSE /*XXX isTopOfPage*/);
aState.SetFlag(BRS_LINE_LAYOUT_EMPTY, PR_FALSE); aState.SetFlag(BRS_LINE_LAYOUT_EMPTY, PR_FALSE);
@ -3486,7 +3503,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// continuations // continuations
PRBool isContinuingPlaceholders = PR_FALSE; PRBool isContinuingPlaceholders = PR_FALSE;
if (floatAvailableSpace.mHasFloats) { if (aFloatAvailableSpace.mHasFloats) {
// There is a soft break opportunity at the start of the line, because // There is a soft break opportunity at the start of the line, because
// we can always move this line down below float(s). // we can always move this line down below float(s).
if (aLineLayout.NotifyOptionalBreakPosition(frame->GetContent(), 0, PR_TRUE, eNormalBreak)) { if (aLineLayout.NotifyOptionalBreakPosition(frame->GetContent(), 0, PR_TRUE, eNormalBreak)) {
@ -3591,20 +3608,32 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// //
// What we do is to advance past the first float we find and // What we do is to advance past the first float we find and
// then reflow the line all over again. // then reflow the line all over again.
NS_ASSERTION(NS_UNCONSTRAINEDSIZE != floatAvailableSpace.mRect.height, NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aFloatAvailableSpace.mRect.height,
"unconstrained height on totally empty line"); "unconstrained height on totally empty line");
// See the analogous code for blocks in nsBlockReflowState::ClearFloats. // See the analogous code for blocks in nsBlockReflowState::ClearFloats.
if (floatAvailableSpace.mRect.height > 0) { if (aFloatAvailableSpace.mRect.height > 0) {
NS_ASSERTION(floatAvailableSpace.mHasFloats, NS_ASSERTION(aFloatAvailableSpace.mHasFloats,
"redo line on totally empty line with non-empty band..."); "redo line on totally empty line with non-empty band...");
aState.mY += floatAvailableSpace.mRect.height; // We should never hit this case if we've placed floats on the
// line; if we have, then the GetFloatAvailableSpace call is wrong
// and needs to happen after the caller pops the space manager
// state.
aState.mFloatManager->AssertStateMatches(aFloatStateBeforeLine);
aState.mY += aFloatAvailableSpace.mRect.height;
aFloatAvailableSpace = aState.GetFloatAvailableSpace();
} else { } else {
NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableHeight, NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableHeight,
"We shouldn't be running out of height here"); "We shouldn't be running out of height here");
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableHeight) { if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableHeight) {
// just move it down a bit to try to get out of this mess // just move it down a bit to try to get out of this mess
aState.mY += 1; aState.mY += 1;
// We should never hit this case if we've placed floats on the
// line; if we have, then the GetFloatAvailableSpace call is wrong
// and needs to happen after the caller pops the space manager
// state.
aState.mFloatManager->AssertStateMatches(aFloatStateBeforeLine);
aFloatAvailableSpace = aState.GetFloatAvailableSpace();
} else { } else {
// There's nowhere to retry placing the line. Just treat it as if // There's nowhere to retry placing the line. Just treat it as if
// we placed the float but it was truncated so we need this line // we placed the float but it was truncated so we need this line
@ -3614,30 +3643,22 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
PushTruncatedPlaceholderLine(aState, aLine, *aKeepReflowGoing); PushTruncatedPlaceholderLine(aState, aLine, *aKeepReflowGoing);
} }
} }
// We don't want to advance by the bottom margin anymore (we did it
// once at the beginning of this function, which will just be called
// again), and we certainly don't want to go back if it's negative
// (infinite loop, bug 153429).
aState.mPrevBottomMargin.Zero();
// XXX: a small optimization can be done here when paginating: // XXX: a small optimization can be done here when paginating:
// if the new Y coordinate is past the end of the block then // if the new Y coordinate is past the end of the block then
// push the line and return now instead of later on after we are // push the line and return now instead of later on after we are
// past the float. // past the float.
} }
else if (LINE_REFLOW_REDO_NO_PULL == lineReflowStatus) { else if (LINE_REFLOW_TRUNCATED != lineReflowStatus &&
// We don't want to advance by the bottom margin anymore (we did it LINE_REFLOW_REDO_NO_PULL != lineReflowStatus) {
// once at the beginning of this function, which will just be called
// again), and we certainly don't want to go back if it's negative
// (infinite loop, bug 153429).
aState.mPrevBottomMargin.Zero();
}
else if (LINE_REFLOW_TRUNCATED != lineReflowStatus) {
// If we are propagating out a break-before status then there is // If we are propagating out a break-before status then there is
// no point in placing the line. // no point in placing the line.
if (!NS_INLINE_IS_BREAK_BEFORE(aState.mReflowStatus)) { if (!NS_INLINE_IS_BREAK_BEFORE(aState.mReflowStatus)) {
PlaceLine(aState, aLineLayout, aLine, aKeepReflowGoing); if (!PlaceLine(aState, aLineLayout, aLine, aFloatStateBeforeLine,
aFloatAvailableSpace.mRect, aKeepReflowGoing)) {
lineReflowStatus = LINE_REFLOW_REDO_MORE_FLOATS;
// PlaceLine already called GetAvailableSpaceForHeight for us.
}
} }
} }
#ifdef DEBUG #ifdef DEBUG
@ -4017,10 +4038,12 @@ nsBlockFrame::ShouldJustifyLine(nsBlockReflowState& aState,
return PR_FALSE; return PR_FALSE;
} }
void PRBool
nsBlockFrame::PlaceLine(nsBlockReflowState& aState, nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
nsLineLayout& aLineLayout, nsLineLayout& aLineLayout,
line_iterator aLine, line_iterator aLine,
nsFloatManager::SavedState *aFloatStateBeforeLine,
nsRect& aFloatAvailableSpace,
PRBool* aKeepReflowGoing) PRBool* aKeepReflowGoing)
{ {
// Trim extra white-space from the line before placing the frames // Trim extra white-space from the line before placing the frames
@ -4049,6 +4072,26 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
} }
aLineLayout.VerticalAlignLine(); aLineLayout.VerticalAlignLine();
// We want to compare to the available space that we would have had in
// the line's height *before* we placed any floats in the line itself.
// Floats that are in the line are handled during line reflow (and may
// result in floats being pushed to below the line or (I HOPE???) in a
// reflow with a forced break position).
nsRect oldFloatAvailableSpace(aFloatAvailableSpace);
aFloatAvailableSpace =
aState.GetFloatAvailableSpaceForHeight(aLine->mBounds.y,
aLine->mBounds.height,
aFloatStateBeforeLine).mRect;
NS_ASSERTION(aFloatAvailableSpace.y == oldFloatAvailableSpace.y, "yikes");
// Restore the height to the position of the next band.
aFloatAvailableSpace.height = oldFloatAvailableSpace.height;
// If the available space between the floats is smaller now that we
// know the height, return false (and cause another pass with
// LINE_REFLOW_REDO_MORE_FLOATS).
if (AvailableSpaceShrunk(oldFloatAvailableSpace, aFloatAvailableSpace)) {
return PR_FALSE;
}
#ifdef DEBUG #ifdef DEBUG
{ {
static nscoord lastHeight = 0; static nscoord lastHeight = 0;
@ -4143,7 +4186,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus); NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
*aKeepReflowGoing = PR_FALSE; *aKeepReflowGoing = PR_FALSE;
} }
return; return PR_TRUE;
} }
// May be needed below // May be needed below
@ -4200,6 +4243,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
if (aLine->HasFloatBreakAfter()) { if (aLine->HasFloatBreakAfter()) {
aState.mY = aState.ClearFloats(aState.mY, aLine->GetBreakTypeAfter()); aState.mY = aState.ClearFloats(aState.mY, aLine->GetBreakTypeAfter());
} }
return PR_TRUE;
} }
void void

View File

@ -50,6 +50,7 @@
#include "nsLineBox.h" #include "nsLineBox.h"
#include "nsCSSPseudoElements.h" #include "nsCSSPseudoElements.h"
#include "nsStyleSet.h" #include "nsStyleSet.h"
#include "nsFloatManager.h"
enum LineReflowStatus { enum LineReflowStatus {
// The line was completely reflowed and fit in available width, and we should // The line was completely reflowed and fit in available width, and we should
@ -61,6 +62,10 @@ enum LineReflowStatus {
// We need to reflow the line again at its current vertical position. The // We need to reflow the line again at its current vertical position. The
// new reflow should not try to pull up any frames from the next line. // new reflow should not try to pull up any frames from the next line.
LINE_REFLOW_REDO_NO_PULL, LINE_REFLOW_REDO_NO_PULL,
// We need to reflow the line again using the floats from its height
// this reflow, since its height made it hit floats that were not
// adjacent to its top.
LINE_REFLOW_REDO_MORE_FLOATS,
// We need to reflow the line again at a lower vertical postion where there // We need to reflow the line again at a lower vertical postion where there
// may be more horizontal space due to different float configuration. // may be more horizontal space due to different float configuration.
LINE_REFLOW_REDO_NEXT_BAND, LINE_REFLOW_REDO_NEXT_BAND,
@ -479,11 +484,15 @@ protected:
line_iterator aLine, line_iterator aLine,
PRBool* aKeepReflowGoing); PRBool* aKeepReflowGoing);
// Return PR_TRUE if aLine gets pushed. // Return false if it needs another reflow because of reduced space
void PlaceLine(nsBlockReflowState& aState, // between floats that are next to it (but not next to its top), and
nsLineLayout& aLineLayout, // return true otherwise.
line_iterator aLine, PRBool PlaceLine(nsBlockReflowState& aState,
PRBool* aKeepReflowGoing); nsLineLayout& aLineLayout,
line_iterator aLine,
nsFloatManager::SavedState* aFloatStateBeforeLine,
nsRect& aFloatAvailableSpace, /* in-out */
PRBool* aKeepReflowGoing);
/** /**
* Mark |aLine| dirty, and, if necessary because of possible * Mark |aLine| dirty, and, if necessary because of possible
@ -522,6 +531,9 @@ protected:
nsresult DoReflowInlineFrames(nsBlockReflowState& aState, nsresult DoReflowInlineFrames(nsBlockReflowState& aState,
nsLineLayout& aLineLayout, nsLineLayout& aLineLayout,
line_iterator aLine, line_iterator aLine,
nsFlowAreaRect& aFloatAvailableSpace,
nsFloatManager::SavedState*
aFloatStateBeforeLine,
PRBool* aKeepReflowGoing, PRBool* aKeepReflowGoing,
LineReflowStatus* aLineReflowStatus, LineReflowStatus* aLineReflowStatus,
PRBool aAllowPullUp); PRBool aAllowPullUp);

View File

@ -366,6 +366,38 @@ nsBlockReflowState::GetFloatAvailableSpaceWithState(
return result; return result;
} }
nsFlowAreaRect
nsBlockReflowState::GetFloatAvailableSpaceForHeight(
nscoord aY, nscoord aHeight,
nsFloatManager::SavedState *aState) const
{
#ifdef DEBUG
// Verify that the caller setup the coordinate system properly
nscoord wx, wy;
mFloatManager->GetTranslation(wx, wy);
NS_ASSERTION((wx == mFloatManagerX) && (wy == mFloatManagerY),
"bad coord system");
#endif
nsFlowAreaRect result =
mFloatManager->GetFlowArea(aY - BorderPadding().top,
nsFloatManager::WIDTH_WITHIN_HEIGHT,
aHeight, mContentArea.width, aState);
// Keep the width >= 0 for compatibility with nsSpaceManager.
if (result.mRect.width < 0)
result.mRect.width = 0;
#ifdef DEBUG
if (nsBlockFrame::gNoisyReflow) {
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
printf("GetAvailableSpaceForHeight: space=%d,%d,%d,%d hasfloats=%d\n",
result.mRect.x, result.mRect.y, result.mRect.width,
result.mRect.height, result.mHasFloats);
}
#endif
return result;
}
/* /*
* Reconstruct the vertical margin before the line |aLine| in order to * Reconstruct the vertical margin before the line |aLine| in order to
* do an incremental reflow that begins with |aLine| without reflowing * do an incremental reflow that begins with |aLine| without reflowing

View File

@ -100,6 +100,9 @@ public:
nsFlowAreaRect nsFlowAreaRect
GetFloatAvailableSpaceWithState(nscoord aY, PRBool aRelaxHeightConstraint, GetFloatAvailableSpaceWithState(nscoord aY, PRBool aRelaxHeightConstraint,
nsFloatManager::SavedState *aState) const; nsFloatManager::SavedState *aState) const;
nsFlowAreaRect
GetFloatAvailableSpaceForHeight(nscoord aY, nscoord aHeight,
nsFloatManager::SavedState *aState) const;
/* /*
* The following functions all return PR_TRUE if they were able to * The following functions all return PR_TRUE if they were able to

View File

@ -227,6 +227,13 @@ public:
*/ */
nscoord ClearFloats(nscoord aY, PRUint8 aBreakType) const; nscoord ClearFloats(nscoord aY, PRUint8 aBreakType) const;
void AssertStateMatches(SavedState *aState) const
{
NS_ASSERTION(aState->mX == mX && aState->mY == mY &&
aState->mFloatInfoCount == mFloats.Length(),
"float manager state should match saved state");
}
#ifdef DEBUG #ifdef DEBUG
/** /**
* Dump the state of the float manager out to a file. * Dump the state of the float manager out to a file.

View File

@ -36,14 +36,14 @@
== 23604-1.html 23604-1-ref.html == 23604-1.html 23604-1-ref.html
== 23604-2.html 23604-2-ref.html == 23604-2.html 23604-2-ref.html
!= 24998-1.html 24998-1-ref.html != 24998-1.html 24998-1-ref.html
fails == 25888-1l.html 25888-1l-ref.html # bug 25888 == 25888-1l.html 25888-1l-ref.html
fails != 25888-1l.html 25888-1l-notref.html # bug 25888 != 25888-1l.html 25888-1l-notref.html
fails == 25888-1r.html 25888-1r-ref.html # bug 25888 == 25888-1r.html 25888-1r-ref.html
fails != 25888-1r.html 25888-1r-notref.html # bug 25888 != 25888-1r.html 25888-1r-notref.html
fails == 25888-2l.html 25888-2l-ref.html # bug 25888 == 25888-2l.html 25888-2l-ref.html
fails == 25888-2r.html 25888-2r-ref.html # bug 25888 == 25888-2r.html 25888-2r-ref.html
fails == 25888-3l.html 25888-3l-ref.html # bug 25888 == 25888-3l.html 25888-3l-ref.html
fails == 25888-3r.html 25888-3r-ref.html # bug 25888 == 25888-3r.html 25888-3r-ref.html
== 28811-1a.html 28811-1-ref.html == 28811-1a.html 28811-1-ref.html
== 28811-1b.html 28811-1-ref.html == 28811-1b.html 28811-1-ref.html
== 28811-2a.html 28811-2-ref.html == 28811-2a.html 28811-2-ref.html

View File

@ -0,0 +1,9 @@
<title>Ambiguous line width</title>
<div style="background: yellow; width: 10em; height: 10em; position: absolute">
<div style="position: absolute; top: 0; left: 0; height: 0.5em; width: 1em; background: blue"></div>
<div style="position: absolute; top: 0.5em; left: 0; height: 2em; width: 10em; background: aqua"></div>
<span style="position: absolute; top: 2.5em; left: 0; height: 1em; width: 4em; background: maroon;"></span>
</div>

View File

@ -0,0 +1,9 @@
<title>Ambiguous line width</title>
<div style="background: yellow; width: 10em; height: 10em; line-height: 1; font-family: sans-serif;">
<div style="float: left; height: 0.5em; width: 1em; background: blue"></div>
<div style="float: left; height: 2em; width: 10em; background: aqua"></div>
<span style="display:inline-block; height: 1em; width: 4em; background: maroon; vertical-align: bottom"></span>
</div>

View File

@ -0,0 +1,10 @@
<title>Ambiguous line width</title>
<div style="background: yellow; width: 10em; height: 10em; position: relative">
<div style="position: absolute; top: 0; left: 0; height: 2em; width: 1em; background: blue"></div>
<div style="position: absolute; top: 2em; left: 0; height: 2em; width: 5em; background: aqua"></div>
<span style="position: absolute; top: 0; left: 1em; height: 1em; width: 4em; background: maroon; vertical-align: bottom"></span>
<span style="position: absolute; top: 1em; left: 5em; height: 3em; width: 4em; background: maroon; vertical-align: bottom"></span>
</div>

View File

@ -0,0 +1,12 @@
<title>Ambiguous line width</title>
<div style="background: yellow; width: 10em; height: 10em; line-height: 1; font-family: sans-serif;">
<div style="float: left; height: 2em; width: 1em; background: blue"></div>
<div style="float: left; clear: left; height: 2em; width: 5em; background: aqua"></div>
<!-- small <span style="font-size: 3em">big</span> -->
<span style="display:inline-block; height: 1em; width: 4em; background: maroon; vertical-align: bottom"></span>
<span style="display:inline-block; height: 3em; width: 4em; background: maroon; vertical-align: bottom"></span>
</div>

View File

@ -0,0 +1,10 @@
<title>Ambiguous line width</title>
<div style="background: yellow; width: 10em; height: 10em; position: relative">
<div style="position: absolute; top: 0; left: 0; height: 2em; width: 1em; background: blue"></div>
<div style="position: absolute; top: 2em; left: 0; height: 2em; width: 5em; background: aqua"></div>
<span style="position: absolute; top: 0; left: 1em; height: 1em; width: 4em; background: maroon; vertical-align: bottom"></span>
<span style="position: absolute; top: 4em; left: 0; height: 3em; width: 6em; background: maroon; vertical-align: bottom"></span>
</div>

View File

@ -0,0 +1,10 @@
<title>Ambiguous line width</title>
<div style="background: yellow; width: 10em; height: 10em; line-height: 1; font-family: sans-serif;">
<div style="float: left; height: 2em; width: 1em; background: blue"></div>
<div style="float: left; clear: left; height: 2em; width: 5em; background: aqua"></div>
<span style="display:inline-block; height: 1em; width: 4em; background: maroon; vertical-align: bottom"></span>
<span style="display:inline-block; height: 3em; width: 6em; background: maroon; vertical-align: bottom"></span>
</div>

View File

@ -0,0 +1,10 @@
<title>Ambiguous line width</title>
<div style="background: yellow; width: 10em; height: 10em; position: relative">
<div style="position: absolute; top: 0; left: 0; height: 2em; width: 2em; background: blue"></div>
<div style="position: absolute; top: 2em; left: 0; height: 2em; width: 5em; background: aqua"></div>
<span style="position: absolute; top: 0; left: 2em; height: 1em; width: 3em; background: maroon; vertical-align: bottom"></span>
<span style="position: absolute; top: 1em; left: 5em; height: 3em; width: 5em; background: maroon; vertical-align: bottom"></span>
</div>

View File

@ -0,0 +1,10 @@
<title>Ambiguous line width</title>
<div style="background: yellow; width: 10em; height: 10em; line-height: 1; font-family: sans-serif;">
<div style="float: left; height: 2em; width: 2em; background: blue"></div>
<div style="float: left; clear: left; height: 2em; width: 5em; background: aqua"></div>
<span style="display:inline-block; height: 1em; width: 3em; background: maroon; vertical-align: bottom"></span>
<span style="display:inline-block; height: 3em; width: 5em; background: maroon; vertical-align: bottom"></span>
</div>

View File

@ -0,0 +1,10 @@
<title>Ambiguous line width</title>
<div style="background: yellow; width: 10em; height: 10em; position: relative">
<div style="position: absolute; top: 0; left: 0; height: 2em; width: 2em; background: blue"></div>
<div style="position: absolute; top: 2em; left: 0; height: 2em; width: 5em; background: aqua"></div>
<span style="position: absolute; top: 0; left: 2em; height: 1em; width: 2em; background: maroon; vertical-align: bottom"></span>
<span style="position: absolute; top: 4em; left: 0; height: 3em; width: 6em; background: maroon; vertical-align: bottom"></span>
</div>

View File

@ -0,0 +1,10 @@
<title>Ambiguous line width</title>
<div style="background: yellow; width: 10em; height: 10em; line-height: 1; font-family: sans-serif;">
<div style="float: left; height: 2em; width: 2em; background: blue"></div>
<div style="float: left; clear: left; height: 2em; width: 5em; background: aqua"></div>
<span style="display:inline-block; height: 1em; width: 2em; background: maroon; vertical-align: bottom"></span>
<span style="display:inline-block; height: 3em; width: 6em; background: maroon; vertical-align: bottom"></span>
</div>

View File

@ -7,5 +7,10 @@ fails == other-float-outside-rule-3-right-2.html other-float-outside-rule-3-righ
fails == other-float-outside-rule-7-left.html other-float-outside-rule-7-left-ref.html fails == other-float-outside-rule-7-left.html other-float-outside-rule-7-left-ref.html
fails == other-float-outside-rule-7-right.html other-float-outside-rule-7-right-ref.html fails == other-float-outside-rule-7-right.html other-float-outside-rule-7-right-ref.html
== float-outside-block-push.html float-outside-block-push-ref.html == float-outside-block-push.html float-outside-block-push-ref.html
fails == zero-height-float-base.html zero-height-float-ref.html == zero-height-float-base.html zero-height-float-ref.html
fails == zero-height-float.html zero-height-float-ref.html fails == zero-height-float.html zero-height-float-ref.html
fails == 345369-1.html 345369-1-ref.html
fails == 345369-2.html 345369-2-ref.html
== 345369-3.html 345369-3-ref.html
== 345369-4.html 345369-4-ref.html
== 345369-5.html 345369-5-ref.html