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
parent c804c1c09e
commit 771fb25729
3 changed files with 45 additions and 29 deletions

View File

@ -3907,6 +3907,14 @@ nsBlockFrame::SplitFloat(nsBlockReflowState& aState,
// Make sure the containing block knows about the float's status
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) {
// Next in flow was created above.
aState.AppendFloatContinuation(nextInFlow);

View File

@ -74,7 +74,9 @@ nsFloatManager::nsFloatManager(nsIPresShell* aPresShell)
: mX(0), mY(0),
mFloatDamage(PSArenaAllocCB, PSArenaFreeCB, aPresShell),
mPushedLeftFloatPastBreak(PR_FALSE),
mPushedRightFloatPastBreak(PR_FALSE)
mPushedRightFloatPastBreak(PR_FALSE),
mSplitLeftFloatAcrossBreak(PR_FALSE),
mSplitRightFloatAcrossBreak(PR_FALSE)
{
MOZ_COUNT_CTOR(nsFloatManager);
}
@ -419,6 +421,8 @@ nsFloatManager::PushState(SavedState* aState)
aState->mY = mY;
aState->mPushedLeftFloatPastBreak = mPushedLeftFloatPastBreak;
aState->mPushedRightFloatPastBreak = mPushedRightFloatPastBreak;
aState->mSplitLeftFloatAcrossBreak = mSplitLeftFloatAcrossBreak;
aState->mSplitRightFloatAcrossBreak = mSplitRightFloatAcrossBreak;
aState->mFloatInfoCount = mFloats.Length();
}
@ -431,6 +435,8 @@ nsFloatManager::PopState(SavedState* aState)
mY = aState->mY;
mPushedLeftFloatPastBreak = aState->mPushedLeftFloatPastBreak;
mPushedRightFloatPastBreak = aState->mPushedRightFloatPastBreak;
mSplitLeftFloatAcrossBreak = aState->mSplitLeftFloatAcrossBreak;
mSplitRightFloatAcrossBreak = aState->mSplitRightFloatAcrossBreak;
NS_ASSERTION(aState->mFloatInfoCount <= mFloats.Length(),
"somebody misused PushState/PopState");
@ -510,33 +516,12 @@ nsFloatManager::ClearFloats(nscoord aY, PRUint8 aBreakType) const
PRBool
nsFloatManager::ClearContinues(PRUint8 aBreakType) const
{
if ((mPushedLeftFloatPastBreak &&
(aBreakType == NS_STYLE_CLEAR_LEFT_AND_RIGHT ||
aBreakType == NS_STYLE_CLEAR_LEFT)) ||
(mPushedRightFloatPastBreak &&
(aBreakType == NS_STYLE_CLEAR_LEFT_AND_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;
return ((mPushedLeftFloatPastBreak || mSplitLeftFloatAcrossBreak) &&
(aBreakType == NS_STYLE_CLEAR_LEFT_AND_RIGHT ||
aBreakType == NS_STYLE_CLEAR_LEFT)) ||
((mPushedRightFloatPastBreak || mSplitRightFloatAcrossBreak) &&
(aBreakType == NS_STYLE_CLEAR_LEFT_AND_RIGHT ||
aBreakType == NS_STYLE_CLEAR_RIGHT));
}
/////////////////////////////////////////////////////////////////////////////

View File

@ -113,6 +113,8 @@ public:
nscoord mX, mY;
PRPackedBool mPushedLeftFloatPastBreak;
PRPackedBool mPushedRightFloatPastBreak;
PRPackedBool mSplitLeftFloatAcrossBreak;
PRPackedBool mSplitRightFloatAcrossBreak;
friend class nsFloatManager;
};
@ -187,13 +189,24 @@ public:
* 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
* 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()
{ mPushedLeftFloatPastBreak = PR_TRUE; }
void SetPushedRightFloatPastBreak()
{ 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
* next-sibling list. Some of the frames may never have been added;
@ -276,6 +289,10 @@ public:
mPushedLeftFloatPastBreak &&
aState->mPushedRightFloatPastBreak ==
mPushedRightFloatPastBreak &&
aState->mSplitLeftFloatAcrossBreak ==
mSplitLeftFloatAcrossBreak &&
aState->mSplitRightFloatAcrossBreak ==
mSplitRightFloatAcrossBreak &&
aState->mFloatInfoCount == mFloats.Length(),
"float manager state should match saved state");
}
@ -315,6 +332,12 @@ private:
PRPackedBool mPushedLeftFloatPastBreak;
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 void* sCachedFloatManagers[NS_FLOAT_MANAGER_CACHE_SIZE];