diff --git a/components/gfx/font_template.rs b/components/gfx/font_template.rs index 6a46834901b..920e9735737 100644 --- a/components/gfx/font_template.rs +++ b/components/gfx/font_template.rs @@ -46,7 +46,7 @@ impl FontTemplateDescriptor { // A value higher than all weights. return 1000 } - ((self.weight as i16) - (other.weight as i16)).abs() as u32 + ((self.weight.0 as i16) - (other.weight.0 as i16)).abs() as u32 } } diff --git a/components/gfx/platform/freetype/font.rs b/components/gfx/platform/freetype/font.rs index 6a2b948be7e..b7bcd92d470 100644 --- a/components/gfx/platform/freetype/font.rs +++ b/components/gfx/platform/freetype/font.rs @@ -128,7 +128,7 @@ impl FontHandleMethods for FontHandle { unsafe { (*self.face).style_flags & FT_STYLE_FLAG_ITALIC as c_long != 0 } } fn boldness(&self) -> font_weight::T { - let default_weight = font_weight::T::Weight400; + let default_weight = font_weight::T::normal(); if unsafe { (*self.face).style_flags & FT_STYLE_FLAG_BOLD as c_long == 0 } { default_weight } else { @@ -136,18 +136,13 @@ impl FontHandleMethods for FontHandle { let os2 = FT_Get_Sfnt_Table(self.face, FT_Sfnt_Tag::FT_SFNT_OS2) as *mut TT_OS2; let valid = !os2.is_null() && (*os2).version != 0xffff; if valid { - let weight =(*os2).usWeightClass; - match weight { - 1 | 100...199 => font_weight::T::Weight100, - 2 | 200...299 => font_weight::T::Weight200, - 3 | 300...399 => font_weight::T::Weight300, - 4 | 400...499 => font_weight::T::Weight400, - 5 | 500...599 => font_weight::T::Weight500, - 6 | 600...699 => font_weight::T::Weight600, - 7 | 700...799 => font_weight::T::Weight700, - 8 | 800...899 => font_weight::T::Weight800, - 9 | 900...999 => font_weight::T::Weight900, - _ => default_weight + let weight =(*os2).usWeightClass as i32; + if weight < 10 { + font_weight::T::from_int(weight * 100).unwrap() + } else if weight >= 100 && weight < 1000 { + font_weight::T::from_int(weight / 100 * 100).unwrap() + } else { + default_weight } } else { default_weight diff --git a/components/gfx/platform/macos/font.rs b/components/gfx/platform/macos/font.rs index d87fec6f36d..aaaad7332ba 100644 --- a/components/gfx/platform/macos/font.rs +++ b/components/gfx/platform/macos/font.rs @@ -217,17 +217,7 @@ impl FontHandleMethods for FontHandle { } else { 4.0 + normalized * 5.0 // [4.0, 9.0] }; // [1.0, 9.0], centered on 4.0 - match normalized.round() as u32 { - 1 => font_weight::T::Weight100, - 2 => font_weight::T::Weight200, - 3 => font_weight::T::Weight300, - 4 => font_weight::T::Weight400, - 5 => font_weight::T::Weight500, - 6 => font_weight::T::Weight600, - 7 => font_weight::T::Weight700, - 8 => font_weight::T::Weight800, - _ => font_weight::T::Weight900, - } + font_weight::T::from_int(normalized.round() as i32 * 100).unwrap() } fn stretchiness(&self) -> font_stretch::T { diff --git a/components/gfx/platform/windows/font.rs b/components/gfx/platform/windows/font.rs index 1778c9a603f..38a2e6e0db3 100644 --- a/components/gfx/platform/windows/font.rs +++ b/components/gfx/platform/windows/font.rs @@ -155,18 +155,8 @@ impl FontInfo { }, }; - let weight = match min(9, max(1, weight_val / 100)) { - 1 => font_weight::T::Weight100, - 2 => font_weight::T::Weight200, - 3 => font_weight::T::Weight300, - 4 => font_weight::T::Weight400, - 5 => font_weight::T::Weight500, - 6 => font_weight::T::Weight600, - 7 => font_weight::T::Weight700, - 8 => font_weight::T::Weight800, - 9 => font_weight::T::Weight900, - _ => return Err(()), - }; + let weight = font_weight::T:: + from_int(min(9, max(1, weight_val as i32 / 100)) * 100).unwrap(); let stretch = match min(9, max(1, width_val)) { 1 => font_stretch::T::ultra_condensed, @@ -198,21 +188,21 @@ impl FontInfo { fn new_from_font(font: &Font) -> Result { let style = font.style(); - let weight = match font.weight() { - FontWeight::Thin => font_weight::T::Weight100, - FontWeight::ExtraLight => font_weight::T::Weight200, - FontWeight::Light => font_weight::T::Weight300, + let weight = font_weight::T(match font.weight() { + FontWeight::Thin => 100, + FontWeight::ExtraLight => 200, + FontWeight::Light => 300, // slightly grayer gray - FontWeight::SemiLight => font_weight::T::Weight300, - FontWeight::Regular => font_weight::T::Weight400, - FontWeight::Medium => font_weight::T::Weight500, - FontWeight::SemiBold => font_weight::T::Weight600, - FontWeight::Bold => font_weight::T::Weight700, - FontWeight::ExtraBold => font_weight::T::Weight800, - FontWeight::Black => font_weight::T::Weight900, + FontWeight::SemiLight => 300, + FontWeight::Regular => 400, + FontWeight::Medium => 500, + FontWeight::SemiBold => 600, + FontWeight::Bold => 700, + FontWeight::ExtraBold => 800, + FontWeight::Black => 900, // slightly blacker black - FontWeight::ExtraBlack => font_weight::T::Weight900, - }; + FontWeight::ExtraBlack => 900, + }); let stretch = match font.stretch() { FontStretch::Undefined => font_stretch::T::normal, FontStretch::UltraCondensed => font_stretch::T::ultra_condensed, diff --git a/components/style/font_face.rs b/components/style/font_face.rs index 5737d4ee60c..04554ca81ae 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -109,29 +109,13 @@ impl Parse for FontWeight { } }); result.or_else(|_| { - FontWeight::from_int(input.expect_integer()?) + font_weight::T::from_int(input.expect_integer()?) + .map(FontWeight::Weight) .map_err(|()| StyleParseError::UnspecifiedError.into()) }) } } -#[cfg(feature = "gecko")] -impl FontWeight { - fn from_int(kw: i32) -> Result { - match kw { - 100 => Ok(FontWeight::Weight(font_weight::T::Weight100)), - 200 => Ok(FontWeight::Weight(font_weight::T::Weight200)), - 300 => Ok(FontWeight::Weight(font_weight::T::Weight300)), - 400 => Ok(FontWeight::Weight(font_weight::T::Weight400)), - 500 => Ok(FontWeight::Weight(font_weight::T::Weight500)), - 600 => Ok(FontWeight::Weight(font_weight::T::Weight600)), - 700 => Ok(FontWeight::Weight(font_weight::T::Weight700)), - 800 => Ok(FontWeight::Weight(font_weight::T::Weight800)), - 900 => Ok(FontWeight::Weight(font_weight::T::Weight900)), - _ => Err(()) - } - } -} /// Parse the block inside a `@font-face` rule. /// /// Note that the prelude parsing code lives in the `stylesheets` module. diff --git a/components/style/gecko/rules.rs b/components/style/gecko/rules.rs index 33b2c2c9591..fbdc8dbf34a 100644 --- a/components/style/gecko/rules.rs +++ b/components/style/gecko/rules.rs @@ -31,7 +31,7 @@ impl ToNsCssValue for FamilyName { impl ToNsCssValue for font_weight::T { fn convert(self, nscssvalue: &mut nsCSSValue) { - nscssvalue.set_integer(self as i32) + nscssvalue.set_integer(self.0 as i32) } } @@ -42,7 +42,7 @@ impl ToNsCssValue for FontWeight { nscssvalue.set_enum(structs::NS_STYLE_FONT_WEIGHT_NORMAL as i32), FontWeight::Bold => nscssvalue.set_enum(structs::NS_STYLE_FONT_WEIGHT_BOLD as i32), - FontWeight::Weight(weight) => nscssvalue.set_integer(weight as i32), + FontWeight::Weight(weight) => nscssvalue.set_integer(weight.0 as i32), } } } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index c881dab0ca7..6823d6d5dba 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1906,7 +1906,7 @@ fn static_assert() { } pub fn set_font_weight(&mut self, v: longhands::font_weight::computed_value::T) { - self.gecko.mFont.weight = v as u16; + self.gecko.mFont.weight = v.0; } ${impl_simple_copy('font_weight', 'mFont.weight')} diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index e68faeb8924..1af4268b32d 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -1415,38 +1415,21 @@ impl Animatable for MaxLength { impl Animatable for FontWeight { #[inline] fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result { - let a = (*self as u32) as f64; - let b = (*other as u32) as f64; + let a = self.0 as f64; + let b = other.0 as f64; const NORMAL: f64 = 400.; let weight = (a - NORMAL) * self_portion + (b - NORMAL) * other_portion + NORMAL; - Ok(if weight < 150. { - FontWeight::Weight100 - } else if weight < 250. { - FontWeight::Weight200 - } else if weight < 350. { - FontWeight::Weight300 - } else if weight < 450. { - FontWeight::Weight400 - } else if weight < 550. { - FontWeight::Weight500 - } else if weight < 650. { - FontWeight::Weight600 - } else if weight < 750. { - FontWeight::Weight700 - } else if weight < 850. { - FontWeight::Weight800 - } else { - FontWeight::Weight900 - }) + let weight = (weight.min(100.).max(900.) / 100.).round() * 100.; + Ok(FontWeight(weight as u16)) } #[inline] - fn get_zero_value(&self) -> Result { Ok(FontWeight::Weight400) } + fn get_zero_value(&self) -> Result { Ok(FontWeight::normal()) } #[inline] fn compute_distance(&self, other: &Self) -> Result { - let a = (*self as u32) as f64; - let b = (*other as u32) as f64; + let a = self.0 as f64; + let b = other.0 as f64; a.compute_distance(&b) } } diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index e9defdb86ac..f9ec82514c0 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -422,9 +422,7 @@ ${helpers.single_keyword_system("font-variant-caps", Bold, Bolder, Lighter, - % for weight in range(100, 901, 100): - Weight${weight}, - % endfor + Weight(computed_value::T), System(SystemFont), } @@ -435,16 +433,14 @@ ${helpers.single_keyword_system("font-variant-caps", 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::Weight(weight) => weight.to_css(dest), SpecifiedValue::System(_) => Ok(()) } } } /// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 - pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) + pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { let result = input.try(|input| { let ident = input.expect_ident().map_err(|_| ())?; @@ -456,25 +452,13 @@ ${helpers.single_keyword_system("font-variant-caps", _ => Err(()) } }); - result.or_else(|_| { - SpecifiedValue::from_int(input.expect_integer()?) - .map_err(|()| StyleParseError::UnspecifiedError.into()) - }) + result.or_else(|_| computed_value::T::parse(context, input).map(SpecifiedValue::Weight)) } impl SpecifiedValue { - pub fn from_int(kw: i32) -> Result { - match kw { - % for weight in range(100, 901, 100): - ${weight} => Ok(SpecifiedValue::Weight${weight}), - % endfor - _ => Err(()) - } - } - 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") + computed_value::T::from_int(kw as i32).map(SpecifiedValue::Weight) + .expect("Found unexpected value in style struct for font-weight property") } } @@ -491,64 +475,79 @@ ${helpers.single_keyword_system("font-variant-caps", } } - /// Used in @font-face, where relative keywords are not allowed. - impl Parse for computed_value::T { - fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - 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(StyleParseError::UnspecifiedError.into()), - SpecifiedValue::System(..) => unreachable!(), - } - } - } - pub mod computed_value { - #[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)] + /// As of CSS Fonts Module Level 3, only the following values are + /// valid: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, ToCss)] #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] - #[repr(u16)] - pub enum T { - % for weight in range(100, 901, 100): - Weight${weight} = ${weight}, - % endfor - } + pub struct T(pub u16); + impl T { - #[inline] - pub fn is_bold(self) -> bool { - match self { - T::Weight900 | T::Weight800 | - T::Weight700 | T::Weight600 => true, - _ => false + /// Value for normal + pub fn normal() -> Self { + T(400) + } + + /// Value for bold + pub fn bold() -> Self { + T(700) + } + + /// Convert from an integer to Weight + pub fn from_int(n: i32) -> Result { + if n >= 100 && n <= 900 && n % 100 == 0 { + Ok(T(n as u16)) + } else { + Err(()) } } - /// Obtain a Servo computed value from a Gecko computed font-weight + /// Convert from an Gecko weight pub fn from_gecko_weight(weight: u16) -> Self { - match weight { - % for weight in range(100, 901, 100): - ${weight} => T::Weight${weight}, - % endfor - _ => panic!("from_gecko_weight: called with invalid weight") + Self::from_int(weight as i32) + .expect("from_gecko_weight: called with invalid weight") + } + + /// Weither this weight is bold + pub fn is_bold(&self) -> bool { + self.0 > 500 + } + + /// Return the bolder weight + pub fn bolder(self) -> Self { + if self.0 < 400 { + T(400) + } else if self.0 < 600 { + T(700) + } else { + T(900) + } + } + + /// Returns the lighter weight + pub fn lighter(self) -> Self { + if self.0 < 600 { + T(100) + } else if self.0 < 800 { + T(400) + } else { + T(700) } } } } - impl ToCss for computed_value::T { - fn to_css(&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 + + impl Parse for computed_value::T { + fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) + -> Result> { + Self::from_int(input.expect_integer()?) + .map_err(|_| StyleParseError::UnspecifiedError.into()) } - } } + #[inline] pub fn get_initial_value() -> computed_value::T { - computed_value::T::Weight400 // normal + computed_value::T::normal() } #[inline] @@ -562,33 +561,13 @@ ${helpers.single_keyword_system("font-variant-caps", #[inline] fn to_computed_value(&self, context: &Context) -> computed_value::T { match *self { - % for weight in range(100, 901, 100): - SpecifiedValue::Weight${weight} => computed_value::T::Weight${weight}, - % endfor - SpecifiedValue::Normal => computed_value::T::Weight400, - SpecifiedValue::Bold => computed_value::T::Weight700, - SpecifiedValue::Bolder => match context.inherited_style().get_font().clone_font_weight() { - computed_value::T::Weight100 => computed_value::T::Weight400, - computed_value::T::Weight200 => computed_value::T::Weight400, - computed_value::T::Weight300 => computed_value::T::Weight400, - computed_value::T::Weight400 => computed_value::T::Weight700, - computed_value::T::Weight500 => computed_value::T::Weight700, - computed_value::T::Weight600 => computed_value::T::Weight900, - computed_value::T::Weight700 => computed_value::T::Weight900, - computed_value::T::Weight800 => computed_value::T::Weight900, - computed_value::T::Weight900 => computed_value::T::Weight900, - }, - SpecifiedValue::Lighter => match context.inherited_style().get_font().clone_font_weight() { - computed_value::T::Weight100 => computed_value::T::Weight100, - computed_value::T::Weight200 => computed_value::T::Weight100, - 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::Weight(weight) => weight, + SpecifiedValue::Normal => computed_value::T::normal(), + SpecifiedValue::Bold => computed_value::T::bold(), + SpecifiedValue::Bolder => + context.inherited_style().get_font().clone_font_weight().bolder(), + SpecifiedValue::Lighter => + context.inherited_style().get_font().clone_font_weight().lighter(), SpecifiedValue::System(_) => { <%self:nongecko_unreachable> context.cached_system_font.as_ref().unwrap().font_weight.clone() @@ -599,11 +578,7 @@ ${helpers.single_keyword_system("font-variant-caps", #[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}, - % endfor - } + SpecifiedValue::Weight(*computed) } } diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 10c113ad790..b69b3bacbc8 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -1673,7 +1673,7 @@ pub mod style_structs { // Corresponds to the fields in // `gfx::font_template::FontTemplateDescriptor`. let mut hasher: FnvHasher = Default::default(); - hasher.write_u16(self.font_weight as u16); + hasher.write_u16(self.font_weight.0); self.font_stretch.hash(&mut hasher); self.font_family.hash(&mut hasher); self.hash = hasher.finish() diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs index 6d0d84c34f4..a2c692455af 100644 --- a/components/style/style_adjuster.rs +++ b/components/style/style_adjuster.rs @@ -184,7 +184,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { let mut font_style = self.style.mutate_font(); // Sadly we don't have a nice name for the computed value // of "font-weight: normal". - font_style.set_font_weight(font_weight::Weight400); + font_style.set_font_weight(font_weight::normal()); font_style.set_font_style(font_style::normal); } }