Serialize font longhands to -moz-use-system-font when using system font like what Gecko does. r?Manishearth draft
authorXidorn Quan <me@upsuper.org>
Tue, 11 Jul 2017 13:52:58 +1000
changeset 606574 110bd69b4773a21d32fb571dd1e74378bb7e6196
parent 606573 d7987288cd1327fd330939eb7f2f4b85717a9ca9
child 606575 cf7a27bb1d4c501cdf4fb7d7d8e245a252f66bf3
push id67729
push userxquan@mozilla.com
push dateTue, 11 Jul 2017 03:54:04 +0000
reviewersManishearth
milestone56.0a1
Serialize font longhands to -moz-use-system-font when using system font like what Gecko does. r?Manishearth MozReview-Commit-ID: 3EONeP5U9Xt
servo/components/style/properties/helpers.mako.rs
servo/components/style/properties/longhand/font.mako.rs
--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -490,18 +490,16 @@
             'gecko_constant_prefix', 'gecko_enum_prefix',
             'extra_gecko_values', 'extra_servo_values',
             'custom_consts', 'gecko_inexhaustive',
         ]}
         keyword = keyword=Keyword(name, values, **keyword_kwargs)
     %>
     <%call expr="longhand(name, keyword=Keyword(name, values, **keyword_kwargs), **kwargs)">
         use properties::longhands::system_font::SystemFont;
-        use std::fmt;
-        use style_traits::ToCss;
         no_viewport_percentage!(SpecifiedValue);
 
         pub mod computed_value {
             use cssparser::Parser;
             use parser::{Parse, ParserContext};
 
             use style_traits::{ToCss, ParseError};
             define_css_keyword_enum! { T:
@@ -514,31 +512,22 @@
                 fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
                     T::parse(input)
                 }
             }
 
             ${gecko_keyword_conversion(keyword, keyword.values_for(product), type="T", cast_to="i32")}
         }
 
-        #[derive(Debug, Clone, PartialEq, Eq, Copy)]
+        #[derive(Debug, Clone, PartialEq, Eq, Copy, ToCss)]
         pub enum SpecifiedValue {
             Keyword(computed_value::T),
             System(SystemFont),
         }
 
-        impl ToCss for SpecifiedValue {
-            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-                match *self {
-                    SpecifiedValue::Keyword(k) => k.to_css(dest),
-                    SpecifiedValue::System(_) => Ok(())
-                }
-            }
-        }
-
         pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<SpecifiedValue, ParseError<'i>> {
             Ok(SpecifiedValue::Keyword(computed_value::T::parse(input)?))
         }
 
         impl ToComputedValue for SpecifiedValue {
             type ComputedValue = computed_value::T;
             fn to_computed_value(&self, _cx: &Context) -> Self::ComputedValue {
                 match *self {
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -30,26 +30,16 @@ macro_rules! impl_gecko_keyword_conversi
             }
         }
     };
 }
 
 // Define ToComputedValue, ToCss, and other boilerplate for a specified value
 // which is of the form `enum SpecifiedValue {Value(..), System(SystemFont)}`
 <%def name="simple_system_boilerplate(name)">
-    impl ToCss for SpecifiedValue {
-        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-            match *self {
-                SpecifiedValue::Value(ref v) => v.to_css(dest),
-                SpecifiedValue::System(_) => Ok(())
-            }
-        }
-    }
-
-
     impl SpecifiedValue {
         pub fn system_font(f: SystemFont) -> Self {
             SpecifiedValue::System(f)
         }
         pub fn get_system(&self) -> Option<SystemFont> {
             if let SpecifiedValue::System(s) = *self {
                 Some(s)
             } else {
@@ -361,17 +351,17 @@ macro_rules! impl_gecko_keyword_conversi
                     let mut iter = v.iter();
                     iter.next().unwrap().to_css(dest)?;
                     for family in iter {
                         dest.write_str(", ")?;
                         family.to_css(dest)?;
                     }
                     Ok(())
                 }
-                _ => Ok(())
+                SpecifiedValue::System(sys) => sys.to_css(dest),
             }
         }
     }
 
     /// `FamilyName::parse` is based on `FontFamily::parse` and not the other way around
     /// because we want the former to exclude generic family keywords.
     impl Parse for FamilyName {
         fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
@@ -429,17 +419,17 @@ macro_rules! impl_gecko_keyword_conversi
     impl ToCss for SpecifiedValue {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             match *self {
                 SpecifiedValue::Normal => dest.write_str("normal"),
                 SpecifiedValue::Bold => dest.write_str("bold"),
                 SpecifiedValue::Bolder => dest.write_str("bolder"),
                 SpecifiedValue::Lighter => dest.write_str("lighter"),
                 SpecifiedValue::Weight(weight) => weight.to_css(dest),
-                SpecifiedValue::System(_) => Ok(())
+                SpecifiedValue::System(sys) => sys.to_css(dest),
             }
         }
     }
 
     /// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
     pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue, ParseError<'i>> {
         let result = input.try(|input| {
@@ -597,17 +587,17 @@ macro_rules! impl_gecko_keyword_conversi
 
     impl ToCss for SpecifiedValue {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             match *self {
                 SpecifiedValue::Length(ref lop) => lop.to_css(dest),
                 SpecifiedValue::Keyword(kw, _) => kw.to_css(dest),
                 SpecifiedValue::Smaller => dest.write_str("smaller"),
                 SpecifiedValue::Larger => dest.write_str("larger"),
-                SpecifiedValue::System(_) => Ok(()),
+                SpecifiedValue::System(sys) => sys.to_css(dest),
             }
         }
     }
 
     impl HasViewportPercentage for SpecifiedValue {
         fn has_viewport_percentage(&self) -> bool {
             match *self {
                 SpecifiedValue::Length(ref lop) => lop.has_viewport_percentage(),
@@ -1028,17 +1018,17 @@ macro_rules! impl_gecko_keyword_conversi
 
     impl ToCss for SpecifiedValue {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result
             where W: fmt::Write,
         {
             match *self {
                 SpecifiedValue::None => dest.write_str("none"),
                 SpecifiedValue::Number(number) => number.to_css(dest),
-                SpecifiedValue::System(_) => Ok(()),
+                SpecifiedValue::System(sys) => sys.to_css(dest),
             }
         }
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
@@ -1267,17 +1257,17 @@ macro_rules! impl_gecko_keyword_conversi
         Annotation(CustomIdent),
         HistoricalForms,
     }
 
     #[derive(Debug, Clone, PartialEq)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     pub struct VariantAlternatesList(pub Box<[VariantAlternates]>);
 
-    #[derive(Debug, Clone, PartialEq)]
+    #[derive(Debug, Clone, PartialEq, ToCss)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     pub enum SpecifiedValue {
         Value(VariantAlternatesList),
         System(SystemFont)
     }
 
     <%self:simple_system_boilerplate name="font_variant_alternates"></%self:simple_system_boilerplate>
 
@@ -1476,17 +1466,17 @@ macro_rules! exclusive_value {
             const TRADITIONAL = 0x20,
             const FULL_WIDTH = 0x40,
             const PROPORTIONAL_WIDTH = 0x80,
             const RUBY = 0x100,
         }
     }
 
 
-    #[derive(Debug, Clone, PartialEq)]
+    #[derive(Debug, Clone, PartialEq, ToCss)]
     pub enum SpecifiedValue {
         Value(VariantEastAsian),
         System(SystemFont)
     }
 
     <%self:simple_system_boilerplate name="font_variant_east_asian"></%self:simple_system_boilerplate>
 
     //                                 servo_bit: gecko_bit
@@ -1621,17 +1611,17 @@ macro_rules! exclusive_value {
             const HISTORICAL_LIGATURES = 0x20,
             const NO_HISTORICAL_LIGATURES = 0x40,
             const CONTEXTUAL = 0x80,
             const NO_CONTEXTUAL = 0x100,
         }
     }
 
 
-    #[derive(Debug, Clone, PartialEq)]
+    #[derive(Debug, Clone, PartialEq, ToCss)]
     pub enum SpecifiedValue {
         Value(VariantLigatures),
         System(SystemFont)
     }
 
     <%self:simple_system_boilerplate name="font_variant_ligatures"></%self:simple_system_boilerplate>
 
     //                                 servo_bit: gecko_bit
@@ -1780,17 +1770,17 @@ macro_rules! exclusive_value {
             const STACKED_FRACTIONS = 0x20,
             const SLASHED_ZERO = 0x40,
             const ORDINAL = 0x80,
         }
     }
 
 
 
-    #[derive(Debug, Clone, PartialEq)]
+    #[derive(Debug, Clone, PartialEq, ToCss)]
     pub enum SpecifiedValue {
         Value(VariantNumeric),
         System(SystemFont)
     }
 
     <%self:simple_system_boilerplate name="font_variant_numeric"></%self:simple_system_boilerplate>
 
 
@@ -1915,21 +1905,19 @@ macro_rules! exclusive_value {
                                 gecko_constant_prefix="NS_FONT_VARIANT_POSITION",
                                 spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-position",
                                 animation_value_type="discrete")}
 
 <%helpers:longhand name="font-feature-settings" products="gecko" animation_value_type="discrete"
                    extra_prefixes="moz" boxed="True"
                    spec="https://drafts.csswg.org/css-fonts/#propdef-font-feature-settings">
     use properties::longhands::system_font::SystemFont;
-    use std::fmt;
-    use style_traits::ToCss;
     use values::generics::FontSettings;
 
-    #[derive(Debug, Clone, PartialEq)]
+    #[derive(Debug, Clone, PartialEq, ToCss)]
     pub enum SpecifiedValue {
         Value(computed_value::T),
         System(SystemFont)
     }
     no_viewport_percentage!(SpecifiedValue);
 
     <%self:simple_system_boilerplate name="font_feature_settings"></%self:simple_system_boilerplate>
 
@@ -2007,17 +1995,17 @@ https://drafts.csswg.org/css-fonts-4/#lo
         System(SystemFont)
     }
 
     impl ToCss for SpecifiedValue {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             match *self {
                 SpecifiedValue::Normal => dest.write_str("normal"),
                 SpecifiedValue::Override(ref lang) => lang.to_css(dest),
-                SpecifiedValue::System(_) => Ok(())
+                SpecifiedValue::System(sys) => sys.to_css(dest),
             }
         }
     }
 
     impl SpecifiedValue {
         pub fn system_font(f: SystemFont) -> Self {
             SpecifiedValue::System(f)
         }
@@ -2375,18 +2363,19 @@ https://drafts.csswg.org/css-fonts-4/#lo
         //! from the -x-system-font property, we avoid this. Instead,
         //! each font longhand has a special SystemFont variant which contains
         //! the specified system font. When the cascade function (in helpers)
         //! detects that a value has a system font, it will resolve it, and
         //! cache it on the ComputedValues. After this, it can be just fetched
         //! whenever a font longhand on the same element needs the system font.
 
         use app_units::Au;
-        use cssparser::Parser;
+        use cssparser::{Parser, ToCss};
         use properties::longhands;
+        use std::fmt;
         use std::hash::{Hash, Hasher};
         use style_traits::ParseError;
         use values::computed::{ToComputedValue, Context};
         <%
             system_fonts = """caption icon menu message-box small-caption status-bar
                               -moz-window -moz-document -moz-workspace -moz-desktop
                               -moz-info -moz-dialog -moz-button -moz-pull-down-menu
                               -moz-list -moz-field""".split()
@@ -2508,34 +2497,48 @@ https://drafts.csswg.org/css-fonts-4/#lo
             pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
                 try_match_ident_ignore_ascii_case! { input.expect_ident()?,
                     % for font in system_fonts:
                         "${font}" => Ok(SystemFont::${to_camel_case(font)}),
                     % endfor
                 }
             }
         }
+
+        impl ToCss for SystemFont {
+            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+                // We may want to do something better in the future, see
+                // w3c/csswg-drafts#1586.
+                dest.write_str("-moz-use-system-font")
+            }
+        }
     }
 % else:
     pub mod system_font {
-        use cssparser::Parser;
+        use cssparser::{Parser, ToCss};
+        use std::fmt;
 
         // We don't parse system fonts, but in the interest of not littering
         // a lot of code with `if product == gecko` conditionals, we have a
         // dummy system font module that does nothing
 
         #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         /// void enum for system font, can never exist
         pub enum SystemFont {}
         impl SystemFont {
             pub fn parse(_: &mut Parser) -> Result<Self, ()> {
                 Err(())
             }
         }
+        impl ToCss for SystemFont {
+            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+                Ok(())
+            }
+        }
     }
 % endif
 
 ${helpers.single_keyword("-moz-osx-font-smoothing",
                          "auto grayscale",
                          gecko_constant_prefix="NS_FONT_SMOOTHING",
                          gecko_ffi_name="mFont.smoothing",
                          products="gecko",