зеркало из https://github.com/mozilla/gecko-dev.git
Bug 730769 - Make nsLineBox use a frame hash table for lines with many frames. part=2/2 r=bz
This commit is contained in:
Родитель
170ef239c4
Коммит
7213c84c26
|
@ -2671,16 +2671,14 @@ nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState,
|
|||
}
|
||||
// when aFromContainer is 'this', then aLine->LastChild()'s next sibling
|
||||
// is already set correctly.
|
||||
aLine->SetChildCount(aLine->GetChildCount() + 1);
|
||||
|
||||
PRInt32 fromLineChildCount = fromLine->GetChildCount();
|
||||
if (0 != --fromLineChildCount) {
|
||||
aLine->NoteFrameAdded(frame);
|
||||
|
||||
if (fromLine->GetChildCount() > 1) {
|
||||
// Mark line dirty now that we pulled a child
|
||||
fromLine->SetChildCount(fromLineChildCount);
|
||||
fromLine->NoteFrameRemoved(frame);
|
||||
fromLine->MarkDirty();
|
||||
fromLine->mFirstChild = newFirstChild;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// Free up the fromLine now that it's empty
|
||||
// Its bounds might need to be redrawn, though.
|
||||
// XXX WHY do we invalidate the bounds AND the combined area? doesn't
|
||||
|
@ -3305,7 +3303,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||
|
||||
// Push continuation to a new line, but only if we actually made one.
|
||||
if (madeContinuation) {
|
||||
nsLineBox* line = NewLineBox(nextFrame, 1, true);
|
||||
nsLineBox* line = NewLineBox(nextFrame, true);
|
||||
NS_ENSURE_TRUE(line, NS_ERROR_OUT_OF_MEMORY);
|
||||
mLines.after_insert(aLine, line);
|
||||
}
|
||||
|
@ -3976,7 +3974,7 @@ nsBlockFrame::CreateContinuationFor(nsBlockReflowState& aState,
|
|||
mFrames.InsertFrame(nsnull, aFrame, newFrame);
|
||||
|
||||
if (aLine) {
|
||||
aLine->SetChildCount(aLine->GetChildCount() + 1);
|
||||
aLine->NoteFrameAdded(newFrame);
|
||||
}
|
||||
|
||||
aMadeNewFrame = true;
|
||||
|
@ -4099,12 +4097,11 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState,
|
|||
#endif
|
||||
|
||||
// Put frames being split out into their own line
|
||||
nsLineBox* newLine = NewLineBox(aFrame, pushCount, false);
|
||||
nsLineBox* newLine = NewLineBox(aLine, aFrame, pushCount);
|
||||
if (!newLine) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mLines.after_insert(aLine, newLine);
|
||||
aLine->SetChildCount(aLine->GetChildCount() - pushCount);
|
||||
#ifdef DEBUG
|
||||
if (gReallyNoisyReflow) {
|
||||
newLine->List(stdout, gNoiseIndent+1);
|
||||
|
@ -4920,12 +4917,11 @@ nsBlockFrame::AddFrames(nsFrameList& aFrameList, nsIFrame* aPrevSibling)
|
|||
PRInt32 rem = prevSibLine->GetChildCount() - prevSiblingIndex - 1;
|
||||
if (rem) {
|
||||
// Split the line in two where the frame(s) are being inserted.
|
||||
nsLineBox* line = NewLineBox(aPrevSibling->GetNextSibling(), rem, false);
|
||||
nsLineBox* line = NewLineBox(prevSibLine, aPrevSibling->GetNextSibling(), rem);
|
||||
if (!line) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
lineList->after_insert(prevSibLine, line);
|
||||
prevSibLine->SetChildCount(prevSibLine->GetChildCount() - rem);
|
||||
// Mark prevSibLine dirty and as needing textrun invalidation, since
|
||||
// we may be breaking up text in the line. Its previous line may also
|
||||
// need to be invalidated because it may be able to pull some text up.
|
||||
|
@ -4966,7 +4962,7 @@ nsBlockFrame::AddFrames(nsFrameList& aFrameList, nsIFrame* aPrevSibling)
|
|||
(aPrevSibling && ShouldPutNextSiblingOnNewLine(aPrevSibling))) {
|
||||
// Create a new line for the frame and add its line to the line
|
||||
// list.
|
||||
nsLineBox* line = NewLineBox(newFrame, 1, isBlock);
|
||||
nsLineBox* line = NewLineBox(newFrame, isBlock);
|
||||
if (!line) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -4982,7 +4978,7 @@ nsBlockFrame::AddFrames(nsFrameList& aFrameList, nsIFrame* aPrevSibling)
|
|||
}
|
||||
}
|
||||
else {
|
||||
prevSibLine->SetChildCount(prevSibLine->GetChildCount() + 1);
|
||||
prevSibLine->NoteFrameAdded(newFrame);
|
||||
// We're adding inline content to prevSibLine, so we need to mark it
|
||||
// dirty, ensure its textruns are recomputed, and possibly do the same
|
||||
// to its previous line since that line may be able to pull content up.
|
||||
|
@ -5504,9 +5500,7 @@ nsBlockFrame::DoRemoveFrame(nsIFrame* aDeletedFrame, PRUint32 aFlags)
|
|||
}
|
||||
|
||||
// Update the child count of the line to be accurate
|
||||
PRInt32 lineChildCount = line->GetChildCount();
|
||||
lineChildCount--;
|
||||
line->SetChildCount(lineChildCount);
|
||||
line->NoteFrameRemoved(aDeletedFrame);
|
||||
|
||||
// Destroy frame; capture its next continuation first in case we need
|
||||
// to destroy that too.
|
||||
|
@ -5533,7 +5527,7 @@ nsBlockFrame::DoRemoveFrame(nsIFrame* aDeletedFrame, PRUint32 aFlags)
|
|||
|
||||
bool haveAdvancedToNextLine = false;
|
||||
// If line is empty, remove it now.
|
||||
if (0 == lineChildCount) {
|
||||
if (0 == line->GetChildCount()) {
|
||||
#ifdef NOISY_REMOVE_FRAME
|
||||
printf("DoRemoveFrame: %s line=%p became empty so it will be removed\n",
|
||||
searchingOverflowList?"overflow":"normal", line.get());
|
||||
|
@ -5686,12 +5680,10 @@ nsBlockFrame::StealFrame(nsPresContext* aPresContext,
|
|||
}
|
||||
|
||||
// Register removal with the line boxes
|
||||
PRInt32 count = line->GetChildCount();
|
||||
line->SetChildCount(--count);
|
||||
if (count > 0) {
|
||||
line->NoteFrameRemoved(frame);
|
||||
if (line->GetChildCount() > 0) {
|
||||
line->MarkDirty();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// Remove the line box
|
||||
nsLineBox* lineBox = line;
|
||||
if (searchingOverflowList) {
|
||||
|
@ -5710,8 +5702,7 @@ nsBlockFrame::StealFrame(nsPresContext* aPresContext,
|
|||
line_end = mLines.end();
|
||||
line = line_end;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
line = mLines.erase(line);
|
||||
}
|
||||
lineBox->Destroy(aPresContext->PresShell());
|
||||
|
|
|
@ -354,8 +354,11 @@ protected:
|
|||
#endif
|
||||
#endif
|
||||
|
||||
nsLineBox* NewLineBox(nsIFrame* aFrame, PRInt32 aCount, bool aIsBlock) {
|
||||
return NS_NewLineBox(PresContext()->PresShell(), aFrame, aCount, aIsBlock);
|
||||
nsLineBox* NewLineBox(nsIFrame* aFrame, bool aIsBlock) {
|
||||
return NS_NewLineBox(PresContext()->PresShell(), aFrame, aIsBlock);
|
||||
}
|
||||
nsLineBox* NewLineBox(nsLineBox* aFromLine, nsIFrame* aFrame, PRInt32 aCount) {
|
||||
return NS_NewLineBox(PresContext()->PresShell(), aFromLine, aFrame, aCount);
|
||||
}
|
||||
void FreeLineBox(nsLineBox* aLine) {
|
||||
aLine->Destroy(PresContext()->PresShell());
|
||||
|
|
|
@ -55,6 +55,11 @@ static PRInt32 ctorCount;
|
|||
PRInt32 nsLineBox::GetCtorCount() { return ctorCount; }
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
// static nsLineBox constant; initialized in the header file.
|
||||
const PRUint32 nsLineBox::kMinChildCountForHashtable;
|
||||
#endif
|
||||
|
||||
nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, bool aIsBlock)
|
||||
: mFirstChild(aFrame),
|
||||
mBounds(0, 0, 0, 0),
|
||||
|
@ -76,7 +81,7 @@ nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, bool aIsBlock)
|
|||
#if NS_STYLE_CLEAR_NONE > 0
|
||||
mFlags.mBreakType = NS_STYLE_CLEAR_NONE;
|
||||
#endif
|
||||
SetChildCount(aCount);
|
||||
mChildCount = aCount;
|
||||
MarkDirty();
|
||||
mFlags.mBlock = aIsBlock;
|
||||
}
|
||||
|
@ -84,14 +89,88 @@ nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, bool aIsBlock)
|
|||
nsLineBox::~nsLineBox()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsLineBox);
|
||||
if (NS_UNLIKELY(mFlags.mHasHashedFrames)) {
|
||||
delete mFrames;
|
||||
}
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
nsLineBox*
|
||||
NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame,
|
||||
PRInt32 aCount, bool aIsBlock)
|
||||
NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame, bool aIsBlock)
|
||||
{
|
||||
return new (aPresShell)nsLineBox(aFrame, aCount, aIsBlock);
|
||||
return new (aPresShell) nsLineBox(aFrame, 1, aIsBlock);
|
||||
}
|
||||
|
||||
nsLineBox*
|
||||
NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine,
|
||||
nsIFrame* aFrame, PRInt32 aCount)
|
||||
{
|
||||
nsLineBox* newLine = new (aPresShell) nsLineBox(aFrame, aCount, false);
|
||||
if (newLine) {
|
||||
newLine->NoteFramesMovedFrom(aFromLine);
|
||||
}
|
||||
return newLine;
|
||||
}
|
||||
|
||||
void
|
||||
nsLineBox::StealHashTableFrom(nsLineBox* aFromLine, PRUint32 aFromLineNewCount)
|
||||
{
|
||||
MOZ_ASSERT(!mFlags.mHasHashedFrames);
|
||||
MOZ_ASSERT(GetChildCount() >= PRInt32(aFromLineNewCount));
|
||||
mFrames = aFromLine->mFrames;
|
||||
mFlags.mHasHashedFrames = 1;
|
||||
aFromLine->mFlags.mHasHashedFrames = 0;
|
||||
aFromLine->mChildCount = aFromLineNewCount;
|
||||
// remove aFromLine's frames that aren't on this line
|
||||
nsIFrame* f = aFromLine->mFirstChild;
|
||||
for (PRUint32 i = 0; i < aFromLineNewCount; f = f->GetNextSibling(), ++i) {
|
||||
mFrames->RemoveEntry(f);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsLineBox::NoteFramesMovedFrom(nsLineBox* aFromLine)
|
||||
{
|
||||
PRUint32 fromCount = aFromLine->GetChildCount();
|
||||
PRUint32 toCount = GetChildCount();
|
||||
MOZ_ASSERT(toCount <= fromCount, "moved more frames than aFromLine has");
|
||||
PRUint32 fromNewCount = fromCount - toCount;
|
||||
if (NS_LIKELY(!aFromLine->mFlags.mHasHashedFrames)) {
|
||||
aFromLine->mChildCount = fromNewCount;
|
||||
MOZ_ASSERT(toCount < kMinChildCountForHashtable);
|
||||
} else if (fromNewCount < kMinChildCountForHashtable) {
|
||||
// aFromLine has a hash table but will not have it after moving the frames
|
||||
// so this line can steal the hash table if it needs it.
|
||||
if (toCount >= kMinChildCountForHashtable) {
|
||||
StealHashTableFrom(aFromLine, fromNewCount);
|
||||
} else {
|
||||
delete aFromLine->mFrames;
|
||||
aFromLine->mFlags.mHasHashedFrames = 0;
|
||||
aFromLine->mChildCount = fromNewCount;
|
||||
}
|
||||
} else {
|
||||
// aFromLine still needs a hash table.
|
||||
if (toCount < kMinChildCountForHashtable) {
|
||||
// remove the moved frames from it
|
||||
nsIFrame* f = mFirstChild;
|
||||
for (PRUint32 i = 0; i < toCount; f = f->GetNextSibling(), ++i) {
|
||||
aFromLine->mFrames->RemoveEntry(f);
|
||||
}
|
||||
} else if (toCount <= fromNewCount) {
|
||||
// This line needs a hash table, allocate a hash table for it since that
|
||||
// means fewer hash ops.
|
||||
nsIFrame* f = mFirstChild;
|
||||
for (PRUint32 i = 0; i < toCount; f = f->GetNextSibling(), ++i) {
|
||||
aFromLine->mFrames->RemoveEntry(f); // toCount RemoveEntry
|
||||
}
|
||||
SwitchToHashtable(); // toCount PutEntry
|
||||
} else {
|
||||
// This line needs a hash table, but it's fewer hash ops to steal
|
||||
// aFromLine's hash table and allocate a new hash table for that line.
|
||||
StealHashTableFrom(aFromLine, fromNewCount); // fromNewCount RemoveEntry
|
||||
aFromLine->SwitchToHashtable(); // fromNewCount PutEntry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Overloaded new operator. Uses an arena (which comes from the presShell)
|
||||
|
@ -102,21 +181,11 @@ nsLineBox::operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW
|
|||
return aPresShell->AllocateMisc(sz);
|
||||
}
|
||||
|
||||
// Overloaded delete operator. Doesn't actually free the memory, because we
|
||||
// use an arena
|
||||
void
|
||||
nsLineBox::operator delete(void* aPtr, size_t sz)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsLineBox::Destroy(nsIPresShell* aPresShell)
|
||||
{
|
||||
// Destroy the object. This won't actually free the memory, though
|
||||
delete this;
|
||||
|
||||
// Have the pres shell recycle the memory
|
||||
aPresShell->FreeMisc(sizeof(*this), (void*)this);
|
||||
this->nsLineBox::~nsLineBox();
|
||||
aPresShell->FreeMisc(sizeof(*this), this);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -365,10 +434,18 @@ nsLineBox::RFindLineContaining(nsIFrame* aFrame,
|
|||
PRInt32* aFrameIndexInLine)
|
||||
{
|
||||
NS_PRECONDITION(aFrame, "null ptr");
|
||||
|
||||
nsIFrame* curFrame = aLastFrameBeforeEnd;
|
||||
while (aBegin != aEnd) {
|
||||
--aEnd;
|
||||
NS_ASSERTION(aEnd->LastChild() == curFrame, "Unexpected curFrame");
|
||||
if (NS_UNLIKELY(aEnd->mFlags.mHasHashedFrames) &&
|
||||
!aEnd->Contains(aFrame)) {
|
||||
if (aEnd->mFirstChild) {
|
||||
curFrame = aEnd->mFirstChild->GetPrevSibling();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// i is the index of curFrame in aEnd
|
||||
PRInt32 i = aEnd->GetChildCount() - 1;
|
||||
while (i >= 0) {
|
||||
|
@ -379,6 +456,7 @@ nsLineBox::RFindLineContaining(nsIFrame* aFrame,
|
|||
--i;
|
||||
curFrame = curFrame->GetPrevSibling();
|
||||
}
|
||||
MOZ_ASSERT(!aEnd->mFlags.mHasHashedFrames, "Contains lied to us!");
|
||||
}
|
||||
*aFrameIndexInLine = -1;
|
||||
return false;
|
||||
|
|
|
@ -182,9 +182,21 @@ protected:
|
|||
need to rearrange the mBits bitfield;
|
||||
#endif
|
||||
|
||||
// Funtion to create a line box
|
||||
/**
|
||||
* Function to create a line box and initialize it with a single frame.
|
||||
* If the frame was moved from another line then you're responsible
|
||||
* for notifying that line using NoteFrameRemoved(). Alternatively,
|
||||
* it's better to use the next function that does that for you in an
|
||||
* optimal way.
|
||||
*/
|
||||
nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame,
|
||||
PRInt32 aCount, bool aIsBlock);
|
||||
bool aIsBlock);
|
||||
/**
|
||||
* Function to create a line box and initialize it with aCount frames
|
||||
* that are currently on aFromLine.
|
||||
*/
|
||||
nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine,
|
||||
nsIFrame* aFrame, PRInt32 aCount);
|
||||
|
||||
class nsLineList;
|
||||
|
||||
|
@ -232,13 +244,14 @@ private:
|
|||
// Overloaded new operator. Uses an arena (which comes from the presShell)
|
||||
// to perform the allocation.
|
||||
void* operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW;
|
||||
void operator delete(void* aPtr, size_t sz);
|
||||
void operator delete(void* aPtr, size_t sz) MOZ_DELETE;
|
||||
|
||||
public:
|
||||
// Use these two functions to allocate and destroy line boxes
|
||||
// Use these functions to allocate and destroy line boxes
|
||||
friend nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame,
|
||||
PRInt32 aCount, bool aIsBlock);
|
||||
|
||||
bool aIsBlock);
|
||||
friend nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine,
|
||||
nsIFrame* aFrame, PRInt32 aCount);
|
||||
void Destroy(nsIPresShell* aPresShell);
|
||||
|
||||
// mBlock bit
|
||||
|
@ -284,7 +297,6 @@ public:
|
|||
|
||||
// mImpactedByFloat bit
|
||||
void SetLineIsImpactedByFloat(bool aValue) {
|
||||
NS_ASSERTION((false==aValue || true==aValue), "somebody is playing fast and loose with bools and bits!");
|
||||
mFlags.mImpactedByFloat = aValue;
|
||||
}
|
||||
bool IsImpactedByFloat() const {
|
||||
|
@ -293,7 +305,6 @@ public:
|
|||
|
||||
// mLineWrapped bit
|
||||
void SetLineWrapped(bool aOn) {
|
||||
NS_ASSERTION((false==aOn || true==aOn), "somebody is playing fast and loose with bools and bits!");
|
||||
mFlags.mLineWrapped = aOn;
|
||||
}
|
||||
bool IsLineWrapped() const {
|
||||
|
@ -302,7 +313,6 @@ public:
|
|||
|
||||
// mInvalidateTextRuns bit
|
||||
void SetInvalidateTextRuns(bool aOn) {
|
||||
NS_ASSERTION((false==aOn || true==aOn), "somebody is playing fast and loose with bools and bits!");
|
||||
mFlags.mInvalidateTextRuns = aOn;
|
||||
}
|
||||
bool GetInvalidateTextRuns() const {
|
||||
|
@ -344,20 +354,76 @@ public:
|
|||
return mFlags.mHadFloatPushed;
|
||||
}
|
||||
|
||||
private:
|
||||
// Add a hash table for fast lookup when the line has more frames than this.
|
||||
static const PRUint32 kMinChildCountForHashtable = 200;
|
||||
|
||||
// mChildCount value
|
||||
PRInt32 GetChildCount() const {
|
||||
return (PRInt32) mFlags.mChildCount;
|
||||
/**
|
||||
* Take ownership of aFromLine's hash table and remove the frames that
|
||||
* stay on aFromLine from it, i.e. aFromLineNewCount frames starting with
|
||||
* mFirstChild. This method is used to optimize moving a large number
|
||||
* of frames from one line to the next.
|
||||
*/
|
||||
void StealHashTableFrom(nsLineBox* aFromLine, PRUint32 aFromLineNewCount);
|
||||
|
||||
/**
|
||||
* Does the equivalent of this->NoteFrameAdded and aFromLine->NoteFrameRemoved
|
||||
* for each frame on this line, but in a optimized way.
|
||||
*/
|
||||
void NoteFramesMovedFrom(nsLineBox* aFromLine);
|
||||
|
||||
void SwitchToHashtable()
|
||||
{
|
||||
MOZ_ASSERT(!mFlags.mHasHashedFrames);
|
||||
PRUint32 count = GetChildCount();
|
||||
mFrames = new nsTHashtable< nsPtrHashKey<nsIFrame> >();
|
||||
mFlags.mHasHashedFrames = 1;
|
||||
PRUint32 minSize =
|
||||
NS_MAX(kMinChildCountForHashtable, PRUint32(PL_DHASH_MIN_SIZE));
|
||||
mFrames->Init(NS_MAX(count, minSize));
|
||||
for (nsIFrame* f = mFirstChild; count-- > 0; f = f->GetNextSibling()) {
|
||||
mFrames->PutEntry(f);
|
||||
}
|
||||
}
|
||||
void SetChildCount(PRInt32 aNewCount) {
|
||||
if (aNewCount < 0) {
|
||||
NS_WARNING("negative child count");
|
||||
aNewCount = 0;
|
||||
void SwitchToCounter() {
|
||||
MOZ_ASSERT(mFlags.mHasHashedFrames);
|
||||
PRUint32 count = GetChildCount();
|
||||
delete mFrames;
|
||||
mFlags.mHasHashedFrames = 0;
|
||||
mChildCount = count;
|
||||
}
|
||||
|
||||
public:
|
||||
PRInt32 GetChildCount() const {
|
||||
return NS_UNLIKELY(mFlags.mHasHashedFrames) ? mFrames->Count() : mChildCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register that aFrame is now on this line.
|
||||
*/
|
||||
void NoteFrameAdded(nsIFrame* aFrame) {
|
||||
if (NS_UNLIKELY(mFlags.mHasHashedFrames)) {
|
||||
mFrames->PutEntry(aFrame);
|
||||
} else {
|
||||
if (++mChildCount >= kMinChildCountForHashtable) {
|
||||
SwitchToHashtable();
|
||||
}
|
||||
}
|
||||
if (aNewCount > LINE_MAX_CHILD_COUNT) {
|
||||
aNewCount = LINE_MAX_CHILD_COUNT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register that aFrame is not on this line anymore.
|
||||
*/
|
||||
void NoteFrameRemoved(nsIFrame* aFrame) {
|
||||
MOZ_ASSERT(GetChildCount() > 0);
|
||||
if (NS_UNLIKELY(mFlags.mHasHashedFrames)) {
|
||||
mFrames->RemoveEntry(aFrame);
|
||||
if (mFrames->Count() < kMinChildCountForHashtable) {
|
||||
SwitchToCounter();
|
||||
}
|
||||
} else {
|
||||
--mChildCount;
|
||||
}
|
||||
mFlags.mChildCount = aNewCount;
|
||||
}
|
||||
|
||||
// mBreakType value
|
||||
|
@ -473,10 +539,13 @@ public:
|
|||
nsIFrame* LastChild() const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
PRInt32 IndexOf(nsIFrame* aFrame) const;
|
||||
public:
|
||||
|
||||
bool Contains(nsIFrame* aFrame) const {
|
||||
return IndexOf(aFrame) >= 0;
|
||||
return NS_UNLIKELY(mFlags.mHasHashedFrames) ? mFrames->Contains(aFrame)
|
||||
: IndexOf(aFrame) >= 0;
|
||||
}
|
||||
|
||||
// whether the line box is "logically" empty (just like nsIFrame::IsEmpty)
|
||||
|
@ -504,6 +573,12 @@ public:
|
|||
|
||||
nsRect mBounds;
|
||||
|
||||
// mFlags.mHasHashedFrames says which one to use
|
||||
union {
|
||||
nsTHashtable< nsPtrHashKey<nsIFrame> >* mFrames;
|
||||
PRUint32 mChildCount;
|
||||
};
|
||||
|
||||
struct FlagBits {
|
||||
PRUint32 mDirty : 1;
|
||||
PRUint32 mPreviousMarginDirty : 1;
|
||||
|
@ -521,10 +596,8 @@ public:
|
|||
// Indicates that this line *may* have a placeholder for a float
|
||||
// that was pushed to a later column or page.
|
||||
PRUint32 mHadFloatPushed : 1;
|
||||
PRUint32 mHasHashedFrames: 1;
|
||||
PRUint32 mBreakType : 4;
|
||||
|
||||
// FIXME: Move this out of FlagBits
|
||||
PRUint32 mChildCount;
|
||||
};
|
||||
|
||||
struct ExtraData {
|
||||
|
|
Загрузка…
Ссылка в новой задаче