diff --git a/components/style/gecko_bindings/sugar/ns_timing_function.rs b/components/style/gecko_bindings/sugar/ns_timing_function.rs index 53c0d468523..192125b4785 100644 --- a/components/style/gecko_bindings/sugar/ns_timing_function.rs +++ b/components/style/gecko_bindings/sugar/ns_timing_function.rs @@ -71,8 +71,8 @@ impl From for nsTimingFunction { }, SpecifiedTimingFunction::CubicBezier(p1, p2) => { tf.set_as_bezier(nsTimingFunction_Type::CubicBezier, - Point2D::new(p1.x.value, p1.y.value), - Point2D::new(p2.x.value, p2.y.value)); + Point2D::new(p1.x.get(), p1.y.get()), + Point2D::new(p2.x.get(), p2.y.get())); }, SpecifiedTimingFunction::Keyword(keyword) => { match keyword.to_computed_value() { diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 4f066f46da5..82b3ebddae6 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -3155,11 +3155,11 @@ fn static_assert() { self.gecko.mInitialLetterSink = 0; }, T::Specified(size, sink) => { - self.gecko.mInitialLetterSize = size.value; + self.gecko.mInitialLetterSize = size.get(); if let Some(sink) = sink { self.gecko.mInitialLetterSink = sink.value(); } else { - self.gecko.mInitialLetterSink = size.value.floor() as i32; + self.gecko.mInitialLetterSink = size.get().floor() as i32; } } } diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index 34cdc44a57c..b33ca398209 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -574,8 +574,8 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", p2y = try!(specified::parse_number(context, input)); Ok(()) })); - if p1x.value < 0.0 || p1x.value > 1.0 || - p2x.value < 0.0 || p2x.value > 1.0 { + if p1x.get() < 0.0 || p1x.get() > 1.0 || + p2x.get() < 0.0 || p2x.get() > 1.0 { return Err(()) } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 05ebe2dc211..1852a10f370 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -18,6 +18,7 @@ use std::f32::consts::PI; use std::fmt; use std::ops::Mul; use style_traits::ToCss; +use style_traits::values::specified::AllowedNumericType; use super::{Auto, CSSFloat, CSSInteger, HasViewportPercentage, Either, None_}; use super::computed::{self, Context}; use super::computed::{Shadow as ComputedShadow, ToComputedValue}; @@ -237,11 +238,19 @@ pub fn parse_integer(context: &ParserContext, input: &mut Parser) -> Result Result { + parse_number_with_clamping_mode(context, input, AllowedNumericType::All) +} + +#[allow(missing_docs)] +pub fn parse_number_with_clamping_mode(context: &ParserContext, + input: &mut Parser, + clamping_mode: AllowedNumericType) + -> Result { match try!(input.next()) { - Token::Number(ref value) => { + Token::Number(ref value) if clamping_mode.is_ok(value.value) => { Ok(Number { value: value.value.min(f32::MAX).max(f32::MIN), - was_calc: false, + calc_clamping_mode: None, }) }, Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { @@ -263,7 +272,7 @@ pub fn parse_number(context: &ParserContext, input: &mut Parser) -> Result { Ok(Number { value: result.min(f32::MAX).max(f32::MIN), - was_calc: true, + calc_clamping_mode: Some(clamping_mode), }) }, _ => Err(()) @@ -692,11 +701,10 @@ impl ToCss for Time { #[allow(missing_docs)] pub struct Number { /// The numeric value itself. - pub value: CSSFloat, - /// Whether this came from a `calc()` expression. This is needed for - /// serialization purposes, since `calc(1)` should still serialize to - /// `calc(1)`, not just `1`. - was_calc: bool, + value: CSSFloat, + /// If this number came from a calc() expression, this tells how clamping + /// should be done on the value. + calc_clamping_mode: Option, } no_viewport_percentage!(Number); @@ -708,29 +716,27 @@ impl Parse for Number { } impl Number { - fn parse_with_minimum(context: &ParserContext, input: &mut Parser, min: CSSFloat) -> Result { - match parse_number(context, input) { - Ok(value) if value.value >= min => Ok(value), - _ => Err(()), - } - } - /// Returns a new number with the value `val`. pub fn new(val: CSSFloat) -> Self { Number { value: val, - was_calc: false, + calc_clamping_mode: None, } } + /// Returns the numeric value, clamped if needed. + pub fn get(&self) -> f32 { + self.calc_clamping_mode.map_or(self.value, |mode| mode.clamp(self.value)) + } + #[allow(missing_docs)] pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result { - Number::parse_with_minimum(context, input, 0.0) + parse_number_with_clamping_mode(context, input, AllowedNumericType::NonNegative) } #[allow(missing_docs)] pub fn parse_at_least_one(context: &ParserContext, input: &mut Parser) -> Result { - Number::parse_with_minimum(context, input, 1.0) + parse_number_with_clamping_mode(context, input, AllowedNumericType::AtLeastOne) } } @@ -738,13 +744,13 @@ impl ToComputedValue for Number { type ComputedValue = CSSFloat; #[inline] - fn to_computed_value(&self, _: &Context) -> CSSFloat { self.value } + fn to_computed_value(&self, _: &Context) -> CSSFloat { self.get() } #[inline] fn from_computed_value(computed: &CSSFloat) -> Self { Number { value: *computed, - was_calc: false, + calc_clamping_mode: None, } } } @@ -753,11 +759,11 @@ impl ToCss for Number { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write, { - if self.was_calc { + if self.calc_clamping_mode.is_some() { dest.write_str("calc(")?; } self.value.to_css(dest)?; - if self.was_calc { + if self.calc_clamping_mode.is_some() { dest.write_str(")")?; } Ok(()) diff --git a/components/style_traits/values.rs b/components/style_traits/values.rs index a2825a01a69..05dab8440f6 100644 --- a/components/style_traits/values.rs +++ b/components/style_traits/values.rs @@ -150,6 +150,7 @@ macro_rules! __define_css_keyword_enum__actual { /// Helper types for the handling of specified values. pub mod specified { use app_units::Au; + use std::cmp; /// Whether to allow negative lengths or not. #[repr(u8)] @@ -175,13 +176,47 @@ pub mod specified { /// Clamp the value following the rules of this numeric type. #[inline] pub fn clamp(&self, val: Au) -> Au { - use std::cmp; match *self { AllowedLengthType::All => val, AllowedLengthType::NonNegative => cmp::max(Au(0), val), } } } + + /// Whether to allow negative lengths or not. + #[repr(u8)] + #[cfg_attr(feature = "servo", derive(HeapSizeOf))] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd)] + pub enum AllowedNumericType { + /// Allow all kind of numeric values. + All, + /// Allow only non-negative numeric values. + NonNegative, + /// Allow only numeric values greater or equal to 1.0. + AtLeastOne, + } + + impl AllowedNumericType { + /// Whether the value fits the rules of this numeric type. + #[inline] + pub fn is_ok(&self, val: f32) -> bool { + match *self { + AllowedNumericType::All => true, + AllowedNumericType::NonNegative => val >= 0.0, + AllowedNumericType::AtLeastOne => val >= 1.0, + } + } + + /// Clamp the value following the rules of this numeric type. + #[inline] + pub fn clamp(&self, val: f32) -> f32 { + match *self { + AllowedNumericType::NonNegative if val < 0. => 0., + AllowedNumericType::AtLeastOne if val < 1. => 1., + _ => val, + } + } + } }