servo: Merge #17430 - Store font-weight as integer directly (from upsuper:font-weight-int); r=nox

It doesn't make much sense to store `font-weight` as separate enums, especially given that we would need to support (somehow) arbitrary font weight value when we implement CSS Fonts Level 4.

This PR refactors the `font-weight` a bit to make it store as `u16` directly.

Source-Repo: https://github.com/servo/servo
Source-Revision: f11a922760a08ffb956607d9ab447f8f2a319a25

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 2c8f317216c5c66b2ced1f308efe14ff61fb3add
This commit is contained in:
Xidorn Quan 2017-07-06 16:18:36 -07:00
Родитель 0c16f513c9
Коммит 220e6d47b6
11 изменённых файлов: 111 добавлений и 194 удалений

Просмотреть файл

@ -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
}
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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 {

Просмотреть файл

@ -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<FontInfo, ()> {
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,

Просмотреть файл

@ -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<Self, ()> {
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.

Просмотреть файл

@ -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),
}
}
}

Просмотреть файл

@ -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')}

Просмотреть файл

@ -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<Self, ()> {
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<Self, ()> { Ok(FontWeight::Weight400) }
fn get_zero_value(&self) -> Result<Self, ()> { Ok(FontWeight::normal()) }
#[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
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)
}
}

Просмотреть файл

@ -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<SpecifiedValue, ParseError<'i>> {
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<Self, ()> {
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<Self, ParseError<'i>> {
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<Self, ()> {
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<W>(&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, ParseError<'i>> {
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)
}
}
</%helpers:longhand>

Просмотреть файл

@ -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()

Просмотреть файл

@ -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);
}
}