Bug 538194 patch 1 - Refactor some code dealing with fitting block formatting contexts around floats into separate functions. r=roc
authorL. David Baron <dbaron@dbaron.org>
Sun, 02 Aug 2015 21:03:09 -0700
changeset 255765 b17337696896f9e9c33af4fbc7c0229561a1a7b5
parent 255764 8f269ef84bca0aef90799191847347381ea6cce9
child 255766 80ef9bb2c2e9ebaf375e078428e9615d46adbde9
push id63152
push userdbaron@mozilla.com
push dateMon, 03 Aug 2015 04:04:48 +0000
treeherdermozilla-inbound@5dcb38c7f1b8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs538194
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 538194 patch 1 - Refactor some code dealing with fitting block formatting contexts around floats into separate functions. r=roc
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
layout/generic/nsBlockReflowState.cpp
layout/generic/nsBlockReflowState.h
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -7200,17 +7200,17 @@ nsBlockFrame::BlockCanIntersectFloats(ns
 }
 
 // Note that this width can vary based on the vertical position.
 // However, the cases where it varies are the cases where the width fits
 // in the available space given, which means that variation shouldn't
 // matter.
 /* static */
 nsBlockFrame::ReplacedElementISizeToClear
-nsBlockFrame::ISizeToClearPastFloats(nsBlockReflowState& aState,
+nsBlockFrame::ISizeToClearPastFloats(const nsBlockReflowState& aState,
                                      const LogicalRect& aFloatAvailableSpace,
                                      nsIFrame* aFrame)
 {
   nscoord inlineStartOffset, inlineEndOffset;
   WritingMode wm = aState.mReflowState.GetWritingMode();
   nsCSSOffsetState offsetState(aFrame, aState.mReflowState.rendContext,
                                wm, aState.mContentArea.ISize(wm));
 
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -319,17 +319,17 @@ public:
    * care about (which need not be its current mBCoord)
    */
   struct ReplacedElementISizeToClear {
     nscoord marginIStart, borderBoxISize, marginIEnd;
     nscoord MarginBoxISize() const
       { return marginIStart + borderBoxISize + marginIEnd; }
   };
   static ReplacedElementISizeToClear
-    ISizeToClearPastFloats(nsBlockReflowState& aState,
+    ISizeToClearPastFloats(const nsBlockReflowState& aState,
                            const mozilla::LogicalRect& aFloatAvailableSpace,
                            nsIFrame* aFrame);
 
   /**
    * Creates a contination for aFloat and adds it to the list of overflow floats.
    * Also updates aState.mReflowStatus to include the float's incompleteness.
    * Must only be called while this block frame is in reflow.
    * aFloatStatus must be the float's true, unmodified reflow status.
--- a/layout/generic/nsBlockReflowState.cpp
+++ b/layout/generic/nsBlockReflowState.cpp
@@ -156,17 +156,17 @@ nsBlockReflowState::GetConsumedBSize()
   return mConsumedBSize;
 }
 
 void
 nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(
                       nsIFrame* aFrame,
                       const LogicalRect& aFloatAvailableSpace,
                       nscoord& aIStartResult,
-                      nscoord& aIEndResult)
+                      nscoord& aIEndResult) const
 {
   WritingMode wm = mReflowState.GetWritingMode();
   // The frame is clueless about the float manager and therefore we
   // only give it free space. An example is a table frame - the
   // tables do not flow around floats.
   // However, we can let its margins intersect floats.
   NS_ASSERTION(aFloatAvailableSpace.IStart(wm) >= mContentArea.IStart(wm),
                "bad avail space rect inline-coord");
@@ -297,16 +297,40 @@ nsBlockReflowState::ComputeBlockAvailSpa
   }
 
 #ifdef REALLY_NOISY_REFLOW
   printf("  CBAS: result %d %d %d %d\n", aResult.IStart(wm), aResult.BStart(wm),
          aResult.ISize(wm), aResult.BSize(wm));
 #endif
 }
 
+bool
+nsBlockReflowState::ReplacedBlockFitsInAvailSpace(nsIFrame* aReplacedBlock,
+                            const nsFlowAreaRect& aFloatAvailableSpace) const
+{
+  if (!aFloatAvailableSpace.mHasFloats) {
+    // If there aren't any floats here, then we always fit.
+    // We check this before calling ISizeToClearPastFloats, which is
+    // somewhat expensive.
+    return true;
+  }
+  WritingMode wm = mReflowState.GetWritingMode();
+  nsBlockFrame::ReplacedElementISizeToClear replacedISize =
+    nsBlockFrame::ISizeToClearPastFloats(*this, aFloatAvailableSpace.mRect,
+                                         aReplacedBlock);
+  return std::max(aFloatAvailableSpace.mRect.IStart(wm) -
+                    mContentArea.IStart(wm),
+                  replacedISize.marginIStart) +
+           replacedISize.borderBoxISize +
+           std::max(mContentArea.IEnd(wm) -
+                      aFloatAvailableSpace.mRect.IEnd(wm),
+                    replacedISize.marginIEnd) <=
+         mContentArea.ISize(wm);
+}
+
 nsFlowAreaRect
 nsBlockReflowState::GetFloatAvailableSpaceWithState(
                       nscoord aBCoord,
                       nsFloatManager::SavedState *aState) const
 {
   WritingMode wm = mReflowState.GetWritingMode();
 #ifdef DEBUG
   // Verify that the caller setup the coordinate system properly
@@ -1073,56 +1097,32 @@ nsBlockReflowState::ClearFloats(nscoord 
   mFloatManager->List(stdout);
 #endif
 
   if (!mFloatManager->HasAnyFloats()) {
     return aBCoord;
   }
 
   nscoord newBCoord = aBCoord;
-  WritingMode wm = mReflowState.GetWritingMode();
 
   if (aBreakType != NS_STYLE_CLEAR_NONE) {
     newBCoord = mFloatManager->ClearFloats(newBCoord, aBreakType, aFlags);
   }
 
   if (aReplacedBlock) {
     for (;;) {
       nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(newBCoord);
-      if (!floatAvailableSpace.mHasFloats) {
-        // If there aren't any floats here, then we always fit.
-        // We check this before calling ISizeToClearPastFloats, which is
-        // somewhat expensive.
-        break;
-      }
-      nsBlockFrame::ReplacedElementISizeToClear replacedISize =
-        nsBlockFrame::ISizeToClearPastFloats(*this, floatAvailableSpace.mRect,
-                                             aReplacedBlock);
-      if (std::max(floatAvailableSpace.mRect.IStart(wm) -
-                    mContentArea.IStart(wm),
-                   replacedISize.marginIStart) +
-            replacedISize.borderBoxISize +
-            std::max(mContentArea.IEnd(wm) -
-                     floatAvailableSpace.mRect.IEnd(wm),
-                     replacedISize.marginIEnd) <=
-          mContentArea.ISize(wm)) {
+      if (ReplacedBlockFitsInAvailSpace(aReplacedBlock, floatAvailableSpace)) {
         break;
       }
       // See the analogous code for inlines in nsBlockFrame::DoReflowInlineFrames
-      if (floatAvailableSpace.mRect.BSize(wm) > 0) {
-        // See if there's room in the next band.
-        newBCoord += floatAvailableSpace.mRect.BSize(wm);
-      } else {
-        if (mReflowState.AvailableHeight() != NS_UNCONSTRAINEDSIZE) {
-          // Stop trying to clear here; we'll just get pushed to the
-          // next column or page and try again there.
-          break;
-        }
-        NS_NOTREACHED("avail space rect with zero height!");
-        newBCoord += 1;
+      if (!AdvanceToNextBand(floatAvailableSpace.mRect, &newBCoord)) {
+        // Stop trying to clear here; we'll just get pushed to the
+        // next column or page and try again there.
+        break;
       }
     }
   }
 
 #ifdef DEBUG
   if (nsBlockFrame::gNoisyReflow) {
     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
     printf("clear floats: out: y=%d\n", newBCoord);
--- a/layout/generic/nsBlockReflowState.h
+++ b/layout/generic/nsBlockReflowState.h
@@ -88,16 +88,42 @@ public:
 
   // Returns the first coordinate >= aBCoord that clears the
   // floats indicated by aBreakType and has enough inline size between floats
   // (or no floats remaining) to accomodate aReplacedBlock.
   nscoord ClearFloats(nscoord aBCoord, uint8_t aBreakType,
                       nsIFrame *aReplacedBlock = nullptr,
                       uint32_t aFlags = 0);
 
+  // Advances to the next band, i.e., the next horizontal stripe in
+  // which there is a different set of floats.
+  // Return false if it did not advance, which only happens for
+  // constrained heights (and means that we should get pushed to the
+  // next column/page).
+  bool AdvanceToNextBand(const mozilla::LogicalRect& aFloatAvailableSpace,
+                         nscoord *aBCoord) const {
+    mozilla::WritingMode wm = mReflowState.GetWritingMode();
+    if (aFloatAvailableSpace.BSize(wm) > 0) {
+      // See if there's room in the next band.
+      *aBCoord += aFloatAvailableSpace.BSize(wm);
+    } else {
+      if (mReflowState.AvailableHeight() != NS_UNCONSTRAINEDSIZE) {
+        // Stop trying to clear here; we'll just get pushed to the
+        // next column or page and try again there.
+        return false;
+      }
+      NS_NOTREACHED("avail space rect with zero height!");
+      *aBCoord += 1;
+    }
+    return true;
+  }
+
+  bool ReplacedBlockFitsInAvailSpace(nsIFrame* aReplacedBlock,
+                            const nsFlowAreaRect& aFloatAvailableSpace) const;
+
   bool IsAdjacentWithTop() const {
     return mBCoord == mBorderPadding.BStart(mReflowState.GetWritingMode());
   }
 
   /**
    * Return mBlock's computed physical border+padding with GetSkipSides applied.
    */
   const mozilla::LogicalMargin& BorderPadding() const {
@@ -112,17 +138,17 @@ public:
   // Reconstruct the previous block-end margin that goes before |aLine|.
   void ReconstructMarginBefore(nsLineList::iterator aLine);
 
   // Caller must have called GetAvailableSpace for the correct position
   // (which need not be the current mBCoord).
   void ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
                           const mozilla::LogicalRect& aFloatAvailableSpace,
                                             nscoord&  aIStartResult,
-                                            nscoord&  aIEndResult);
+                                            nscoord&  aIEndResult) const;
 
   // Caller must have called GetAvailableSpace for the current mBCoord
   void ComputeBlockAvailSpace(nsIFrame* aFrame,
                               const nsStyleDisplay* aDisplay,
                               const nsFlowAreaRect& aFloatAvailableSpace,
                               bool aBlockAvoidsFloats,
                               mozilla::LogicalRect& aResult);