Bug 1434130 part 4 - Use unified lists to impl several bitflag font-variant properties. r?emilio draft
authorXidorn Quan <me@upsuper.org>
Thu, 26 Apr 2018 15:13:03 +1000
changeset 788770 f2c10917b105912bbe5fa06a986bbce08ebceac4
parent 788769 a4cd0a8db99c2a46af183d44807dffb2a1a88e3f
child 788771 29990f9171efe771ea4d09fd129d37a4a1ec3870
push id108088
push userxquan@mozilla.com
push dateFri, 27 Apr 2018 00:40:56 +0000
reviewersemilio
bugs1434130
milestone61.0a1
Bug 1434130 part 4 - Use unified lists to impl several bitflag font-variant properties. r?emilio This also changes their ToCss impl to use SequenceWriter instead of checking has_value manually. SpecifiedValueInfo for those types are also implemented in this patch. MozReview-Commit-ID: 23h2VWS417H
servo/components/style/values/specified/font.rs
--- a/servo/components/style/values/specified/font.rs
+++ b/servo/components/style/values/specified/font.rs
@@ -10,17 +10,19 @@ use byteorder::{BigEndian, ByteOrder};
 use cssparser::{Parser, Token};
 #[cfg(feature = "gecko")]
 use gecko_bindings::bindings;
 #[cfg(feature = "gecko")]
 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
 use parser::{Parse, ParserContext};
 use properties::longhands::system_font::SystemFont;
 use std::fmt::{self, Write};
-use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, StyleParseErrorKind, ToCss};
+use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
+use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
+use style_traits::values::SequenceWriter;
 use values::CustomIdent;
 use values::computed::{Angle as ComputedAngle, Percentage as ComputedPercentage};
 use values::computed::{font as computed, Context, Length, NonNegativeLength, ToComputedValue};
 use values::computed::font::{FamilyName, FontFamilyList, FontStyleAngle, SingleFontFamily};
 use values::generics::NonNegative;
 use values::generics::font::{self as generics, FeatureTagValue, FontSettings, FontTag};
 use values::generics::font::{KeywordInfo as GenericKeywordInfo, KeywordSize, VariationValue};
 use values::specified::{AllowQuirks, Angle, Integer, LengthOrPercentage, NoCalcLength, Number, Percentage};
@@ -1270,130 +1272,112 @@ impl Parse for FontVariantAlternates {
             return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
         }
         Ok(FontVariantAlternates::Value(VariantAlternatesList(
             alternates.into_boxed_slice(),
         )))
     }
 }
 
-bitflags! {
-    #[derive(MallocSizeOf)]
-    /// Vairants for east asian variant
-    pub struct VariantEastAsian: u16 {
-        /// None of the features
-        const NORMAL = 0;
-        /// Enables rendering of JIS78 forms (OpenType feature: jp78)
-        const JIS78 = 0x01;
-        /// Enables rendering of JIS83 forms (OpenType feature: jp83).
-        const JIS83 = 0x02;
-        /// Enables rendering of JIS90 forms (OpenType feature: jp90).
-        const JIS90 = 0x04;
-        /// Enables rendering of JIS2004 forms (OpenType feature: jp04).
-        const JIS04 = 0x08;
-        /// Enables rendering of simplified forms (OpenType feature: smpl).
-        const SIMPLIFIED = 0x10;
-        /// Enables rendering of traditional forms (OpenType feature: trad).
-        const TRADITIONAL = 0x20;
-        /// Enables rendering of full-width variants (OpenType feature: fwid).
-        const FULL_WIDTH = 0x40;
-        /// Enables rendering of proportionally-spaced variants (OpenType feature: pwid).
-        const PROPORTIONAL_WIDTH = 0x80;
-        /// Enables display of ruby variant glyphs (OpenType feature: ruby).
-        const RUBY = 0x100;
+macro_rules! impl_variant_east_asian {
+    {
+        $(
+            $(#[$($meta:tt)+])*
+            $ident:ident / $css:expr => $gecko:ident = $value:expr,
+        )+
+    } => {
+        bitflags! {
+            #[derive(MallocSizeOf)]
+            /// Vairants for east asian variant
+            pub struct VariantEastAsian: u16 {
+                /// None of the features
+                const NORMAL = 0;
+                $(
+                    $(#[$($meta)+])*
+                    const $ident = $value;
+                )+
+            }
+        }
+
+        impl ToCss for VariantEastAsian {
+            fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
+            where
+                W: Write,
+            {
+                if self.is_empty() {
+                    return dest.write_str("normal");
+                }
+
+                let mut writer = SequenceWriter::new(dest, " ");
+                $(
+                    if self.intersects(VariantEastAsian::$ident) {
+                        writer.raw_item($css)?;
+                    }
+                )+
+                Ok(())
+            }
+        }
+
+        /// Asserts that all variant-east-asian matches its NS_FONT_VARIANT_EAST_ASIAN_* value.
+        #[cfg(feature = "gecko")]
+        #[inline]
+        pub fn assert_variant_east_asian_matches() {
+            use gecko_bindings::structs;
+            $(
+                debug_assert_eq!(structs::$gecko as u16, VariantEastAsian::$ident.bits());
+            )+
+        }
+
+        impl SpecifiedValueInfo for VariantEastAsian {
+            fn collect_completion_keywords(f: KeywordsCollectFn) {
+                f(&["normal", $($css,)+]);
+            }
+        }
     }
 }
 
+impl_variant_east_asian! {
+    /// Enables rendering of JIS78 forms (OpenType feature: jp78)
+    JIS78 / "jis78" => NS_FONT_VARIANT_EAST_ASIAN_JIS78 = 0x01,
+    /// Enables rendering of JIS83 forms (OpenType feature: jp83).
+    JIS83 / "jis83" => NS_FONT_VARIANT_EAST_ASIAN_JIS83 = 0x02,
+    /// Enables rendering of JIS90 forms (OpenType feature: jp90).
+    JIS90 / "jis90" => NS_FONT_VARIANT_EAST_ASIAN_JIS90 = 0x04,
+    /// Enables rendering of JIS2004 forms (OpenType feature: jp04).
+    JIS04 / "jis04" => NS_FONT_VARIANT_EAST_ASIAN_JIS04 = 0x08,
+    /// Enables rendering of simplified forms (OpenType feature: smpl).
+    SIMPLIFIED / "simplified" => NS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED = 0x10,
+    /// Enables rendering of traditional forms (OpenType feature: trad).
+    TRADITIONAL / "traditional" => NS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL = 0x20,
+    /// Enables rendering of full-width variants (OpenType feature: fwid).
+    FULL_WIDTH / "full-width" => NS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH = 0x40,
+    /// Enables rendering of proportionally-spaced variants (OpenType feature: pwid).
+    PROPORTIONAL_WIDTH / "proportional-width" => NS_FONT_VARIANT_EAST_ASIAN_PROP_WIDTH = 0x80,
+    /// Enables display of ruby variant glyphs (OpenType feature: ruby).
+    RUBY / "ruby" => NS_FONT_VARIANT_EAST_ASIAN_RUBY = 0x100,
+}
+
 #[cfg(feature = "gecko")]
 impl VariantEastAsian {
     /// Obtain a specified value from a Gecko keyword value
     ///
     /// Intended for use with presentation attributes, not style structs
     pub fn from_gecko_keyword(kw: u16) -> Self {
         Self::from_bits_truncate(kw)
     }
 
     /// Transform into gecko keyword
     pub fn to_gecko_keyword(self) -> u16 {
         self.bits()
     }
 }
 
-impl ToCss for VariantEastAsian {
-    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
-    where
-        W: Write,
-    {
-        if self.is_empty() {
-            return dest.write_str("normal");
-        }
-
-        let mut has_any = false;
-
-        macro_rules! write_value {
-            ($ident:path => $str:expr) => {
-                if self.intersects($ident) {
-                    if has_any {
-                        dest.write_str(" ")?;
-                    }
-                    has_any = true;
-                    dest.write_str($str)?;
-                }
-            };
-        }
-
-        write_value!(VariantEastAsian::JIS78 => "jis78");
-        write_value!(VariantEastAsian::JIS83 => "jis83");
-        write_value!(VariantEastAsian::JIS90 => "jis90");
-        write_value!(VariantEastAsian::JIS04 => "jis04");
-        write_value!(VariantEastAsian::SIMPLIFIED => "simplified");
-        write_value!(VariantEastAsian::TRADITIONAL => "traditional");
-        write_value!(VariantEastAsian::FULL_WIDTH => "full-width");
-        write_value!(VariantEastAsian::PROPORTIONAL_WIDTH => "proportional-width");
-        write_value!(VariantEastAsian::RUBY => "ruby");
-
-        debug_assert!(has_any);
-        Ok(())
-    }
-}
-
 #[cfg(feature = "gecko")]
 impl_gecko_keyword_conversions!(VariantEastAsian, u16);
 
-impl SpecifiedValueInfo for VariantEastAsian {}
-
-/// Asserts that all variant-east-asian matches its NS_FONT_VARIANT_EAST_ASIAN_* value.
-#[cfg(feature = "gecko")]
-#[inline]
-pub fn assert_variant_east_asian_matches() {
-    use gecko_bindings::structs;
-
-    macro_rules! check_variant_east_asian {
-        ( $( $a:ident => $b:path),*, ) => {
-            if cfg!(debug_assertions) {
-                $(
-                    assert_eq!(structs::$a as u16, $b.bits());
-                )*
-            }
-        }
-    }
-
-    check_variant_east_asian! {
-        NS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH => VariantEastAsian::FULL_WIDTH,
-        NS_FONT_VARIANT_EAST_ASIAN_JIS04 => VariantEastAsian::JIS04,
-        NS_FONT_VARIANT_EAST_ASIAN_JIS78 => VariantEastAsian::JIS78,
-        NS_FONT_VARIANT_EAST_ASIAN_JIS83 => VariantEastAsian::JIS83,
-        NS_FONT_VARIANT_EAST_ASIAN_JIS90 => VariantEastAsian::JIS90,
-        NS_FONT_VARIANT_EAST_ASIAN_PROP_WIDTH => VariantEastAsian::PROPORTIONAL_WIDTH,
-        NS_FONT_VARIANT_EAST_ASIAN_RUBY => VariantEastAsian::RUBY,
-        NS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED => VariantEastAsian::SIMPLIFIED,
-        NS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL => VariantEastAsian::TRADITIONAL,
-    }
-}
-
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
 #[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
 /// Allows control of glyph substitution and sizing in East Asian text.
 pub enum FontVariantEastAsian {
     /// Value variant with `variant-east-asian`
     Value(VariantEastAsian),
     /// System font variant
     #[css(skip)]
@@ -1495,133 +1479,116 @@ impl Parse for FontVariantEastAsian {
         if !result.is_empty() {
             Ok(FontVariantEastAsian::Value(result))
         } else {
             Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
         }
     }
 }
 
-bitflags! {
-    #[derive(MallocSizeOf)]
-    /// Variants of ligatures
-    pub struct VariantLigatures: u16 {
-        /// Specifies that common default features are enabled
-        const NORMAL = 0;
-        /// Specifies that all types of ligatures and contextual forms
-        /// covered by this property are explicitly disabled
-        const NONE = 0x01;
-        /// Enables display of common ligatures
-        const COMMON_LIGATURES = 0x02;
-        /// Disables display of common ligatures
-        const NO_COMMON_LIGATURES = 0x04;
-        /// Enables display of discretionary ligatures
-        const DISCRETIONARY_LIGATURES = 0x08;
-        /// Disables display of discretionary ligatures
-        const NO_DISCRETIONARY_LIGATURES = 0x10;
-        /// Enables display of historical ligatures
-        const HISTORICAL_LIGATURES = 0x20;
-        /// Disables display of historical ligatures
-        const NO_HISTORICAL_LIGATURES = 0x40;
-        /// Enables display of contextual alternates
-        const CONTEXTUAL = 0x80;
-        /// Disables display of contextual alternates
-        const NO_CONTEXTUAL = 0x100;
+macro_rules! impl_variant_ligatures {
+    {
+        $(
+            $(#[$($meta:tt)+])*
+            $ident:ident / $css:expr => $gecko:ident = $value:expr,
+        )+
+    } => {
+        bitflags! {
+            #[derive(MallocSizeOf)]
+            /// Variants of ligatures
+            pub struct VariantLigatures: u16 {
+                /// Specifies that common default features are enabled
+                const NORMAL = 0;
+                $(
+                    $(#[$($meta)+])*
+                    const $ident = $value;
+                )+
+            }
+        }
+
+        impl ToCss for VariantLigatures {
+            fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
+            where
+                W: Write,
+            {
+                if self.is_empty() {
+                    return dest.write_str("normal");
+                }
+                if self.contains(VariantLigatures::NONE) {
+                    return dest.write_str("none");
+                }
+
+                let mut writer = SequenceWriter::new(dest, " ");
+                $(
+                    if self.intersects(VariantLigatures::$ident) {
+                        writer.raw_item($css)?;
+                    }
+                )+
+                Ok(())
+            }
+        }
+
+        /// Asserts that all variant-east-asian matches its NS_FONT_VARIANT_EAST_ASIAN_* value.
+        #[cfg(feature = "gecko")]
+        #[inline]
+        pub fn assert_variant_ligatures_matches() {
+            use gecko_bindings::structs;
+            $(
+                debug_assert_eq!(structs::$gecko as u16, VariantLigatures::$ident.bits());
+            )+
+        }
+
+        impl SpecifiedValueInfo for VariantLigatures {
+            fn collect_completion_keywords(f: KeywordsCollectFn) {
+                f(&["normal", $($css,)+]);
+            }
+        }
     }
 }
 
+impl_variant_ligatures! {
+    /// Specifies that all types of ligatures and contextual forms
+    /// covered by this property are explicitly disabled
+    NONE / "none" => NS_FONT_VARIANT_LIGATURES_NONE = 0x01,
+    /// Enables display of common ligatures
+    COMMON_LIGATURES / "common-ligatures" => NS_FONT_VARIANT_LIGATURES_COMMON = 0x02,
+    /// Disables display of common ligatures
+    NO_COMMON_LIGATURES / "no-common-ligatures" => NS_FONT_VARIANT_LIGATURES_NO_COMMON = 0x04,
+    /// Enables display of discretionary ligatures
+    DISCRETIONARY_LIGATURES / "discretionary-ligatures" => NS_FONT_VARIANT_LIGATURES_DISCRETIONARY = 0x08,
+    /// Disables display of discretionary ligatures
+    NO_DISCRETIONARY_LIGATURES / "no-discretionary-ligatures" => NS_FONT_VARIANT_LIGATURES_NO_DISCRETIONARY = 0x10,
+    /// Enables display of historical ligatures
+    HISTORICAL_LIGATURES / "historical-ligatures" => NS_FONT_VARIANT_LIGATURES_HISTORICAL = 0x20,
+    /// Disables display of historical ligatures
+    NO_HISTORICAL_LIGATURES / "no-historical-ligatures" => NS_FONT_VARIANT_LIGATURES_NO_HISTORICAL = 0x40,
+    /// Enables display of contextual alternates
+    CONTEXTUAL / "contextual" => NS_FONT_VARIANT_LIGATURES_CONTEXTUAL = 0x80,
+    /// Disables display of contextual alternates
+    NO_CONTEXTUAL / "no-contextual" => NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL = 0x100,
+}
+
 #[cfg(feature = "gecko")]
 impl VariantLigatures {
     /// Obtain a specified value from a Gecko keyword value
     ///
     /// Intended for use with presentation attributes, not style structs
     pub fn from_gecko_keyword(kw: u16) -> Self {
         Self::from_bits_truncate(kw)
     }
 
     /// Transform into gecko keyword
     pub fn to_gecko_keyword(self) -> u16 {
         self.bits()
     }
 }
 
-impl ToCss for VariantLigatures {
-    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
-    where
-        W: Write,
-    {
-        if self.is_empty() {
-            return dest.write_str("normal");
-        }
-        if self.contains(VariantLigatures::NONE) {
-            return dest.write_str("none");
-        }
-
-        let mut has_any = false;
-
-        macro_rules! write_value {
-            ($ident:path => $str:expr) => {
-                if self.intersects($ident) {
-                    if has_any {
-                        dest.write_str(" ")?;
-                    }
-                    has_any = true;
-                    dest.write_str($str)?;
-                }
-            };
-        }
-
-        write_value!(VariantLigatures::COMMON_LIGATURES => "common-ligatures");
-        write_value!(VariantLigatures::NO_COMMON_LIGATURES => "no-common-ligatures");
-        write_value!(VariantLigatures::DISCRETIONARY_LIGATURES => "discretionary-ligatures");
-        write_value!(VariantLigatures::NO_DISCRETIONARY_LIGATURES => "no-discretionary-ligatures");
-        write_value!(VariantLigatures::HISTORICAL_LIGATURES => "historical-ligatures");
-        write_value!(VariantLigatures::NO_HISTORICAL_LIGATURES => "no-historical-ligatures");
-        write_value!(VariantLigatures::CONTEXTUAL => "contextual");
-        write_value!(VariantLigatures::NO_CONTEXTUAL => "no-contextual");
-
-        debug_assert!(has_any);
-        Ok(())
-    }
-}
-
-impl SpecifiedValueInfo for VariantLigatures {}
-
 #[cfg(feature = "gecko")]
 impl_gecko_keyword_conversions!(VariantLigatures, u16);
 
-/// Asserts that all variant-east-asian matches its NS_FONT_VARIANT_EAST_ASIAN_* value.
-#[cfg(feature = "gecko")]
-#[inline]
-pub fn assert_variant_ligatures_matches() {
-    use gecko_bindings::structs;
-
-    macro_rules! check_variant_ligatures {
-        ( $( $a:ident => $b:path),*, ) => {
-            if cfg!(debug_assertions) {
-                $(
-                    assert_eq!(structs::$a as u16, $b.bits());
-                )*
-            }
-        }
-    }
-
-    check_variant_ligatures! {
-        NS_FONT_VARIANT_LIGATURES_NONE => VariantLigatures::NONE,
-        NS_FONT_VARIANT_LIGATURES_COMMON => VariantLigatures::COMMON_LIGATURES,
-        NS_FONT_VARIANT_LIGATURES_NO_COMMON => VariantLigatures::NO_COMMON_LIGATURES,
-        NS_FONT_VARIANT_LIGATURES_DISCRETIONARY => VariantLigatures::DISCRETIONARY_LIGATURES,
-        NS_FONT_VARIANT_LIGATURES_NO_DISCRETIONARY => VariantLigatures::NO_DISCRETIONARY_LIGATURES,
-        NS_FONT_VARIANT_LIGATURES_HISTORICAL => VariantLigatures::HISTORICAL_LIGATURES,
-        NS_FONT_VARIANT_LIGATURES_NO_HISTORICAL => VariantLigatures::NO_HISTORICAL_LIGATURES,
-        NS_FONT_VARIANT_LIGATURES_CONTEXTUAL => VariantLigatures::CONTEXTUAL,
-        NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL => VariantLigatures::NO_CONTEXTUAL,
-    }
-}
-
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
 #[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
 /// Ligatures and contextual forms are ways of combining glyphs
 /// to produce more harmonized forms
 pub enum FontVariantLigatures {
     /// Value variant with `variant-ligatures`
     Value(VariantLigatures),
     /// System font variant
@@ -1734,126 +1701,110 @@ impl Parse for FontVariantLigatures {
         if !result.is_empty() {
             Ok(FontVariantLigatures::Value(result))
         } else {
             Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
         }
     }
 }
 
-bitflags! {
-    #[derive(MallocSizeOf)]
-    /// Vairants of numeric values
-    pub struct VariantNumeric: u8 {
-        /// None of other variants are enabled.
-        const NORMAL = 0;
-        /// Enables display of lining numerals.
-        const LINING_NUMS = 0x01;
-        /// Enables display of old-style numerals.
-        const OLDSTYLE_NUMS = 0x02;
-        /// Enables display of proportional numerals.
-        const PROPORTIONAL_NUMS = 0x04;
-        /// Enables display of tabular numerals.
-        const TABULAR_NUMS = 0x08;
-        /// Enables display of lining diagonal fractions.
-        const DIAGONAL_FRACTIONS = 0x10;
-        /// Enables display of lining stacked fractions.
-        const STACKED_FRACTIONS = 0x20;
-        /// Enables display of letter forms used with ordinal numbers.
-        const ORDINAL = 0x80;
-        /// Enables display of slashed zeros.
-        const SLASHED_ZERO = 0x40;
+macro_rules! impl_variant_numeric {
+    {
+        $(
+            $(#[$($meta:tt)+])*
+            $ident:ident / $css:expr => $gecko:ident = $value:expr,
+        )+
+    } => {
+        bitflags! {
+            #[derive(MallocSizeOf)]
+            /// Vairants of numeric values
+            pub struct VariantNumeric: u8 {
+                /// None of other variants are enabled.
+                const NORMAL = 0;
+                $(
+                    $(#[$($meta)+])*
+                    const $ident = $value;
+                )+
+            }
+        }
+
+        impl ToCss for VariantNumeric {
+            fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
+            where
+                W: Write,
+            {
+                if self.is_empty() {
+                    return dest.write_str("normal");
+                }
+
+                let mut writer = SequenceWriter::new(dest, " ");
+                $(
+                    if self.intersects(VariantNumeric::$ident) {
+                        writer.raw_item($css)?;
+                    }
+                )+
+                Ok(())
+            }
+        }
+
+        /// Asserts that all variant-east-asian matches its NS_FONT_VARIANT_EAST_ASIAN_* value.
+        #[cfg(feature = "gecko")]
+        #[inline]
+        pub fn assert_variant_numeric_matches() {
+            use gecko_bindings::structs;
+            $(
+                debug_assert_eq!(structs::$gecko as u8, VariantNumeric::$ident.bits());
+            )+
+        }
+
+        impl SpecifiedValueInfo for VariantNumeric {
+            fn collect_completion_keywords(f: KeywordsCollectFn) {
+                f(&["normal", $($css,)+]);
+            }
+        }
     }
 }
 
+impl_variant_numeric! {
+    /// Enables display of lining numerals.
+    LINING_NUMS / "lining-nums" => NS_FONT_VARIANT_NUMERIC_LINING = 0x01,
+    /// Enables display of old-style numerals.
+    OLDSTYLE_NUMS / "oldstyle-nums" => NS_FONT_VARIANT_NUMERIC_OLDSTYLE = 0x02,
+    /// Enables display of proportional numerals.
+    PROPORTIONAL_NUMS / "proportional-nums" => NS_FONT_VARIANT_NUMERIC_PROPORTIONAL = 0x04,
+    /// Enables display of tabular numerals.
+    TABULAR_NUMS / "tabular-nums" => NS_FONT_VARIANT_NUMERIC_TABULAR = 0x08,
+    /// Enables display of lining diagonal fractions.
+    DIAGONAL_FRACTIONS / "diagonal-fractions" => NS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS = 0x10,
+    /// Enables display of lining stacked fractions.
+    STACKED_FRACTIONS / "stacked-fractions" => NS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS = 0x20,
+    /// Enables display of letter forms used with ordinal numbers.
+    ORDINAL / "ordinal" => NS_FONT_VARIANT_NUMERIC_ORDINAL = 0x80,
+    /// Enables display of slashed zeros.
+    SLASHED_ZERO / "slashed-zero" => NS_FONT_VARIANT_NUMERIC_SLASHZERO = 0x40,
+}
+
 #[cfg(feature = "gecko")]
 impl VariantNumeric {
     /// Obtain a specified value from a Gecko keyword value
     ///
     /// Intended for use with presentation attributes, not style structs
     pub fn from_gecko_keyword(kw: u8) -> Self {
         Self::from_bits_truncate(kw)
     }
 
     /// Transform into gecko keyword
     pub fn to_gecko_keyword(self) -> u8 {
         self.bits()
     }
 }
 
-impl ToCss for VariantNumeric {
-    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
-    where
-        W: Write,
-    {
-        if self.is_empty() {
-            return dest.write_str("normal");
-        }
-
-        let mut has_any = false;
-
-        macro_rules! write_value {
-            ($ident:path => $str:expr) => {
-                if self.intersects($ident) {
-                    if has_any {
-                        dest.write_str(" ")?;
-                    }
-                    has_any = true;
-                    dest.write_str($str)?;
-                }
-            };
-        }
-
-        write_value!(VariantNumeric::LINING_NUMS => "lining-nums");
-        write_value!(VariantNumeric::OLDSTYLE_NUMS => "oldstyle-nums");
-        write_value!(VariantNumeric::PROPORTIONAL_NUMS => "proportional-nums");
-        write_value!(VariantNumeric::TABULAR_NUMS => "tabular-nums");
-        write_value!(VariantNumeric::DIAGONAL_FRACTIONS => "diagonal-fractions");
-        write_value!(VariantNumeric::STACKED_FRACTIONS => "stacked-fractions");
-        write_value!(VariantNumeric::SLASHED_ZERO => "slashed-zero");
-        write_value!(VariantNumeric::ORDINAL => "ordinal");
-
-        debug_assert!(has_any);
-        Ok(())
-    }
-}
-
-impl SpecifiedValueInfo for VariantNumeric {}
-
 #[cfg(feature = "gecko")]
 impl_gecko_keyword_conversions!(VariantNumeric, u8);
 
-/// Asserts that all variant-east-asian matches its NS_FONT_VARIANT_EAST_ASIAN_* value.
-#[cfg(feature = "gecko")]
-#[inline]
-pub fn assert_variant_numeric_matches() {
-    use gecko_bindings::structs;
-
-    macro_rules! check_variant_numeric {
-        ( $( $a:ident => $b:path),*, ) => {
-            if cfg!(debug_assertions) {
-                $(
-                    assert_eq!(structs::$a as u8, $b.bits());
-                )*
-            }
-        }
-    }
-
-    check_variant_numeric! {
-        NS_FONT_VARIANT_NUMERIC_LINING => VariantNumeric::LINING_NUMS,
-        NS_FONT_VARIANT_NUMERIC_OLDSTYLE => VariantNumeric::OLDSTYLE_NUMS,
-        NS_FONT_VARIANT_NUMERIC_PROPORTIONAL => VariantNumeric::PROPORTIONAL_NUMS,
-        NS_FONT_VARIANT_NUMERIC_TABULAR => VariantNumeric::TABULAR_NUMS,
-        NS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS => VariantNumeric::DIAGONAL_FRACTIONS,
-        NS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS => VariantNumeric::STACKED_FRACTIONS,
-        NS_FONT_VARIANT_NUMERIC_SLASHZERO => VariantNumeric::SLASHED_ZERO,
-        NS_FONT_VARIANT_NUMERIC_ORDINAL => VariantNumeric::ORDINAL,
-    }
-}
-
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
 #[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
 /// Specifies control over numerical forms.
 pub enum FontVariantNumeric {
     /// Value variant with `variant-numeric`
     Value(VariantNumeric),
     /// System font
     #[css(skip)]