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);
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);
mFirstChild = aFrame;
mChildCount = aCount;
mAllFlags = 0;
MarkDirty();
SetIsBlock(aIsBlock);
mNext = nsnull;
mBounds.SetRect(0,0,0,0);
mCombinedArea.SetRect(0,0,0,0);
//XXX mCarriedOutTopMargin = 0;
mCarriedOutBottomMargin = 0;
#if NS_STYLE_CLEAR_NONE > 0
mFlags.mBreakType = NS_STYLE_CLEAR_NONE;
mMaxElementWidth = 0;
#endif
SetChildCount(aCount);
MarkDirty();
mFlags.mBlock = aIsBlock;
}
nsLineBox::~nsLineBox()
{
MOZ_COUNT_DTOR(nsLineBox);
if (IsBlock()) {
if (mBlockData) {
delete mBlockData;
}
}
else {
if (mInlineData) {
delete mInlineData;
}
}
}
static void
@ -82,9 +94,11 @@ ListFloaters(FILE* out, PRInt32 aIndent, const nsFloaterCacheList& aFloaters)
char*
nsLineBox::StateToString(char* aBuf, PRInt32 aBufSize) const
{
PR_snprintf(aBuf, aBufSize, "%s,%s[0x%x]",
IsDirty() ? "dirty" : "clean",
PR_snprintf(aBuf, aBufSize, "%s,%s,%s,%s[0x%x]",
IsBlock() ? "block" : "inline",
IsDirty() ? "dirty" : "",
IsImpactedByFloater() ? "impacted" : "",
IsTrimmed() ? "trimmed" : "",
mAllFlags);
return aBuf;
}
@ -97,30 +111,33 @@ nsLineBox::List(FILE* out, PRInt32 aIndent) const
for (i = aIndent; --i >= 0; ) fputs(" ", out);
char cbuf[100];
fprintf(out, "line %p: count=%d state=%s ",
this, ChildCount(), StateToString(cbuf, sizeof(cbuf)));
if (0 != mCarriedOutBottomMargin) {
fprintf(out, "bm=%d ", mCarriedOutBottomMargin);
this, GetChildCount(), StateToString(cbuf, sizeof(cbuf)));
if (0 != GetCarriedOutBottomMargin()) {
fprintf(out, "bm=%d ", GetCarriedOutBottomMargin());
}
if (0 != mMaxElementWidth) {
fprintf(out, "mew=%d ", mMaxElementWidth);
}
fprintf(out, "{%d,%d,%d,%d} ca={%d,%d,%d,%d}",
mBounds.x, mBounds.y, mBounds.width, mBounds.height,
mCombinedArea.x, mCombinedArea.y,
mCombinedArea.width, mCombinedArea.height);
fprintf(out, " <\n");
fprintf(out, "{%d,%d,%d,%d} ",
mBounds.x, mBounds.y, mBounds.width, mBounds.height);
if (mData) {
fprintf(out, "ca={%d,%d,%d,%d} ",
mData->mCombinedArea.x, mData->mCombinedArea.y,
mData->mCombinedArea.width, mData->mCombinedArea.height);
}
fprintf(out, "<\n");
nsIFrame* frame = mFirstChild;
PRInt32 n = ChildCount();
PRInt32 n = GetChildCount();
while (--n >= 0) {
frame->List(out, aIndent + 1);
frame->GetNextSibling(&frame);
}
for (i = aIndent; --i >= 0; ) fputs(" ", out);
if (mFloaters.NotEmpty()) {
if (HasFloaters()) {
fputs("> floaters <\n", out);
ListFloaters(out, aIndent + 1, mFloaters);
ListFloaters(out, aIndent + 1, mInlineData->mFloaters);
for (i = aIndent; --i >= 0; ) fputs(" ", out);
}
fputs(">\n", out);
@ -130,7 +147,7 @@ nsIFrame*
nsLineBox::LastChild() const
{
nsIFrame* frame = mFirstChild;
PRInt32 n = ChildCount() - 1;
PRInt32 n = GetChildCount() - 1;
while (--n >= 0) {
frame->GetNextSibling(&frame);
}
@ -147,7 +164,7 @@ nsLineBox::IsLastChild(nsIFrame* aFrame) const
PRInt32
nsLineBox::IndexOf(nsIFrame* aFrame) const
{
PRInt32 i, n = ChildCount();
PRInt32 i, n = GetChildCount();
nsIFrame* frame = mFirstChild;
for (i = 0; i < n; i++) {
if (frame == aFrame) {
@ -208,39 +225,172 @@ nsLineBox::FindLineContaining(nsLineBox* aLine, nsIFrame* aFrame,
return nsnull;
}
#ifdef NS_DEBUG
PRBool
nsLineBox::CheckIsBlock() const
nscoord
nsLineBox::GetCarriedOutBottomMargin() const
{
PRBool isBlock = nsLineLayout::TreatFrameAsBlock(mFirstChild);
return isBlock == IsBlock();
return (IsBlock() && mBlockData) ? mBlockData->mCarriedOutBottomMargin : 0;
}
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
PRBool
nsIAtom*
nsLineBox::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const
{
NS_PRECONDITION(aResult, "null OUT parameter pointer");
*aResult = sizeof(*this);
PRBool big = PR_TRUE;
if ((IsBlock() || mFloaters.IsEmpty()) &&
(mBounds == mCombinedArea)) {
big = PR_FALSE;
nsIAtom* atom;
if (IsBlock()) {
atom = nsLayoutAtoms::lineBoxBlockSmall;
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
if (HasFloaters()) {
PRUint32 floatersSize;
mInlineData->mFloaters.SizeOf(aHandler, &floatersSize);
// Base size of embedded object was included in sizeof(*this) above
floatersSize -= sizeof(mInlineData->mFloaters);
aHandler->AddSize(nsLayoutAtoms::lineBoxFloaters, floatersSize);
}
}
}
// Add in the size needed for floaters associated with this line
if (mFloaters.NotEmpty()) {
PRUint32 floatersSize;
mFloaters.SizeOf(aHandler, &floatersSize);
// Base size of embedded object was included in sizeof(*this) above
floatersSize -= sizeof(mFloaters);
aHandler->AddSize(nsLayoutAtoms::lineBoxFloaters, floatersSize);
}
return big;
return atom;
}
#endif
@ -346,7 +496,7 @@ nsLineIterator::GetLine(PRInt32 aLineNumber,
}
nsLineBox* line = mLines[aLineNumber];
*aFirstFrameOnLine = line->mFirstChild;
*aNumFramesOnLine = line->mChildCount;
*aNumFramesOnLine = line->GetChildCount();
aLineBounds = line->mBounds;
PRUint32 flags = 0;
@ -462,7 +612,7 @@ nsLineIterator::FindFrameAt(PRInt32 aLineNumber,
*aXIsAfterLastFrame = PR_FALSE;
nsRect r1, r2;
nsIFrame* frame = line->mFirstChild;
PRInt32 n = line->mChildCount;
PRInt32 n = line->GetChildCount();
if (mRightToLeft) {
while (--n >= 0) {
nsIFrame* nextFrame;
@ -528,6 +678,7 @@ nsFloaterCacheList::~nsFloaterCacheList()
delete floater;
floater = next;
}
mHead = nsnull;
}
nsFloaterCache*

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

@ -26,9 +26,6 @@
class nsISpaceManager;
class nsLineBox;
//----------------------------------------------------------------------
class nsFloaterCache;
class nsFloaterCacheList;
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
* enough state to support incremental reflow of the frames, event handling
@ -145,44 +149,96 @@ public:
nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock);
~nsLineBox();
// mBlock bit
PRBool IsBlock() const {
return mFlags.mBlock;
}
PRBool IsInline() const {
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) {
mFlags.mTrimmed = aOn;
}
PRBool IsTrimmed() const {
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 {
return NS_STYLE_CLEAR_NONE != mFlags.mBreakType;
}
void SetBreakType(PRUint8 aBreakType) {
NS_WARN_IF_FALSE(aBreakType <= LINE_MAX_BREAK_TYPE, "bad break type");
mFlags.mBreakType = aBreakType;
}
PRUint8 GetBreakType() const {
return mFlags.mBreakType;
}
nscoord GetCarriedOutBottomMargin() const {
return mCarriedOutBottomMargin;
// mCarriedOutBottomMargin value
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);
@ -193,38 +249,10 @@ public:
void List(FILE* out, PRInt32 aIndent) const;
PRInt32 ChildCount() const {
return PRInt32(mChildCount);
}
nsIFrame* LastChild() 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;
PRInt32 IndexOf(nsIFrame* aFrame) const;
@ -233,21 +261,14 @@ public:
return IndexOf(aFrame) >= 0;
}
#ifdef NS_DEBUG
PRBool CheckIsBlock() const;
#endif
#ifdef DEBUG
PRBool SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
nsIAtom* SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
#endif
nsIFrame* mFirstChild;
PRUint16 mChildCount;
nsRect mBounds;
nsRect mCombinedArea;
nscoord mCarriedOutBottomMargin;/* XXX switch to 16 bits */
nsFloaterCacheList mFloaters;
nsLineBox* mNext;
nsRect mBounds;
nscoord mMaxElementWidth; // width part of max-element-size
struct FlagBits {
@ -256,9 +277,28 @@ public:
PRUint32 mImpactedByFloater : 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:
@ -266,6 +306,14 @@ protected:
PRUint32 mAllFlags;
FlagBits mFlags;
};
union {
ExtraData* mData;
ExtraBlockData* mBlockData;
ExtraInlineData* mInlineData;
};
void MaybeFreeData();
};
//----------------------------------------------------------------------

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

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

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

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

@ -30,25 +30,37 @@
MOZ_DECL_CTOR_COUNTER(nsLineBox);
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);
mFirstChild = aFrame;
mChildCount = aCount;
mAllFlags = 0;
MarkDirty();
SetIsBlock(aIsBlock);
mNext = nsnull;
mBounds.SetRect(0,0,0,0);
mCombinedArea.SetRect(0,0,0,0);
//XXX mCarriedOutTopMargin = 0;
mCarriedOutBottomMargin = 0;
#if NS_STYLE_CLEAR_NONE > 0
mFlags.mBreakType = NS_STYLE_CLEAR_NONE;
mMaxElementWidth = 0;
#endif
SetChildCount(aCount);
MarkDirty();
mFlags.mBlock = aIsBlock;
}
nsLineBox::~nsLineBox()
{
MOZ_COUNT_DTOR(nsLineBox);
if (IsBlock()) {
if (mBlockData) {
delete mBlockData;
}
}
else {
if (mInlineData) {
delete mInlineData;
}
}
}
static void
@ -82,9 +94,11 @@ ListFloaters(FILE* out, PRInt32 aIndent, const nsFloaterCacheList& aFloaters)
char*
nsLineBox::StateToString(char* aBuf, PRInt32 aBufSize) const
{
PR_snprintf(aBuf, aBufSize, "%s,%s[0x%x]",
IsDirty() ? "dirty" : "clean",
PR_snprintf(aBuf, aBufSize, "%s,%s,%s,%s[0x%x]",
IsBlock() ? "block" : "inline",
IsDirty() ? "dirty" : "",
IsImpactedByFloater() ? "impacted" : "",
IsTrimmed() ? "trimmed" : "",
mAllFlags);
return aBuf;
}
@ -97,30 +111,33 @@ nsLineBox::List(FILE* out, PRInt32 aIndent) const
for (i = aIndent; --i >= 0; ) fputs(" ", out);
char cbuf[100];
fprintf(out, "line %p: count=%d state=%s ",
this, ChildCount(), StateToString(cbuf, sizeof(cbuf)));
if (0 != mCarriedOutBottomMargin) {
fprintf(out, "bm=%d ", mCarriedOutBottomMargin);
this, GetChildCount(), StateToString(cbuf, sizeof(cbuf)));
if (0 != GetCarriedOutBottomMargin()) {
fprintf(out, "bm=%d ", GetCarriedOutBottomMargin());
}
if (0 != mMaxElementWidth) {
fprintf(out, "mew=%d ", mMaxElementWidth);
}
fprintf(out, "{%d,%d,%d,%d} ca={%d,%d,%d,%d}",
mBounds.x, mBounds.y, mBounds.width, mBounds.height,
mCombinedArea.x, mCombinedArea.y,
mCombinedArea.width, mCombinedArea.height);
fprintf(out, " <\n");
fprintf(out, "{%d,%d,%d,%d} ",
mBounds.x, mBounds.y, mBounds.width, mBounds.height);
if (mData) {
fprintf(out, "ca={%d,%d,%d,%d} ",
mData->mCombinedArea.x, mData->mCombinedArea.y,
mData->mCombinedArea.width, mData->mCombinedArea.height);
}
fprintf(out, "<\n");
nsIFrame* frame = mFirstChild;
PRInt32 n = ChildCount();
PRInt32 n = GetChildCount();
while (--n >= 0) {
frame->List(out, aIndent + 1);
frame->GetNextSibling(&frame);
}
for (i = aIndent; --i >= 0; ) fputs(" ", out);
if (mFloaters.NotEmpty()) {
if (HasFloaters()) {
fputs("> floaters <\n", out);
ListFloaters(out, aIndent + 1, mFloaters);
ListFloaters(out, aIndent + 1, mInlineData->mFloaters);
for (i = aIndent; --i >= 0; ) fputs(" ", out);
}
fputs(">\n", out);
@ -130,7 +147,7 @@ nsIFrame*
nsLineBox::LastChild() const
{
nsIFrame* frame = mFirstChild;
PRInt32 n = ChildCount() - 1;
PRInt32 n = GetChildCount() - 1;
while (--n >= 0) {
frame->GetNextSibling(&frame);
}
@ -147,7 +164,7 @@ nsLineBox::IsLastChild(nsIFrame* aFrame) const
PRInt32
nsLineBox::IndexOf(nsIFrame* aFrame) const
{
PRInt32 i, n = ChildCount();
PRInt32 i, n = GetChildCount();
nsIFrame* frame = mFirstChild;
for (i = 0; i < n; i++) {
if (frame == aFrame) {
@ -208,39 +225,172 @@ nsLineBox::FindLineContaining(nsLineBox* aLine, nsIFrame* aFrame,
return nsnull;
}
#ifdef NS_DEBUG
PRBool
nsLineBox::CheckIsBlock() const
nscoord
nsLineBox::GetCarriedOutBottomMargin() const
{
PRBool isBlock = nsLineLayout::TreatFrameAsBlock(mFirstChild);
return isBlock == IsBlock();
return (IsBlock() && mBlockData) ? mBlockData->mCarriedOutBottomMargin : 0;
}
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
PRBool
nsIAtom*
nsLineBox::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const
{
NS_PRECONDITION(aResult, "null OUT parameter pointer");
*aResult = sizeof(*this);
PRBool big = PR_TRUE;
if ((IsBlock() || mFloaters.IsEmpty()) &&
(mBounds == mCombinedArea)) {
big = PR_FALSE;
nsIAtom* atom;
if (IsBlock()) {
atom = nsLayoutAtoms::lineBoxBlockSmall;
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
if (HasFloaters()) {
PRUint32 floatersSize;
mInlineData->mFloaters.SizeOf(aHandler, &floatersSize);
// Base size of embedded object was included in sizeof(*this) above
floatersSize -= sizeof(mInlineData->mFloaters);
aHandler->AddSize(nsLayoutAtoms::lineBoxFloaters, floatersSize);
}
}
}
// Add in the size needed for floaters associated with this line
if (mFloaters.NotEmpty()) {
PRUint32 floatersSize;
mFloaters.SizeOf(aHandler, &floatersSize);
// Base size of embedded object was included in sizeof(*this) above
floatersSize -= sizeof(mFloaters);
aHandler->AddSize(nsLayoutAtoms::lineBoxFloaters, floatersSize);
}
return big;
return atom;
}
#endif
@ -346,7 +496,7 @@ nsLineIterator::GetLine(PRInt32 aLineNumber,
}
nsLineBox* line = mLines[aLineNumber];
*aFirstFrameOnLine = line->mFirstChild;
*aNumFramesOnLine = line->mChildCount;
*aNumFramesOnLine = line->GetChildCount();
aLineBounds = line->mBounds;
PRUint32 flags = 0;
@ -462,7 +612,7 @@ nsLineIterator::FindFrameAt(PRInt32 aLineNumber,
*aXIsAfterLastFrame = PR_FALSE;
nsRect r1, r2;
nsIFrame* frame = line->mFirstChild;
PRInt32 n = line->mChildCount;
PRInt32 n = line->GetChildCount();
if (mRightToLeft) {
while (--n >= 0) {
nsIFrame* nextFrame;
@ -528,6 +678,7 @@ nsFloaterCacheList::~nsFloaterCacheList()
delete floater;
floater = next;
}
mHead = nsnull;
}
nsFloaterCache*

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

@ -26,9 +26,6 @@
class nsISpaceManager;
class nsLineBox;
//----------------------------------------------------------------------
class nsFloaterCache;
class nsFloaterCacheList;
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
* enough state to support incremental reflow of the frames, event handling
@ -145,44 +149,96 @@ public:
nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock);
~nsLineBox();
// mBlock bit
PRBool IsBlock() const {
return mFlags.mBlock;
}
PRBool IsInline() const {
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) {
mFlags.mTrimmed = aOn;
}
PRBool IsTrimmed() const {
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 {
return NS_STYLE_CLEAR_NONE != mFlags.mBreakType;
}
void SetBreakType(PRUint8 aBreakType) {
NS_WARN_IF_FALSE(aBreakType <= LINE_MAX_BREAK_TYPE, "bad break type");
mFlags.mBreakType = aBreakType;
}
PRUint8 GetBreakType() const {
return mFlags.mBreakType;
}
nscoord GetCarriedOutBottomMargin() const {
return mCarriedOutBottomMargin;
// mCarriedOutBottomMargin value
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);
@ -193,38 +249,10 @@ public:
void List(FILE* out, PRInt32 aIndent) const;
PRInt32 ChildCount() const {
return PRInt32(mChildCount);
}
nsIFrame* LastChild() 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;
PRInt32 IndexOf(nsIFrame* aFrame) const;
@ -233,21 +261,14 @@ public:
return IndexOf(aFrame) >= 0;
}
#ifdef NS_DEBUG
PRBool CheckIsBlock() const;
#endif
#ifdef DEBUG
PRBool SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
nsIAtom* SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
#endif
nsIFrame* mFirstChild;
PRUint16 mChildCount;
nsRect mBounds;
nsRect mCombinedArea;
nscoord mCarriedOutBottomMargin;/* XXX switch to 16 bits */
nsFloaterCacheList mFloaters;
nsLineBox* mNext;
nsRect mBounds;
nscoord mMaxElementWidth; // width part of max-element-size
struct FlagBits {
@ -256,9 +277,28 @@ public:
PRUint32 mImpactedByFloater : 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:
@ -266,6 +306,14 @@ protected:
PRUint32 mAllFlags;
FlagBits mFlags;
};
union {
ExtraData* mData;
ExtraBlockData* mBlockData;
ExtraInlineData* mInlineData;
};
void MaybeFreeData();
};
//----------------------------------------------------------------------