diff --git a/components/style/properties/data.py b/components/style/properties/data.py index 8bb1fc86988..5b18424ebee 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -127,6 +127,15 @@ class Keyword(object): def maybe_cast(self, type_str): return "as " + type_str if self.needs_cast() else "" + def casted_constant_name(self, value, cast_type): + if cast_type is None: + raise TypeError("We should specify the cast_type.") + + if self.gecko_enum_prefix is None: + return cast_type.upper() + "_" + self.gecko_constant(value) + else: + return cast_type.upper() + "_" + self.gecko_constant(value).upper().replace("::", "_") + def arg_to_bool(arg): if isinstance(arg, bool): diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 599605c23af..d398534b7fd 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -274,14 +274,25 @@ def set_gecko_property(ffi_name, expr): } -<%def name="impl_keyword_clone(ident, gecko_ffi_name, keyword)"> +<%def name="impl_keyword_clone(ident, gecko_ffi_name, keyword, cast_type='u8')"> #[allow(non_snake_case)] pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { use properties::longhands::${ident}::computed_value::T as Keyword; // FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts - match ${get_gecko_property(gecko_ffi_name)} ${keyword.maybe_cast("u32")} { + + // Some constant macros in the gecko are defined as negative integer(e.g. font-stretch). + // And they are convert to signed integer in Rust bindings. We need to cast then + // as signed type when we have both signed/unsigned integer in order to use them + // as match's arms. + // Also, to use same implementation here we use casted constant if we have only singed values. + % for value in keyword.values_for('gecko'): + const ${keyword.casted_constant_name(value, cast_type)} : ${cast_type} = + structs::${keyword.gecko_constant(value)} as ${cast_type}; + % endfor + + match ${get_gecko_property(gecko_ffi_name)} as ${cast_type} { % for value in keyword.values_for('gecko'): - structs::${keyword.gecko_constant(value)} => Keyword::${to_rust_ident(value)}, + ${keyword.casted_constant_name(value, cast_type)} => Keyword::${to_rust_ident(value)}, % endfor % if keyword.gecko_inexhaustive: x => panic!("Found unexpected value in style struct for ${ident} property: {:?}", x), @@ -334,11 +345,11 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { } -<%def name="impl_keyword(ident, gecko_ffi_name, keyword, need_clone, **kwargs)"> -<%call expr="impl_keyword_setter(ident, gecko_ffi_name, keyword, **kwargs)"> +<%def name="impl_keyword(ident, gecko_ffi_name, keyword, need_clone, cast_type='u8', **kwargs)"> +<%call expr="impl_keyword_setter(ident, gecko_ffi_name, keyword, cast_type, **kwargs)"> <%call expr="impl_simple_copy(ident, gecko_ffi_name)"> %if need_clone: -<%call expr="impl_keyword_clone(ident, gecko_ffi_name, keyword)"> +<%call expr="impl_keyword_clone(ident, gecko_ffi_name, keyword, cast_type)"> % endif @@ -2010,6 +2021,7 @@ fn static_assert() { "-moz-grid-group -moz-grid-line -moz-stack -moz-inline-stack -moz-deck " + "-moz-popup -moz-groupbox", gecko_enum_prefix="StyleDisplay", + gecko_inexhaustive="True", gecko_strip_moz_prefix=False) %> pub fn set_display(&mut self, v: longhands::display::computed_value::T) { diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 071454dd2ba..11fa3956a8a 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -17,6 +17,7 @@ use properties::{CSSWideKeyword, PropertyDeclaration}; use properties::longhands; use properties::longhands::background_size::computed_value::T as BackgroundSizeList; use properties::longhands::font_weight::computed_value::T as FontWeight; +use properties::longhands::font_stretch::computed_value::T as FontStretch; use properties::longhands::line_height::computed_value::T as LineHeight; use properties::longhands::text_shadow::computed_value::T as TextShadowList; use properties::longhands::text_shadow::computed_value::TextShadow; @@ -1360,6 +1361,54 @@ impl Animatable for FontWeight { } } +/// https://drafts.csswg.org/css-fonts/#font-stretch-prop +impl Animatable for FontStretch { + #[inline] + fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result { + let from = f64::from(*self); + let to = f64::from(*other); + let interpolated_mapped_index = ((from * self_portion + to * other_portion) + 0.5).floor(); + Ok(interpolated_mapped_index.into()) + } + + #[inline] + fn compute_distance(&self, other: &Self) -> Result { + let from = f64::from(*self); + let to = f64::from(*other); + from.compute_distance(&to) + } +} + +/// We should treat font stretch as real number in order to interpolate this property. +/// https://drafts.csswg.org/css-fonts-3/#font-stretch-animation +impl From for f64 { + fn from(stretch: FontStretch) -> f64 { + use self::FontStretch::*; + match stretch { + ultra_condensed => 1.0, + extra_condensed => 2.0, + condensed => 3.0, + semi_condensed => 4.0, + normal => 5.0, + semi_expanded => 6.0, + expanded => 7.0, + extra_expanded => 8.0, + ultra_expanded => 9.0, + } + } +} + +impl Into for f64 { + fn into(self) -> FontStretch { + use properties::longhands::font_stretch::computed_value::T::*; + debug_assert!(self >= 1.0 && self <= 9.0); + static FONT_STRETCH_ENUM_MAP: [FontStretch; 9] = + [ ultra_condensed, extra_condensed, condensed, semi_condensed, normal, + semi_expanded, expanded, extra_expanded, ultra_expanded ]; + FONT_STRETCH_ENUM_MAP[(self - 1.0) as usize] + } +} + /// https://drafts.csswg.org/css-transitions/#animtype-simple-list impl Animatable for generic_position::Position { #[inline] diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 9d2ec4215d4..d4c8c4b2fae 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -1178,7 +1178,6 @@ ${helpers.single_keyword_system("font-variant-caps", } -// FIXME: This prop should be animatable ${helpers.single_keyword_system("font-stretch", "normal ultra-condensed extra-condensed condensed \ semi-condensed semi-expanded expanded extra-expanded \ @@ -1187,14 +1186,14 @@ ${helpers.single_keyword_system("font-stretch", gecko_constant_prefix="NS_FONT_STRETCH", cast_type='i16', spec="https://drafts.csswg.org/css-fonts/#propdef-font-stretch", - animation_value_type="none")} + animation_value_type="ComputedValue")} ${helpers.single_keyword_system("font-kerning", "auto none normal", products="gecko", gecko_ffi_name="mFont.kerning", gecko_constant_prefix="NS_FONT_KERNING", - spec="https://drafts.csswg.org/css-fonts/#propdef-font-stretch", + spec="https://drafts.csswg.org/css-fonts/#propdef-font-kerning", animation_value_type="none")} /// FIXME: Implement proper handling of each values.