Bug 1140264 part 3 - Rename IsInlineDescendantOfRuby to ShouldSuppressLineBreak and exclude rbc/rtc from it. r=dbaron
authorXidorn Quan <quanxunzhen@gmail.com>
Wed, 11 Mar 2015 10:28:21 +1100
changeset 232888 f672b2cd7a4f89c6e91aa62d2e758fff62fbbaa6
parent 232887 a71446331ce6bbaf195f70a84774d3827402ef4d
child 232889 144ea3057b66c0422c3a307bb97fe32250104257
push id56673
push userxquan@mozilla.com
push dateTue, 10 Mar 2015 23:30:22 +0000
treeherdermozilla-inbound@144ea3057b66 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs1140264
milestone39.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 1140264 part 3 - Rename IsInlineDescendantOfRuby to ShouldSuppressLineBreak and exclude rbc/rtc from it. r=dbaron
layout/base/RestyleManager.cpp
layout/generic/nsBRFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsLineLayout.cpp
layout/generic/nsRubyBaseContainerFrame.cpp
layout/generic/nsTextFrame.cpp
layout/style/nsStyleContext.cpp
layout/style/nsStyleContext.h
layout/style/nsStyleStruct.h
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -3018,19 +3018,19 @@ ElementRestyler::ComputeRestyleResultFro
 
   if (oldContext->HasPseudoElementData() !=
         aNewContext->HasPseudoElementData()) {
     LOG_RESTYLE_CONTINUE("NS_STYLE_HAS_PSEUDO_ELEMENT_DATA differs between old"
                          " and new style contexts");
     return eRestyleResult_Continue;
   }
 
-  if (oldContext->IsInlineDescendantOfRuby() !=
-        aNewContext->IsInlineDescendantOfRuby()) {
-    LOG_RESTYLE_CONTINUE("NS_STYLE_IS_INLINE_DESCENDANT_OF_RUBY differes"
+  if (oldContext->ShouldSuppressLineBreak() !=
+        aNewContext->ShouldSuppressLineBreak()) {
+    LOG_RESTYLE_CONTINUE("NS_STYLE_SUPPRESS_LINEBREAK differes"
                          "between old and new style contexts");
     return eRestyleResult_Continue;
   }
 
   return eRestyleResult_Stop;
 }
 
 ElementRestyler::RestyleResult
--- a/layout/generic/nsBRFrame.cpp
+++ b/layout/generic/nsBRFrame.cpp
@@ -92,17 +92,17 @@ BRFrame::Reflow(nsPresContext* aPresCont
                            // mode by nsLineLayout::VerticalAlignFrames .
                            // However, it's not always 0.  See below.
   finalSize.ISize(wm) = 0;
   aMetrics.SetBlockStartAscent(0);
 
   // Only when the BR is operating in a line-layout situation will it
   // behave like a BR. BR is suppressed when it is inside ruby frames.
   nsLineLayout* ll = aReflowState.mLineLayout;
-  if (ll && !StyleContext()->IsInlineDescendantOfRuby()) {
+  if (ll && !StyleContext()->ShouldSuppressLineBreak()) {
     // Note that the compatibility mode check excludes AlmostStandards
     // mode, since this is the inline box model.  See bug 161691.
     if ( ll->LineIsEmpty() ||
          aPresContext->CompatibilityMode() == eCompatibility_FullStandards ) {
       // The line is logically empty; any whitespace is trimmed away.
       //
       // If this frame is going to terminate the line we know
       // that nothing else will go on the line. Therefore, in this
@@ -159,26 +159,26 @@ BRFrame::Reflow(nsPresContext* aPresCont
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
 }
 
 /* virtual */ void
 BRFrame::AddInlineMinISize(nsRenderingContext *aRenderingContext,
                            nsIFrame::InlineMinISizeData *aData)
 {
-  if (!StyleContext()->IsInlineDescendantOfRuby()) {
+  if (!StyleContext()->ShouldSuppressLineBreak()) {
     aData->ForceBreak(aRenderingContext);
   }
 }
 
 /* virtual */ void
 BRFrame::AddInlinePrefISize(nsRenderingContext *aRenderingContext,
                             nsIFrame::InlinePrefISizeData *aData)
 {
-  if (!StyleContext()->IsInlineDescendantOfRuby()) {
+  if (!StyleContext()->ShouldSuppressLineBreak()) {
     aData->ForceBreak(aRenderingContext);
   }
 }
 
 /* virtual */ nscoord
 BRFrame::GetMinISize(nsRenderingContext *aRenderingContext)
 {
   nscoord result = 0;
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -3924,17 +3924,17 @@ nsFrame::GetPrefISize(nsRenderingContext
 
 /* virtual */ void
 nsFrame::AddInlineMinISize(nsRenderingContext *aRenderingContext,
                            nsIFrame::InlineMinISizeData *aData)
 {
   NS_ASSERTION(GetParent(), "Must have a parent if we get here!");
   nsIFrame* parent = GetParent();
   bool canBreak = !CanContinueTextRun() &&
-    !parent->StyleContext()->IsInlineDescendantOfRuby() &&
+    !parent->StyleContext()->ShouldSuppressLineBreak() &&
     parent->StyleText()->WhiteSpaceCanWrap(parent);
   
   if (canBreak)
     aData->OptionallyBreak(aRenderingContext);
   aData->trailingWhitespace = 0;
   aData->skipWhitespace = false;
   aData->trailingTextFrame = nullptr;
   aData->currentLine += nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -452,17 +452,17 @@ nsLineLayout::BeginSpan(nsIFrame* aFrame
   psd->mIStart = aIStart;
   psd->mICoord = aIStart;
   psd->mIEnd = aIEnd;
   psd->mBaseline = aBaseline;
 
   nsIFrame* frame = aSpanReflowState->frame;
   psd->mNoWrap = !frame->StyleText()->WhiteSpaceCanWrap(frame) ||
                  mSuppressLineWrap ||
-                 frame->StyleContext()->IsInlineDescendantOfRuby();
+                 frame->StyleContext()->ShouldSuppressLineBreak();
   psd->mWritingMode = aSpanReflowState->GetWritingMode();
 
   // Switch to new span
   mCurrentSpan = psd;
   mSpanDepth++;
 }
 
 nscoord
@@ -2891,17 +2891,17 @@ nsLineLayout::ApplyFrameJustification(Pe
     }
   }
   return deltaICoord;
 }
 
 static nsIFrame*
 FindNearestRubyBaseAncestor(nsIFrame* aFrame)
 {
-  MOZ_ASSERT(aFrame->StyleContext()->IsInlineDescendantOfRuby());
+  MOZ_ASSERT(aFrame->StyleContext()->ShouldSuppressLineBreak());
   while (aFrame && aFrame->GetType() != nsGkAtoms::rubyBaseFrame) {
     aFrame = aFrame->GetParent();
   }
   // XXX It is possible that no ruby base ancestor is found because of
   // some edge cases like form control or canvas inside ruby text.
   // See bug 1138092 comment 4.
   NS_ASSERTION(aFrame, "No ruby base ancestor?");
   return aFrame;
@@ -3066,26 +3066,26 @@ nsLineLayout::TextAlignLine(nsLineBox* a
 
   int32_t additionalGaps = 0;
   if (!isSVG && (mHasRuby || (doTextAlign &&
                               textAlign == NS_STYLE_TEXT_ALIGN_JUSTIFY))) {
     JustificationComputationState computeState;
     ComputeFrameJustification(psd, computeState);
     if (mHasRuby && computeState.mFirstParticipant) {
       PerFrameData* firstFrame = computeState.mFirstParticipant;
-      if (firstFrame->mFrame->StyleContext()->IsInlineDescendantOfRuby()) {
+      if (firstFrame->mFrame->StyleContext()->ShouldSuppressLineBreak()) {
         MOZ_ASSERT(!firstFrame->mJustificationAssignment.mGapsAtStart);
         nsIFrame* rubyBase = FindNearestRubyBaseAncestor(firstFrame->mFrame);
         if (rubyBase && IsRubyAlignSpaceAround(rubyBase)) {
           firstFrame->mJustificationAssignment.mGapsAtStart = 1;
           additionalGaps++;
         }
       }
       PerFrameData* lastFrame = computeState.mLastParticipant;
-      if (lastFrame->mFrame->StyleContext()->IsInlineDescendantOfRuby()) {
+      if (lastFrame->mFrame->StyleContext()->ShouldSuppressLineBreak()) {
         MOZ_ASSERT(!lastFrame->mJustificationAssignment.mGapsAtEnd);
         nsIFrame* rubyBase = FindNearestRubyBaseAncestor(lastFrame->mFrame);
         if (rubyBase && IsRubyAlignSpaceAround(rubyBase)) {
           lastFrame->mJustificationAssignment.mGapsAtEnd = 1;
           additionalGaps++;
         }
       }
     }
--- a/layout/generic/nsRubyBaseContainerFrame.cpp
+++ b/layout/generic/nsRubyBaseContainerFrame.cpp
@@ -245,24 +245,24 @@ LineBreakBefore(nsIFrame* aFrame,
   return gfxBreakPriority::eNoBreak;
 }
 
 static void
 GetIsLineBreakAllowed(nsIFrame* aFrame, bool aIsLineBreakable,
                       bool* aAllowInitialLineBreak, bool* aAllowLineBreak)
 {
   nsIFrame* parent = aFrame->GetParent();
-  bool inNestedRuby = parent->StyleContext()->IsInlineDescendantOfRuby();
+  bool lineBreakSuppressed = parent->StyleContext()->ShouldSuppressLineBreak();
   // Allow line break between ruby bases when white-space allows,
   // we are not inside a nested ruby, and there is no span.
-  bool allowLineBreak = !inNestedRuby &&
+  bool allowLineBreak = !lineBreakSuppressed &&
                         aFrame->StyleText()->WhiteSpaceCanWrap(aFrame);
   bool allowInitialLineBreak = allowLineBreak;
   if (!aFrame->GetPrevInFlow()) {
-    allowInitialLineBreak = !inNestedRuby &&
+    allowInitialLineBreak = !lineBreakSuppressed &&
                             parent->StyleText()->WhiteSpaceCanWrap(parent);
   }
   if (!aIsLineBreakable) {
     allowInitialLineBreak = false;
   }
   *aAllowInitialLineBreak = allowInitialLineBreak;
   *aAllowLineBreak = allowLineBreak;
 }
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -1922,17 +1922,17 @@ BuildTextRunsScanner::BuildTextRunForFra
     textStyle = f->StyleText();
     if (NS_STYLE_TEXT_TRANSFORM_NONE != textStyle->mTextTransform) {
       anyTextTransformStyle = true;
     }
     textFlags |= GetSpacingFlags(LetterSpacing(f));
     textFlags |= GetSpacingFlags(WordSpacing(f));
     nsTextFrameUtils::CompressionMode compression =
       CSSWhitespaceToCompressionMode[textStyle->mWhiteSpace];
-    if ((enabledJustification || f->StyleContext()->IsInlineDescendantOfRuby()) &&
+    if ((enabledJustification || f->StyleContext()->ShouldSuppressLineBreak()) &&
         !textStyle->WhiteSpaceIsSignificant() && !isSVG) {
       textFlags |= gfxTextRunFactory::TEXT_ENABLE_SPACING;
     }
     fontStyle = f->StyleFont();
     nsIFrame* parent = mLineContainer->GetParent();
     if (NS_MATHML_MATHVARIANT_NONE != fontStyle->mMathVariant) {
       if (NS_MATHML_MATHVARIANT_NORMAL != fontStyle->mMathVariant) {
         anyMathMLStyling = true;
@@ -2798,17 +2798,17 @@ static int32_t FindChar(const nsTextFrag
         return (static_cast<const char*>(p) - str) + aOffset;
     }
   }
   return -1;
 }
 
 static bool IsChineseOrJapanese(nsIFrame* aFrame)
 {
-  if (aFrame->StyleContext()->IsInlineDescendantOfRuby()) {
+  if (aFrame->StyleContext()->ShouldSuppressLineBreak()) {
     // Always treat ruby as CJ language so that those characters can
     // be expanded properly even when surrounded by other language.
     return true;
   }
 
   nsIAtom* language = aFrame->StyleFont()->mLanguage;
   if (!language) {
     return false;
@@ -8290,17 +8290,17 @@ nsTextFrame::ReflowText(nsLineLayout& aL
   gfxFloat trimmedWidth = 0;
   gfxFloat availWidth = aAvailableWidth;
   bool canTrimTrailingWhitespace = !textStyle->WhiteSpaceIsSignificant() ||
                                    (GetStateBits() & TEXT_IS_IN_TOKEN_MATHML);
   int32_t unusedOffset;
   gfxBreakPriority breakPriority;
   aLineLayout.GetLastOptionalBreakPosition(&unusedOffset, &breakPriority);
   gfxTextRun::SuppressBreak suppressBreak = gfxTextRun::eNoSuppressBreak;
-  if (StyleContext()->IsInlineDescendantOfRuby()) {
+  if (StyleContext()->ShouldSuppressLineBreak()) {
     suppressBreak = gfxTextRun::eSuppressAllBreaks;
   } else if (!aLineLayout.LineIsBreakable()) {
     suppressBreak = gfxTextRun::eSuppressInitialBreak;
   }
   uint32_t transformedCharsFit =
     mTextRun->BreakAndMeasureText(transformedOffset, transformedLength,
                                   (GetStateBits() & TEXT_START_OF_LINE) != 0,
                                   availWidth,
@@ -8501,17 +8501,17 @@ nsTextFrame::ReflowText(nsLineLayout& aL
     aLineLayout.NotifyOptionalBreakPosition(this, length, fits,
                                             gfxBreakPriority::eNormalBreak);
   }
   bool breakAfter = forceBreakAfter;
   // length == 0 means either the text is empty or it's all collapsed away
   bool emptyTextAtStartOfLine = atStartOfLine && length == 0;
   if (!breakAfter && charsFit == length && !emptyTextAtStartOfLine &&
       transformedOffset + transformedLength == mTextRun->GetLength() &&
-      !StyleContext()->IsInlineDescendantOfRuby() &&
+      !StyleContext()->ShouldSuppressLineBreak() &&
       (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TRAILING_BREAK)) {
     // We placed all the text in the textrun and we have a break opportunity at
     // the end of the textrun. We need to record it because the following
     // content may not care about nsLineBreaker.
 
     // Note that because we didn't break, we can be sure that (thanks to the
     // code up above) textMetrics.mAdvanceWidth includes the width of any
     // trailing whitespace. So we need to subtract trimmableWidth here
@@ -8563,17 +8563,17 @@ nsTextFrame::ReflowText(nsLineLayout& aL
   } else if (cachedNewlineOffset) {
     mContent->DeleteProperty(nsGkAtoms::newline);
   }
 
   // Compute space and letter counts for justification, if required
   if (!textStyle->WhiteSpaceIsSignificant() &&
       (lineContainer->StyleText()->mTextAlign == NS_STYLE_TEXT_ALIGN_JUSTIFY ||
        lineContainer->StyleText()->mTextAlignLast == NS_STYLE_TEXT_ALIGN_JUSTIFY ||
-       StyleContext()->IsInlineDescendantOfRuby()) &&
+       StyleContext()->ShouldSuppressLineBreak()) &&
       !lineContainer->IsSVGText()) {
     AddStateBits(TEXT_JUSTIFICATION_ENABLED);
     provider.ComputeJustification(offset, charsFit);
     aLineLayout.SetJustificationInfo(provider.GetJustificationInfo());
   }
 
   SetLength(contentLength, &aLineLayout, ALLOW_FRAME_CREATION_AND_DESTRUCTION);
 
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -511,16 +511,46 @@ nsStyleContext::SetStyle(nsStyleStructID
   } else {
     dataSlot = &mCachedInheritedData.mStyleStructs[aSID];
   }
   NS_ASSERTION(!*dataSlot || (mBits & nsCachedStyleData::GetBitForSID(aSID)),
                "Going to leak style data");
   *dataSlot = aStruct;
 }
 
+static bool
+ShouldSuppressLineBreak(const nsStyleDisplay* aStyleDisplay,
+                        const nsStyleContext* aContainerContext,
+                        const nsStyleDisplay* aContainerDisplay)
+{
+  // The display change should only occur for "in-flow" children
+  if (aStyleDisplay->IsOutOfFlowStyle()) {
+    return false;
+  }
+  if (aContainerContext->ShouldSuppressLineBreak()) {
+    // Line break suppressing bit is propagated to any children of line
+    // participants, which include inline and inline ruby boxes.
+    if (aContainerDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE ||
+        aContainerDisplay->mDisplay == NS_STYLE_DISPLAY_RUBY ||
+        aContainerDisplay->mDisplay == NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER) {
+      return true;
+    }
+  }
+  // Any descendant of ruby level containers is non-breakable, but
+  // the level containers themselves are breakable. We have to check
+  // the container display type against all ruby display type here
+  // because any of the ruby boxes could be anonymous.
+  if (aContainerDisplay->IsRubyDisplayType() &&
+      aStyleDisplay->mDisplay != NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER &&
+      aStyleDisplay->mDisplay != NS_STYLE_DISPLAY_RUBY_TEXT_CONTAINER) {
+    return true;
+  }
+  return false;
+}
+
 void
 nsStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup)
 {
   // See if we have any text decorations.
   // First see if our parent has text decorations.  If our parent does, then we inherit the bit.
   if (mParent && mParent->HasTextDecorationLines()) {
     mBits |= NS_STYLE_HAS_TEXT_DECORATION_LINES;
   } else {
@@ -637,22 +667,18 @@ nsStyleContext::ApplyStyleFixups(bool aS
                        "converted its display value to be block-level...)");
           nsStyleDisplay *mutable_display =
             static_cast<nsStyleDisplay*>(GetUniqueStyleData(eStyleStruct_Display));
           mutable_display->mDisplay = displayVal;
         }
       }
     }
 
-    // The display change should only occur for "in-flow" children
-    if (!disp->IsOutOfFlowStyle() &&
-        ((containerDisp->mDisplay == NS_STYLE_DISPLAY_INLINE &&
-          containerContext->IsInlineDescendantOfRuby()) ||
-         containerDisp->IsRubyDisplayType())) {
-      mBits |= NS_STYLE_IS_INLINE_DESCENDANT_OF_RUBY;
+    if (::ShouldSuppressLineBreak(disp, containerContext, containerDisp)) {
+      mBits |= NS_STYLE_SUPPRESS_LINEBREAK;
       uint8_t displayVal = disp->mDisplay;
       nsRuleNode::EnsureInlineDisplay(displayVal);
       if (displayVal != disp->mDisplay) {
         nsStyleDisplay *mutable_display =
           static_cast<nsStyleDisplay*>(GetUniqueStyleData(eStyleStruct_Display));
         mutable_display->mDisplay = displayVal;
       }
     }
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -147,21 +147,23 @@ public:
                      nsRuleNode* aRulesIfVisited,
                      bool aRelevantLinkVisited);
 
   // Does this style context or any of its ancestors have text
   // decoration lines?
   bool HasTextDecorationLines() const
     { return !!(mBits & NS_STYLE_HAS_TEXT_DECORATION_LINES); }
 
-  // Whether this style context or any of its inline-level ancestors
-  // is directly contained by a ruby box? It is used to inlinize
-  // block-level descendants and suppress line breaks inside ruby.
-  bool IsInlineDescendantOfRuby() const
-    { return !!(mBits & NS_STYLE_IS_INLINE_DESCENDANT_OF_RUBY); }
+  // Whether any line break inside should be suppressed? If this returns
+  // true, the line should not be broken inside, which means inlines act
+  // as if nowrap is set, <br> is suppressed, and blocks are inlinized.
+  // This bit is propogated to all children of line partitipants. It is
+  // currenlty used by ruby to make its content frames unbreakable.
+  bool ShouldSuppressLineBreak() const
+    { return !!(mBits & NS_STYLE_SUPPRESS_LINEBREAK); }
 
   // Does this style context represent the style for a pseudo-element or
   // inherit data from such a style context?  Whether this returns true
   // is equivalent to whether it or any of its ancestors returns
   // non-null for GetPseudo.
   bool HasPseudoElementData() const
     { return !!(mBits & NS_STYLE_HAS_PSEUDO_ELEMENT_DATA); }
 
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -51,18 +51,18 @@ class imgIContainer;
 #define NS_STYLE_IS_STYLE_IF_VISITED       0x008000000
 // See nsStyleContext::UsesGrandancestorStyle
 #define NS_STYLE_USES_GRANDANCESTOR_STYLE  0x010000000
 // See nsStyleContext::IsShared
 #define NS_STYLE_IS_SHARED                 0x020000000
 // See nsStyleContext::AssertStructsNotUsedElsewhere
 // (This bit is currently only used in #ifdef DEBUG code.)
 #define NS_STYLE_IS_GOING_AWAY             0x040000000
-// See nsStyleContext::IsInlineDescendantOfRuby
-#define NS_STYLE_IS_INLINE_DESCENDANT_OF_RUBY 0x080000000
+// See nsStyleContext::ShouldSuppressLineBreak
+#define NS_STYLE_SUPPRESS_LINEBREAK        0x080000000
 // See nsStyleContext::GetPseudoEnum
 #define NS_STYLE_CONTEXT_TYPE_SHIFT        32
 
 // Additional bits for nsRuleNode's mDependentBits:
 #define NS_RULE_NODE_GC_MARK                0x02000000
 #define NS_RULE_NODE_USED_DIRECTLY          0x04000000
 #define NS_RULE_NODE_IS_IMPORTANT           0x08000000
 #define NS_RULE_NODE_LEVEL_MASK             0xf0000000