Bug 1399228 - stylo: Remove FontComputationData, switch over to using the new font tracking; r?emilio draft
authorManish Goregaokar <manishearth@gmail.com>
Fri, 15 Sep 2017 15:25:02 -0700
changeset 669458 cba3f3abab6d5fe7577b58d81dc39007fe1c0974
parent 669457 412b4c823835e23d56eaa817d26d1e553c3c6d60
child 669459 79029a15ed190e253dda0c9f2716cf643c11df6e
push id81335
push userbmo:manishearth@gmail.com
push dateSat, 23 Sep 2017 08:49:12 +0000
reviewersemilio
bugs1399228
milestone58.0a1
Bug 1399228 - stylo: Remove FontComputationData, switch over to using the new font tracking; r?emilio MozReview-Commit-ID: 66IAynRiUkU
layout/style/ServoBindings.toml
layout/style/ServoTypes.h
servo/components/style/gecko/generated/structs_debug.rs
servo/components/style/gecko/generated/structs_release.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/longhand/font.mako.rs
servo/components/style/properties/properties.mako.rs
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -347,17 +347,16 @@ opaque-types = [
     "mozilla::dom::.*Callback", # Pulls in ErrorResult and other things that
                                 # don't align properly on Linux 32-bit
 ]
 mapped-generic-types = [
     { generic = true, gecko = "mozilla::ServoUnsafeCell", servo = "::std::cell::UnsafeCell" },
     { generic = true, gecko = "mozilla::ServoCell", servo = "::std::cell::Cell" },
     { generic = false, gecko = "ServoNodeData", servo = "AtomicRefCell<ElementData>" },
     { generic = false, gecko = "mozilla::ServoWritingMode", servo = "::logical_geometry::WritingMode" },
-    { generic = false, gecko = "mozilla::ServoFontComputationData", servo = "::properties::FontComputationData" },
     { generic = false, gecko = "mozilla::ServoCustomPropertiesMap", servo = "Option<::servo_arc::Arc<::custom_properties::CustomPropertiesMap>>" },
     { generic = false, gecko = "mozilla::ServoRuleNode", servo = "Option<::rule_tree::StrongRuleNode>" },
     { generic = false, gecko = "mozilla::ServoVisitedStyle", servo = "Option<::servo_arc::RawOffsetArc<::properties::ComputedValues>>" },
     { generic = false, gecko = "mozilla::ServoComputedValueFlags", servo = "::properties::computed_value_flags::ComputedValueFlags" },
     { generic = true, gecko = "mozilla::ServoRawOffsetArc", servo = "::servo_arc::RawOffsetArc" },
     { generic = false, gecko = "ServoStyleContextStrong", servo = "::gecko_bindings::sugar::ownership::Strong<::properties::ComputedValues>" },
 ]
 fixups = [
--- a/layout/style/ServoTypes.h
+++ b/layout/style/ServoTypes.h
@@ -130,44 +130,16 @@ enum class InheritTarget {
   // We're requesting a style for a placeholder frame.
   PlaceholderFrame,
 };
 
 struct ServoWritingMode {
   uint8_t mBits;
 };
 
-// Don't attempt to read from this
-// (see comment on ServoFontComputationData
-enum ServoKeywordSize {
-  Empty, // when the Option is None
-  XXSmall,
-  XSmall,
-  Small,
-  Medium,
-  Large,
-  XLarge,
-  XXLarge,
-  XXXLarge,
-};
-
-// Don't attempt to read from this. We can't
-// always guarantee that the interior representation
-// of this is correct (the mKeyword field may have a different padding),
-// but the entire struct should
-// have the same size and alignment as the Rust version.
-// Ensure layout tests get run if touching either side.
-struct ServoFontComputationData {
-  ServoKeywordSize mKeyword;
-  float/*32_t*/ mRatio;
-  int32_t mAbsolute;
-
-  static_assert(sizeof(float) == 4, "float should be 32 bit");
-};
-
 struct ServoCustomPropertiesMap {
   uintptr_t mPtr;
 };
 
 struct ServoRuleNode {
   uintptr_t mPtr;
 };
 
@@ -265,24 +237,16 @@ private:
   /// node.  Can be None for default values and text nodes.  This is
   /// essentially an optimization to avoid referencing the root rule node.
   mozilla::ServoRuleNode rules;
   /// The element's computed values if visited, only computed if there's a
   /// relevant link for this element. A element's "relevant link" is the
   /// element being matched if it is a link or the nearest ancestor link.
   mozilla::ServoVisitedStyle visited_style;
 
-  // this is the last member because most of the other members
-  // are pointer sized. This makes it easier to deal with the
-  // alignment of the fields when replacing things via bindgen
-  //
-  // This is opaque, please don't read from it from C++
-  // (see comment on ServoFontComputationData)
-  mozilla::ServoFontComputationData font_computation_data;
-
   // C++ just sees this struct as a bucket of bits, and will
   // do the wrong thing if we let it use the default copy ctor/assignment
   // operator. Remove them so that there is no footgun.
   //
   // We remove the move ctor/assignment operator as well, because
   // moves in C++ don't prevent destructors from being called,
   // which will lead to double frees.
   ServoComputedData& operator=(const ServoComputedData&) = delete;
--- a/servo/components/style/gecko/generated/structs_debug.rs
+++ b/servo/components/style/gecko/generated/structs_debug.rs
@@ -5,17 +5,16 @@ pub use self::root::mozilla::*;
 pub use self::root::mozilla::css::*;
 pub use self::root::mozilla::dom::*;
 use atomic_refcell::AtomicRefCell;
 use data::ElementData;
 pub type ServoUnsafeCell<T> = ::std::cell::UnsafeCell<T>;
 pub type ServoCell<T> = ::std::cell::Cell<T>;
 pub type ServoNodeData = AtomicRefCell<ElementData>;
 pub type ServoWritingMode = ::logical_geometry::WritingMode;
-pub type ServoFontComputationData = ::properties::FontComputationData;
 pub type ServoCustomPropertiesMap = Option<::servo_arc::Arc<::custom_properties::CustomPropertiesMap>>;
 pub type ServoRuleNode = Option<::rule_tree::StrongRuleNode>;
 pub type ServoVisitedStyle = Option<::servo_arc::RawOffsetArc<::properties::ComputedValues>>;
 pub type ServoComputedValueFlags = ::properties::computed_value_flags::ComputedValueFlags;
 pub type ServoRawOffsetArc<T> = ::servo_arc::RawOffsetArc<T>;
 pub type ServoStyleContextStrong = ::gecko_bindings::sugar::ownership::Strong<::properties::ComputedValues>;
 
 #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
@@ -4458,41 +4457,28 @@ pub mod root {
         pub type ParsingMode = u8;
         #[repr(i32)]
         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
         pub enum InheritTarget {
             Text = 0,
             FirstLetterContinuation = 1,
             PlaceholderFrame = 2,
         }
-        #[repr(u32)]
-        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-        pub enum ServoKeywordSize {
-            Empty = 0,
-            XXSmall = 1,
-            XSmall = 2,
-            Small = 3,
-            Medium = 4,
-            Large = 5,
-            XLarge = 6,
-            XXLarge = 7,
-            XXXLarge = 8,
-        }
         #[repr(C)]
         #[derive(Debug)]
         pub struct ServoStyleContext {
             pub _base: root::nsStyleContext,
             pub mPresContext: *mut root::nsPresContext,
             pub mSource: root::ServoComputedData,
             pub mNextInheritingAnonBoxStyle: root::RefPtr<root::mozilla::ServoStyleContext>,
             pub mNextLazyPseudoStyle: root::RefPtr<root::mozilla::ServoStyleContext>,
         }
         #[test]
         fn bindgen_test_layout_ServoStyleContext() {
-            assert_eq!(::std::mem::size_of::<ServoStyleContext>() , 280usize ,
+            assert_eq!(::std::mem::size_of::<ServoStyleContext>() , 264usize ,
                        concat ! (
                        "Size of: " , stringify ! ( ServoStyleContext ) ));
             assert_eq! (::std::mem::align_of::<ServoStyleContext>() , 8usize ,
                         concat ! (
                         "Alignment of " , stringify ! ( ServoStyleContext )
                         ));
             assert_eq! (unsafe {
                         & ( * ( 0 as * const ServoStyleContext ) ) .
@@ -4505,24 +4491,24 @@ pub mod root {
                         & ( * ( 0 as * const ServoStyleContext ) ) . mSource
                         as * const _ as usize } , 32usize , concat ! (
                         "Alignment of field: " , stringify ! (
                         ServoStyleContext ) , "::" , stringify ! ( mSource )
                         ));
             assert_eq! (unsafe {
                         & ( * ( 0 as * const ServoStyleContext ) ) .
                         mNextInheritingAnonBoxStyle as * const _ as usize } ,
-                        264usize , concat ! (
+                        248usize , concat ! (
                         "Alignment of field: " , stringify ! (
                         ServoStyleContext ) , "::" , stringify ! (
                         mNextInheritingAnonBoxStyle ) ));
             assert_eq! (unsafe {
                         & ( * ( 0 as * const ServoStyleContext ) ) .
                         mNextLazyPseudoStyle as * const _ as usize } ,
-                        272usize , concat ! (
+                        256usize , concat ! (
                         "Alignment of field: " , stringify ! (
                         ServoStyleContext ) , "::" , stringify ! (
                         mNextLazyPseudoStyle ) ));
         }
         #[repr(C)]
         #[derive(Debug)]
         pub struct GeckoFont {
             pub gecko: root::nsStyleFont,
@@ -14823,21 +14809,20 @@ pub mod root {
         /// The rule node representing the ordered list of rules matched for this
         /// /// node.  Can be None for default values and text nodes.  This is
         /// /// essentially an optimization to avoid referencing the root rule node.
         pub rules: ::gecko_bindings::structs::ServoRuleNode,
         /// The element's computed values if visited, only computed if there's a
         /// /// relevant link for this element. A element's "relevant link" is the
         /// /// element being matched if it is a link or the nearest ancestor link.
         pub visited_style: ::gecko_bindings::structs::ServoVisitedStyle,
-        pub font_computation_data: ::gecko_bindings::structs::ServoFontComputationData,
     }
     #[test]
     fn bindgen_test_layout_ServoComputedData() {
-        assert_eq!(::std::mem::size_of::<ServoComputedData>() , 232usize ,
+        assert_eq!(::std::mem::size_of::<ServoComputedData>() , 216usize ,
                    concat ! ( "Size of: " , stringify ! ( ServoComputedData )
                    ));
         assert_eq! (::std::mem::align_of::<ServoComputedData>() , 8usize ,
                     concat ! (
                     "Alignment of " , stringify ! ( ServoComputedData ) ));
         assert_eq! (unsafe {
                     & ( * ( 0 as * const ServoComputedData ) ) . Font as *
                     const _ as usize } , 0usize , concat ! (
@@ -14974,22 +14959,16 @@ pub mod root {
                     const _ as usize } , 200usize , concat ! (
                     "Alignment of field: " , stringify ! ( ServoComputedData )
                     , "::" , stringify ! ( rules ) ));
         assert_eq! (unsafe {
                     & ( * ( 0 as * const ServoComputedData ) ) . visited_style
                     as * const _ as usize } , 208usize , concat ! (
                     "Alignment of field: " , stringify ! ( ServoComputedData )
                     , "::" , stringify ! ( visited_style ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const ServoComputedData ) ) .
-                    font_computation_data as * const _ as usize } , 216usize ,
-                    concat ! (
-                    "Alignment of field: " , stringify ! ( ServoComputedData )
-                    , "::" , stringify ! ( font_computation_data ) ));
     }
     #[repr(u32)]
     #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
     pub enum JSValueTag {
         JSVAL_TAG_MAX_DOUBLE = 131056,
         JSVAL_TAG_INT32 = 131057,
         JSVAL_TAG_UNDEFINED = 131058,
         JSVAL_TAG_NULL = 131059,
--- a/servo/components/style/gecko/generated/structs_release.rs
+++ b/servo/components/style/gecko/generated/structs_release.rs
@@ -5,17 +5,16 @@ pub use self::root::mozilla::*;
 pub use self::root::mozilla::css::*;
 pub use self::root::mozilla::dom::*;
 use atomic_refcell::AtomicRefCell;
 use data::ElementData;
 pub type ServoUnsafeCell<T> = ::std::cell::UnsafeCell<T>;
 pub type ServoCell<T> = ::std::cell::Cell<T>;
 pub type ServoNodeData = AtomicRefCell<ElementData>;
 pub type ServoWritingMode = ::logical_geometry::WritingMode;
-pub type ServoFontComputationData = ::properties::FontComputationData;
 pub type ServoCustomPropertiesMap = Option<::servo_arc::Arc<::custom_properties::CustomPropertiesMap>>;
 pub type ServoRuleNode = Option<::rule_tree::StrongRuleNode>;
 pub type ServoVisitedStyle = Option<::servo_arc::RawOffsetArc<::properties::ComputedValues>>;
 pub type ServoComputedValueFlags = ::properties::computed_value_flags::ComputedValueFlags;
 pub type ServoRawOffsetArc<T> = ::servo_arc::RawOffsetArc<T>;
 pub type ServoStyleContextStrong = ::gecko_bindings::sugar::ownership::Strong<::properties::ComputedValues>;
 
 #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
@@ -4378,41 +4377,28 @@ pub mod root {
         pub type ParsingMode = u8;
         #[repr(i32)]
         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
         pub enum InheritTarget {
             Text = 0,
             FirstLetterContinuation = 1,
             PlaceholderFrame = 2,
         }
-        #[repr(u32)]
-        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-        pub enum ServoKeywordSize {
-            Empty = 0,
-            XXSmall = 1,
-            XSmall = 2,
-            Small = 3,
-            Medium = 4,
-            Large = 5,
-            XLarge = 6,
-            XXLarge = 7,
-            XXXLarge = 8,
-        }
         #[repr(C)]
         #[derive(Debug)]
         pub struct ServoStyleContext {
             pub _base: root::nsStyleContext,
             pub mPresContext: *mut root::nsPresContext,
             pub mSource: root::ServoComputedData,
             pub mNextInheritingAnonBoxStyle: root::RefPtr<root::mozilla::ServoStyleContext>,
             pub mNextLazyPseudoStyle: root::RefPtr<root::mozilla::ServoStyleContext>,
         }
         #[test]
         fn bindgen_test_layout_ServoStyleContext() {
-            assert_eq!(::std::mem::size_of::<ServoStyleContext>() , 272usize ,
+            assert_eq!(::std::mem::size_of::<ServoStyleContext>() , 256usize ,
                        concat ! (
                        "Size of: " , stringify ! ( ServoStyleContext ) ));
             assert_eq! (::std::mem::align_of::<ServoStyleContext>() , 8usize ,
                         concat ! (
                         "Alignment of " , stringify ! ( ServoStyleContext )
                         ));
             assert_eq! (unsafe {
                         & ( * ( 0 as * const ServoStyleContext ) ) .
@@ -4425,24 +4411,24 @@ pub mod root {
                         & ( * ( 0 as * const ServoStyleContext ) ) . mSource
                         as * const _ as usize } , 24usize , concat ! (
                         "Alignment of field: " , stringify ! (
                         ServoStyleContext ) , "::" , stringify ! ( mSource )
                         ));
             assert_eq! (unsafe {
                         & ( * ( 0 as * const ServoStyleContext ) ) .
                         mNextInheritingAnonBoxStyle as * const _ as usize } ,
-                        256usize , concat ! (
+                        240usize , concat ! (
                         "Alignment of field: " , stringify ! (
                         ServoStyleContext ) , "::" , stringify ! (
                         mNextInheritingAnonBoxStyle ) ));
             assert_eq! (unsafe {
                         & ( * ( 0 as * const ServoStyleContext ) ) .
                         mNextLazyPseudoStyle as * const _ as usize } ,
-                        264usize , concat ! (
+                        248usize , concat ! (
                         "Alignment of field: " , stringify ! (
                         ServoStyleContext ) , "::" , stringify ! (
                         mNextLazyPseudoStyle ) ));
         }
         #[repr(C)]
         #[derive(Debug)]
         pub struct GeckoFont {
             pub gecko: root::nsStyleFont,
@@ -14670,21 +14656,20 @@ pub mod root {
         /// The rule node representing the ordered list of rules matched for this
         /// /// node.  Can be None for default values and text nodes.  This is
         /// /// essentially an optimization to avoid referencing the root rule node.
         pub rules: ::gecko_bindings::structs::ServoRuleNode,
         /// The element's computed values if visited, only computed if there's a
         /// /// relevant link for this element. A element's "relevant link" is the
         /// /// element being matched if it is a link or the nearest ancestor link.
         pub visited_style: ::gecko_bindings::structs::ServoVisitedStyle,
-        pub font_computation_data: ::gecko_bindings::structs::ServoFontComputationData,
     }
     #[test]
     fn bindgen_test_layout_ServoComputedData() {
-        assert_eq!(::std::mem::size_of::<ServoComputedData>() , 232usize ,
+        assert_eq!(::std::mem::size_of::<ServoComputedData>() , 216usize ,
                    concat ! ( "Size of: " , stringify ! ( ServoComputedData )
                    ));
         assert_eq! (::std::mem::align_of::<ServoComputedData>() , 8usize ,
                     concat ! (
                     "Alignment of " , stringify ! ( ServoComputedData ) ));
         assert_eq! (unsafe {
                     & ( * ( 0 as * const ServoComputedData ) ) . Font as *
                     const _ as usize } , 0usize , concat ! (
@@ -14821,22 +14806,16 @@ pub mod root {
                     const _ as usize } , 200usize , concat ! (
                     "Alignment of field: " , stringify ! ( ServoComputedData )
                     , "::" , stringify ! ( rules ) ));
         assert_eq! (unsafe {
                     & ( * ( 0 as * const ServoComputedData ) ) . visited_style
                     as * const _ as usize } , 208usize , concat ! (
                     "Alignment of field: " , stringify ! ( ServoComputedData )
                     , "::" , stringify ! ( visited_style ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const ServoComputedData ) ) .
-                    font_computation_data as * const _ as usize } , 216usize ,
-                    concat ! (
-                    "Alignment of field: " , stringify ! ( ServoComputedData )
-                    , "::" , stringify ! ( font_computation_data ) ));
     }
     #[repr(u32)]
     #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
     pub enum JSValueTag {
         JSVAL_TAG_MAX_DOUBLE = 131056,
         JSVAL_TAG_INT32 = 131057,
         JSVAL_TAG_UNDEFINED = 131058,
         JSVAL_TAG_NULL = 131059,
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -48,17 +48,17 @@ use gecko_bindings::sugar::ns_style_coor
 use gecko::values::convert_nscolor_to_rgba;
 use gecko::values::convert_rgba_to_nscolor;
 use gecko::values::GeckoStyleCoordConvertible;
 use gecko::values::round_border_to_device_pixels;
 use logical_geometry::WritingMode;
 use media_queries::Device;
 use properties::animated_properties::TransitionProperty;
 use properties::computed_value_flags::*;
-use properties::{default_font_size_keyword, longhands, FontComputationData, Importance, LonghandId};
+use properties::{longhands, Importance, LonghandId};
 use properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyDeclarationId};
 use rule_tree::StrongRuleNode;
 use selector_parser::PseudoElement;
 use servo_arc::{Arc, RawOffsetArc};
 use std::mem::{forget, uninitialized, transmute, zeroed};
 use std::{cmp, ops, ptr};
 use values::{self, Auto, CustomIdent, Either, KeyframesName, None_};
 use values::computed::{NonNegativeLength, ToComputedValue, Percentage};
@@ -80,28 +80,26 @@ pub struct ComputedValues(::gecko_bindin
 
 impl ComputedValues {
     pub fn new(
         device: &Device,
         parent: Option<<&ComputedValues>,
         pseudo: Option<<&PseudoElement>,
         custom_properties: Option<Arc<CustomPropertiesMap>>,
         writing_mode: WritingMode,
-        font_size_keyword: FontComputationData,
         flags: ComputedValueFlags,
         rules: Option<StrongRuleNode>,
         visited_style: Option<Arc<ComputedValues>>,
         % for style_struct in data.style_structs:
         ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
         % endfor
     ) -> Arc<Self> {
         ComputedValuesInner::new(
             custom_properties,
             writing_mode,
-            font_size_keyword,
             flags,
             rules,
             visited_style,
             % for style_struct in data.style_structs:
             ${style_struct.ident},
             % endfor
         ).to_outer(
             device.pres_context(),
@@ -109,17 +107,16 @@ impl ComputedValues {
             pseudo.map(|p| p.pseudo_info())
         )
     }
 
     pub fn default_values(pres_context: RawGeckoPresContextBorrowed) -> Arc<Self> {
         ComputedValuesInner::new(
             /* custom_properties = */ None,
             /* writing_mode = */ WritingMode::empty(), // FIXME(bz): This seems dubious
-            default_font_size_keyword(),
             ComputedValueFlags::empty(),
             /* rules = */ None,
             /* visited_style = */ None,
             % for style_struct in data.style_structs:
             style_structs::${style_struct.name}::default(pres_context),
             % endfor
         ).to_outer(pres_context, None, None)
     }
@@ -169,42 +166,39 @@ impl Clone for ComputedValues {
 impl Clone for ComputedValuesInner {
     fn clone(&self) -> Self {
         ComputedValuesInner {
             % for style_struct in data.style_structs:
                 ${style_struct.gecko_name}: self.${style_struct.gecko_name}.clone(),
             % endfor
             custom_properties: self.custom_properties.clone(),
             writing_mode: self.writing_mode.clone(),
-            font_computation_data: self.font_computation_data.clone(),
             flags: self.flags.clone(),
             rules: self.rules.clone(),
             visited_style: self.visited_style.clone(),
         }
     }
 }
 
 type PseudoInfo = (*mut structs::nsIAtom, structs::CSSPseudoElementType);
 type ParentStyleContextInfo<'a> = Option< &'a ComputedValues>;
 
 impl ComputedValuesInner {
     pub fn new(custom_properties: Option<Arc<CustomPropertiesMap>>,
                writing_mode: WritingMode,
-               font_size_keyword: FontComputationData,
                flags: ComputedValueFlags,
                rules: Option<StrongRuleNode>,
                visited_style: Option<Arc<ComputedValues>>,
                % for style_struct in data.style_structs:
                ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
                % endfor
     ) -> Self {
         ComputedValuesInner {
             custom_properties: custom_properties,
             writing_mode: writing_mode,
-            font_computation_data: font_size_keyword,
             rules: rules,
             visited_style: visited_style.map(|x| Arc::into_raw_offset(x)),
             flags: flags,
             % for style_struct in data.style_structs:
             ${style_struct.gecko_name}: Arc::into_raw_offset(${style_struct.ident}),
             % endfor
         }
     }
@@ -2317,21 +2311,19 @@ fn static_assert() {
             (cmp::min(new_size, cmp::max(new_unconstrained_size, min)),
              new_unconstrained_size)
         }
     }
 
     /// This function will also handle scriptminsize and scriptlevel
     /// so should not be called when you just want the font sizes to be copied.
     /// Hence the different name.
-    ///
-    /// Returns true if the inherited keyword size was actually used
     pub fn inherit_font_size_from(&mut self, parent: &Self,
                                   kw_inherited_size: Option<NonNegativeLength>,
-                                  device: &Device) -> bool {
+                                  device: &Device) {
         let (adjusted_size, adjusted_unconstrained_size)
             = self.calculate_script_level_size(parent, device);
         if adjusted_size.0 != parent.gecko.mSize ||
            adjusted_unconstrained_size.0 != parent.gecko.mScriptUnconstrainedSize {
             // This is incorrect. When there is both a keyword size being inherited
             // and a scriptlevel change, we must handle the keyword size the same
             // way we handle em units. This complicates things because we now have
             // to keep track of the adjusted and unadjusted ratios in the kw font size.
@@ -2350,41 +2342,36 @@ fn static_assert() {
             // Technically the MathML constrained size may also be keyword-derived
             // but we ignore this since it would be too complicated
             // to correctly track and it's mostly unnecessary.
             self.gecko.mFontSizeKeyword = structs::NS_STYLE_FONT_SIZE_NO_KEYWORD as u8;
             self.gecko.mFontSizeFactor = 1.;
             self.gecko.mFontSizeOffset = 0;
 
             self.gecko.mScriptUnconstrainedSize = adjusted_unconstrained_size.0;
-            self.fixup_font_min_size(device);
-            false
         } else if let Some(size) = kw_inherited_size {
             // Parent element was a keyword-derived size.
             self.gecko.mSize = size.0.to_i32_au();
             // Copy keyword info over.
             self.gecko.mFontSizeFactor = parent.gecko.mFontSizeFactor;
             self.gecko.mFontSizeOffset = parent.gecko.mFontSizeOffset;
             self.gecko.mFontSizeKeyword = parent.gecko.mFontSizeKeyword;
             // MathML constraints didn't apply here, so we can ignore this.
             self.gecko.mScriptUnconstrainedSize = size.0.to_i32_au();
-            self.fixup_font_min_size(device);
-            true
         } else {
             // MathML isn't affecting us, and our parent element does not
             // have a keyword-derived size. Set things normally.
             self.gecko.mSize = parent.gecko.mSize;
             // copy keyword info over
             self.gecko.mFontSizeKeyword = structs::NS_STYLE_FONT_SIZE_NO_KEYWORD as u8;
             self.gecko.mFontSizeFactor = 1.;
             self.gecko.mFontSizeOffset = 0;
             self.gecko.mScriptUnconstrainedSize = parent.gecko.mScriptUnconstrainedSize;
-            self.fixup_font_min_size(device);
-            false
-        }
+        }
+        self.fixup_font_min_size(device);
     }
 
     pub fn clone_font_size(&self) -> longhands::font_size::computed_value::T {
         use self::longhands::font_size::KeywordSize;
         let size = Au(self.gecko.mSize).into();
         let kw = match self.gecko.mFontSizeKeyword as u32 {
             structs::NS_STYLE_FONT_SIZE_XXSMALL => KeywordSize::XXSmall,
             structs::NS_STYLE_FONT_SIZE_XSMALL => KeywordSize::XSmall,
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -600,17 +600,17 @@ macro_rules! impl_gecko_keyword_conversi
                    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
                    allow_quirks="True" spec="https://drafts.csswg.org/css-fonts/#propdef-font-size">
     use app_units::Au;
     use properties::longhands::system_font::SystemFont;
     use std::fmt;
     use style_traits::ToCss;
     use values::FONT_MEDIUM_PX;
     use values::computed::NonNegativeLength;
-    use values::specified::{AllowQuirks, FontRelativeLength, LengthOrPercentage, NoCalcLength};
+    use values::specified::{AllowQuirks, LengthOrPercentage, NoCalcLength};
     use values::specified::length::FontBaseSize;
 
     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"),
@@ -856,72 +856,36 @@ macro_rules! impl_gecko_keyword_conversi
                 4 => Large,
                 5 => XLarge,
                 6 => XXLarge,
                 // If value is greater than 7, let it be 7.
                 _ => XXXLarge,
             }, 1., Au(0).into())
         }
 
-        /// If this value is specified as a ratio of the parent font (em units
-        /// or percent) return the ratio
-        pub fn as_font_ratio(&self, context: &Context) -> Option<(f32, NonNegativeLength)> {
-            match *self {
-                SpecifiedValue::Length(ref lop) => {
-                    match *lop {
-                        LengthOrPercentage::Percentage(pc) => {
-                            Some((pc.0, NonNegativeLength::zero()))
-                        }
-                        LengthOrPercentage::Length(ref nocalc) => {
-                            match *nocalc {
-                                NoCalcLength::FontRelative(FontRelativeLength::Em(em)) => {
-                                    Some((em, NonNegativeLength::zero()))
-                                }
-                                _ => None,
-                            }
-                        }
-                        LengthOrPercentage::Calc(ref calc) => {
-                            if calc.em.is_none() && calc.percentage.is_none() {
-                                return None;
-                            }
-                            let ratio = calc.em.unwrap_or(0.) + calc.percentage.map_or(0., |pc| pc.0);
-                            // Compute it, but shave off the font-relative part (em, %)
-                            // This will mean that other font-relative units like ex and ch will be computed against
-                            // the old font even when the font changes. There's no particular "right answer" for what
-                            // to do here -- Gecko recascades as if the font had changed, we instead track the changes
-                            // and reapply, which means that we carry over old computed ex/ch values whilst Gecko
-                            // recomputes new ones. This is enough of an edge case to not really matter.
-                            let abs = calc.to_computed_value_zoomed(context, FontBaseSize::Custom(Au(0)))
-                                          .length_component().into();
-                            Some((ratio, abs))
-                        }
-                    }
-                }
-                SpecifiedValue::Larger => Some((LARGER_FONT_SIZE_RATIO, Au(0).into())),
-                SpecifiedValue::Smaller => Some((1. / LARGER_FONT_SIZE_RATIO, Au(0).into())),
-                _ => None,
-            }
-        }
-
         /// Compute it against a given base font size
         pub fn to_computed_value_against(
             &self,
             context: &Context,
             base_size: FontBaseSize,
         ) -> computed_value::T {
             use values::specified::length::FontRelativeLength;
+            let compose_keyword = |factor| {
+                context.style().get_parent_font()
+                       .clone_font_size().info
+                       .map(|i| i.compose(factor, Au(0).into()))
+            };
             let mut info = None;
             let size = match *self {
                 SpecifiedValue::Length(LengthOrPercentage::Length(
                         NoCalcLength::FontRelative(value))) => {
                     if let FontRelativeLength::Em(em) = value {
                         // If the parent font was keyword-derived, this is too.
                         // Tack the em unit onto the factor
-                        info = context.style().get_parent_font()
-                                      .clone_font_size().info.map(|i| i.compose(em, Au(0).into()));
+                        info = compose_keyword(em);
                     }
                     value.to_computed_value(context, base_size).into()
                 }
                 SpecifiedValue::Length(LengthOrPercentage::Length(
                         NoCalcLength::ServoCharacterWidth(value))) => {
                     value.to_computed_value(base_size.resolve(context)).into()
                 }
                 SpecifiedValue::Length(LengthOrPercentage::Length(
@@ -929,17 +893,17 @@ macro_rules! impl_gecko_keyword_conversi
                     context.maybe_zoom_text(l.to_computed_value(context).into())
                 }
                 SpecifiedValue::Length(LengthOrPercentage::Length(ref l)) => {
                     l.to_computed_value(context).into()
                 }
                 SpecifiedValue::Length(LengthOrPercentage::Percentage(pc)) => {
                     // If the parent font was keyword-derived, this is too.
                     // Tack the % onto the factor
-                    info = context.style().get_parent_font().clone_font_size().info.map(|i| i.compose(pc.0, Au(0).into()));
+                    info = compose_keyword(pc.0);
                     base_size.resolve(context).scale_by(pc.0).into()
                 }
                 SpecifiedValue::Length(LengthOrPercentage::Calc(ref calc)) => {
                     let parent = context.style().get_parent_font().clone_font_size();
                     // if we contain em/% units and the parent was keyword derived, this is too
                     // Extract the ratio/offset and compose it
                     if (calc.em.is_some() || calc.percentage.is_some()) && parent.info.is_some() {
                         let ratio = calc.em.unwrap_or(0.) + calc.percentage.map_or(0., |pc| pc.0);
@@ -962,20 +926,22 @@ macro_rules! impl_gecko_keyword_conversi
                         kw: key,
                         factor: fraction,
                         offset: offset,
                     });
                     let key_len = key.to_computed_value(context).scale_by(fraction) + offset;
                     context.maybe_zoom_text(key_len).into()
                 }
                 SpecifiedValue::Smaller => {
+                    info = compose_keyword(1. / LARGER_FONT_SIZE_RATIO);
                     FontRelativeLength::Em(1. / LARGER_FONT_SIZE_RATIO)
                         .to_computed_value(context, base_size).into()
                 }
                 SpecifiedValue::Larger => {
+                    info = compose_keyword(LARGER_FONT_SIZE_RATIO);
                     FontRelativeLength::Em(LARGER_FONT_SIZE_RATIO)
                         .to_computed_value(context, base_size).into()
                 }
 
                 SpecifiedValue::System(_) => {
                     <%self:nongecko_unreachable>
                         context.cached_system_font.as_ref().unwrap().font_size.size
                     </%self:nongecko_unreachable>
@@ -1058,55 +1024,29 @@ macro_rules! impl_gecko_keyword_conversi
             }
         }
     }
 
     #[allow(unused_mut)]
     pub fn cascade_specified_font_size(context: &mut Context,
                                        specified_value: &SpecifiedValue,
                                        mut computed: computed_value::T) {
-        if let SpecifiedValue::Keyword(kw, fraction, offset) = *specified_value {
-            context.builder.font_size_keyword = Some((kw, fraction, offset));
-        } else if let Some((ratio, abs)) = specified_value.as_font_ratio(context) {
-            // In case a font-size-relative value was applied to a keyword
-            // value, we must preserve this fact in case the generic font family
-            // changes. relative values (em and %) applied to keywords must be
-            // recomputed from the base size for the keyword and the relative size.
-            //
-            // See bug 1355707
-            if let Some((kw, fraction, old_abs)) = *context.builder.inherited_font_computation_data() {
-                context.builder.font_size_keyword =
-                    Some((kw, fraction * ratio, abs + old_abs.scale_by(ratio)));
-            } else {
-                context.builder.font_size_keyword = None;
-            }
-        } else {
-            context.builder.font_size_keyword = None;
-        }
-
         // we could use clone_language and clone_font_family() here but that's
         // expensive. Do it only in gecko mode for now.
         % if product == "gecko":
             use gecko_bindings::structs::nsIAtom;
             // if the language or generic changed, we need to recalculate
             // the font size from the stored font-size origin information.
             if context.builder.get_font().gecko().mLanguage.raw::<nsIAtom>() !=
                context.builder.get_parent_font().gecko().mLanguage.raw::<nsIAtom>() ||
                context.builder.get_font().gecko().mGenericID !=
                context.builder.get_parent_font().gecko().mGenericID {
-                if let Some((kw, ratio, offset)) = context.builder.font_size_keyword {
-                    let len = context.maybe_zoom_text(kw.to_computed_value(context).scale_by(ratio) + offset);
-                    computed = computed_value::T {
-                        size: len,
-                        info: Some(computed_value::KeywordInfo {
-                            kw: kw,
-                            factor: ratio,
-                            offset: offset
-                        }),
-                    }
+                if let Some(info) = computed.info {
+                    computed.size = context.maybe_zoom_text(info.kw.to_computed_value(context)
+                                                                .scale_by(info.factor) + info.offset)
                 }
             }
         % endif
 
         let device = context.builder.device;
         let mut font = context.builder.take_font();
         let parent_unconstrained = {
             let parent_font = context.builder.get_parent_font();
@@ -1125,31 +1065,27 @@ macro_rules! impl_gecko_keyword_conversi
     }
 
     /// FIXME(emilio): This is very complex. Also, it should move to
     /// StyleBuilder.
     pub fn cascade_inherit_font_size(context: &mut Context) {
         // If inheriting, we must recompute font-size in case of language
         // changes using the font_size_keyword. We also need to do this to
         // handle mathml scriptlevel changes
-        let kw_inherited_size = context.builder.font_size_keyword.map(|(kw, ratio, offset)| {
-            context.maybe_zoom_text(SpecifiedValue::Keyword(kw, ratio, offset).to_computed_value(context).size)
+        let kw_inherited_size = context.builder.get_parent_font()
+                                       .clone_font_size()
+                                       .info.map(|info| {
+            context.maybe_zoom_text(SpecifiedValue::Keyword(info.kw, info.factor, info.offset)
+                  .to_computed_value(context).size)
         });
-        let parent_kw;
-        let device = context.builder.device;
         let mut font = context.builder.take_font();
-        let used_kw = {
-            let parent_font = context.builder.get_parent_font();
-            parent_kw = *context.builder.inherited_font_computation_data();
-
-            font.inherit_font_size_from(parent_font, kw_inherited_size, device)
-        };
+        font.inherit_font_size_from(context.builder.get_parent_font(),
+                                    kw_inherited_size,
+                                    context.builder.device);
         context.builder.put_font(font);
-        context.builder.font_size_keyword =
-            if used_kw { parent_kw } else { None };
     }
 
     /// Cascade the initial value for the `font-size` property.
     ///
     /// FIXME(emilio): This is the only function that is outside of the
     /// `StyleBuilder`, and should really move inside!
     ///
     /// Can we move the font stuff there?
@@ -1159,17 +1095,16 @@ macro_rules! impl_gecko_keyword_conversi
         let mut computed = longhands::font_size::get_initial_specified_value()
                                             .to_computed_value(context);
         computed.size = context.maybe_zoom_text(computed.size);
         context.builder.mutate_font().set_font_size(computed);
         % if product == "gecko":
             let device = context.builder.device;
             context.builder.mutate_font().fixup_font_min_size(device);
         % endif
-        context.builder.font_size_keyword = Some((Default::default(), 1., Au(0).into()));
     }
 </%helpers:longhand>
 
 <%helpers:longhand products="gecko" name="font-size-adjust"
                    animation_value_type="longhands::font_size_adjust::computed_value::T"
                    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
                    spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust">
     use properties::longhands::system_font::SystemFont;
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -5,16 +5,17 @@
 // This file is a Mako template: http://www.makotemplates.org/
 
 // Please note that valid Rust syntax may be mangled by the Mako parser.
 // For example, Vec<&Foo> will be mangled as Vec&Foo>. To work around these issues, the code
 // can be escaped. In the above example, Vec<<&Foo> or Vec< &Foo> achieves the desired result of Vec<&Foo>.
 
 <%namespace name="helpers" file="/helpers.mako.rs" />
 
+#[cfg(feature = "servo")]
 use app_units::Au;
 use servo_arc::{Arc, UniqueArc};
 use smallbitvec::SmallBitVec;
 use std::borrow::Cow;
 use hash::HashSet;
 use std::{fmt, mem, ops};
 use std::cell::RefCell;
 #[cfg(feature = "gecko")] use std::ptr;
@@ -87,42 +88,16 @@ pub mod computed_value_flags;
 pub mod declaration_block;
 
 /// Conversion with fewer impls than From/Into
 pub trait MaybeBoxed<Out> {
     /// Convert
     fn maybe_boxed(self) -> Out;
 }
 
-
-/// This is where we store extra font data while
-/// while computing font sizes.
-///
-/// font-size keyword values (and font-size-relative values applied
-/// to keyword values) need to preserve their identity as originating
-/// from keywords and relative font sizes. We store this information
-/// out of band in the ComputedValues. When None, the font size on the
-/// current struct was computed from a value that was not a keyword
-/// or a chain of font-size-relative values applying to successive parents
-/// terminated by a keyword. When Some, this means the font-size was derived
-/// from a keyword value or a keyword value on some ancestor with only
-/// font-size-relative keywords and regular inheritance in between. The
-/// integer stores the final ratio of the chain of font size relative values.
-/// and is 1 when there was just a keyword and no relative values.
-///
-/// When this is Some, we compute font sizes by computing the keyword against
-/// the generic font, and then multiplying it by the ratio (as well as adding any
-/// absolute offset from calcs)
-pub type FontComputationData = Option<(longhands::font_size::KeywordSize, f32, NonNegativeLength)>;
-
-/// Default value for FontComputationData
-pub fn default_font_size_keyword() -> FontComputationData {
-    Some((Default::default(), 1., Au(0).into()))
-}
-
 impl<T> MaybeBoxed<T> for T {
     #[inline]
     fn maybe_boxed(self) -> T { self }
 }
 
 impl<T> MaybeBoxed<Box<T>> for T {
     #[inline]
     fn maybe_boxed(self) -> Box<T> { Box::new(self) }
@@ -1840,19 +1815,18 @@ pub mod style_structs {
                     self.font_stretch.hash(&mut hasher);
                     self.font_family.hash(&mut hasher);
                     self.hash = hasher.finish()
                 }
 
                 /// (Servo does not handle MathML, so this just calls copy_font_size_from)
                 pub fn inherit_font_size_from(&mut self, parent: &Self,
                                               _: Option<NonNegativeLength>,
-                                              _: &Device) -> bool {
+                                              _: &Device) {
                     self.copy_font_size_from(parent);
-                    false
                 }
                 /// (Servo does not handle MathML, so this just calls set_font_size)
                 pub fn apply_font_size(&mut self,
                                        v: longhands::font_size::computed_value::T,
                                        _: &Self,
                                        _: &Device) -> Option<NonNegativeLength> {
                     self.set_font_size(v);
                     None
@@ -1980,19 +1954,16 @@ pub use gecko_properties::{ComputedValue
 pub struct ComputedValuesInner {
     % for style_struct in data.active_style_structs():
         ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
     % endfor
     custom_properties: Option<Arc<::custom_properties::CustomPropertiesMap>>,
     /// The writing mode of this computed values struct.
     pub writing_mode: WritingMode,
 
-    /// The keyword behind the current font-size property, if any
-    pub font_computation_data: FontComputationData,
-
     /// A set of flags we use to store misc information regarding this style.
     pub flags: ComputedValueFlags,
 
     /// The rule node representing the ordered list of rules matched for this
     /// node.  Can be None for default values and text nodes.  This is
     /// essentially an optimization to avoid referencing the root rule node.
     pub rules: Option<StrongRuleNode>,
 
@@ -2038,29 +2009,27 @@ impl ComputedValues {
 impl ComputedValues {
     /// Create a new refcounted `ComputedValues`
     pub fn new(
         _: &Device,
         _: Option<<&ComputedValues>,
         _: Option<<&PseudoElement>,
         custom_properties: Option<Arc<::custom_properties::CustomPropertiesMap>>,
         writing_mode: WritingMode,
-        font_size_keyword: FontComputationData,
         flags: ComputedValueFlags,
         rules: Option<StrongRuleNode>,
         visited_style: Option<Arc<ComputedValues>>,
         % for style_struct in data.active_style_structs():
         ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
         % endfor
     ) -> Arc<Self> {
         Arc::new(Self {
             inner: ComputedValuesInner::new(
                 custom_properties,
                 writing_mode,
-                font_size_keyword,
                 flags,
                 rules,
                 visited_style,
                 % for style_struct in data.active_style_structs():
                 ${style_struct.ident},
                 % endfor
             )
         })
@@ -2071,28 +2040,26 @@ impl ComputedValues {
 }
 
 #[cfg(feature = "servo")]
 impl ComputedValuesInner {
     /// Construct a `ComputedValuesInner` instance.
     pub fn new(
         custom_properties: Option<Arc<::custom_properties::CustomPropertiesMap>>,
         writing_mode: WritingMode,
-        font_size_keyword: FontComputationData,
         flags: ComputedValueFlags,
         rules: Option<StrongRuleNode>,
         visited_style: Option<Arc<ComputedValues>>,
         % for style_struct in data.active_style_structs():
         ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
         % endfor
     ) -> Self {
         ComputedValuesInner {
             custom_properties: custom_properties,
             writing_mode: writing_mode,
-            font_computation_data: font_size_keyword,
             rules: rules,
             visited_style: visited_style,
             flags: flags,
         % for style_struct in data.active_style_structs():
             ${style_struct.ident}: ${style_struct.ident},
         % endfor
         }
     }
@@ -2604,18 +2571,16 @@ pub struct StyleBuilder<'a> {
     /// `clear_modified_reset` was called.  This is used to tell whether the
     /// `StyleAdjuster` did any work.
     modified_reset: bool,
 
     /// The writing mode flags.
     ///
     /// TODO(emilio): Make private.
     pub writing_mode: WritingMode,
-    /// The keyword behind the current font-size property, if any.
-    pub font_size_keyword: FontComputationData,
     /// Flags for the computed value.
     pub flags: ComputedValueFlags,
     /// The element's style if visited, only computed if there's a relevant link
     /// for this element.  A element's "relevant link" is the element being
     /// matched if it is a link or the nearest ancestor link.
     visited_style: Option<Arc<ComputedValues>>,
     % for style_struct in data.active_style_structs():
         ${style_struct.ident}: StyleStructRef<'a, style_structs::${style_struct.name}>,
@@ -2628,17 +2593,16 @@ impl<'a> StyleBuilder<'a> {
         device: &'a Device,
         parent_style: Option<<&'a ComputedValues>,
         parent_style_ignoring_first_line: Option<<&'a ComputedValues>,
         pseudo: Option<<&'a PseudoElement>,
         cascade_flags: CascadeFlags,
         rules: Option<StrongRuleNode>,
         custom_properties: Option<Arc<::custom_properties::CustomPropertiesMap>>,
         writing_mode: WritingMode,
-        font_size_keyword: FontComputationData,
         mut flags: ComputedValueFlags,
         visited_style: Option<Arc<ComputedValues>>,
     ) -> Self {
         debug_assert_eq!(parent_style.is_some(), parent_style_ignoring_first_line.is_some());
         #[cfg(feature = "gecko")]
         debug_assert!(parent_style.is_none() ||
                       ptr::eq(parent_style.unwrap(),
                               parent_style_ignoring_first_line.unwrap()) ||
@@ -2666,17 +2630,16 @@ impl<'a> StyleBuilder<'a> {
             inherited_style,
             inherited_style_ignoring_first_line,
             reset_style,
             pseudo,
             rules,
             modified_reset: false,
             custom_properties,
             writing_mode,
-            font_size_keyword,
             flags,
             visited_style,
             % for style_struct in data.active_style_structs():
             % if style_struct.inherited:
             ${style_struct.ident}: StyleStructRef::Borrowed(inherited_style.${style_struct.name_lower}_arc()),
             % else:
             ${style_struct.ident}: StyleStructRef::Borrowed(reset_style.${style_struct.name_lower}_arc()),
             % endif
@@ -2709,17 +2672,16 @@ impl<'a> StyleBuilder<'a> {
             // None of our callers pass in ::first-line parent styles.
             inherited_style_ignoring_first_line: inherited_style,
             reset_style,
             pseudo,
             modified_reset: false,
             rules: None, // FIXME(emilio): Dubious...
             custom_properties: style_to_derive_from.custom_properties(),
             writing_mode: style_to_derive_from.writing_mode,
-            font_size_keyword: style_to_derive_from.font_computation_data,
             flags: style_to_derive_from.flags,
             visited_style: style_to_derive_from.clone_visited_style(),
             % for style_struct in data.active_style_structs():
             ${style_struct.ident}: StyleStructRef::Borrowed(
                 style_to_derive_from.${style_struct.name_lower}_arc()
             ),
             % endfor
         }
@@ -2829,17 +2791,16 @@ impl<'a> StyleBuilder<'a> {
             device,
             Some(parent),
             Some(parent),
             pseudo,
             CascadeFlags::empty(),
             /* rules = */ None,
             parent.custom_properties(),
             parent.writing_mode,
-            parent.font_computation_data,
             parent.flags,
             parent.clone_visited_style()
         )
     }
 
     /// Returns whether we have a visited style.
     pub fn has_visited_style(&self) -> bool {
         self.visited_style.is_some()
@@ -2936,17 +2897,16 @@ impl<'a> StyleBuilder<'a> {
     /// Turns this `StyleBuilder` into a proper `ComputedValues` instance.
     pub fn build(self) -> Arc<ComputedValues> {
         ComputedValues::new(
             self.device,
             self.parent_style,
             self.pseudo,
             self.custom_properties,
             self.writing_mode,
-            self.font_size_keyword,
             self.flags,
             self.rules,
             self.visited_style,
             % for style_struct in data.active_style_structs():
             self.${style_struct.ident}.build(),
             % endfor
         )
     }
@@ -2959,21 +2919,16 @@ impl<'a> StyleBuilder<'a> {
         self.custom_properties.clone()
     }
 
     /// Access to various information about our inherited styles.  We don't
     /// expose an inherited ComputedValues directly, because in the
     /// ::first-line case some of the inherited information needs to come from
     /// one ComputedValues instance and some from a different one.
 
-    /// Inherited font bits.
-    pub fn inherited_font_computation_data(&self) -> &FontComputationData {
-        &self.inherited_style.font_computation_data
-    }
-
     /// Inherited writing-mode.
     pub fn inherited_writing_mode(&self) -> &WritingMode {
         &self.inherited_style.writing_mode
     }
 
     /// Inherited style flags.
     pub fn inherited_flags(&self) -> &ComputedValueFlags {
         &self.inherited_style.flags
@@ -3001,17 +2956,16 @@ pub use self::lazy_static_module::INITIA
 
 // Use a module to work around #[cfg] on lazy_static! not being applied to every generated item.
 #[cfg(feature = "servo")]
 #[allow(missing_docs)]
 mod lazy_static_module {
     use logical_geometry::WritingMode;
     use servo_arc::Arc;
     use super::{ComputedValues, ComputedValuesInner, longhands, style_structs};
-    use super::default_font_size_keyword;
     use super::computed_value_flags::ComputedValueFlags;
 
     /// The initial values for all style structs as defined by the specification.
     lazy_static! {
         pub static ref INITIAL_SERVO_VALUES: ComputedValues = ComputedValues {
             inner: ComputedValuesInner {
                 % for style_struct in data.active_style_structs():
                     ${style_struct.ident}: Arc::new(style_structs::${style_struct.name} {
@@ -3020,17 +2974,16 @@ mod lazy_static_module {
                         % endfor
                         % if style_struct.name == "Font":
                             hash: 0,
                         % endif
                     }),
                 % endfor
                 custom_properties: None,
                 writing_mode: WritingMode::empty(),
-                font_computation_data: default_font_size_keyword(),
                 rules: None,
                 visited_style: None,
                 flags: ComputedValueFlags::empty(),
             }
         };
     }
 }
 
@@ -3247,17 +3200,16 @@ where
             device,
             parent_style,
             parent_style_ignoring_first_line,
             pseudo,
             flags,
             Some(rules.clone()),
             custom_properties,
             WritingMode::empty(),
-            inherited_style.font_computation_data,
             ComputedValueFlags::empty(),
             visited_style,
         ),
         cached_system_font: None,
         in_media_query: false,
         for_smil_animation: false,
         for_non_inherited_property: None,
         font_metrics_provider,