diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index 30eaac343ac..c3987874dc1 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -554,7 +554,7 @@ keyword = keyword=Keyword(name, values, **keyword_kwargs) %> <%call expr="longhand(name, keyword=Keyword(name, values, **keyword_kwargs), **kwargs)"> - use crate::properties::longhands::system_font::SystemFont; + use crate::values::specified::font::SystemFont; pub mod computed_value { #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] diff --git a/components/style/properties/longhands/font.mako.rs b/components/style/properties/longhands/font.mako.rs index 1fb52a01c77..e84a5574d1a 100644 --- a/components/style/properties/longhands/font.mako.rs +++ b/components/style/properties/longhands/font.mako.rs @@ -288,208 +288,153 @@ ${helpers.predefined_type( )} % if engine == "gecko": - pub mod system_font { - //! We deal with system fonts here - //! - //! System fonts can only be set as a group via the font shorthand. - //! They resolve at compute time (not parse time -- this lets the - //! browser respond to changes to the OS font settings). - //! - //! While Gecko handles these as a separate property and keyword - //! values on each property indicating that the font should be picked - //! from the -x-system-font property, we avoid this. Instead, - //! each font longhand has a special SystemFont variant which contains - //! the specified system font. When the cascade function (in helpers) - //! detects that a value has a system font, it will resolve it, and - //! cache it on the ComputedValues. After this, it can be just fetched - //! whenever a font longhand on the same element needs the system font. - //! - //! When a longhand property is holding a SystemFont, it's serialized - //! to an empty string as if its value comes from a shorthand with - //! variable reference. We may want to improve this behavior at some - //! point. See also https://github.com/w3c/csswg-drafts/issues/1586. +pub mod system_font { + //! We deal with system fonts here + //! + //! System fonts can only be set as a group via the font shorthand. + //! They resolve at compute time (not parse time -- this lets the + //! browser respond to changes to the OS font settings). + //! + //! While Gecko handles these as a separate property and keyword + //! values on each property indicating that the font should be picked + //! from the -x-system-font property, we avoid this. Instead, + //! each font longhand has a special SystemFont variant which contains + //! the specified system font. When the cascade function (in helpers) + //! detects that a value has a system font, it will resolve it, and + //! cache it on the ComputedValues. After this, it can be just fetched + //! whenever a font longhand on the same element needs the system font. + //! + //! When a longhand property is holding a SystemFont, it's serialized + //! to an empty string as if its value comes from a shorthand with + //! variable reference. We may want to improve this behavior at some + //! point. See also https://github.com/w3c/csswg-drafts/issues/1586. - use cssparser::{Parser, ToCss}; - use crate::values::computed::font::GenericFontFamily; - use crate::properties::longhands; - use std::fmt; - use std::hash::{Hash, Hasher}; - use style_traits::ParseError; - use crate::values::computed::{ToComputedValue, Context}; + use crate::values::computed::font::GenericFontFamily; + use crate::properties::longhands; + use std::hash::{Hash, Hasher}; + use crate::values::computed::{ToComputedValue, Context}; + use crate::values::specified::font::SystemFont; - <% - system_fonts = """caption icon menu message-box small-caption status-bar - -moz-window -moz-document -moz-workspace -moz-desktop - -moz-info -moz-dialog -moz-button -moz-pull-down-menu - -moz-list -moz-field""".split() - kw_font_props = """font_variant_caps - font_kerning font_variant_position font_variant_ligatures - font_variant_east_asian font_variant_numeric - font_optical_sizing""".split() - kw_cast = """font_variant_caps font_kerning font_variant_position - font_optical_sizing""".split() - %> - #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToCss, ToShmem)] - pub enum SystemFont { - % for font in system_fonts: - ${to_camel_case(font)}, - % endfor - } + <% + kw_font_props = """font_variant_caps + font_kerning font_variant_position font_variant_ligatures + font_variant_east_asian font_variant_numeric + font_optical_sizing""".split() + kw_cast = """font_variant_caps font_kerning font_variant_position + font_optical_sizing""".split() + %> - // ComputedValues are compared at times - // so we need these impls. We don't want to - // add Eq to Number (which contains a float) - // so instead we have an eq impl which skips the - // cached values - impl PartialEq for ComputedSystemFont { - fn eq(&self, other: &Self) -> bool { - self.system_font == other.system_font - } - } - impl Eq for ComputedSystemFont {} - - impl Hash for ComputedSystemFont { - fn hash(&self, hasher: &mut H) { - self.system_font.hash(hasher) - } - } - - impl ToComputedValue for SystemFont { - type ComputedValue = ComputedSystemFont; - - fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { - use crate::gecko_bindings::bindings; - use crate::gecko_bindings::structs::{LookAndFeel_FontID, nsFont}; - use std::mem; - use crate::values::computed::Percentage; - use crate::values::specified::font::KeywordInfo; - use crate::values::computed::font::{FontFamily, FontSize, FontStretch, FontStyle, FontFamilyList}; - use crate::values::generics::NonNegative; - - let id = match *self { - % for font in system_fonts: - SystemFont::${to_camel_case(font)} => { - LookAndFeel_FontID::${to_camel_case(font.replace("-moz-", ""))} - } - % endfor - }; - - let mut system = mem::MaybeUninit::::uninit(); - let system = unsafe { - bindings::Gecko_nsFont_InitSystem( - system.as_mut_ptr(), - id as i32, - cx.style().get_font().gecko(), - cx.device().document() - ); - &mut *system.as_mut_ptr() - }; - let font_weight = longhands::font_weight::computed_value::T::from_gecko_weight(system.weight); - let font_stretch = FontStretch(NonNegative(Percentage(unsafe { - bindings::Gecko_FontStretch_ToFloat(system.stretch) - }))); - let font_style = FontStyle::from_gecko(system.style); - let ret = ComputedSystemFont { - font_family: FontFamily { - families: FontFamilyList::SharedFontList( - unsafe { system.fontlist.mFontlist.mBasePtr.to_safe() } - ), - is_system_font: true, - }, - font_size: FontSize { - size: NonNegative(cx.maybe_zoom_text(system.size.0)), - keyword_info: KeywordInfo::none() - }, - font_weight, - font_stretch, - font_style, - font_size_adjust: longhands::font_size_adjust::computed_value - ::T::from_gecko_adjust(system.sizeAdjust), - % for kwprop in kw_font_props: - ${kwprop}: longhands::${kwprop}::computed_value::T::from_gecko_keyword( - system.${to_camel_case_lower(kwprop.replace('font_', ''))} - % if kwprop in kw_cast: - as u32 - % endif - ), - % endfor - font_language_override: longhands::font_language_override::computed_value - ::T(system.languageOverride), - font_feature_settings: longhands::font_feature_settings::get_initial_value(), - font_variation_settings: longhands::font_variation_settings::get_initial_value(), - font_variant_alternates: longhands::font_variant_alternates::get_initial_value(), - system_font: *self, - default_font_type: system.fontlist.mDefaultFontType, - }; - unsafe { bindings::Gecko_nsFont_Destroy(system); } - ret - } - - fn from_computed_value(_: &ComputedSystemFont) -> Self { - unreachable!() - } - } - - #[inline] - /// Compute and cache a system font - /// - /// Must be called before attempting to compute a system font - /// specified value - pub fn resolve_system_font(system: SystemFont, context: &mut Context) { - // Checking if context.cached_system_font.is_none() isn't enough, - // if animating from one system font to another the cached system font - // may change - if Some(system) != context.cached_system_font.as_ref().map(|x| x.system_font) { - let computed = system.to_computed_value(context); - context.cached_system_font = Some(computed); - } - } - - #[derive(Clone, Debug)] - pub struct ComputedSystemFont { - % for name in SYSTEM_FONT_LONGHANDS: - pub ${name}: longhands::${name}::computed_value::T, - % endfor - pub system_font: SystemFont, - pub default_font_type: GenericFontFamily, - } - - impl SystemFont { - pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { - try_match_ident_ignore_ascii_case! { input, - % for font in system_fonts: - "${font}" => Ok(SystemFont::${to_camel_case(font)}), - % endfor - } - } - } - - impl ToCss for SystemFont { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - // We may want to do something better in the future, see - // w3c/csswg-drafts#1586. - dest.write_str("-moz-use-system-font") - } + // ComputedValues are compared at times + // so we need these impls. We don't want to + // add Eq to Number (which contains a float) + // so instead we have an eq impl which skips the + // cached values + impl PartialEq for ComputedSystemFont { + fn eq(&self, other: &Self) -> bool { + self.system_font == other.system_font } } -% else: - pub mod system_font { - use cssparser::Parser; + impl Eq for ComputedSystemFont {} - // We don't parse system fonts, but in the interest of not littering - // a lot of code with `if engine == "gecko"` conditionals, we have a - // dummy system font module that does nothing - - #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)] - /// void enum for system font, can never exist - pub enum SystemFont {} - impl SystemFont { - pub fn parse(_: &mut Parser) -> Result { - Err(()) - } + impl Hash for ComputedSystemFont { + fn hash(&self, hasher: &mut H) { + self.system_font.hash(hasher) } } + + impl ToComputedValue for SystemFont { + type ComputedValue = ComputedSystemFont; + + fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { + use crate::gecko_bindings::bindings; + use crate::gecko_bindings::structs::nsFont; + use std::mem; + use crate::values::computed::Percentage; + use crate::values::specified::font::KeywordInfo; + use crate::values::computed::font::{FontFamily, FontSize, FontStretch, FontStyle, FontFamilyList}; + use crate::values::generics::NonNegative; + + let mut system = mem::MaybeUninit::::uninit(); + let system = unsafe { + bindings::Gecko_nsFont_InitSystem( + system.as_mut_ptr(), + *self, + cx.style().get_font().gecko(), + cx.device().document() + ); + &mut *system.as_mut_ptr() + }; + let font_weight = longhands::font_weight::computed_value::T::from_gecko_weight(system.weight); + let font_stretch = FontStretch(NonNegative(Percentage(unsafe { + bindings::Gecko_FontStretch_ToFloat(system.stretch) + }))); + let font_style = FontStyle::from_gecko(system.style); + let ret = ComputedSystemFont { + font_family: FontFamily { + families: FontFamilyList::SharedFontList( + unsafe { system.fontlist.mFontlist.mBasePtr.to_safe() } + ), + is_system_font: true, + }, + font_size: FontSize { + size: NonNegative(cx.maybe_zoom_text(system.size.0)), + keyword_info: KeywordInfo::none() + }, + font_weight, + font_stretch, + font_style, + font_size_adjust: longhands::font_size_adjust::computed_value + ::T::from_gecko_adjust(system.sizeAdjust), + % for kwprop in kw_font_props: + ${kwprop}: longhands::${kwprop}::computed_value::T::from_gecko_keyword( + system.${to_camel_case_lower(kwprop.replace('font_', ''))} + % if kwprop in kw_cast: + as u32 + % endif + ), + % endfor + font_language_override: longhands::font_language_override::computed_value + ::T(system.languageOverride), + font_feature_settings: longhands::font_feature_settings::get_initial_value(), + font_variation_settings: longhands::font_variation_settings::get_initial_value(), + font_variant_alternates: longhands::font_variant_alternates::get_initial_value(), + system_font: *self, + default_font_type: system.fontlist.mDefaultFontType, + }; + unsafe { bindings::Gecko_nsFont_Destroy(system); } + ret + } + + fn from_computed_value(_: &ComputedSystemFont) -> Self { + unreachable!() + } + } + + #[inline] + /// Compute and cache a system font + /// + /// Must be called before attempting to compute a system font + /// specified value + pub fn resolve_system_font(system: SystemFont, context: &mut Context) { + // Checking if context.cached_system_font.is_none() isn't enough, + // if animating from one system font to another the cached system font + // may change + if Some(system) != context.cached_system_font.as_ref().map(|x| x.system_font) { + let computed = system.to_computed_value(context); + context.cached_system_font = Some(computed); + } + } + + #[derive(Clone, Debug)] + pub struct ComputedSystemFont { + % for name in SYSTEM_FONT_LONGHANDS: + pub ${name}: longhands::${name}::computed_value::T, + % endfor + pub system_font: SystemFont, + pub default_font_type: GenericFontFamily, + } + +} % endif ${helpers.single_keyword( diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index b27831a5785..ea3e043ea49 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -32,7 +32,6 @@ use crate::computed_value_flags::*; use crate::hash::FxHashMap; use crate::media_queries::Device; use crate::parser::ParserContext; -use crate::properties::longhands::system_font::SystemFont; use crate::selector_parser::PseudoElement; #[cfg(feature = "servo")] use servo_config::prefs; use style_traits::{CssWriter, KeywordsCollectFn, ParseError, ParsingMode}; @@ -44,6 +43,7 @@ use crate::values::generics::text::LineHeight; use crate::values::{computed, resolved}; use crate::values::computed::NonNegativeLength; use crate::values::serialize_atom_name; +use crate::values::specified::font::SystemFont; use crate::rule_tree::StrongRuleNode; use crate::Zero; use crate::str::{CssString, CssStringWriter}; diff --git a/components/style/properties/shorthands/font.mako.rs b/components/style/properties/shorthands/font.mako.rs index 2ed36ae88a5..99caaa0ca43 100644 --- a/components/style/properties/shorthands/font.mako.rs +++ b/components/style/properties/shorthands/font.mako.rs @@ -34,11 +34,11 @@ use crate::parser::Parse; use crate::properties::longhands::{font_family, font_style, font_weight, font_stretch}; use crate::properties::longhands::font_variant_caps; - #[cfg(feature = "gecko")] - use crate::properties::longhands::system_font::SystemFont; use crate::values::specified::text::LineHeight; use crate::values::specified::FontSize; use crate::values::specified::font::{FontStretch, FontStretchKeyword}; + #[cfg(feature = "gecko")] + use crate::values::specified::font::SystemFont; <% gecko_sub_properties = "kerning language_override size_adjust \ @@ -289,7 +289,7 @@ % for p in subprops_for_value_info: ${p}::collect_completion_keywords(f); % endfor - ::collect_completion_keywords(f); + ::collect_completion_keywords(f); } } diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index 6e43c34d53b..b536ddf3e21 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -9,7 +9,6 @@ use crate::context::QuirksMode; #[cfg(feature = "gecko")] use crate::gecko_bindings::bindings; use crate::parser::{Parse, ParserContext}; -use crate::properties::longhands::system_font::SystemFont; use crate::values::computed::font::{FamilyName, FontFamilyList, FontStyleAngle, SingleFontFamily}; use crate::values::computed::{font as computed, Length, NonNegativeLength}; use crate::values::computed::{Angle as ComputedAngle, Percentage as ComputedPercentage}; @@ -65,6 +64,33 @@ macro_rules! system_font_methods { }; } +/// System fonts. +#[repr(u8)] +#[derive( + Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem +)] +#[allow(missing_docs)] +pub enum SystemFont { + Caption, + Icon, + Menu, + MessageBox, + SmallCaption, + StatusBar, + MozWindow, + MozDocument, + MozWorkspace, + MozDesktop, + MozInfo, + MozDialog, + MozButton, + MozPullDownMenu, + MozList, + MozField, + #[css(skip)] + End, // Just for indexing purposes. +} + const DEFAULT_SCRIPT_MIN_SIZE_PT: u32 = 8; const DEFAULT_SCRIPT_SIZE_MULTIPLIER: f64 = 0.71;