From 64906b0b2091f644ca3634e2609121373e71b98c Mon Sep 17 00:00:00 2001 From: "buster%netscape.com" Date: Thu, 23 Dec 1999 20:49:07 +0000 Subject: [PATCH] fixed bug 19494 r=troy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The problem was the space mgr was computing mCount to be > 2* mSize, which this code couldn't handle correctly. So now if the space mgr computes mCount to be more than twice the size of the current count, we immediately bump up the size to that count.� If more are needed later, the next call will give us twice this number anyway. --- layout/generic/nsBlockBandData.cpp | 64 ++++++++++++++++++------ layout/generic/nsBlockBandData.h | 9 ++++ layout/html/base/src/nsBlockBandData.cpp | 64 ++++++++++++++++++------ layout/html/base/src/nsBlockBandData.h | 9 ++++ 4 files changed, 114 insertions(+), 32 deletions(-) diff --git a/layout/generic/nsBlockBandData.cpp b/layout/generic/nsBlockBandData.cpp index fc21fa2a8466..ce7514a0ce1e 100644 --- a/layout/generic/nsBlockBandData.cpp +++ b/layout/generic/nsBlockBandData.cpp @@ -74,20 +74,8 @@ nsresult nsBlockBandData::GetAvailableSpace(nscoord aY, nsRect& aResult) { // Get the raw band data for the given Y coordinate - nsresult rv = mSpaceManager->GetBandData(aY, mSpace, *this); - while (NS_FAILED(rv)) { - // We need more space for our bands - if (mTrapezoids != mData) { - delete [] mTrapezoids; - } - PRInt32 newSize = mSize * 2; - mTrapezoids = new nsBandTrapezoid[newSize]; - if (!mTrapezoids) { - return NS_ERROR_OUT_OF_MEMORY; - } - mSize = newSize; - rv = mSpaceManager->GetBandData(aY, mSpace, *this); - } + nsresult rv = GetBandData(aY); + if (NS_FAILED(rv)) { return rv; } // Compute the bounding rect of the available space, i.e. space // between any left and right floaters. @@ -96,6 +84,46 @@ nsBlockBandData::GetAvailableSpace(nscoord aY, nsRect& aResult) return NS_OK; } +// the code below should never loop more than a very few times. +// this is a safety valve to see if we've gone off the deep end +#define ERROR_TOO_MANY_ITERATIONS 1000 + +/* nsBlockBandData methods should never call mSpaceManager->GetBandData directly. + * They should always call nsBlockBandData::GetBandData() instead. + */ +nsresult +nsBlockBandData::GetBandData(nscoord aY) +{ + PRInt32 iterations =0; + nsresult rv = mSpaceManager->GetBandData(aY, mSpace, *this); + while (NS_FAILED(rv)) { + iterations++; + if (iterations>ERROR_TOO_MANY_ITERATIONS) + { + NS_ASSERTION(PR_FALSE, "too many iterations in nsBlockBandData::GetBandData"); + return NS_ERROR_FAILURE; + } + // We need more space for our bands + if (mTrapezoids != mData) { + delete [] mTrapezoids; + } + PRInt32 newSize = mSize * 2; + if (newSizeGetBandData(aY, mSpace, *this); + } + NS_POSTCONDITION(mCount<=mSize, "bad state, count > size"); + return NS_OK; +} + + + /** * Computes the bounding rect of the available space, i.e. space * between any left and right floaters. Uses the current trapezoid @@ -125,6 +153,7 @@ nsBlockBandData::ComputeAvailSpaceRect() // Examine each trapezoid in the band, counting up the number of // left and right floaters. Use the right-most floater to // determine where the right edge of the available space is. + NS_PRECONDITION(mCount<=mSize, "bad state, count > size"); for (i = 0; i < mCount; i++) { trapezoid = &mTrapezoids[i]; if (trapezoid->mState != nsBandTrapezoid::Available) { @@ -245,8 +274,10 @@ nscoord nsBlockBandData::ClearFloaters(nscoord aY, PRUint8 aBreakType) { for (;;) { - // Update band information based on target Y before clearing. - mSpaceManager->GetBandData(aY, mSpace, *this); + nsresult rv = GetBandData(aY); + if (NS_FAILED(rv)) { + break; // something is seriously wrong, bail + } ComputeAvailSpaceRect(); // Compute aYS as aY in space-manager "root" coordinates. @@ -256,6 +287,7 @@ nsBlockBandData::ClearFloaters(nscoord aY, PRUint8 aBreakType) // this band. nscoord yMost = aYS; PRInt32 i; + NS_PRECONDITION(mCount<=mSize, "bad state, count > size"); for (i = 0; i < mCount; i++) { nsBandTrapezoid* trapezoid = &mTrapezoids[i]; if (nsBandTrapezoid::Available != trapezoid->mState) { diff --git a/layout/generic/nsBlockBandData.h b/layout/generic/nsBlockBandData.h index 3f3838e9f282..29ac776dd93a 100644 --- a/layout/generic/nsBlockBandData.h +++ b/layout/generic/nsBlockBandData.h @@ -90,6 +90,15 @@ public: nsSize* aResult); protected: + + /** utility method to calculate the band data at aY. + * nsBlockBandData methods should never call + * mSpaceManager->GetBandData directly. + * They should always call this method instead so data members + * mTrapezoid, mCount, and mSize all get managed properly. + */ + nsresult GetBandData(nscoord aY); + // The spacemanager we are getting space from nsISpaceManager* mSpaceManager; nscoord mSpaceManagerX, mSpaceManagerY; diff --git a/layout/html/base/src/nsBlockBandData.cpp b/layout/html/base/src/nsBlockBandData.cpp index fc21fa2a8466..ce7514a0ce1e 100644 --- a/layout/html/base/src/nsBlockBandData.cpp +++ b/layout/html/base/src/nsBlockBandData.cpp @@ -74,20 +74,8 @@ nsresult nsBlockBandData::GetAvailableSpace(nscoord aY, nsRect& aResult) { // Get the raw band data for the given Y coordinate - nsresult rv = mSpaceManager->GetBandData(aY, mSpace, *this); - while (NS_FAILED(rv)) { - // We need more space for our bands - if (mTrapezoids != mData) { - delete [] mTrapezoids; - } - PRInt32 newSize = mSize * 2; - mTrapezoids = new nsBandTrapezoid[newSize]; - if (!mTrapezoids) { - return NS_ERROR_OUT_OF_MEMORY; - } - mSize = newSize; - rv = mSpaceManager->GetBandData(aY, mSpace, *this); - } + nsresult rv = GetBandData(aY); + if (NS_FAILED(rv)) { return rv; } // Compute the bounding rect of the available space, i.e. space // between any left and right floaters. @@ -96,6 +84,46 @@ nsBlockBandData::GetAvailableSpace(nscoord aY, nsRect& aResult) return NS_OK; } +// the code below should never loop more than a very few times. +// this is a safety valve to see if we've gone off the deep end +#define ERROR_TOO_MANY_ITERATIONS 1000 + +/* nsBlockBandData methods should never call mSpaceManager->GetBandData directly. + * They should always call nsBlockBandData::GetBandData() instead. + */ +nsresult +nsBlockBandData::GetBandData(nscoord aY) +{ + PRInt32 iterations =0; + nsresult rv = mSpaceManager->GetBandData(aY, mSpace, *this); + while (NS_FAILED(rv)) { + iterations++; + if (iterations>ERROR_TOO_MANY_ITERATIONS) + { + NS_ASSERTION(PR_FALSE, "too many iterations in nsBlockBandData::GetBandData"); + return NS_ERROR_FAILURE; + } + // We need more space for our bands + if (mTrapezoids != mData) { + delete [] mTrapezoids; + } + PRInt32 newSize = mSize * 2; + if (newSizeGetBandData(aY, mSpace, *this); + } + NS_POSTCONDITION(mCount<=mSize, "bad state, count > size"); + return NS_OK; +} + + + /** * Computes the bounding rect of the available space, i.e. space * between any left and right floaters. Uses the current trapezoid @@ -125,6 +153,7 @@ nsBlockBandData::ComputeAvailSpaceRect() // Examine each trapezoid in the band, counting up the number of // left and right floaters. Use the right-most floater to // determine where the right edge of the available space is. + NS_PRECONDITION(mCount<=mSize, "bad state, count > size"); for (i = 0; i < mCount; i++) { trapezoid = &mTrapezoids[i]; if (trapezoid->mState != nsBandTrapezoid::Available) { @@ -245,8 +274,10 @@ nscoord nsBlockBandData::ClearFloaters(nscoord aY, PRUint8 aBreakType) { for (;;) { - // Update band information based on target Y before clearing. - mSpaceManager->GetBandData(aY, mSpace, *this); + nsresult rv = GetBandData(aY); + if (NS_FAILED(rv)) { + break; // something is seriously wrong, bail + } ComputeAvailSpaceRect(); // Compute aYS as aY in space-manager "root" coordinates. @@ -256,6 +287,7 @@ nsBlockBandData::ClearFloaters(nscoord aY, PRUint8 aBreakType) // this band. nscoord yMost = aYS; PRInt32 i; + NS_PRECONDITION(mCount<=mSize, "bad state, count > size"); for (i = 0; i < mCount; i++) { nsBandTrapezoid* trapezoid = &mTrapezoids[i]; if (nsBandTrapezoid::Available != trapezoid->mState) { diff --git a/layout/html/base/src/nsBlockBandData.h b/layout/html/base/src/nsBlockBandData.h index 3f3838e9f282..29ac776dd93a 100644 --- a/layout/html/base/src/nsBlockBandData.h +++ b/layout/html/base/src/nsBlockBandData.h @@ -90,6 +90,15 @@ public: nsSize* aResult); protected: + + /** utility method to calculate the band data at aY. + * nsBlockBandData methods should never call + * mSpaceManager->GetBandData directly. + * They should always call this method instead so data members + * mTrapezoid, mCount, and mSize all get managed properly. + */ + nsresult GetBandData(nscoord aY); + // The spacemanager we are getting space from nsISpaceManager* mSpaceManager; nscoord mSpaceManagerX, mSpaceManagerY;