r=troy; Reworked nsLineBox api to allow for reduced storage overhead; fixed bug 16252 while keeping bug 12709 fixed

This commit is contained in:
kipp%netscape.com 1999-10-14 23:10:03 +00:00
Родитель 27ff1e76cb
Коммит ab0a40b009
10 изменённых файлов: 2290 добавлений и 2000 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -30,25 +30,37 @@
MOZ_DECL_CTOR_COUNTER(nsLineBox); MOZ_DECL_CTOR_COUNTER(nsLineBox);
nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock) nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock)
: mFirstChild(aFrame),
mNext(nsnull),
mBounds(0, 0, 0, 0),
mMaxElementWidth(0),
mData(nsnull)
{ {
MOZ_COUNT_CTOR(nsLineBox); MOZ_COUNT_CTOR(nsLineBox);
mFirstChild = aFrame;
mChildCount = aCount;
mAllFlags = 0; mAllFlags = 0;
MarkDirty(); #if NS_STYLE_CLEAR_NONE > 0
SetIsBlock(aIsBlock);
mNext = nsnull;
mBounds.SetRect(0,0,0,0);
mCombinedArea.SetRect(0,0,0,0);
//XXX mCarriedOutTopMargin = 0;
mCarriedOutBottomMargin = 0;
mFlags.mBreakType = NS_STYLE_CLEAR_NONE; mFlags.mBreakType = NS_STYLE_CLEAR_NONE;
mMaxElementWidth = 0; #endif
SetChildCount(aCount);
MarkDirty();
mFlags.mBlock = aIsBlock;
} }
nsLineBox::~nsLineBox() nsLineBox::~nsLineBox()
{ {
MOZ_COUNT_DTOR(nsLineBox); MOZ_COUNT_DTOR(nsLineBox);
if (IsBlock()) {
if (mBlockData) {
delete mBlockData;
}
}
else {
if (mInlineData) {
delete mInlineData;
}
}
} }
static void static void
@ -82,9 +94,11 @@ ListFloaters(FILE* out, PRInt32 aIndent, const nsFloaterCacheList& aFloaters)
char* char*
nsLineBox::StateToString(char* aBuf, PRInt32 aBufSize) const nsLineBox::StateToString(char* aBuf, PRInt32 aBufSize) const
{ {
PR_snprintf(aBuf, aBufSize, "%s,%s[0x%x]", PR_snprintf(aBuf, aBufSize, "%s,%s,%s,%s[0x%x]",
IsDirty() ? "dirty" : "clean",
IsBlock() ? "block" : "inline", IsBlock() ? "block" : "inline",
IsDirty() ? "dirty" : "",
IsImpactedByFloater() ? "impacted" : "",
IsTrimmed() ? "trimmed" : "",
mAllFlags); mAllFlags);
return aBuf; return aBuf;
} }
@ -97,30 +111,33 @@ nsLineBox::List(FILE* out, PRInt32 aIndent) const
for (i = aIndent; --i >= 0; ) fputs(" ", out); for (i = aIndent; --i >= 0; ) fputs(" ", out);
char cbuf[100]; char cbuf[100];
fprintf(out, "line %p: count=%d state=%s ", fprintf(out, "line %p: count=%d state=%s ",
this, ChildCount(), StateToString(cbuf, sizeof(cbuf))); this, GetChildCount(), StateToString(cbuf, sizeof(cbuf)));
if (0 != mCarriedOutBottomMargin) { if (0 != GetCarriedOutBottomMargin()) {
fprintf(out, "bm=%d ", mCarriedOutBottomMargin); fprintf(out, "bm=%d ", GetCarriedOutBottomMargin());
} }
if (0 != mMaxElementWidth) { if (0 != mMaxElementWidth) {
fprintf(out, "mew=%d ", mMaxElementWidth); fprintf(out, "mew=%d ", mMaxElementWidth);
} }
fprintf(out, "{%d,%d,%d,%d} ca={%d,%d,%d,%d}", fprintf(out, "{%d,%d,%d,%d} ",
mBounds.x, mBounds.y, mBounds.width, mBounds.height, mBounds.x, mBounds.y, mBounds.width, mBounds.height);
mCombinedArea.x, mCombinedArea.y, if (mData) {
mCombinedArea.width, mCombinedArea.height); fprintf(out, "ca={%d,%d,%d,%d} ",
fprintf(out, " <\n"); mData->mCombinedArea.x, mData->mCombinedArea.y,
mData->mCombinedArea.width, mData->mCombinedArea.height);
}
fprintf(out, "<\n");
nsIFrame* frame = mFirstChild; nsIFrame* frame = mFirstChild;
PRInt32 n = ChildCount(); PRInt32 n = GetChildCount();
while (--n >= 0) { while (--n >= 0) {
frame->List(out, aIndent + 1); frame->List(out, aIndent + 1);
frame->GetNextSibling(&frame); frame->GetNextSibling(&frame);
} }
for (i = aIndent; --i >= 0; ) fputs(" ", out); for (i = aIndent; --i >= 0; ) fputs(" ", out);
if (mFloaters.NotEmpty()) { if (HasFloaters()) {
fputs("> floaters <\n", out); fputs("> floaters <\n", out);
ListFloaters(out, aIndent + 1, mFloaters); ListFloaters(out, aIndent + 1, mInlineData->mFloaters);
for (i = aIndent; --i >= 0; ) fputs(" ", out); for (i = aIndent; --i >= 0; ) fputs(" ", out);
} }
fputs(">\n", out); fputs(">\n", out);
@ -130,7 +147,7 @@ nsIFrame*
nsLineBox::LastChild() const nsLineBox::LastChild() const
{ {
nsIFrame* frame = mFirstChild; nsIFrame* frame = mFirstChild;
PRInt32 n = ChildCount() - 1; PRInt32 n = GetChildCount() - 1;
while (--n >= 0) { while (--n >= 0) {
frame->GetNextSibling(&frame); frame->GetNextSibling(&frame);
} }
@ -147,7 +164,7 @@ nsLineBox::IsLastChild(nsIFrame* aFrame) const
PRInt32 PRInt32
nsLineBox::IndexOf(nsIFrame* aFrame) const nsLineBox::IndexOf(nsIFrame* aFrame) const
{ {
PRInt32 i, n = ChildCount(); PRInt32 i, n = GetChildCount();
nsIFrame* frame = mFirstChild; nsIFrame* frame = mFirstChild;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (frame == aFrame) { if (frame == aFrame) {
@ -208,39 +225,172 @@ nsLineBox::FindLineContaining(nsLineBox* aLine, nsIFrame* aFrame,
return nsnull; return nsnull;
} }
#ifdef NS_DEBUG nscoord
PRBool nsLineBox::GetCarriedOutBottomMargin() const
nsLineBox::CheckIsBlock() const
{ {
PRBool isBlock = nsLineLayout::TreatFrameAsBlock(mFirstChild); return (IsBlock() && mBlockData) ? mBlockData->mCarriedOutBottomMargin : 0;
return isBlock == IsBlock(); }
void
nsLineBox::SetCarriedOutBottomMargin(nscoord aValue)
{
if (IsBlock()) {
if (aValue) {
if (!mBlockData) {
mBlockData = new ExtraBlockData(mBounds);
}
if (mBlockData) {
mBlockData->mCarriedOutBottomMargin = aValue;
}
}
else if (mBlockData) {
mBlockData->mCarriedOutBottomMargin = aValue;
MaybeFreeData();
}
}
}
void
nsLineBox::MaybeFreeData()
{
if (mData && (mData->mCombinedArea == mBounds)) {
if (IsInline()) {
if (mInlineData->mFloaters.IsEmpty()) {
delete mInlineData;
mInlineData = nsnull;
}
}
else if (0 == mBlockData->mCarriedOutBottomMargin) {
delete mBlockData;
mBlockData = nsnull;
}
}
}
// XXX get rid of this???
nsFloaterCache*
nsLineBox::GetFirstFloater()
{
if (NS_WARN_IF_FALSE(IsInline(), "block line can't have floaters")) {
return nsnull;
}
return mInlineData ? mInlineData->mFloaters.Head() : nsnull;
}
// XXX this might be too eager to free memory
void
nsLineBox::FreeFloaters(nsFloaterCacheFreeList& aFreeList)
{
NS_WARN_IF_FALSE(IsInline(), "block line can't have floaters");
if (IsInline()) {
if (mInlineData) {
aFreeList.Append(mInlineData->mFloaters);
MaybeFreeData();
}
}
}
void
nsLineBox::AppendFloaters(nsFloaterCacheFreeList& aFreeList)
{
NS_WARN_IF_FALSE(IsInline(), "block line can't have floaters");
if (IsInline()) {
if (aFreeList.NotEmpty()) {
if (!mInlineData) {
mInlineData = new ExtraInlineData(mBounds);
}
if (mInlineData) {
mInlineData->mFloaters.Append(aFreeList);
}
}
}
}
PRBool
nsLineBox::RemoveFloater(nsIFrame* aFrame)
{
NS_WARN_IF_FALSE(IsInline(), "block line can't have floaters");
if (IsInline() && mInlineData) {
nsFloaterCache* fc = mInlineData->mFloaters.Find(aFrame);
if (fc) {
// Note: the placeholder is part of the line's child list
// and will be removed later.
fc->mPlaceholder->SetOutOfFlowFrame(nsnull);
mInlineData->mFloaters.Remove(fc);
MaybeFreeData();
}
}
return PR_FALSE;
}
void
nsLineBox::SetCombinedArea(const nsRect& aCombinedArea)
{
if (aCombinedArea != mBounds) {
if (mData) {
mData->mCombinedArea = aCombinedArea;
}
else {
if (IsInline()) {
mInlineData = new ExtraInlineData(aCombinedArea);
}
else {
mBlockData = new ExtraBlockData(aCombinedArea);
}
}
}
else {
if (mData) {
// Store away new value so that MaybeFreeData compares against
// the right value.
mData->mCombinedArea = aCombinedArea;
}
MaybeFreeData();
}
}
void
nsLineBox::GetCombinedArea(nsRect* aResult)
{
if (aResult) {
*aResult = mData ? mData->mCombinedArea : mBounds;
}
} }
#endif
#ifdef DEBUG #ifdef DEBUG
PRBool nsIAtom*
nsLineBox::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const nsLineBox::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const
{ {
NS_PRECONDITION(aResult, "null OUT parameter pointer"); NS_PRECONDITION(aResult, "null OUT parameter pointer");
*aResult = sizeof(*this); *aResult = sizeof(*this);
PRBool big = PR_TRUE; nsIAtom* atom;
if ((IsBlock() || mFloaters.IsEmpty()) && if (IsBlock()) {
(mBounds == mCombinedArea)) { atom = nsLayoutAtoms::lineBoxBlockSmall;
big = PR_FALSE; if (mBlockData) {
atom = nsLayoutAtoms::lineBoxBlockBig;
*aResult += sizeof(*mBlockData);
} }
}
else {
atom = nsLayoutAtoms::lineBoxSmall;
if (mInlineData) {
atom = nsLayoutAtoms::lineBoxBig;
*aResult += sizeof(*mInlineData);
// Add in the size needed for floaters associated with this line // Add in the size needed for floaters associated with this line
if (mFloaters.NotEmpty()) { if (HasFloaters()) {
PRUint32 floatersSize; PRUint32 floatersSize;
mInlineData->mFloaters.SizeOf(aHandler, &floatersSize);
mFloaters.SizeOf(aHandler, &floatersSize);
// Base size of embedded object was included in sizeof(*this) above // Base size of embedded object was included in sizeof(*this) above
floatersSize -= sizeof(mFloaters); floatersSize -= sizeof(mInlineData->mFloaters);
aHandler->AddSize(nsLayoutAtoms::lineBoxFloaters, floatersSize); aHandler->AddSize(nsLayoutAtoms::lineBoxFloaters, floatersSize);
} }
}
}
return big; return atom;
} }
#endif #endif
@ -346,7 +496,7 @@ nsLineIterator::GetLine(PRInt32 aLineNumber,
} }
nsLineBox* line = mLines[aLineNumber]; nsLineBox* line = mLines[aLineNumber];
*aFirstFrameOnLine = line->mFirstChild; *aFirstFrameOnLine = line->mFirstChild;
*aNumFramesOnLine = line->mChildCount; *aNumFramesOnLine = line->GetChildCount();
aLineBounds = line->mBounds; aLineBounds = line->mBounds;
PRUint32 flags = 0; PRUint32 flags = 0;
@ -462,7 +612,7 @@ nsLineIterator::FindFrameAt(PRInt32 aLineNumber,
*aXIsAfterLastFrame = PR_FALSE; *aXIsAfterLastFrame = PR_FALSE;
nsRect r1, r2; nsRect r1, r2;
nsIFrame* frame = line->mFirstChild; nsIFrame* frame = line->mFirstChild;
PRInt32 n = line->mChildCount; PRInt32 n = line->GetChildCount();
if (mRightToLeft) { if (mRightToLeft) {
while (--n >= 0) { while (--n >= 0) {
nsIFrame* nextFrame; nsIFrame* nextFrame;
@ -528,6 +678,7 @@ nsFloaterCacheList::~nsFloaterCacheList()
delete floater; delete floater;
floater = next; floater = next;
} }
mHead = nsnull;
} }
nsFloaterCache* nsFloaterCache*

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

@ -26,9 +26,6 @@
class nsISpaceManager; class nsISpaceManager;
class nsLineBox; class nsLineBox;
//----------------------------------------------------------------------
class nsFloaterCache; class nsFloaterCache;
class nsFloaterCacheList; class nsFloaterCacheList;
class nsFloaterCacheFreeList; class nsFloaterCacheFreeList;
@ -135,6 +132,13 @@ protected:
//---------------------------------------------------------------------- //----------------------------------------------------------------------
#define LINE_MAX_BREAK_TYPE ((1 << 4) - 1)
#define LINE_MAX_CHILD_COUNT ((1 << 24) - 1)
#if NS_STYLE_CLEAR_LAST_VALUE > 15
need to rearrange the mBits bitfield;
#endif
/** /**
* The nsLineBox class represents a horizontal line of frames. It contains * The nsLineBox class represents a horizontal line of frames. It contains
* enough state to support incremental reflow of the frames, event handling * enough state to support incremental reflow of the frames, event handling
@ -145,44 +149,96 @@ public:
nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock); nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock);
~nsLineBox(); ~nsLineBox();
// mBlock bit
PRBool IsBlock() const { PRBool IsBlock() const {
return mFlags.mBlock; return mFlags.mBlock;
} }
PRBool IsInline() const { PRBool IsInline() const {
return 0 == mFlags.mBlock; return 0 == mFlags.mBlock;
} }
// XXX Turn into a bit-field to simplify this code // mDirty bit
void MarkDirty() {
mFlags.mDirty = 1;
}
void ClearDirty() {
mFlags.mDirty = 0;
}
PRBool IsDirty() const {
return mFlags.mDirty;
}
// mImpactedByFloater bit
void SetLineIsImpactedByFloater(PRBool aValue) {
mFlags.mImpactedByFloater = aValue;
}
PRBool IsImpactedByFloater() const {
return mFlags.mImpactedByFloater;
}
// mTrimmed bit
void SetTrimmed(PRBool aOn) { void SetTrimmed(PRBool aOn) {
mFlags.mTrimmed = aOn; mFlags.mTrimmed = aOn;
} }
PRBool IsTrimmed() const { PRBool IsTrimmed() const {
return mFlags.mTrimmed; return mFlags.mTrimmed;
} }
// mChildCount value
PRInt32 GetChildCount() const {
return (PRInt32) mFlags.mChildCount;
}
void SetChildCount(PRInt32 aNewCount) {
if (NS_WARN_IF_FALSE(aNewCount >= 0, "negative child count")) {
aNewCount = 0;
}
if (aNewCount > LINE_MAX_CHILD_COUNT) {
aNewCount = LINE_MAX_CHILD_COUNT;
}
mFlags.mChildCount = aNewCount;
}
// mBreakType value
PRBool HasBreak() const { PRBool HasBreak() const {
return NS_STYLE_CLEAR_NONE != mFlags.mBreakType; return NS_STYLE_CLEAR_NONE != mFlags.mBreakType;
} }
void SetBreakType(PRUint8 aBreakType) { void SetBreakType(PRUint8 aBreakType) {
NS_WARN_IF_FALSE(aBreakType <= LINE_MAX_BREAK_TYPE, "bad break type");
mFlags.mBreakType = aBreakType; mFlags.mBreakType = aBreakType;
} }
PRUint8 GetBreakType() const { PRUint8 GetBreakType() const {
return mFlags.mBreakType; return mFlags.mBreakType;
} }
nscoord GetCarriedOutBottomMargin() const { // mCarriedOutBottomMargin value
return mCarriedOutBottomMargin; nscoord GetCarriedOutBottomMargin() const;
void SetCarriedOutBottomMargin(nscoord aValue);
// mFloaters
PRBool HasFloaters() const {
return (IsInline() && mInlineData) && mInlineData->mFloaters.NotEmpty();
}
nsFloaterCache* GetFirstFloater();
void FreeFloaters(nsFloaterCacheFreeList& aFreeList);
void AppendFloaters(nsFloaterCacheFreeList& aFreeList);
PRBool RemoveFloater(nsIFrame* aFrame);
void SetCombinedArea(const nsRect& aCombinedArea);
void GetCombinedArea(nsRect* aResult);
void SlideBy(nscoord aDY) {
mBounds.y += aDY;
if (mData) {
mData->mCombinedArea.y += aDY;
}
} }
nscoord GetHeight() const { return mBounds.height; } //----------------------------------------
//----------------------------------------------------------------------
// XXX old junk
nscoord GetHeight() const {
return mBounds.height;
}
static void DeleteLineList(nsIPresContext& aPresContext, nsLineBox* aLine); static void DeleteLineList(nsIPresContext& aPresContext, nsLineBox* aLine);
@ -193,38 +249,10 @@ public:
void List(FILE* out, PRInt32 aIndent) const; void List(FILE* out, PRInt32 aIndent) const;
PRInt32 ChildCount() const {
return PRInt32(mChildCount);
}
nsIFrame* LastChild() const; nsIFrame* LastChild() const;
PRBool IsLastChild(nsIFrame* aFrame) const; PRBool IsLastChild(nsIFrame* aFrame) const;
void SetIsBlock(PRBool aValue) {
mFlags.mBlock = aValue;
}
void SetLineIsImpactedByFloater(PRBool aValue) {
mFlags.mImpactedByFloater = aValue;
}
PRBool IsImpactedByFloater() const {
return mFlags.mImpactedByFloater;
}
void MarkDirty() {
mFlags.mDirty = 1;
}
void ClearDirty() {
mFlags.mDirty = 0;
}
PRBool IsDirty() const {
return mFlags.mDirty;
}
char* StateToString(char* aBuf, PRInt32 aBufSize) const; char* StateToString(char* aBuf, PRInt32 aBufSize) const;
PRInt32 IndexOf(nsIFrame* aFrame) const; PRInt32 IndexOf(nsIFrame* aFrame) const;
@ -233,21 +261,14 @@ public:
return IndexOf(aFrame) >= 0; return IndexOf(aFrame) >= 0;
} }
#ifdef NS_DEBUG
PRBool CheckIsBlock() const;
#endif
#ifdef DEBUG #ifdef DEBUG
PRBool SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; nsIAtom* SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
#endif #endif
nsIFrame* mFirstChild; nsIFrame* mFirstChild;
PRUint16 mChildCount;
nsRect mBounds;
nsRect mCombinedArea;
nscoord mCarriedOutBottomMargin;/* XXX switch to 16 bits */
nsFloaterCacheList mFloaters;
nsLineBox* mNext; nsLineBox* mNext;
nsRect mBounds;
nscoord mMaxElementWidth; // width part of max-element-size nscoord mMaxElementWidth; // width part of max-element-size
struct FlagBits { struct FlagBits {
@ -256,9 +277,28 @@ public:
PRUint32 mImpactedByFloater : 1; PRUint32 mImpactedByFloater : 1;
PRUint32 mTrimmed : 1; PRUint32 mTrimmed : 1;
PRUint32 reserved : 20; PRUint32 mBreakType : 4;
PRUint32 mBreakType : 8; PRUint32 mChildCount : 24;
};
struct ExtraData {
ExtraData(const nsRect& aBounds) : mCombinedArea(aBounds) {
}
nsRect mCombinedArea;
};
struct ExtraBlockData : public ExtraData {
ExtraBlockData(const nsRect& aBounds) : ExtraData(aBounds) {
mCarriedOutBottomMargin = 0;
}
nscoord mCarriedOutBottomMargin;
};
struct ExtraInlineData : public ExtraData {
ExtraInlineData(const nsRect& aBounds) : ExtraData(aBounds) {
}
nsFloaterCacheList mFloaters;
}; };
protected: protected:
@ -266,6 +306,14 @@ protected:
PRUint32 mAllFlags; PRUint32 mAllFlags;
FlagBits mFlags; FlagBits mFlags;
}; };
union {
ExtraData* mData;
ExtraBlockData* mBlockData;
ExtraInlineData* mInlineData;
};
void MaybeFreeData();
}; };
//---------------------------------------------------------------------- //----------------------------------------------------------------------

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -30,25 +30,37 @@
MOZ_DECL_CTOR_COUNTER(nsLineBox); MOZ_DECL_CTOR_COUNTER(nsLineBox);
nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock) nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock)
: mFirstChild(aFrame),
mNext(nsnull),
mBounds(0, 0, 0, 0),
mMaxElementWidth(0),
mData(nsnull)
{ {
MOZ_COUNT_CTOR(nsLineBox); MOZ_COUNT_CTOR(nsLineBox);
mFirstChild = aFrame;
mChildCount = aCount;
mAllFlags = 0; mAllFlags = 0;
MarkDirty(); #if NS_STYLE_CLEAR_NONE > 0
SetIsBlock(aIsBlock);
mNext = nsnull;
mBounds.SetRect(0,0,0,0);
mCombinedArea.SetRect(0,0,0,0);
//XXX mCarriedOutTopMargin = 0;
mCarriedOutBottomMargin = 0;
mFlags.mBreakType = NS_STYLE_CLEAR_NONE; mFlags.mBreakType = NS_STYLE_CLEAR_NONE;
mMaxElementWidth = 0; #endif
SetChildCount(aCount);
MarkDirty();
mFlags.mBlock = aIsBlock;
} }
nsLineBox::~nsLineBox() nsLineBox::~nsLineBox()
{ {
MOZ_COUNT_DTOR(nsLineBox); MOZ_COUNT_DTOR(nsLineBox);
if (IsBlock()) {
if (mBlockData) {
delete mBlockData;
}
}
else {
if (mInlineData) {
delete mInlineData;
}
}
} }
static void static void
@ -82,9 +94,11 @@ ListFloaters(FILE* out, PRInt32 aIndent, const nsFloaterCacheList& aFloaters)
char* char*
nsLineBox::StateToString(char* aBuf, PRInt32 aBufSize) const nsLineBox::StateToString(char* aBuf, PRInt32 aBufSize) const
{ {
PR_snprintf(aBuf, aBufSize, "%s,%s[0x%x]", PR_snprintf(aBuf, aBufSize, "%s,%s,%s,%s[0x%x]",
IsDirty() ? "dirty" : "clean",
IsBlock() ? "block" : "inline", IsBlock() ? "block" : "inline",
IsDirty() ? "dirty" : "",
IsImpactedByFloater() ? "impacted" : "",
IsTrimmed() ? "trimmed" : "",
mAllFlags); mAllFlags);
return aBuf; return aBuf;
} }
@ -97,30 +111,33 @@ nsLineBox::List(FILE* out, PRInt32 aIndent) const
for (i = aIndent; --i >= 0; ) fputs(" ", out); for (i = aIndent; --i >= 0; ) fputs(" ", out);
char cbuf[100]; char cbuf[100];
fprintf(out, "line %p: count=%d state=%s ", fprintf(out, "line %p: count=%d state=%s ",
this, ChildCount(), StateToString(cbuf, sizeof(cbuf))); this, GetChildCount(), StateToString(cbuf, sizeof(cbuf)));
if (0 != mCarriedOutBottomMargin) { if (0 != GetCarriedOutBottomMargin()) {
fprintf(out, "bm=%d ", mCarriedOutBottomMargin); fprintf(out, "bm=%d ", GetCarriedOutBottomMargin());
} }
if (0 != mMaxElementWidth) { if (0 != mMaxElementWidth) {
fprintf(out, "mew=%d ", mMaxElementWidth); fprintf(out, "mew=%d ", mMaxElementWidth);
} }
fprintf(out, "{%d,%d,%d,%d} ca={%d,%d,%d,%d}", fprintf(out, "{%d,%d,%d,%d} ",
mBounds.x, mBounds.y, mBounds.width, mBounds.height, mBounds.x, mBounds.y, mBounds.width, mBounds.height);
mCombinedArea.x, mCombinedArea.y, if (mData) {
mCombinedArea.width, mCombinedArea.height); fprintf(out, "ca={%d,%d,%d,%d} ",
fprintf(out, " <\n"); mData->mCombinedArea.x, mData->mCombinedArea.y,
mData->mCombinedArea.width, mData->mCombinedArea.height);
}
fprintf(out, "<\n");
nsIFrame* frame = mFirstChild; nsIFrame* frame = mFirstChild;
PRInt32 n = ChildCount(); PRInt32 n = GetChildCount();
while (--n >= 0) { while (--n >= 0) {
frame->List(out, aIndent + 1); frame->List(out, aIndent + 1);
frame->GetNextSibling(&frame); frame->GetNextSibling(&frame);
} }
for (i = aIndent; --i >= 0; ) fputs(" ", out); for (i = aIndent; --i >= 0; ) fputs(" ", out);
if (mFloaters.NotEmpty()) { if (HasFloaters()) {
fputs("> floaters <\n", out); fputs("> floaters <\n", out);
ListFloaters(out, aIndent + 1, mFloaters); ListFloaters(out, aIndent + 1, mInlineData->mFloaters);
for (i = aIndent; --i >= 0; ) fputs(" ", out); for (i = aIndent; --i >= 0; ) fputs(" ", out);
} }
fputs(">\n", out); fputs(">\n", out);
@ -130,7 +147,7 @@ nsIFrame*
nsLineBox::LastChild() const nsLineBox::LastChild() const
{ {
nsIFrame* frame = mFirstChild; nsIFrame* frame = mFirstChild;
PRInt32 n = ChildCount() - 1; PRInt32 n = GetChildCount() - 1;
while (--n >= 0) { while (--n >= 0) {
frame->GetNextSibling(&frame); frame->GetNextSibling(&frame);
} }
@ -147,7 +164,7 @@ nsLineBox::IsLastChild(nsIFrame* aFrame) const
PRInt32 PRInt32
nsLineBox::IndexOf(nsIFrame* aFrame) const nsLineBox::IndexOf(nsIFrame* aFrame) const
{ {
PRInt32 i, n = ChildCount(); PRInt32 i, n = GetChildCount();
nsIFrame* frame = mFirstChild; nsIFrame* frame = mFirstChild;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (frame == aFrame) { if (frame == aFrame) {
@ -208,39 +225,172 @@ nsLineBox::FindLineContaining(nsLineBox* aLine, nsIFrame* aFrame,
return nsnull; return nsnull;
} }
#ifdef NS_DEBUG nscoord
PRBool nsLineBox::GetCarriedOutBottomMargin() const
nsLineBox::CheckIsBlock() const
{ {
PRBool isBlock = nsLineLayout::TreatFrameAsBlock(mFirstChild); return (IsBlock() && mBlockData) ? mBlockData->mCarriedOutBottomMargin : 0;
return isBlock == IsBlock(); }
void
nsLineBox::SetCarriedOutBottomMargin(nscoord aValue)
{
if (IsBlock()) {
if (aValue) {
if (!mBlockData) {
mBlockData = new ExtraBlockData(mBounds);
}
if (mBlockData) {
mBlockData->mCarriedOutBottomMargin = aValue;
}
}
else if (mBlockData) {
mBlockData->mCarriedOutBottomMargin = aValue;
MaybeFreeData();
}
}
}
void
nsLineBox::MaybeFreeData()
{
if (mData && (mData->mCombinedArea == mBounds)) {
if (IsInline()) {
if (mInlineData->mFloaters.IsEmpty()) {
delete mInlineData;
mInlineData = nsnull;
}
}
else if (0 == mBlockData->mCarriedOutBottomMargin) {
delete mBlockData;
mBlockData = nsnull;
}
}
}
// XXX get rid of this???
nsFloaterCache*
nsLineBox::GetFirstFloater()
{
if (NS_WARN_IF_FALSE(IsInline(), "block line can't have floaters")) {
return nsnull;
}
return mInlineData ? mInlineData->mFloaters.Head() : nsnull;
}
// XXX this might be too eager to free memory
void
nsLineBox::FreeFloaters(nsFloaterCacheFreeList& aFreeList)
{
NS_WARN_IF_FALSE(IsInline(), "block line can't have floaters");
if (IsInline()) {
if (mInlineData) {
aFreeList.Append(mInlineData->mFloaters);
MaybeFreeData();
}
}
}
void
nsLineBox::AppendFloaters(nsFloaterCacheFreeList& aFreeList)
{
NS_WARN_IF_FALSE(IsInline(), "block line can't have floaters");
if (IsInline()) {
if (aFreeList.NotEmpty()) {
if (!mInlineData) {
mInlineData = new ExtraInlineData(mBounds);
}
if (mInlineData) {
mInlineData->mFloaters.Append(aFreeList);
}
}
}
}
PRBool
nsLineBox::RemoveFloater(nsIFrame* aFrame)
{
NS_WARN_IF_FALSE(IsInline(), "block line can't have floaters");
if (IsInline() && mInlineData) {
nsFloaterCache* fc = mInlineData->mFloaters.Find(aFrame);
if (fc) {
// Note: the placeholder is part of the line's child list
// and will be removed later.
fc->mPlaceholder->SetOutOfFlowFrame(nsnull);
mInlineData->mFloaters.Remove(fc);
MaybeFreeData();
}
}
return PR_FALSE;
}
void
nsLineBox::SetCombinedArea(const nsRect& aCombinedArea)
{
if (aCombinedArea != mBounds) {
if (mData) {
mData->mCombinedArea = aCombinedArea;
}
else {
if (IsInline()) {
mInlineData = new ExtraInlineData(aCombinedArea);
}
else {
mBlockData = new ExtraBlockData(aCombinedArea);
}
}
}
else {
if (mData) {
// Store away new value so that MaybeFreeData compares against
// the right value.
mData->mCombinedArea = aCombinedArea;
}
MaybeFreeData();
}
}
void
nsLineBox::GetCombinedArea(nsRect* aResult)
{
if (aResult) {
*aResult = mData ? mData->mCombinedArea : mBounds;
}
} }
#endif
#ifdef DEBUG #ifdef DEBUG
PRBool nsIAtom*
nsLineBox::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const nsLineBox::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const
{ {
NS_PRECONDITION(aResult, "null OUT parameter pointer"); NS_PRECONDITION(aResult, "null OUT parameter pointer");
*aResult = sizeof(*this); *aResult = sizeof(*this);
PRBool big = PR_TRUE; nsIAtom* atom;
if ((IsBlock() || mFloaters.IsEmpty()) && if (IsBlock()) {
(mBounds == mCombinedArea)) { atom = nsLayoutAtoms::lineBoxBlockSmall;
big = PR_FALSE; if (mBlockData) {
atom = nsLayoutAtoms::lineBoxBlockBig;
*aResult += sizeof(*mBlockData);
} }
}
else {
atom = nsLayoutAtoms::lineBoxSmall;
if (mInlineData) {
atom = nsLayoutAtoms::lineBoxBig;
*aResult += sizeof(*mInlineData);
// Add in the size needed for floaters associated with this line // Add in the size needed for floaters associated with this line
if (mFloaters.NotEmpty()) { if (HasFloaters()) {
PRUint32 floatersSize; PRUint32 floatersSize;
mInlineData->mFloaters.SizeOf(aHandler, &floatersSize);
mFloaters.SizeOf(aHandler, &floatersSize);
// Base size of embedded object was included in sizeof(*this) above // Base size of embedded object was included in sizeof(*this) above
floatersSize -= sizeof(mFloaters); floatersSize -= sizeof(mInlineData->mFloaters);
aHandler->AddSize(nsLayoutAtoms::lineBoxFloaters, floatersSize); aHandler->AddSize(nsLayoutAtoms::lineBoxFloaters, floatersSize);
} }
}
}
return big; return atom;
} }
#endif #endif
@ -346,7 +496,7 @@ nsLineIterator::GetLine(PRInt32 aLineNumber,
} }
nsLineBox* line = mLines[aLineNumber]; nsLineBox* line = mLines[aLineNumber];
*aFirstFrameOnLine = line->mFirstChild; *aFirstFrameOnLine = line->mFirstChild;
*aNumFramesOnLine = line->mChildCount; *aNumFramesOnLine = line->GetChildCount();
aLineBounds = line->mBounds; aLineBounds = line->mBounds;
PRUint32 flags = 0; PRUint32 flags = 0;
@ -462,7 +612,7 @@ nsLineIterator::FindFrameAt(PRInt32 aLineNumber,
*aXIsAfterLastFrame = PR_FALSE; *aXIsAfterLastFrame = PR_FALSE;
nsRect r1, r2; nsRect r1, r2;
nsIFrame* frame = line->mFirstChild; nsIFrame* frame = line->mFirstChild;
PRInt32 n = line->mChildCount; PRInt32 n = line->GetChildCount();
if (mRightToLeft) { if (mRightToLeft) {
while (--n >= 0) { while (--n >= 0) {
nsIFrame* nextFrame; nsIFrame* nextFrame;
@ -528,6 +678,7 @@ nsFloaterCacheList::~nsFloaterCacheList()
delete floater; delete floater;
floater = next; floater = next;
} }
mHead = nsnull;
} }
nsFloaterCache* nsFloaterCache*

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

@ -26,9 +26,6 @@
class nsISpaceManager; class nsISpaceManager;
class nsLineBox; class nsLineBox;
//----------------------------------------------------------------------
class nsFloaterCache; class nsFloaterCache;
class nsFloaterCacheList; class nsFloaterCacheList;
class nsFloaterCacheFreeList; class nsFloaterCacheFreeList;
@ -135,6 +132,13 @@ protected:
//---------------------------------------------------------------------- //----------------------------------------------------------------------
#define LINE_MAX_BREAK_TYPE ((1 << 4) - 1)
#define LINE_MAX_CHILD_COUNT ((1 << 24) - 1)
#if NS_STYLE_CLEAR_LAST_VALUE > 15
need to rearrange the mBits bitfield;
#endif
/** /**
* The nsLineBox class represents a horizontal line of frames. It contains * The nsLineBox class represents a horizontal line of frames. It contains
* enough state to support incremental reflow of the frames, event handling * enough state to support incremental reflow of the frames, event handling
@ -145,44 +149,96 @@ public:
nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock); nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock);
~nsLineBox(); ~nsLineBox();
// mBlock bit
PRBool IsBlock() const { PRBool IsBlock() const {
return mFlags.mBlock; return mFlags.mBlock;
} }
PRBool IsInline() const { PRBool IsInline() const {
return 0 == mFlags.mBlock; return 0 == mFlags.mBlock;
} }
// XXX Turn into a bit-field to simplify this code // mDirty bit
void MarkDirty() {
mFlags.mDirty = 1;
}
void ClearDirty() {
mFlags.mDirty = 0;
}
PRBool IsDirty() const {
return mFlags.mDirty;
}
// mImpactedByFloater bit
void SetLineIsImpactedByFloater(PRBool aValue) {
mFlags.mImpactedByFloater = aValue;
}
PRBool IsImpactedByFloater() const {
return mFlags.mImpactedByFloater;
}
// mTrimmed bit
void SetTrimmed(PRBool aOn) { void SetTrimmed(PRBool aOn) {
mFlags.mTrimmed = aOn; mFlags.mTrimmed = aOn;
} }
PRBool IsTrimmed() const { PRBool IsTrimmed() const {
return mFlags.mTrimmed; return mFlags.mTrimmed;
} }
// mChildCount value
PRInt32 GetChildCount() const {
return (PRInt32) mFlags.mChildCount;
}
void SetChildCount(PRInt32 aNewCount) {
if (NS_WARN_IF_FALSE(aNewCount >= 0, "negative child count")) {
aNewCount = 0;
}
if (aNewCount > LINE_MAX_CHILD_COUNT) {
aNewCount = LINE_MAX_CHILD_COUNT;
}
mFlags.mChildCount = aNewCount;
}
// mBreakType value
PRBool HasBreak() const { PRBool HasBreak() const {
return NS_STYLE_CLEAR_NONE != mFlags.mBreakType; return NS_STYLE_CLEAR_NONE != mFlags.mBreakType;
} }
void SetBreakType(PRUint8 aBreakType) { void SetBreakType(PRUint8 aBreakType) {
NS_WARN_IF_FALSE(aBreakType <= LINE_MAX_BREAK_TYPE, "bad break type");
mFlags.mBreakType = aBreakType; mFlags.mBreakType = aBreakType;
} }
PRUint8 GetBreakType() const { PRUint8 GetBreakType() const {
return mFlags.mBreakType; return mFlags.mBreakType;
} }
nscoord GetCarriedOutBottomMargin() const { // mCarriedOutBottomMargin value
return mCarriedOutBottomMargin; nscoord GetCarriedOutBottomMargin() const;
void SetCarriedOutBottomMargin(nscoord aValue);
// mFloaters
PRBool HasFloaters() const {
return (IsInline() && mInlineData) && mInlineData->mFloaters.NotEmpty();
}
nsFloaterCache* GetFirstFloater();
void FreeFloaters(nsFloaterCacheFreeList& aFreeList);
void AppendFloaters(nsFloaterCacheFreeList& aFreeList);
PRBool RemoveFloater(nsIFrame* aFrame);
void SetCombinedArea(const nsRect& aCombinedArea);
void GetCombinedArea(nsRect* aResult);
void SlideBy(nscoord aDY) {
mBounds.y += aDY;
if (mData) {
mData->mCombinedArea.y += aDY;
}
} }
nscoord GetHeight() const { return mBounds.height; } //----------------------------------------
//----------------------------------------------------------------------
// XXX old junk
nscoord GetHeight() const {
return mBounds.height;
}
static void DeleteLineList(nsIPresContext& aPresContext, nsLineBox* aLine); static void DeleteLineList(nsIPresContext& aPresContext, nsLineBox* aLine);
@ -193,38 +249,10 @@ public:
void List(FILE* out, PRInt32 aIndent) const; void List(FILE* out, PRInt32 aIndent) const;
PRInt32 ChildCount() const {
return PRInt32(mChildCount);
}
nsIFrame* LastChild() const; nsIFrame* LastChild() const;
PRBool IsLastChild(nsIFrame* aFrame) const; PRBool IsLastChild(nsIFrame* aFrame) const;
void SetIsBlock(PRBool aValue) {
mFlags.mBlock = aValue;
}
void SetLineIsImpactedByFloater(PRBool aValue) {
mFlags.mImpactedByFloater = aValue;
}
PRBool IsImpactedByFloater() const {
return mFlags.mImpactedByFloater;
}
void MarkDirty() {
mFlags.mDirty = 1;
}
void ClearDirty() {
mFlags.mDirty = 0;
}
PRBool IsDirty() const {
return mFlags.mDirty;
}
char* StateToString(char* aBuf, PRInt32 aBufSize) const; char* StateToString(char* aBuf, PRInt32 aBufSize) const;
PRInt32 IndexOf(nsIFrame* aFrame) const; PRInt32 IndexOf(nsIFrame* aFrame) const;
@ -233,21 +261,14 @@ public:
return IndexOf(aFrame) >= 0; return IndexOf(aFrame) >= 0;
} }
#ifdef NS_DEBUG
PRBool CheckIsBlock() const;
#endif
#ifdef DEBUG #ifdef DEBUG
PRBool SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; nsIAtom* SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
#endif #endif
nsIFrame* mFirstChild; nsIFrame* mFirstChild;
PRUint16 mChildCount;
nsRect mBounds;
nsRect mCombinedArea;
nscoord mCarriedOutBottomMargin;/* XXX switch to 16 bits */
nsFloaterCacheList mFloaters;
nsLineBox* mNext; nsLineBox* mNext;
nsRect mBounds;
nscoord mMaxElementWidth; // width part of max-element-size nscoord mMaxElementWidth; // width part of max-element-size
struct FlagBits { struct FlagBits {
@ -256,9 +277,28 @@ public:
PRUint32 mImpactedByFloater : 1; PRUint32 mImpactedByFloater : 1;
PRUint32 mTrimmed : 1; PRUint32 mTrimmed : 1;
PRUint32 reserved : 20; PRUint32 mBreakType : 4;
PRUint32 mBreakType : 8; PRUint32 mChildCount : 24;
};
struct ExtraData {
ExtraData(const nsRect& aBounds) : mCombinedArea(aBounds) {
}
nsRect mCombinedArea;
};
struct ExtraBlockData : public ExtraData {
ExtraBlockData(const nsRect& aBounds) : ExtraData(aBounds) {
mCarriedOutBottomMargin = 0;
}
nscoord mCarriedOutBottomMargin;
};
struct ExtraInlineData : public ExtraData {
ExtraInlineData(const nsRect& aBounds) : ExtraData(aBounds) {
}
nsFloaterCacheList mFloaters;
}; };
protected: protected:
@ -266,6 +306,14 @@ protected:
PRUint32 mAllFlags; PRUint32 mAllFlags;
FlagBits mFlags; FlagBits mFlags;
}; };
union {
ExtraData* mData;
ExtraBlockData* mBlockData;
ExtraInlineData* mInlineData;
};
void MaybeFreeData();
}; };
//---------------------------------------------------------------------- //----------------------------------------------------------------------