Bug 775624 Part 12 - Add bit-fields for inline break status, and convert NS_INLINE_LINE_BREAK_BEFORE. r=dholbert
authorTing-Yu Lin <tlin@mozilla.com>
Tue, 14 Feb 2017 11:52:53 +0800
changeset 373403 43b83d0ac36b7f27b02defaecc00f735e3c1a9e3
parent 373402 6d832b39d9a090a94c830f2ccb8927c4e1020545
child 373404 b39fdda36636395fefd8a671ced01fa4eee9f154
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs775624
milestone54.0a1
Bug 775624 Part 12 - Add bit-fields for inline break status, and convert NS_INLINE_LINE_BREAK_BEFORE. r=dholbert NS_INLINE_LINE_BREAK_BEFORE() was replaced by the help of the following script. function rename() { find layout\ -type f\ \( -name "*.cpp" -or\ -name "*.h" \)\ -exec sed -i -r "s/$1/$2/g" "{}" \; } rename " = NS_INLINE_LINE_BREAK_BEFORE\(\);" ".SetInlineLineBreakBeforeAndReset();" MozReview-Commit-ID: mz6L8zay7q
layout/generic/nsBlockFrame.cpp
layout/generic/nsGridContainerFrame.cpp
layout/generic/nsIFrame.h
layout/generic/nsLineLayout.cpp
layout/generic/nsRubyBaseContainerFrame.cpp
layout/generic/nsTextFrame.cpp
layout/tables/nsTableFrame.cpp
layout/tables/nsTableRowFrame.cpp
layout/tables/nsTableRowGroupFrame.cpp
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -3401,17 +3401,17 @@ nsBlockFrame::ReflowBlockFrame(BlockRefl
       // Doing this means that we also don't need to worry about the
       // |availSpace.BSize(wm) += bStartMargin| below interacting with
       // pushed floats (which force nscoord_MAX clearance) to cause a
       // constrained block size to turn into an unconstrained one.
       aState.mBCoord = startingBCoord;
       aState.mPrevBEndMargin = incomingMargin;
       *aKeepReflowGoing = false;
       if (ShouldAvoidBreakInside(aState.mReflowInput)) {
-        aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
+        aState.mReflowStatus.SetInlineLineBreakBeforeAndReset();
       } else {
         PushLines(aState, aLine.prev());
         aState.mReflowStatus.SetIncomplete();
       }
       return;
     }
 
     // Now put the block-dir coordinate back to the start of the
@@ -3578,17 +3578,17 @@ nsBlockFrame::ReflowBlockFrame(BlockRefl
 #if defined(REFLOW_STATUS_COVERAGE)
     RecordReflowStatus(true, frameReflowStatus);
 #endif
 
     if (NS_INLINE_IS_BREAK_BEFORE(frameReflowStatus)) {
       // None of the child block fits.
       *aKeepReflowGoing = false;
       if (ShouldAvoidBreakInside(aState.mReflowInput)) {
-        aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
+        aState.mReflowStatus.SetInlineLineBreakBeforeAndReset();
       } else {
         PushLines(aState, aLine.prev());
         aState.mReflowStatus.SetIncomplete();
       }
     }
     else {
       // Note: line-break-after a block is a nop
 
@@ -3752,17 +3752,17 @@ nsBlockFrame::ReflowBlockFrame(BlockRefl
                aState.mPrevBEndMargin.get());
 #endif
       } else {
         if ((aLine == mLines.front() && !GetPrevInFlow()) ||
             ShouldAvoidBreakInside(aState.mReflowInput)) {
           // If it's our very first line *or* we're not at the top of the page
           // and we have page-break-inside:avoid, then we need to be pushed to
           // our parent's next-in-flow.
-          aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
+          aState.mReflowStatus.SetInlineLineBreakBeforeAndReset();
         } else {
           // Push the line that didn't fit and any lines that follow it
           // to our next-in-flow.
           PushLines(aState, aLine.prev());
           aState.mReflowStatus.SetIncomplete();
         }
       }
     }
@@ -4639,28 +4639,28 @@ nsBlockFrame::PlaceLine(BlockReflowInput
     nscoord dy = aState.mFlags.mShouldApplyBStartMargin
                    ? -aState.mPrevBEndMargin.get() : 0;
     newBCoord = aState.mBCoord + dy;
   }
 
   if (!aState.mReflowStatus.IsFullyComplete() &&
       ShouldAvoidBreakInside(aState.mReflowInput)) {
     aLine->AppendFloats(aState.mCurrentLineFloats);
-    aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
+    aState.mReflowStatus.SetInlineLineBreakBeforeAndReset();
     return true;
   }
 
   // See if the line fit (our first line always does).
   if (mLines.front() != aLine &&
       newBCoord > aState.mBEndEdge &&
       aState.mBEndEdge != NS_UNCONSTRAINEDSIZE) {
     NS_ASSERTION(aState.mCurrentLine == aLine, "oops");
     if (ShouldAvoidBreakInside(aState.mReflowInput)) {
       // All our content doesn't fit, start on the next page.
-      aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
+      aState.mReflowStatus.SetInlineLineBreakBeforeAndReset();
     } else {
       // Push aLine and all of its children and anything else that
       // follows to our next-in-flow.
       PushTruncatedLine(aState, aLine, aKeepReflowGoing);
     }
     return true;
   }
 
@@ -6272,17 +6272,17 @@ nsBlockFrame::ReflowFloat(BlockReflowInp
     brc.ReflowBlock(aAdjustedAvailableSpace, true, margin,
                     0, isAdjacentWithTop,
                     nullptr, floatRS,
                     aReflowStatus, aState);
   } while (clearanceFrame);
 
   if (!aReflowStatus.IsFullyComplete() &&
       ShouldAvoidBreakInside(floatRS)) {
-    aReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
+    aReflowStatus.SetInlineLineBreakBeforeAndReset();
   } else if (aReflowStatus.IsIncomplete() &&
              (NS_UNCONSTRAINEDSIZE == aAdjustedAvailableSpace.BSize(wm))) {
     // An incomplete reflow status means we should split the float
     // if the height is constrained (bug 145305).
     aReflowStatus = NS_FRAME_COMPLETE;
   }
 
   if (aReflowStatus.NextInFlowNeedsReflow()) {
@@ -7418,17 +7418,17 @@ nsBlockFrame::ComputeFinalBSize(const Re
     aStatus->SetOverflowIncomplete();
   }
 
   if (aStatus->IsComplete()) {
     if (computedBSizeLeftOver > 0 &&
         NS_UNCONSTRAINEDSIZE != aReflowInput.AvailableBSize() &&
         aFinalSize.BSize(wm) > aReflowInput.AvailableBSize()) {
       if (ShouldAvoidBreakInside(aReflowInput)) {
-        *aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+        aStatus->SetInlineLineBreakBeforeAndReset();
         return;
       }
       // We don't fit and we consumed some of the computed height,
       // so we should consume all the available height and then
       // break.  If our bottom border/padding straddles the break
       // point, then this will increase our height and push the
       // border/padding to the next page/column.
       aFinalSize.BSize(wm) = std::max(aReflowInput.AvailableBSize(),
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -5383,17 +5383,17 @@ nsGridContainerFrame::ReflowInFragmentai
     if (itemStartRow == endRow) {
       break;
     }
     auto disp = info->mFrame->StyleDisplay();
     if (disp->mBreakBefore) {
       // Propagate break-before on the first row to the container unless we're
       // already at top-of-page.
       if ((itemStartRow == 0 && !isTopOfPage) || avoidBreakInside) {
-        aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+        aStatus.SetInlineLineBreakBeforeAndReset();
         return aState.mFragBStart;
       }
       if ((itemStartRow > startRow ||
            (itemStartRow == startRow && !isTopOfPage)) &&
           itemStartRow < endRow) {
         endRow = itemStartRow;
         isForcedBreak = true;
         // reset any BREAK_AFTER we found on an earlier item
@@ -5422,17 +5422,17 @@ nsGridContainerFrame::ReflowInFragmentai
   // Except for the first row if there's a break opportunity before it.
   if (startRow == endRow && startRow != numRows &&
       (startRow != 0 || !aFragmentainer.mCanBreakAtStart)) {
     ++endRow;
   }
 
   // Honor break-inside:avoid if we can't fit all rows.
   if (avoidBreakInside && endRow < numRows) {
-    aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+    aStatus.SetInlineLineBreakBeforeAndReset();
     return aState.mFragBStart;
   }
 
   // Calculate the block-size including this fragment.
   nscoord bEndRow =
     aState.mRows.GridLineEdge(endRow, GridLineSide::eBeforeGridGap);
   nscoord bSize;
   if (aFragmentainer.mIsAutoBSize) {
@@ -5458,17 +5458,17 @@ nsGridContainerFrame::ReflowInFragmentai
                           aState.mReflowInput->ComputedMinBSize(),
                           aState.mReflowInput->ComputedMaxBSize());
   }
 
   // Check for overflow and set aStatus INCOMPLETE if so.
   bool overflow = bSize + bpBEnd > childAvailableSize;
   if (overflow) {
     if (avoidBreakInside) {
-      aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+      aStatus.SetInlineLineBreakBeforeAndReset();
       return aState.mFragBStart;
     }
     bool breakAfterLastRow = endRow == numRows && aFragmentainer.mCanBreakAtEnd;
     if (breakAfterLastRow) {
       MOZ_ASSERT(bEndRow < bSize, "bogus aFragmentainer.mCanBreakAtEnd");
       nscoord availableSize = childAvailableSize;
       if (isBDBClone) {
         availableSize -= bpBEnd;
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -192,31 +192,39 @@ enum nsSpread {
 
 // Carried out margin flags
 #define NS_CARRIED_TOP_MARGIN_IS_AUTO    0x1
 #define NS_CARRIED_BOTTOM_MARGIN_IS_AUTO 0x2
 
 //----------------------------------------------------------------------
 // Reflow status returned by the Reflow() methods.
 class nsReflowStatus final {
+  using StyleClear = mozilla::StyleClear;
+
 public:
   nsReflowStatus()
     : mStatus(0)
+    , mBreakType(StyleClear::None)
     , mIncomplete(false)
     , mOverflowIncomplete(false)
     , mNextInFlowNeedsReflow(false)
     , mTruncated(false)
+    , mInlineBreak(false)
+    , mInlineBreakAfter(false)
   {}
 
   // Reset all the bit-fields.
   void Reset() {
+    mBreakType = StyleClear::None;
     mIncomplete = false;
     mOverflowIncomplete = false;
     mNextInFlowNeedsReflow = false;
     mTruncated = false;
+    mInlineBreak = false;
+    mInlineBreakAfter = false;
   }
 
   nsReflowStatus(uint32_t aStatus)
     : mStatus(aStatus)
   {}
 
   uint32_t& operator=(uint32_t aRhs) {
     mStatus = aRhs;
@@ -304,38 +312,53 @@ public:
     mOverflowIncomplete |= aStatus.mOverflowIncomplete;
     mNextInFlowNeedsReflow |= aStatus.mNextInFlowNeedsReflow;
     mTruncated |= aStatus.mTruncated;
     if (mIncomplete) {
       mOverflowIncomplete = false;
     }
   }
 
+  // mInlineBreak bit flag means a break is requested.
+
+  // Suppose a break is requested. When mInlineBreakAfter is set, the break
+  // should occur after the frame just reflowed; when mInlineBreakAfter is
+  // clear, the break should occur before the frame just reflowed.
+
+  // Set the inline line-break-before status, and reset other bit flags. The
+  // break type is StyleClear::Line. Note that other frame completion status
+  // isn't expected to matter after calling this method.
+  void SetInlineLineBreakBeforeAndReset() {
+    Reset();
+    mBreakType = StyleClear::Line;
+    mInlineBreak = true;
+    mInlineBreakAfter = false;
+  }
+
 private:
   uint32_t mStatus;
 
+  StyleClear mBreakType;
+
   // Frame completion status bit flags.
   bool mIncomplete : 1;
   bool mOverflowIncomplete : 1;
   bool mNextInFlowNeedsReflow : 1;
   bool mTruncated : 1;
+
+  // Inline break status bit flags.
+  bool mInlineBreak : 1;
+  bool mInlineBreakAfter : 1;
 };
 
 #define NS_FRAME_COMPLETE             0       // Note: not a bit!
 #define NS_FRAME_NOT_COMPLETE         0x1
 #define NS_FRAME_OVERFLOW_INCOMPLETE  0x4
 
-// This bit is set, when a break is requested. This bit is orthogonal
-// to the nsIFrame::nsReflowStatus completion bits.
 #define NS_INLINE_BREAK              0x0100
-
-// When a break is requested, this bit when set indicates that the
-// break should occur after the frame just reflowed; when the bit is
-// clear the break should occur before the frame just reflowed.
-#define NS_INLINE_BREAK_BEFORE       0x0000
 #define NS_INLINE_BREAK_AFTER        0x0200
 
 // The type of break requested can be found in these bits.
 #define NS_INLINE_BREAK_TYPE_MASK    0xF000
 
 // Set when a break was induced by completion of a first-letter
 #define NS_INLINE_BREAK_FIRST_LETTER_COMPLETE 0x10000
 
@@ -351,24 +374,16 @@ private:
 #define NS_INLINE_IS_BREAK_BEFORE(_status) \
   (NS_INLINE_BREAK == ((_status) & (NS_INLINE_BREAK|NS_INLINE_BREAK_AFTER)))
 
 #define NS_INLINE_GET_BREAK_TYPE(_status) \
   (static_cast<StyleClear>(((_status) >> 12) & 0xF))
 
 #define NS_INLINE_MAKE_BREAK_TYPE(_type)  (static_cast<int>(_type) << 12)
 
-// Construct a line-break-before status. Note that there is no
-// completion status for a line-break before because we *know* that
-// the frame will be reflowed later and hence its current completion
-// status doesn't matter.
-#define NS_INLINE_LINE_BREAK_BEFORE()                                   \
-  (NS_INLINE_BREAK | NS_INLINE_BREAK_BEFORE |                           \
-   NS_INLINE_MAKE_BREAK_TYPE(StyleClear::Line))
-
 // Take a completion status and add to it the desire to have a
 // line-break after. For this macro we do need the completion status
 // because the user of the status will need to know whether to
 // continue the frame or not.
 #define NS_INLINE_LINE_BREAK_AFTER(_completionStatus)                   \
   ((_completionStatus) | NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER |      \
    NS_INLINE_MAKE_BREAK_TYPE(StyleClear::Line))
 
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -1413,17 +1413,17 @@ nsLineLayout::CanPlaceFrame(PerFrameData
     // We will want to try backup.
     mNeedBackup = true;
     return true;
   }
 
 #ifdef NOISY_CAN_PLACE_FRAME
   printf("   ==> didn't fit\n");
 #endif
-  aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+  aStatus.SetInlineLineBreakBeforeAndReset();
   return false;
 }
 
 /**
  * Place the frame. Update running counters.
  */
 void
 nsLineLayout::PlaceFrame(PerFrameData* pfd, ReflowOutput& aMetrics)
--- a/layout/generic/nsRubyBaseContainerFrame.cpp
+++ b/layout/generic/nsRubyBaseContainerFrame.cpp
@@ -509,27 +509,27 @@ nsRubyBaseContainerFrame::ReflowColumns(
     }
   }
 
   if (!e.AtEnd() && NS_INLINE_IS_BREAK_AFTER(reflowStatus)) {
     // The current column has been successfully placed.
     // Skip to the next column and mark break before.
     e.Next();
     e.GetColumn(column);
-    reflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
+    reflowStatus.SetInlineLineBreakBeforeAndReset();
   }
   if (!e.AtEnd() || (GetNextInFlow() && !isComplete)) {
     aStatus.SetIncomplete();
   }
 
   if (NS_INLINE_IS_BREAK_BEFORE(reflowStatus)) {
     if (!columnIndex || !aReflowInput.mAllowLineBreak) {
       // If no column has been placed yet, or we have any span,
       // the whole container should be in the next line.
-      aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+      aStatus.SetInlineLineBreakBeforeAndReset();
       return 0;
     }
     aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus);
     MOZ_ASSERT(aStatus.IsComplete() || aReflowInput.mAllowLineBreak);
 
     // If we are on an intra-level whitespace column, null values in
     // column.mBaseFrame and column.mTextFrames don't represent the
     // end of the frame-sibling-chain at that level -- instead, they
@@ -593,17 +593,17 @@ nsRubyBaseContainerFrame::ReflowOneColum
         gfxBreakPriority lastBreakPriority =
           baseReflowInput.mLineLayout->LastOptionalBreakPriority();
         if (breakPriority >= lastBreakPriority) {
           // Either we have been overflow, or we are forced
           // to break here, do break before.
           if (istart > baseReflowInput.AvailableISize() ||
               baseReflowInput.mLineLayout->NotifyOptionalBreakPosition(
                 aColumn.mBaseFrame, 0, true, breakPriority)) {
-            aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+            aStatus.SetInlineLineBreakBeforeAndReset();
             return 0;
           }
         }
       }
     }
   }
 
   const uint32_t rtcCount = aReflowInput.mTextContainers.Length();
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -9545,17 +9545,17 @@ nsTextFrame::ReflowText(nsLineLayout& aL
   }
 
   // Compute reflow status
   aStatus = contentLength == maxContentLength
     ? NS_FRAME_COMPLETE : NS_FRAME_NOT_COMPLETE;
 
   if (charsFit == 0 && length > 0 && !usedHyphenation) {
     // Couldn't place any text
-    aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+    aStatus.SetInlineLineBreakBeforeAndReset();
   } else if (contentLength > 0 && mContentOffset + contentLength - 1 == newLineOffset) {
     // Ends in \n
     aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus);
     aLineLayout.SetLineEndsInBR(true);
   } else if (breakAfter) {
     aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus);
   }
   if (completedFirstLetter) {
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -3160,28 +3160,28 @@ nsTableFrame::ReflowChildren(TableReflow
         childX = rowGroups.IndexOf(kidFrame);
         if (childX == RowGroupArray::NoIndex) {
           // XXXbz can this happen?
           childX = rowGroups.Length();
         }
       }
       if (isPaginated && !aStatus.IsFullyComplete() &&
           ShouldAvoidBreakInside(aReflowInput.reflowInput)) {
-        aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+        aStatus.SetInlineLineBreakBeforeAndReset();
         break;
       }
       // see if the rowgroup did not fit on this page might be pushed on
       // the next page
       if (isPaginated &&
           (NS_INLINE_IS_BREAK_BEFORE(aStatus) ||
            (aStatus.IsComplete() &&
             (NS_UNCONSTRAINEDSIZE != kidReflowInput.AvailableHeight()) &&
             kidReflowInput.AvailableHeight() < desiredSize.Height()))) {
         if (ShouldAvoidBreakInside(aReflowInput.reflowInput)) {
-          aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+          aStatus.SetInlineLineBreakBeforeAndReset();
           break;
         }
         // if we are on top of the page place with dataloss
         if (kidReflowInput.mFlags.mIsTopOfPage) {
           if (childX+1 < rowGroups.Length()) {
             nsIFrame* nextRowGroupFrame = rowGroups[childX + 1];
             if (nextRowGroupFrame) {
               PlaceChild(aReflowInput, kidFrame,
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -1115,17 +1115,17 @@ nsTableRowFrame::Reflow(nsPresContext*  
 
   // See if we have a cell with specified/pct bsize
   InitHasCellWithStyleBSize(tableFrame);
 
   ReflowChildren(aPresContext, aDesiredSize, aReflowInput, *tableFrame, aStatus);
 
   if (aPresContext->IsPaginated() && !aStatus.IsFullyComplete() &&
       ShouldAvoidBreakInside(aReflowInput)) {
-    aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+    aStatus.SetInlineLineBreakBeforeAndReset();
   }
 
   // Just set our isize to what was available.
   // The table will calculate the isize and not use our value.
   aDesiredSize.ISize(wm) = aReflowInput.AvailableISize();
 
   // If our parent is in initial reflow, it'll handle invalidating our
   // entire overflow rect.
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -1171,17 +1171,17 @@ nsTableRowGroupFrame::SplitRowGroup(nsPr
         ReflowChild(rowFrame, aPresContext, rowMetrics, rowReflowInput,
                     0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
         rowFrame->SetSize(nsSize(rowMetrics.Width(), rowMetrics.Height()));
         rowFrame->DidReflow(aPresContext, nullptr, nsDidReflowStatus::FINISHED);
         rowFrame->DidResize();
 
         if (!aRowForcedPageBreak && !aStatus.IsFullyComplete() &&
             ShouldAvoidBreakInside(aReflowInput)) {
-          aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+          aStatus.SetInlineLineBreakBeforeAndReset();
           break;
         }
 
         nsTableFrame::InvalidateTableFrame(rowFrame, oldRowRect,
                                            oldRowVisualOverflow,
                                            false);
 
         if (aStatus.IsIncomplete()) {
@@ -1237,17 +1237,17 @@ nsTableRowGroupFrame::SplitRowGroup(nsPr
         rowIsOnPage = false;
       }
 
       nsTableRowFrame* lastRowThisPage = rowFrame;
       nscoord spanningRowBottom = availHeight;
       if (!rowIsOnPage) {
         NS_ASSERTION(!contRow, "We should not have created a continuation if none of this row fits");
         if (!aRowForcedPageBreak && ShouldAvoidBreakInside(aReflowInput)) {
-          aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+          aStatus.SetInlineLineBreakBeforeAndReset();
           break;
         }
         if (prevRowFrame) {
           spanningRowBottom = prevRowFrame->GetNormalRect().YMost();
           lastRowThisPage = prevRowFrame;
           isTopOfPage = (lastRowThisPage == firstRowThisPage) && aReflowInput.mFlags.mIsTopOfPage;
           aStatus = NS_FRAME_NOT_COMPLETE;
         }