Bug 422283. Make sure that an overflow container's next-in-flows are always also overflow containers. This means that when we convert a normal frame into an overflow container, we need to scan through its next-in-flows and make them overflow containers too. r=fantasai,sr=mats

This commit is contained in:
Robert O'Callahan 2008-09-06 20:48:09 +12:00
parent b45eb57f56
commit dd26ad1004
4 changed files with 75 additions and 19 deletions

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head></head>
<body style="-moz-column-width: 1px;"><div style="padding: 150px 0; height: 80px;"><span>
</span>x<div></div><span>
</span>a ! b c<div></div>
</div></body>
</html>

View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
div { height: .5em; margin: 1em; }
</style>
<script type="text/javascript">
function boom()
{
document.getElementById("b").style.padding = "";
document.getElementById("a").style.padding = "12em";
}
</script>
</head>
<body onload="boom();" style="-moz-column-width: 2em;"><div id="a"></div><div></div><div></div><div id="b" style="padding: 12em;">This is text</div>This is textThis is text<div>This is text</div></body>
</html>

View File

@ -137,6 +137,8 @@ load 416264-1.html
load 416476-1.html
load 418532-1.html
load 421404-1.html
load 422283-1.html
load 422301-1.html
load 425253-1.html
load 430352-1.html
load 448903-1.html

View File

@ -1440,9 +1440,10 @@ nsOverflowContinuationTracker::Insert(nsIFrame* aOverflowCont,
NS_PRECONDITION(aOverflowCont->GetPrevInFlow(),
"overflow containers must have a prev-in-flow");
nsresult rv = NS_OK;
PRBool convertedToOverflowContainer = PR_FALSE;
nsPresContext* presContext = aOverflowCont->PresContext();
if (!mSentry || aOverflowCont != mSentry->GetNextInFlow()) {
// Not in our list, so we need to add it
nsPresContext* presContext = aOverflowCont->PresContext();
if (aOverflowCont->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
// aOverflowCont is in some other overflow container list,
// steal it first
@ -1455,6 +1456,7 @@ nsOverflowContinuationTracker::Insert(nsIFrame* aOverflowCont,
}
else {
aOverflowCont->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
convertedToOverflowContainer = PR_TRUE;
}
if (!mOverflowContList) {
mOverflowContList = new nsFrameList();
@ -1483,6 +1485,20 @@ nsOverflowContinuationTracker::Insert(nsIFrame* aOverflowCont,
(mPrevOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW) !=
(aOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW)),
"OverflowContTracker in unexpected state");
if (convertedToOverflowContainer) {
// Convert all non-overflow-container continuations of aOverflowCont
// into overflow containers and move them to our overflow
// tracker. This preserves the invariant that the next-continuations
// of an overflow container are also overflow containers.
nsIFrame* f = aOverflowCont->GetNextContinuation();
if (f && !(f->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
nsContainerFrame* parent = static_cast<nsContainerFrame*>(f->GetParent());
rv = parent->StealFrame(presContext, f);
NS_ENSURE_SUCCESS(rv, rv);
Insert(f, aReflowStatus);
}
}
return rv;
}
@ -1492,24 +1508,28 @@ nsOverflowContinuationTracker::Finish(nsIFrame* aChild)
NS_PRECONDITION(aChild, "null ptr");
NS_PRECONDITION(aChild->GetNextInFlow(),
"supposed to call Finish *before* deleting next-in-flow!");
if (aChild == mSentry) {
// Make sure we drop all references if this was the only frame
// in the overflow containers list
if (mOverflowContList->FirstChild() == aChild->GetNextInFlow()
&& !aChild->GetNextInFlow()->GetNextSibling()) {
mOverflowContList = nsnull;
mPrevOverflowCont = nsnull;
mSentry = nsnull;
mParent = static_cast<nsContainerFrame*>(aChild->GetParent());
}
else {
// Step past aChild
nsIFrame* prevOverflowCont = mPrevOverflowCont;
StepForward();
if (mPrevOverflowCont == aChild->GetNextInFlow()) {
// Pull mPrevOverflowChild back to aChild's prevSibling:
// aChild will be removed from our list by our caller
mPrevOverflowCont = prevOverflowCont;
for (nsIFrame* f = aChild; f; f = f->GetNextInFlow()) {
if (f == mSentry) {
// Make sure we drop all references if this was the only frame
// in the overflow containers list
if (mOverflowContList->FirstChild() == f->GetNextInFlow()
&& !f->GetNextInFlow()->GetNextSibling()) {
mOverflowContList = nsnull;
mPrevOverflowCont = nsnull;
mSentry = nsnull;
mParent = static_cast<nsContainerFrame*>(f->GetParent());
break;
}
else {
// Step past aChild
nsIFrame* prevOverflowCont = mPrevOverflowCont;
StepForward();
if (mPrevOverflowCont == f->GetNextInFlow()) {
// Pull mPrevOverflowChild back to aChild's prevSibling:
// aChild will be removed from our list by our caller
mPrevOverflowCont = prevOverflowCont;
}
}
}
}