Bug 1116037 part 5 - Use unified struct for ruby reflow states. r=dbaron
authorXidorn Quan <quanxunzhen@gmail.com>
Mon, 29 Dec 2014 15:03:38 +1100
changeset 247654 8bf00a9544f0303a11d4acaf76e2005448f7d537
parent 247653 5f691b17679e356f928e6cb89564ad1da4920869
child 247655 f02749f3c8fc90c7a12dae1a5ecab3bc93d65390
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs1116037
milestone37.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 1116037 part 5 - Use unified struct for ruby reflow states. r=dbaron
layout/generic/nsRubyBaseContainerFrame.cpp
layout/generic/nsRubyBaseContainerFrame.h
--- a/layout/generic/nsRubyBaseContainerFrame.cpp
+++ b/layout/generic/nsRubyBaseContainerFrame.cpp
@@ -234,16 +234,23 @@ nsRubyBaseContainerFrame::ComputeSize(ns
 }
 
 /* virtual */ nscoord
 nsRubyBaseContainerFrame::GetLogicalBaseline(WritingMode aWritingMode) const
 {
   return mBaseline;
 }
 
+struct nsRubyBaseContainerFrame::ReflowState
+{
+  bool mAllowLineBreak;
+  const nsHTMLReflowState& mBaseReflowState;
+  const nsTArray<nsHTMLReflowState*>& mTextReflowStates;
+};
+
 // Check whether the given extra isize can fit in the line in base level.
 static bool
 ShouldBreakBefore(const nsHTMLReflowState& aReflowState, nscoord aExtraISize)
 {
   nsLineLayout* lineLayout = aReflowState.mLineLayout;
   int32_t offset;
   gfxBreakPriority priority;
   nscoord icoord = lineLayout->GetCurrentICoord();
@@ -359,29 +366,34 @@ nsRubyBaseContainerFrame::Reflow(nsPresC
         this, 0, startEdge <= aReflowState.AvailableISize(),
         gfxBreakPriority::eNormalBreak)) {
     aStatus = NS_INLINE_LINE_BREAK_BEFORE();
   }
 
   nscoord isize = 0;
   if (aStatus == NS_FRAME_COMPLETE) {
     // Reflow columns excluding any span
-    bool allowInternalLineBreak = allowLineBreak && mSpanContainers.IsEmpty();
-    isize = ReflowColumns(allowInternalLineBreak,
-                          aReflowState, rtcReflowStates, aStatus);
+    ReflowState reflowState = {
+      allowLineBreak && mSpanContainers.IsEmpty(),
+      aReflowState, rtcReflowStates
+    };
+    isize = ReflowColumns(reflowState, aStatus);
   }
 
   // If there exists any span, the columns must either be completely
   // reflowed, or be not reflowed at all.
   MOZ_ASSERT(NS_INLINE_IS_BREAK_BEFORE(aStatus) ||
              NS_FRAME_IS_COMPLETE(aStatus) || mSpanContainers.IsEmpty());
   if (!NS_INLINE_IS_BREAK_BEFORE(aStatus) &&
       NS_FRAME_IS_COMPLETE(aStatus) && !mSpanContainers.IsEmpty()) {
     // Reflow spans
-    nscoord spanISize = ReflowSpans(aReflowState, spanReflowStates);
+    ReflowState reflowState = {
+      false, aReflowState, spanReflowStates
+    };
+    nscoord spanISize = ReflowSpans(reflowState);
     nscoord deltaISize = spanISize - isize;
     if (deltaISize <= 0) {
       RubyUtils::ClearReservedISize(this);
     } else if (allowLineBreak && ShouldBreakBefore(aReflowState, deltaISize)) {
       aStatus = NS_INLINE_LINE_BREAK_BEFORE();
     } else {
       RubyUtils::SetReservedISize(this, deltaISize);
       aReflowState.mLineLayout->AdvanceICoord(deltaISize);
@@ -443,37 +455,35 @@ struct MOZ_STACK_CLASS nsRubyBaseContain
 {
   ContinuationTraversingState mBase;
   nsAutoTArray<ContinuationTraversingState, RTC_ARRAY_SIZE> mTexts;
 
   explicit PullFrameState(nsRubyBaseContainerFrame* aFrame);
 };
 
 nscoord
-nsRubyBaseContainerFrame::ReflowColumns(bool aAllowLineBreak,
-                                        const nsHTMLReflowState& aReflowState,
-                                        nsTArray<nsHTMLReflowState*>& aReflowStates,
+nsRubyBaseContainerFrame::ReflowColumns(const ReflowState& aReflowState,
                                         nsReflowStatus& aStatus)
 {
-  nsLineLayout* lineLayout = aReflowState.mLineLayout;
+  nsLineLayout* lineLayout = aReflowState.mBaseReflowState.mLineLayout;
   const uint32_t rtcCount = mTextContainers.Length();
   nscoord istart = lineLayout->GetCurrentICoord();
   nscoord icoord = istart;
   nsReflowStatus reflowStatus = NS_FRAME_COMPLETE;
   aStatus = NS_FRAME_COMPLETE;
 
   mColumnCount = 0;
   nsIFrame* baseFrame = nullptr;
   nsAutoTArray<nsIFrame*, RTC_ARRAY_SIZE> textFrames;
   textFrames.SetCapacity(rtcCount);
   RubyColumnEnumerator e(this, mTextContainers);
   for (; !e.AtEnd(); e.Next()) {
     e.GetFrames(baseFrame, textFrames);
-    icoord += ReflowOneColumn(aAllowLineBreak, aReflowState, aReflowStates,
-                              baseFrame, textFrames, reflowStatus);
+    icoord += ReflowOneColumn(aReflowState, baseFrame,
+                              textFrames, reflowStatus);
     if (NS_INLINE_IS_BREAK(reflowStatus)) {
       break;
     }
     // We are not handling overflow here.
     MOZ_ASSERT(reflowStatus == NS_FRAME_COMPLETE);
   }
 
   bool isComplete = false;
@@ -485,18 +495,18 @@ nsRubyBaseContainerFrame::ReflowColumns(
     // Try pull some frames from next continuations. This call replaces
     // |baseFrame| and |textFrames| with the frame pulled in each level.
     PullOneColumn(lineLayout, pullFrameState,
                   baseFrame, textFrames, isComplete);
     if (isComplete) {
       // No more frames can be pulled.
       break;
     }
-    icoord += ReflowOneColumn(aAllowLineBreak, aReflowState, aReflowStates,
-                              baseFrame, textFrames, reflowStatus);
+    icoord += ReflowOneColumn(aReflowState, baseFrame,
+                              textFrames, reflowStatus);
   }
 
   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.GetFrames(baseFrame, textFrames);
     reflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
@@ -533,28 +543,29 @@ nsRubyBaseContainerFrame::ReflowColumns(
     MOZ_ASSERT(e.AtEnd());
     aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus);
   }
 
   return icoord - istart;
 }
 
 nscoord
-nsRubyBaseContainerFrame::ReflowOneColumn(bool aAllowLineBreak,
-                                          const nsHTMLReflowState& aReflowState,
-                                          nsTArray<nsHTMLReflowState*>& aReflowStates,
+nsRubyBaseContainerFrame::ReflowOneColumn(const ReflowState& aReflowState,
                                           nsIFrame* aBaseFrame,
                                           const nsTArray<nsIFrame*>& aTextFrames,
                                           nsReflowStatus& aStatus)
 {
-  WritingMode lineWM = aReflowState.mLineLayout->GetWritingMode();
+  const nsHTMLReflowState& baseReflowState = aReflowState.mBaseReflowState;
+  const auto& textReflowStates = aReflowState.mTextReflowStates;
+
+  WritingMode lineWM = baseReflowState.mLineLayout->GetWritingMode();
   const uint32_t rtcCount = mTextContainers.Length();
   MOZ_ASSERT(aTextFrames.Length() == rtcCount);
-  MOZ_ASSERT(aReflowStates.Length() == rtcCount);
-  nscoord istart = aReflowState.mLineLayout->GetCurrentICoord();
+  MOZ_ASSERT(textReflowStates.Length() == rtcCount);
+  nscoord istart = baseReflowState.mLineLayout->GetCurrentICoord();
   nscoord columnISize = 0;
 
   nsAutoString baseText;
   if (aBaseFrame) {
     if (!nsContentUtils::GetNodeTextContent(aBaseFrame->GetContent(),
                                             true, baseText)) {
       NS_RUNTIMEABORT("OOM");
     }
@@ -577,78 +588,79 @@ nsRubyBaseContainerFrame::ReflowOneColum
       // using the content tree text comparison is correct.
       if (annotationText.Equals(baseText)) {
         textFrame->AddStateBits(NS_RUBY_TEXT_FRAME_AUTOHIDE);
       } else {
         textFrame->RemoveStateBits(NS_RUBY_TEXT_FRAME_AUTOHIDE);
       }
 
       nsReflowStatus reflowStatus;
-      nsHTMLReflowMetrics metrics(*aReflowStates[i]);
+      nsHTMLReflowMetrics metrics(*textReflowStates[i]);
       RubyUtils::ClearReservedISize(textFrame);
 
       bool pushedFrame;
-      aReflowStates[i]->mLineLayout->ReflowFrame(textFrame, reflowStatus,
-                                                 &metrics, pushedFrame);
+      textReflowStates[i]->mLineLayout->ReflowFrame(textFrame, reflowStatus,
+                                                    &metrics, pushedFrame);
       MOZ_ASSERT(!NS_INLINE_IS_BREAK(reflowStatus) && !pushedFrame,
                  "Any line break inside ruby box should has been suppressed");
       columnISize = std::max(columnISize, metrics.ISize(lineWM));
     }
   }
-  if (aAllowLineBreak && ShouldBreakBefore(aReflowState, columnISize)) {
+  if (aReflowState.mAllowLineBreak &&
+      ShouldBreakBefore(baseReflowState, columnISize)) {
     // Since ruby text container uses an independent line layout, it
     // may successfully place a frame because the line is empty while
     // the line of base container is not.
     aStatus = NS_INLINE_LINE_BREAK_BEFORE();
     return 0;
   }
 
   // Reflow the base frame
   if (aBaseFrame) {
     MOZ_ASSERT(aBaseFrame->GetType() == nsGkAtoms::rubyBaseFrame);
     nsReflowStatus reflowStatus;
-    nsHTMLReflowMetrics metrics(aReflowState);
+    nsHTMLReflowMetrics metrics(baseReflowState);
     RubyUtils::ClearReservedISize(aBaseFrame);
 
     bool pushedFrame;
-    aReflowState.mLineLayout->ReflowFrame(aBaseFrame, reflowStatus,
-                                          &metrics, pushedFrame);
+    baseReflowState.mLineLayout->ReflowFrame(aBaseFrame, reflowStatus,
+                                             &metrics, pushedFrame);
     MOZ_ASSERT(!NS_INLINE_IS_BREAK(reflowStatus) && !pushedFrame,
                "Any line break inside ruby box should has been suppressed");
     columnISize = std::max(columnISize, metrics.ISize(lineWM));
   }
 
   // Align all the line layout to the new coordinate.
   nscoord icoord = istart + columnISize;
-  nscoord deltaISize = icoord - aReflowState.mLineLayout->GetCurrentICoord();
+  nscoord deltaISize = icoord - baseReflowState.mLineLayout->GetCurrentICoord();
   if (deltaISize > 0) {
-    aReflowState.mLineLayout->AdvanceICoord(deltaISize);
+    baseReflowState.mLineLayout->AdvanceICoord(deltaISize);
     if (aBaseFrame) {
       RubyUtils::SetReservedISize(aBaseFrame, deltaISize);
     }
   }
   for (uint32_t i = 0; i < rtcCount; i++) {
-    nsLineLayout* lineLayout = aReflowStates[i]->mLineLayout;
+    nsLineLayout* lineLayout = textReflowStates[i]->mLineLayout;
     nsIFrame* textFrame = aTextFrames[i];
     nscoord deltaISize = icoord - lineLayout->GetCurrentICoord();
     if (deltaISize > 0) {
       lineLayout->AdvanceICoord(deltaISize);
       if (textFrame) {
         RubyUtils::SetReservedISize(textFrame, deltaISize);
       }
     }
     if (aBaseFrame && textFrame) {
       lineLayout->AttachLastFrameToBaseLineLayout();
     }
   }
 
   mColumnCount++;
-  if (aAllowLineBreak &&
-      aReflowState.mLineLayout->NotifyOptionalBreakPosition(
-        this, mColumnCount, icoord <= aReflowState.AvailableISize(),
+  if (aReflowState.mAllowLineBreak &&
+      baseReflowState.mLineLayout->NotifyOptionalBreakPosition(
+        this, mColumnCount, icoord <= baseReflowState.AvailableISize(),
         gfxBreakPriority::eNormalBreak)) {
     aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus);
   }
 
   return columnISize;
 }
 
 nsRubyBaseContainerFrame::PullFrameState::PullFrameState(
@@ -685,30 +697,30 @@ nsRubyBaseContainerFrame::PullOneColumn(
 
   if (!aIsComplete) {
     // We pulled frames from the next line, hence mark it dirty.
     aLineLayout->SetDirtyNextLine();
   }
 }
 
 nscoord
-nsRubyBaseContainerFrame::ReflowSpans(const nsHTMLReflowState& aReflowState,
-                                      nsTArray<nsHTMLReflowState*>& aReflowStates)
+nsRubyBaseContainerFrame::ReflowSpans(const ReflowState& aReflowState)
 {
-  WritingMode lineWM = aReflowState.mLineLayout->GetWritingMode();
+  WritingMode lineWM =
+    aReflowState.mBaseReflowState.mLineLayout->GetWritingMode();
   const uint32_t spanCount = mSpanContainers.Length();
   nscoord spanISize = 0;
 
   for (uint32_t i = 0; i < spanCount; i++) {
     nsRubyTextContainerFrame* container = mSpanContainers[i];
     nsIFrame* rtFrame = container->GetFirstPrincipalChild();
     nsReflowStatus reflowStatus;
-    nsHTMLReflowMetrics metrics(*aReflowStates[i]);
+    nsHTMLReflowMetrics metrics(*aReflowState.mTextReflowStates[i]);
     bool pushedFrame;
-    aReflowStates[i]->mLineLayout->ReflowFrame(rtFrame, reflowStatus,
-                                               &metrics, pushedFrame);
+    aReflowState.mTextReflowStates[i]->mLineLayout->
+      ReflowFrame(rtFrame, reflowStatus, &metrics, pushedFrame);
     MOZ_ASSERT(!NS_INLINE_IS_BREAK(reflowStatus) && !pushedFrame,
                "Any line break inside ruby box should has been suppressed");
     spanISize = std::max(spanISize, metrics.ISize(lineWM));
   }
 
   return spanISize;
 }
--- a/layout/generic/nsRubyBaseContainerFrame.h
+++ b/layout/generic/nsRubyBaseContainerFrame.h
@@ -73,30 +73,24 @@ public:
 protected:
   friend nsContainerFrame*
     NS_NewRubyBaseContainerFrame(nsIPresShell* aPresShell,
                                  nsStyleContext* aContext);
   explicit nsRubyBaseContainerFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
 
   nscoord CalculateMaxSpanISize(nsRenderingContext* aRenderingContext);
 
-  nscoord ReflowColumns(bool aAllowLineBreak,
-                        const nsHTMLReflowState& aReflowState,
-                        nsTArray<nsHTMLReflowState*>& aReflowStates,
+  struct ReflowState;
+  nscoord ReflowColumns(const ReflowState& aReflowState,
                         nsReflowStatus& aStatus);
-
-  nscoord ReflowOneColumn(bool aAllowLineBreak,
-                          const nsHTMLReflowState& aReflowState,
-                          nsTArray<nsHTMLReflowState*>& aReflowStates,
+  nscoord ReflowOneColumn(const ReflowState& aReflowState,
                           nsIFrame* aBaseFrame,
                           const nsTArray<nsIFrame*>& aTextFrames,
                           nsReflowStatus& aStatus);
-
-  nscoord ReflowSpans(const nsHTMLReflowState& aReflowState,
-                      nsTArray<nsHTMLReflowState*>& aReflowStates);
+  nscoord ReflowSpans(const ReflowState& aReflowState);
 
   struct PullFrameState;
 
   // Pull ruby base and corresponding ruby text frames from
   // continuations after them.
   void PullOneColumn(nsLineLayout* aLineLayout,
                      PullFrameState& aPullFrameState,
                      nsIFrame*& aBaseFrame,