Bug 838688 - Make ReparentFloats/CollectFloats not require a priori knowledge of which child list a float is expected to be on. r=bzbarsky

This commit is contained in:
Mats Palmgren 2013-02-28 00:05:45 +01:00
parent 8b24a5ee5f
commit 68ac87f2e4
3 changed files with 30 additions and 35 deletions

View File

@ -1792,11 +1792,10 @@ static bool LineHasClear(nsLineBox* aLine) {
* removed from the list. They end up appended to our mFloats list. * removed from the list. They end up appended to our mFloats list.
*/ */
void void
nsBlockFrame::ReparentFloats(nsIFrame* aFirstFrame, nsBlockFrame::ReparentFloats(nsIFrame* aFirstFrame, nsBlockFrame* aOldParent,
nsBlockFrame* aOldParent, bool aFromOverflow,
bool aReparentSiblings) { bool aReparentSiblings) {
nsFrameList list; nsFrameList list;
aOldParent->CollectFloats(aFirstFrame, list, aFromOverflow, aReparentSiblings); aOldParent->CollectFloats(aFirstFrame, list, aReparentSiblings);
if (list.NotEmpty()) { if (list.NotEmpty()) {
for (nsIFrame* f = list.FirstChild(); f; f = f->GetNextSibling()) { for (nsIFrame* f = list.FirstChild(); f; f = f->GetNextSibling()) {
ReparentFrame(f, aOldParent, this); ReparentFrame(f, aOldParent, this);
@ -2247,7 +2246,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
nsBlockFrame* nextInFlow = aState.mNextInFlow; nsBlockFrame* nextInFlow = aState.mNextInFlow;
nsLineBox* pulledLine; nsLineBox* pulledLine;
nsFrameList pulledFrames; nsFrameList pulledFrames;
bool isOverflowLine = false;
if (!nextInFlow->mLines.empty()) { if (!nextInFlow->mLines.empty()) {
RemoveFirstLine(nextInFlow->mLines, nextInFlow->mFrames, RemoveFirstLine(nextInFlow->mLines, nextInFlow->mFrames,
&pulledLine, &pulledFrames); &pulledLine, &pulledFrames);
@ -2265,7 +2263,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
if (last) { if (last) {
nextInFlow->DestroyOverflowLines(); nextInFlow->DestroyOverflowLines();
} }
isOverflowLine = true;
} }
if (pulledFrames.IsEmpty()) { if (pulledFrames.IsEmpty()) {
@ -2295,7 +2292,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
aState.mPrevChild = mFrames.LastChild(); aState.mPrevChild = mFrames.LastChild();
// Reparent floats whose placeholders are in the line. // Reparent floats whose placeholders are in the line.
ReparentFloats(pulledLine->mFirstChild, nextInFlow, isOverflowLine, true); ReparentFloats(pulledLine->mFirstChild, nextInFlow, true);
DumpLine(aState, pulledLine, deltaY, 0); DumpLine(aState, pulledLine, deltaY, 0);
#ifdef DEBUG #ifdef DEBUG
@ -2595,7 +2592,7 @@ nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState,
// The frame might have (or contain) floats that need to be // The frame might have (or contain) floats that need to be
// brought over too. // brought over too.
ReparentFloats(frame, aFromContainer, aFromOverflowLine, true); ReparentFloats(frame, aFromContainer, true);
} }
// when aFromContainer is 'this', then aLine->LastChild()'s next sibling // when aFromContainer is 'this', then aLine->LastChild()'s next sibling
// is already set correctly. // is already set correctly.
@ -4317,7 +4314,7 @@ nsBlockFrame::PushLines(nsBlockReflowState& aState,
if (overBegin != end_lines()) { if (overBegin != end_lines()) {
// Remove floats in the lines from mFloats // Remove floats in the lines from mFloats
nsFrameList floats; nsFrameList floats;
CollectFloats(overBegin->mFirstChild, floats, false, true); CollectFloats(overBegin->mFirstChild, floats, true);
if (floats.NotEmpty()) { if (floats.NotEmpty()) {
// Push the floats onto the front of the overflow out-of-flows list // 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). // are ignored (they are not added to aList).
void void
nsBlockFrame::CollectFloats(nsIFrame* aFrame, nsFrameList& aList, nsBlockFrame::CollectFloats(nsIFrame* aFrame, nsFrameList& aList,
bool aFromOverflow, bool aCollectSiblings) bool aCollectSiblings)
{ {
while (aFrame) { while (aFrame) {
// Don't descend into float containing blocks. // Don't descend into float containing blocks.
@ -6908,19 +6905,28 @@ nsBlockFrame::CollectFloats(nsIFrame* aFrame, nsFrameList& aList,
aFrame->GetType() == nsGkAtoms::placeholderFrame ? aFrame->GetType() == nsGkAtoms::placeholderFrame ?
nsLayoutUtils::GetFloatFromPlaceholder(aFrame) : nullptr; nsLayoutUtils::GetFloatFromPlaceholder(aFrame) : nullptr;
if (outOfFlowFrame && outOfFlowFrame->GetParent() == this) { if (outOfFlowFrame && outOfFlowFrame->GetParent() == this) {
bool removed = false; // Floats live in mFloats, or in the PushedFloat or OverflowOutOfFlows
if (outOfFlowFrame->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT) { // frame list properties.
#ifdef DEBUG
if (!mFloats.ContainsFrame(outOfFlowFrame)) {
nsFrameList* list = GetPushedFloats(); nsFrameList* list = GetPushedFloats();
removed = list && list->RemoveFrameIfPresent(outOfFlowFrame); if (!list || !list->ContainsFrame(outOfFlowFrame)) {
} list = GetOverflowOutOfFlows();
if (!removed) { MOZ_ASSERT(list && list->ContainsFrame(outOfFlowFrame),
if (aFromOverflow) { "the float is not our child");
nsAutoOOFFrameList oofs(this);
oofs.mList.RemoveFrame(outOfFlowFrame);
} else {
mFloats.RemoveFrame(outOfFlowFrame);
} }
} }
#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); aList.AppendFrame(nullptr, outOfFlowFrame);
// FIXME: By not pulling floats whose parent is one of our // FIXME: By not pulling floats whose parent is one of our
// later siblings, are we risking the pushed floats getting // 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. // XXXmats nsInlineFrame's lazy reparenting depends on NOT doing that.
} }
CollectFloats(aFrame->GetFirstPrincipalChild(), CollectFloats(aFrame->GetFirstPrincipalChild(), aList, true);
aList, aFromOverflow, true); CollectFloats(aFrame->GetFirstChild(kOverflowList), aList, 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);
} }
if (!aCollectSiblings) if (!aCollectSiblings)
break; break;

View File

@ -457,8 +457,7 @@ public:
}; };
nsresult DoRemoveFrame(nsIFrame* aDeletedFrame, uint32_t aFlags); nsresult DoRemoveFrame(nsIFrame* aDeletedFrame, uint32_t aFlags);
void ReparentFloats(nsIFrame* aFirstFrame, void ReparentFloats(nsIFrame* aFirstFrame, nsBlockFrame* aOldParent,
nsBlockFrame* aOldParent, bool aFromOverflow,
bool aReparentSiblings); bool aReparentSiblings);
virtual bool UpdateOverflow(); virtual bool UpdateOverflow();
@ -506,7 +505,7 @@ protected:
void RemoveFloat(nsIFrame* aFloat); void RemoveFloat(nsIFrame* aFloat);
void CollectFloats(nsIFrame* aFrame, nsFrameList& aList, 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 // Remove a float, abs, rel positioned frame from the appropriate block's list
static void DoRemoveOutOfFlowFrame(nsIFrame* aFrame); static void DoRemoveOutOfFlowFrame(nsIFrame* aFrame);

View File

@ -243,9 +243,7 @@ nsInlineFrame::ReparentFloatsForInlineChild(nsIFrame* aOurLineContainer,
} }
nsIFrame* ancestor = aFrame; nsIFrame* ancestor = aFrame;
nsIFrame* ancestorBlockChild;
do { do {
ancestorBlockChild = ancestor;
ancestor = ancestor->GetParent(); ancestor = ancestor->GetParent();
if (!ancestor) if (!ancestor)
return; return;
@ -259,11 +257,8 @@ nsInlineFrame::ReparentFloatsForInlineChild(nsIFrame* aOurLineContainer,
nsBlockFrame* frameBlock = nsLayoutUtils::GetAsBlock(ancestor); nsBlockFrame* frameBlock = nsLayoutUtils::GetAsBlock(ancestor);
NS_ASSERTION(frameBlock, "ancestor not a block"); NS_ASSERTION(frameBlock, "ancestor not a block");
const nsFrameList& blockChildren(ancestor->PrincipalChildList());
bool isOverflow = !blockChildren.ContainsFrame(ancestorBlockChild);
while (true) { while (true) {
ourBlock->ReparentFloats(aFrame, frameBlock, isOverflow, false); ourBlock->ReparentFloats(aFrame, frameBlock, false);
if (!aReparentSiblings) if (!aReparentSiblings)
return; return;