Properly serialize % values in calc expressions

This commit is contained in:
David Zbarsky 2015-08-13 14:33:21 -04:00
parent cfa1e467f1
commit 6573e8088c
4 changed files with 50 additions and 41 deletions

View file

@ -367,7 +367,8 @@ impl RawLayoutElementHelpers for Element {
match width { match width {
LengthOrPercentageOrAuto::Auto => {} LengthOrPercentageOrAuto::Auto => {}
LengthOrPercentageOrAuto::Percentage(percentage) => { LengthOrPercentageOrAuto::Percentage(percentage) => {
let width_value = specified::LengthOrPercentageOrAuto::Percentage(percentage); let width_value =
specified::LengthOrPercentageOrAuto::Percentage(specified::Percentage(percentage));
hints.push(from_declaration( hints.push(from_declaration(
PropertyDeclaration::Width(SpecifiedValue(width_value)))); PropertyDeclaration::Width(SpecifiedValue(width_value))));
} }
@ -390,7 +391,8 @@ impl RawLayoutElementHelpers for Element {
match height { match height {
LengthOrPercentageOrAuto::Auto => {} LengthOrPercentageOrAuto::Auto => {}
LengthOrPercentageOrAuto::Percentage(percentage) => { LengthOrPercentageOrAuto::Percentage(percentage) => {
let height_value = specified::LengthOrPercentageOrAuto::Percentage(percentage); let height_value =
specified::LengthOrPercentageOrAuto::Percentage(specified::Percentage(percentage));
hints.push(from_declaration( hints.push(from_declaration(
PropertyDeclaration::Height(SpecifiedValue(height_value)))); PropertyDeclaration::Height(SpecifiedValue(height_value))));
} }

View file

@ -1912,7 +1912,7 @@ pub mod longhands {
.map(|value| match value { .map(|value| match value {
specified::LengthOrPercentage::Length(value) => value, specified::LengthOrPercentage::Length(value) => value,
specified::LengthOrPercentage::Percentage(value) => specified::LengthOrPercentage::Percentage(value) =>
specified::Length::FontRelative(specified::FontRelativeLength::Em(value)), specified::Length::FontRelative(specified::FontRelativeLength::Em(value.0)),
// FIXME(dzbarsky) handle calc for font-size // FIXME(dzbarsky) handle calc for font-size
specified::LengthOrPercentage::Calc(_) => specified::LengthOrPercentage::Calc(_) =>
specified::Length::FontRelative(specified::FontRelativeLength::Em(1.)), specified::Length::FontRelative(specified::FontRelativeLength::Em(1.)),
@ -3986,6 +3986,7 @@ pub mod longhands {
} }
pub fn parse_origin(_: &ParserContext, input: &mut Parser) -> Result<OriginParseResult,()> { 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); let (mut horizontal, mut vertical, mut depth) = (None, None, None);
loop { loop {
if let Err(_) = input.try(|input| { if let Err(_) = input.try(|input| {
@ -3994,37 +3995,37 @@ pub mod longhands {
token, token,
"left" => { "left" => {
if horizontal.is_none() { if horizontal.is_none() {
horizontal = Some(specified::LengthOrPercentage::Percentage(0.0)) horizontal = Some(LengthOrPercentage::Percentage(Percentage(0.0)))
} else { } else {
return Err(()) return Err(())
} }
}, },
"center" => { "center" => {
if horizontal.is_none() { if horizontal.is_none() {
horizontal = Some(specified::LengthOrPercentage::Percentage(0.5)) horizontal = Some(LengthOrPercentage::Percentage(Percentage(0.5)))
} else if vertical.is_none() { } else if vertical.is_none() {
vertical = Some(specified::LengthOrPercentage::Percentage(0.5)) vertical = Some(LengthOrPercentage::Percentage(Percentage(0.5)))
} else { } else {
return Err(()) return Err(())
} }
}, },
"right" => { "right" => {
if horizontal.is_none() { if horizontal.is_none() {
horizontal = Some(specified::LengthOrPercentage::Percentage(1.0)) horizontal = Some(LengthOrPercentage::Percentage(Percentage(1.0)))
} else { } else {
return Err(()) return Err(())
} }
}, },
"top" => { "top" => {
if vertical.is_none() { if vertical.is_none() {
vertical = Some(specified::LengthOrPercentage::Percentage(0.0)) vertical = Some(LengthOrPercentage::Percentage(Percentage(0.0)))
} else { } else {
return Err(()) return Err(())
} }
}, },
"bottom" => { "bottom" => {
if vertical.is_none() { if vertical.is_none() {
vertical = Some(specified::LengthOrPercentage::Percentage(1.0)) vertical = Some(LengthOrPercentage::Percentage(Percentage(1.0)))
} else { } else {
return Err(()) return Err(())
} }
@ -4033,13 +4034,13 @@ pub mod longhands {
} }
Ok(()) Ok(())
}) { }) {
match specified::LengthOrPercentage::parse(input) { match LengthOrPercentage::parse(input) {
Ok(value) => { Ok(value) => {
if horizontal.is_none() { if horizontal.is_none() {
horizontal = Some(value); horizontal = Some(value);
} else if vertical.is_none() { } else if vertical.is_none() {
vertical = Some(value); vertical = Some(value);
} else if let specified::LengthOrPercentage::Length(length) = value { } else if let LengthOrPercentage::Length(length) = value {
depth = Some(length); depth = Some(length);
} else { } else {
break; break;
@ -4067,7 +4068,7 @@ pub mod longhands {
<%self:longhand name="transform-origin"> <%self:longhand name="transform-origin">
use values::computed::Context; use values::computed::Context;
use values::specified::{Length, LengthOrPercentage}; use values::specified::{Length, LengthOrPercentage, Percentage};
use cssparser::ToCss; use cssparser::ToCss;
use std::fmt; use std::fmt;
@ -4123,8 +4124,8 @@ pub mod longhands {
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> { pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
let result = try!(super::parse_origin(context, input)); let result = try!(super::parse_origin(context, input));
Ok(SpecifiedValue { Ok(SpecifiedValue {
horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(0.5)), horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(0.5)), vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
depth: result.depth.unwrap_or(Length::Absolute(Au(0))), depth: result.depth.unwrap_or(Length::Absolute(Au(0))),
}) })
} }
@ -4149,7 +4150,7 @@ pub mod longhands {
<%self:longhand name="perspective-origin"> <%self:longhand name="perspective-origin">
use values::computed::Context; use values::computed::Context;
use values::specified::LengthOrPercentage; use values::specified::{LengthOrPercentage, Percentage};
use cssparser::ToCss; use cssparser::ToCss;
use std::fmt; use std::fmt;
@ -4199,8 +4200,8 @@ pub mod longhands {
match result.depth { match result.depth {
Some(_) => Err(()), Some(_) => Err(()),
None => Ok(SpecifiedValue { None => Ok(SpecifiedValue {
horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(0.5)), horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(0.5)), vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
}) })
} }
} }

View file

@ -387,7 +387,7 @@ pub mod specified {
pub em: Option<FontRelativeLength>, pub em: Option<FontRelativeLength>,
pub ex: Option<FontRelativeLength>, pub ex: Option<FontRelativeLength>,
pub rem: Option<FontRelativeLength>, pub rem: Option<FontRelativeLength>,
pub percentage: Option<CSSFloat>, pub percentage: Option<Percentage>,
} }
impl Calc { impl Calc {
fn parse_sum(input: &mut Parser) -> Result<CalcSumNode, ()> { fn parse_sum(input: &mut Parser) -> Result<CalcSumNode, ()> {
@ -603,7 +603,7 @@ pub mod specified {
em: em.map(FontRelativeLength::Em), em: em.map(FontRelativeLength::Em),
ex: ex.map(FontRelativeLength::Ex), ex: ex.map(FontRelativeLength::Ex),
rem: rem.map(FontRelativeLength::Rem), rem: rem.map(FontRelativeLength::Rem),
percentage: percentage, percentage: percentage.map(Percentage),
}) })
} }
} }
@ -659,10 +659,19 @@ pub mod specified {
} }
} }
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
pub struct Percentage(pub CSSFloat); // [0 .. 100%] maps to [0.0 .. 1.0]
impl ToCss for Percentage {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
write!(dest, "{}%", self.0 * 100.)
}
}
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)] #[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
pub enum LengthOrPercentage { pub enum LengthOrPercentage {
Length(Length), Length(Length),
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0] Percentage(Percentage),
Calc(Calc), Calc(Calc),
} }
@ -670,8 +679,7 @@ pub mod specified {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match self { match self {
&LengthOrPercentage::Length(length) => length.to_css(dest), &LengthOrPercentage::Length(length) => length.to_css(dest),
&LengthOrPercentage::Percentage(percentage) &LengthOrPercentage::Percentage(percentage) => percentage.to_css(dest),
=> write!(dest, "{}%", percentage * 100.),
&LengthOrPercentage::Calc(calc) => calc.to_css(dest), &LengthOrPercentage::Calc(calc) => calc.to_css(dest),
} }
} }
@ -688,7 +696,7 @@ pub mod specified {
Token::Dimension(ref value, ref unit) if context.is_ok(value.value) => Token::Dimension(ref value, ref unit) if context.is_ok(value.value) =>
Length::parse_dimension(value.value, unit).map(LengthOrPercentage::Length), Length::parse_dimension(value.value, unit).map(LengthOrPercentage::Length),
Token::Percentage(ref value) if context.is_ok(value.unit_value) => Token::Percentage(ref value) if context.is_ok(value.unit_value) =>
Ok(LengthOrPercentage::Percentage(value.unit_value)), Ok(LengthOrPercentage::Percentage(Percentage(value.unit_value))),
Token::Number(ref value) if value.value == 0. => Token::Number(ref value) if value.value == 0. =>
Ok(LengthOrPercentage::Length(Length::Absolute(Au(0)))), Ok(LengthOrPercentage::Length(Length::Absolute(Au(0)))),
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
@ -712,7 +720,7 @@ pub mod specified {
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)] #[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
pub enum LengthOrPercentageOrAuto { pub enum LengthOrPercentageOrAuto {
Length(Length), Length(Length),
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0] Percentage(Percentage),
Auto, Auto,
Calc(Calc), Calc(Calc),
} }
@ -721,8 +729,7 @@ pub mod specified {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match self { match self {
&LengthOrPercentageOrAuto::Length(length) => length.to_css(dest), &LengthOrPercentageOrAuto::Length(length) => length.to_css(dest),
&LengthOrPercentageOrAuto::Percentage(percentage) &LengthOrPercentageOrAuto::Percentage(percentage) => percentage.to_css(dest),
=> write!(dest, "{}%", percentage * 100.),
&LengthOrPercentageOrAuto::Auto => dest.write_str("auto"), &LengthOrPercentageOrAuto::Auto => dest.write_str("auto"),
&LengthOrPercentageOrAuto::Calc(calc) => calc.to_css(dest), &LengthOrPercentageOrAuto::Calc(calc) => calc.to_css(dest),
} }
@ -737,7 +744,7 @@ pub mod specified {
Token::Dimension(ref value, ref unit) if context.is_ok(value.value) => Token::Dimension(ref value, ref unit) if context.is_ok(value.value) =>
Length::parse_dimension(value.value, unit).map(LengthOrPercentageOrAuto::Length), Length::parse_dimension(value.value, unit).map(LengthOrPercentageOrAuto::Length),
Token::Percentage(ref value) if context.is_ok(value.unit_value) => Token::Percentage(ref value) if context.is_ok(value.unit_value) =>
Ok(LengthOrPercentageOrAuto::Percentage(value.unit_value)), Ok(LengthOrPercentageOrAuto::Percentage(Percentage(value.unit_value))),
Token::Number(ref value) if value.value == 0. => Token::Number(ref value) if value.value == 0. =>
Ok(LengthOrPercentageOrAuto::Length(Length::Absolute(Au(0)))), Ok(LengthOrPercentageOrAuto::Length(Length::Absolute(Au(0)))),
Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") => Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") =>
@ -762,7 +769,7 @@ pub mod specified {
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)] #[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
pub enum LengthOrPercentageOrNone { pub enum LengthOrPercentageOrNone {
Length(Length), Length(Length),
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0] Percentage(Percentage),
None, None,
} }
@ -770,8 +777,7 @@ pub mod specified {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match self { match self {
&LengthOrPercentageOrNone::Length(length) => length.to_css(dest), &LengthOrPercentageOrNone::Length(length) => length.to_css(dest),
&LengthOrPercentageOrNone::Percentage(percentage) => &LengthOrPercentageOrNone::Percentage(percentage) => percentage.to_css(dest),
write!(dest, "{}%", percentage * 100.),
&LengthOrPercentageOrNone::None => dest.write_str("none"), &LengthOrPercentageOrNone::None => dest.write_str("none"),
} }
} }
@ -784,7 +790,7 @@ pub mod specified {
Token::Dimension(ref value, ref unit) if context.is_ok(value.value) => Token::Dimension(ref value, ref unit) if context.is_ok(value.value) =>
Length::parse_dimension(value.value, unit).map(LengthOrPercentageOrNone::Length), Length::parse_dimension(value.value, unit).map(LengthOrPercentageOrNone::Length),
Token::Percentage(ref value) if context.is_ok(value.unit_value) => Token::Percentage(ref value) if context.is_ok(value.unit_value) =>
Ok(LengthOrPercentageOrNone::Percentage(value.unit_value)), Ok(LengthOrPercentageOrNone::Percentage(Percentage(value.unit_value))),
Token::Number(ref value) if value.value == 0. => Token::Number(ref value) if value.value == 0. =>
Ok(LengthOrPercentageOrNone::Length(Length::Absolute(Au(0)))), Ok(LengthOrPercentageOrNone::Length(Length::Absolute(Au(0)))),
Token::Ident(ref value) if value.eq_ignore_ascii_case("none") => Token::Ident(ref value) if value.eq_ignore_ascii_case("none") =>
@ -846,7 +852,7 @@ pub mod specified {
#[derive(Clone, PartialEq, Copy)] #[derive(Clone, PartialEq, Copy)]
pub enum PositionComponent { pub enum PositionComponent {
Length(Length), Length(Length),
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0] Percentage(Percentage),
Center, Center,
Left, Left,
Right, Right,
@ -861,7 +867,7 @@ pub mod specified {
.map(PositionComponent::Length) .map(PositionComponent::Length)
} }
Token::Percentage(ref value) => { Token::Percentage(ref value) => {
Ok(PositionComponent::Percentage(value.unit_value)) Ok(PositionComponent::Percentage(Percentage(value.unit_value)))
} }
Token::Number(ref value) if value.value == 0. => { Token::Number(ref value) if value.value == 0. => {
Ok(PositionComponent::Length(Length::Absolute(Au(0)))) Ok(PositionComponent::Length(Length::Absolute(Au(0))))
@ -884,11 +890,11 @@ pub mod specified {
match self { match self {
PositionComponent::Length(x) => LengthOrPercentage::Length(x), PositionComponent::Length(x) => LengthOrPercentage::Length(x),
PositionComponent::Percentage(x) => LengthOrPercentage::Percentage(x), PositionComponent::Percentage(x) => LengthOrPercentage::Percentage(x),
PositionComponent::Center => LengthOrPercentage::Percentage(0.5), PositionComponent::Center => LengthOrPercentage::Percentage(Percentage(0.5)),
PositionComponent::Left | PositionComponent::Left |
PositionComponent::Top => LengthOrPercentage::Percentage(0.0), PositionComponent::Top => LengthOrPercentage::Percentage(Percentage(0.0)),
PositionComponent::Right | PositionComponent::Right |
PositionComponent::Bottom => LengthOrPercentage::Percentage(1.0), PositionComponent::Bottom => LengthOrPercentage::Percentage(Percentage(1.0)),
} }
} }
} }
@ -1305,7 +1311,7 @@ pub mod computed {
} }
} }
Calc { length: length, percentage: self.percentage } Calc { length: length, percentage: self.percentage.map(|p| p.0) }
} }
} }
@ -1342,7 +1348,7 @@ pub mod computed {
LengthOrPercentage::Length(value.to_computed_value(context)) LengthOrPercentage::Length(value.to_computed_value(context))
} }
specified::LengthOrPercentage::Percentage(value) => { specified::LengthOrPercentage::Percentage(value) => {
LengthOrPercentage::Percentage(value) LengthOrPercentage::Percentage(value.0)
} }
specified::LengthOrPercentage::Calc(calc) => { specified::LengthOrPercentage::Calc(calc) => {
LengthOrPercentage::Calc(calc.to_computed_value(context)) LengthOrPercentage::Calc(calc.to_computed_value(context))
@ -1390,7 +1396,7 @@ pub mod computed {
LengthOrPercentageOrAuto::Length(value.to_computed_value(context)) LengthOrPercentageOrAuto::Length(value.to_computed_value(context))
} }
specified::LengthOrPercentageOrAuto::Percentage(value) => { specified::LengthOrPercentageOrAuto::Percentage(value) => {
LengthOrPercentageOrAuto::Percentage(value) LengthOrPercentageOrAuto::Percentage(value.0)
} }
specified::LengthOrPercentageOrAuto::Auto => { specified::LengthOrPercentageOrAuto::Auto => {
LengthOrPercentageOrAuto::Auto LengthOrPercentageOrAuto::Auto
@ -1440,7 +1446,7 @@ pub mod computed {
LengthOrPercentageOrNone::Length(value.to_computed_value(context)) LengthOrPercentageOrNone::Length(value.to_computed_value(context))
} }
specified::LengthOrPercentageOrNone::Percentage(value) => { specified::LengthOrPercentageOrNone::Percentage(value) => {
LengthOrPercentageOrNone::Percentage(value) LengthOrPercentageOrNone::Percentage(value.0)
} }
specified::LengthOrPercentageOrNone::None => { specified::LengthOrPercentageOrNone::None => {
LengthOrPercentageOrNone::None LengthOrPercentageOrNone::None

View file

@ -451,7 +451,7 @@ impl ViewportConstraints {
LengthOrPercentageOrAuto::Length(value) => LengthOrPercentageOrAuto::Length(value) =>
Some(value.to_computed_value(&context)), Some(value.to_computed_value(&context)),
LengthOrPercentageOrAuto::Percentage(value) => LengthOrPercentageOrAuto::Percentage(value) =>
Some(initial_viewport.$dimension.scale_by(value)), Some(initial_viewport.$dimension.scale_by(value.0)),
LengthOrPercentageOrAuto::Auto => None, LengthOrPercentageOrAuto::Auto => None,
LengthOrPercentageOrAuto::Calc(calc) => { LengthOrPercentageOrAuto::Calc(calc) => {
let calc = calc.to_computed_value(&context); let calc = calc.to_computed_value(&context);