mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Refactor style::values::specified::Length to store length by kind (absolute, font-relative or character width)
This commit is contained in:
parent
00785ecf63
commit
41786c4cb4
3 changed files with 105 additions and 75 deletions
|
@ -114,17 +114,70 @@ pub mod specified {
|
|||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Copy)]
|
||||
pub enum Length {
|
||||
Au(Au), // application units
|
||||
pub enum FontRelativeLength {
|
||||
Em(CSSFloat),
|
||||
Ex(CSSFloat),
|
||||
Rem(CSSFloat),
|
||||
Ch(CSSFloat),
|
||||
Rem(CSSFloat)
|
||||
}
|
||||
|
||||
impl fmt::Debug for FontRelativeLength {
|
||||
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
|
||||
}
|
||||
|
||||
impl ToCss for FontRelativeLength {
|
||||
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
|
||||
match self {
|
||||
&FontRelativeLength::Em(length) => write!(dest, "{}em", length),
|
||||
&FontRelativeLength::Ex(length) => write!(dest, "{}ex", length),
|
||||
&FontRelativeLength::Ch(length) => write!(dest, "{}ch", length),
|
||||
&FontRelativeLength::Rem(length) => write!(dest, "{}rem", length)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FontRelativeLength {
|
||||
pub fn to_computed_value(&self,
|
||||
reference_font_size: Au,
|
||||
root_font_size: Au)
|
||||
-> Au
|
||||
{
|
||||
match self {
|
||||
&FontRelativeLength::Em(length) => reference_font_size.scale_by(length),
|
||||
&FontRelativeLength::Ex(length) => {
|
||||
let x_height = 0.5; // TODO: find that from the font
|
||||
reference_font_size.scale_by(length * x_height)
|
||||
},
|
||||
&FontRelativeLength::Ch(_) => unimplemented!(),
|
||||
&FontRelativeLength::Rem(length) => root_font_size.scale_by(length)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Copy)]
|
||||
pub struct CharacterWidth(pub i32);
|
||||
|
||||
impl CharacterWidth {
|
||||
pub fn to_computed_value(&self, reference_font_size: Au) -> Au {
|
||||
// This applies the *converting a character width to pixels* algorithm as specified
|
||||
// in HTML5 § 14.5.4.
|
||||
//
|
||||
// TODO(pcwalton): Find these from the font.
|
||||
let average_advance = reference_font_size.scale_by(0.5);
|
||||
let max_advance = reference_font_size;
|
||||
average_advance.scale_by(self.0 as CSSFloat - 1.0) + max_advance
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Copy)]
|
||||
pub enum Length {
|
||||
Absolute(Au), // application units
|
||||
FontRelative(FontRelativeLength),
|
||||
/// HTML5 "character width", as defined in HTML5 § 14.5.4.
|
||||
///
|
||||
/// This cannot be specified by the user directly and is only generated by
|
||||
/// `Stylist::synthesize_rules_for_legacy_attributes()`.
|
||||
ServoCharacterWidth(i32),
|
||||
ServoCharacterWidth(CharacterWidth),
|
||||
}
|
||||
|
||||
impl fmt::Debug for Length {
|
||||
|
@ -134,41 +187,14 @@ pub mod specified {
|
|||
impl ToCss for Length {
|
||||
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
|
||||
match self {
|
||||
&Length::Au(length) => write!(dest, "{}px", length.to_subpx()),
|
||||
&Length::Em(length) => write!(dest, "{}em", length),
|
||||
&Length::Ex(length) => write!(dest, "{}ex", length),
|
||||
&Length::Rem(length) => write!(dest, "{}rem", length),
|
||||
&Length::Absolute(length) => write!(dest, "{}px", length.to_subpx()),
|
||||
&Length::FontRelative(length) => length.to_css(dest),
|
||||
&Length::ServoCharacterWidth(_)
|
||||
=> panic!("internal CSS values should never be serialized"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Length {
|
||||
pub fn to_computed_value_with_font_size(&self, reference_font_size: Au, root_font_size: Au)
|
||||
-> Au {
|
||||
match *self {
|
||||
Length::Au(value) => value,
|
||||
Length::Em(value) => reference_font_size.scale_by(value),
|
||||
Length::Ex(value) => {
|
||||
let x_height = 0.5; // TODO: find that from the font
|
||||
reference_font_size.scale_by(value * x_height)
|
||||
},
|
||||
Length::Rem(value) => root_font_size.scale_by(value),
|
||||
Length::ServoCharacterWidth(value) => {
|
||||
// This applies the *converting a character width to pixels* algorithm as specified
|
||||
// in HTML5 § 14.5.4.
|
||||
//
|
||||
// TODO(pcwalton): Find these from the font.
|
||||
let average_advance = reference_font_size.scale_by(0.5);
|
||||
let max_advance = reference_font_size;
|
||||
average_advance.scale_by(value as CSSFloat - 1.0) + max_advance
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const AU_PER_PX: CSSFloat = 60.;
|
||||
const AU_PER_IN: CSSFloat = AU_PER_PX * 96.;
|
||||
const AU_PER_CM: CSSFloat = AU_PER_IN / 2.54;
|
||||
|
@ -182,7 +208,7 @@ pub mod specified {
|
|||
Token::Dimension(ref value, ref unit) if negative_ok || value.value >= 0. => {
|
||||
Length::parse_dimension(value.value, unit)
|
||||
}
|
||||
Token::Number(ref value) if value.value == 0. => Ok(Length::Au(Au(0))),
|
||||
Token::Number(ref value) if value.value == 0. => Ok(Length::Absolute(Au(0))),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -196,20 +222,22 @@ pub mod specified {
|
|||
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Length, ()> {
|
||||
match_ignore_ascii_case! { unit,
|
||||
"px" => Ok(Length::from_px(value)),
|
||||
"in" => Ok(Length::Au(Au((value * AU_PER_IN) as i32))),
|
||||
"cm" => Ok(Length::Au(Au((value * AU_PER_CM) as i32))),
|
||||
"mm" => Ok(Length::Au(Au((value * AU_PER_MM) as i32))),
|
||||
"pt" => Ok(Length::Au(Au((value * AU_PER_PT) as i32))),
|
||||
"pc" => Ok(Length::Au(Au((value * AU_PER_PC) as i32))),
|
||||
"em" => Ok(Length::Em(value)),
|
||||
"ex" => Ok(Length::Ex(value)),
|
||||
"rem" => Ok(Length::Rem(value))
|
||||
"in" => Ok(Length::Absolute(Au((value * AU_PER_IN) as i32))),
|
||||
"cm" => Ok(Length::Absolute(Au((value * AU_PER_CM) as i32))),
|
||||
"mm" => Ok(Length::Absolute(Au((value * AU_PER_MM) as i32))),
|
||||
"pt" => Ok(Length::Absolute(Au((value * AU_PER_PT) as i32))),
|
||||
"pc" => Ok(Length::Absolute(Au((value * AU_PER_PC) as i32))),
|
||||
// font-relative
|
||||
"em" => Ok(Length::FontRelative(FontRelativeLength::Em(value))),
|
||||
"ex" => Ok(Length::FontRelative(FontRelativeLength::Ex(value))),
|
||||
"ch" => Err(()),
|
||||
"rem" => Ok(Length::FontRelative(FontRelativeLength::Rem(value))),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn from_px(px_value: CSSFloat) -> Length {
|
||||
Length::Au(Au((px_value * AU_PER_PX) as i32))
|
||||
Length::Absolute(Au((px_value * AU_PER_PX) as i32))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,7 +273,7 @@ pub mod specified {
|
|||
Ok(LengthOrPercentage::Percentage(value.unit_value))
|
||||
}
|
||||
Token::Number(ref value) if value.value == 0. => {
|
||||
Ok(LengthOrPercentage::Length(Length::Au(Au(0))))
|
||||
Ok(LengthOrPercentage::Length(Length::Absolute(Au(0))))
|
||||
}
|
||||
_ => Err(())
|
||||
}
|
||||
|
@ -294,7 +322,7 @@ pub mod specified {
|
|||
Ok(LengthOrPercentageOrAuto::Percentage(value.unit_value))
|
||||
}
|
||||
Token::Number(ref value) if value.value == 0. => {
|
||||
Ok(LengthOrPercentageOrAuto::Length(Length::Au(Au(0))))
|
||||
Ok(LengthOrPercentageOrAuto::Length(Length::Absolute(Au(0))))
|
||||
}
|
||||
Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") => {
|
||||
Ok(LengthOrPercentageOrAuto::Auto)
|
||||
|
@ -345,7 +373,7 @@ pub mod specified {
|
|||
Ok(LengthOrPercentageOrNone::Percentage(value.unit_value))
|
||||
}
|
||||
Token::Number(ref value) if value.value == 0. => {
|
||||
Ok(LengthOrPercentageOrNone::Length(Length::Au(Au(0))))
|
||||
Ok(LengthOrPercentageOrNone::Length(Length::Absolute(Au(0))))
|
||||
}
|
||||
Token::Ident(ref value) if value.eq_ignore_ascii_case("none") => {
|
||||
Ok(LengthOrPercentageOrNone::None)
|
||||
|
@ -386,7 +414,7 @@ pub mod specified {
|
|||
Ok(PositionComponent::Percentage(value.unit_value))
|
||||
}
|
||||
Token::Number(ref value) if value.value == 0. => {
|
||||
Ok(PositionComponent::Length(Length::Au(Au(0))))
|
||||
Ok(PositionComponent::Length(Length::Absolute(Au(0))))
|
||||
}
|
||||
Token::Ident(value) => {
|
||||
match_ignore_ascii_case! { value,
|
||||
|
@ -736,7 +764,13 @@ pub mod computed {
|
|||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> Au {
|
||||
self.to_computed_value_with_font_size(context.font_size, context.root_font_size)
|
||||
match self {
|
||||
&specified::Length::Absolute(length) => length,
|
||||
&specified::Length::FontRelative(length) =>
|
||||
length.to_computed_value(context.font_size, context.root_font_size),
|
||||
&specified::Length::ServoCharacterWidth(length) =>
|
||||
length.to_computed_value(context.font_size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue