From ce915e403f0dc014313ae0577cef5886f15204eb Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Thu, 24 Sep 2009 04:39:21 +0200 Subject: [PATCH] Store the overflow out of flows as an nsFrameList. b=516974 r=bzbarsky --- layout/generic/nsBlockFrame.cpp | 48 ++++++++++++++++++++------------- layout/generic/nsBlockFrame.h | 22 +++++++-------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index f17a0b11cda1..0b2662610639 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -534,7 +534,8 @@ nsBlockFrame::GetChildList(nsIAtom* aListName) const : nsFrameList::EmptyList(); } else if (aListName == nsGkAtoms::overflowOutOfFlowList) { - return GetOverflowOutOfFlows(); + const nsFrameList* list = GetOverflowOutOfFlows(); + return list ? *list : nsFrameList::EmptyList(); } else if (aListName == nsGkAtoms::floatList) { return mFloats; @@ -4522,35 +4523,46 @@ nsBlockFrame::SetOverflowLines(nsLineList* aOverflowLines) return rv; } -nsFrameList +nsFrameList* nsBlockFrame::GetOverflowOutOfFlows() const { if (!(GetStateBits() & NS_BLOCK_HAS_OVERFLOW_OUT_OF_FLOWS)) { - return nsFrameList(); + return nsnull; } - nsIFrame* result = static_cast - (GetProperty(nsGkAtoms::overflowOutOfFlowsProperty)); + nsFrameList* result = + GetPropTableFrames(PresContext(), nsGkAtoms::overflowOutOfFlowsProperty); NS_ASSERTION(result, "value should always be non-empty when state set"); - return nsFrameList(result, nsLayoutUtils::GetLastSibling(result)); + return result; } // This takes ownership of the frames void -nsBlockFrame::SetOverflowOutOfFlows(const nsFrameList& aList) +nsBlockFrame::SetOverflowOutOfFlows(const nsFrameList& aList, + nsFrameList* aPropValue) { + NS_PRECONDITION(!!(GetStateBits() & NS_BLOCK_HAS_OVERFLOW_OUT_OF_FLOWS) == + !!aPropValue, "state does not match value"); + if (aList.IsEmpty()) { if (!(GetStateBits() & NS_BLOCK_HAS_OVERFLOW_OUT_OF_FLOWS)) { return; } -#ifdef DEBUG - nsIFrame* result = static_cast -#endif - (UnsetProperty(nsGkAtoms::overflowOutOfFlowsProperty)); - NS_ASSERTION(result, "value should always be non-empty when state set"); + nsFrameList* list = + RemovePropTableFrames(PresContext(), + nsGkAtoms::overflowOutOfFlowsProperty); + NS_ASSERTION(aPropValue == list, "prop value mismatch"); + delete list; RemoveStateBits(NS_BLOCK_HAS_OVERFLOW_OUT_OF_FLOWS); - } else { - SetProperty(nsGkAtoms::overflowOutOfFlowsProperty, - aList.FirstChild(), nsnull); + } + else if (GetStateBits() & NS_BLOCK_HAS_OVERFLOW_OUT_OF_FLOWS) { + NS_ASSERTION(aPropValue == GetPropTableFrames(PresContext(), + nsGkAtoms::overflowOutOfFlowsProperty), + "prop value mismatch"); + *aPropValue = aList; + } + else { + SetPropTableFrames(PresContext(), new nsFrameList(aList), + nsGkAtoms::overflowOutOfFlowsProperty); AddStateBits(NS_BLOCK_HAS_OVERFLOW_OUT_OF_FLOWS); } } @@ -6674,8 +6686,8 @@ nsBlockFrame::CheckFloats(nsBlockReflowState& aState) } #endif - nsFrameList oofs = GetOverflowOutOfFlows(); - if (oofs.NotEmpty()) { + const nsFrameList* oofs = GetOverflowOutOfFlows(); + if (oofs && oofs->NotEmpty()) { // Floats that were pushed should be removed from our float // manager. Otherwise the float manager's YMost or XMost might // be larger than necessary, causing this block to get an @@ -6686,7 +6698,7 @@ nsBlockFrame::CheckFloats(nsBlockReflowState& aState) // because we know from here on the float manager will only be // used for its XMost and YMost, not to place new floats and // lines. - aState.mFloatManager->RemoveTrailingRegions(oofs.FirstChild()); + aState.mFloatManager->RemoveTrailingRegions(oofs->FirstChild()); } } diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h index 44d5c8b4334d..cf8fe05ef2d2 100644 --- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -677,30 +677,28 @@ protected: * overflow list. It gives the client direct writable access to * the frame list temporarily but ensures that property is only * written back if absolutely necessary. - * @note currently we can ignore mList.mLastChild being different because - * the overflow OOFs are stored internally as a frame pointer property - * (the first child of the list). */ struct nsAutoOOFFrameList { nsFrameList mList; nsAutoOOFFrameList(nsBlockFrame* aBlock) - : mList(aBlock->GetOverflowOutOfFlows()) - , mOldFirstChild(mList.FirstChild()) - , mBlock(aBlock) {} - ~nsAutoOOFFrameList() { - if (mList.FirstChild() != mOldFirstChild) { - mBlock->SetOverflowOutOfFlows(mList); + : mPropValue(aBlock->GetOverflowOutOfFlows()) + , mBlock(aBlock) { + if (mPropValue) { + mList = *mPropValue; } } + ~nsAutoOOFFrameList() { + mBlock->SetOverflowOutOfFlows(mList, mPropValue); + } protected: - nsIFrame* const mOldFirstChild; + nsFrameList* const mPropValue; nsBlockFrame* const mBlock; }; friend struct nsAutoOOFFrameList; - nsFrameList GetOverflowOutOfFlows() const; - void SetOverflowOutOfFlows(const nsFrameList& aList); + nsFrameList* GetOverflowOutOfFlows() const; + void SetOverflowOutOfFlows(const nsFrameList& aList, nsFrameList* aPropValue); #ifdef NS_DEBUG void VerifyLines(PRBool aFinalCheckOK);