Bug 492627 - Remove Placeholder Continuations [Part VII: More intelligent deletion of floats and overflow containers] r=roc
authorfantasai <fantasai.cvs@inkedblade.net>
Mon, 31 Aug 2009 11:25:37 -0700
changeset 32111 1b724a06a345bd91efa825e9e16cbce44e4d41c5
parent 32110 ac59a41e7815b553ce69f0548439b3b627f4d07c
child 32112 7d5e1bcb47299ed50993f23880447b5a62fccc00
push id8851
push userfantasai.cvs@inkedblade.net
push dateMon, 31 Aug 2009 19:40:38 +0000
treeherderautoland@1b724a06a345 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs492627
milestone1.9.3a1pre
Bug 492627 - Remove Placeholder Continuations [Part VII: More intelligent deletion of floats and overflow containers] r=roc
layout/generic/nsBlockFrame.cpp
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -4902,27 +4902,27 @@ nsBlockFrame::RemoveFrame(nsIAtom*  aLis
     if (hasFloats) {
       MarkSameFloatManagerLinesDirty(this);
     }
   }
   else if (nsGkAtoms::absoluteList == aListName) {
     return mAbsoluteContainer.RemoveFrame(this, aListName, aOldFrame);
   }
   else if (nsGkAtoms::floatList == aListName) {
-    nsIFrame* curFrame = aOldFrame;
-    // Make sure to delete all the continuations for the float frame
+    // Make sure to mark affected lines dirty for the float frame
     // we are removing; this way is a bit messy, but so is the rest of the code.
     // See bug 390762.
-    do {
-      nsIFrame* continuation = curFrame->GetNextContinuation();
-      nsBlockFrame* curParent = static_cast<nsBlockFrame*>(curFrame->GetParent());
-      curParent->RemoveFloat(curFrame);
-      MarkSameFloatManagerLinesDirty(curParent);
-      curFrame = continuation;
-    } while (curFrame);
+    NS_ASSERTION(!aOldFrame->GetPrevContinuation(),
+                 "RemoveFrame should not be called on float continuations.");
+    for (nsIFrame* f = aOldFrame;
+         f && !(f->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER);
+         f = f->GetNextContinuation()) {
+      MarkSameFloatManagerLinesDirty(static_cast<nsBlockFrame*>(f->GetParent()));
+    }
+    DoRemoveOutOfFlowFrame(aOldFrame);
   }
 #ifdef IBMBIDI
   else if (nsGkAtoms::nextBidi == aListName) {
     // Skip the call to |FrameNeedsReflow| below by returning now.
     return DoRemoveFrame(aOldFrame, REMOVE_FIXED_CONTINUATIONS);
   }
 #endif // IBMBIDI
   else {
@@ -5168,16 +5168,23 @@ nsBlockFrame::DoRemoveFrame(nsIFrame* aD
     }
     else {
       nsContainerFrame::DeleteNextInFlowChild(presContext, aDeletedFrame,
                                               (aFlags & FRAMES_ARE_EMPTY) != 0);
     }
     return NS_OK;
   }
 
+  // If next-in-flow is an overflow container, must remove it first
+  nsIFrame* next = aDeletedFrame->GetNextInFlow();
+  if (next && next->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
+    static_cast<nsContainerFrame*>(next->GetParent())
+      ->DeleteNextInFlowChild(next->PresContext(), next, PR_FALSE);
+  }
+
   nsIPresShell* presShell = presContext->PresShell();
 
   // Find the line and the previous sibling that contains
   // deletedFrame; we also find the pointer to the line.
   nsLineList::iterator line_start = mLines.begin(),
                        line_end = mLines.end();
   nsLineList::iterator line = line_start;
   PRBool searchingOverflowList = PR_FALSE;
@@ -5469,18 +5476,18 @@ nsBlockFrame::StealFrame(nsPresContext* 
 
 void
 nsBlockFrame::DeleteNextInFlowChild(nsPresContext* aPresContext,
                                     nsIFrame*      aNextInFlow,
                                     PRBool         aDeletingEmptyFrames)
 {
   NS_PRECONDITION(aNextInFlow->GetPrevInFlow(), "bad next-in-flow");
 
-  if (aNextInFlow->GetPrevInFlow() && (aNextInFlow->GetStateBits() &
-      (NS_FRAME_OUT_OF_FLOW | NS_FRAME_IS_OVERFLOW_CONTAINER))) {
+  if (aNextInFlow->GetStateBits() &
+      (NS_FRAME_OUT_OF_FLOW | NS_FRAME_IS_OVERFLOW_CONTAINER)) {
     nsContainerFrame::DeleteNextInFlowChild(aPresContext,
         aNextInFlow, aDeletingEmptyFrames);
   }
   else {
     DoRemoveFrame(aNextInFlow,
         aDeletingEmptyFrames ? FRAMES_ARE_EMPTY : 0);
   }
 }