From 4dcbca8b3c26b451e1376cd1b7c88ab984a45b39 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Tue, 14 Apr 2015 22:12:39 -0400 Subject: [PATCH] Bug 1143299 - Make frame insertion methods deal with aPrevFrame being on an overflow list. r=roc, a=bkerensa --- layout/generic/nsBlockFrame.cpp | 18 ++++++++++++--- layout/generic/nsBlockFrame.h | 14 ++++++++---- layout/generic/nsContainerFrame.cpp | 41 +++++++++++++++++++--------------- layout/tables/nsTableFrame.cpp | 2 ++ layout/tables/nsTableRowFrame.cpp | 2 ++ layout/tables/nsTableRowGroupFrame.cpp | 2 ++ 6 files changed, 54 insertions(+), 25 deletions(-) diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index a011bcf..70d5297 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -1049,7 +1049,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext, state.mOverflowTracker = &tracker; // Drain & handle pushed floats - DrainPushedFloats(state); + DrainPushedFloats(); nsOverflowAreas fcBounds; nsReflowStatus fcStatus = NS_FRAME_COMPLETE; ReflowPushedFloats(state, fcBounds, fcStatus); @@ -4438,9 +4438,13 @@ nsBlockFrame::DrainSelfOverflowList() * might push some of them on). Floats with placeholders in this block * are reflowed by (nsBlockReflowState/nsLineLayout)::AddFloat, which * also maintains these invariants. + * + * DrainSelfPushedFloats moves any pushed floats from this block's own + * PushedFloats list back into mFloats. DrainPushedFloats additionally + * moves frames from its prev-in-flow's PushedFloats list into mFloats. */ void -nsBlockFrame::DrainPushedFloats(nsBlockReflowState& aState) +nsBlockFrame::DrainSelfPushedFloats() { #ifdef DEBUG // Between when we drain pushed floats and when we complete reflow, @@ -4503,12 +4507,18 @@ nsBlockFrame::DrainPushedFloats(nsBlockReflowState& aState) RemovePushedFloats()->Delete(presContext->PresShell()); } } +} + +void +nsBlockFrame::DrainPushedFloats() +{ + DrainSelfPushedFloats(); // After our prev-in-flow has completed reflow, it may have a pushed // floats list, containing floats that we need to own. Take these. nsBlockFrame* prevBlock = static_cast(GetPrevInFlow()); if (prevBlock) { - AutoFrameListPtr list(presContext, prevBlock->RemovePushedFloats()); + AutoFrameListPtr list(PresContext(), prevBlock->RemovePushedFloats()); if (list && list->NotEmpty()) { mFloats.InsertFrames(this, nullptr, *list); } @@ -4711,6 +4721,7 @@ nsBlockFrame::AppendFrames(ChildListID aListID, return nsContainerFrame::AppendFrames(aListID, aFrameList); } else if (kFloatList == aListID) { + DrainSelfPushedFloats(); // ensure the last frame is in mFloats mFloats.AppendFrames(nullptr, aFrameList); return NS_OK; } @@ -4757,6 +4768,7 @@ nsBlockFrame::InsertFrames(ChildListID aListID, return nsContainerFrame::InsertFrames(aListID, aPrevFrame, aFrameList); } else if (kFloatList == aListID) { + DrainSelfPushedFloats(); // ensure aPrevFrame is in mFloats mFloats.InsertFrames(this, aPrevFrame, aFrameList); return NS_OK; } diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h index 1a6bb1e..07f7508 100644 --- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -533,10 +533,16 @@ protected: return GetStateBits() & NS_BLOCK_HAS_OVERFLOW_OUT_OF_FLOWS; } - /** grab pushed floats from this block's prevInFlow, and splice - * them into this block's mFloats list. - */ - void DrainPushedFloats(nsBlockReflowState& aState); + /** + * Moves frames from our PushedFloats list back into our mFloats list. + */ + void DrainSelfPushedFloats(); + + /** + * First calls DrainSelfPushedFloats() then grabs pushed floats from this + * block's prev-in-flow, and splice them into this block's mFloats list too. + */ + void DrainPushedFloats(); /** Load all our floats into the float manager (without reflowing them). * Assumes float manager is in our own coordinate system. diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index 76f0748..3ffcba7 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -102,16 +102,18 @@ nsContainerFrame::AppendFrames(ChildListID aListID, return NS_ERROR_INVALID_ARG; } } - if (aFrameList.NotEmpty()) { - mFrames.AppendFrames(this, aFrameList); - // Ask the parent frame to reflow me. - if (aListID == kPrincipalList) - { - PresContext()->PresShell()-> - FrameNeedsReflow(this, nsIPresShell::eTreeChange, - NS_FRAME_HAS_DIRTY_CHILDREN); - } + if (MOZ_UNLIKELY(aFrameList.IsEmpty())) { + return NS_OK; + } + + DrainSelfOverflowList(); // ensure the last frame is in mFrames + mFrames.AppendFrames(this, aFrameList); + + if (aListID != kNoReflowPrincipalList) { + PresContext()->PresShell()-> + FrameNeedsReflow(this, nsIPresShell::eTreeChange, + NS_FRAME_HAS_DIRTY_CHILDREN); } return NS_OK; } @@ -131,16 +133,19 @@ nsContainerFrame::InsertFrames(ChildListID aListID, return NS_ERROR_INVALID_ARG; } } - if (aFrameList.NotEmpty()) { - // Insert frames after aPrevFrame - mFrames.InsertFrames(this, aPrevFrame, aFrameList); - if (aListID == kPrincipalList) - { - PresContext()->PresShell()-> - FrameNeedsReflow(this, nsIPresShell::eTreeChange, - NS_FRAME_HAS_DIRTY_CHILDREN); - } + if (MOZ_UNLIKELY(aFrameList.IsEmpty())) { + return NS_OK; + } + + DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames + mFrames.InsertFrames(this, aPrevFrame, aFrameList); + + if (aListID != kNoReflowPrincipalList) { + PresContext()->PresShell()-> + FrameNeedsReflow(this, nsIPresShell::eTreeChange, + NS_FRAME_HAS_DIRTY_CHILDREN); + } return NS_OK; } diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index 60613ba..44088da 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -2232,6 +2232,7 @@ nsTableFrame::AppendFrames(ChildListID aListID, InsertColGroups(startColIndex, nsFrameList::Slice(mColGroups, f, f->GetNextSibling())); } else if (IsRowGroup(display->mDisplay)) { + DrainSelfOverflowList(); // ensure the last frame is in mFrames // Append the new row group frame to the sibling chain mFrames.AppendFrame(nullptr, f); @@ -2404,6 +2405,7 @@ nsTableFrame::HomogenousInsertFrames(ChildListID aListID, InsertColGroups(startColIndex, newColgroups); } else if (IsRowGroup(display->mDisplay)) { NS_ASSERTION(aListID == kPrincipalList, "unexpected child list"); + DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames // Insert the frames in the sibling chain const nsFrameList::Slice& newRowGroups = mFrames.InsertFrames(nullptr, aPrevFrame, aFrameList); diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp index d1c493b..2351de3 100644 --- a/layout/tables/nsTableRowFrame.cpp +++ b/layout/tables/nsTableRowFrame.cpp @@ -182,6 +182,7 @@ nsTableRowFrame::AppendFrames(ChildListID aListID, { NS_ASSERTION(aListID == kPrincipalList, "unexpected child list"); + DrainSelfOverflowList(); // ensure the last frame is in mFrames const nsFrameList::Slice& newCells = mFrames.AppendFrames(nullptr, aFrameList); // Add the new cell frames to the table @@ -208,6 +209,7 @@ nsTableRowFrame::InsertFrames(ChildListID aListID, NS_ASSERTION(aListID == kPrincipalList, "unexpected child list"); NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this, "inserting after sibling frame with different parent"); + DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames //Insert Frames in the frame list const nsFrameList::Slice& newCells = mFrames.InsertFrames(nullptr, aPrevFrame, aFrameList); diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp index 34aaf02..40b349b 100644 --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -1389,6 +1389,7 @@ nsTableRowGroupFrame::AppendFrames(ChildListID aListID, { NS_ASSERTION(aListID == kPrincipalList, "unexpected child list"); + DrainSelfOverflowList(); // ensure the last frame is in mFrames ClearRowCursor(); // collect the new row frames in an array @@ -1430,6 +1431,7 @@ nsTableRowGroupFrame::InsertFrames(ChildListID aListID, NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this, "inserting after sibling frame with different parent"); + DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames ClearRowCursor(); // collect the new row frames in an array -- 2.2.1