servo: Merge #17121 - stylo: Fix serialization of system fonts (from Manishearth:stylo-system-font-ser); r=upsuper
authorJeff Hajewski <jeff.hajewski@gmail.com>
Thu, 01 Jun 2017 14:04:41 -0700
changeset 361965 975ba5ad9bb040982e81aa6091be9acfdaa019c6
parent 361964 5ae487045afba6c08bd1310ca597bfe888b0693b
child 361966 e8e908b731ad73478a68c39f87427341409ac5fe
push id90977
push usercbook@mozilla.com
push dateFri, 02 Jun 2017 12:33:01 +0000
treeherdermozilla-inbound@d5cd9b6d1a87 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersupsuper
milestone55.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
servo: Merge #17121 - stylo: Fix serialization of system fonts (from Manishearth:stylo-system-font-ser); r=upsuper Source-Repo: https://github.com/servo/servo Source-Revision: cfdb6af53b065d92fae028e48bf5e6c2c180dc56
servo/components/style/gecko/generated/structs_debug.rs
servo/components/style/gecko/generated/structs_release.rs
servo/components/style/properties/declaration_block.rs
servo/components/style/properties/longhand/inherited_text.mako.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/properties/shorthand/font.mako.rs
--- a/servo/components/style/gecko/generated/structs_debug.rs
+++ b/servo/components/style/gecko/generated/structs_debug.rs
@@ -710,22 +710,16 @@ pub mod root {
     pub const NS_STYLE_VERTICAL_ALIGN_BOTTOM: ::std::os::raw::c_uint = 21;
     pub const NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE:
               ::std::os::raw::c_uint =
         22;
     pub const NS_STYLE_VISIBILITY_HIDDEN: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_VISIBILITY_VISIBLE: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_VISIBILITY_COLLAPSE: ::std::os::raw::c_uint = 2;
     pub const NS_STYLE_TABSIZE_INITIAL: ::std::os::raw::c_uint = 8;
-    pub const NS_STYLE_WHITESPACE_NORMAL: ::std::os::raw::c_uint = 0;
-    pub const NS_STYLE_WHITESPACE_PRE: ::std::os::raw::c_uint = 1;
-    pub const NS_STYLE_WHITESPACE_NOWRAP: ::std::os::raw::c_uint = 2;
-    pub const NS_STYLE_WHITESPACE_PRE_WRAP: ::std::os::raw::c_uint = 3;
-    pub const NS_STYLE_WHITESPACE_PRE_LINE: ::std::os::raw::c_uint = 4;
-    pub const NS_STYLE_WHITESPACE_PRE_SPACE: ::std::os::raw::c_uint = 5;
     pub const NS_STYLE_WORDBREAK_NORMAL: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_WORDBREAK_BREAK_ALL: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_WORDBREAK_KEEP_ALL: ::std::os::raw::c_uint = 2;
     pub const NS_STYLE_OVERFLOWWRAP_NORMAL: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_OVERFLOWWRAP_BREAK_WORD: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_RUBY_ALIGN_START: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_RUBY_ALIGN_CENTER: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_RUBY_ALIGN_SPACE_BETWEEN: ::std::os::raw::c_uint = 2;
@@ -6195,16 +6189,26 @@ pub mod root {
             MozInlineStack = 35,
             MozDeck = 36,
             MozGroupbox = 37,
             MozPopup = 38,
         }
         #[repr(u8)]
         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
         pub enum StyleGridTrackBreadth { MaxContent = 1, MinContent = 2, }
+        #[repr(u8)]
+        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+        pub enum StyleWhiteSpace {
+            Normal = 0,
+            Pre = 1,
+            Nowrap = 2,
+            PreWrap = 3,
+            PreLine = 4,
+            PreSpace = 5,
+        }
         #[repr(C)]
         #[derive(Debug, Copy, Clone)]
         pub struct WritingMode {
             _unused: [u8; 0],
         }
         #[repr(u32)]
         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
         pub enum LogicalSide {
@@ -30347,17 +30351,17 @@ pub mod root {
     #[repr(C)]
     #[derive(Debug)]
     pub struct nsStyleText {
         pub mTextAlign: u8,
         pub mTextAlignLast: u8,
         pub _bitfield_1: u8,
         pub mTextJustify: root::mozilla::StyleTextJustify,
         pub mTextTransform: u8,
-        pub mWhiteSpace: u8,
+        pub mWhiteSpace: root::mozilla::StyleWhiteSpace,
         pub mWordBreak: u8,
         pub mOverflowWrap: u8,
         pub mHyphens: root::mozilla::StyleHyphens,
         pub mRubyAlign: u8,
         pub mRubyPosition: u8,
         pub mTextSizeAdjust: u8,
         pub mTextCombineUpright: u8,
         pub mControlCharacterVisibility: u8,
--- a/servo/components/style/gecko/generated/structs_release.rs
+++ b/servo/components/style/gecko/generated/structs_release.rs
@@ -710,22 +710,16 @@ pub mod root {
     pub const NS_STYLE_VERTICAL_ALIGN_BOTTOM: ::std::os::raw::c_uint = 21;
     pub const NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE:
               ::std::os::raw::c_uint =
         22;
     pub const NS_STYLE_VISIBILITY_HIDDEN: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_VISIBILITY_VISIBLE: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_VISIBILITY_COLLAPSE: ::std::os::raw::c_uint = 2;
     pub const NS_STYLE_TABSIZE_INITIAL: ::std::os::raw::c_uint = 8;
-    pub const NS_STYLE_WHITESPACE_NORMAL: ::std::os::raw::c_uint = 0;
-    pub const NS_STYLE_WHITESPACE_PRE: ::std::os::raw::c_uint = 1;
-    pub const NS_STYLE_WHITESPACE_NOWRAP: ::std::os::raw::c_uint = 2;
-    pub const NS_STYLE_WHITESPACE_PRE_WRAP: ::std::os::raw::c_uint = 3;
-    pub const NS_STYLE_WHITESPACE_PRE_LINE: ::std::os::raw::c_uint = 4;
-    pub const NS_STYLE_WHITESPACE_PRE_SPACE: ::std::os::raw::c_uint = 5;
     pub const NS_STYLE_WORDBREAK_NORMAL: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_WORDBREAK_BREAK_ALL: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_WORDBREAK_KEEP_ALL: ::std::os::raw::c_uint = 2;
     pub const NS_STYLE_OVERFLOWWRAP_NORMAL: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_OVERFLOWWRAP_BREAK_WORD: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_RUBY_ALIGN_START: ::std::os::raw::c_uint = 0;
     pub const NS_STYLE_RUBY_ALIGN_CENTER: ::std::os::raw::c_uint = 1;
     pub const NS_STYLE_RUBY_ALIGN_SPACE_BETWEEN: ::std::os::raw::c_uint = 2;
@@ -6063,16 +6057,26 @@ pub mod root {
             MozInlineStack = 35,
             MozDeck = 36,
             MozGroupbox = 37,
             MozPopup = 38,
         }
         #[repr(u8)]
         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
         pub enum StyleGridTrackBreadth { MaxContent = 1, MinContent = 2, }
+        #[repr(u8)]
+        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+        pub enum StyleWhiteSpace {
+            Normal = 0,
+            Pre = 1,
+            Nowrap = 2,
+            PreWrap = 3,
+            PreLine = 4,
+            PreSpace = 5,
+        }
         #[repr(C)]
         #[derive(Debug, Copy, Clone)]
         pub struct WritingMode {
             _unused: [u8; 0],
         }
         #[repr(u32)]
         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
         pub enum LogicalSide {
@@ -29828,17 +29832,17 @@ pub mod root {
     #[repr(C)]
     #[derive(Debug)]
     pub struct nsStyleText {
         pub mTextAlign: u8,
         pub mTextAlignLast: u8,
         pub _bitfield_1: u8,
         pub mTextJustify: root::mozilla::StyleTextJustify,
         pub mTextTransform: u8,
-        pub mWhiteSpace: u8,
+        pub mWhiteSpace: root::mozilla::StyleWhiteSpace,
         pub mWordBreak: u8,
         pub mOverflowWrap: u8,
         pub mHyphens: root::mozilla::StyleHyphens,
         pub mRubyAlign: u8,
         pub mRubyPosition: u8,
         pub mTextSizeAdjust: u8,
         pub mTextCombineUpright: u8,
         pub mControlCharacterVisibility: u8,
--- a/servo/components/style/properties/declaration_block.rs
+++ b/servo/components/style/properties/declaration_block.rs
@@ -507,34 +507,48 @@ impl ToCss for PropertyDeclarationBlock 
 
                 // Step 3.3.2
                 for &shorthand in shorthands {
                     let properties = shorthand.longhands();
 
                     // Substep 2 & 3
                     let mut current_longhands = Vec::new();
                     let mut important_count = 0;
+                    let mut found_system = None;
 
-                    for &&(ref longhand, longhand_importance) in longhands.iter() {
-                        if longhand.id().is_longhand_of(shorthand) {
-                            current_longhands.push(longhand);
-                            if longhand_importance.important() {
-                                important_count += 1;
+                    if shorthand == ShorthandId::Font && longhands.iter().any(|&&(ref l, _)| l.get_system().is_some()) {
+                        for &&(ref longhand, longhand_importance) in longhands.iter() {
+                            if longhand.get_system().is_some() || longhand.is_default_line_height() {
+                                current_longhands.push(longhand);
+                                if found_system.is_none() {
+                                   found_system = longhand.get_system();
+                                }
+                                if longhand_importance.important() {
+                                    important_count += 1;
+                                }
                             }
                         }
-                    }
-
-                    // Substep 1:
-                    //
-                    // Assuming that the PropertyDeclarationBlock contains no
-                    // duplicate entries, if the current_longhands length is
-                    // equal to the properties length, it means that the
-                    // properties that map to shorthand are present in longhands
-                    if current_longhands.len() != properties.len() {
-                        continue;
+                    } else {
+                        for &&(ref longhand, longhand_importance) in longhands.iter() {
+                            if longhand.id().is_longhand_of(shorthand) {
+                                current_longhands.push(longhand);
+                                if longhand_importance.important() {
+                                    important_count += 1;
+                                }
+                            }
+                        }
+                        // Substep 1:
+                        //
+                         // Assuming that the PropertyDeclarationBlock contains no
+                         // duplicate entries, if the current_longhands length is
+                         // equal to the properties length, it means that the
+                         // properties that map to shorthand are present in longhands
+                        if current_longhands.len() != properties.len() {
+                            continue;
+                        }
                     }
 
                     // Substep 4
                     let is_important = important_count > 0;
                     if is_important && important_count != current_longhands.len() {
                         continue;
                     }
                     let importance = if is_important {
@@ -548,35 +562,43 @@ impl ToCss for PropertyDeclarationBlock 
                     let appendable_value =
                         match shorthand.get_shorthand_appendable_value(current_longhands.iter().cloned()) {
                             None => continue,
                             Some(appendable_value) => appendable_value,
                         };
 
                     // We avoid re-serializing if we're already an
                     // AppendableValue::Css.
-                    let mut value = String::new();
-                    let value = match appendable_value {
-                        AppendableValue::Css { css, with_variables } => {
+                    let mut v = String::new();
+                    let value = match (appendable_value, found_system) {
+                        (AppendableValue::Css { css, with_variables }, _) => {
                             debug_assert!(!css.is_empty());
                             AppendableValue::Css {
                                 css: css,
                                 with_variables: with_variables,
                             }
                         }
-                        other @ _ => {
-                            append_declaration_value(&mut value, other)?;
+                        #[cfg(feature = "gecko")]
+                        (_, Some(sys)) => {
+                            sys.to_css(&mut v)?;
+                            AppendableValue::Css {
+                                css: &v,
+                                with_variables: false,
+                            }
+                        }
+                        (other, _) => {
+                            append_declaration_value(&mut v, other)?;
 
                             // Substep 6
-                            if value.is_empty() {
+                            if v.is_empty() {
                                 continue;
                             }
 
                             AppendableValue::Css {
-                                css: &value,
+                                css: &v,
                                 with_variables: false,
                             }
                         }
                     };
 
                     // Substeps 7 and 8
                     // We need to check the shorthand whether it's an alias property or not.
                     // If it's an alias property, it should be serialized like its longhand.
--- a/servo/components/style/properties/longhand/inherited_text.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_text.mako.rs
@@ -630,17 +630,17 @@
         let derived = derive(context);
         context.mutate_style().mutate_inheritedtext().set__servo_text_decorations_in_effect(derived);
     }
 </%helpers:longhand>
 
 <%helpers:single_keyword_computed name="white-space"
                                   values="normal pre nowrap pre-wrap pre-line"
                                   extra_gecko_values="-moz-pre-space"
-                                  gecko_constant_prefix="NS_STYLE_WHITESPACE"
+                                  gecko_enum_prefix="StyleWhiteSpace"
                                   needs_conversion="True"
                                   animation_value_type="none"
                                   spec="https://drafts.csswg.org/css-text/#propdef-white-space">
     use values::computed::ComputedValueAsSpecified;
     impl ComputedValueAsSpecified for SpecifiedValue {}
     no_viewport_percentage!(SpecifiedValue);
 
     % if product != "gecko":
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -27,16 +27,17 @@ use context::QuirksMode;
 use font_metrics::FontMetricsProvider;
 #[cfg(feature = "gecko")] use gecko_bindings::bindings;
 #[cfg(feature = "gecko")] use gecko_bindings::structs::{self, nsCSSPropertyID};
 #[cfg(feature = "servo")] use logical_geometry::{LogicalMargin, PhysicalSide};
 use logical_geometry::WritingMode;
 use media_queries::Device;
 use parser::{PARSING_MODE_DEFAULT, Parse, ParserContext};
 use properties::animated_properties::TransitionProperty;
+#[cfg(feature = "gecko")] use properties::longhands::system_font::SystemFont;
 #[cfg(feature = "servo")] use servo_config::prefs::PREFS;
 use shared_lock::StylesheetGuards;
 use style_traits::{HasViewportPercentage, ToCss};
 use stylesheets::{CssRuleType, MallocSizeOf, MallocSizeOfFn, Origin, UrlExtraData};
 #[cfg(feature = "servo")] use values::Either;
 use values::specified::Color;
 use values::computed;
 use cascade_info::CascadeInfo;
@@ -48,17 +49,17 @@ pub use self::declaration_block::*;
 
 #[cfg(feature = "gecko")]
 #[macro_export]
 macro_rules! property_name {
     ($s: tt) => { atom!($s) }
 }
 
 <%!
-    from data import Method, Keyword, to_rust_ident, to_camel_case
+    from data import Method, Keyword, to_rust_ident, to_camel_case, SYSTEM_FONT_LONGHANDS
     import os.path
 %>
 
 #[path="${repr(os.path.join(os.path.dirname(__file__), 'declaration_block.rs'))[1:-1]}"]
 pub mod declaration_block;
 
 /// Conversion with fewer impls than From/Into
 pub trait MaybeBoxed<Out> {
@@ -1242,16 +1243,45 @@ impl PropertyDeclaration {
     /// Returns a CSS-wide keyword if the declaration's value is one.
     pub fn get_css_wide_keyword(&self) -> Option<CSSWideKeyword> {
         match *self {
             PropertyDeclaration::CSSWideKeyword(_, keyword) => Some(keyword),
             _ => None,
         }
     }
 
+    /// Returns whether or not the property is set by a system font
+    #[cfg(feature = "gecko")]
+    pub fn get_system(&self) -> Option<SystemFont> {
+        match *self {
+            % for prop in SYSTEM_FONT_LONGHANDS:
+                PropertyDeclaration::${to_camel_case(prop)}(ref prop) => {
+                    prop.get_system()
+                }
+            % endfor
+            _ => None,
+        }
+    }
+
+    /// Is it the default value of line-height?
+    ///
+    /// (using match because it generates less code than)
+    pub fn is_default_line_height(&self) -> bool {
+        match *self {
+            PropertyDeclaration::LineHeight(longhands::line_height::SpecifiedValue::Normal) => true,
+            _ => false
+        }
+    }
+
+    #[cfg(feature = "servo")]
+    /// Dummy method to avoid cfg()s
+    pub fn get_system(&self) -> Option<()> {
+        None
+    }
+
     /// Returns whether the declaration may be serialized as part of a shorthand.
     ///
     /// This method returns false if this declaration contains variable or has a
     /// CSS-wide keyword value, since these values cannot be serialized as part
     /// of a shorthand.
     ///
     /// Caller should check `with_variables_from_shorthand()` and whether all
     /// needed declarations has the same CSS-wide keyword first.
--- a/servo/components/style/properties/shorthand/font.mako.rs
+++ b/servo/components/style/properties/shorthand/font.mako.rs
@@ -17,16 +17,17 @@
                                     ${'font-variant-position' if product == 'gecko' or data.testing else ''}
                                     ${'font-language-override' if product == 'gecko' or data.testing else ''}
                                     ${'font-feature-settings' if product == 'gecko' or data.testing else ''}"
                     spec="https://drafts.csswg.org/css-fonts-3/#propdef-font">
     use properties::longhands::{font_family, font_style, font_weight, font_stretch};
     use properties::longhands::{font_size, line_height, font_variant_caps};
     #[cfg(feature = "gecko")]
     use properties::longhands::system_font::SystemFont;
+
     <%
         gecko_sub_properties = "kerning language_override size_adjust \
                                 variant_alternates variant_east_asian \
                                 variant_ligatures variant_numeric \
                                 variant_position feature_settings".split()
     %>
     % if product == "gecko" or data.testing:
         % for prop in gecko_sub_properties: