зеркало из https://github.com/mozilla/gecko-dev.git
Fixed various incremental reflow bugs (1764,12890,1910,2222) and list bullet painting bug (10675,13599)
This commit is contained in:
Родитель
71877ee89f
Коммит
6488f7b26e
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -115,9 +115,6 @@ public:
|
|||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
NS_IMETHOD MoveInSpaceManager(nsIPresContext* aPresContext,
|
||||
nsISpaceManager* aSpaceManager,
|
||||
nscoord aDeltaX, nscoord aDeltaY);
|
||||
|
||||
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
|
||||
nsIContent* aChild,
|
||||
|
@ -144,6 +141,9 @@ public:
|
|||
|
||||
nsIFrame* GetTopBlockChild();
|
||||
|
||||
nsresult UpdateSpaceManager(nsIPresContext* aPresContext,
|
||||
nsISpaceManager* aSpaceManager);
|
||||
|
||||
protected:
|
||||
nsBlockFrame();
|
||||
virtual ~nsBlockFrame();
|
||||
|
@ -166,10 +166,6 @@ protected:
|
|||
nsISpaceManager* aSpaceManager,
|
||||
nsLineBox* aLine, nscoord aDY);
|
||||
|
||||
void SlideFloaters(nsIPresContext* aPresContext,
|
||||
nsISpaceManager* aSpaceManager,
|
||||
nsLineBox* aLine, nscoord aDY);
|
||||
|
||||
PRBool DrainOverflowLines();
|
||||
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
|
@ -228,10 +224,6 @@ protected:
|
|||
PRBool* aKeepReflowGoing,
|
||||
PRBool aDamageDirtyArea = PR_FALSE);
|
||||
|
||||
virtual void DidReflowLine(nsBlockReflowState& aState,
|
||||
nsLineBox* aLine,
|
||||
PRBool aKeepReflowGoing);
|
||||
|
||||
nsresult PlaceLine(nsBlockReflowState& aState,
|
||||
nsLineLayout& aLineLayout,
|
||||
nsLineBox* aLine,
|
||||
|
@ -249,8 +241,6 @@ protected:
|
|||
// XXX where to go
|
||||
PRBool ShouldJustifyLine(nsBlockReflowState& aState, nsLineBox* aLine);
|
||||
|
||||
void FindFloaters(nsLineBox* aLine);
|
||||
|
||||
void DeleteLine(nsBlockReflowState& aState, nsLineBox* aLine);
|
||||
|
||||
//----------------------------------------
|
||||
|
@ -339,6 +329,7 @@ protected:
|
|||
|
||||
void PropogateReflowDamage(nsBlockReflowState& aState,
|
||||
nsLineBox* aLine,
|
||||
const nsRect& aOldCombinedArea,
|
||||
nscoord aDeltaY);
|
||||
|
||||
nsresult ComputeTextRuns(nsIPresContext* aPresContext);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -27,7 +27,6 @@ nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRUint16 flags)
|
|||
mFirstChild = aFrame;
|
||||
mChildCount = aCount;
|
||||
mState = LINE_IS_DIRTY | flags;
|
||||
mFloaters = nsnull;
|
||||
mNext = nsnull;
|
||||
mBounds.SetRect(0,0,0,0);
|
||||
mCombinedArea.SetRect(0,0,0,0);
|
||||
|
@ -39,19 +38,16 @@ nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRUint16 flags)
|
|||
|
||||
nsLineBox::~nsLineBox()
|
||||
{
|
||||
if (nsnull != mFloaters) {
|
||||
delete mFloaters;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ListFloaters(FILE* out, PRInt32 aIndent, nsVoidArray* aFloaters)
|
||||
ListFloaters(FILE* out, PRInt32 aIndent, const nsFloaterCacheList& aFloaters)
|
||||
{
|
||||
nsAutoString frameName;
|
||||
PRInt32 j, i, n = aFloaters->Count();
|
||||
for (i = 0; i < n; i++) {
|
||||
for (j = aIndent; --j >= 0; ) fputs(" ", out);
|
||||
nsPlaceholderFrame* ph = (nsPlaceholderFrame*) aFloaters->ElementAt(i);
|
||||
nsFloaterCache* fc = aFloaters.Head();
|
||||
while (fc) {
|
||||
nsFrame::IndentBy(out, aIndent);
|
||||
nsPlaceholderFrame* ph = fc->mPlaceholder;
|
||||
if (nsnull != ph) {
|
||||
fprintf(out, "placeholder@%p ", ph);
|
||||
nsIFrame* frame = ph->GetOutOfFlowFrame();
|
||||
|
@ -59,8 +55,13 @@ ListFloaters(FILE* out, PRInt32 aIndent, nsVoidArray* aFloaters)
|
|||
frame->GetFrameName(frameName);
|
||||
fputs(frameName, out);
|
||||
}
|
||||
fprintf(out, " %s region={%d,%d,%d,%d}",
|
||||
fc->mIsCurrentLineFloater ? "cl" : "bcl",
|
||||
fc->mRegion.x, fc->mRegion.y,
|
||||
fc->mRegion.width, fc->mRegion.height);
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
fc = fc->Next();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +106,7 @@ nsLineBox::List(FILE* out, PRInt32 aIndent) const
|
|||
}
|
||||
|
||||
for (i = aIndent; --i >= 0; ) fputs(" ", out);
|
||||
if (nsnull != mFloaters) {
|
||||
if (mFloaters.NotEmpty()) {
|
||||
fputs("> floaters <\n", out);
|
||||
ListFloaters(out, aIndent + 1, mFloaters);
|
||||
for (i = aIndent; --i >= 0; ) fputs(" ", out);
|
||||
|
@ -463,3 +464,128 @@ nsLineIterator::FindFrameAt(PRInt32 aLineNumber,
|
|||
*aFrameFound = frame;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsFloaterCacheList::~nsFloaterCacheList()
|
||||
{
|
||||
nsFloaterCache* floater = mHead;
|
||||
while (floater) {
|
||||
nsFloaterCache* next = floater->mNext;
|
||||
delete floater;
|
||||
floater = next;
|
||||
}
|
||||
}
|
||||
|
||||
nsFloaterCache*
|
||||
nsFloaterCacheList::Tail() const
|
||||
{
|
||||
nsFloaterCache* fc = mHead;
|
||||
while (fc) {
|
||||
if (!fc->mNext) {
|
||||
break;
|
||||
}
|
||||
fc = fc->mNext;
|
||||
}
|
||||
return fc;
|
||||
}
|
||||
|
||||
void
|
||||
nsFloaterCacheList::Append(nsFloaterCacheFreeList& aList)
|
||||
{
|
||||
nsFloaterCache* tail = Tail();
|
||||
if (tail) {
|
||||
tail->mNext = aList.mHead;
|
||||
}
|
||||
else {
|
||||
mHead = aList.mHead;
|
||||
}
|
||||
aList.mHead = nsnull;
|
||||
aList.mTail = nsnull;
|
||||
}
|
||||
|
||||
nsFloaterCache*
|
||||
nsFloaterCacheList::Find(nsIFrame* aOutOfFlowFrame)
|
||||
{
|
||||
nsFloaterCache* fc = mHead;
|
||||
while (fc) {
|
||||
if (fc->mPlaceholder->GetOutOfFlowFrame() == aOutOfFlowFrame) {
|
||||
break;
|
||||
}
|
||||
fc = fc->Next();
|
||||
}
|
||||
return fc;
|
||||
}
|
||||
|
||||
void
|
||||
nsFloaterCacheList::Remove(nsFloaterCache* aElement)
|
||||
{
|
||||
nsFloaterCache** fcp = &mHead;
|
||||
nsFloaterCache* fc;
|
||||
while (nsnull != (fc = *fcp)) {
|
||||
if (fc == aElement) {
|
||||
*fcp = fc->mNext;
|
||||
break;
|
||||
}
|
||||
fcp = &fc->mNext;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
nsFloaterCacheFreeList::Append(nsFloaterCacheList& aList)
|
||||
{
|
||||
if (mTail) {
|
||||
mTail->mNext = aList.mHead;
|
||||
}
|
||||
else {
|
||||
mHead = aList.mHead;
|
||||
}
|
||||
mTail = aList.Tail();
|
||||
aList.mHead = nsnull;
|
||||
}
|
||||
|
||||
nsFloaterCache*
|
||||
nsFloaterCacheFreeList::Alloc()
|
||||
{
|
||||
nsFloaterCache* fc = mHead;
|
||||
if (mHead) {
|
||||
if (mHead == mTail) {
|
||||
mHead = mTail = nsnull;
|
||||
}
|
||||
else {
|
||||
mHead = fc->mNext;
|
||||
}
|
||||
fc->mNext = nsnull;
|
||||
}
|
||||
else {
|
||||
fc = new nsFloaterCache();
|
||||
}
|
||||
return fc;
|
||||
}
|
||||
|
||||
void
|
||||
nsFloaterCacheFreeList::Append(nsFloaterCache* aFloater)
|
||||
{
|
||||
aFloater->mNext = nsnull;
|
||||
if (mTail) {
|
||||
mTail->mNext = aFloater;
|
||||
mTail = aFloater;
|
||||
}
|
||||
else {
|
||||
mHead = mTail = aFloater;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsFloaterCache::nsFloaterCache()
|
||||
: mPlaceholder(nsnull),
|
||||
mIsCurrentLineFloater(PR_TRUE),
|
||||
mMargins(0, 0, 0, 0),
|
||||
mOffsets(0, 0, 0, 0),
|
||||
mCombinedArea(0, 0, 0, 0),
|
||||
mNext(nsnull)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -24,16 +24,117 @@
|
|||
#include "nsILineIterator.h"
|
||||
|
||||
// bits in nsLineBox.mState
|
||||
#define LINE_IS_DIRTY 0x1
|
||||
#define LINE_IS_BLOCK 0x2
|
||||
#define LINE_IS_DIRTY 0x1
|
||||
#define LINE_IS_BLOCK 0x2
|
||||
#define LINE_IS_IMPACTED_BY_FLOATER 0x4
|
||||
#ifdef BLOCK_DOES_FIRST_LINE
|
||||
#define LINE_IS_FIRST_LINE 0x4
|
||||
#define LINE_IS_FIRST_LINE 0x8
|
||||
#endif
|
||||
#define LINE_WAS_DIRTY 0x8
|
||||
#define LINE_WAS_DIRTY 0x10
|
||||
|
||||
class nsISpaceManager;
|
||||
class nsLineBox;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class nsFloaterCache;
|
||||
class nsFloaterCacheList;
|
||||
class nsFloaterCacheFreeList;
|
||||
|
||||
// State cached after reflowing a floater. This state is used during
|
||||
// incremental reflow when we avoid reflowing a floater.
|
||||
class nsFloaterCache {
|
||||
public:
|
||||
nsFloaterCache();
|
||||
~nsFloaterCache() { }
|
||||
|
||||
nsFloaterCache* Next() const { return mNext; }
|
||||
|
||||
nsPlaceholderFrame* mPlaceholder; // nsPlaceholderFrame
|
||||
|
||||
// This will be true if the floater was placed on the current line
|
||||
// instead of below the current line.
|
||||
PRBool mIsCurrentLineFloater;
|
||||
|
||||
nsMargin mMargins; // computed margins
|
||||
|
||||
nsMargin mOffsets; // computed offsets (relative pos)
|
||||
|
||||
// Region in the spacemanager impacted by this floater; the
|
||||
// coordinates are relative to the containing block frame. The
|
||||
// region includes the margins around the floater, but doesn't
|
||||
// include the relative offsets.
|
||||
nsRect mRegion;
|
||||
|
||||
// Combined area for the floater. This will not include the margins
|
||||
// for the floater. Like mRegion, the coordinates are relative to
|
||||
// the containing block frame.
|
||||
nsRect mCombinedArea;
|
||||
|
||||
protected:
|
||||
nsFloaterCache* mNext;
|
||||
|
||||
friend class nsFloaterCacheList;
|
||||
friend class nsFloaterCacheFreeList;
|
||||
};
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
class nsFloaterCacheList {
|
||||
public:
|
||||
nsFloaterCacheList() : mHead(nsnull) { }
|
||||
~nsFloaterCacheList();
|
||||
|
||||
PRBool IsEmpty() const {
|
||||
return nsnull == mHead;
|
||||
}
|
||||
|
||||
PRBool NotEmpty() const {
|
||||
return nsnull != mHead;
|
||||
}
|
||||
|
||||
nsFloaterCache* Head() const {
|
||||
return mHead;
|
||||
}
|
||||
|
||||
nsFloaterCache* Tail() const;
|
||||
|
||||
nsFloaterCache* Find(nsIFrame* aOutOfFlowFrame);
|
||||
|
||||
void Remove(nsFloaterCache* aElement);
|
||||
|
||||
void Append(nsFloaterCacheFreeList& aList);
|
||||
|
||||
protected:
|
||||
nsFloaterCache* mHead;
|
||||
|
||||
friend class nsFloaterCacheFreeList;
|
||||
};
|
||||
|
||||
//---------------------------------------
|
||||
|
||||
class nsFloaterCacheFreeList : public nsFloaterCacheList {
|
||||
public:
|
||||
nsFloaterCacheFreeList() : mTail(nsnull) { }
|
||||
~nsFloaterCacheFreeList() { }
|
||||
|
||||
// Steal away aList's nsFloaterCache objects and put them on this
|
||||
// free-list.
|
||||
void Append(nsFloaterCacheList& aList);
|
||||
|
||||
void Append(nsFloaterCache* aFloaterCache);
|
||||
|
||||
// Allocate a new nsFloaterCache object
|
||||
nsFloaterCache* Alloc();
|
||||
|
||||
protected:
|
||||
nsFloaterCache* mTail;
|
||||
|
||||
friend class nsFloaterCacheList;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The nsLineBox class represents a horizontal line of frames. It contains
|
||||
* enough state to support incremental reflow of the frames, event handling
|
||||
|
@ -92,6 +193,19 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void SetLineIsImpactedByFloater(PRBool aValue) {
|
||||
if (aValue) {
|
||||
mState |= LINE_IS_IMPACTED_BY_FLOATER;
|
||||
}
|
||||
else {
|
||||
mState &= ~LINE_IS_IMPACTED_BY_FLOATER;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool IsImpactedByFloater() const {
|
||||
return 0 != (LINE_IS_IMPACTED_BY_FLOATER & mState);
|
||||
}
|
||||
|
||||
#ifdef BLOCK_DOES_FIRST_LINE
|
||||
PRBool IsFirstLine() const {
|
||||
return 0 != (LINE_IS_FIRST_LINE & mState);
|
||||
|
@ -150,7 +264,7 @@ public:
|
|||
nsRect mBounds;
|
||||
nsRect mCombinedArea;
|
||||
nscoord mCarriedOutBottomMargin;/* XXX switch to 16 bits */
|
||||
nsVoidArray* mFloaters;
|
||||
nsFloaterCacheList mFloaters;
|
||||
nsLineBox* mNext;
|
||||
nscoord mMaxElementWidth; // width part of max-element-size
|
||||
};
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -115,9 +115,6 @@ public:
|
|||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
NS_IMETHOD MoveInSpaceManager(nsIPresContext* aPresContext,
|
||||
nsISpaceManager* aSpaceManager,
|
||||
nscoord aDeltaX, nscoord aDeltaY);
|
||||
|
||||
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
|
||||
nsIContent* aChild,
|
||||
|
@ -144,6 +141,9 @@ public:
|
|||
|
||||
nsIFrame* GetTopBlockChild();
|
||||
|
||||
nsresult UpdateSpaceManager(nsIPresContext* aPresContext,
|
||||
nsISpaceManager* aSpaceManager);
|
||||
|
||||
protected:
|
||||
nsBlockFrame();
|
||||
virtual ~nsBlockFrame();
|
||||
|
@ -166,10 +166,6 @@ protected:
|
|||
nsISpaceManager* aSpaceManager,
|
||||
nsLineBox* aLine, nscoord aDY);
|
||||
|
||||
void SlideFloaters(nsIPresContext* aPresContext,
|
||||
nsISpaceManager* aSpaceManager,
|
||||
nsLineBox* aLine, nscoord aDY);
|
||||
|
||||
PRBool DrainOverflowLines();
|
||||
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
|
@ -228,10 +224,6 @@ protected:
|
|||
PRBool* aKeepReflowGoing,
|
||||
PRBool aDamageDirtyArea = PR_FALSE);
|
||||
|
||||
virtual void DidReflowLine(nsBlockReflowState& aState,
|
||||
nsLineBox* aLine,
|
||||
PRBool aKeepReflowGoing);
|
||||
|
||||
nsresult PlaceLine(nsBlockReflowState& aState,
|
||||
nsLineLayout& aLineLayout,
|
||||
nsLineBox* aLine,
|
||||
|
@ -249,8 +241,6 @@ protected:
|
|||
// XXX where to go
|
||||
PRBool ShouldJustifyLine(nsBlockReflowState& aState, nsLineBox* aLine);
|
||||
|
||||
void FindFloaters(nsLineBox* aLine);
|
||||
|
||||
void DeleteLine(nsBlockReflowState& aState, nsLineBox* aLine);
|
||||
|
||||
//----------------------------------------
|
||||
|
@ -339,6 +329,7 @@ protected:
|
|||
|
||||
void PropogateReflowDamage(nsBlockReflowState& aState,
|
||||
nsLineBox* aLine,
|
||||
const nsRect& aOldCombinedArea,
|
||||
nscoord aDeltaY);
|
||||
|
||||
nsresult ComputeTextRuns(nsIPresContext* aPresContext);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -27,7 +27,6 @@ nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRUint16 flags)
|
|||
mFirstChild = aFrame;
|
||||
mChildCount = aCount;
|
||||
mState = LINE_IS_DIRTY | flags;
|
||||
mFloaters = nsnull;
|
||||
mNext = nsnull;
|
||||
mBounds.SetRect(0,0,0,0);
|
||||
mCombinedArea.SetRect(0,0,0,0);
|
||||
|
@ -39,19 +38,16 @@ nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRUint16 flags)
|
|||
|
||||
nsLineBox::~nsLineBox()
|
||||
{
|
||||
if (nsnull != mFloaters) {
|
||||
delete mFloaters;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ListFloaters(FILE* out, PRInt32 aIndent, nsVoidArray* aFloaters)
|
||||
ListFloaters(FILE* out, PRInt32 aIndent, const nsFloaterCacheList& aFloaters)
|
||||
{
|
||||
nsAutoString frameName;
|
||||
PRInt32 j, i, n = aFloaters->Count();
|
||||
for (i = 0; i < n; i++) {
|
||||
for (j = aIndent; --j >= 0; ) fputs(" ", out);
|
||||
nsPlaceholderFrame* ph = (nsPlaceholderFrame*) aFloaters->ElementAt(i);
|
||||
nsFloaterCache* fc = aFloaters.Head();
|
||||
while (fc) {
|
||||
nsFrame::IndentBy(out, aIndent);
|
||||
nsPlaceholderFrame* ph = fc->mPlaceholder;
|
||||
if (nsnull != ph) {
|
||||
fprintf(out, "placeholder@%p ", ph);
|
||||
nsIFrame* frame = ph->GetOutOfFlowFrame();
|
||||
|
@ -59,8 +55,13 @@ ListFloaters(FILE* out, PRInt32 aIndent, nsVoidArray* aFloaters)
|
|||
frame->GetFrameName(frameName);
|
||||
fputs(frameName, out);
|
||||
}
|
||||
fprintf(out, " %s region={%d,%d,%d,%d}",
|
||||
fc->mIsCurrentLineFloater ? "cl" : "bcl",
|
||||
fc->mRegion.x, fc->mRegion.y,
|
||||
fc->mRegion.width, fc->mRegion.height);
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
fc = fc->Next();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +106,7 @@ nsLineBox::List(FILE* out, PRInt32 aIndent) const
|
|||
}
|
||||
|
||||
for (i = aIndent; --i >= 0; ) fputs(" ", out);
|
||||
if (nsnull != mFloaters) {
|
||||
if (mFloaters.NotEmpty()) {
|
||||
fputs("> floaters <\n", out);
|
||||
ListFloaters(out, aIndent + 1, mFloaters);
|
||||
for (i = aIndent; --i >= 0; ) fputs(" ", out);
|
||||
|
@ -463,3 +464,128 @@ nsLineIterator::FindFrameAt(PRInt32 aLineNumber,
|
|||
*aFrameFound = frame;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsFloaterCacheList::~nsFloaterCacheList()
|
||||
{
|
||||
nsFloaterCache* floater = mHead;
|
||||
while (floater) {
|
||||
nsFloaterCache* next = floater->mNext;
|
||||
delete floater;
|
||||
floater = next;
|
||||
}
|
||||
}
|
||||
|
||||
nsFloaterCache*
|
||||
nsFloaterCacheList::Tail() const
|
||||
{
|
||||
nsFloaterCache* fc = mHead;
|
||||
while (fc) {
|
||||
if (!fc->mNext) {
|
||||
break;
|
||||
}
|
||||
fc = fc->mNext;
|
||||
}
|
||||
return fc;
|
||||
}
|
||||
|
||||
void
|
||||
nsFloaterCacheList::Append(nsFloaterCacheFreeList& aList)
|
||||
{
|
||||
nsFloaterCache* tail = Tail();
|
||||
if (tail) {
|
||||
tail->mNext = aList.mHead;
|
||||
}
|
||||
else {
|
||||
mHead = aList.mHead;
|
||||
}
|
||||
aList.mHead = nsnull;
|
||||
aList.mTail = nsnull;
|
||||
}
|
||||
|
||||
nsFloaterCache*
|
||||
nsFloaterCacheList::Find(nsIFrame* aOutOfFlowFrame)
|
||||
{
|
||||
nsFloaterCache* fc = mHead;
|
||||
while (fc) {
|
||||
if (fc->mPlaceholder->GetOutOfFlowFrame() == aOutOfFlowFrame) {
|
||||
break;
|
||||
}
|
||||
fc = fc->Next();
|
||||
}
|
||||
return fc;
|
||||
}
|
||||
|
||||
void
|
||||
nsFloaterCacheList::Remove(nsFloaterCache* aElement)
|
||||
{
|
||||
nsFloaterCache** fcp = &mHead;
|
||||
nsFloaterCache* fc;
|
||||
while (nsnull != (fc = *fcp)) {
|
||||
if (fc == aElement) {
|
||||
*fcp = fc->mNext;
|
||||
break;
|
||||
}
|
||||
fcp = &fc->mNext;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
nsFloaterCacheFreeList::Append(nsFloaterCacheList& aList)
|
||||
{
|
||||
if (mTail) {
|
||||
mTail->mNext = aList.mHead;
|
||||
}
|
||||
else {
|
||||
mHead = aList.mHead;
|
||||
}
|
||||
mTail = aList.Tail();
|
||||
aList.mHead = nsnull;
|
||||
}
|
||||
|
||||
nsFloaterCache*
|
||||
nsFloaterCacheFreeList::Alloc()
|
||||
{
|
||||
nsFloaterCache* fc = mHead;
|
||||
if (mHead) {
|
||||
if (mHead == mTail) {
|
||||
mHead = mTail = nsnull;
|
||||
}
|
||||
else {
|
||||
mHead = fc->mNext;
|
||||
}
|
||||
fc->mNext = nsnull;
|
||||
}
|
||||
else {
|
||||
fc = new nsFloaterCache();
|
||||
}
|
||||
return fc;
|
||||
}
|
||||
|
||||
void
|
||||
nsFloaterCacheFreeList::Append(nsFloaterCache* aFloater)
|
||||
{
|
||||
aFloater->mNext = nsnull;
|
||||
if (mTail) {
|
||||
mTail->mNext = aFloater;
|
||||
mTail = aFloater;
|
||||
}
|
||||
else {
|
||||
mHead = mTail = aFloater;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsFloaterCache::nsFloaterCache()
|
||||
: mPlaceholder(nsnull),
|
||||
mIsCurrentLineFloater(PR_TRUE),
|
||||
mMargins(0, 0, 0, 0),
|
||||
mOffsets(0, 0, 0, 0),
|
||||
mCombinedArea(0, 0, 0, 0),
|
||||
mNext(nsnull)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -24,16 +24,117 @@
|
|||
#include "nsILineIterator.h"
|
||||
|
||||
// bits in nsLineBox.mState
|
||||
#define LINE_IS_DIRTY 0x1
|
||||
#define LINE_IS_BLOCK 0x2
|
||||
#define LINE_IS_DIRTY 0x1
|
||||
#define LINE_IS_BLOCK 0x2
|
||||
#define LINE_IS_IMPACTED_BY_FLOATER 0x4
|
||||
#ifdef BLOCK_DOES_FIRST_LINE
|
||||
#define LINE_IS_FIRST_LINE 0x4
|
||||
#define LINE_IS_FIRST_LINE 0x8
|
||||
#endif
|
||||
#define LINE_WAS_DIRTY 0x8
|
||||
#define LINE_WAS_DIRTY 0x10
|
||||
|
||||
class nsISpaceManager;
|
||||
class nsLineBox;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class nsFloaterCache;
|
||||
class nsFloaterCacheList;
|
||||
class nsFloaterCacheFreeList;
|
||||
|
||||
// State cached after reflowing a floater. This state is used during
|
||||
// incremental reflow when we avoid reflowing a floater.
|
||||
class nsFloaterCache {
|
||||
public:
|
||||
nsFloaterCache();
|
||||
~nsFloaterCache() { }
|
||||
|
||||
nsFloaterCache* Next() const { return mNext; }
|
||||
|
||||
nsPlaceholderFrame* mPlaceholder; // nsPlaceholderFrame
|
||||
|
||||
// This will be true if the floater was placed on the current line
|
||||
// instead of below the current line.
|
||||
PRBool mIsCurrentLineFloater;
|
||||
|
||||
nsMargin mMargins; // computed margins
|
||||
|
||||
nsMargin mOffsets; // computed offsets (relative pos)
|
||||
|
||||
// Region in the spacemanager impacted by this floater; the
|
||||
// coordinates are relative to the containing block frame. The
|
||||
// region includes the margins around the floater, but doesn't
|
||||
// include the relative offsets.
|
||||
nsRect mRegion;
|
||||
|
||||
// Combined area for the floater. This will not include the margins
|
||||
// for the floater. Like mRegion, the coordinates are relative to
|
||||
// the containing block frame.
|
||||
nsRect mCombinedArea;
|
||||
|
||||
protected:
|
||||
nsFloaterCache* mNext;
|
||||
|
||||
friend class nsFloaterCacheList;
|
||||
friend class nsFloaterCacheFreeList;
|
||||
};
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
class nsFloaterCacheList {
|
||||
public:
|
||||
nsFloaterCacheList() : mHead(nsnull) { }
|
||||
~nsFloaterCacheList();
|
||||
|
||||
PRBool IsEmpty() const {
|
||||
return nsnull == mHead;
|
||||
}
|
||||
|
||||
PRBool NotEmpty() const {
|
||||
return nsnull != mHead;
|
||||
}
|
||||
|
||||
nsFloaterCache* Head() const {
|
||||
return mHead;
|
||||
}
|
||||
|
||||
nsFloaterCache* Tail() const;
|
||||
|
||||
nsFloaterCache* Find(nsIFrame* aOutOfFlowFrame);
|
||||
|
||||
void Remove(nsFloaterCache* aElement);
|
||||
|
||||
void Append(nsFloaterCacheFreeList& aList);
|
||||
|
||||
protected:
|
||||
nsFloaterCache* mHead;
|
||||
|
||||
friend class nsFloaterCacheFreeList;
|
||||
};
|
||||
|
||||
//---------------------------------------
|
||||
|
||||
class nsFloaterCacheFreeList : public nsFloaterCacheList {
|
||||
public:
|
||||
nsFloaterCacheFreeList() : mTail(nsnull) { }
|
||||
~nsFloaterCacheFreeList() { }
|
||||
|
||||
// Steal away aList's nsFloaterCache objects and put them on this
|
||||
// free-list.
|
||||
void Append(nsFloaterCacheList& aList);
|
||||
|
||||
void Append(nsFloaterCache* aFloaterCache);
|
||||
|
||||
// Allocate a new nsFloaterCache object
|
||||
nsFloaterCache* Alloc();
|
||||
|
||||
protected:
|
||||
nsFloaterCache* mTail;
|
||||
|
||||
friend class nsFloaterCacheList;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The nsLineBox class represents a horizontal line of frames. It contains
|
||||
* enough state to support incremental reflow of the frames, event handling
|
||||
|
@ -92,6 +193,19 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void SetLineIsImpactedByFloater(PRBool aValue) {
|
||||
if (aValue) {
|
||||
mState |= LINE_IS_IMPACTED_BY_FLOATER;
|
||||
}
|
||||
else {
|
||||
mState &= ~LINE_IS_IMPACTED_BY_FLOATER;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool IsImpactedByFloater() const {
|
||||
return 0 != (LINE_IS_IMPACTED_BY_FLOATER & mState);
|
||||
}
|
||||
|
||||
#ifdef BLOCK_DOES_FIRST_LINE
|
||||
PRBool IsFirstLine() const {
|
||||
return 0 != (LINE_IS_FIRST_LINE & mState);
|
||||
|
@ -150,7 +264,7 @@ public:
|
|||
nsRect mBounds;
|
||||
nsRect mCombinedArea;
|
||||
nscoord mCarriedOutBottomMargin;/* XXX switch to 16 bits */
|
||||
nsVoidArray* mFloaters;
|
||||
nsFloaterCacheList mFloaters;
|
||||
nsLineBox* mNext;
|
||||
nscoord mMaxElementWidth; // width part of max-element-size
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче