mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +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
|
@ -119,7 +119,7 @@ impl PresentationalHintSynthesis for Stylist {
|
|||
*shareable = false
|
||||
}
|
||||
LengthOrPercentageOrAuto::Length(length) => {
|
||||
let width_value = specified::LengthOrPercentageOrAuto::Length(specified::Length::Au(length));
|
||||
let width_value = specified::LengthOrPercentageOrAuto::Length(specified::Length::Absolute(length));
|
||||
matching_rules_list.vec_push(from_declaration(
|
||||
PropertyDeclaration::Width(SpecifiedValue(width_value))));
|
||||
*shareable = false
|
||||
|
@ -160,9 +160,9 @@ impl PresentationalHintSynthesis for Stylist {
|
|||
// FIXME(pcwalton): More use of atoms, please!
|
||||
let value = match element.get_attr(&ns!(""), &atom!("type")) {
|
||||
Some("text") | Some("password") => {
|
||||
specified::Length::ServoCharacterWidth(value)
|
||||
specified::Length::ServoCharacterWidth(specified::CharacterWidth(value))
|
||||
}
|
||||
_ => specified::Length::Au(Au::from_px(value as int)),
|
||||
_ => specified::Length::Absolute(Au::from_px(value as int)),
|
||||
};
|
||||
matching_rules_list.vec_push(from_declaration(
|
||||
PropertyDeclaration::Width(SpecifiedValue(
|
||||
|
@ -180,7 +180,7 @@ impl PresentationalHintSynthesis for Stylist {
|
|||
// scrollbar size into consideration (but we don't have a scrollbar yet!)
|
||||
//
|
||||
// https://html.spec.whatwg.org/multipage/rendering.html#textarea-effective-width
|
||||
let value = specified::Length::ServoCharacterWidth(value);
|
||||
let value = specified::Length::ServoCharacterWidth(specified::CharacterWidth(value));
|
||||
matching_rules_list.vec_push(from_declaration(
|
||||
PropertyDeclaration::Width(SpecifiedValue(
|
||||
specified::LengthOrPercentageOrAuto::Length(value)))));
|
||||
|
@ -193,7 +193,7 @@ impl PresentationalHintSynthesis for Stylist {
|
|||
// TODO(mttr) This should take scrollbar size into consideration.
|
||||
//
|
||||
// https://html.spec.whatwg.org/multipage/rendering.html#textarea-effective-height
|
||||
let value = specified::Length::Em(value as CSSFloat);
|
||||
let value = specified::Length::FontRelative(specified::FontRelativeLength::Em(value as CSSFloat));
|
||||
matching_rules_list.vec_push(from_declaration(
|
||||
PropertyDeclaration::Height(SpecifiedValue(
|
||||
longhands::height::SpecifiedValue(
|
||||
|
@ -241,7 +241,7 @@ impl PresentationalHintSynthesis for Stylist {
|
|||
match element.get_unsigned_integer_attribute(UnsignedIntegerAttribute::Border) {
|
||||
None => {}
|
||||
Some(length) => {
|
||||
let width_value = specified::Length::Au(Au::from_px(length as int));
|
||||
let width_value = specified::Length::Absolute(Au::from_px(length as int));
|
||||
matching_rules_list.vec_push(from_declaration(
|
||||
PropertyDeclaration::BorderTopWidth(SpecifiedValue(
|
||||
longhands::border_top_width::SpecifiedValue(width_value)))));
|
||||
|
|
|
@ -566,7 +566,7 @@ pub mod longhands {
|
|||
SpecifiedValue::Number(value) => computed_value::T::Number(value),
|
||||
SpecifiedValue::Percentage(value) => {
|
||||
computed_value::T::Length(
|
||||
specified::Length::Em(value).to_computed_value(context))
|
||||
specified::Length::FontRelative(specified::FontRelativeLength::Em(value)).to_computed_value(context))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1475,21 +1475,21 @@ pub mod longhands {
|
|||
input.try(specified::LengthOrPercentage::parse_non_negative)
|
||||
.map(|value| match value {
|
||||
specified::LengthOrPercentage::Length(value) => value,
|
||||
specified::LengthOrPercentage::Percentage(value) => specified::Length::Em(value)
|
||||
specified::LengthOrPercentage::Percentage(value) => specified::Length::FontRelative(specified::FontRelativeLength::Em(value))
|
||||
})
|
||||
.or_else(|()| {
|
||||
match_ignore_ascii_case! { try!(input.expect_ident()),
|
||||
"xx-small" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 3 / 5)),
|
||||
"x-small" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 3 / 4)),
|
||||
"small" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 8 / 9)),
|
||||
"medium" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX))),
|
||||
"large" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 6 / 5)),
|
||||
"x-large" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 3 / 2)),
|
||||
"xx-large" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 2)),
|
||||
"xx-small" => Ok(specified::Length::Absolute(Au::from_px(MEDIUM_PX) * 3 / 5)),
|
||||
"x-small" => Ok(specified::Length::Absolute(Au::from_px(MEDIUM_PX) * 3 / 4)),
|
||||
"small" => Ok(specified::Length::Absolute(Au::from_px(MEDIUM_PX) * 8 / 9)),
|
||||
"medium" => Ok(specified::Length::Absolute(Au::from_px(MEDIUM_PX))),
|
||||
"large" => Ok(specified::Length::Absolute(Au::from_px(MEDIUM_PX) * 6 / 5)),
|
||||
"x-large" => Ok(specified::Length::Absolute(Au::from_px(MEDIUM_PX) * 3 / 2)),
|
||||
"xx-large" => Ok(specified::Length::Absolute(Au::from_px(MEDIUM_PX) * 2)),
|
||||
|
||||
// https://github.com/servo/servo/issues/3423#issuecomment-56321664
|
||||
"smaller" => Ok(specified::Length::Em(0.85)),
|
||||
"larger" => Ok(specified::Length::Em(1.2))
|
||||
"smaller" => Ok(specified::Length::FontRelative(specified::FontRelativeLength::Em(0.85))),
|
||||
"larger" => Ok(specified::Length::FontRelative(specified::FontRelativeLength::Em(1.2)))
|
||||
|
||||
_ => Err(())
|
||||
}
|
||||
|
@ -2038,7 +2038,7 @@ pub mod longhands {
|
|||
|
||||
pub fn parse_one_box_shadow(input: &mut Parser) -> Result<SpecifiedBoxShadow, ()> {
|
||||
use util::geometry::Au;
|
||||
let mut lengths = [specified::Length::Au(Au(0)); 4];
|
||||
let mut lengths = [specified::Length::Absolute(Au(0)); 4];
|
||||
let mut lengths_parsed = false;
|
||||
let mut color = None;
|
||||
let mut inset = false;
|
||||
|
@ -2208,10 +2208,10 @@ pub mod longhands {
|
|||
}));
|
||||
if sides.len() == 4 {
|
||||
Ok(Some(SpecifiedClipRect {
|
||||
top: sides[0].unwrap_or(Length::Au(Au(0))),
|
||||
top: sides[0].unwrap_or(Length::Absolute(Au(0))),
|
||||
right: sides[1],
|
||||
bottom: sides[2],
|
||||
left: sides[3].unwrap_or(Length::Au(Au(0))),
|
||||
left: sides[3].unwrap_or(Length::Absolute(Au(0))),
|
||||
}))
|
||||
} else {
|
||||
Err(())
|
||||
|
@ -2317,7 +2317,7 @@ pub mod longhands {
|
|||
|
||||
fn parse_one_text_shadow(input: &mut Parser) -> Result<SpecifiedTextShadow,()> {
|
||||
use util::geometry::Au;
|
||||
let mut lengths = [specified::Length::Au(Au(0)); 3];
|
||||
let mut lengths = [specified::Length::Absolute(Au(0)); 3];
|
||||
let mut lengths_parsed = false;
|
||||
let mut color = None;
|
||||
|
||||
|
@ -2857,7 +2857,7 @@ pub mod shorthands {
|
|||
fn parse_one_set_of_border_radii(mut input: &mut Parser)
|
||||
-> Result<[LengthOrPercentage; 4], ()> {
|
||||
let mut count = 0;
|
||||
let mut values = [LengthOrPercentage::Length(Length::Au(Au(0))); 4];
|
||||
let mut values = [LengthOrPercentage::Length(Length::Absolute(Au(0))); 4];
|
||||
while count < 4 {
|
||||
if let Ok(value) = input.try(LengthOrPercentage::parse) {
|
||||
values[count] = value;
|
||||
|
@ -3773,11 +3773,7 @@ pub fn cascade(viewport_size: Size2D<Au>,
|
|||
match *declaration {
|
||||
PropertyDeclaration::FontSize(ref value) => {
|
||||
context.font_size = match *value {
|
||||
DeclaredValue::SpecifiedValue(ref specified_value) => {
|
||||
specified_value.0.to_computed_value_with_font_size(
|
||||
context.inherited_font_size, context.root_font_size
|
||||
)
|
||||
}
|
||||
DeclaredValue::SpecifiedValue(ref specified_value) => specified_value.0.to_computed_value(&context),
|
||||
DeclaredValue::Initial => longhands::font_size::get_initial_value(),
|
||||
DeclaredValue::Inherit => context.inherited_font_size,
|
||||
}
|
||||
|
|
|
@ -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