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

View file

@ -20,7 +20,7 @@ use cssparser::{Parser, Color, RGBA, AtRuleParser, DeclarationParser,
use geom::SideOffsets2D; use geom::SideOffsets2D;
use values::specified::BorderStyle; use values::specified::BorderStyle;
use values::computed; use values::computed::{self, ToComputedValue};
use selector_matching::DeclarationBlock; use selector_matching::DeclarationBlock;
use parser::{ParserContext, log_css_error}; use parser::{ParserContext, log_css_error};
use stylesheets::Origin; use stylesheets::Origin;
@ -95,11 +95,6 @@ def switch_to_style_struct(name):
%> %>
pub mod longhands { pub mod longhands {
use values::computed;
pub fn computed_as_specified<T>(value: T, _context: &computed::Context) -> T {
value
}
<%def name="raw_longhand(name, derived_from=None, experimental=False)"> <%def name="raw_longhand(name, derived_from=None, experimental=False)">
<% <%
@ -177,8 +172,8 @@ pub mod longhands {
<%self:single_keyword_computed name="${name}" <%self:single_keyword_computed name="${name}"
values="${values}" values="${values}"
experimental="${experimental}"> experimental="${experimental}">
// The computed value is the same as the specified value. use values::computed::ComputedValueAsSpecified;
pub use super::computed_as_specified as to_computed_value; impl ComputedValueAsSpecified for SpecifiedValue {}
</%self:single_keyword_computed> </%self:single_keyword_computed>
</%def> </%def>
@ -186,7 +181,6 @@ pub mod longhands {
<%self:longhand name="${name}"> <%self:longhand name="${name}">
#[allow(unused_imports)] #[allow(unused_imports)]
use util::geometry::Au; use util::geometry::Au;
pub use values::computed::compute_${type} as to_computed_value;
pub type SpecifiedValue = specified::${type}; pub type SpecifiedValue = specified::${type};
pub mod computed_value { pub mod computed_value {
pub use values::computed::${type} as T; pub use values::computed::${type} as T;
@ -224,18 +218,29 @@ pub mod longhands {
% endfor % endfor
% for side in ["top", "right", "bottom", "left"]: % for side in ["top", "right", "bottom", "left"]:
${predefined_type("border-%s-style" % side, "BorderStyle", "computed::BorderStyle::none")} ${predefined_type("border-%s-style" % side, "BorderStyle", "specified::BorderStyle::none")}
% endfor % endfor
% for side in ["top", "right", "bottom", "left"]: % for side in ["top", "right", "bottom", "left"]:
<%self:longhand name="border-${side}-width"> <%self:longhand name="border-${side}-width">
use values::computed::{ToComputedValue, Context};
use util::geometry::Au; use util::geometry::Au;
use cssparser::ToCss;
use text_writer::{self, TextWriter};
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
self.0.to_css(dest)
}
}
#[inline] #[inline]
pub fn parse(_context: &ParserContext, input: &mut Parser) pub fn parse(_context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> { -> Result<SpecifiedValue, ()> {
specified::parse_border_width(input) specified::parse_border_width(input).map(SpecifiedValue)
} }
pub type SpecifiedValue = specified::Length; #[derive(Clone, PartialEq)]
pub struct SpecifiedValue(pub specified::Length);
pub mod computed_value { pub mod computed_value {
use util::geometry::Au; use util::geometry::Au;
pub type T = Au; pub type T = Au;
@ -243,13 +248,17 @@ pub mod longhands {
#[inline] pub fn get_initial_value() -> computed_value::T { #[inline] pub fn get_initial_value() -> computed_value::T {
Au::from_px(3) // medium Au::from_px(3) // medium
} }
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline] #[inline]
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) fn to_computed_value(&self, context: &Context) -> computed_value::T {
-> computed_value::T {
if !context.border_${side}_present { if !context.border_${side}_present {
Au(0) Au(0)
} else { } else {
computed::compute_Au(value, context) self.0.to_computed_value(context)
}
} }
} }
</%self:longhand> </%self:longhand>
@ -269,7 +278,6 @@ pub mod longhands {
<%self:longhand name="outline-style"> <%self:longhand name="outline-style">
pub use values::specified::BorderStyle as SpecifiedValue; pub use values::specified::BorderStyle as SpecifiedValue;
pub use super::computed_as_specified as to_computed_value;
pub fn get_initial_value() -> SpecifiedValue { SpecifiedValue::none } pub fn get_initial_value() -> SpecifiedValue { SpecifiedValue::none }
pub mod computed_value { pub mod computed_value {
pub use values::specified::BorderStyle as T; pub use values::specified::BorderStyle as T;
@ -283,12 +291,14 @@ pub mod longhands {
</%self:longhand> </%self:longhand>
<%self:longhand name="outline-width"> <%self:longhand name="outline-width">
pub use super::border_top_width::{get_initial_value, parse}; pub use super::border_top_width::get_initial_value;
pub use values::computed::compute_Au as to_computed_value; pub type SpecifiedValue = specified::Length;
pub type SpecifiedValue = super::border_top_width::SpecifiedValue;
pub mod computed_value { pub mod computed_value {
pub use util::geometry::Au as T; pub use util::geometry::Au as T;
} }
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
specified::parse_border_width(input)
}
</%self:longhand> </%self:longhand>
${predefined_type("outline-offset", "Length", "Au(0)")} ${predefined_type("outline-offset", "Length", "Au(0)")}
@ -311,15 +321,19 @@ pub mod longhands {
table-row table-column-group table-column table-cell table-caption table-row table-column-group table-column table-cell table-caption
list-item list-item
none"> none">
use values::computed::{ToComputedValue, Context};
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline] #[inline]
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) fn to_computed_value(&self, context: &Context) -> computed_value::T {
-> computed_value::T {
use self::computed_value::T; use self::computed_value::T;
// if context.is_root_element && value == list_item { // if context.is_root_element && value == list_item {
// return block // return block
// } // }
if context.positioned || context.floated || context.is_root_element { if context.positioned || context.floated || context.is_root_element {
match value { match *self {
T::inline_table => T::table, T::inline_table => T::table,
T::inline | T::inline_block | T::inline | T::inline_block |
T::table_row_group | T::table_column | T::table_row_group | T::table_column |
@ -327,10 +341,11 @@ pub mod longhands {
T::table_footer_group | T::table_row | T::table_cell | T::table_footer_group | T::table_row | T::table_cell |
T::table_caption T::table_caption
=> T::block, => T::block,
_ => value, _ => *self,
} }
} else { } else {
value *self
}
} }
} }
</%self:single_keyword_computed> </%self:single_keyword_computed>
@ -340,7 +355,6 @@ pub mod longhands {
${single_keyword("clear", "none left right both")} ${single_keyword("clear", "none left right both")}
<%self:longhand name="-servo-display-for-hypothetical-box" derived_from="display"> <%self:longhand name="-servo-display-for-hypothetical-box" derived_from="display">
pub use super::computed_as_specified as to_computed_value;
pub use super::display::{SpecifiedValue, get_initial_value}; pub use super::display::{SpecifiedValue, get_initial_value};
pub use super::display::{parse}; pub use super::display::{parse};
@ -358,7 +372,9 @@ pub mod longhands {
</%self:longhand> </%self:longhand>
<%self:longhand name="z-index"> <%self:longhand name="z-index">
pub use super::computed_as_specified as to_computed_value; use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {}
pub type SpecifiedValue = computed_value::T; pub type SpecifiedValue = computed_value::T;
pub mod computed_value { pub mod computed_value {
use cssparser::ToCss; use cssparser::ToCss;
@ -413,7 +429,18 @@ pub mod longhands {
"computed::LengthOrPercentageOrAuto::Auto", "computed::LengthOrPercentageOrAuto::Auto",
"parse_non_negative")} "parse_non_negative")}
<%self:longhand name="height"> <%self:longhand name="height">
pub type SpecifiedValue = specified::LengthOrPercentageOrAuto; use values::computed::{ToComputedValue, Context};
use cssparser::ToCss;
use text_writer::{self, TextWriter};
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
self.0.to_css(dest)
}
}
#[derive(Clone, PartialEq)]
pub struct SpecifiedValue(pub specified::LengthOrPercentageOrAuto);
pub mod computed_value { pub mod computed_value {
pub use values::computed::LengthOrPercentageOrAuto as T; pub use values::computed::LengthOrPercentageOrAuto as T;
} }
@ -421,17 +448,22 @@ pub mod longhands {
pub fn get_initial_value() -> computed_value::T { computed::LengthOrPercentageOrAuto::Auto } pub fn get_initial_value() -> computed_value::T { computed::LengthOrPercentageOrAuto::Auto }
#[inline] #[inline]
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> { pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
specified::LengthOrPercentageOrAuto::parse_non_negative(input) specified::LengthOrPercentageOrAuto::parse_non_negative(input).map(SpecifiedValue)
} }
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
-> computed_value::T { impl ToComputedValue for SpecifiedValue {
match (value, context.inherited_height) { type ComputedValue = computed_value::T;
#[inline]
fn to_computed_value(&self, context: &Context) -> computed_value::T {
match (self.0, context.inherited_height) {
(specified::LengthOrPercentageOrAuto::Percentage(_), (specified::LengthOrPercentageOrAuto::Percentage(_),
computed::LengthOrPercentageOrAuto::Auto) computed::LengthOrPercentageOrAuto::Auto)
if !context.is_root_element && !context.positioned => { if !context.is_root_element && !context.positioned => {
computed::LengthOrPercentageOrAuto::Auto computed::LengthOrPercentageOrAuto::Auto
}, },
_ => computed::compute_LengthOrPercentageOrAuto(value, context) _ => self.0.to_computed_value(context)
}
} }
} }
</%self:longhand> </%self:longhand>
@ -453,6 +485,7 @@ pub mod longhands {
${switch_to_style_struct("InheritedBox")} ${switch_to_style_struct("InheritedBox")}
<%self:longhand name="line-height"> <%self:longhand name="line-height">
use values::computed::{ToComputedValue, Context};
use cssparser::ToCss; use cssparser::ToCss;
use text_writer::{self, TextWriter}; use text_writer::{self, TextWriter};
use values::CSSFloat; use values::CSSFloat;
@ -518,18 +551,22 @@ pub mod longhands {
} }
#[inline] #[inline]
pub fn get_initial_value() -> computed_value::T { computed_value::T::Normal } pub fn get_initial_value() -> computed_value::T { computed_value::T::Normal }
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline] #[inline]
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) fn to_computed_value(&self, context: &Context) -> computed_value::T {
-> computed_value::T { match *self {
match value {
SpecifiedValue::Normal => computed_value::T::Normal, SpecifiedValue::Normal => computed_value::T::Normal,
SpecifiedValue::Length(value) => { SpecifiedValue::Length(value) => {
computed_value::T::Length(computed::compute_Au(value, context)) computed_value::T::Length(value.to_computed_value(context))
} }
SpecifiedValue::Number(value) => computed_value::T::Number(value), SpecifiedValue::Number(value) => computed_value::T::Number(value),
SpecifiedValue::Percentage(value) => { SpecifiedValue::Percentage(value) => {
computed_value::T::Length(computed::compute_Au( computed_value::T::Length(
specified::Length::Em(value), context)) specified::Length::Em(value).to_computed_value(context))
}
} }
} }
} }
@ -538,6 +575,7 @@ pub mod longhands {
${switch_to_style_struct("Box")} ${switch_to_style_struct("Box")}
<%self:longhand name="vertical-align"> <%self:longhand name="vertical-align">
use values::computed::{ToComputedValue, Context};
use cssparser::ToCss; use cssparser::ToCss;
use text_writer::{self, TextWriter}; use text_writer::{self, TextWriter};
@ -608,17 +646,20 @@ pub mod longhands {
} }
#[inline] #[inline]
pub fn get_initial_value() -> computed_value::T { computed_value::T::baseline } pub fn get_initial_value() -> computed_value::T { computed_value::T::baseline }
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline] #[inline]
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) fn to_computed_value(&self, context: &Context) -> computed_value::T {
-> computed_value::T { match *self {
match value {
% for keyword in vertical_align_keywords: % for keyword in vertical_align_keywords:
SpecifiedValue::${to_rust_ident(keyword)} => { SpecifiedValue::${to_rust_ident(keyword)} => {
computed_value::T::${to_rust_ident(keyword)} computed_value::T::${to_rust_ident(keyword)}
} }
% endfor % endfor
SpecifiedValue::LengthOrPercentage(value) => { SpecifiedValue::LengthOrPercentage(value) => {
match computed::compute_LengthOrPercentage(value, context) { match value.to_computed_value(context) {
computed::LengthOrPercentage::Length(value) => { computed::LengthOrPercentage::Length(value) => {
computed_value::T::Length(value) computed_value::T::Length(value)
} }
@ -629,6 +670,7 @@ pub mod longhands {
} }
} }
} }
}
</%self:longhand> </%self:longhand>
@ -646,10 +688,12 @@ pub mod longhands {
${switch_to_style_struct("Box")} ${switch_to_style_struct("Box")}
<%self:longhand name="content"> <%self:longhand name="content">
pub use super::computed_as_specified as to_computed_value;
pub use self::computed_value::T as SpecifiedValue; pub use self::computed_value::T as SpecifiedValue;
pub use self::computed_value::ContentItem; pub use self::computed_value::ContentItem;
use cssparser::Token; use cssparser::Token;
use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {}
pub mod computed_value { pub mod computed_value {
use std::borrow::IntoCow; use std::borrow::IntoCow;
@ -746,6 +790,7 @@ pub mod longhands {
use url::Url; use url::Url;
use cssparser::{ToCss, Token}; use cssparser::{ToCss, Token};
use text_writer::{self, TextWriter}; use text_writer::{self, TextWriter};
use values::computed::{ToComputedValue, Context};
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub enum SpecifiedValue { pub enum SpecifiedValue {
@ -769,11 +814,15 @@ pub mod longhands {
pub type T = Option<Url>; pub type T = Option<Url>;
} }
pub fn to_computed_value(value: SpecifiedValue, _context: &computed::Context) impl ToComputedValue for SpecifiedValue {
-> computed_value::T { type ComputedValue = computed_value::T;
match value {
#[inline]
fn to_computed_value(&self, _context: &Context) -> computed_value::T {
match *self {
SpecifiedValue::None => None, SpecifiedValue::None => None,
SpecifiedValue::Url(url) => Some(url), SpecifiedValue::Url(ref url) => Some(url.clone()),
}
} }
} }
@ -799,28 +848,48 @@ pub mod longhands {
"::cssparser::Color::RGBA(::cssparser::RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) /* transparent */")} "::cssparser::Color::RGBA(::cssparser::RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) /* transparent */")}
<%self:longhand name="background-image"> <%self:longhand name="background-image">
use values::specified::{CSSImage, Image}; use values::specified::Image;
use values::computed::{ToComputedValue, Context};
use cssparser::ToCss;
use text_writer::{self, TextWriter};
pub mod computed_value { pub mod computed_value {
use values::computed; use values::computed;
pub type T = Option<computed::Image>; pub type T = Option<computed::Image>;
} }
pub type SpecifiedValue = CSSImage;
#[derive(Clone, PartialEq)]
pub struct SpecifiedValue(pub Option<Image>);
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
match *self {
SpecifiedValue(Some(ref image)) => image.to_css(dest),
SpecifiedValue(None) => dest.write_str("none"),
}
}
}
#[inline] #[inline]
pub fn get_initial_value() -> computed_value::T { pub fn get_initial_value() -> computed_value::T {
None None
} }
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> { pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() { if input.try(|input| input.expect_ident_matching("none")).is_ok() {
Ok(CSSImage(None)) Ok(SpecifiedValue(None))
} else { } else {
Ok(CSSImage(Some(try!(Image::parse(context, input))))) Ok(SpecifiedValue(Some(try!(Image::parse(context, input)))))
} }
} }
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) impl ToComputedValue for SpecifiedValue {
-> computed_value::T { type ComputedValue = computed_value::T;
match value {
CSSImage(None) => None, #[inline]
CSSImage(Some(image)) => Some(image.to_computed_value(context)), fn to_computed_value(&self, context: &Context) -> computed_value::T {
match *self {
SpecifiedValue(None) => None,
SpecifiedValue(Some(ref image)) => Some(image.to_computed_value(context)),
}
} }
} }
</%self:longhand> </%self:longhand>
@ -828,6 +897,7 @@ pub mod longhands {
<%self:longhand name="background-position"> <%self:longhand name="background-position">
use cssparser::ToCss; use cssparser::ToCss;
use text_writer::{self, TextWriter}; use text_writer::{self, TextWriter};
use values::computed::{ToComputedValue, Context};
pub mod computed_value { pub mod computed_value {
use values::computed::LengthOrPercentage; use values::computed::LengthOrPercentage;
@ -900,12 +970,15 @@ pub mod longhands {
} }
} }
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline] #[inline]
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) fn to_computed_value(&self, context: &Context) -> computed_value::T {
-> computed_value::T {
computed_value::T { computed_value::T {
horizontal: computed::compute_LengthOrPercentage(value.horizontal, context), horizontal: self.horizontal.to_computed_value(context),
vertical: computed::compute_LengthOrPercentage(value.vertical, context), vertical: self.vertical.to_computed_value(context),
}
} }
} }
@ -935,10 +1008,15 @@ pub mod longhands {
<%self:raw_longhand name="color"> <%self:raw_longhand name="color">
use cssparser::{Color, RGBA}; use cssparser::{Color, RGBA};
use values::specified::{CSSColor, CSSRGBA}; use values::specified::{CSSColor, CSSRGBA};
use values::computed::{ToComputedValue, Context};
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline] #[inline]
pub fn to_computed_value(value: SpecifiedValue, _context: &computed::Context) fn to_computed_value(&self, _context: &Context) -> computed_value::T {
-> computed_value::T { self.parsed
value.parsed }
} }
pub type SpecifiedValue = CSSRGBA; pub type SpecifiedValue = CSSRGBA;
@ -968,9 +1046,11 @@ pub mod longhands {
${new_style_struct("Font", is_inherited=True)} ${new_style_struct("Font", is_inherited=True)}
<%self:longhand name="font-family"> <%self:longhand name="font-family">
pub use super::computed_as_specified as to_computed_value;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use self::computed_value::FontFamily; use self::computed_value::FontFamily;
use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {}
pub mod computed_value { pub mod computed_value {
use cssparser::ToCss; use cssparser::ToCss;
use text_writer::{self, TextWriter}; use text_writer::{self, TextWriter};
@ -1053,6 +1133,7 @@ pub mod longhands {
<%self:longhand name="font-weight"> <%self:longhand name="font-weight">
use cssparser::ToCss; use cssparser::ToCss;
use text_writer::{self, TextWriter}; use text_writer::{self, TextWriter};
use values::computed::{ToComputedValue, Context};
#[derive(Clone, PartialEq, Eq, Copy)] #[derive(Clone, PartialEq, Eq, Copy)]
pub enum SpecifiedValue { pub enum SpecifiedValue {
@ -1130,10 +1211,13 @@ pub mod longhands {
pub fn get_initial_value() -> computed_value::T { pub fn get_initial_value() -> computed_value::T {
computed_value::T::Weight400 // normal computed_value::T::Weight400 // normal
} }
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline] #[inline]
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) fn to_computed_value(&self, context: &Context) -> computed_value::T {
-> computed_value::T { match *self {
match value {
% for weight in range(100, 901, 100): % for weight in range(100, 901, 100):
SpecifiedValue::Weight${weight} => computed_value::T::Weight${weight}, SpecifiedValue::Weight${weight} => computed_value::T::Weight${weight},
% endfor % endfor
@ -1161,11 +1245,23 @@ pub mod longhands {
}, },
} }
} }
}
</%self:longhand> </%self:longhand>
<%self:longhand name="font-size"> <%self:longhand name="font-size">
use util::geometry::Au; use util::geometry::Au;
pub type SpecifiedValue = specified::Length; // Percentages are the same as em. use values::computed::{ToComputedValue, Context};
use cssparser::ToCss;
use text_writer::{self, TextWriter};
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
self.0.to_css(dest)
}
}
#[derive(Clone, PartialEq)]
pub struct SpecifiedValue(pub specified::Length); // Percentages are the same as em.
pub mod computed_value { pub mod computed_value {
use util::geometry::Au; use util::geometry::Au;
pub type T = Au; pub type T = Au;
@ -1174,12 +1270,16 @@ pub mod longhands {
#[inline] pub fn get_initial_value() -> computed_value::T { #[inline] pub fn get_initial_value() -> computed_value::T {
Au::from_px(MEDIUM_PX) Au::from_px(MEDIUM_PX)
} }
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline] #[inline]
pub fn to_computed_value(_value: SpecifiedValue, context: &computed::Context) fn to_computed_value(&self, context: &Context) -> computed_value::T {
-> computed_value::T {
// We already computed this element's font size; no need to compute it again. // We already computed this element's font size; no need to compute it again.
return context.font_size return context.font_size
} }
}
/// <length> | <percentage> | <absolute-size> | <relative-size> /// <length> | <percentage> | <absolute-size> | <relative-size>
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> { pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
input.try(specified::LengthOrPercentage::parse_non_negative) input.try(specified::LengthOrPercentage::parse_non_negative)
@ -1204,6 +1304,7 @@ pub mod longhands {
_ => Err(()) _ => Err(())
} }
}) })
.map(SpecifiedValue)
} }
</%self:longhand> </%self:longhand>
@ -1218,6 +1319,7 @@ pub mod longhands {
${single_keyword("text-align", "left right center justify")} ${single_keyword("text-align", "left right center justify")}
<%self:longhand name="letter-spacing"> <%self:longhand name="letter-spacing">
use values::computed::{ToComputedValue, Context};
use cssparser::ToCss; use cssparser::ToCss;
use text_writer::{self, TextWriter}; use text_writer::{self, TextWriter};
@ -1246,12 +1348,15 @@ pub mod longhands {
None None
} }
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline] #[inline]
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) fn to_computed_value(&self, context: &Context) -> computed_value::T {
-> computed_value::T { match *self {
match value {
SpecifiedValue::Normal => None, SpecifiedValue::Normal => None,
SpecifiedValue::Specified(l) => Some(computed::compute_Au(l, context)) SpecifiedValue::Specified(l) => Some(l.to_computed_value(context))
}
} }
} }
@ -1265,6 +1370,7 @@ pub mod longhands {
</%self:longhand> </%self:longhand>
<%self:longhand name="word-spacing"> <%self:longhand name="word-spacing">
use values::computed::{ToComputedValue, Context};
use cssparser::ToCss; use cssparser::ToCss;
use text_writer::{self, TextWriter}; use text_writer::{self, TextWriter};
@ -1293,12 +1399,15 @@ pub mod longhands {
None None
} }
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline] #[inline]
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) fn to_computed_value(&self, context: &Context) -> computed_value::T {
-> computed_value::T { match *self {
match value {
SpecifiedValue::Normal => None, SpecifiedValue::Normal => None,
SpecifiedValue::Specified(l) => Some(computed::compute_Au(l, context)) SpecifiedValue::Specified(l) => Some(l.to_computed_value(context))
}
} }
} }
@ -1328,9 +1437,11 @@ pub mod longhands {
${new_style_struct("Text", is_inherited=False)} ${new_style_struct("Text", is_inherited=False)}
<%self:longhand name="text-decoration"> <%self:longhand name="text-decoration">
pub use super::computed_as_specified as to_computed_value;
use cssparser::ToCss; use cssparser::ToCss;
use text_writer::{self, TextWriter}; use text_writer::{self, TextWriter};
use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {}
#[derive(PartialEq, Eq, Copy, Clone)] #[derive(PartialEq, Eq, Copy, Clone)]
pub struct SpecifiedValue { pub struct SpecifiedValue {
@ -1406,7 +1517,9 @@ pub mod longhands {
<%self:longhand name="-servo-text-decorations-in-effect" <%self:longhand name="-servo-text-decorations-in-effect"
derived_from="display text-decoration"> derived_from="display text-decoration">
use cssparser::RGBA; use cssparser::RGBA;
pub use super::computed_as_specified as to_computed_value; use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {}
#[derive(Clone, PartialEq, Copy)] #[derive(Clone, PartialEq, Copy)]
pub struct SpecifiedValue { pub struct SpecifiedValue {
@ -1521,8 +1634,10 @@ pub mod longhands {
<%self:longhand name="cursor"> <%self:longhand name="cursor">
use util::cursor as util_cursor; use util::cursor as util_cursor;
pub use super::computed_as_specified as to_computed_value;
pub use self::computed_value::T as SpecifiedValue; pub use self::computed_value::T as SpecifiedValue;
use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {}
pub mod computed_value { pub mod computed_value {
use cssparser::ToCss; use cssparser::ToCss;
@ -1571,7 +1686,18 @@ pub mod longhands {
<%self:longhand name="opacity"> <%self:longhand name="opacity">
use values::CSSFloat; use values::CSSFloat;
pub type SpecifiedValue = CSSFloat; use values::computed::{ToComputedValue, Context};
use cssparser::ToCss;
use text_writer::{self, TextWriter};
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
self.0.to_css(dest)
}
}
#[derive(Clone, PartialEq)]
pub struct SpecifiedValue(pub CSSFloat);
pub mod computed_value { pub mod computed_value {
use values::CSSFloat; use values::CSSFloat;
pub type T = CSSFloat; pub type T = CSSFloat;
@ -1580,25 +1706,30 @@ pub mod longhands {
pub fn get_initial_value() -> computed_value::T { pub fn get_initial_value() -> computed_value::T {
1.0 1.0
} }
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline] #[inline]
pub fn to_computed_value(value: SpecifiedValue, _: &computed::Context) fn to_computed_value(&self, _context: &Context) -> computed_value::T {
-> computed_value::T { if self.0 < 0.0 {
if value < 0.0 {
0.0 0.0
} else if value > 1.0 { } else if self.0 > 1.0 {
1.0 1.0
} else { } else {
value self.0
}
} }
} }
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> { fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
input.expect_number() input.expect_number().map(SpecifiedValue)
} }
</%self:longhand> </%self:longhand>
<%self:longhand name="box-shadow"> <%self:longhand name="box-shadow">
use cssparser::{self, ToCss}; use cssparser::{self, ToCss};
use text_writer::{self, TextWriter}; use text_writer::{self, TextWriter};
use values::computed::{ToComputedValue, Context};
pub type SpecifiedValue = Vec<SpecifiedBoxShadow>; pub type SpecifiedValue = Vec<SpecifiedBoxShadow>;
@ -1692,19 +1823,24 @@ pub mod longhands {
} }
} }
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) impl ToComputedValue for SpecifiedValue {
-> computed_value::T { type ComputedValue = computed_value::T;
value.into_iter().map(|value| compute_one_box_shadow(value, context)).collect()
#[inline]
fn to_computed_value(&self, context: &Context) -> computed_value::T {
self.iter().map(|value| compute_one_box_shadow(value, context)).collect()
}
} }
pub fn compute_one_box_shadow(value: SpecifiedBoxShadow, context: &computed::Context) pub fn compute_one_box_shadow(value: &SpecifiedBoxShadow, context: &computed::Context)
-> computed_value::BoxShadow { -> computed_value::BoxShadow {
computed_value::BoxShadow { computed_value::BoxShadow {
offset_x: computed::compute_Au(value.offset_x, context), offset_x: value.offset_x.to_computed_value(context),
offset_y: computed::compute_Au(value.offset_y, context), offset_y: value.offset_y.to_computed_value(context),
blur_radius: computed::compute_Au(value.blur_radius, context), blur_radius: value.blur_radius.to_computed_value(context),
spread_radius: computed::compute_Au(value.spread_radius, context), spread_radius: value.spread_radius.to_computed_value(context),
color: value.color color: value.color
.as_ref()
.map(|color| color.parsed) .map(|color| color.parsed)
.unwrap_or(cssparser::Color::CurrentColor), .unwrap_or(cssparser::Color::CurrentColor),
inset: value.inset, inset: value.inset,
@ -1778,6 +1914,8 @@ pub mod longhands {
// NB: `top` and `left` are 0 if `auto` per CSS 2.1 11.1.2. // NB: `top` and `left` are 0 if `auto` per CSS 2.1 11.1.2.
use values::computed::{ToComputedValue, Context};
pub mod computed_value { pub mod computed_value {
use util::geometry::Au; use util::geometry::Au;
@ -1845,15 +1983,19 @@ pub mod longhands {
None None
} }
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) impl ToComputedValue for SpecifiedValue {
-> computed_value::T { type ComputedValue = computed_value::T;
value.map(|value| computed_value::ClipRect {
top: computed::compute_Au(value.top, context), #[inline]
right: value.right.map(|right| computed::compute_Au(right, context)), fn to_computed_value(&self, context: &Context) -> computed_value::T {
bottom: value.bottom.map(|bottom| computed::compute_Au(bottom, context)), self.map(|value| computed_value::ClipRect {
left: computed::compute_Au(value.left, context), top: value.top.to_computed_value(context),
right: value.right.map(|right| right.to_computed_value(context)),
bottom: value.bottom.map(|bottom| bottom.to_computed_value(context)),
left: value.left.to_computed_value(context),
}) })
} }
}
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> { pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
@ -1890,9 +2032,11 @@ pub mod longhands {
<%self:longhand name="filter"> <%self:longhand name="filter">
use values::specified::Angle; use values::specified::Angle;
pub use super::computed_as_specified as to_computed_value;
pub use self::computed_value::T as SpecifiedValue; pub use self::computed_value::T as SpecifiedValue;
pub use self::computed_value::Filter; pub use self::computed_value::Filter;
use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {}
pub mod computed_value { pub mod computed_value {
use values::specified::Angle; use values::specified::Angle;
@ -2068,22 +2212,18 @@ pub mod shorthands {
} }
</%def> </%def>
<%def name="four_sides_shorthand(name, sub_property_pattern, parser_function)"> fn parse_four_sides<F, T>(input: &mut Parser, parse_one: F) -> Result<(T, T, T, T), ()>
<%self:shorthand name="${name}" sub_properties="${ where F: Fn(&mut Parser) -> Result<T, ()>, F: Copy, T: Clone {
' '.join(sub_property_pattern % side
for side in ['top', 'right', 'bottom', 'left'])}">
use values::specified;
let _unused = context;
// zero or more than four values is invalid. // zero or more than four values is invalid.
// one value sets them all // one value sets them all
// two values set (top, bottom) and (left, right) // two values set (top, bottom) and (left, right)
// three values set top, (left, right) and bottom // three values set top, (left, right) and bottom
// four values set them in order // four values set them in order
let top = try!(${parser_function}(input)); let top = try!(parse_one(input));
let right; let right;
let bottom; let bottom;
let left; let left;
match input.try(${parser_function}) { match input.try(parse_one) {
Err(()) => { Err(()) => {
right = top.clone(); right = top.clone();
bottom = top.clone(); bottom = top.clone();
@ -2091,14 +2231,14 @@ pub mod shorthands {
} }
Ok(value) => { Ok(value) => {
right = value; right = value;
match input.try(${parser_function}) { match input.try(parse_one) {
Err(()) => { Err(()) => {
bottom = top.clone(); bottom = top.clone();
left = right.clone(); left = right.clone();
} }
Ok(value) => { Ok(value) => {
bottom = value; bottom = value;
match input.try(${parser_function}) { match input.try(parse_one) {
Err(()) => { Err(()) => {
left = right.clone(); left = right.clone();
} }
@ -2112,6 +2252,17 @@ pub mod shorthands {
} }
} }
Ok((top, right, bottom, left))
}
<%def name="four_sides_shorthand(name, sub_property_pattern, parser_function)">
<%self:shorthand name="${name}" sub_properties="${
' '.join(sub_property_pattern % side
for side in ['top', 'right', 'bottom', 'left'])}">
use values::specified;
use super::parse_four_sides;
let _unused = context;
let (top, right, bottom, left) = try!(parse_four_sides(input, ${parser_function}));
Ok(Longhands { Ok(Longhands {
% for side in ["top", "right", "bottom", "left"]: % for side in ["top", "right", "bottom", "left"]:
${to_rust_ident(sub_property_pattern % side)}: Some(${side}), ${to_rust_ident(sub_property_pattern % side)}: Some(${side}),
@ -2191,8 +2342,21 @@ pub mod shorthands {
${four_sides_shorthand("border-color", "border-%s-color", "specified::CSSColor::parse")} ${four_sides_shorthand("border-color", "border-%s-color", "specified::CSSColor::parse")}
${four_sides_shorthand("border-style", "border-%s-style", ${four_sides_shorthand("border-style", "border-%s-style",
"specified::BorderStyle::parse")} "specified::BorderStyle::parse")}
${four_sides_shorthand("border-width", "border-%s-width", <%self:shorthand name="border-width" sub_properties="${
"specified::parse_border_width")} ' '.join('border-%s-width' % side
for side in ['top', 'right', 'bottom', 'left'])}">
use values::specified;
use super::parse_four_sides;
let _unused = context;
let (top, right, bottom, left) = try!(parse_four_sides(input, specified::parse_border_width));
Ok(Longhands {
% for side in ["top", "right", "bottom", "left"]:
${to_rust_ident('border-%s-width' % side)}:
Some(longhands::${to_rust_ident('border-%s-width' % side)}::SpecifiedValue(${side})),
% endfor
})
</%self:shorthand>
pub fn parse_border(context: &ParserContext, input: &mut Parser) pub fn parse_border(context: &ParserContext, input: &mut Parser)
-> Result<(Option<specified::CSSColor>, -> Result<(Option<specified::CSSColor>,
@ -2239,9 +2403,9 @@ pub mod shorthands {
)}"> )}">
let (color, style, width) = try!(super::parse_border(context, input)); let (color, style, width) = try!(super::parse_border(context, input));
Ok(Longhands { Ok(Longhands {
% for prop in ["color", "style", "width"]: border_${side}_color: color,
${"border_%s_%s: %s," % (side, prop, prop)} border_${side}_style: style,
% endfor border_${side}_width: width.map(longhands::${to_rust_ident('border-%s-width' % side)}::SpecifiedValue),
}) })
</%self:shorthand> </%self:shorthand>
% endfor % endfor
@ -2254,9 +2418,9 @@ pub mod shorthands {
let (color, style, width) = try!(super::parse_border(context, input)); let (color, style, width) = try!(super::parse_border(context, input));
Ok(Longhands { Ok(Longhands {
% for side in ["top", "right", "bottom", "left"]: % for side in ["top", "right", "bottom", "left"]:
% for prop in ["color", "style", "width"]: border_${side}_color: color.clone(),
${"border_%s_%s: %s.clone()," % (side, prop, prop)} border_${side}_style: style,
% endfor border_${side}_width: width.map(longhands::${to_rust_ident('border-%s-width' % side)}::SpecifiedValue),
% endfor % endfor
}) })
</%self:shorthand> </%self:shorthand>
@ -3048,10 +3212,7 @@ fn cascade_with_cached_declarations(applicable_declarations: &[DeclarationBlock]
seen.set_${property.ident}(); seen.set_${property.ident}();
let computed_value = match *declared_value { let computed_value = match *declared_value {
DeclaredValue::SpecifiedValue(ref specified_value) DeclaredValue::SpecifiedValue(ref specified_value)
=> longhands::${property.ident}::to_computed_value( => specified_value.to_computed_value(context),
(*specified_value).clone(),
context
),
DeclaredValue::Initial DeclaredValue::Initial
=> longhands::${property.ident}::get_initial_value(), => longhands::${property.ident}::get_initial_value(),
DeclaredValue::Inherit => { DeclaredValue::Inherit => {
@ -3176,8 +3337,11 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock],
match *declaration { match *declaration {
PropertyDeclaration::FontSize(ref value) => { PropertyDeclaration::FontSize(ref value) => {
context.font_size = match *value { context.font_size = match *value {
DeclaredValue::SpecifiedValue(specified_value) => computed::compute_Au_with_font_size( DeclaredValue::SpecifiedValue(ref specified_value) => {
specified_value, context.inherited_font_size, context.root_font_size), specified_value.0.to_computed_value_with_font_size(
context.inherited_font_size, context.root_font_size
)
}
DeclaredValue::Initial => longhands::font_size::get_initial_value(), DeclaredValue::Initial => longhands::font_size::get_initial_value(),
DeclaredValue::Inherit => context.inherited_font_size, DeclaredValue::Inherit => context.inherited_font_size,
} }
@ -3259,10 +3423,7 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock],
seen.set_${property.ident}(); seen.set_${property.ident}();
let computed_value = match *declared_value { let computed_value = match *declared_value {
DeclaredValue::SpecifiedValue(ref specified_value) DeclaredValue::SpecifiedValue(ref specified_value)
=> longhands::${property.ident}::to_computed_value( => specified_value.to_computed_value(&context),
(*specified_value).clone(),
&context
),
DeclaredValue::Initial DeclaredValue::Initial
=> longhands::${property.ident}::get_initial_value(), => longhands::${property.ident}::get_initial_value(),
DeclaredValue::Inherit => { DeclaredValue::Inherit => {
@ -3316,7 +3477,7 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock],
// The initial value of display may be changed at computed value time. // The initial value of display may be changed at computed value time.
if !seen.get_display() { if !seen.get_display() {
let box_ = style_box_.make_unique(); let box_ = style_box_.make_unique();
box_.display = longhands::display::to_computed_value(box_.display, &context); box_.display = box_.display.to_computed_value(&context);
} }
if is_root_element { if is_root_element {

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 {
type ComputedValue;
#[inline] #[inline]
pub fn compute_CSSColor(value: specified::CSSColor, _context: &Context) -> CSSColor { fn to_computed_value(&self, _context: &Context) -> Self::ComputedValue;
value.parsed
} }
#[allow(non_snake_case)] pub trait ComputedValueAsSpecified {}
impl<T> ToComputedValue for T where T: ComputedValueAsSpecified + Clone {
type ComputedValue = T;
#[inline] #[inline]
pub fn compute_BorderStyle(value: BorderStyle, _context: &Context) -> BorderStyle { fn to_computed_value(&self, _context: &Context) -> T {
value self.clone()
}
} }
#[allow(non_snake_case)] impl ToComputedValue for specified::CSSColor {
type ComputedValue = CSSColor;
#[inline] #[inline]
pub fn compute_Au(value: specified::Length, context: &Context) -> Au { fn to_computed_value(&self, _context: &Context) -> CSSColor {
compute_Au_with_font_size(value, context.font_size, context.root_font_size) self.parsed
}
} }
/// A special version of `compute_Au` used for `font-size`. impl ComputedValueAsSpecified for specified::BorderStyle {}
#[allow(non_snake_case)]
impl ToComputedValue for specified::Length {
type ComputedValue = Au;
#[inline] #[inline]
pub fn compute_Au_with_font_size(value: specified::Length, reference_font_size: Au, root_font_size: Au) -> Au { fn to_computed_value(&self, context: &Context) -> Au {
match value { self.to_computed_value_with_font_size(context.font_size, context.root_font_size)
specified::Length::Au(value) => value,
specified::Length::Em(value) => reference_font_size.scale_by(value),
specified::Length::Ex(value) => {
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,18 +817,41 @@ 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)]
@ -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;
} }