Do "computed value" calculation with a trait with an associated type.

This commit is contained in:
Simon Sapin 2015-01-29 21:32:06 +01:00
parent 0a4c8c0e4c
commit be599158e0
4 changed files with 543 additions and 351 deletions

View file

@ -10,6 +10,7 @@ use values::specified::CSSColor;
use values::{CSSFloat, specified}; use values::{CSSFloat, specified};
use properties::DeclaredValue::SpecifiedValue; use properties::DeclaredValue::SpecifiedValue;
use properties::PropertyDeclaration; use properties::PropertyDeclaration;
use properties::longhands;
use selector_matching::{DeclarationBlock, Stylist}; use selector_matching::{DeclarationBlock, Stylist};
use cssparser::Color; use cssparser::Color;
@ -191,7 +192,8 @@ impl PresentationalHintSynthesis for Stylist {
let value = specified::Length::Em(value as CSSFloat); let value = specified::Length::Em(value as CSSFloat);
matching_rules_list.vec_push(DeclarationBlock::from_declaration( matching_rules_list.vec_push(DeclarationBlock::from_declaration(
PropertyDeclaration::Height(SpecifiedValue( PropertyDeclaration::Height(SpecifiedValue(
specified::LengthOrPercentageOrAuto::Length(value))))); longhands::height::SpecifiedValue(
specified::LengthOrPercentageOrAuto::Length(value))))));
*shareable = false *shareable = false
} }
Some(_) | None => {} Some(_) | None => {}
@ -237,13 +239,17 @@ impl PresentationalHintSynthesis for Stylist {
Some(length) => { Some(length) => {
let width_value = specified::Length::Au(Au::from_px(length as int)); let width_value = specified::Length::Au(Au::from_px(length as int));
matching_rules_list.vec_push(DeclarationBlock::from_declaration( matching_rules_list.vec_push(DeclarationBlock::from_declaration(
PropertyDeclaration::BorderTopWidth(SpecifiedValue(width_value)))); PropertyDeclaration::BorderTopWidth(SpecifiedValue(
longhands::border_top_width::SpecifiedValue(width_value)))));
matching_rules_list.vec_push(DeclarationBlock::from_declaration( matching_rules_list.vec_push(DeclarationBlock::from_declaration(
PropertyDeclaration::BorderLeftWidth(SpecifiedValue(width_value)))); PropertyDeclaration::BorderLeftWidth(SpecifiedValue(
longhands::border_left_width::SpecifiedValue(width_value)))));
matching_rules_list.vec_push(DeclarationBlock::from_declaration( matching_rules_list.vec_push(DeclarationBlock::from_declaration(
PropertyDeclaration::BorderBottomWidth(SpecifiedValue(width_value)))); PropertyDeclaration::BorderBottomWidth(SpecifiedValue(
longhands::border_bottom_width::SpecifiedValue(width_value)))));
matching_rules_list.vec_push(DeclarationBlock::from_declaration( matching_rules_list.vec_push(DeclarationBlock::from_declaration(
PropertyDeclaration::BorderRightWidth(SpecifiedValue(width_value)))); PropertyDeclaration::BorderRightWidth(SpecifiedValue(
longhands::border_right_width::SpecifiedValue(width_value)))));
*shareable = false *shareable = false
} }
} }

View file

@ -8,7 +8,7 @@ use cssparser::{Token, Parser, Delimiter};
use geom::size::TypedSize2D; use geom::size::TypedSize2D;
use properties::longhands; use properties::longhands;
use util::geometry::{Au, ViewportPx}; use util::geometry::{Au, ViewportPx};
use values::{computed, specified}; use values::specified;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -98,7 +98,7 @@ fn parse_non_negative_length(input: &mut Parser) -> Result<Au, ()> {
// http://dev.w3.org/csswg/mediaqueries3/ - Section 6 // http://dev.w3.org/csswg/mediaqueries3/ - Section 6
// em units are relative to the initial font-size. // em units are relative to the initial font-size.
let initial_font_size = longhands::font_size::get_initial_value(); let initial_font_size = longhands::font_size::get_initial_value();
Ok(computed::compute_Au_with_font_size(length, initial_font_size, initial_font_size)) Ok(length.to_computed_value_with_font_size(initial_font_size, initial_font_size))
} }

File diff suppressed because it is too large Load diff

View file

@ -49,6 +49,7 @@ macro_rules! define_css_keyword_enum {
pub type CSSFloat = f64; pub type CSSFloat = f64;
pub mod specified { pub mod specified {
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::f64::consts::PI; use std::f64::consts::PI;
@ -60,7 +61,6 @@ pub mod specified {
use text_writer::{self, TextWriter}; use text_writer::{self, TextWriter};
use util::geometry::Au; use util::geometry::Au;
use super::CSSFloat; use super::CSSFloat;
use super::computed;
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub struct CSSColor { pub struct CSSColor {
@ -113,22 +113,6 @@ pub mod specified {
} }
} }
#[derive(Clone, PartialEq)]
pub struct CSSImage(pub Option<Image>);
impl fmt::Debug for CSSImage {
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
}
impl ToCss for CSSImage {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match self {
&CSSImage(Some(ref image)) => image.to_css(dest),
&CSSImage(None) => dest.write_str("none"),
}
}
}
#[derive(Clone, PartialEq, Copy)] #[derive(Clone, PartialEq, Copy)]
pub enum Length { pub enum Length {
Au(Au), // application units Au(Au), // application units
@ -160,6 +144,31 @@ pub mod specified {
} }
} }
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_PX: CSSFloat = 60.;
const AU_PER_IN: CSSFloat = AU_PER_PX * 96.; const AU_PER_IN: CSSFloat = AU_PER_PX * 96.;
const AU_PER_CM: CSSFloat = AU_PER_IN / 2.54; const AU_PER_CM: CSSFloat = AU_PER_IN / 2.54;
@ -493,16 +502,6 @@ pub mod specified {
_ => Err(()) _ => Err(())
} }
} }
pub fn to_computed_value(self, context: &computed::Context) -> computed::Image {
match self {
Image::Url(url) => computed::Image::Url(url),
Image::LinearGradient(linear_gradient) => {
computed::Image::LinearGradient(
computed::LinearGradient::compute(linear_gradient, context))
}
}
}
} }
/// Specified values for a CSS linear gradient. /// Specified values for a CSS linear gradient.
@ -701,45 +700,41 @@ pub mod computed {
// TODO, as needed: viewport size, etc. // TODO, as needed: viewport size, etc.
} }
#[allow(non_snake_case)] pub trait ToComputedValue {
#[inline] type ComputedValue;
pub fn compute_CSSColor(value: specified::CSSColor, _context: &Context) -> CSSColor {
value.parsed #[inline]
fn to_computed_value(&self, _context: &Context) -> Self::ComputedValue;
} }
#[allow(non_snake_case)] pub trait ComputedValueAsSpecified {}
#[inline]
pub fn compute_BorderStyle(value: BorderStyle, _context: &Context) -> BorderStyle { impl<T> ToComputedValue for T where T: ComputedValueAsSpecified + Clone {
value type ComputedValue = T;
#[inline]
fn to_computed_value(&self, _context: &Context) -> T {
self.clone()
}
} }
#[allow(non_snake_case)] impl ToComputedValue for specified::CSSColor {
#[inline] type ComputedValue = CSSColor;
pub fn compute_Au(value: specified::Length, context: &Context) -> Au {
compute_Au_with_font_size(value, context.font_size, context.root_font_size) #[inline]
fn to_computed_value(&self, _context: &Context) -> CSSColor {
self.parsed
}
} }
/// A special version of `compute_Au` used for `font-size`. impl ComputedValueAsSpecified for specified::BorderStyle {}
#[allow(non_snake_case)]
#[inline] impl ToComputedValue for specified::Length {
pub fn compute_Au_with_font_size(value: specified::Length, reference_font_size: Au, root_font_size: Au) -> Au { type ComputedValue = Au;
match value {
specified::Length::Au(value) => value, #[inline]
specified::Length::Em(value) => reference_font_size.scale_by(value), fn to_computed_value(&self, context: &Context) -> Au {
specified::Length::Ex(value) => { self.to_computed_value_with_font_size(context.font_size, context.root_font_size)
let x_height = 0.5; // TODO: find that from the font
reference_font_size.scale_by(value * x_height)
},
specified::Length::Rem(value) => root_font_size.scale_by(value),
specified::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
}
} }
} }
@ -757,14 +752,18 @@ pub mod computed {
} }
} }
#[allow(non_snake_case)] impl ToComputedValue for specified::LengthOrPercentage {
pub fn compute_LengthOrPercentage(value: specified::LengthOrPercentage, context: &Context) type ComputedValue = LengthOrPercentage;
-> LengthOrPercentage {
match value { fn to_computed_value(&self, context: &Context) -> LengthOrPercentage {
specified::LengthOrPercentage::Length(value) => match *self {
LengthOrPercentage::Length(compute_Au(value, context)), specified::LengthOrPercentage::Length(value) => {
specified::LengthOrPercentage::Percentage(value) => LengthOrPercentage::Length(value.to_computed_value(context))
LengthOrPercentage::Percentage(value), }
specified::LengthOrPercentage::Percentage(value) => {
LengthOrPercentage::Percentage(value)
}
}
} }
} }
@ -783,16 +782,23 @@ pub mod computed {
} }
} }
} }
#[allow(non_snake_case)]
pub fn compute_LengthOrPercentageOrAuto(value: specified::LengthOrPercentageOrAuto, impl ToComputedValue for specified::LengthOrPercentageOrAuto {
context: &Context) -> LengthOrPercentageOrAuto { type ComputedValue = LengthOrPercentageOrAuto;
match value {
specified::LengthOrPercentageOrAuto::Length(value) => #[inline]
LengthOrPercentageOrAuto::Length(compute_Au(value, context)), fn to_computed_value(&self, context: &Context) -> LengthOrPercentageOrAuto {
specified::LengthOrPercentageOrAuto::Percentage(value) => match *self {
LengthOrPercentageOrAuto::Percentage(value), specified::LengthOrPercentageOrAuto::Length(value) => {
specified::LengthOrPercentageOrAuto::Auto => LengthOrPercentageOrAuto::Length(value.to_computed_value(context))
LengthOrPercentageOrAuto::Auto, }
specified::LengthOrPercentageOrAuto::Percentage(value) => {
LengthOrPercentageOrAuto::Percentage(value)
}
specified::LengthOrPercentageOrAuto::Auto => {
LengthOrPercentageOrAuto::Auto
}
}
} }
} }
@ -811,19 +817,42 @@ pub mod computed {
} }
} }
} }
#[allow(non_snake_case)]
pub fn compute_LengthOrPercentageOrNone(value: specified::LengthOrPercentageOrNone, impl ToComputedValue for specified::LengthOrPercentageOrNone {
context: &Context) -> LengthOrPercentageOrNone { type ComputedValue = LengthOrPercentageOrNone;
match value {
specified::LengthOrPercentageOrNone::Length(value) => #[inline]
LengthOrPercentageOrNone::Length(compute_Au(value, context)), fn to_computed_value(&self, context: &Context) -> LengthOrPercentageOrNone {
specified::LengthOrPercentageOrNone::Percentage(value) => match *self {
LengthOrPercentageOrNone::Percentage(value), specified::LengthOrPercentageOrNone::Length(value) => {
specified::LengthOrPercentageOrNone::None => LengthOrPercentageOrNone::Length(value.to_computed_value(context))
LengthOrPercentageOrNone::None, }
specified::LengthOrPercentageOrNone::Percentage(value) => {
LengthOrPercentageOrNone::Percentage(value)
}
specified::LengthOrPercentageOrNone::None => {
LengthOrPercentageOrNone::None
}
}
} }
} }
impl ToComputedValue for specified::Image {
type ComputedValue = Image;
#[inline]
fn to_computed_value(&self, context: &Context) -> Image {
match *self {
specified::Image::Url(ref url) => Image::Url(url.clone()),
specified::Image::LinearGradient(ref linear_gradient) => {
Image::LinearGradient(linear_gradient.to_computed_value(context))
}
}
}
}
/// Computed values for an image according to CSS-IMAGES. /// Computed values for an image according to CSS-IMAGES.
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub enum Image { pub enum Image {
@ -881,32 +910,28 @@ pub mod computed {
} }
} }
impl LinearGradient { impl ToComputedValue for specified::LinearGradient {
pub fn compute(value: specified::LinearGradient, context: &Context) -> LinearGradient { type ComputedValue = LinearGradient;
#[inline]
fn to_computed_value(&self, context: &Context) -> LinearGradient {
let specified::LinearGradient { let specified::LinearGradient {
angle_or_corner, angle_or_corner,
stops ref stops
} = value; } = *self;
LinearGradient { LinearGradient {
angle_or_corner: angle_or_corner, angle_or_corner: angle_or_corner,
stops: stops.into_iter().map(|stop| { stops: stops.iter().map(|stop| {
ColorStop { ColorStop {
color: stop.color.parsed, color: stop.color.parsed,
position: match stop.position { position: match stop.position {
None => None, None => None,
Some(value) => Some(compute_LengthOrPercentage(value, context)), Some(value) => Some(value.to_computed_value(context)),
}, },
} }
}).collect() }).collect()
} }
} }
} }
#[allow(non_snake_case)]
#[inline]
pub fn compute_Length(value: specified::Length, context: &Context) -> Au {
compute_Au(value, context)
}
pub type Length = Au; pub type Length = Au;
} }