Bug 1339711 - Part 1: stylo: Support -moz-script-size-multiplier, -moz-script-level, -moz-math-display; r?emilio draft
authorManish Goregaokar <manishearth@gmail.com>
Mon, 10 Apr 2017 15:28:48 +0800
changeset 561222 896f607cf52634ca300a1a6618c2118cf9d59f1e
parent 561221 9ed5ddbb68bbe6f53729f79e399d1a61d49c33d9
child 561223 9ab135c9da1843387fe976d616747d1cd42af379
push id53654
push userbmo:manishearth@gmail.com
push dateWed, 12 Apr 2017 09:22:24 +0000
reviewersemilio
bugs1339711
milestone55.0a1
Bug 1339711 - Part 1: stylo: Support -moz-script-size-multiplier, -moz-script-level, -moz-math-display; r?emilio MozReview-Commit-ID: KzBDsmZK5w0
dom/mathml/nsMathMLElement.cpp
layout/style/GenericSpecifiedValues.h
layout/style/GenericSpecifiedValuesInlines.h
layout/style/ServoBindingList.h
layout/style/ServoSpecifiedValues.cpp
layout/style/ServoSpecifiedValues.h
layout/style/nsRuleData.h
servo/components/style/build_gecko.rs
servo/components/style/gecko_bindings/bindings.rs
servo/components/style/gecko_bindings/structs_debug.rs
servo/components/style/gecko_bindings/structs_release.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/longhand/font.mako.rs
servo/ports/geckolib/glue.rs
--- a/dom/mathml/nsMathMLElement.cpp
+++ b/dom/mathml/nsMathMLElement.cpp
@@ -503,29 +503,27 @@ nsMathMLElement::MapMathMLAttributesInto
     // "Specifies the multiplier to be used to adjust font size due to changes
     // in scriptlevel.
     //
     // values: number
     // default: 0.71
     //
     const nsAttrValue* value =
       aAttributes->GetAttr(nsGkAtoms::scriptsizemultiplier_);
-    nsCSSValue* scriptSizeMultiplier =
-      aData->ValueForScriptSizeMultiplier();
     if (value && value->Type() == nsAttrValue::eString &&
-        scriptSizeMultiplier->GetUnit() == eCSSUnit_Null) {
+        !aData->PropertyIsSet(eCSSProperty__moz_script_size_multiplier)) {
       nsAutoString str(value->GetStringValue());
       str.CompressWhitespace();
       // MathML numbers can't have leading '+'
       if (str.Length() > 0 && str.CharAt(0) != '+') {
         nsresult errorCode;
         float floatValue = str.ToFloat(&errorCode);
         // Negative scriptsizemultipliers are not parsed
         if (NS_SUCCEEDED(errorCode) && floatValue >= 0.0f) {
-          scriptSizeMultiplier->SetFloatValue(floatValue, eCSSUnit_Number);
+          aData->SetNumberValue(eCSSProperty__moz_script_size_multiplier, floatValue);
         } else {
           ReportParseErrorNoTag(str,
                                 nsGkAtoms::scriptsizemultiplier_,
                                 aData->mPresContext->Document());
         }
       }
     }
 
@@ -561,34 +559,33 @@ nsMathMLElement::MapMathMLAttributesInto
     // sign is given, it increments ("+") or decrements ("-") the current
     // value. (Note that large decrements can result in negative values of
     // scriptlevel, but these values are considered legal.)"
     //
     // values: ( "+" | "-" )? unsigned-integer
     // default: inherited
     //
     value = aAttributes->GetAttr(nsGkAtoms::scriptlevel_);
-    nsCSSValue* scriptLevel = aData->ValueForScriptLevel();
     if (value && value->Type() == nsAttrValue::eString &&
-        scriptLevel->GetUnit() == eCSSUnit_Null) {
+        !aData->PropertyIsSet(eCSSProperty__moz_script_level)) {
       nsAutoString str(value->GetStringValue());
       str.CompressWhitespace();
       if (str.Length() > 0) {
         nsresult errorCode;
         int32_t intValue = str.ToInteger(&errorCode);
         if (NS_SUCCEEDED(errorCode)) {
           // This is kind of cheesy ... if the scriptlevel has a sign,
           // then it's a relative value and we store the nsCSSValue as an
           // Integer to indicate that. Otherwise we store it as a Number
           // to indicate that the scriptlevel is absolute.
           char16_t ch = str.CharAt(0);
           if (ch == '+' || ch == '-') {
-            scriptLevel->SetIntValue(intValue, eCSSUnit_Integer);
+            aData->SetIntValue(eCSSProperty__moz_script_level, intValue);
           } else {
-            scriptLevel->SetFloatValue(intValue, eCSSUnit_Number);
+            aData->SetNumberValue(eCSSProperty__moz_script_level, intValue);
           }
         } else {
           ReportParseErrorNoTag(str,
                                 nsGkAtoms::scriptlevel_,
                                 aData->mPresContext->Document());
         }
       }
     }
@@ -736,20 +733,19 @@ nsMathMLElement::MapMathMLAttributesInto
     // than styling, it typically conveys semantic intent;"
     //
     // values: "normal" | "bold" | "italic" | "bold-italic" | "double-struck" |
     // "bold-fraktur" | "script" | "bold-script" | "fraktur" | "sans-serif" |
     // "bold-sans-serif" | "sans-serif-italic" | "sans-serif-bold-italic" |
     // "monospace" | "initial" | "tailed" | "looped" | "stretched"
     // default: normal (except on <mi>)
     //
-    nsCSSValue* mathVariant = aData->ValueForMathVariant();
     value = aAttributes->GetAttr(nsGkAtoms::mathvariant_);
     if (value && value->Type() == nsAttrValue::eString &&
-        mathVariant->GetUnit() == eCSSUnit_Null) {
+        !aData->PropertyIsSet(eCSSProperty__moz_math_variant)) {
       nsAutoString str(value->GetStringValue());
       str.CompressWhitespace();
       static const char sizes[19][23] = {
         "normal", "bold", "italic", "bold-italic", "script", "bold-script",
         "fraktur", "double-struck", "bold-fraktur", "sans-serif",
         "bold-sans-serif", "sans-serif-italic", "sans-serif-bold-italic",
         "monospace", "initial", "tailed", "looped", "stretched"
       };
@@ -763,17 +759,17 @@ nsMathMLElement::MapMathMLAttributesInto
         NS_MATHML_MATHVARIANT_SANS_SERIF_ITALIC,
         NS_MATHML_MATHVARIANT_SANS_SERIF_BOLD_ITALIC,
         NS_MATHML_MATHVARIANT_MONOSPACE, NS_MATHML_MATHVARIANT_INITIAL,
         NS_MATHML_MATHVARIANT_TAILED, NS_MATHML_MATHVARIANT_LOOPED,
         NS_MATHML_MATHVARIANT_STRETCHED
       };
       for (uint32_t i = 0; i < ArrayLength(sizes); ++i) {
         if (str.EqualsASCII(sizes[i])) {
-          mathVariant->SetIntValue(values[i], eCSSUnit_Enumerated);
+          aData->SetKeywordValue(eCSSProperty__moz_math_variant, values[i]);
           break;
         }
       }
     }
   }
 
   // mathbackground
   // 
--- a/layout/style/GenericSpecifiedValues.h
+++ b/layout/style/GenericSpecifiedValues.h
@@ -73,16 +73,19 @@ public:
     }
 
     // Set a property to an integer value
     inline void SetIntValue(nsCSSPropertyID aId, int32_t aValue);
     // Set a property to a pixel value
     inline void SetPixelValue(nsCSSPropertyID aId, float aValue);
     inline void SetPixelValueIfUnset(nsCSSPropertyID aId, float aValue);
 
+    // Set a property to a number value
+    inline void SetNumberValue(nsCSSPropertyID aId, float aValue);
+
     // Set a property to a percent value
     inline void SetPercentValue(nsCSSPropertyID aId, float aValue);
     inline void SetPercentValueIfUnset(nsCSSPropertyID aId, float aValue);
 
     // Set a property to `auto`
     inline void SetAutoValue(nsCSSPropertyID aId);
     inline void SetAutoValueIfUnset(nsCSSPropertyID aId);
 
--- a/layout/style/GenericSpecifiedValuesInlines.h
+++ b/layout/style/GenericSpecifiedValuesInlines.h
@@ -94,16 +94,22 @@ GenericSpecifiedValues::SetPixelValue(ns
 
 void
 GenericSpecifiedValues::SetPixelValueIfUnset(nsCSSPropertyID aId, float aValue)
 {
   MOZ_STYLO_FORWARD(SetPixelValueIfUnset, (aId, aValue))
 }
 
 void
+GenericSpecifiedValues::SetNumberValue(nsCSSPropertyID aId, float aValue)
+{
+  MOZ_STYLO_FORWARD(SetNumberValue, (aId, aValue))
+}
+
+void
 GenericSpecifiedValues::SetPercentValue(nsCSSPropertyID aId, float aValue)
 {
   MOZ_STYLO_FORWARD(SetPercentValue, (aId, aValue))
 }
 
 void
 GenericSpecifiedValues::SetPercentValueIfUnset(nsCSSPropertyID aId, float aValue)
 {
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -235,16 +235,20 @@ SERVO_BINDING_FUNC(Servo_DeclarationBloc
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_SetIntValue, void,
                    RawServoDeclarationBlockBorrowed declarations,
                    nsCSSPropertyID property,
                    int32_t value)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_SetPixelValue, void,
                    RawServoDeclarationBlockBorrowed declarations,
                    nsCSSPropertyID property,
                    float value)
+SERVO_BINDING_FUNC(Servo_DeclarationBlock_SetNumberValue, void,
+                   RawServoDeclarationBlockBorrowed declarations,
+                   nsCSSPropertyID property,
+                   float value)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_SetPercentValue, void,
                    RawServoDeclarationBlockBorrowed declarations,
                    nsCSSPropertyID property,
                    float value)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_SetAutoValue, void,
                    RawServoDeclarationBlockBorrowed declarations,
                    nsCSSPropertyID property)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_SetCurrentColor, void,
--- a/layout/style/ServoSpecifiedValues.cpp
+++ b/layout/style/ServoSpecifiedValues.cpp
@@ -64,16 +64,22 @@ ServoSpecifiedValues::SetIntValue(nsCSSP
 
 void
 ServoSpecifiedValues::SetPixelValue(nsCSSPropertyID aId, float aValue)
 {
   Servo_DeclarationBlock_SetPixelValue(mDecl, aId, aValue);
 }
 
 void
+ServoSpecifiedValues::SetNumberValue(nsCSSPropertyID aId, float aValue)
+{
+  Servo_DeclarationBlock_SetNumberValue(mDecl, aId, aValue);
+}
+
+void
 ServoSpecifiedValues::SetPercentValue(nsCSSPropertyID aId, float aValue)
 {
   Servo_DeclarationBlock_SetPercentValue(mDecl, aId, aValue);
 }
 
 void
 ServoSpecifiedValues::SetAutoValue(nsCSSPropertyID aId)
 {
--- a/layout/style/ServoSpecifiedValues.h
+++ b/layout/style/ServoSpecifiedValues.h
@@ -55,16 +55,19 @@ public:
 
   void SetPixelValueIfUnset(nsCSSPropertyID aId,
                             float aValue) {
     if (!PropertyIsSet(aId)) {
       SetPixelValue(aId, aValue);
     }
   }
 
+  void SetNumberValue(nsCSSPropertyID aId,
+                     float aValue);
+
   void SetPercentValue(nsCSSPropertyID aId,
                        float aValue);
 
   void SetAutoValue(nsCSSPropertyID aId);
 
   void SetAutoValueIfUnset(nsCSSPropertyID aId) {
     if (!PropertyIsSet(aId)) {
       SetAutoValue(aId);
--- a/layout/style/nsRuleData.h
+++ b/layout/style/nsRuleData.h
@@ -161,16 +161,21 @@ struct nsRuleData final: mozilla::Generi
 
   void SetPixelValueIfUnset(nsCSSPropertyID aId,
                             float aValue) {
     if (!PropertyIsSet(aId)) {
       SetPixelValue(aId, aValue);
     }
   }
 
+  void SetNumberValue(nsCSSPropertyID aId,
+                     float aValue) {
+    ValueFor(aId)->SetFloatValue(aValue, eCSSUnit_Number);
+  }
+
   void SetPercentValue(nsCSSPropertyID aId,
                        float aValue) {
     ValueFor(aId)->SetPercentValue(aValue);
   }
 
   void SetAutoValue(nsCSSPropertyID aId) {
     ValueFor(aId)->SetAutoValue();
   }
--- a/servo/components/style/build_gecko.rs
+++ b/servo/components/style/build_gecko.rs
@@ -297,16 +297,17 @@ mod bindings {
             .bitfield_enum("nsChangeHint")
             .bitfield_enum("nsRestyleHint")
             .constified_enum("UpdateAnimationsTasks");
         let whitelist_vars = [
             "NS_THEME_.*",
             "NODE_.*",
             "NS_FONT_.*",
             "NS_STYLE_.*",
+            "NS_MATHML_.*",
             "NS_RADIUS_.*",
             "BORDER_COLOR_.*",
             "BORDER_STYLE_.*",
             "mozilla::SERVO_PREF_.*",
             "kNameSpaceID_.*",
             "kGenericFont_.*",
             "kPresContext_.*",
         ];
--- a/servo/components/style/gecko_bindings/bindings.rs
+++ b/servo/components/style/gecko_bindings/bindings.rs
@@ -1846,16 +1846,22 @@ extern "C" {
 }
 extern "C" {
     pub fn Servo_DeclarationBlock_SetPixelValue(declarations:
                                                     RawServoDeclarationBlockBorrowed,
                                                 property: nsCSSPropertyID,
                                                 value: f32);
 }
 extern "C" {
+    pub fn Servo_DeclarationBlock_SetNumberValue(declarations:
+                                                     RawServoDeclarationBlockBorrowed,
+                                                 property: nsCSSPropertyID,
+                                                 value: f32);
+}
+extern "C" {
     pub fn Servo_DeclarationBlock_SetPercentValue(declarations:
                                                       RawServoDeclarationBlockBorrowed,
                                                   property: nsCSSPropertyID,
                                                   value: f32);
 }
 extern "C" {
     pub fn Servo_DeclarationBlock_SetAutoValue(declarations:
                                                    RawServoDeclarationBlockBorrowed,
--- a/servo/components/style/gecko_bindings/structs_debug.rs
+++ b/servo/components/style/gecko_bindings/structs_debug.rs
@@ -535,16 +535,45 @@ pub mod root {
     pub const NS_STYLE_FONT_LIST: ::std::os::raw::c_uint = 15;
     pub const NS_STYLE_FONT_FIELD: ::std::os::raw::c_uint = 16;
     pub const NS_STYLE_GRID_AUTO_FLOW_ROW: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_GRID_AUTO_FLOW_COLUMN: ::std::os::raw::c_uint = 2;
     pub const NS_STYLE_GRID_AUTO_FLOW_DENSE: ::std::os::raw::c_uint = 4;
     pub const NS_STYLE_GRID_TEMPLATE_SUBGRID: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_GRID_REPEAT_AUTO_FILL: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_GRID_REPEAT_AUTO_FIT: ::std::os::raw::c_uint = 1;
+    pub const NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER: f32 = 0.71;
+    pub const NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT: ::std::os::raw::c_uint =
+        8;
+    pub const NS_MATHML_MATHVARIANT_NONE: ::std::os::raw::c_uint = 0;
+    pub const NS_MATHML_MATHVARIANT_NORMAL: ::std::os::raw::c_uint = 1;
+    pub const NS_MATHML_MATHVARIANT_BOLD: ::std::os::raw::c_uint = 2;
+    pub const NS_MATHML_MATHVARIANT_ITALIC: ::std::os::raw::c_uint = 3;
+    pub const NS_MATHML_MATHVARIANT_BOLD_ITALIC: ::std::os::raw::c_uint = 4;
+    pub const NS_MATHML_MATHVARIANT_SCRIPT: ::std::os::raw::c_uint = 5;
+    pub const NS_MATHML_MATHVARIANT_BOLD_SCRIPT: ::std::os::raw::c_uint = 6;
+    pub const NS_MATHML_MATHVARIANT_FRAKTUR: ::std::os::raw::c_uint = 7;
+    pub const NS_MATHML_MATHVARIANT_DOUBLE_STRUCK: ::std::os::raw::c_uint = 8;
+    pub const NS_MATHML_MATHVARIANT_BOLD_FRAKTUR: ::std::os::raw::c_uint = 9;
+    pub const NS_MATHML_MATHVARIANT_SANS_SERIF: ::std::os::raw::c_uint = 10;
+    pub const NS_MATHML_MATHVARIANT_BOLD_SANS_SERIF: ::std::os::raw::c_uint =
+        11;
+    pub const NS_MATHML_MATHVARIANT_SANS_SERIF_ITALIC: ::std::os::raw::c_uint
+              =
+        12;
+    pub const NS_MATHML_MATHVARIANT_SANS_SERIF_BOLD_ITALIC:
+              ::std::os::raw::c_uint =
+        13;
+    pub const NS_MATHML_MATHVARIANT_MONOSPACE: ::std::os::raw::c_uint = 14;
+    pub const NS_MATHML_MATHVARIANT_INITIAL: ::std::os::raw::c_uint = 15;
+    pub const NS_MATHML_MATHVARIANT_TAILED: ::std::os::raw::c_uint = 16;
+    pub const NS_MATHML_MATHVARIANT_LOOPED: ::std::os::raw::c_uint = 17;
+    pub const NS_MATHML_MATHVARIANT_STRETCHED: ::std::os::raw::c_uint = 18;
+    pub const NS_MATHML_DISPLAYSTYLE_INLINE: ::std::os::raw::c_uint = 0;
+    pub const NS_MATHML_DISPLAYSTYLE_BLOCK: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_WIDTH_MAX_CONTENT: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_WIDTH_MIN_CONTENT: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_WIDTH_FIT_CONTENT: ::std::os::raw::c_uint = 2;
     pub const NS_STYLE_WIDTH_AVAILABLE: ::std::os::raw::c_uint = 3;
     pub const NS_STYLE_POSITION_STATIC: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_POSITION_RELATIVE: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_POSITION_ABSOLUTE: ::std::os::raw::c_uint = 2;
     pub const NS_STYLE_POSITION_FIXED: ::std::os::raw::c_uint = 3;
--- a/servo/components/style/gecko_bindings/structs_release.rs
+++ b/servo/components/style/gecko_bindings/structs_release.rs
@@ -535,16 +535,45 @@ pub mod root {
     pub const NS_STYLE_FONT_LIST: ::std::os::raw::c_uint = 15;
     pub const NS_STYLE_FONT_FIELD: ::std::os::raw::c_uint = 16;
     pub const NS_STYLE_GRID_AUTO_FLOW_ROW: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_GRID_AUTO_FLOW_COLUMN: ::std::os::raw::c_uint = 2;
     pub const NS_STYLE_GRID_AUTO_FLOW_DENSE: ::std::os::raw::c_uint = 4;
     pub const NS_STYLE_GRID_TEMPLATE_SUBGRID: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_GRID_REPEAT_AUTO_FILL: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_GRID_REPEAT_AUTO_FIT: ::std::os::raw::c_uint = 1;
+    pub const NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER: f32 = 0.71;
+    pub const NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT: ::std::os::raw::c_uint =
+        8;
+    pub const NS_MATHML_MATHVARIANT_NONE: ::std::os::raw::c_uint = 0;
+    pub const NS_MATHML_MATHVARIANT_NORMAL: ::std::os::raw::c_uint = 1;
+    pub const NS_MATHML_MATHVARIANT_BOLD: ::std::os::raw::c_uint = 2;
+    pub const NS_MATHML_MATHVARIANT_ITALIC: ::std::os::raw::c_uint = 3;
+    pub const NS_MATHML_MATHVARIANT_BOLD_ITALIC: ::std::os::raw::c_uint = 4;
+    pub const NS_MATHML_MATHVARIANT_SCRIPT: ::std::os::raw::c_uint = 5;
+    pub const NS_MATHML_MATHVARIANT_BOLD_SCRIPT: ::std::os::raw::c_uint = 6;
+    pub const NS_MATHML_MATHVARIANT_FRAKTUR: ::std::os::raw::c_uint = 7;
+    pub const NS_MATHML_MATHVARIANT_DOUBLE_STRUCK: ::std::os::raw::c_uint = 8;
+    pub const NS_MATHML_MATHVARIANT_BOLD_FRAKTUR: ::std::os::raw::c_uint = 9;
+    pub const NS_MATHML_MATHVARIANT_SANS_SERIF: ::std::os::raw::c_uint = 10;
+    pub const NS_MATHML_MATHVARIANT_BOLD_SANS_SERIF: ::std::os::raw::c_uint =
+        11;
+    pub const NS_MATHML_MATHVARIANT_SANS_SERIF_ITALIC: ::std::os::raw::c_uint
+              =
+        12;
+    pub const NS_MATHML_MATHVARIANT_SANS_SERIF_BOLD_ITALIC:
+              ::std::os::raw::c_uint =
+        13;
+    pub const NS_MATHML_MATHVARIANT_MONOSPACE: ::std::os::raw::c_uint = 14;
+    pub const NS_MATHML_MATHVARIANT_INITIAL: ::std::os::raw::c_uint = 15;
+    pub const NS_MATHML_MATHVARIANT_TAILED: ::std::os::raw::c_uint = 16;
+    pub const NS_MATHML_MATHVARIANT_LOOPED: ::std::os::raw::c_uint = 17;
+    pub const NS_MATHML_MATHVARIANT_STRETCHED: ::std::os::raw::c_uint = 18;
+    pub const NS_MATHML_DISPLAYSTYLE_INLINE: ::std::os::raw::c_uint = 0;
+    pub const NS_MATHML_DISPLAYSTYLE_BLOCK: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_WIDTH_MAX_CONTENT: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_WIDTH_MIN_CONTENT: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_WIDTH_FIT_CONTENT: ::std::os::raw::c_uint = 2;
     pub const NS_STYLE_WIDTH_AVAILABLE: ::std::os::raw::c_uint = 3;
     pub const NS_STYLE_POSITION_STATIC: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_POSITION_RELATIVE: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_POSITION_ABSOLUTE: ::std::os::raw::c_uint = 2;
     pub const NS_STYLE_POSITION_FIXED: ::std::os::raw::c_uint = 3;
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -645,16 +645,17 @@ impl Debug for ${style_struct.gecko_stru
         "Position": impl_position,
         "LengthOrPercentage": impl_style_coord,
         "LengthOrPercentageOrAuto": impl_style_coord,
         "LengthOrPercentageOrNone": impl_style_coord,
         "LengthOrNone": impl_style_coord,
         "MaxLength": impl_style_coord,
         "MinLength": impl_style_coord,
         "Number": impl_simple,
+        "Integer": impl_simple,
         "Opacity": impl_simple,
         "CSSColor": impl_color,
         "SVGPaint": impl_svg_paint,
         "UrlOrNone": impl_css_url,
     }
 
     def longhand_method(longhand):
         args = dict(ident=longhand.ident, gecko_ffi_name=longhand.gecko_ffi_name,
@@ -1240,18 +1241,22 @@ fn static_assert() {
                                corner.y_index) %>
     % endfor
 
     pub fn outline_has_nonzero_width(&self) -> bool {
         self.gecko.mActualOutlineWidth != 0
     }
 </%self:impl_trait>
 
+<%
+    skip_font_longhands = """font-family font-size font-size-adjust font-weight
+                             font-synthesis -x-lang font-language-override"""
+%>
 <%self:impl_trait style_struct_name="Font"
-    skip_longhands="font-family font-size font-size-adjust font-weight font-synthesis -x-lang font-language-override"
+    skip_longhands="${skip_font_longhands}"
     skip_additionals="*">
 
     pub fn set_font_family(&mut self, v: longhands::font_family::computed_value::T) {
         use properties::longhands::font_family::computed_value::FontFamily;
         use gecko_bindings::structs::FontFamilyType;
 
         let list = &mut self.gecko.mFont.fontlist;
         unsafe { Gecko_FontFamilyList_Clear(list); }
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -1091,18 +1091,17 @@
             input.expect_string().map(|cow| {
                 SpecifiedValue::Override(cow.into_owned())
             })
         }
     }
 </%helpers:longhand>
 
 <%helpers:longhand name="-x-lang" products="gecko" animation_type="none" internal="True"
-                   spec="Internal (not web-exposed)"
-                   internal="True">
+                   spec="Internal (not web-exposed)">
     use values::HasViewportPercentage;
     use values::computed::ComputedValueAsSpecified;
     pub use self::computed_value::T as SpecifiedValue;
 
     impl ComputedValueAsSpecified for SpecifiedValue {}
     no_viewport_percentage!(SpecifiedValue);
 
     pub mod computed_value {
@@ -1126,8 +1125,133 @@
         computed_value::T(atom!(""))
     }
 
     pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> {
         debug_assert!(false, "Should be set directly by presentation attributes only.");
         Err(())
     }
 </%helpers:longhand>
+
+// MathML properties
+<%helpers:longhand name="-moz-script-size-multiplier" products="gecko" animation_type="none"
+                   predefined_type="Number" gecko_ffi_name="mScriptSizeMultiplier"
+                   spec="Internal (not web-exposed)"
+                   internal="True" disable_when_testing="True">
+    use values::HasViewportPercentage;
+    use values::computed::ComputedValueAsSpecified;
+    pub use self::computed_value::T as SpecifiedValue;
+
+    impl ComputedValueAsSpecified for SpecifiedValue {}
+    no_viewport_percentage!(SpecifiedValue);
+
+    pub mod computed_value {
+        pub type T = f32;
+    }
+
+    #[inline]
+    pub fn get_initial_value() -> computed_value::T {
+        ::gecko_bindings::structs::NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER
+    }
+
+    pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> {
+        debug_assert!(false, "Should be set directly by presentation attributes only.");
+        Err(())
+    }
+</%helpers:longhand>
+
+<%helpers:longhand name="-moz-script-level" products="gecko" animation_type="none"
+                   predefined_type="Integer" gecko_ffi_name="mScriptLevel"
+                   spec="Internal (not web-exposed)"
+                   internal="True" disable_when_testing="True" need_clone="True">
+    use std::fmt;
+    use style_traits::ToCss;
+    use values::HasViewportPercentage;
+
+    no_viewport_percentage!(SpecifiedValue);
+
+    pub mod computed_value {
+        pub type T = i8;
+    }
+
+    #[inline]
+    pub fn get_initial_value() -> computed_value::T {
+        0
+    }
+
+    #[derive(Copy, Clone, PartialEq, Debug)]
+    pub enum SpecifiedValue {
+        Relative(i32),
+        Absolute(i32),
+        Auto
+    }
+
+    impl ToCss for SpecifiedValue {
+        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+            match *self {
+                SpecifiedValue::Auto => dest.write_str("auto"),
+                SpecifiedValue::Relative(rel) => write!(dest, "{}", rel),
+                // can only be specified by pres attrs; should not
+                // serialize to anything else
+                SpecifiedValue::Absolute(_) => Ok(()),
+            }
+        }
+    }
+
+    impl ToComputedValue for SpecifiedValue {
+        type ComputedValue = computed_value::T;
+
+        fn to_computed_value(&self, cx: &Context) -> i8 {
+            use properties::longhands::_moz_math_display::SpecifiedValue as DisplayValue;
+            use std::{cmp, i8};
+
+            let int = match *self {
+                SpecifiedValue::Auto => {
+                    let parent = cx.inherited_style().get_font().clone__moz_script_level() as i32;
+                    let display = cx.inherited_style().get_font().clone__moz_math_display();
+                    if display == DisplayValue::inline {
+                        parent + 1
+                    } else {
+                        parent
+                    }
+                }
+                SpecifiedValue::Relative(rel) => {
+                    let parent = cx.inherited_style().get_font().clone__moz_script_level();
+                    parent as i32 + rel
+                }
+                SpecifiedValue::Absolute(abs) => abs,
+            };
+            cmp::min(int, i8::MAX as i32) as i8
+        }
+        fn from_computed_value(other: &computed_value::T) -> Self {
+            SpecifiedValue::Absolute(*other as i32)
+        }
+    }
+
+    pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
+        if let Ok(i) = input.try(|i| i.expect_integer()) {
+            return Ok(SpecifiedValue::Relative(i))
+        }
+        input.expect_ident_matching("auto")?;
+        Ok(SpecifiedValue::Auto)
+    }
+</%helpers:longhand>
+
+${helpers.single_keyword("-moz-math-display",
+                         "inline block",
+                         gecko_constant_prefix="NS_MATHML_DISPLAYSTYLE",
+                         gecko_ffi_name="mMathDisplay",
+                         products="gecko",
+                         spec="Internal (not web-exposed)",
+                         animation_type="none",
+                         need_clone="True")}
+
+${helpers.single_keyword("-moz-math-variant",
+                         """normal bold italic bold-italic script bold-script
+                            fraktur double-struck bold-fraktur sans-serif
+                            bold-sans-serif sans-serif-italic sans-serif-bold-italic
+                            monospace initial tailed looped stretched""",
+                         gecko_constant_prefix="NS_MATHML_MATHVARIANT",
+                         gecko_ffi_name="mMathVariant",
+                         products="gecko",
+                         spec="Internal (not web-exposed)",
+                         animation_type="none",
+                         needs_conversion=True)}
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -1287,16 +1287,17 @@ pub extern "C" fn Servo_DeclarationBlock
         TextAlign => longhands::text_align::SpecifiedValue::from_gecko_keyword(value),
         TextEmphasisPosition => longhands::text_emphasis_position::SpecifiedValue::from_gecko_keyword(value),
         Clear => longhands::clear::SpecifiedValue::from_gecko_keyword(value),
         FontSize => {
             // We rely on Gecko passing in font-size values (0...7) here.
             longhands::font_size::SpecifiedValue::from_html_size(value as u8)
         },
         ListStyleType => longhands::list_style_type::SpecifiedValue::from_gecko_keyword(value),
+        MozMathVariant => longhands::_moz_math_variant::SpecifiedValue::from_gecko_keyword(value),
         WhiteSpace => longhands::white_space::SpecifiedValue::from_gecko_keyword(value),
         CaptionSide => longhands::caption_side::SpecifiedValue::from_gecko_keyword(value),
         BorderTopStyle => BorderStyle::from_gecko_keyword(value),
         BorderRightStyle => BorderStyle::from_gecko_keyword(value),
         BorderBottomStyle => BorderStyle::from_gecko_keyword(value),
         BorderLeftStyle => BorderStyle::from_gecko_keyword(value),
     };
     write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
@@ -1304,21 +1305,24 @@ pub extern "C" fn Servo_DeclarationBlock
     })
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_DeclarationBlock_SetIntValue(declarations: RawServoDeclarationBlockBorrowed,
                                                      property: nsCSSPropertyID,
                                                      value: i32) {
     use style::properties::{PropertyDeclaration, LonghandId};
+    use style::properties::longhands::_moz_script_level::SpecifiedValue as MozScriptLevel;
     use style::properties::longhands::_x_span::computed_value::T as Span;
 
     let long = get_longhand_from_id!(property);
     let prop = match_wrap_declared! { long,
         XSpan => Span(value),
+        // Gecko uses Integer values to signal that it is relative
+        MozScriptLevel => MozScriptLevel::Relative(value),
     };
     write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
         decls.push(prop, Importance::Normal);
     })
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_DeclarationBlock_SetPixelValue(declarations:
@@ -1356,16 +1360,36 @@ pub extern "C" fn Servo_DeclarationBlock
         ),
     };
     write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
         decls.push(prop, Importance::Normal);
     })
 }
 
 #[no_mangle]
+pub extern "C" fn Servo_DeclarationBlock_SetNumberValue(declarations:
+                                                       RawServoDeclarationBlockBorrowed,
+                                                       property: nsCSSPropertyID,
+                                                       value: f32) {
+    use style::properties::{PropertyDeclaration, LonghandId};
+    use style::properties::longhands::_moz_script_level::SpecifiedValue as MozScriptLevel;
+
+    let long = get_longhand_from_id!(property);
+
+    let prop = match_wrap_declared! { long,
+        MozScriptSizeMultiplier => value,
+        // Gecko uses Number values to signal that it is absolute
+        MozScriptLevel => MozScriptLevel::Absolute(value as i32),
+    };
+    write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
+        decls.push(prop, Importance::Normal);
+    })
+}
+
+#[no_mangle]
 pub extern "C" fn Servo_DeclarationBlock_SetPercentValue(declarations:
                                                          RawServoDeclarationBlockBorrowed,
                                                          property: nsCSSPropertyID,
                                                          value: f32) {
     use style::properties::{PropertyDeclaration, LonghandId};
     use style::values::specified::length::Percentage;
 
     let long = get_longhand_from_id!(property);