Bug 1027354 - Fix fontweight and fontstyle on single char <mi>. r=roc, a=sledru
authorJames Kitchener <jkitch.bug@gmail.com>
Wed, 25 Jun 2014 05:20:00 -0400
changeset 207518 7d454f6db4d5a0e16e71d922b8d734ea92a85ef8
parent 207517 4856bfe6102b40653caf7dc1ceabe6ef5ad3fae4
child 207519 6a84ea30242cfdf9a7782513999ffb0a960a81ad
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, sledru
bugs1027354
milestone32.0a2
Bug 1027354 - Fix fontweight and fontstyle on single char <mi>. r=roc, a=sledru
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>