From 68ac87f2e424208ff23545b55011796a4c49e7e6 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Thu, 28 Feb 2013 00:05:45 +0100 Subject: [PATCH] Bug 838688 - Make ReparentFloats/CollectFloats not require a priori knowledge of which child list a float is expected to be on. r=bzbarsky --- layout/generic/nsBlockFrame.cpp | 53 ++++++++++++++++---------------- layout/generic/nsBlockFrame.h | 5 ++- layout/generic/nsInlineFrame.cpp | 7 +---- 3 files changed, 30 insertions(+), 35 deletions(-) diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 8e5189a865fa..73f223efc58b 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -1792,11 +1792,10 @@ static bool LineHasClear(nsLineBox* aLine) { * removed from the list. They end up appended to our mFloats list. */ void -nsBlockFrame::ReparentFloats(nsIFrame* aFirstFrame, - nsBlockFrame* aOldParent, bool aFromOverflow, +nsBlockFrame::ReparentFloats(nsIFrame* aFirstFrame, nsBlockFrame* aOldParent, bool aReparentSiblings) { nsFrameList list; - aOldParent->CollectFloats(aFirstFrame, list, aFromOverflow, aReparentSiblings); + aOldParent->CollectFloats(aFirstFrame, list, aReparentSiblings); if (list.NotEmpty()) { for (nsIFrame* f = list.FirstChild(); f; f = f->GetNextSibling()) { ReparentFrame(f, aOldParent, this); @@ -2247,7 +2246,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState) nsBlockFrame* nextInFlow = aState.mNextInFlow; nsLineBox* pulledLine; nsFrameList pulledFrames; - bool isOverflowLine = false; if (!nextInFlow->mLines.empty()) { RemoveFirstLine(nextInFlow->mLines, nextInFlow->mFrames, &pulledLine, &pulledFrames); @@ -2265,7 +2263,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState) if (last) { nextInFlow->DestroyOverflowLines(); } - isOverflowLine = true; } if (pulledFrames.IsEmpty()) { @@ -2295,7 +2292,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState) aState.mPrevChild = mFrames.LastChild(); // Reparent floats whose placeholders are in the line. - ReparentFloats(pulledLine->mFirstChild, nextInFlow, isOverflowLine, true); + ReparentFloats(pulledLine->mFirstChild, nextInFlow, true); DumpLine(aState, pulledLine, deltaY, 0); #ifdef DEBUG @@ -2595,7 +2592,7 @@ nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState, // The frame might have (or contain) floats that need to be // brought over too. - ReparentFloats(frame, aFromContainer, aFromOverflowLine, true); + ReparentFloats(frame, aFromContainer, true); } // when aFromContainer is 'this', then aLine->LastChild()'s next sibling // is already set correctly. @@ -4317,7 +4314,7 @@ nsBlockFrame::PushLines(nsBlockReflowState& aState, if (overBegin != end_lines()) { // Remove floats in the lines from mFloats nsFrameList floats; - CollectFloats(overBegin->mFirstChild, floats, false, true); + CollectFloats(overBegin->mFirstChild, floats, true); if (floats.NotEmpty()) { // Push the floats onto the front of the overflow out-of-flows list @@ -6899,7 +6896,7 @@ nsBlockFrame::ReflowBullet(nsIFrame* aBulletFrame, // are ignored (they are not added to aList). void nsBlockFrame::CollectFloats(nsIFrame* aFrame, nsFrameList& aList, - bool aFromOverflow, bool aCollectSiblings) + bool aCollectSiblings) { while (aFrame) { // Don't descend into float containing blocks. @@ -6908,19 +6905,28 @@ nsBlockFrame::CollectFloats(nsIFrame* aFrame, nsFrameList& aList, aFrame->GetType() == nsGkAtoms::placeholderFrame ? nsLayoutUtils::GetFloatFromPlaceholder(aFrame) : nullptr; if (outOfFlowFrame && outOfFlowFrame->GetParent() == this) { - bool removed = false; - if (outOfFlowFrame->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT) { + // Floats live in mFloats, or in the PushedFloat or OverflowOutOfFlows + // frame list properties. +#ifdef DEBUG + if (!mFloats.ContainsFrame(outOfFlowFrame)) { nsFrameList* list = GetPushedFloats(); - removed = list && list->RemoveFrameIfPresent(outOfFlowFrame); - } - if (!removed) { - if (aFromOverflow) { - nsAutoOOFFrameList oofs(this); - oofs.mList.RemoveFrame(outOfFlowFrame); - } else { - mFloats.RemoveFrame(outOfFlowFrame); + if (!list || !list->ContainsFrame(outOfFlowFrame)) { + list = GetOverflowOutOfFlows(); + MOZ_ASSERT(list && list->ContainsFrame(outOfFlowFrame), + "the float is not our child"); } } +#endif + bool removed = mFloats.StartRemoveFrame(outOfFlowFrame); + if (!removed) { + nsFrameList* list = GetPushedFloats(); + removed = list && list->ContinueRemoveFrame(outOfFlowFrame); + if (!removed) { + nsAutoOOFFrameList oofs(this); + removed = oofs.mList.ContinueRemoveFrame(outOfFlowFrame); + } + } + MOZ_ASSERT(removed, "misplaced float child"); aList.AppendFrame(nullptr, outOfFlowFrame); // FIXME: By not pulling floats whose parent is one of our // later siblings, are we risking the pushed floats getting @@ -6928,13 +6934,8 @@ nsBlockFrame::CollectFloats(nsIFrame* aFrame, nsFrameList& aList, // XXXmats nsInlineFrame's lazy reparenting depends on NOT doing that. } - CollectFloats(aFrame->GetFirstPrincipalChild(), - aList, aFromOverflow, true); - // Note: Even though we're calling CollectFloats on aFrame's overflow - // list, we'll pass down aFromOverflow unchanged because we're still - // traversing the regular-children subtree of the 'this' frame. - CollectFloats(aFrame->GetFirstChild(kOverflowList), - aList, aFromOverflow, true); + CollectFloats(aFrame->GetFirstPrincipalChild(), aList, true); + CollectFloats(aFrame->GetFirstChild(kOverflowList), aList, true); } if (!aCollectSiblings) break; diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h index c2d97fc3098b..6a3da0c2dcb4 100644 --- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -457,8 +457,7 @@ public: }; nsresult DoRemoveFrame(nsIFrame* aDeletedFrame, uint32_t aFlags); - void ReparentFloats(nsIFrame* aFirstFrame, - nsBlockFrame* aOldParent, bool aFromOverflow, + void ReparentFloats(nsIFrame* aFirstFrame, nsBlockFrame* aOldParent, bool aReparentSiblings); virtual bool UpdateOverflow(); @@ -506,7 +505,7 @@ protected: void RemoveFloat(nsIFrame* aFloat); void CollectFloats(nsIFrame* aFrame, nsFrameList& aList, - bool aFromOverflow, bool aCollectFromSiblings); + bool aCollectFromSiblings); // Remove a float, abs, rel positioned frame from the appropriate block's list static void DoRemoveOutOfFlowFrame(nsIFrame* aFrame); diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index 771607a8cf9d..f1870aa7ae32 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -243,9 +243,7 @@ nsInlineFrame::ReparentFloatsForInlineChild(nsIFrame* aOurLineContainer, } nsIFrame* ancestor = aFrame; - nsIFrame* ancestorBlockChild; do { - ancestorBlockChild = ancestor; ancestor = ancestor->GetParent(); if (!ancestor) return; @@ -259,11 +257,8 @@ nsInlineFrame::ReparentFloatsForInlineChild(nsIFrame* aOurLineContainer, nsBlockFrame* frameBlock = nsLayoutUtils::GetAsBlock(ancestor); NS_ASSERTION(frameBlock, "ancestor not a block"); - const nsFrameList& blockChildren(ancestor->PrincipalChildList()); - bool isOverflow = !blockChildren.ContainsFrame(ancestorBlockChild); - while (true) { - ourBlock->ReparentFloats(aFrame, frameBlock, isOverflow, false); + ourBlock->ReparentFloats(aFrame, frameBlock, false); if (!aReparentSiblings) return;