Bug 92543 - BandRect.mFrames should be created as an nsAutoVoidArray, patch by Alfred Kayser, r+sr=roc, a=dbaron

This commit is contained in:
martijn.martijn@gmail.com 2007-08-30 08:29:06 -07:00
parent 8f0ca3eee1
commit dd8687a04c
4 changed files with 82 additions and 224 deletions

View File

@ -6605,7 +6605,7 @@ CompareTrees(nsPresContext* aFirstPresContext, nsIFrame* aFirstFrame,
for ( ;trapIndex<band1.mCount; trapIndex++)
{
PRBool match = (trap1[trapIndex].EqualGeometry(trap2[trapIndex])) &&
trap1[trapIndex].mState == trap2[trapIndex].mState;
((trap1[trapIndex].mFrames!=nsnull) == (trap2[trapIndex].mFrames!=nsnull));
if (!match)
{
LogVerifyMessage(k1, k2, "band.mTrapezoids of space managers differs\n");
@ -6630,7 +6630,7 @@ CompareTrees(nsPresContext* aFirstPresContext, nsIFrame* aFirstFrame,
for ( ; trapIndex<band1.mCount; trapIndex++)
{
PRBool match = (trap1[trapIndex].EqualGeometry(trap2[trapIndex])) &&
trap1[trapIndex].mState == trap2[trapIndex].mState;
((trap1[trapIndex].mFrames!=nsnull) == (trap2[trapIndex].mFrames!=nsnull));
if (!match)
{
LogVerifyMessage(k1, k2, "band.mTrapezoids of space managers differs\n");

View File

@ -183,28 +183,16 @@ nsBlockBandData::ComputeAvailSpaceRect()
NS_PRECONDITION(mCount<=mSize, "bad state, count > size");
for (i = 0; i < mCount; i++) {
trapezoid = &mTrapezoids[i];
if (trapezoid->mState != nsBandTrapezoid::Available) {
if (trapezoid->mFrames) {
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
printf("band %p checking !Avail trap %p with frame %p\n", this, trapezoid, trapezoid->mFrame);
printf("band %p checking !Avail trap %p with frame %p\n", this, trapezoid, trapezoid->mFrames);
#endif
if (nsBandTrapezoid::OccupiedMultiple == trapezoid->mState) {
PRInt32 j, numFrames = trapezoid->mFrames->Count();
NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
for (j = 0; j < numFrames; j++) {
nsIFrame* f = (nsIFrame*) trapezoid->mFrames->ElementAt(j);
const nsStyleDisplay* display = f->GetStyleDisplay();
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
leftFloats++;
}
else if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
rightFloats++;
if ((nsnull == rightTrapezoid) && (i > 0)) {
rightTrapezoid = &mTrapezoids[i - 1];
}
}
}
} else {
const nsStyleDisplay* display = trapezoid->mFrame->GetStyleDisplay();
const nsSmallVoidArray* frames = trapezoid->mFrames;
const PRInt32 numFrames = frames->Count();
NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
for (PRInt32 j = 0; j < numFrames; j++) {
nsIFrame* f = static_cast<nsIFrame*>(frames->ElementAt(j));
const nsStyleDisplay* display = f->GetStyleDisplay();
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
leftFloats++;
}
@ -218,7 +206,7 @@ nsBlockBandData::ComputeAvailSpaceRect()
}
}
}
else if (mTrapezoids[0].mState != nsBandTrapezoid::Available) {
else if (mTrapezoids[0].mFrames) {
// We have a float using up all the available space
leftFloats = 1;
}
@ -238,28 +226,21 @@ nsBlockBandData::ComputeAvailSpaceRect()
// When there is no available space, we still need a proper X
// coordinate to place objects that end up here anyway.
if (nsBandTrapezoid::Available != trapezoid->mState) {
if (nsBandTrapezoid::OccupiedMultiple == trapezoid->mState) {
// It's not clear what coordinate to use when there is no
// available space and the space is multiply occupied...So: If
// any of the floats that are a part of the trapezoid are left
// floats then we move over to the right edge of the
// unavaliable space.
PRInt32 j, numFrames = trapezoid->mFrames->Count();
NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
for (j = 0; j < numFrames; j++) {
nsIFrame* f = (nsIFrame*) trapezoid->mFrames->ElementAt(j);
const nsStyleDisplay* display = f->GetStyleDisplay();
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
mAvailSpace.x = mAvailSpace.XMost();
break;
}
}
}
else {
const nsStyleDisplay* display = trapezoid->mFrame->GetStyleDisplay();
const nsSmallVoidArray* frames = trapezoid->mFrames;
if (frames) {
// It's not clear what coordinate to use when there is no
// available space and the space is multiply occupied...So: If
// any of the floats that are a part of the trapezoid are left
// floats then we move over to the right edge of the
// unavaliable space.
const PRInt32 numFrames = frames->Count();
NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
for (PRInt32 j = 0; j < numFrames; j++) {
nsIFrame* f = static_cast<nsIFrame*>(frames->ElementAt(j));
const nsStyleDisplay* display = f->GetStyleDisplay();
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
mAvailSpace.x = mAvailSpace.XMost();
break;
}
}
mAvailSpace.width = 0;

View File

@ -69,7 +69,6 @@ nsSpaceManager::BandList::BandList()
: nsSpaceManager::BandRect(NSCOORD_MIN, NSCOORD_MIN, NSCOORD_MIN, NSCOORD_MIN, (nsIFrame*)nsnull)
{
PR_INIT_CLIST(this);
mNumFrames = 0;
}
void
@ -276,8 +275,7 @@ nsSpaceManager::GetBandAvailableSpace(const BandRect* aBand,
aBandData.mCount += 2 * aBand->Length() + 2; // estimate the number needed
return NS_ERROR_FAILURE;
}
trapezoid->mState = nsBandTrapezoid::Available;
trapezoid->mFrame = nsnull;
trapezoid->mFrames = nsnull;
// Assign the trapezoid a rectangular shape. The trapezoid must be in the
// local coordinate space, so convert the current left coordinate
@ -294,14 +292,8 @@ nsSpaceManager::GetBandAvailableSpace(const BandRect* aBand,
aBandData.mCount += 2 * aBand->Length() + 1; // estimate the number needed
return NS_ERROR_FAILURE;
}
if (1 == aBand->mNumFrames) {
trapezoid->mState = nsBandTrapezoid::Occupied;
trapezoid->mFrame = aBand->mFrame;
} else {
NS_ASSERTION(aBand->mNumFrames > 1, "unexpected frame count");
trapezoid->mState = nsBandTrapezoid::OccupiedMultiple;
trapezoid->mFrames = aBand->mFrames;
}
NS_ASSERTION(aBand->mFrames.Count() > 0, "unexpected frame count");
trapezoid->mFrames = &aBand->mFrames;
nscoord x = aBand->mLeft;
// The first band can straddle the clip rect
@ -333,8 +325,7 @@ nsSpaceManager::GetBandAvailableSpace(const BandRect* aBand,
aBandData.mCount++;
return NS_ERROR_FAILURE;
}
trapezoid->mState = nsBandTrapezoid::Available;
trapezoid->mFrame = nsnull;
trapezoid->mFrames = nsnull;
// Assign the trapezoid a rectangular shape. The trapezoid must be in the
// local coordinate space, so convert the current left coordinate
@ -366,8 +357,7 @@ nsSpaceManager::GetBandData(nscoord aYOffset,
// All the requested space is available
aBandData.mCount = 1;
aBandData.mTrapezoids[0] = nsRect(0, aYOffset, aMaxSize.width, maxHeight);
aBandData.mTrapezoids[0].mState = nsBandTrapezoid::Available;
aBandData.mTrapezoids[0].mFrame = nsnull;
aBandData.mTrapezoids[0].mFrames = nsnull;
} else {
// Find the first band that contains the y-offset or is below the y-offset
BandRect* band = GuessBandWithTopAbove(y);
@ -380,8 +370,7 @@ nsSpaceManager::GetBandData(nscoord aYOffset,
aBandData.mCount = 1;
aBandData.mTrapezoids[0] =
nsRect(0, aYOffset, aMaxSize.width, PR_MIN(band->mTop - y, maxHeight));
aBandData.mTrapezoids[0].mState = nsBandTrapezoid::Available;
aBandData.mTrapezoids[0].mFrame = nsnull;
aBandData.mTrapezoids[0].mFrames = nsnull;
break;
} else if (y < band->mBottom) {
// The band contains the y-offset. Return a list of available and
@ -584,7 +573,7 @@ nsSpaceManager::AddRectToBand(BandRect* aBand, BandRect* aBandRect)
{
NS_PRECONDITION((aBand->mTop == aBandRect->mTop) &&
(aBand->mBottom == aBandRect->mBottom), "bad band");
NS_PRECONDITION(1 == aBandRect->mNumFrames, "shared band rect");
NS_PRECONDITION(1 == aBandRect->mFrames.Count(), "shared band rect");
nscoord topOfBand = aBand->mTop;
// Figure out where in the band horizontally to insert the rect
@ -651,7 +640,7 @@ nsSpaceManager::AddRectToBand(BandRect* aBand, BandRect* aBandRect)
}
// Mark the existing rect as shared
aBand->AddFrame(aBandRect->mFrame);
aBand->AddFrame(aBandRect->FrameAt(0));
return;
}
}
@ -701,12 +690,12 @@ nsSpaceManager::AddRectToBand(BandRect* aBand, BandRect* aBandRect)
aBand->InsertAfter(r1);
// Mark the overlap as being shared
aBand->AddFrame(aBandRect->mFrame);
aBand->AddFrame(aBandRect->FrameAt(0));
return;
} else {
// Indicate the frames share the existing rect
aBand->AddFrame(aBandRect->mFrame);
aBand->AddFrame(aBandRect->FrameAt(0));
if (aBand->mRight == aBandRect->mRight) {
// The new and existing rect have the same right edge. We're all done,
@ -789,7 +778,7 @@ nsSpaceManager::InsertBandRect(BandRect* aBandRect)
// the part that's above the band
BandRect* bandRect1 = new BandRect(aBandRect->mLeft, aBandRect->mTop,
aBandRect->mRight, band->mTop,
aBandRect->mFrame);
aBandRect->mFrames);
// Insert bandRect1 as a new band
band->InsertBefore(bandRect1);
@ -835,7 +824,7 @@ nsSpaceManager::InsertBandRect(BandRect* aBandRect)
// the rect, creating a new rect for the part that overlaps the band
BandRect* bandRect1 = new BandRect(aBandRect->mLeft, aBandRect->mTop,
aBandRect->mRight, band->mBottom,
aBandRect->mFrame);
aBandRect->mFrames);
// Add bandRect1 to the band
AddRectToBand(band, bandRect1);
@ -952,9 +941,9 @@ nsSpaceManager::RemoveRegion(nsIFrame* aFrame)
// Remember that we found a matching rect in this band
foundMatchingRect = PR_TRUE;
if (rect->mNumFrames > 1) {
if (rect->mFrames.Count() > 1) {
// The band rect is occupied by more than one frame
rect->RemoveFrame(aFrame);
rect->mFrames.RemoveElement(aFrame);
// Remember that this rect was being shared by more than one frame
// including aFrame
@ -1156,33 +1145,19 @@ nsSpaceManager::List(FILE* out)
else {
BandRect* band = mBandList.Head();
do {
fprintf(out, " left=%d top=%d right=%d bottom=%d numFrames=%d",
band->mLeft, band->mTop, band->mRight, band->mBottom,
band->mNumFrames);
if (1 == band->mNumFrames) {
nsIFrameDebug* frameDebug;
PRInt32 const n = band->mFrames.Count();
fprintf(out, " left=%d top=%d right=%d bottom=%d count=%d frames=",
band->mLeft, band->mTop, band->mRight, band->mBottom, n);
if (NS_SUCCEEDED(band->mFrame->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&frameDebug))) {
frameDebug->GetFrameName(tmp);
fprintf(out, " frame=");
fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out);
fprintf(out, "@%p", band->mFrame);
}
}
else if (1 < band->mNumFrames) {
fprintf(out, "\n ");
nsVoidArray* a = band->mFrames;
PRInt32 i, n = a->Count();
for (i = 0; i < n; i++) {
nsIFrame* frame = (nsIFrame*) a->ElementAt(i);
if (frame) {
nsIFrameDebug* frameDebug;
for (PRInt32 i = 0; i < n; i++) {
nsIFrame* frame = (nsIFrame*)band->mFrames.FastElementAt(i);
if (frame) {
nsIFrameDebug* frameDebug;
if (NS_SUCCEEDED(frame->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&frameDebug))) {
frameDebug->GetFrameName(tmp);
fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out);
fprintf(out, "@%p ", frame);
}
if (NS_SUCCEEDED(frame->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&frameDebug))) {
frameDebug->GetFrameName(tmp);
fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out);
fprintf(out, "@%p ", frame);
}
}
}
@ -1387,32 +1362,26 @@ nsSpaceManager::BandRect::BandRect(nscoord aLeft,
mTop = aTop;
mRight = aRight;
mBottom = aBottom;
mFrame = aFrame;
mNumFrames = 1;
AddFrame(aFrame);
}
nsSpaceManager::BandRect::BandRect(nscoord aLeft,
nscoord aTop,
nscoord aRight,
nscoord aBottom,
nsVoidArray* aFrames)
nsSmallVoidArray& aFrames)
{
MOZ_COUNT_CTOR(BandRect);
mLeft = aLeft;
mTop = aTop;
mRight = aRight;
mBottom = aBottom;
mFrames = new nsVoidArray;
mFrames->operator=(*aFrames);
mNumFrames = mFrames->Count();
mFrames = aFrames;
}
nsSpaceManager::BandRect::~BandRect()
{
MOZ_COUNT_DTOR(BandRect);
if (mNumFrames > 1) {
delete mFrames;
}
}
nsSpaceManager::BandRect*
@ -1421,13 +1390,7 @@ nsSpaceManager::BandRect::SplitVertically(nscoord aBottom)
NS_PRECONDITION((aBottom > mTop) && (aBottom < mBottom), "bad argument");
// Create a new band rect for the bottom part
BandRect* bottomBandRect;
if (mNumFrames > 1) {
bottomBandRect = new BandRect(mLeft, aBottom, mRight, mBottom, mFrames);
} else {
bottomBandRect = new BandRect(mLeft, aBottom, mRight, mBottom, mFrame);
}
BandRect* bottomBandRect = new BandRect(mLeft, aBottom, mRight, mBottom, mFrames);
// This band rect becomes the top part, so adjust the bottom edge
mBottom = aBottom;
@ -1440,99 +1403,31 @@ nsSpaceManager::BandRect::SplitHorizontally(nscoord aRight)
NS_PRECONDITION((aRight > mLeft) && (aRight < mRight), "bad argument");
// Create a new band rect for the right part
BandRect* rightBandRect;
if (mNumFrames > 1) {
rightBandRect = new BandRect(aRight, mTop, mRight, mBottom, mFrames);
} else {
rightBandRect = new BandRect(aRight, mTop, mRight, mBottom, mFrame);
}
BandRect* rightBandRect = new BandRect(aRight, mTop, mRight, mBottom, mFrames);
// This band rect becomes the left part, so adjust the right edge
mRight = aRight;
return rightBandRect;
}
PRBool
nsSpaceManager::BandRect::IsOccupiedBy(const nsIFrame* aFrame) const
{
PRBool result;
if (1 == mNumFrames) {
result = (mFrame == aFrame);
} else {
PRInt32 count = mFrames->Count();
result = PR_FALSE;
for (PRInt32 i = 0; i < count; i++) {
nsIFrame* f = (nsIFrame*)mFrames->ElementAt(i);
if (f == aFrame) {
result = PR_TRUE;
break;
}
}
}
return result;
}
void
nsSpaceManager::BandRect::AddFrame(const nsIFrame* aFrame)
{
if (1 == mNumFrames) {
nsIFrame* f = mFrame;
mFrames = new nsVoidArray;
mFrames->AppendElement(f);
}
mNumFrames++;
mFrames->AppendElement((void*)aFrame);
NS_POSTCONDITION(mFrames->Count() == mNumFrames, "bad frame count");
}
void
nsSpaceManager::BandRect::RemoveFrame(const nsIFrame* aFrame)
{
NS_PRECONDITION(mNumFrames > 1, "only one frame");
mFrames->RemoveElement((void*)aFrame);
mNumFrames--;
if (1 == mNumFrames) {
nsIFrame* f = (nsIFrame*)mFrames->ElementAt(0);
delete mFrames;
mFrame = f;
}
}
PRBool
nsSpaceManager::BandRect::HasSameFrameList(const BandRect* aBandRect) const
{
PRBool result;
const PRInt32 count = mFrames.Count();
// Check whether they're occupied by the same number of frames
if (mNumFrames != aBandRect->mNumFrames) {
result = PR_FALSE;
} else if (1 == mNumFrames) {
result = (mFrame == aBandRect->mFrame);
} else {
result = PR_TRUE;
// For each frame occupying this band rect check whether it also occupies
// aBandRect
PRInt32 count = mFrames->Count();
for (PRInt32 i = 0; i < count; i++) {
nsIFrame* f = (nsIFrame*)mFrames->ElementAt(i);
if (-1 == aBandRect->mFrames->IndexOf(f)) {
result = PR_FALSE;
break;
}
if (count != aBandRect->mFrames.Count()) {
return PR_FALSE;
}
// For each frame occupying this band rect check whether it also occupies
// aBandRect
for (PRInt32 i = 0; i < count; i++) {
if (-1 == aBandRect->mFrames.IndexOf(mFrames.FastElementAt(i))) {
return PR_FALSE;
}
}
return result;
return PR_TRUE;
}
/**

View File

@ -49,10 +49,10 @@
#include "nsISupports.h"
#include "nsCoord.h"
#include "nsRect.h"
#include "nsVoidArray.h"
class nsIPresShell;
class nsIFrame;
class nsVoidArray;
struct nsSize;
struct nsHTMLReflowState;
class nsPresContext;
@ -69,16 +69,10 @@ class nsPresContext;
* </ul>
*/
struct nsBandTrapezoid {
enum State {Available, Occupied, OccupiedMultiple};
nscoord mTopY, mBottomY; // top and bottom y-coordinates
nscoord mTopLeftX, mBottomLeftX; // left edge x-coordinates
nscoord mTopRightX, mBottomRightX; // right edge x-coordinates
State mState; // state of the space
union {
nsIFrame* mFrame; // single frame occupying the space
const nsVoidArray* mFrames; // list of frames occupying the space
};
const nsSmallVoidArray* mFrames; // list of frames occupying the space
// Get the height of the trapezoid
nscoord GetHeight() const {return mBottomY - mTopY;}
@ -89,9 +83,6 @@ struct nsBandTrapezoid {
// Set the trapezoid from a rectangle
inline void operator=(const nsRect& aRect);
// Do these trapezoids have the same geometry, frame, and state?
inline PRBool Equals(const nsBandTrapezoid& aTrap) const;
// Do these trapezoids have the same geometry?
inline PRBool EqualGeometry(const nsBandTrapezoid& aTrap) const;
@ -102,7 +93,7 @@ struct nsBandTrapezoid {
mBottomLeftX(0),
mTopRightX(0),
mBottomRightX(0),
mFrame(nsnull)
mFrames(nsnull)
{
}
};
@ -126,20 +117,6 @@ inline void nsBandTrapezoid::operator=(const nsRect& aRect)
mBottomY = aRect.YMost();
}
inline PRBool nsBandTrapezoid::Equals(const nsBandTrapezoid& aTrap) const
{
return (
mTopLeftX == aTrap.mTopLeftX &&
mBottomLeftX == aTrap.mBottomLeftX &&
mTopRightX == aTrap.mTopRightX &&
mBottomRightX == aTrap.mBottomRightX &&
mTopY == aTrap.mTopY &&
mBottomY == aTrap.mBottomY &&
mState == aTrap.mState &&
mFrame == aTrap.mFrame
);
}
inline PRBool nsBandTrapezoid::EqualGeometry(const nsBandTrapezoid& aTrap) const
{
return (
@ -377,18 +354,14 @@ public:
struct BandRect : PRCListStr {
nscoord mLeft, mTop;
nscoord mRight, mBottom;
PRInt32 mNumFrames; // number of frames occupying this rect
union {
nsIFrame* mFrame; // single frame occupying the space
nsVoidArray* mFrames; // list of frames occupying the space
};
nsSmallVoidArray mFrames; // list of frames occupying the space
BandRect(nscoord aLeft, nscoord aTop,
nscoord aRight, nscoord aBottom,
nsIFrame*);
nsIFrame* aFrame);
BandRect(nscoord aLeft, nscoord aTop,
nscoord aRight, nscoord aBottom,
nsVoidArray*);
nsSmallVoidArray& frames);
~BandRect();
// List operations
@ -413,9 +386,18 @@ public:
BandRect* SplitHorizontally(nscoord aRight);
// Accessor functions
PRBool IsOccupiedBy(const nsIFrame*) const;
void AddFrame(const nsIFrame*);
void RemoveFrame(const nsIFrame*);
PRBool IsOccupiedBy(const nsIFrame* aFrame) const {
return (mFrames.IndexOf((void*)aFrame) != -1);
}
void AddFrame(const nsIFrame* aFrame) {
mFrames.AppendElement((void*)aFrame);
}
void RemoveFrame(const nsIFrame* aFrame) {
mFrames.RemoveElement((void*)aFrame);
}
nsIFrame * FrameAt(PRInt32 index) {
return static_cast<nsIFrame*>(mFrames.FastElementAt(index));
}
PRBool HasSameFrameList(const BandRect* aBandRect) const;
PRInt32 Length() const;
};