diff options
-rw-r--r-- | components/style/values/computed/mod.rs | 1 | ||||
-rw-r--r-- | components/style/values/specified/mod.rs | 88 | ||||
-rw-r--r-- | components/style_traits/values.rs | 2 |
3 files changed, 64 insertions, 27 deletions
diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 265ed2f3a25..28fc7b3892f 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -167,6 +167,7 @@ impl ToComputedValue for specified::CalcLengthOrPercentage { self.compute_from_viewport_and_font_size(context.viewport_size(), context.style().get_font().clone_font_size(), context.style().root_font_size()) + } } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 6746f6bb62c..3bbdcb1ccb9 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -286,22 +286,24 @@ impl Length { } #[inline] - fn parse_internal(input: &mut Parser, context: &AllowedNumericType) -> Result<Length, ()> { + fn parse_internal(input: &mut Parser, context: AllowedNumericType) -> Result<Length, ()> { match try!(input.next()) { Token::Dimension(ref value, ref unit) if context.is_ok(value.value) => Length::parse_dimension(value.value, unit), Token::Number(ref value) if value.value == 0. => Ok(Length::Absolute(Au(0))), Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => - input.parse_nested_block(CalcLengthOrPercentage::parse_length), + input.parse_nested_block(|input| { + CalcLengthOrPercentage::parse_length(input, context) + }), _ => Err(()) } } pub fn parse(input: &mut Parser) -> Result<Length, ()> { - Length::parse_internal(input, &AllowedNumericType::All) + Length::parse_internal(input, AllowedNumericType::All) } pub fn parse_non_negative(input: &mut Parser) -> Result<Length, ()> { - Length::parse_internal(input, &AllowedNumericType::NonNegative) + Length::parse_internal(input, AllowedNumericType::NonNegative) } pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Length, ()> { match_ignore_ascii_case! { unit, @@ -467,6 +469,8 @@ pub struct CalcLengthOrPercentage { pub ch: Option<FontRelativeLength>, pub rem: Option<FontRelativeLength>, pub percentage: Option<Percentage>, + /// Whether the value returned can be negative at computed value time. + pub allowed_numeric_type: AllowedNumericType, } impl CalcLengthOrPercentage { @@ -617,15 +621,19 @@ impl CalcLengthOrPercentage { } } - fn parse_length(input: &mut Parser) -> Result<Length, ()> { - CalcLengthOrPercentage::parse(input, CalcUnit::Length).map(Length::Calc) + fn parse_length(input: &mut Parser, + context: AllowedNumericType) -> Result<Length, ()> { + CalcLengthOrPercentage::parse(input, CalcUnit::Length, context).map(Length::Calc) } - fn parse_length_or_percentage(input: &mut Parser) -> Result<CalcLengthOrPercentage, ()> { - CalcLengthOrPercentage::parse(input, CalcUnit::LengthOrPercentage) + fn parse_length_or_percentage(input: &mut Parser, + context: AllowedNumericType) -> Result<CalcLengthOrPercentage, ()> { + CalcLengthOrPercentage::parse(input, CalcUnit::LengthOrPercentage, context) } - fn parse(input: &mut Parser, expected_unit: CalcUnit) -> Result<CalcLengthOrPercentage, ()> { + fn parse(input: &mut Parser, + expected_unit: CalcUnit, + context: AllowedNumericType) -> Result<CalcLengthOrPercentage, ()> { let ast = try!(CalcLengthOrPercentage::parse_sum(input, expected_unit)); let mut simplified = Vec::new(); @@ -692,6 +700,7 @@ impl CalcLengthOrPercentage { ch: ch.map(FontRelativeLength::Ch), rem: rem.map(FontRelativeLength::Rem), percentage: percentage.map(Percentage), + allowed_numeric_type: context, }) } @@ -770,6 +779,7 @@ impl CalcLengthOrPercentage { val.to_computed_value(viewport_size)); } } + for val in &[self.ch, self.em, self.ex, self.rem] { if let Some(val) = *val { length = Some(length.unwrap_or(Au(0)) + val.to_computed_value( @@ -777,9 +787,23 @@ impl CalcLengthOrPercentage { } } + // https://drafts.csswg.org/css-values/#calc-range + let mut percentage = self.percentage.map(|p| p.0); + if let AllowedNumericType::NonNegative = self.allowed_numeric_type { + if let Some(ref mut length) = length { + *length = cmp::max(*length, Au(0)); + } + + if let Some(ref mut percentage) = percentage { + if *percentage < 0. { + *percentage = 0.; + } + } + } + computed::CalcLengthOrPercentage { length: length, - percentage: self.percentage.map(|p| p.0) + percentage: percentage, } } } @@ -884,7 +908,7 @@ impl LengthOrPercentage { LengthOrPercentage::Length(Length::Absolute(Au(0))) } - fn parse_internal(input: &mut Parser, context: &AllowedNumericType) + fn parse_internal(input: &mut Parser, context: AllowedNumericType) -> Result<LengthOrPercentage, ()> { match try!(input.next()) { @@ -895,7 +919,9 @@ impl LengthOrPercentage { Token::Number(ref value) if value.value == 0. => Ok(LengthOrPercentage::Length(Length::Absolute(Au(0)))), Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { - let calc = try!(input.parse_nested_block(CalcLengthOrPercentage::parse_length_or_percentage)); + let calc = try!(input.parse_nested_block(|input| { + CalcLengthOrPercentage::parse_length_or_percentage(input, context) + })); Ok(LengthOrPercentage::Calc(calc)) }, _ => Err(()) @@ -903,11 +929,11 @@ impl LengthOrPercentage { } #[inline] pub fn parse(input: &mut Parser) -> Result<LengthOrPercentage, ()> { - LengthOrPercentage::parse_internal(input, &AllowedNumericType::All) + LengthOrPercentage::parse_internal(input, AllowedNumericType::All) } #[inline] pub fn parse_non_negative(input: &mut Parser) -> Result<LengthOrPercentage, ()> { - LengthOrPercentage::parse_internal(input, &AllowedNumericType::NonNegative) + LengthOrPercentage::parse_internal(input, AllowedNumericType::NonNegative) } } @@ -942,7 +968,7 @@ impl ToCss for LengthOrPercentageOrAuto { } impl LengthOrPercentageOrAuto { - fn parse_internal(input: &mut Parser, context: &AllowedNumericType) + fn parse_internal(input: &mut Parser, context: AllowedNumericType) -> Result<LengthOrPercentageOrAuto, ()> { match try!(input.next()) { @@ -955,7 +981,9 @@ impl LengthOrPercentageOrAuto { Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") => Ok(LengthOrPercentageOrAuto::Auto), Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { - let calc = try!(input.parse_nested_block(CalcLengthOrPercentage::parse_length_or_percentage)); + let calc = try!(input.parse_nested_block(|input| { + CalcLengthOrPercentage::parse_length_or_percentage(input, context) + })); Ok(LengthOrPercentageOrAuto::Calc(calc)) }, _ => Err(()) @@ -963,11 +991,11 @@ impl LengthOrPercentageOrAuto { } #[inline] pub fn parse(input: &mut Parser) -> Result<LengthOrPercentageOrAuto, ()> { - LengthOrPercentageOrAuto::parse_internal(input, &AllowedNumericType::All) + LengthOrPercentageOrAuto::parse_internal(input, AllowedNumericType::All) } #[inline] pub fn parse_non_negative(input: &mut Parser) -> Result<LengthOrPercentageOrAuto, ()> { - LengthOrPercentageOrAuto::parse_internal(input, &AllowedNumericType::NonNegative) + LengthOrPercentageOrAuto::parse_internal(input, AllowedNumericType::NonNegative) } } @@ -1001,7 +1029,7 @@ impl ToCss for LengthOrPercentageOrNone { } } impl LengthOrPercentageOrNone { - fn parse_internal(input: &mut Parser, context: &AllowedNumericType) + fn parse_internal(input: &mut Parser, context: AllowedNumericType) -> Result<LengthOrPercentageOrNone, ()> { match try!(input.next()) { @@ -1012,7 +1040,9 @@ impl LengthOrPercentageOrNone { Token::Number(ref value) if value.value == 0. => Ok(LengthOrPercentageOrNone::Length(Length::Absolute(Au(0)))), Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { - let calc = try!(input.parse_nested_block(CalcLengthOrPercentage::parse_length_or_percentage)); + let calc = try!(input.parse_nested_block(|input| { + CalcLengthOrPercentage::parse_length_or_percentage(input, context) + })); Ok(LengthOrPercentageOrNone::Calc(calc)) }, Token::Ident(ref value) if value.eq_ignore_ascii_case("none") => @@ -1022,11 +1052,11 @@ impl LengthOrPercentageOrNone { } #[inline] pub fn parse(input: &mut Parser) -> Result<LengthOrPercentageOrNone, ()> { - LengthOrPercentageOrNone::parse_internal(input, &AllowedNumericType::All) + LengthOrPercentageOrNone::parse_internal(input, AllowedNumericType::All) } #[inline] pub fn parse_non_negative(input: &mut Parser) -> Result<LengthOrPercentageOrNone, ()> { - LengthOrPercentageOrNone::parse_internal(input, &AllowedNumericType::NonNegative) + LengthOrPercentageOrNone::parse_internal(input, AllowedNumericType::NonNegative) } } @@ -1055,7 +1085,7 @@ impl ToCss for LengthOrNone { } } impl LengthOrNone { - fn parse_internal(input: &mut Parser, context: &AllowedNumericType) + fn parse_internal(input: &mut Parser, context: AllowedNumericType) -> Result<LengthOrNone, ()> { match try!(input.next()) { @@ -1064,7 +1094,9 @@ impl LengthOrNone { Token::Number(ref value) if value.value == 0. => Ok(LengthOrNone::Length(Length::Absolute(Au(0)))), Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => - input.parse_nested_block(CalcLengthOrPercentage::parse_length).map(LengthOrNone::Length), + input.parse_nested_block(|input| { + CalcLengthOrPercentage::parse_length(input, context) + }).map(LengthOrNone::Length), Token::Ident(ref value) if value.eq_ignore_ascii_case("none") => Ok(LengthOrNone::None), _ => Err(()) @@ -1072,11 +1104,11 @@ impl LengthOrNone { } #[inline] pub fn parse(input: &mut Parser) -> Result<LengthOrNone, ()> { - LengthOrNone::parse_internal(input, &AllowedNumericType::All) + LengthOrNone::parse_internal(input, AllowedNumericType::All) } #[inline] pub fn parse_non_negative(input: &mut Parser) -> Result<LengthOrNone, ()> { - LengthOrNone::parse_internal(input, &AllowedNumericType::NonNegative) + LengthOrNone::parse_internal(input, AllowedNumericType::NonNegative) } } @@ -1127,7 +1159,9 @@ impl LengthOrPercentageOrAutoOrContent { Token::Ident(ref value) if value.eq_ignore_ascii_case("content") => Ok(LengthOrPercentageOrAutoOrContent::Content), Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { - let calc = try!(input.parse_nested_block(CalcLengthOrPercentage::parse_length_or_percentage)); + let calc = try!(input.parse_nested_block(|input| { + CalcLengthOrPercentage::parse_length_or_percentage(input, context) + })); Ok(LengthOrPercentageOrAutoOrContent::Calc(calc)) }, _ => Err(()) diff --git a/components/style_traits/values.rs b/components/style_traits/values.rs index 995e98fcfef..eb6f3c13a55 100644 --- a/components/style_traits/values.rs +++ b/components/style_traits/values.rs @@ -63,6 +63,8 @@ macro_rules! __define_css_keyword_enum__actual { pub mod specified { + #[repr(u8)] + #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum AllowedNumericType { All, |