Bug 1349417 - Part 4: stylo: System font support for font-weight; r?xidorn draft
authorManish Goregaokar <manishearth@gmail.com>
Tue, 21 Mar 2017 20:38:12 -0700
changeset 564172 feb1cd187b7d8af415057ed36ac3971178a4c4bd
parent 564171 960d40b060d8d8b00cb43f01a440123c4951289b
child 564173 acd8ac848e495b529bcb9f7c8855f4c79bd7f339
push id54548
push userbmo:manishearth@gmail.com
push dateTue, 18 Apr 2017 10:18:30 +0000
reviewersxidorn
bugs1349417
milestone55.0a1
Bug 1349417 - Part 4: stylo: System font support for font-weight; r?xidorn MozReview-Commit-ID: 1L55bqGnpCs
servo/components/style/properties/data.py
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/longhand/font.mako.rs
servo/components/style/properties/shorthand/font.mako.rs
--- a/servo/components/style/properties/data.py
+++ b/servo/components/style/properties/data.py
@@ -10,17 +10,17 @@ PHYSICAL_SIZES = ["width", "height"]
 LOGICAL_SIZES = ["block-size", "inline-size"]
 
 # bool is True when logical
 ALL_SIDES = [(side, False) for side in PHYSICAL_SIDES] + [(side, True) for side in LOGICAL_SIDES]
 ALL_SIZES = [(size, False) for size in PHYSICAL_SIZES] + [(size, True) for size in LOGICAL_SIZES]
 
 SYSTEM_FONT_LONGHANDS = """font_family font_size font_style
                            font_variant_caps font_stretch font_kerning
-                           font_variant_position""".split()
+                           font_variant_position font_weight""".split()
 
 def maybe_moz_logical_alias(product, side, prop):
     if product == "gecko" and side[1]:
         axis, dir = side[0].split("-")
         if axis == "inline":
             return prop % dir
     return None
 
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -1364,20 +1364,17 @@ fn static_assert() {
     }
 
     pub fn set_font_weight(&mut self, v: longhands::font_weight::computed_value::T) {
         self.gecko.mFont.weight = v as u16;
     }
     ${impl_simple_copy('font_weight', 'mFont.weight')}
 
     pub fn clone_font_weight(&self) -> longhands::font_weight::computed_value::T {
-        debug_assert!(self.gecko.mFont.weight >= 100);
-        debug_assert!(self.gecko.mFont.weight <= 900);
-        debug_assert!(self.gecko.mFont.weight % 10 == 0);
-        unsafe { transmute(self.gecko.mFont.weight) }
+        unsafe { longhands::font_weight::computed_value::T::from_gecko_weight(self.gecko.mFont.weight) }
     }
 
     pub fn set_font_synthesis(&mut self, v: longhands::font_synthesis::computed_value::T) {
         use gecko_bindings::structs::{NS_FONT_SYNTHESIS_WEIGHT, NS_FONT_SYNTHESIS_STYLE};
 
         self.gecko.mFont.synthesis = 0;
         if v.weight {
             self.gecko.mFont.synthesis |= NS_FONT_SYNTHESIS_WEIGHT as u8;
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -305,44 +305,48 @@
                                custom_consts=font_variant_caps_custom_consts,
                                animation_type="none")}
 
 <%helpers:longhand name="font-weight" need_clone="True" animation_type="normal"
                    spec="https://drafts.csswg.org/css-fonts/#propdef-font-weight">
     use std::fmt;
     use style_traits::ToCss;
     use values::HasViewportPercentage;
+    use properties::longhands::system_font::SystemFont;
 
     no_viewport_percentage!(SpecifiedValue);
 
     #[derive(Debug, Clone, PartialEq, Eq, Copy)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     pub enum SpecifiedValue {
         Normal,
         Bold,
         Bolder,
         Lighter,
         % for weight in range(100, 901, 100):
             Weight${weight},
         % endfor
+        System(SystemFont),
     }
 
     impl ToCss for SpecifiedValue {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             match *self {
                 SpecifiedValue::Normal => dest.write_str("normal"),
                 SpecifiedValue::Bold => dest.write_str("bold"),
                 SpecifiedValue::Bolder => dest.write_str("bolder"),
                 SpecifiedValue::Lighter => dest.write_str("lighter"),
                 % for weight in range(100, 901, 100):
                     SpecifiedValue::Weight${weight} => dest.write_str("${weight}"),
                 % endfor
+                SpecifiedValue::System(_) => Ok(())
             }
         }
     }
+
     /// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
     pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
         input.try(|input| {
             match_ignore_ascii_case! { &try!(input.expect_ident()),
                 "normal" => Ok(SpecifiedValue::Normal),
                 "bold" => Ok(SpecifiedValue::Bold),
                 "bolder" => Ok(SpecifiedValue::Bolder),
                 "lighter" => Ok(SpecifiedValue::Lighter),
@@ -364,27 +368,41 @@
         }
 
         pub fn from_gecko_keyword(kw: u32) -> Self {
             Self::from_int(kw as i32).expect("Found unexpected value in style
                                               struct for font-weight property")
         }
     }
 
+    impl SpecifiedValue {
+        pub fn system_font(f: SystemFont) -> Self {
+            SpecifiedValue::System(f)
+        }
+        pub fn get_system(&self) -> Option<SystemFont> {
+            if let SpecifiedValue::System(s) = *self {
+                Some(s)
+            } else {
+                None
+            }
+        }
+    }
+
     /// Used in @font-face, where relative keywords are not allowed.
     impl Parse for computed_value::T {
         fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
             match parse(context, input)? {
                 % for weight in range(100, 901, 100):
                     SpecifiedValue::Weight${weight} => Ok(computed_value::T::Weight${weight}),
                 % endfor
                 SpecifiedValue::Normal => Ok(computed_value::T::Weight400),
                 SpecifiedValue::Bold => Ok(computed_value::T::Weight700),
                 SpecifiedValue::Bolder |
-                SpecifiedValue::Lighter => Err(())
+                SpecifiedValue::Lighter => Err(()),
+                SpecifiedValue::System(..) => unreachable!(),
             }
         }
     }
 
     pub mod computed_value {
         use std::fmt;
         #[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
@@ -398,16 +416,25 @@
             #[inline]
             pub fn is_bold(self) -> bool {
                 match self {
                     T::Weight900 | T::Weight800 |
                     T::Weight700 | T::Weight600 => true,
                     _ => false
                 }
             }
+
+            /// Obtain a Servo computed value from a Gecko computed font-weight
+            pub unsafe fn from_gecko_weight(weight: u16) -> Self {
+                use std::mem::transmute;
+                debug_assert!(weight >= 100);
+                debug_assert!(weight <= 900);
+                debug_assert!(weight % 10 == 0);
+                transmute(weight)
+            }
         }
     }
     impl ToCss for computed_value::T {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             match *self {
                 % for weight in range(100, 901, 100):
                     computed_value::T::Weight${weight} => dest.write_str("${weight}"),
                 % endfor
@@ -452,16 +479,21 @@
                     computed_value::T::Weight300 => computed_value::T::Weight100,
                     computed_value::T::Weight400 => computed_value::T::Weight100,
                     computed_value::T::Weight500 => computed_value::T::Weight100,
                     computed_value::T::Weight600 => computed_value::T::Weight400,
                     computed_value::T::Weight700 => computed_value::T::Weight400,
                     computed_value::T::Weight800 => computed_value::T::Weight700,
                     computed_value::T::Weight900 => computed_value::T::Weight700,
                 },
+                SpecifiedValue::System(_) => {
+                    <%self:nongecko_unreachable>
+                        context.style.cached_system_font.as_ref().unwrap().font_weight.clone()
+                    </%self:nongecko_unreachable>
+                }
             }
         }
 
         #[inline]
         fn from_computed_value(computed: &computed_value::T) -> Self {
             match *computed {
                 % for weight in range(100, 901, 100):
                     computed_value::T::Weight${weight} => SpecifiedValue::Weight${weight},
@@ -1929,19 +1961,23 @@ macro_rules! exclusive_value {
                 }
                 let family = system.fontlist.mFontlist.iter().map(|font| {
                     use properties::longhands::font_family::computed_value::*;
                     FontFamily::FamilyName(FamilyName {
                         name: (&*font.mName).into(),
                         quoted: true
                     })
                 }).collect::<Vec<_>>();
+                let weight = unsafe {
+                    longhands::font_weight::computed_value::T::from_gecko_weight(system.weight)
+                };
                 let ret = ComputedSystemFont {
                     font_family: longhands::font_family::computed_value::T(family),
                     font_size: Au(system.size),
+                    font_weight: weight,
                     % for kwprop in kw_font_props:
                         ${kwprop}: longhands::${kwprop}::computed_value::T::from_gecko_keyword(
                             system.${to_camel_case_lower(kwprop.replace('font_', ''))} as u32
                         ),
                     % endfor
                     system_font: *self,
                 };
                 unsafe { bindings::Gecko_nsFont_Destroy(&mut system); }
--- a/servo/components/style/properties/shorthand/font.mako.rs
+++ b/servo/components/style/properties/shorthand/font.mako.rs
@@ -41,17 +41,17 @@
         let mut stretch = None;
         let size;
         % if product == "gecko":
             if let Ok(sys) = input.try(SystemFont::parse) {
                 return Ok(Longhands {
                      % for name in SYSTEM_FONT_LONGHANDS:
                          ${name}: ${name}::SpecifiedValue::system_font(sys),
                      % endfor
-                     % for name in gecko_sub_properties + "weight variant_caps stretch".split():
+                     % for name in gecko_sub_properties + "variant_caps stretch".split():
                         % if "font_" + name not in SYSTEM_FONT_LONGHANDS:
                             font_${name}: font_${name}::get_initial_specified_value(),
                         % endif
                      % endfor
                      line_height: line_height::get_initial_specified_value(),
                  })
             }
         % endif