Allow the float manager to record that a float has been pushed past a break. (Bug 563584, patch 9) r=roc

This commit is contained in:
L. David Baron 2010-08-05 21:59:19 -07:00
parent f6db316887
commit c804c1c09e
6 changed files with 86 additions and 2 deletions

View File

@ -72,7 +72,9 @@ PSArenaFreeCB(size_t aSize, void* aPtr, void* aClosure)
nsFloatManager::nsFloatManager(nsIPresShell* aPresShell)
: mX(0), mY(0),
mFloatDamage(PSArenaAllocCB, PSArenaFreeCB, aPresShell)
mFloatDamage(PSArenaAllocCB, PSArenaFreeCB, aPresShell),
mPushedLeftFloatPastBreak(PR_FALSE),
mPushedRightFloatPastBreak(PR_FALSE)
{
MOZ_COUNT_CTOR(nsFloatManager);
}
@ -415,6 +417,8 @@ nsFloatManager::PushState(SavedState* aState)
// reflows ensures that nothing gets missed.
aState->mX = mX;
aState->mY = mY;
aState->mPushedLeftFloatPastBreak = mPushedLeftFloatPastBreak;
aState->mPushedRightFloatPastBreak = mPushedRightFloatPastBreak;
aState->mFloatInfoCount = mFloats.Length();
}
@ -425,6 +429,8 @@ nsFloatManager::PopState(SavedState* aState)
mX = aState->mX;
mY = aState->mY;
mPushedLeftFloatPastBreak = aState->mPushedLeftFloatPastBreak;
mPushedRightFloatPastBreak = aState->mPushedRightFloatPastBreak;
NS_ASSERTION(aState->mFloatInfoCount <= mFloats.Length(),
"somebody misused PushState/PopState");
@ -434,6 +440,9 @@ nsFloatManager::PopState(SavedState* aState)
nscoord
nsFloatManager::GetLowestFloatTop() const
{
if (mPushedLeftFloatPastBreak || mPushedRightFloatPastBreak) {
return nscoord_MAX;
}
if (!HasAnyFloats()) {
return nscoord_MIN;
}
@ -467,6 +476,9 @@ nsFloatManager::List(FILE* out) const
nscoord
nsFloatManager::ClearFloats(nscoord aY, PRUint8 aBreakType) const
{
if (ClearContinues(aBreakType)) {
return nscoord_MAX;
}
if (!HasAnyFloats()) {
return aY;
}
@ -498,8 +510,19 @@ 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()) {

View File

@ -111,7 +111,9 @@ public:
private:
PRUint32 mFloatInfoCount;
nscoord mX, mY;
PRPackedBool mPushedLeftFloatPastBreak;
PRPackedBool mPushedRightFloatPastBreak;
friend class nsFloatManager;
};
@ -181,6 +183,17 @@ public:
*/
nsresult AddFloat(nsIFrame* aFloatFrame, const nsRect& aMarginRect);
/**
* 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.)
*/
void SetPushedLeftFloatPastBreak()
{ mPushedLeftFloatPastBreak = PR_TRUE; }
void SetPushedRightFloatPastBreak()
{ mPushedRightFloatPastBreak = PR_TRUE; }
/**
* Remove the regions associated with this floating frame and its
* next-sibling list. Some of the frames may never have been added;
@ -259,6 +272,10 @@ public:
void AssertStateMatches(SavedState *aState) const
{
NS_ASSERTION(aState->mX == mX && aState->mY == mY &&
aState->mPushedLeftFloatPastBreak ==
mPushedLeftFloatPastBreak &&
aState->mPushedRightFloatPastBreak ==
mPushedRightFloatPastBreak &&
aState->mFloatInfoCount == mFloats.Length(),
"float manager state should match saved state");
}
@ -289,6 +306,15 @@ private:
nsTArray<FloatInfo> mFloats;
nsIntervalSet mFloatDamage;
// Did we try 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. And we also
// need to apply this information to 'clear', and thus need to
// separate left and right floats.
PRPackedBool mPushedLeftFloatPastBreak;
PRPackedBool mPushedRightFloatPastBreak;
static PRInt32 sCachedFloatManagerCount;
static void* sCachedFloatManagers[NS_FLOAT_MANAGER_CACHE_SIZE];

View File

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<html class="reftest-print">
<title>Test that nsFloatManager::ClearFloats calls ClearContinues</title>
<body style="margin: 0">
<div style="background: aqua; height: 1in; width: 1in"></div>
<div style="page-break-before: always; background: fuchsia; height: 1.5in; width: 1in"></div>
<div style="height: 0.25in; background: yellow; width: 1in"></div>

View File

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html class="reftest-print">
<title>Test that nsFloatManager::ClearFloats calls ClearContinues</title>
<body style="margin: 0">
<div style="float: left;">
<div>
<div style="display:inline-block; vertical-align: top; background: aqua; height: 1in; width: 1in"></div>
</div>
<div>
<div style="display:inline-block; vertical-align: top; background: fuchsia; height: 1.5in; width: 1in"></div>
</div>
</div>
<div style="float: left; clear: left; height: 0.25in; background: yellow; width: 1in"></div>

View File

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html class="reftest-print">
<title>Test that nsFloatManager::ClearFloats calls ClearContinues</title>
<body style="margin: 0">
<div style="float: left;">
<div>
<div style="display:inline-block; vertical-align: top; background: aqua; height: 1in; width: 1in"></div>
</div>
<div>
<div style="display:inline-block; vertical-align: top; background: fuchsia; height: 1.5in; width: 1in"></div>
</div>
</div>
<div style="clear: left; height: 0.25in; background: yellow; width: 1in"></div>

View File

@ -1456,6 +1456,8 @@ random-if(!haveTestPlugin) == 546071-1.html 546071-1-ref.html
== 563584-9b.html 563584-9b-ref.html
== 563584-9c.html 563584-9cd-ref.html
== 563584-9d.html 563584-9cd-ref.html
== 563584-10a.html 563584-10-ref.html
== 563584-10b.html 563584-10-ref.html
== 564054-1.html 564054-1-ref.html
== 564991-1.html 564991-1-ref.html
== 565819-1.html 565819-ref.html