Bug 285608: hangs when page with float printed. r+sr=roc.
authorsharparrow1@yahoo.com
Wed, 27 Jun 2007 09:35:31 -0700
changeset 2853 2951e12840bc0df54c231fd5697862a775e29d11
parent 2852 ccd17bc840f985d9084e450c34d3fe4a18743917
child 2854 d1c36463d34adae9cd0df6f78f4034598df66d70
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs285608
milestone1.9a6pre
Bug 285608: hangs when page with float printed. r+sr=roc.
layout/generic/nsBlockReflowState.cpp
layout/generic/nsLineLayout.cpp
--- a/layout/generic/nsBlockReflowState.cpp
+++ b/layout/generic/nsBlockReflowState.cpp
@@ -539,59 +539,69 @@ nsBlockReflowState::AddFloat(nsLineLayou
     // And then place it
     PRBool isLeftFloat;
     // force it to fit if we're at the top of the block and we can't
     // break before this
     PRBool forceFit = IsAdjacentWithTop() && !aLineLayout.LineIsBreakable();
     placed = FlowAndPlaceFloat(fc, &isLeftFloat, aReflowStatus, forceFit);
     NS_ASSERTION(placed || !forceFit,
                  "If we asked for force-fit, it should have been placed");
-    if (placed) {
+    if (forceFit || (placed && !NS_FRAME_IS_TRUNCATED(aReflowStatus))) {
       // Pass on updated available space to the current inline reflow engine
       GetAvailableSpace(mY, forceFit);
       aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
                              mAvailSpaceRect.width,
                              mAvailSpaceRect.height,
                              isLeftFloat,
                              aPlaceholder->GetOutOfFlowFrame());
       
       // Record this float in the current-line list
       mCurrentLineFloats.Append(fc);
+      // If we can't break here, hide the fact that it's truncated
+      // XXX We can probably do this more cleanly
+      aReflowStatus &= ~NS_FRAME_TRUNCATED;
     }
     else {
+      if (IsAdjacentWithTop()) {
+        // Pushing the line to the next page won't give us any more space;
+        // therefore, we break.
+        NS_ASSERTION(aLineLayout.LineIsBreakable(),
+                     "We can't get here unless forceFit is false");
+        aReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
+      } else {
+        // Make sure we propagate the truncated status; this signals the
+        // block to push the line to the next page.
+        aReflowStatus |= NS_FRAME_TRUNCATED;
+      }
       delete fc;
     }
 
     // Restore coordinate system
     mSpaceManager->Translate(dx, dy);
   }
   else {
+    // Always claim to be placed; we don't know whether we fit yet, so we
+    // deal with this in PlaceBelowCurrentLineFloats
+    placed = PR_TRUE;
     // This float will be placed after the line is done (it is a
     // below-current-line float).
     mBelowCurrentLineFloats.Append(fc);
     if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE ||
         aPlaceholder->GetNextInFlow()) {
       // If the float might not be complete, mark it incomplete now to
       // prevent the placeholders being torn down. We will destroy any
       // placeholders later if PlaceBelowCurrentLineFloats finds the
       // float is complete.
       // Note that we could have unconstrained height and yet have
       // a next-in-flow placeholder --- for example columns can switch
       // from constrained height to unconstrained height.
-      if (aPlaceholder->GetSplittableType() == NS_FRAME_NOT_SPLITTABLE) {
-        placed = PR_FALSE;
-      }
-      else {
-        placed = PR_TRUE;
+      if (aPlaceholder->GetSplittableType() != NS_FRAME_NOT_SPLITTABLE) {
         aReflowStatus = NS_FRAME_NOT_COMPLETE;
       }
     }
-    else {
-      placed = PR_TRUE;
-    }
   }
   return placed;
 }
 
 PRBool
 nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
                                   PRUint8 aFloats, PRBool aForceFit)
 {
@@ -986,17 +996,22 @@ nsBlockReflowState::PlaceBelowCurrentLin
 #endif
       // Place the float
       PRBool isLeftFloat;
       nsReflowStatus reflowStatus;
       PRBool placed = FlowAndPlaceFloat(fc, &isLeftFloat, reflowStatus, aForceFit);
       NS_ASSERTION(placed || !aForceFit,
                    "If we're in force-fit mode, we should have placed the float");
 
-      if (!placed || NS_FRAME_IS_TRUNCATED(reflowStatus)) {
+      // XXX We could deal with this situation better by breaking before
+      // the associated placeholder
+      NS_WARN_IF_FALSE(NS_FRAME_IS_TRUNCATED(reflowStatus) && aForceFit,
+                       "This situation currently leads to data not printing");
+
+      if (!placed || (NS_FRAME_IS_TRUNCATED(reflowStatus) && !aForceFit)) {
         // return before processing all of the floats, since the line will be pushed.
         return PR_FALSE;
       }
       else if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus)) {
         // Create a continuation for the incomplete float and its placeholder.
         nsresult rv = mBlock->SplitPlaceholder(*this, fc->mPlaceholder);
         if (NS_FAILED(rv)) 
           return PR_FALSE;
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -919,19 +919,16 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
         // XXXldb What is this test supposed to be?
         if (!NS_SUBTREE_DIRTY(aFrame)) {
           // incremental reflow of child
           placedFloat = InitFloat(placeholder, aReflowStatus);
         }
         else {
           placedFloat = AddFloat(placeholder, aReflowStatus);
         }
-        if (!placedFloat) {
-          aReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
-        }
         if (outOfFlowFrame->GetType() == nsGkAtoms::letterFrame) {
           SetFlag(LL_FIRSTLETTERSTYLEOK, PR_FALSE);
         }
       }
     }
     else if (nsGkAtoms::textFrame == frameType) {
       // Note non-empty text-frames for inline frame compatibility hackery
       pfd->SetFlag(PFD_ISTEXTFRAME, PR_TRUE);