Auto merge of #7496 - servo:calc_, r=SimonSapin

Implement CSS3 Calc

This is #7185 with one commit added to make it build merged with master, which got support for the `ch` unit in the meantime.

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/7496)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-09-02 02:33:18 -06:00
commit a547ae6826
21 changed files with 873 additions and 63 deletions

View file

@ -760,7 +760,7 @@ pub mod longhands {
pub mod computed_value {
use std::fmt;
use util::geometry::Au;
use values::CSSFloat;
use values::{CSSFloat, computed};
#[allow(non_camel_case_types)]
#[derive(PartialEq, Copy, Clone, HeapSizeOf)]
pub enum T {
@ -769,6 +769,7 @@ pub mod longhands {
% endfor
Length(Au),
Percentage(CSSFloat),
Calc(computed::Calc),
}
impl fmt::Debug for T {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@ -778,6 +779,7 @@ pub mod longhands {
% endfor
&T::Length(length) => write!(f, "{:?}", length),
&T::Percentage(number) => write!(f, "{}%", number),
&T::Calc(calc) => write!(f, "{:?}", calc)
}
}
}
@ -789,6 +791,7 @@ pub mod longhands {
% endfor
T::Length(value) => value.to_css(dest),
T::Percentage(percentage) => write!(dest, "{}%", percentage * 100.),
T::Calc(calc) => calc.to_css(dest),
}
}
}
@ -809,12 +812,12 @@ pub mod longhands {
% endfor
SpecifiedValue::LengthOrPercentage(value) => {
match value.to_computed_value(context) {
computed::LengthOrPercentage::Length(value) => {
computed_value::T::Length(value)
}
computed::LengthOrPercentage::Percentage(value) => {
computed_value::T::Percentage(value)
}
computed::LengthOrPercentage::Length(value) =>
computed_value::T::Length(value),
computed::LengthOrPercentage::Percentage(value) =>
computed_value::T::Percentage(value),
computed::LengthOrPercentage::Calc(value) =>
computed_value::T::Calc(value),
}
}
}
@ -1910,10 +1913,12 @@ pub mod longhands {
/// <length> | <percentage> | <absolute-size> | <relative-size>
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
input.try(specified::LengthOrPercentage::parse_non_negative)
.map(|value| match value {
specified::LengthOrPercentage::Length(value) => value,
.and_then(|value| match value {
specified::LengthOrPercentage::Length(value) => Ok(value),
specified::LengthOrPercentage::Percentage(value) =>
specified::Length::FontRelative(specified::FontRelativeLength::Em(value))
Ok(specified::Length::FontRelative(specified::FontRelativeLength::Em(value.0))),
// FIXME(dzbarsky) handle calc for font-size
specified::LengthOrPercentage::Calc(_) => Err(())
})
.or_else(|()| {
match_ignore_ascii_case! { try!(input.expect_ident()),
@ -3984,6 +3989,7 @@ pub mod longhands {
}
pub fn parse_origin(_: &ParserContext, input: &mut Parser) -> Result<OriginParseResult,()> {
use values::specified::{LengthOrPercentage, Percentage};
let (mut horizontal, mut vertical, mut depth) = (None, None, None);
loop {
if let Err(_) = input.try(|input| {
@ -3992,37 +3998,37 @@ pub mod longhands {
token,
"left" => {
if horizontal.is_none() {
horizontal = Some(specified::LengthOrPercentage::Percentage(0.0))
horizontal = Some(LengthOrPercentage::Percentage(Percentage(0.0)))
} else {
return Err(())
}
},
"center" => {
if horizontal.is_none() {
horizontal = Some(specified::LengthOrPercentage::Percentage(0.5))
horizontal = Some(LengthOrPercentage::Percentage(Percentage(0.5)))
} else if vertical.is_none() {
vertical = Some(specified::LengthOrPercentage::Percentage(0.5))
vertical = Some(LengthOrPercentage::Percentage(Percentage(0.5)))
} else {
return Err(())
}
},
"right" => {
if horizontal.is_none() {
horizontal = Some(specified::LengthOrPercentage::Percentage(1.0))
horizontal = Some(LengthOrPercentage::Percentage(Percentage(1.0)))
} else {
return Err(())
}
},
"top" => {
if vertical.is_none() {
vertical = Some(specified::LengthOrPercentage::Percentage(0.0))
vertical = Some(LengthOrPercentage::Percentage(Percentage(0.0)))
} else {
return Err(())
}
},
"bottom" => {
if vertical.is_none() {
vertical = Some(specified::LengthOrPercentage::Percentage(1.0))
vertical = Some(LengthOrPercentage::Percentage(Percentage(1.0)))
} else {
return Err(())
}
@ -4031,13 +4037,13 @@ pub mod longhands {
}
Ok(())
}) {
match specified::LengthOrPercentage::parse(input) {
match LengthOrPercentage::parse(input) {
Ok(value) => {
if horizontal.is_none() {
horizontal = Some(value);
} else if vertical.is_none() {
vertical = Some(value);
} else if let specified::LengthOrPercentage::Length(length) = value {
} else if let LengthOrPercentage::Length(length) = value {
depth = Some(length);
} else {
break;
@ -4065,7 +4071,7 @@ pub mod longhands {
<%self:longhand name="transform-origin">
use values::computed::Context;
use values::specified::{Length, LengthOrPercentage};
use values::specified::{Length, LengthOrPercentage, Percentage};
use cssparser::ToCss;
use std::fmt;
@ -4121,8 +4127,8 @@ pub mod longhands {
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
let result = try!(super::parse_origin(context, input));
Ok(SpecifiedValue {
horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(0.5)),
vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(0.5)),
horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
depth: result.depth.unwrap_or(Length::Absolute(Au(0))),
})
}
@ -4147,7 +4153,7 @@ pub mod longhands {
<%self:longhand name="perspective-origin">
use values::computed::Context;
use values::specified::LengthOrPercentage;
use values::specified::{LengthOrPercentage, Percentage};
use cssparser::ToCss;
use std::fmt;
@ -4197,8 +4203,8 @@ pub mod longhands {
match result.depth {
Some(_) => Err(()),
None => Ok(SpecifiedValue {
horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(0.5)),
vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(0.5)),
horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
})
}
}