diff --git a/servo/components/style/properties/longhand/font.mako.rs b/servo/components/style/properties/longhand/font.mako.rs index 528f19ce65d2..acf9cf334605 100644 --- a/servo/components/style/properties/longhand/font.mako.rs +++ b/servo/components/style/properties/longhand/font.mako.rs @@ -642,92 +642,13 @@ ${helpers.predefined_type("font-size-adjust", flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust")} -<%helpers:longhand products="gecko" name="font-synthesis" 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-synthesis"> - use std::fmt; - use style_traits::ToCss; - - pub mod computed_value { - pub use super::SpecifiedValue as T; - } - - #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)] - pub struct SpecifiedValue { - pub weight: bool, - pub style: bool, - } - - impl ToCss for computed_value::T { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - if self.weight && self.style { - dest.write_str("weight style") - } else if self.style { - dest.write_str("style") - } else if self.weight { - dest.write_str("weight") - } else { - dest.write_str("none") - } - } - } - - #[inline] - pub fn get_initial_value() -> computed_value::T { - SpecifiedValue { weight: true, style: true } - } - - pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result> { - let mut result = SpecifiedValue { weight: false, style: false }; - // FIXME: remove clone() when lifetimes are non-lexical - try_match_ident_ignore_ascii_case! { input, - "none" => Ok(result), - "weight" => { - result.weight = true; - if input.try(|input| input.expect_ident_matching("style")).is_ok() { - result.style = true; - } - Ok(result) - }, - "style" => { - result.style = true; - if input.try(|input| input.expect_ident_matching("weight")).is_ok() { - result.weight = true; - } - Ok(result) - }, - } - } - - #[cfg(feature = "gecko")] - impl From for SpecifiedValue { - fn from(bits: u8) -> SpecifiedValue { - use gecko_bindings::structs; - - SpecifiedValue { - weight: bits & structs::NS_FONT_SYNTHESIS_WEIGHT as u8 != 0, - style: bits & structs::NS_FONT_SYNTHESIS_STYLE as u8 != 0 - } - } - } - - #[cfg(feature = "gecko")] - impl From for u8 { - fn from(v: SpecifiedValue) -> u8 { - use gecko_bindings::structs; - - let mut bits: u8 = 0; - if v.weight { - bits |= structs::NS_FONT_SYNTHESIS_WEIGHT as u8; - } - if v.style { - bits |= structs::NS_FONT_SYNTHESIS_STYLE as u8; - } - bits - } - } - +${helpers.predefined_type("font-synthesis", + "FontSynthesis", + products="gecko", + initial_value="specified::FontSynthesis::get_initial_value()", + 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-synthesis")} ${helpers.single_keyword_system("font-stretch", "normal ultra-condensed extra-condensed condensed \ diff --git a/servo/components/style/values/computed/font.rs b/servo/components/style/values/computed/font.rs index 37ae58b8eb06..a14d6e19cbae 100644 --- a/servo/components/style/values/computed/font.rs +++ b/servo/components/style/values/computed/font.rs @@ -14,7 +14,7 @@ use values::specified::font as specified; use values::specified::length::{FontBaseSize, NoCalcLength}; pub use values::computed::Length as MozScriptMinSize; -pub use values::specified::font::XTextZoom; +pub use values::specified::font::{XTextZoom, FontSynthesis}; /// As of CSS Fonts Module Level 3, only the following values are /// valid: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 diff --git a/servo/components/style/values/computed/mod.rs b/servo/components/style/values/computed/mod.rs index 65eb27eea0c3..51fe7f209878 100644 --- a/servo/components/style/values/computed/mod.rs +++ b/servo/components/style/values/computed/mod.rs @@ -36,7 +36,7 @@ pub use self::angle::Angle; pub use self::background::{BackgroundSize, BackgroundRepeat}; pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth}; pub use self::border::{BorderRadius, BorderCornerRadius, BorderSpacing}; -pub use self::font::{FontSize, FontSizeAdjust, FontWeight, MozScriptLevel, MozScriptMinSize, XTextZoom}; +pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, 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/servo/components/style/values/specified/font.rs b/servo/components/style/values/specified/font.rs index 571a1841c58e..67c9956d4b89 100644 --- a/servo/components/style/values/specified/font.rs +++ b/servo/components/style/values/specified/font.rs @@ -610,6 +610,95 @@ impl Parse for FontSize { } } +#[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 +pub struct FontSynthesis { + /// If a `font-weight` is requested that the font family does not contain, + /// the user agent may synthesize the requested weight from the weights + /// that do exist in the font family. + pub weight: bool, + /// If a font-style is requested that the font family does not contain, + /// the user agent may synthesize the requested style from the normal face in the font family. + pub style: bool, +} + +impl FontSynthesis { + #[inline] + /// Get the default value of font-synthesis + pub fn get_initial_value() -> Self { + FontSynthesis { + weight: true, + style: true + } + } +} + +impl Parse for FontSynthesis { + fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + let mut result = FontSynthesis { weight: false, style: false }; + try_match_ident_ignore_ascii_case! { input, + "none" => Ok(result), + "weight" => { + result.weight = true; + if input.try(|input| input.expect_ident_matching("style")).is_ok() { + result.style = true; + } + Ok(result) + }, + "style" => { + result.style = true; + if input.try(|input| input.expect_ident_matching("weight")).is_ok() { + result.weight = true; + } + Ok(result) + }, + } + } +} + +impl ToCss for FontSynthesis { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + if self.weight && self.style { + dest.write_str("weight style") + } else if self.style { + dest.write_str("style") + } else if self.weight { + dest.write_str("weight") + } else { + dest.write_str("none") + } + } +} + +#[cfg(feature = "gecko")] +impl From for FontSynthesis { + fn from(bits: u8) -> FontSynthesis { + use gecko_bindings::structs; + + FontSynthesis { + weight: bits & structs::NS_FONT_SYNTHESIS_WEIGHT as u8 != 0, + style: bits & structs::NS_FONT_SYNTHESIS_STYLE as u8 != 0 + } + } +} + +#[cfg(feature = "gecko")] +impl From for u8 { + fn from(v: FontSynthesis) -> u8 { + use gecko_bindings::structs; + + let mut bits: u8 = 0; + if v.weight { + bits |= structs::NS_FONT_SYNTHESIS_WEIGHT as u8; + } + if v.style { + bits |= structs::NS_FONT_SYNTHESIS_STYLE as u8; + } + bits + } +} + #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)] /// text-zoom. Enable if true, disable if false pub struct XTextZoom(pub bool); diff --git a/servo/components/style/values/specified/mod.rs b/servo/components/style/values/specified/mod.rs index 11afe1dfd5f6..5d89190e229d 100644 --- a/servo/components/style/values/specified/mod.rs +++ b/servo/components/style/values/specified/mod.rs @@ -30,7 +30,7 @@ pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, Justify pub use self::background::{BackgroundRepeat, BackgroundSize}; pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth}; pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing}; -pub use self::font::{FontSize, FontSizeAdjust, FontWeight, MozScriptLevel, MozScriptMinSize, XTextZoom}; +pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, 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};