Bug 1027354 - Fix fontweight and fontstyle on single char <mi>. r=roc
authorJames Kitchener <jkitch.bug@gmail.com>
Wed, 25 Jun 2014 05:20:00 -0400
changeset 190909 72f554d3e1c89ce66d0f7b8025bb93030f306f57
parent 190908 9f8a077acb66b8cd9249a71277c7b8b49df1c556
child 190910 f7bb59ea6a4acd033c1bc5ca93986bc79bbc5216
push id45437
push userryanvm@gmail.com
push dateThu, 26 Jun 2014 12:59:47 +0000
treeherdermozilla-inbound@72f554d3e1c8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs1027354
milestone33.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 1027354 - Fix fontweight and fontstyle on single char <mi>. r=roc
layout/generic/MathMLTextRunFactory.cpp
layout/generic/MathMLTextRunFactory.h
layout/generic/nsTextFrame.cpp
layout/reftests/mathml/mathvariant-3-ref.html
layout/reftests/mathml/mathvariant-3.html
--- a/layout/generic/MathMLTextRunFactory.cpp
+++ b/layout/generic/MathMLTextRunFactory.cpp
@@ -591,17 +591,33 @@ MathMLTextRunFactory::RebuildTextRun(nsT
   bool doMathvariantStyling = true;
 
   for (uint32_t i = 0; i < length; ++i) {
     int extraChars = 0;
     nsStyleContext* styleContext = styles[i];
     mathVar = styleContext->StyleFont()->mMathVariant;
 
     if (singleCharMI && mathVar == NS_MATHML_MATHVARIANT_NONE) {
-      mathVar = NS_MATHML_MATHVARIANT_ITALIC;
+      // If the user has explicitly set a non-default value for fontstyle or
+      // fontweight, the italic mathvariant behaviour of <mi> is disabled
+      // This overrides the initial values specified in fontStyle, to avoid
+      // inconsistencies in which attributes allow CSS changes and which do not.
+      if (mFlags & MATH_FONT_WEIGHT_BOLD) {
+        fontStyle.weight = NS_FONT_WEIGHT_BOLD;
+        if (mFlags & MATH_FONT_STYLING_NORMAL) {
+          fontStyle.style = NS_FONT_STYLE_NORMAL;
+        } else {
+          fontStyle.style = NS_FONT_STYLE_ITALIC;
+        }
+      } else if (mFlags & MATH_FONT_STYLING_NORMAL) {
+        fontStyle.style = NS_FONT_STYLE_NORMAL;
+        fontStyle.weight = NS_FONT_WEIGHT_NORMAL;
+      } else {
+        mathVar = NS_MATHML_MATHVARIANT_ITALIC;
+      }
     }
 
     uint32_t ch = str[i];
     if (NS_IS_HIGH_SURROGATE(ch) && i < length - 1 &&
         NS_IS_LOW_SURROGATE(str[i + 1])) {
       ch = SURROGATE_TO_UCS4(ch, str[i + 1]);
     }
     uint32_t ch2 = MathVariant(ch, mathVar);
--- a/layout/generic/MathMLTextRunFactory.h
+++ b/layout/generic/MathMLTextRunFactory.h
@@ -9,20 +9,28 @@
 #include "nsTextRunTransformations.h"
 
 /**
  * Builds textruns that render their text with MathML specific renderings.
  */
 class MathMLTextRunFactory : public nsTransformingTextRunFactory {
 public:
   MathMLTextRunFactory(nsTransformingTextRunFactory* aInnerTransformingTextRunFactory,
-                       uint8_t aSSTYScriptLevel)
+                       uint32_t aFlags, uint8_t aSSTYScriptLevel)
     : mInnerTransformingTextRunFactory(aInnerTransformingTextRunFactory),
+      mFlags(aFlags),
       mSSTYScriptLevel(aSSTYScriptLevel) {}
 
   virtual void RebuildTextRun(nsTransformedTextRun* aTextRun,
                               gfxContext* aRefContext) MOZ_OVERRIDE;
+  enum {
+    // Style effects which may override single character <mi> behaviour
+    MATH_FONT_STYLING_NORMAL   = 0x1, // fontstyle="normal" has been set.
+    MATH_FONT_WEIGHT_BOLD      = 0x2, // fontweight="bold" has been set.
+  };
+
 protected:
   nsAutoPtr<nsTransformingTextRunFactory> mInnerTransformingTextRunFactory;
+  uint32_t mFlags;
   uint8_t mSSTYScriptLevel;
 };
 
 #endif /*MATHMLTEXTRUNFACTORY_H_*/
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -1816,16 +1816,17 @@ gfxTextRun*
 BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
 {
   gfxSkipChars skipChars;
 
   const void* textPtr = aTextBuffer;
   bool anyTextTransformStyle = false;
   bool anyMathMLStyling = false;
   uint8_t sstyScriptLevel = 0;
+  uint32_t mathFlags = 0;
   uint32_t textFlags = nsTextFrameUtils::TEXT_NO_BREAKS;
 
   if (mCurrentRunContextInfo & nsTextFrameUtils::INCOMING_WHITESPACE) {
     textFlags |= nsTextFrameUtils::TEXT_INCOMING_WHITESPACE;
   }
   if (mCurrentRunContextInfo & nsTextFrameUtils::INCOMING_ARABICCHAR) {
     textFlags |= gfxTextRunFactory::TEXT_INCOMING_ARABICCHAR;
   }
@@ -1890,23 +1891,43 @@ BuildTextRunsScanner::BuildTextRunForFra
     textFlags |= GetSpacingFlags(LetterSpacing(f));
     textFlags |= GetSpacingFlags(WordSpacing(f));
     nsTextFrameUtils::CompressionMode compression =
       CSSWhitespaceToCompressionMode[textStyle->mWhiteSpace];
     if (enabledJustification && !textStyle->WhiteSpaceIsSignificant()) {
       textFlags |= gfxTextRunFactory::TEXT_ENABLE_SPACING;
     }
     fontStyle = f->StyleFont();
+    nsIFrame* parent = mLineContainer->GetParent();
     if (NS_MATHML_MATHVARIANT_NONE != fontStyle->mMathVariant) {
       anyMathMLStyling = true;
     } else if (mLineContainer->GetStateBits() & NS_FRAME_IS_IN_SINGLE_CHAR_MI) {
       textFlags |= nsTextFrameUtils::TEXT_IS_SINGLE_CHAR_MI;
       anyMathMLStyling = true;
-    }
-    nsIFrame* parent = mLineContainer->GetParent();
+      // Test for fontstyle attribute as StyleFont() may not be accurate
+      // To be consistent in terms of ignoring CSS style changes, fontweight
+      // gets checked too.
+      if (parent) {
+        nsIContent* content = parent->GetContent();
+        if (content) {
+          if (content->AttrValueIs(kNameSpaceID_None,
+                                  nsGkAtoms::fontstyle_,
+                                  NS_LITERAL_STRING("normal"),
+                                  eCaseMatters)) {
+            mathFlags |= MathMLTextRunFactory::MATH_FONT_STYLING_NORMAL;
+          }
+          if (content->AttrValueIs(kNameSpaceID_None,
+                                   nsGkAtoms::fontweight_,
+                                   NS_LITERAL_STRING("bold"),
+                                   eCaseMatters)) {
+            mathFlags |= MathMLTextRunFactory::MATH_FONT_WEIGHT_BOLD;
+          }
+        }
+      }
+    }
     if (mLineContainer->HasAnyStateBits(TEXT_IS_IN_TOKEN_MATHML)) {
       // All MathML tokens except <mtext> use 'math' script.
       if (!(parent && parent->GetContent() &&
           parent->GetContent()->Tag() == nsGkAtoms::mtext_)) {
         textFlags |= gfxTextRunFactory::TEXT_USE_MATH_SCRIPT;
       }
     }
     nsIFrame* child = mLineContainer;
@@ -2060,17 +2081,18 @@ BuildTextRunsScanner::BuildTextRunForFra
   // Setup factory chain
   nsAutoPtr<nsTransformingTextRunFactory> transformingFactory;
   if (anyTextTransformStyle) {
     transformingFactory =
       new nsCaseTransformTextRunFactory(transformingFactory.forget());
   }
   if (anyMathMLStyling) {
     transformingFactory =
-      new MathMLTextRunFactory(transformingFactory.forget(), sstyScriptLevel);
+      new MathMLTextRunFactory(transformingFactory.forget(), mathFlags,
+                               sstyScriptLevel);
   }
   nsTArray<nsStyleContext*> styles;
   if (transformingFactory) {
     iter.SetOriginalOffset(0);
     for (uint32_t i = 0; i < mMappedFlows.Length(); ++i) {
       MappedFlow* mappedFlow = &mMappedFlows[i];
       nsTextFrame* f;
       for (f = mappedFlow->mStartFrame; f != mappedFlow->mEndFrame;
--- a/layout/reftests/mathml/mathvariant-3-ref.html
+++ b/layout/reftests/mathml/mathvariant-3-ref.html
@@ -1,14 +1,44 @@
 <!doctype html>
 <html>
   <head>
-    <title>Test math-variant overrides fontstyle and fontweight</title>
+    <title>Test math-variant interaction with fontstyle and fontweight</title>
   </head>
   <body>
     <math>
       <mrow>
         <mtext>A</mtext>
         <mtext>A</mtext>
       </mrow>
     </math>
+    <p>
+    <math>
+    <mn>A</mn>
+    </math>
+    </p>
+    <p>
+    <math>
+    <mn fontweight="bold">A</mn>
+    </math>
+    </p>
+    <p>
+    <math>
+    <mn fontweight="bold" fontstyle="italic">A</mn>
+    </math>
+    </p>
+    <p>
+    <math>
+    <mn fontweight="bold" fontstyle="italic">A</mn>
+    </math>
+    </p>
+    <p>
+    <math>
+      <mn fontweight="bold" fontstyle="italic">A</mn>
+    </math>
+    </p>
+    <p>
+    <math>
+      <mn>A</mn>
+    </math>
+    </p>
   </body>
  </html>
--- a/layout/reftests/mathml/mathvariant-3.html
+++ b/layout/reftests/mathml/mathvariant-3.html
@@ -1,15 +1,45 @@
 <!doctype html>
 <html>
   <head>
-    <title>Test math-variant overrides fontstyle and fontweight</title>
+    <title>Test math-variant interaction with fontstyle and fontweight</title>
   </head>
   <body>
     <math>
       <mrow>
         <mtext mathvariant="normal" fontweight="bold">A</mtext>
         <mtext mathvariant="normal" fontstyle="italic">A</mtext>
       </mrow>
     </math>
+    <p>
+    <math>
+      <mi fontstyle="normal">A</mi>
+    </math>
+    </p>
+    <p>
+    <math>
+      <mi fontstyle="normal" fontweight="bold">A</mi>
+    </math>
+    </p>
+    <p>
+    <math>
+      <mi fontweight="bold">A</mi>
+    </math>
+    </p>
+    <p>
+    <math>
+      <mi fontweight="bold" fontstyle="italic">A</mi>
+    </math>
+    </p>
+    <p>
+    <math>
+      <mi fontweight="bold" style="font-style:normal">A</mi>
+    </math>
+    </p>
+    <p>
+    <math>
+      <mi fontstyle="normal" style="font-weight:bold">A</mi>
+    </math>
+    </p>
   </body>
  </html>