From a38de8b540cbde4c2c1a4bc0318e113d032a0e7c Mon Sep 17 00:00:00 2001 From: CYBAI Date: Sat, 18 Nov 2017 17:57:22 +0800 Subject: [PATCH] style: Move font-variant-numeric outside of mako --- components/style/macros.rs | 17 ++ .../style/properties/longhand/font.mako.rs | 182 +------------- components/style/values/computed/font.rs | 3 + components/style/values/computed/mod.rs | 2 +- components/style/values/specified/font.rs | 223 ++++++++++++++++++ components/style/values/specified/mod.rs | 2 +- 6 files changed, 253 insertions(+), 176 deletions(-) diff --git a/components/style/macros.rs b/components/style/macros.rs index 236a03f1f8a..aa505498d3b 100644 --- a/components/style/macros.rs +++ b/components/style/macros.rs @@ -14,6 +14,23 @@ macro_rules! exclusive_value { } } +#[cfg(feature = "gecko")] +macro_rules! impl_gecko_keyword_conversions { + ($name: ident, $utype: ty) => { + impl From<$utype> for $name { + fn from(bits: $utype) -> $name { + $name::from_gecko_keyword(bits) + } + } + + impl From<$name> for $utype { + fn from(v: $name) -> $utype { + v.to_gecko_keyword() + } + } + }; +} + macro_rules! trivial_to_computed_value { ($name:ty) => { impl $crate::values::computed::ToComputedValue for $name { diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 917237b0bee..99d53d54bef 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -15,23 +15,6 @@ %endif -#[cfg(feature = "gecko")] -macro_rules! impl_gecko_keyword_conversions { - ($name: ident, $utype: ty) => { - impl From<$utype> for $name { - fn from(bits: $utype) -> $name { - $name::from_gecko_keyword(bits) - } - } - - impl From<$name> for $utype { - fn from(v: $name) -> $utype { - v.to_gecko_keyword() - } - } - }; -} - // Define ToComputedValue, ToCss, and other boilerplate for a specified value // which is of the form `enum SpecifiedValue {Value(..), System(SystemFont)}` <%def name="simple_system_boilerplate(name)"> @@ -679,17 +662,6 @@ ${helpers.predefined_type("font-variant-alternates", flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-alternates")} -#[cfg(feature = "gecko")] -macro_rules! exclusive_value { - (($value:ident, $set:expr) => $ident:path) => { - if $value.intersects($set) { - return Err(()) - } else { - $ident - } - } -} - ${helpers.predefined_type("font-variant-east-asian", "FontVariantEastAsian", products="gecko", @@ -708,152 +680,14 @@ ${helpers.predefined_type("font-variant-ligatures", flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-ligatures")} -<%helpers:longhand name="font-variant-numeric" products="gecko" animation_value_type="discrete" - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER" - spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-numeric"> - use properties::longhands::system_font::SystemFont; - use std::fmt; - use style_traits::ToCss; - - - bitflags! { - #[derive(MallocSizeOf)] - pub struct VariantNumeric: u8 { - const NORMAL = 0; - const LINING_NUMS = 0x01; - const OLDSTYLE_NUMS = 0x02; - const PROPORTIONAL_NUMS = 0x04; - const TABULAR_NUMS = 0x08; - const DIAGONAL_FRACTIONS = 0x10; - const STACKED_FRACTIONS = 0x20; - const SLASHED_ZERO = 0x40; - const ORDINAL = 0x80; - } - } - - #[cfg_attr(feature = "gecko", derive(MallocSizeOf))] - #[derive(Clone, Debug, PartialEq, ToCss)] - pub enum SpecifiedValue { - Value(VariantNumeric), - System(SystemFont) - } - - <%self:simple_system_boilerplate name="font_variant_numeric"> - - - // servo_bit: gecko_bit - <% font_variant_numeric_map = { "VariantNumeric::LINING_NUMS": "LINING", - "VariantNumeric::OLDSTYLE_NUMS": "OLDSTYLE", - "VariantNumeric::PROPORTIONAL_NUMS": "PROPORTIONAL", - "VariantNumeric::TABULAR_NUMS": "TABULAR", - "VariantNumeric::DIAGONAL_FRACTIONS": "DIAGONAL_FRACTIONS", - "VariantNumeric::STACKED_FRACTIONS": "STACKED_FRACTIONS", - "VariantNumeric::SLASHED_ZERO": "SLASHZERO", - "VariantNumeric::ORDINAL": "ORDINAL" } %> - - ${helpers.gecko_bitflags_conversion(font_variant_numeric_map, 'NS_FONT_VARIANT_NUMERIC_', - 'VariantNumeric')} - - impl ToCss for VariantNumeric { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - if self.is_empty() { - return dest.write_str("normal") - } - - let mut has_any = false; - - macro_rules! write_value { - ($ident:path => $str:expr) => { - if self.intersects($ident) { - if has_any { - dest.write_str(" ")?; - } - has_any = true; - dest.write_str($str)?; - } - } - } - - write_value!(VariantNumeric::LINING_NUMS => "lining-nums"); - write_value!(VariantNumeric::OLDSTYLE_NUMS => "oldstyle-nums"); - write_value!(VariantNumeric::PROPORTIONAL_NUMS => "proportional-nums"); - write_value!(VariantNumeric::TABULAR_NUMS => "tabular-nums"); - write_value!(VariantNumeric::DIAGONAL_FRACTIONS => "diagonal-fractions"); - write_value!(VariantNumeric::STACKED_FRACTIONS => "stacked-fractions"); - write_value!(VariantNumeric::SLASHED_ZERO => "slashed-zero"); - write_value!(VariantNumeric::ORDINAL => "ordinal"); - - debug_assert!(has_any); - Ok(()) - } - } - - pub mod computed_value { - pub type T = super::VariantNumeric; - } - #[inline] - pub fn get_initial_value() -> computed_value::T { - computed_value::T::empty() - } - #[inline] - pub fn get_initial_specified_value() -> SpecifiedValue { - SpecifiedValue::Value(VariantNumeric::empty()) - } - - /// normal | - /// [ || - /// || - /// || - /// ordinal || - /// slashed-zero ] - /// = [ lining-nums | oldstyle-nums ] - /// = [ proportional-nums | tabular-nums ] - /// = [ diagonal-fractions | stacked-fractions ] - <% numeric_figure_values = "VariantNumeric::LINING_NUMS | VariantNumeric::OLDSTYLE_NUMS" %> - <% numeric_spacing_values = "VariantNumeric::PROPORTIONAL_NUMS | VariantNumeric::TABULAR_NUMS" %> - <% numeric_fraction_values = "VariantNumeric::DIAGONAL_FRACTIONS | VariantNumeric::STACKED_FRACTIONS" %> - pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result> { - let mut result = VariantNumeric::empty(); - - if input.try(|input| input.expect_ident_matching("normal")).is_ok() { - return Ok(SpecifiedValue::Value(result)) - } - - while let Ok(flag) = input.try(|input| { - Ok(match_ignore_ascii_case! { &input.expect_ident().map_err(|_| ())?, - "ordinal" => - exclusive_value!((result, VariantNumeric::ORDINAL) => VariantNumeric::ORDINAL), - "slashed-zero" => - exclusive_value!((result, VariantNumeric::SLASHED_ZERO) => VariantNumeric::SLASHED_ZERO), - "lining-nums" => - exclusive_value!((result, ${numeric_figure_values}) => VariantNumeric::LINING_NUMS), - "oldstyle-nums" => - exclusive_value!((result, ${numeric_figure_values}) => VariantNumeric::OLDSTYLE_NUMS), - "proportional-nums" => - exclusive_value!((result, ${numeric_spacing_values}) => VariantNumeric::PROPORTIONAL_NUMS), - "tabular-nums" => - exclusive_value!((result, ${numeric_spacing_values}) => VariantNumeric::TABULAR_NUMS), - "diagonal-fractions" => - exclusive_value!((result, ${numeric_fraction_values}) => VariantNumeric::DIAGONAL_FRACTIONS), - "stacked-fractions" => - exclusive_value!((result, ${numeric_fraction_values}) => VariantNumeric::STACKED_FRACTIONS), - _ => return Err(()), - }) - }) { - result.insert(flag); - } - - if !result.is_empty() { - Ok(SpecifiedValue::Value(result)) - } else { - Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) - } - } - - #[cfg(feature = "gecko")] - impl_gecko_keyword_conversions!(VariantNumeric, u8); - +${helpers.predefined_type("font-variant-numeric", + "FontVariantNumeric", + products="gecko", + initial_value="computed::FontVariantNumeric::empty()", + initial_specified_value="specified::FontVariantNumeric::empty()", + animation_value_type="discrete", + flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-numeric")} ${helpers.single_keyword_system("font-variant-position", "normal sub super", diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index e0e7a6e50f6..5ea93352a75 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -283,6 +283,9 @@ pub type FontVariantEastAsian = specified::VariantEastAsian; /// Use VariantLigatures as computed type of FontVariantLigatures pub type FontVariantLigatures = specified::VariantLigatures; +/// Use VariantNumeric as computed type of FontVariantNumeric +pub type FontVariantNumeric = specified::VariantNumeric; + /// font-language-override can only have a single three-letter /// OpenType "language system" tag, so we should be able to compute /// it and store it as a 32-bit integer diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 2ddd5af7ce9..2eac34a7d17 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -38,7 +38,7 @@ pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth} pub use self::border::{BorderRadius, BorderCornerRadius, BorderSpacing}; pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVariantAlternates}; pub use self::font::{FontLanguageOverride, FontVariantSettings, FontVariantEastAsian}; -pub use self::font::{FontVariantLigatures, MozScriptLevel, MozScriptMinSize, XTextZoom}; +pub use self::font::{FontVariantLigatures, FontVariantNumeric, MozScriptLevel, MozScriptMinSize, XTextZoom}; pub use self::box_::{AnimationIterationCount, AnimationName, ScrollSnapType, VerticalAlign}; pub use self::color::{Color, ColorPropertyValue, RGBAColor}; pub use self::effects::{BoxShadow, Filter, SimpleShadow}; diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index 37230ad15ae..56e4b88b17e 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -1350,6 +1350,229 @@ impl Parse for FontVariantLigatures { } } +bitflags! { + #[derive(MallocSizeOf)] + /// Vairants of numeric values + pub struct VariantNumeric: u8 { + /// None of other variants are enabled. + const NORMAL = 0; + /// Enables display of lining numerals. + const LINING_NUMS = 0x01; + /// Enables display of old-style numerals. + const OLDSTYLE_NUMS = 0x02; + /// Enables display of proportional numerals. + const PROPORTIONAL_NUMS = 0x04; + /// Enables display of tabular numerals. + const TABULAR_NUMS = 0x08; + /// Enables display of lining diagonal fractions. + const DIAGONAL_FRACTIONS = 0x10; + /// Enables display of lining stacked fractions. + const STACKED_FRACTIONS = 0x20; + /// Enables display of letter forms used with ordinal numbers. + const ORDINAL = 0x80; + /// Enables display of slashed zeros. + const SLASHED_ZERO = 0x40; + } +} + +#[cfg(feature = "gecko")] +impl VariantNumeric { + /// Obtain a specified value from a Gecko keyword value + /// + /// Intended for use with presentation attributes, not style structs + pub fn from_gecko_keyword(kw: u8) -> Self { + Self::from_bits_truncate(kw) + } + + /// Transform into gecko keyword + pub fn to_gecko_keyword(self) -> u8 { + self.bits() + } +} + +impl ToCss for VariantNumeric { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + if self.is_empty() { + return dest.write_str("normal") + } + + let mut has_any = false; + + macro_rules! write_value { + ($ident:path => $str:expr) => { + if self.intersects($ident) { + if has_any { + dest.write_str(" ")?; + } + has_any = true; + dest.write_str($str)?; + } + } + } + + write_value!(VariantNumeric::LINING_NUMS => "lining-nums"); + write_value!(VariantNumeric::OLDSTYLE_NUMS => "oldstyle-nums"); + write_value!(VariantNumeric::PROPORTIONAL_NUMS => "proportional-nums"); + write_value!(VariantNumeric::TABULAR_NUMS => "tabular-nums"); + write_value!(VariantNumeric::DIAGONAL_FRACTIONS => "diagonal-fractions"); + write_value!(VariantNumeric::STACKED_FRACTIONS => "stacked-fractions"); + write_value!(VariantNumeric::SLASHED_ZERO => "slashed-zero"); + write_value!(VariantNumeric::ORDINAL => "ordinal"); + + debug_assert!(has_any); + Ok(()) + } +} + +#[cfg(feature = "gecko")] +impl_gecko_keyword_conversions!(VariantNumeric, u8); + +/// Asserts that all variant-east-asian matches its NS_FONT_VARIANT_EAST_ASIAN_* value. +#[cfg(feature = "gecko")] +#[inline] +pub fn assert_variant_numeric_matches() { + use gecko_bindings::structs; + + macro_rules! check_variant_numeric { + ( $( $a:ident => $b:path),*, ) => { + if cfg!(debug_assertions) { + $( + assert_eq!(structs::$a as u8, $b.bits()); + )* + } + } + } + + check_variant_numeric! { + NS_FONT_VARIANT_NUMERIC_LINING => VariantNumeric::LINING_NUMS, + NS_FONT_VARIANT_NUMERIC_OLDSTYLE => VariantNumeric::OLDSTYLE_NUMS, + NS_FONT_VARIANT_NUMERIC_PROPORTIONAL => VariantNumeric::PROPORTIONAL_NUMS, + NS_FONT_VARIANT_NUMERIC_TABULAR => VariantNumeric::TABULAR_NUMS, + NS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS => VariantNumeric::DIAGONAL_FRACTIONS, + NS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS => VariantNumeric::STACKED_FRACTIONS, + NS_FONT_VARIANT_NUMERIC_SLASHZERO => VariantNumeric::SLASHED_ZERO, + NS_FONT_VARIANT_NUMERIC_ORDINAL => VariantNumeric::ORDINAL, + } +} + +#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] +#[derive(Clone, Debug, PartialEq, ToCss)] +/// Specifies control over numerical forms. +pub enum FontVariantNumeric { + /// Value variant with `variant-numeric` + Value(VariantNumeric), + /// System font + System(SystemFont) +} + +impl FontVariantNumeric { + #[inline] + /// Default value of `font-variant-numeric` as `empty` + pub fn empty() -> FontVariantNumeric { + FontVariantNumeric::Value(VariantNumeric::empty()) + } + + /// Get `font-variant-numeric` with system font + pub fn system_font(f: SystemFont) -> Self { + FontVariantNumeric::System(f) + } + + /// Get system font + pub fn get_system(&self) -> Option { + if let FontVariantNumeric::System(s) = *self { + Some(s) + } else { + None + } + } +} + +impl ToComputedValue for FontVariantNumeric { + type ComputedValue = computed::FontVariantNumeric; + + fn to_computed_value(&self, _context: &Context) -> computed::FontVariantNumeric { + match *self { + FontVariantNumeric::Value(ref v) => v.clone(), + FontVariantNumeric::System(_) => { + #[cfg(feature = "gecko")] { + _context.cached_system_font.as_ref().unwrap().font_variant_numeric.clone() + } + #[cfg(feature = "servo")] { + unreachable!() + } + } + } + } + + fn from_computed_value(other: &computed::FontVariantNumeric) -> Self { + FontVariantNumeric::Value(other.clone()) + } +} + +impl Parse for FontVariantNumeric { + /// normal | + /// [ || + /// || + /// || + /// ordinal || + /// slashed-zero ] + /// = [ lining-nums | oldstyle-nums ] + /// = [ proportional-nums | tabular-nums ] + /// = [ diagonal-fractions | stacked-fractions ] + fn parse<'i, 't>( + _context: &ParserContext, + input: &mut Parser<'i, 't> + ) -> Result> { + let mut result = VariantNumeric::empty(); + + if input.try(|input| input.expect_ident_matching("normal")).is_ok() { + return Ok(FontVariantNumeric::Value(result)) + } + + while let Ok(flag) = input.try(|input| { + Ok(match_ignore_ascii_case! { &input.expect_ident().map_err(|_| ())?, + "ordinal" => + exclusive_value!((result, VariantNumeric::ORDINAL) => VariantNumeric::ORDINAL), + "slashed-zero" => + exclusive_value!((result, VariantNumeric::SLASHED_ZERO) => VariantNumeric::SLASHED_ZERO), + "lining-nums" => + exclusive_value!((result, VariantNumeric::LINING_NUMS | + VariantNumeric::OLDSTYLE_NUMS + ) => VariantNumeric::LINING_NUMS), + "oldstyle-nums" => + exclusive_value!((result, VariantNumeric::LINING_NUMS | + VariantNumeric::OLDSTYLE_NUMS + ) => VariantNumeric::OLDSTYLE_NUMS), + "proportional-nums" => + exclusive_value!((result, VariantNumeric::PROPORTIONAL_NUMS | + VariantNumeric::TABULAR_NUMS + ) => VariantNumeric::PROPORTIONAL_NUMS), + "tabular-nums" => + exclusive_value!((result, VariantNumeric::PROPORTIONAL_NUMS | + VariantNumeric::TABULAR_NUMS + ) => VariantNumeric::TABULAR_NUMS), + "diagonal-fractions" => + exclusive_value!((result, VariantNumeric::DIAGONAL_FRACTIONS | + VariantNumeric::STACKED_FRACTIONS + ) => VariantNumeric::DIAGONAL_FRACTIONS), + "stacked-fractions" => + exclusive_value!((result, VariantNumeric::DIAGONAL_FRACTIONS | + VariantNumeric::STACKED_FRACTIONS + ) => VariantNumeric::STACKED_FRACTIONS), + _ => return Err(()), + }) + }) { + result.insert(flag); + } + + if !result.is_empty() { + Ok(FontVariantNumeric::Value(result)) + } else { + Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) + } + } +} + #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)] /// Whether user agents are allowed to synthesize bold or oblique font faces /// when a font family lacks bold or italic faces diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 7bd01722e9d..07b38ea4d07 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -32,7 +32,7 @@ pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth}; pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing}; pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVariantAlternates}; pub use self::font::{FontLanguageOverride, FontVariantSettings, FontVariantEastAsian}; -pub use self::font::{FontVariantLigatures, MozScriptLevel, MozScriptMinSize, XTextZoom}; +pub use self::font::{FontVariantLigatures, FontVariantNumeric, MozScriptLevel, MozScriptMinSize, XTextZoom}; pub use self::box_::{AnimationIterationCount, AnimationName, ScrollSnapType, VerticalAlign}; pub use self::color::{Color, ColorPropertyValue, RGBAColor}; pub use self::effects::{BoxShadow, Filter, SimpleShadow};