Bug 288560. Set mIsTopOfPage for each column in a column set. Also, make it possible to force floats to fit by relaxing the space manager's height constraint if necessary. r+sr=dbaron,a=chofmann

This commit is contained in:
roc+%cs.cmu.edu 2005-04-28 21:25:11 +00:00
Родитель 8e32ad6218
Коммит 907a58adbb
6 изменённых файлов: 54 добавлений и 37 удалений

Просмотреть файл

@ -79,10 +79,11 @@ nsBlockBandData::Init(nsSpaceManager* aSpaceManager,
// available space is relative to our coordinate system (0,0) is our
// upper left corner.
nsresult
nsBlockBandData::GetAvailableSpace(nscoord aY, nsRect& aResult)
nsBlockBandData::GetAvailableSpace(nscoord aY, PRBool aRelaxHeightConstraint,
nsRect& aResult)
{
// Get the raw band data for the given Y coordinate
nsresult rv = GetBandData(aY);
nsresult rv = GetBandData(aY, aRelaxHeightConstraint);
if (NS_FAILED(rv)) { return rv; }
// Compute the bounding rect of the available space, i.e. space
@ -104,11 +105,15 @@ nsBlockBandData::GetAvailableSpace(nscoord aY, nsRect& aResult)
* They should always call nsBlockBandData::GetBandData() instead.
*/
nsresult
nsBlockBandData::GetBandData(nscoord aY)
nsBlockBandData::GetBandData(nscoord aY, PRBool aRelaxHeightConstraint)
{
NS_ASSERTION(mSpaceManager, "bad state, no space manager");
PRInt32 iterations =0;
nsresult rv = mSpaceManager->GetBandData(aY, mSpace, *this);
nsSize space = mSpace;
if (aRelaxHeightConstraint) {
space.height = NS_UNCONSTRAINEDSIZE;
}
nsresult rv = mSpaceManager->GetBandData(aY, space, *this);
while (NS_FAILED(rv)) {
iterations++;
if (iterations>ERROR_TOO_MANY_ITERATIONS)
@ -131,7 +136,7 @@ nsBlockBandData::GetBandData(nscoord aY)
return NS_ERROR_OUT_OF_MEMORY;
}
mSize = newSize;
rv = mSpaceManager->GetBandData(aY, mSpace, *this);
rv = mSpaceManager->GetBandData(aY, space, *this);
}
NS_POSTCONDITION(mCount<=mSize, "bad state, count > size");
return NS_OK;

Просмотреть файл

@ -58,7 +58,8 @@ public:
// Get some available space. Note that aY is relative to the current
// space manager translation.
nsresult GetAvailableSpace(nscoord aY, nsRect& aResult);
nsresult GetAvailableSpace(nscoord aY, PRBool aRelaxHeightConstraint,
nsRect& aResult);
// Get the raw trapezoid count for this band.
PRInt32 GetTrapezoidCount() const {
@ -95,7 +96,7 @@ protected:
* They should always call this method instead so data members
* mTrapezoid, mCount, and mSize all get managed properly.
*/
nsresult GetBandData(nscoord aY);
nsresult GetBandData(nscoord aY, PRBool aRelaxHeightConstraint);
// The spacemanager we are getting space from
nsSpaceManager* mSpaceManager;

Просмотреть файл

@ -1999,7 +1999,7 @@ nsBlockFrame::PropagateFloatDamage(nsBlockReflowState& aState,
// XXXPerf: An optimization: if the line was and is completely
// impacted by a float and the float hasn't changed size,
// then we don't need to mark the line dirty.
aState.GetAvailableSpace(aLine->mBounds.y + aDeltaY);
aState.GetAvailableSpace(aLine->mBounds.y + aDeltaY, PR_FALSE);
PRBool wasImpactedByFloat = aLine->IsImpactedByFloat();
PRBool isImpactedByFloat = aState.IsImpactedByFloat();
#ifdef REALLY_NOISY_REFLOW
@ -4507,6 +4507,9 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
return PR_TRUE;
}
// May be needed below
PRBool wasAdjacentWIthTop = aState.IsAdjacentWithTop();
aState.mY = newY;
// If we're reflowing the line just to incrementally update the
@ -4541,13 +4544,14 @@ 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)) {
if (aState.PlaceBelowCurrentLineFloats(aState.mBelowCurrentLineFloats,
wasAdjacentWIthTop)) {
aLine->AppendFloats(aState.mBelowCurrentLineFloats);
}
else {
// At least one float is truncated, so fix up any placeholders that got split and
// push the line. XXX It may be better to put the float on the next line, but this
// is not common enough to justify the complexity.
// is not common enough to justify the complexity. Or maybe it is now...
// If we just want to calculate the maximum width, then don't push the line.
// We'll reflow it again and then it will get pushed if necessary.
@ -5731,7 +5735,7 @@ nsBlockFrame::DeleteNextInFlowChild(nsPresContext* aPresContext,
nsresult
nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
nsPlaceholderFrame* aPlaceholder,
nsFloatCache* aFloatCache,
nsFloatCache* aFloatCache,
nsReflowStatus& aReflowStatus)
{
// Reflow the float.
@ -6190,7 +6194,7 @@ nsBlockFrame::Paint(nsPresContext* aPresContext,
nscoord y = 0;
while (y < mRect.height) {
nsRect availArea;
band.GetAvailableSpace(y, availArea);
band.GetAvailableSpace(y, PR_FALSE, availArea);
// Render a box and a diagonal line through the band
aRenderingContext.SetColor(NS_RGB(0,255,0));

Просмотреть файл

@ -325,7 +325,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
}
void
nsBlockReflowState::GetAvailableSpace(nscoord aY)
nsBlockReflowState::GetAvailableSpace(nscoord aY, PRBool aRelaxHeightConstraint)
{
#ifdef DEBUG
// Verify that the caller setup the coordinate system properly
@ -335,7 +335,8 @@ nsBlockReflowState::GetAvailableSpace(nscoord aY)
"bad coord system");
#endif
mBand.GetAvailableSpace(aY - BorderPadding().top, mAvailSpaceRect);
mBand.GetAvailableSpace(aY - BorderPadding().top, aRelaxHeightConstraint,
mAvailSpaceRect);
#ifdef DEBUG
if (nsBlockFrame::gNoisyReflow) {
@ -613,10 +614,15 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout,
// And then place it
PRBool isLeftFloat;
placed = FlowAndPlaceFloat(fc, &isLeftFloat, aReflowStatus);
// force it to fit if we're at the top of the block and we can't
// break before this
PRBool forceFit = IsAdjacentWithTop() && !aLineLayout.LineIsBreakable();
placed = FlowAndPlaceFloat(fc, &isLeftFloat, aReflowStatus, forceFit);
NS_ASSERTION(placed || !forceFit,
"If we asked for force-fit, it should have been placed");
if (placed) {
// Pass on updated available space to the current inline reflow engine
GetAvailableSpace();
GetAvailableSpace(mY, forceFit);
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
GetFlag(BRS_UNCONSTRAINEDWIDTH) ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
mAvailSpaceRect.height,
@ -683,7 +689,7 @@ nsBlockReflowState::UpdateMaximumWidth(nscoord aMaximumWidth)
PRBool
nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
PRUint8 aFloats)
PRUint8 aFloats, PRBool aForceFit)
{
// If the current Y coordinate is not impacted by any floats
// then by definition the float fits.
@ -748,7 +754,7 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
}
mY += mAvailSpaceRect.height;
GetAvailableSpace();
GetAvailableSpace(mY, aForceFit);
if (0 == mBand.GetFloatCount()) {
// Winner. This band has no floats on it, therefore
@ -776,7 +782,7 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
// Restore Y coordinate and available space information
// regardless of the outcome.
mY = saveY;
GetAvailableSpace();
GetAvailableSpace(mY, aForceFit);
}
}
}
@ -786,7 +792,8 @@ nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
PRBool
nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
PRBool* aIsLeftFloat,
nsReflowStatus& aReflowStatus)
nsReflowStatus& aReflowStatus,
PRBool aForceFit)
{
aReflowStatus = NS_FRAME_COMPLETE;
// Save away the Y coordinate before placing the float. We will
@ -816,7 +823,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
mY = ClearFloats(mY, floatDisplay->mBreakType);
}
// Get the band of available space
GetAvailableSpace();
GetAvailableSpace(mY, aForceFit);
NS_ASSERTION(floatFrame->GetParent() == mBlock,
"Float frame has wrong parent");
@ -851,7 +858,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
// Can the float fit here?
PRBool keepFloatOnSameLine = PR_FALSE;
while (! CanPlaceFloat(floatSize, floatDisplay->mFloats)) {
while (!CanPlaceFloat(floatSize, floatDisplay->mFloats, aForceFit)) {
if (mAvailSpaceRect.height <= 0) {
// No space, nowhere to put anything.
mY = saveY;
@ -863,7 +870,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) {
mY += mAvailSpaceRect.height;
GetAvailableSpace();
GetAvailableSpace(mY, aForceFit);
} else {
// This quirk matches the one in nsBlockFrame::ReflowFloat
// IE handles float tables in a very special way
@ -904,7 +911,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
// the table does not fit anymore in this line so advance to next band
mY += mAvailSpaceRect.height;
GetAvailableSpace();
GetAvailableSpace(mY, aForceFit);
// reflow the float again now since we have more space
mBlock->ReflowFloat(*this, placeholder, aFloatCache, aReflowStatus);
// Get the floats bounding box and margin information
@ -1068,7 +1075,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
* Place below-current-line floats.
*/
PRBool
nsBlockReflowState::PlaceBelowCurrentLineFloats(nsFloatCacheList& aList)
nsBlockReflowState::PlaceBelowCurrentLineFloats(nsFloatCacheList& aList, PRBool aForceFit)
{
nsFloatCache* fc = aList.Head();
while (fc) {
@ -1083,11 +1090,12 @@ nsBlockReflowState::PlaceBelowCurrentLineFloats(nsFloatCacheList& aList)
printf("\n");
}
#endif
// Place the float
PRBool isLeftFloat;
nsReflowStatus reflowStatus;
PRBool placed = FlowAndPlaceFloat(fc, &isLeftFloat, reflowStatus);
PRBool placed = FlowAndPlaceFloat(fc, &isLeftFloat, reflowStatus, aForceFit);
NS_ASSERTION(placed || !aForceFit,
"If we're in force-fit mode, we should have placed the float");
if (!placed || NS_FRAME_IS_TRUNCATED(reflowStatus)) {
// return before processing all of the floats, since the line will be pushed.

Просмотреть файл

@ -75,11 +75,8 @@ public:
* available space is relative to our coordinate system (0,0) is our
* upper left corner.
*/
void GetAvailableSpace() {
GetAvailableSpace(mY);
}
void GetAvailableSpace(nscoord aY);
void GetAvailableSpace() { GetAvailableSpace(mY, PR_FALSE); }
void GetAvailableSpace(nscoord aY, PRBool aRelaxHeightConstraint);
/*
* The following functions all return PR_TRUE if they were able to
@ -93,11 +90,12 @@ public:
nsPlaceholderFrame* aPlaceholderFrame,
PRBool aInitialReflow,
nsReflowStatus& aReflowStatus);
PRBool CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats);
PRBool FlowAndPlaceFloat(nsFloatCache* aFloatCache,
PRBool CanPlaceFloat(const nsSize& aFloatSize, PRUint8 aFloats, PRBool aForceFit);
PRBool FlowAndPlaceFloat(nsFloatCache* aFloatCache,
PRBool* aIsLeftFloat,
nsReflowStatus& aReflowStatus);
PRBool PlaceBelowCurrentLineFloats(nsFloatCacheList& aFloats);
nsReflowStatus& aReflowStatus,
PRBool aForceFit);
PRBool PlaceBelowCurrentLineFloats(nsFloatCacheList& aFloats, PRBool aForceFit);
// Returns the first coordinate >= aY that clears the
// indicated floats.

Просмотреть файл

@ -448,7 +448,8 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
nsHTMLReflowState kidReflowState(GetPresContext(), aReflowState, child,
availSize, availSize.width,
aReflowState.mComputedHeight, tmpReason);
kidReflowState.mFlags.mIsTopOfPage = PR_TRUE;
#ifdef DEBUG_roc
printf("*** Reflowing child #%d %p: reason = %d, availHeight=%d\n",
columnCount, (void*)child, tmpReason, availSize.height);