Add the optimization mentioned in the previous patch, so we don't have to iterate all floats to determine if one was split. (Bug 563584, patch 10) r=roc

This commit is contained in:
L. David Baron 2010-08-05 21:59:19 -07:00
Родитель 43782767d3
Коммит bc27ba3246
3 изменённых файлов: 45 добавлений и 29 удалений

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

@ -3907,6 +3907,14 @@ nsBlockFrame::SplitFloat(nsBlockReflowState& aState,
// Make sure the containing block knows about the float's status // Make sure the containing block knows about the float's status
NS_MergeReflowStatusInto(&aState.mReflowStatus, aFloatStatus); NS_MergeReflowStatusInto(&aState.mReflowStatus, aFloatStatus);
if (aFloat->GetStyleDisplay()->mFloats == NS_STYLE_FLOAT_LEFT) {
aState.mFloatManager->SetSplitLeftFloatAcrossBreak();
} else {
NS_ABORT_IF_FALSE(aFloat->GetStyleDisplay()->mFloats ==
NS_STYLE_FLOAT_RIGHT, "unexpected float side");
aState.mFloatManager->SetSplitRightFloatAcrossBreak();
}
if (nextInFlow) { if (nextInFlow) {
// Next in flow was created above. // Next in flow was created above.
aState.AppendFloatContinuation(nextInFlow); aState.AppendFloatContinuation(nextInFlow);

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

@ -74,7 +74,9 @@ nsFloatManager::nsFloatManager(nsIPresShell* aPresShell)
: mX(0), mY(0), : mX(0), mY(0),
mFloatDamage(PSArenaAllocCB, PSArenaFreeCB, aPresShell), mFloatDamage(PSArenaAllocCB, PSArenaFreeCB, aPresShell),
mPushedLeftFloatPastBreak(PR_FALSE), mPushedLeftFloatPastBreak(PR_FALSE),
mPushedRightFloatPastBreak(PR_FALSE) mPushedRightFloatPastBreak(PR_FALSE),
mSplitLeftFloatAcrossBreak(PR_FALSE),
mSplitRightFloatAcrossBreak(PR_FALSE)
{ {
MOZ_COUNT_CTOR(nsFloatManager); MOZ_COUNT_CTOR(nsFloatManager);
} }
@ -419,6 +421,8 @@ nsFloatManager::PushState(SavedState* aState)
aState->mY = mY; aState->mY = mY;
aState->mPushedLeftFloatPastBreak = mPushedLeftFloatPastBreak; aState->mPushedLeftFloatPastBreak = mPushedLeftFloatPastBreak;
aState->mPushedRightFloatPastBreak = mPushedRightFloatPastBreak; aState->mPushedRightFloatPastBreak = mPushedRightFloatPastBreak;
aState->mSplitLeftFloatAcrossBreak = mSplitLeftFloatAcrossBreak;
aState->mSplitRightFloatAcrossBreak = mSplitRightFloatAcrossBreak;
aState->mFloatInfoCount = mFloats.Length(); aState->mFloatInfoCount = mFloats.Length();
} }
@ -431,6 +435,8 @@ nsFloatManager::PopState(SavedState* aState)
mY = aState->mY; mY = aState->mY;
mPushedLeftFloatPastBreak = aState->mPushedLeftFloatPastBreak; mPushedLeftFloatPastBreak = aState->mPushedLeftFloatPastBreak;
mPushedRightFloatPastBreak = aState->mPushedRightFloatPastBreak; mPushedRightFloatPastBreak = aState->mPushedRightFloatPastBreak;
mSplitLeftFloatAcrossBreak = aState->mSplitLeftFloatAcrossBreak;
mSplitRightFloatAcrossBreak = aState->mSplitRightFloatAcrossBreak;
NS_ASSERTION(aState->mFloatInfoCount <= mFloats.Length(), NS_ASSERTION(aState->mFloatInfoCount <= mFloats.Length(),
"somebody misused PushState/PopState"); "somebody misused PushState/PopState");
@ -510,33 +516,12 @@ nsFloatManager::ClearFloats(nscoord aY, PRUint8 aBreakType) const
PRBool PRBool
nsFloatManager::ClearContinues(PRUint8 aBreakType) const nsFloatManager::ClearContinues(PRUint8 aBreakType) const
{ {
if ((mPushedLeftFloatPastBreak && return ((mPushedLeftFloatPastBreak || mSplitLeftFloatAcrossBreak) &&
(aBreakType == NS_STYLE_CLEAR_LEFT_AND_RIGHT || (aBreakType == NS_STYLE_CLEAR_LEFT_AND_RIGHT ||
aBreakType == NS_STYLE_CLEAR_LEFT)) || aBreakType == NS_STYLE_CLEAR_LEFT)) ||
(mPushedRightFloatPastBreak && ((mPushedRightFloatPastBreak || mSplitRightFloatAcrossBreak) &&
(aBreakType == NS_STYLE_CLEAR_LEFT_AND_RIGHT || (aBreakType == NS_STYLE_CLEAR_LEFT_AND_RIGHT ||
aBreakType == NS_STYLE_CLEAR_RIGHT))) { aBreakType == NS_STYLE_CLEAR_RIGHT));
return PR_TRUE;
}
if (!HasAnyFloats() || aBreakType == NS_STYLE_CLEAR_NONE)
return PR_FALSE;
// FIXME: We could make this faster by recording whenever we split a
// float (in addition to recording whenever we push a float in its
// entirety).
for (PRUint32 i = mFloats.Length(); i > 0; i--) {
nsIFrame* f = mFloats[i-1].mFrame;
if (f->GetNextInFlow()) {
if (aBreakType == NS_STYLE_CLEAR_LEFT_AND_RIGHT)
return PR_TRUE;
PRUint8 floatSide = f->GetStyleDisplay()->mFloats;
if ((aBreakType == NS_STYLE_CLEAR_LEFT &&
floatSide == NS_STYLE_FLOAT_LEFT) ||
(aBreakType == NS_STYLE_CLEAR_RIGHT &&
floatSide == NS_STYLE_FLOAT_RIGHT))
return PR_TRUE;
}
}
return PR_FALSE;
} }
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////

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

@ -113,6 +113,8 @@ public:
nscoord mX, mY; nscoord mX, mY;
PRPackedBool mPushedLeftFloatPastBreak; PRPackedBool mPushedLeftFloatPastBreak;
PRPackedBool mPushedRightFloatPastBreak; PRPackedBool mPushedRightFloatPastBreak;
PRPackedBool mSplitLeftFloatAcrossBreak;
PRPackedBool mSplitRightFloatAcrossBreak;
friend class nsFloatManager; friend class nsFloatManager;
}; };
@ -187,13 +189,24 @@ public:
* Notify that we tried to place a float that could not fit at all and * Notify that we tried to place a float that could not fit at all and
* had to be pushed to the next page/column? (If so, we can't place * had to be pushed to the next page/column? (If so, we can't place
* any more floats in this page/column because of the rule that the * any more floats in this page/column because of the rule that the
* top of a float cannot be above the top of an earlier float.) * top of a float cannot be above the top of an earlier float. It
* also means that any clear needs to continue to the next column.)
*/ */
void SetPushedLeftFloatPastBreak() void SetPushedLeftFloatPastBreak()
{ mPushedLeftFloatPastBreak = PR_TRUE; } { mPushedLeftFloatPastBreak = PR_TRUE; }
void SetPushedRightFloatPastBreak() void SetPushedRightFloatPastBreak()
{ mPushedRightFloatPastBreak = PR_TRUE; } { mPushedRightFloatPastBreak = PR_TRUE; }
/**
* Notify that we split a float, with part of it needing to be pushed
* to the next page/column. (This means that any 'clear' needs to
* continue to the next page/column.)
*/
void SetSplitLeftFloatAcrossBreak()
{ mSplitLeftFloatAcrossBreak = PR_TRUE; }
void SetSplitRightFloatAcrossBreak()
{ mSplitRightFloatAcrossBreak = PR_TRUE; }
/** /**
* Remove the regions associated with this floating frame and its * Remove the regions associated with this floating frame and its
* next-sibling list. Some of the frames may never have been added; * next-sibling list. Some of the frames may never have been added;
@ -276,6 +289,10 @@ public:
mPushedLeftFloatPastBreak && mPushedLeftFloatPastBreak &&
aState->mPushedRightFloatPastBreak == aState->mPushedRightFloatPastBreak ==
mPushedRightFloatPastBreak && mPushedRightFloatPastBreak &&
aState->mSplitLeftFloatAcrossBreak ==
mSplitLeftFloatAcrossBreak &&
aState->mSplitRightFloatAcrossBreak ==
mSplitRightFloatAcrossBreak &&
aState->mFloatInfoCount == mFloats.Length(), aState->mFloatInfoCount == mFloats.Length(),
"float manager state should match saved state"); "float manager state should match saved state");
} }
@ -315,6 +332,12 @@ private:
PRPackedBool mPushedLeftFloatPastBreak; PRPackedBool mPushedLeftFloatPastBreak;
PRPackedBool mPushedRightFloatPastBreak; PRPackedBool mPushedRightFloatPastBreak;
// Did we split a float, with part of it needing to be pushed to the
// next page/column. This means that any 'clear' needs to continue to
// the next page/column.
PRPackedBool mSplitLeftFloatAcrossBreak;
PRPackedBool mSplitRightFloatAcrossBreak;
static PRInt32 sCachedFloatManagerCount; static PRInt32 sCachedFloatManagerCount;
static void* sCachedFloatManagers[NS_FLOAT_MANAGER_CACHE_SIZE]; static void* sCachedFloatManagers[NS_FLOAT_MANAGER_CACHE_SIZE];