From fa8b53c57c38151414f730fb3ac3b30e2e908751 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 24 Jul 2009 09:32:32 -0400 Subject: [PATCH] Bug 505482. Make sure to not leave frames on overflow lists when we interrupt reflow. Also fixes bug 478527 and bug 496742. r=roc --- layout/generic/nsBlockFrame.cpp | 10 +++++++++ layout/generic/nsColumnSetFrame.cpp | 3 +++ layout/generic/nsIFrame.h | 6 ++++++ layout/generic/nsInlineFrame.cpp | 33 +++++++++++++++++++++++++++++ layout/generic/nsInlineFrame.h | 4 ++++ 5 files changed, 56 insertions(+) diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 109c989fe5d..429367e4ba6 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -1857,6 +1857,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState) aState.ReconstructMarginAbove(line); } + PRBool reflowedPrevLine = !needToRecoverState; if (needToRecoverState) { needToRecoverState = PR_FALSE; @@ -2001,6 +2002,15 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState) } needToRecoverState = PR_TRUE; + + if (reflowedPrevLine && !line->IsBlock() && + aState.mPresContext->HasPendingInterrupt()) { + // Need to make sure to pull overflows from any prev-in-flows + for (nsIFrame* inlineKid = line->mFirstChild; inlineKid; + inlineKid = inlineKid->GetFirstChild(nsnull)) { + inlineKid->PullOverflowsFromPrevInFlow(); + } + } } // Record if we need to clear floats before reflowing the next diff --git a/layout/generic/nsColumnSetFrame.cpp b/layout/generic/nsColumnSetFrame.cpp index 4f678a19567..9b5eabcf91f 100644 --- a/layout/generic/nsColumnSetFrame.cpp +++ b/layout/generic/nsColumnSetFrame.cpp @@ -901,6 +901,9 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + // Don't support interruption in columns + nsPresContext::InterruptPreventer noInterrupts(aPresContext); + DO_GLOBAL_REFLOW_COUNT("nsColumnSetFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index bd23376e622..f74ee20b08a 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -2315,6 +2315,12 @@ NS_PTR_TO_INT32(frame->GetProperty(nsGkAtoms::embeddingLevel)) */ virtual nsILineIterator* GetLineIterator() = 0; + /** + * If this frame is a next-in-flow, and its prev-in-flow has something on its + * overflow list, pull those frames into the child list of this one. + */ + virtual void PullOverflowsFromPrevInFlow() {} + protected: // Members nsRect mRect; diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index 3a42e236da6..c347c001990 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -398,6 +398,21 @@ nsInlineFrame::CanContinueTextRun() const return PR_TRUE; } +/* virtual */ void +nsInlineFrame::PullOverflowsFromPrevInFlow() +{ + nsInlineFrame* prevInFlow = static_cast(GetPrevInFlow()); + if (prevInFlow) { + nsPresContext* presContext = PresContext(); + nsIFrame* prevOverflowFrames = + prevInFlow->GetOverflowFrames(presContext, PR_TRUE); + if (prevOverflowFrames) { + // Assume that our prev-in-flow has the same line container that we do. + mFrames.InsertFrames(this, nsnull, prevOverflowFrames); + } + } +} + nsresult nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, @@ -1036,6 +1051,24 @@ nsFirstLineFrame::Reflow(nsPresContext* aPresContext, return rv; } +/* virtual */ void +nsFirstLineFrame::PullOverflowsFromPrevInFlow() +{ + nsFirstLineFrame* prevInFlow = static_cast(GetPrevInFlow()); + if (prevInFlow) { + nsPresContext* presContext = PresContext(); + nsIFrame* prevOverflowFrames = + prevInFlow->GetOverflowFrames(presContext, PR_TRUE); + if (prevOverflowFrames) { + nsFrameList frames(prevOverflowFrames); + + // Assume that our prev-in-flow has the same line container that we do. + mFrames.InsertFrames(this, nsnull, prevOverflowFrames); + ReParentChildListStyle(presContext, frames, this); + } + } +} + ////////////////////////////////////////////////////////////////////// nsIFrame* diff --git a/layout/generic/nsInlineFrame.h b/layout/generic/nsInlineFrame.h index 1a613cf4a10..6feedcec7de 100644 --- a/layout/generic/nsInlineFrame.h +++ b/layout/generic/nsInlineFrame.h @@ -123,6 +123,8 @@ public: virtual PRBool CanContinueTextRun() const; + virtual void PullOverflowsFromPrevInFlow(); + // Take all of the frames away from this frame. The caller is // presumed to keep them alive. void StealAllFrames() { @@ -222,6 +224,8 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + virtual void PullOverflowsFromPrevInFlow(); + // Take frames starting at aFrame until the end of the frame-list // away from this frame. The caller is presumed to keep them alive. void StealFramesFrom(nsIFrame* aFrame);