From 0000423887c682d578f2743ab8cca688bf1955ce Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Wed, 8 Apr 2009 13:52:37 -0700 Subject: [PATCH] Use a struct containing a rectangle and a boolean for float available space rather than passing them around separately. (Bug 25888) r+sr=roc --- layout/generic/nsBlockFrame.cpp | 55 +++++------ layout/generic/nsBlockReflowState.cpp | 129 +++++++++++++------------- layout/generic/nsBlockReflowState.h | 24 +++-- layout/generic/nsFloatManager.cpp | 11 +-- layout/generic/nsFloatManager.h | 34 +++++-- 5 files changed, 127 insertions(+), 126 deletions(-) diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index a804a26c0278..86c97e862204 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -1658,20 +1658,18 @@ nsBlockFrame::PropagateFloatDamage(nsBlockReflowState& aState, // 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(); - nsRect floatAvailableSpace; - PRBool isImpactedByFloat = - aState.GetFloatAvailableSpace(aLine->mBounds.y + aDeltaY, PR_FALSE, - floatAvailableSpace); + nsFlowAreaRect floatAvailableSpace = + aState.GetFloatAvailableSpace(aLine->mBounds.y + aDeltaY, PR_FALSE); #ifdef REALLY_NOISY_REFLOW printf("nsBlockFrame::PropagateFloatDamage %p was = %d, is=%d\n", - this, wasImpactedByFloat, isImpactedByFloat); + this, wasImpactedByFloat, floatAvailableSpace.mHasFloats); #endif // Mark the line dirty if it was or is affected by a float // We actually only really need to reflow if the amount of impact // changes, but that's not straightforward to check - if (wasImpactedByFloat || isImpactedByFloat) { + if (wasImpactedByFloat || floatAvailableSpace.mHasFloats) { aLine->MarkDirty(); } } @@ -2953,16 +2951,14 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState, // Here aState.mY is the top border-edge of the block. // Compute the available space for the block - nsRect floatAvailableSpace; - PRBool isImpacted = aState.GetFloatAvailableSpace(floatAvailableSpace); + nsFlowAreaRect floatAvailableSpace = aState.GetFloatAvailableSpace(); #ifdef REALLY_NOISY_REFLOW printf("setting line %p isImpacted to %s\n", - aLine.get(), isImpacted?"true":"false"); + aLine.get(), floatAvailableSpace.mHasFloats?"true":"false"); #endif - aLine->SetLineIsImpactedByFloat(isImpacted); + aLine->SetLineIsImpactedByFloat(floatAvailableSpace.mHasFloats); nsRect availSpace; - aState.ComputeBlockAvailSpace(frame, display, - isImpacted, floatAvailableSpace, + aState.ComputeBlockAvailSpace(frame, display, floatAvailableSpace, replacedBlock != nsnull, availSpace); // Now put the Y coordinate back to the top of the top-margin + @@ -3043,7 +3039,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState, // then pushing it to the next page would give it more room. Note that // isImpacted doesn't include impact from the block's own floats. PRBool forceFit = aState.IsAdjacentWithTop() && clearance <= 0 && - !isImpacted; + !floatAvailableSpace.mHasFloats; nsCollapsingMargin collapsedBottomMargin; nsRect combinedArea(0,0,0,0); *aKeepReflowGoing = brc.PlaceBlock(blockHtmlRS, forceFit, aLine.get(), @@ -3351,24 +3347,23 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, if (ShouldApplyTopMargin(aState, aLine)) { aState.mY += aState.mPrevBottomMargin.get(); } - nsRect floatAvailableSpace; - PRBool impactedByFloats = aState.GetFloatAvailableSpace(floatAvailableSpace); - aLine->SetLineIsImpactedByFloat(impactedByFloats); + nsFlowAreaRect floatAvailableSpace = aState.GetFloatAvailableSpace(); + aLine->SetLineIsImpactedByFloat(floatAvailableSpace.mHasFloats); #ifdef REALLY_NOISY_REFLOW printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n", - this, impactedByFloats); + this, floatAvailableSpace.mHasFloats); #endif const nsMargin& borderPadding = aState.BorderPadding(); - nscoord x = floatAvailableSpace.x + borderPadding.left; - nscoord availWidth = floatAvailableSpace.width; + nscoord x = floatAvailableSpace.mRect.x + borderPadding.left; + nscoord availWidth = floatAvailableSpace.mRect.width; nscoord availHeight; if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) { availHeight = NS_UNCONSTRAINEDSIZE; } else { /* XXX get the height right! */ - availHeight = floatAvailableSpace.height; + availHeight = floatAvailableSpace.mRect.height; } // Make sure to enable resize optimization before we call BeginLineReflow @@ -3377,7 +3372,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, aLineLayout.BeginLineReflow(x, aState.mY, availWidth, availHeight, - impactedByFloats, + floatAvailableSpace.mHasFloats, PR_FALSE /*XXX isTopOfPage*/); aState.SetFlag(BRS_LINE_LAYOUT_EMPTY, PR_FALSE); @@ -3400,7 +3395,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, // continuations PRBool isContinuingPlaceholders = PR_FALSE; - if (impactedByFloats) { + if (floatAvailableSpace.mHasFloats) { // There is a soft break opportunity at the start of the line, because // we can always move this line down below float(s). if (aLineLayout.NotifyOptionalBreakPosition(frame->GetContent(), 0, PR_TRUE, eNormalBreak)) { @@ -3505,14 +3500,14 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, // // What we do is to advance past the first float we find and // then reflow the line all over again. - NS_ASSERTION(NS_UNCONSTRAINEDSIZE != floatAvailableSpace.height, + NS_ASSERTION(NS_UNCONSTRAINEDSIZE != floatAvailableSpace.mRect.height, "unconstrained height on totally empty line"); // See the analogous code for blocks in nsBlockReflowState::ClearFloats. - if (floatAvailableSpace.height > 0) { - NS_ASSERTION(impactedByFloats, + if (floatAvailableSpace.mRect.height > 0) { + NS_ASSERTION(floatAvailableSpace.mHasFloats, "redo line on totally empty line with non-empty band..."); - aState.mY += floatAvailableSpace.height; + aState.mY += floatAvailableSpace.mRect.height; } else { NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableHeight, "We shouldn't be running out of height here"); @@ -6664,10 +6659,10 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, // the block. // FIXME: aLineTop isn't actually set correctly by some callers, since // they reposition the line. - nsRect floatAvailSpace; - aState.GetFloatAvailableSpaceWithState(aLineTop, PR_FALSE, - &aState.mFloatManagerStateBefore, - floatAvailSpace); + nsRect floatAvailSpace = + aState.GetFloatAvailableSpaceWithState(aLineTop, PR_FALSE, + &aState.mFloatManagerStateBefore) + .mRect; // FIXME (bug 25888): need to check the entire region that the first // line overlaps, not just the top pixel. diff --git a/layout/generic/nsBlockReflowState.cpp b/layout/generic/nsBlockReflowState.cpp index 3b0685779fb6..0d59fe1d9449 100644 --- a/layout/generic/nsBlockReflowState.cpp +++ b/layout/generic/nsBlockReflowState.cpp @@ -245,13 +245,13 @@ nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame, void nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame, const nsStyleDisplay* aDisplay, - PRBool aBandHasFloats, - const nsRect& aFloatAvailableSpace, + const nsFlowAreaRect& aFloatAvailableSpace, PRBool aBlockAvoidsFloats, nsRect& aResult) { #ifdef REALLY_NOISY_REFLOW - printf("CBAS frame=%p has floats %d\n", aFrame, aBandHasFloats); + printf("CBAS frame=%p has floats %d\n", + aFrame, aFloatAvailableSpace.mHasFloats); #endif aResult.y = mY; aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT) @@ -279,7 +279,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame, !aBlockAvoidsFloats, "unexpected replaced width"); if (!aBlockAvoidsFloats) { - if (aBandHasFloats) { + if (aFloatAvailableSpace.mHasFloats) { // Use the float-edge property to determine how the child block // will interact with the float. const nsStyleBorder* borderStyle = aFrame->GetStyleBorder(); @@ -295,8 +295,8 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame, { // The child block's margins should be placed adjacent to, // but not overlap the float. - aResult.x = aFloatAvailableSpace.x + borderPadding.left; - aResult.width = aFloatAvailableSpace.width; + aResult.x = aFloatAvailableSpace.mRect.x + borderPadding.left; + aResult.width = aFloatAvailableSpace.mRect.width; } break; } @@ -315,12 +315,12 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame, if (aFrame->GetType() == nsGkAtoms::tableOuterFrame) { replacedWidth = &replacedWidthStruct; replacedWidthStruct = - nsBlockFrame::WidthToClearPastFloats(*this, aFloatAvailableSpace, + nsBlockFrame::WidthToClearPastFloats(*this, aFloatAvailableSpace.mRect, aFrame); } nscoord leftOffset, rightOffset; - ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace, + ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace.mRect, leftOffset, rightOffset, replacedWidth); aResult.x = borderPadding.left + leftOffset; @@ -332,11 +332,10 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame, #endif } -PRBool +nsFlowAreaRect nsBlockReflowState::GetFloatAvailableSpaceWithState( nscoord aY, PRBool aRelaxHeightConstraint, - nsFloatManager::SavedState *aState, - nsRect& aResult) const + nsFloatManager::SavedState *aState) const { #ifdef DEBUG // Verify that the caller setup the coordinate system properly @@ -346,24 +345,24 @@ nsBlockReflowState::GetFloatAvailableSpaceWithState( "bad coord system"); #endif - PRBool hasFloats; - aResult = + nsFlowAreaRect result = mFloatManager->GetBand(aY - BorderPadding().top, aRelaxHeightConstraint ? nscoord_MAX : mContentArea.height, - mContentArea.width, aState, &hasFloats); + mContentArea.width, aState); // Keep the width >= 0 for compatibility with nsSpaceManager. - if (aResult.width < 0) - aResult.width = 0; + if (result.mRect.width < 0) + result.mRect.width = 0; #ifdef DEBUG if (nsBlockFrame::gNoisyReflow) { nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent); printf("GetAvailableSpace: band=%d,%d,%d,%d hasfloats=%d\n", - aResult.x, aResult.y, aResult.width, aResult.height, hasFloats); + result.mRect.x, result.mRect.y, result.mRect.width, + result.mRect.height, result.mHasFloats); } #endif - return hasFloats; + return result; } /* @@ -580,8 +579,7 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout, // If one or more floats has already been pushed to the next line, // don't let this one go on the current line, since that would violate // float ordering. - nsRect floatAvailableSpace; - GetFloatAvailableSpace(floatAvailableSpace); + nsRect floatAvailableSpace = GetFloatAvailableSpace().mRect; if (mBelowCurrentLineFloats.IsEmpty() && (aLineLayout.LineIsEmpty() || mBlock->ComputeFloatWidth(*this, floatAvailableSpace, aPlaceholder) <= @@ -596,10 +594,11 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout, "If we asked for force-fit, it should have been placed"); if (forceFit || (placed && !NS_FRAME_IS_TRUNCATED(aReflowStatus))) { // Pass on updated available space to the current inline reflow engine - nsRect floatAvailSpace; - GetFloatAvailableSpace(mY, forceFit, floatAvailSpace); - nsRect availSpace(nsPoint(floatAvailSpace.x + BorderPadding().left, mY), - floatAvailSpace.Size()); + nsFlowAreaRect floatAvailSpace = + GetFloatAvailableSpace(mY, forceFit); + nsRect availSpace(nsPoint(floatAvailSpace.mRect.x + BorderPadding().left, + mY), + floatAvailSpace.mRect.Size()); aLineLayout.UpdateBand(availSpace, isLeftFloat, aPlaceholder->GetOutOfFlowFrame()); @@ -653,15 +652,15 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout, PRBool nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats, - const nsRect& aFloatAvailableSpace, - PRBool aBandHasFloats, PRBool aForceFit) + const nsFlowAreaRect& aFloatAvailableSpace, + PRBool aForceFit) { // If the current Y coordinate is not impacted by any floats // then by definition the float fits. PRBool result = PR_TRUE; - if (aBandHasFloats) { + if (aFloatAvailableSpace.mHasFloats) { // XXX We should allow overflow by up to half a pixel here (bug 21193). - if (aFloatAvailableSpace.width < aFloatSize.width) { + if (aFloatAvailableSpace.mRect.width < aFloatSize.width) { // The available width is too narrow (and its been impacted by a // prior float) result = PR_FALSE; @@ -674,7 +673,8 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats, // At this point we know that there is enough horizontal space for // the float (somewhere). Lets see if there is enough vertical // space. - if (NSCoordGreaterThan(aFloatSize.height, aFloatAvailableSpace.height)) { + if (NSCoordGreaterThan(aFloatSize.height, + aFloatAvailableSpace.mRect.height)) { // The available height is too short. However, its possible that // there is enough open space below which is not impacted by a // float. @@ -685,16 +685,16 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats, // here. nscoord xa; if (NS_STYLE_FLOAT_LEFT == aFloats) { - xa = aFloatAvailableSpace.x; + xa = aFloatAvailableSpace.mRect.x; } else { - xa = aFloatAvailableSpace.XMost() - aFloatSize.width; + xa = aFloatAvailableSpace.mRect.XMost() - aFloatSize.width; // In case the float is too big, don't go past the left edge // XXXldb This seems wrong, but we might want to fix bug 6976 // first. - if (xa < aFloatAvailableSpace.x) { - xa = aFloatAvailableSpace.x; + if (xa < aFloatAvailableSpace.mRect.x) { + xa = aFloatAvailableSpace.mRect.x; } } nscoord xb = xa + aFloatSize.width; @@ -714,22 +714,21 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats, nscoord yb = ya + aFloatSize.height; nscoord saveY = mY; - nsRect floatAvailableSpace(aFloatAvailableSpace); + nsFlowAreaRect floatAvailableSpace(aFloatAvailableSpace); for (;;) { // Get the available space at the new Y coordinate - if (floatAvailableSpace.height <= 0) { + if (floatAvailableSpace.mRect.height <= 0) { // there is no more available space. We lose. result = PR_FALSE; break; } - mY += floatAvailableSpace.height; - PRBool bandHasFloats = - GetFloatAvailableSpace(mY, aForceFit, floatAvailableSpace); + mY += floatAvailableSpace.mRect.height; + floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit); - if (bandHasFloats) { - if (xa < floatAvailableSpace.x || - xb > floatAvailableSpace.XMost()) { + if (floatAvailableSpace.mHasFloats) { + if (xa < floatAvailableSpace.mRect.x || + xb > floatAvailableSpace.mRect.XMost()) { // The float can't go here. result = PR_FALSE; break; @@ -737,7 +736,7 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats, } // See if there is now enough height for the float. - if (yb <= mY + floatAvailableSpace.height) { + if (yb <= mY + floatAvailableSpace.mRect.height) { // Winner. The bottom Y coordinate of the float is in // this band. break; @@ -786,16 +785,14 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache, mY = ClearFloats(mY, floatDisplay->mBreakType); } // Get the band of available space - nsRect floatAvailableSpace; - PRBool bandHasFloats = - GetFloatAvailableSpace(mY, aForceFit, floatAvailableSpace); + nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit); NS_ASSERTION(floatFrame->GetParent() == mBlock, "Float frame has wrong parent"); // Reflow the float nsMargin floatMargin; - mBlock->ReflowFloat(*this, floatAvailableSpace, placeholder, + mBlock->ReflowFloat(*this, floatAvailableSpace.mRect, placeholder, floatMargin, aReflowStatus); #ifdef DEBUG @@ -823,8 +820,8 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache, PRBool keepFloatOnSameLine = PR_FALSE; while (!CanPlaceFloat(floatSize, floatDisplay->mFloats, floatAvailableSpace, - bandHasFloats, aForceFit)) { - if (floatAvailableSpace.height <= 0) { + aForceFit)) { + if (floatAvailableSpace.mRect.height <= 0) { // No space, nowhere to put anything. mY = saveY; return PR_FALSE; @@ -834,9 +831,8 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache, if (NS_STYLE_DISPLAY_TABLE != floatDisplay->mDisplay || eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) { - mY += floatAvailableSpace.height; - bandHasFloats = - GetFloatAvailableSpace(mY, aForceFit, floatAvailableSpace); + mY += floatAvailableSpace.mRect.height; + floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit); } else { // This quirk matches the one in nsBlockFrame::ReflowFloat // IE handles float tables in a very special way @@ -874,14 +870,13 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache, } // the table does not fit anymore in this line so advance to next band - mY += floatAvailableSpace.height; - bandHasFloats = - GetFloatAvailableSpace(mY, aForceFit, floatAvailableSpace); + mY += floatAvailableSpace.mRect.height; + floatAvailableSpace = GetFloatAvailableSpace(mY, aForceFit); // 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, placeholder, + mBlock->ReflowFloat(*this, floatAvailableSpace.mRect, placeholder, floatMargin, aReflowStatus); // Get the floats bounding box and margin information floatSize = floatFrame->GetSize() + @@ -901,18 +896,18 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache, nscoord floatX, floatY; if (NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) { isLeftFloat = PR_TRUE; - floatX = floatAvailableSpace.x; + floatX = floatAvailableSpace.mRect.x; } else { isLeftFloat = PR_FALSE; if (!keepFloatOnSameLine) { - floatX = floatAvailableSpace.XMost() - floatSize.width; + floatX = floatAvailableSpace.mRect.XMost() - floatSize.width; } else { // this is the IE quirk (see few lines above) // the table is kept in the same line: don't let it overlap the // previous float - floatX = floatAvailableSpace.x; + floatX = floatAvailableSpace.mRect.x; } } *aIsLeftFloat = isLeftFloat; @@ -1106,25 +1101,25 @@ nsBlockReflowState::ClearFloats(nscoord aY, PRUint8 aBreakType, if (aReplacedBlock) { for (;;) { - nsRect floatAvailableSpace; - PRBool bandHasFloats = - GetFloatAvailableSpace(newY, PR_FALSE, floatAvailableSpace); + nsFlowAreaRect floatAvailableSpace = + GetFloatAvailableSpace(newY, PR_FALSE); nsBlockFrame::ReplacedElementWidthToClear replacedWidth = - nsBlockFrame::WidthToClearPastFloats(*this, floatAvailableSpace, + nsBlockFrame::WidthToClearPastFloats(*this, floatAvailableSpace.mRect, aReplacedBlock); - if (!bandHasFloats || - PR_MAX(floatAvailableSpace.x, replacedWidth.marginLeft) + + if (!floatAvailableSpace.mHasFloats || + PR_MAX(floatAvailableSpace.mRect.x, replacedWidth.marginLeft) + replacedWidth.borderBoxWidth + PR_MAX(mContentArea.width - - PR_MIN(mContentArea.width, floatAvailableSpace.XMost()), + PR_MIN(mContentArea.width, + floatAvailableSpace.mRect.XMost()), replacedWidth.marginRight) <= mContentArea.width) { break; } // See the analogous code for inlines in nsBlockFrame::DoReflowInlineFrames - if (floatAvailableSpace.height > 0) { + if (floatAvailableSpace.mRect.height > 0) { // See if there's room in the next band. - newY += floatAvailableSpace.height; + newY += floatAvailableSpace.mRect.height; } else { if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) { // Stop trying to clear here; we'll just get pushed to the diff --git a/layout/generic/nsBlockReflowState.h b/layout/generic/nsBlockReflowState.h index 828925d6834c..9d611b5faf4a 100644 --- a/layout/generic/nsBlockReflowState.h +++ b/layout/generic/nsBlockReflowState.h @@ -91,16 +91,15 @@ public: * Returns whether there are floats present at the given vertical * coordinate and within the width of the content rect. */ - PRBool GetFloatAvailableSpace(nsRect& aResult) const - { return GetFloatAvailableSpace(mY, PR_FALSE, aResult); } - PRBool GetFloatAvailableSpace(nscoord aY, PRBool aRelaxHeightConstraint, - nsRect& aResult) const + nsFlowAreaRect GetFloatAvailableSpace() const + { return GetFloatAvailableSpace(mY, PR_FALSE); } + nsFlowAreaRect GetFloatAvailableSpace(nscoord aY, + PRBool aRelaxHeightConstraint) const { return GetFloatAvailableSpaceWithState(aY, aRelaxHeightConstraint, - nsnull, aResult); } - PRBool GetFloatAvailableSpaceWithState(nscoord aY, - PRBool aRelaxHeightConstraint, - nsFloatManager::SavedState *aState, - nsRect& aResult) const; + nsnull); } + nsFlowAreaRect + GetFloatAvailableSpaceWithState(nscoord aY, PRBool aRelaxHeightConstraint, + nsFloatManager::SavedState *aState) const; /* * The following functions all return PR_TRUE if they were able to @@ -117,8 +116,8 @@ public: nscoord aAvailableWidth, nsReflowStatus& aReflowStatus); PRBool CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats, - const nsRect& aFloatAvailableSpace, - PRBool aBandHasFloats, PRBool aForceFit); + const nsFlowAreaRect& aFloatAvailableSpace, + PRBool aForceFit); PRBool FlowAndPlaceFloat(nsFloatCache* aFloatCache, PRBool* aIsLeftFloat, nsReflowStatus& aReflowStatus, @@ -172,8 +171,7 @@ public: // Caller must have called GetAvailableSpace for the current mY void ComputeBlockAvailSpace(nsIFrame* aFrame, const nsStyleDisplay* aDisplay, - PRBool aBandHasFloats, - const nsRect& aFloatAvailableSpace, + const nsFlowAreaRect& aFloatAvailableSpace, PRBool aBlockAvoidsFloats, nsRect& aResult); diff --git a/layout/generic/nsFloatManager.cpp b/layout/generic/nsFloatManager.cpp index 0d76991768c5..b4b88b1c9afe 100644 --- a/layout/generic/nsFloatManager.cpp +++ b/layout/generic/nsFloatManager.cpp @@ -135,12 +135,11 @@ void nsFloatManager::Shutdown() sCachedFloatManagerCount = -1; } -nsRect +nsFlowAreaRect nsFloatManager::GetBand(nscoord aYOffset, nscoord aMaxHeight, nscoord aContentAreaWidth, - SavedState* aState, - PRBool* aHasFloats) const + SavedState* aState) const { NS_ASSERTION(aMaxHeight >= 0, "unexpected max height"); NS_ASSERTION(aContentAreaWidth >= 0, "unexpected content area width"); @@ -167,8 +166,7 @@ nsFloatManager::GetBand(nscoord aYOffset, if (floatCount == 0 || (mFloats[floatCount-1].mLeftYMost <= top && mFloats[floatCount-1].mRightYMost <= top)) { - *aHasFloats = PR_FALSE; - return nsRect(0, aYOffset, aContentAreaWidth, aMaxHeight); + return nsFlowAreaRect(0, aYOffset, aContentAreaWidth, aMaxHeight, PR_FALSE); } nscoord bottom; @@ -241,9 +239,8 @@ nsFloatManager::GetBand(nscoord aYOffset, } } - *aHasFloats = haveFloats; nscoord height = (bottom == nscoord_MAX) ? nscoord_MAX : (bottom - top); - return nsRect(left - mX, top - mY, right - left, height); + return nsFlowAreaRect(left - mX, top - mY, right - left, height, haveFloats); } nsresult diff --git a/layout/generic/nsFloatManager.h b/layout/generic/nsFloatManager.h index 9a11616c54a7..1569dae50b33 100644 --- a/layout/generic/nsFloatManager.h +++ b/layout/generic/nsFloatManager.h @@ -52,6 +52,22 @@ class nsIFrame; struct nsHTMLReflowState; class nsPresContext; +/** + * The available space for content not occupied by floats is divided + * into a (vertical) sequence of rectangles. However, we need to know + * not only the rectangle, but also whether it was reduced (from the + * content rectangle) by floats that actually intruded into the content + * rectangle. + */ +struct nsFlowAreaRect { + nsRect mRect; + PRPackedBool mHasFloats; + + nsFlowAreaRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight, + PRBool aHasFloats) + : mRect(aX, aY, aWidth, aHeight), mHasFloats(aHasFloats) {} +}; + #define NS_FLOAT_MANAGER_CACHE_SIZE 4 class nsFloatManager { @@ -107,18 +123,18 @@ public: * @param aState [in] If null, use the current state, otherwise, do * computation based only on floats present in the given * saved state. - * @param aHasFloats [out] whether there are floats at the sides of - * the return value including those that do not - * reduce the line box width at all (because they - * are entirely in the margins) - * @return the resulting rectangle for line boxes. It will not go - * left of 0, nor right of aContentAreaWidth, but will be - * narrower when floats are present. + * @return An nsFlowAreaRect whose: + * mRect is the resulting rectangle for line boxes. It will not go + * left of 0, nor right of aContentAreaWidth, but will be + * narrower when floats are present. + * mBandHasFloats is whether there are floats at the sides of the + * return value including those that do not reduce the line box + * width at all (because they are entirely in the margins) * * aY and aAvailSpace are positioned relative to the current translation */ - nsRect GetBand(nscoord aY, nscoord aMaxHeight, nscoord aContentAreaWidth, - SavedState* aState, PRBool* aHasFloats) const; + nsFlowAreaRect GetBand(nscoord aY, nscoord aMaxHeight, + nscoord aContentAreaWidth, SavedState* aState) const; /** * Add a float that comes after all floats previously added. Its top