Bug 1341775 - Part 4: stylo: Special-case initial-computation of font-size; r?heycam draft
authorManish Goregaokar <manishearth@gmail.com>
Fri, 17 Mar 2017 19:48:20 -0700
changeset 503956 4f37590f98f3082ed6f6b0a93dce29add1d7066a
parent 503946 e2821aa36c9801122abf35eee1b29fbbdd006ca1
child 503957 b30b14b07b6e2c37ac34f642ae640ba62eb2b17a
push id50721
push userbmo:manishearth@gmail.com
push dateThu, 23 Mar 2017 21:48:28 +0000
reviewersheycam
bugs1341775
milestone55.0a1
Bug 1341775 - Part 4: stylo: Special-case initial-computation of font-size; r?heycam MozReview-Commit-ID: Ff6kt8RLChI
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/helpers.mako.rs
servo/components/style/properties/longhand/font.mako.rs
servo/components/style/properties/properties.mako.rs
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -75,60 +75,65 @@ pub struct ComputedValues {
     % for style_struct in data.style_structs:
     ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
     % endfor
 
     custom_properties: Option<Arc<ComputedValuesMap>>,
     shareable: bool,
     pub writing_mode: WritingMode,
     pub root_font_size: Au,
+    pub font_size_keyword: Option<longhands::font_size::KeywordSize>,
 }
 
 impl ComputedValues {
     pub fn inherit_from(parent: &Self, default: &Self) -> Arc<Self> {
         Arc::new(ComputedValues {
             custom_properties: parent.custom_properties.clone(),
             shareable: parent.shareable,
             writing_mode: parent.writing_mode,
             root_font_size: parent.root_font_size,
+            font_size_keyword: parent.font_size_keyword,
             % for style_struct in data.style_structs:
             % if style_struct.inherited:
             ${style_struct.ident}: parent.${style_struct.ident}.clone(),
             % else:
             ${style_struct.ident}: default.${style_struct.ident}.clone(),
             % endif
             % endfor
         })
     }
 
     pub fn new(custom_properties: Option<Arc<ComputedValuesMap>>,
            shareable: bool,
            writing_mode: WritingMode,
            root_font_size: Au,
+           font_size_keyword: Option<longhands::font_size::KeywordSize>,
             % for style_struct in data.style_structs:
            ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
             % endfor
     ) -> Self {
         ComputedValues {
             custom_properties: custom_properties,
             shareable: shareable,
             writing_mode: writing_mode,
             root_font_size: root_font_size,
+            font_size_keyword: font_size_keyword,
             % for style_struct in data.style_structs:
             ${style_struct.ident}: ${style_struct.ident},
             % endfor
         }
     }
 
     pub fn default_values(pres_context: RawGeckoPresContextBorrowed) -> Arc<Self> {
         Arc::new(ComputedValues {
             custom_properties: None,
             shareable: true,
             writing_mode: WritingMode::empty(), // FIXME(bz): This seems dubious
             root_font_size: longhands::font_size::get_initial_value(), // FIXME(bz): Also seems dubious?
+            font_size_keyword: Some(Default::default()),
             % for style_struct in data.style_structs:
                 ${style_struct.ident}: style_structs::${style_struct.name}::default(pres_context),
             % endfor
         })
     }
 
     #[inline]
     pub fn is_display_contents(&self) -> bool {
--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -261,50 +261,70 @@
                         }
                         % if property.logical:
                             let wm = context.style.writing_mode;
                         % endif
                         <% maybe_wm = ", wm" if property.logical else "" %>
                         match *value {
                             DeclaredValue::Value(ref specified_value) => {
                                 let computed = specified_value.to_computed_value(context);
+                                % if property.ident == "font_size":
+                                    if let longhands::font_size::SpecifiedValue::Keyword(kw) = **specified_value {
+                                        context.mutate_style().font_size_keyword = Some(kw);
+                                    } else {
+                                        context.mutate_style().font_size_keyword = None;
+                                    }
+                                % endif
                                 % if property.has_uncacheable_values:
                                 context.mutate_style().mutate_${data.current_style_struct.name_lower}()
                                                       .set_${property.ident}(computed, cacheable ${maybe_wm});
                                 % else:
                                 context.mutate_style().mutate_${data.current_style_struct.name_lower}()
                                                       .set_${property.ident}(computed ${maybe_wm});
                                 % endif
                             }
                             DeclaredValue::WithVariables(_) => unreachable!(),
                             DeclaredValue::CSSWideKeyword(keyword) => match keyword {
                                 % if not data.current_style_struct.inherited:
                                 CSSWideKeyword::Unset |
                                 % endif
                                 CSSWideKeyword::Initial => {
-                                    // We assume that it's faster to use copy_*_from rather than
-                                    // set_*(get_initial_value());
-                                    let initial_struct = default_style
-                                                        .get_${data.current_style_struct.name_lower}();
-                                    context.mutate_style().mutate_${data.current_style_struct.name_lower}()
-                                                        .copy_${property.ident}_from(initial_struct ${maybe_wm});
+                                    % if property.ident == "font_size":
+                                        // font-size's default ("medium") does not always
+                                        // compute to the same value and depends on the font
+                                        let computed = longhands::font_size::get_initial_specified_value()
+                                                            .to_computed_value(context);
+                                        context.mutate_style().mutate_${data.current_style_struct.name_lower}()
+                                               .set_font_size(computed);
+                                        context.mutate_style().font_size_keyword = Some(Default::default());
+                                    % else:
+                                        // We assume that it's faster to use copy_*_from rather than
+                                        // set_*(get_initial_value());
+                                        let initial_struct = default_style
+                                                            .get_${data.current_style_struct.name_lower}();
+                                        context.mutate_style().mutate_${data.current_style_struct.name_lower}()
+                                                            .copy_${property.ident}_from(initial_struct ${maybe_wm});
+                                    % endif
                                 },
                                 % if data.current_style_struct.inherited:
                                 CSSWideKeyword::Unset |
                                 % endif
                                 CSSWideKeyword::Inherit => {
                                     // This is a bit slow, but this is rare so it shouldn't
                                     // matter.
                                     //
                                     // FIXME: is it still?
                                     *cacheable = false;
                                     let inherited_struct =
                                         inherited_style.get_${data.current_style_struct.name_lower}();
                                     context.mutate_style().mutate_${data.current_style_struct.name_lower}()
                                         .copy_${property.ident}_from(inherited_struct ${maybe_wm});
+                                    % if property.ident == "font_size":
+                                        context.mutate_style().font_size_keyword = context.inherited_style.font_size_keyword;
+                                    % endif
                                 }
                             }
                         }
                     }, error_reporter);
                 }
 
                 % if property.custom_cascade:
                     cascade_property_custom(declaration,
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -460,16 +460,22 @@
                 "large" => Large,
                 "x-large" => XLarge,
                 "xx-large" => XXLarge,
                 _ => return Err(())
             })
         }
     }
 
+    impl Default for KeywordSize {
+        fn default() -> Self {
+            Medium
+        }
+    }
+
     impl ToCss for KeywordSize {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             dest.write_str(match *self {
                 XXSmall => "xx-small",
                 XSmall => "x-small",
                 Small => "small",
                 Medium => "medium",
                 Large => "large",
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -1497,34 +1497,38 @@ pub struct ComputedValues {
         ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
     % endfor
     custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
     shareable: bool,
     /// The writing mode of this computed values struct.
     pub writing_mode: WritingMode,
     /// The root element's computed font size.
     pub root_font_size: Au,
+    /// The keyword behind the current font-size property, if any
+    pub font_size_keyword: Option<longhands::font_size::KeywordSize>,
 }
 
 #[cfg(feature = "servo")]
 impl ComputedValues {
     /// Construct a `ComputedValues` instance.
     pub fn new(custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
                shareable: bool,
                writing_mode: WritingMode,
                root_font_size: Au,
+               font_size_keyword: Option<longhands::font_size::KeywordSize>,
             % for style_struct in data.active_style_structs():
                ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
             % endfor
     ) -> Self {
         ComputedValues {
             custom_properties: custom_properties,
             shareable: shareable,
             writing_mode: writing_mode,
             root_font_size: root_font_size,
+            font_size_keyword: font_size_keyword,
         % for style_struct in data.active_style_structs():
             ${style_struct.ident}: ${style_struct.ident},
         % endfor
         }
     }
 
     /// Get the initial computed values.
     pub fn initial_values() -> &'static Self { &*INITIAL_SERVO_VALUES }
@@ -1838,16 +1842,17 @@ mod lazy_static_module {
                         hash: 0,
                     % endif
                 }),
             % endfor
             custom_properties: None,
             shareable: true,
             writing_mode: WritingMode::empty(),
             root_font_size: longhands::font_size::get_initial_value(),
+            font_size_keyword: Some(Default::default()),
         };
     }
 }
 
 /// A per-longhand function that performs the CSS cascade for that longhand.
 pub type CascadePropertyFn =
     extern "Rust" fn(declaration: &PropertyDeclaration,
                      inherited_style: &ComputedValues,
@@ -1979,29 +1984,31 @@ pub fn apply_declarations<'a, F, I>(devi
         ::custom_properties::finish_cascade(
             custom_properties, &inherited_custom_properties);
 
     let starting_style = if !flags.contains(INHERIT_ALL) {
         ComputedValues::new(custom_properties,
                             flags.contains(SHAREABLE),
                             WritingMode::empty(),
                             inherited_style.root_font_size,
+                            inherited_style.font_size_keyword,
                             % for style_struct in data.active_style_structs():
                                 % if style_struct.inherited:
                                     inherited_style.clone_${style_struct.name_lower}(),
                                 % else:
                                     default_style.clone_${style_struct.name_lower}(),
                                 % endif
                             % endfor
                             )
     } else {
         ComputedValues::new(custom_properties,
                             flags.contains(SHAREABLE),
                             WritingMode::empty(),
                             inherited_style.root_font_size,
+                            inherited_style.font_size_keyword,
                             % for style_struct in data.active_style_structs():
                                 inherited_style.clone_${style_struct.name_lower}(),
                             % endfor
                             )
     };
 
     let mut context = computed::Context {
         is_root_element: is_root_element,
@@ -2071,34 +2078,35 @@ pub fn apply_declarations<'a, F, I>(devi
             if
                 % if category_to_cascade_now == "early":
                     !
                 % endif
                 is_early_property
             {
                 continue
             }
+
+            <% maybe_to_physical = ".to_physical(writing_mode)" if category_to_cascade_now != "early" else "" %>
+            let physical_longhand_id = longhand_id ${maybe_to_physical};
+            if seen.contains(physical_longhand_id) {
+                continue
+            }
+            seen.insert(physical_longhand_id);
+
             % if category_to_cascade_now == "early":
                 if LonghandId::FontSize == longhand_id {
                     font_size = Some(declaration);
                     continue;
                 }
                 if LonghandId::FontFamily == longhand_id {
                     font_family = Some(declaration);
                     continue;
                 }
             % endif
 
-            <% maybe_to_physical = ".to_physical(writing_mode)" if category_to_cascade_now != "early" else "" %>
-            let physical_longhand_id = longhand_id ${maybe_to_physical};
-            if seen.contains(physical_longhand_id) {
-                continue
-            }
-            seen.insert(physical_longhand_id);
-
             let discriminant = longhand_id as usize;
             (CASCADE_PROPERTY[discriminant])(declaration,
                                              inherited_style,
                                              default_style,
                                              &mut context,
                                              &mut cacheable,
                                              &mut cascade_info,
                                              error_reporter);
@@ -2131,16 +2139,30 @@ pub fn apply_declarations<'a, F, I>(devi
                 let discriminant = LonghandId::FontSize as usize;
                 (CASCADE_PROPERTY[discriminant])(declaration,
                                                  inherited_style,
                                                  default_style,
                                                  &mut context,
                                                  &mut cacheable,
                                                  &mut cascade_info,
                                                  error_reporter);
+            } else if let Some(kw) = inherited_style.font_size_keyword {
+                // Font size keywords will inherit as keywords and be recomputed
+                // each time.
+                let discriminant = LonghandId::FontSize as usize;
+                let size = PropertyDeclaration::FontSize(
+                    longhands::font_size::SpecifiedValue::Keyword(kw)
+                );
+                (CASCADE_PROPERTY[discriminant])(&size,
+                                                 inherited_style,
+                                                 default_style,
+                                                 &mut context,
+                                                 &mut cacheable,
+                                                 &mut cascade_info,
+                                                 error_reporter);
             }
         % endif
     % endfor
 
     let mut style = context.style;
 
     let positioned = matches!(style.get_box().clone_position(),
         longhands::position::SpecifiedValue::absolute |