Bug 1374233 - Part 1: Add NonNegativeNumber and GreaterThanOrEqualToOneNumber.

NonNegativeNumber: for -moz-box-flex, flex-grow, and flex-shrink.
GreaterThanOrEqualToOneNumber: for stroke-miterlimit.

MozReview-Commit-ID: Kgbt99BPdVA
This commit is contained in:
Boris Chiou 2017-07-19 19:45:24 +08:00
parent 50c9797ddd
commit 4cc97746f2
12 changed files with 181 additions and 26 deletions

View file

@ -137,8 +137,8 @@ impl FlexItem {
min_size: Au(0), min_size: Au(0),
max_size: MAX_AU, max_size: MAX_AU,
index: index, index: index,
flex_grow: flex_grow, flex_grow: flex_grow.into(),
flex_shrink: flex_shrink, flex_shrink: flex_shrink.into(),
order: order, order: order,
is_frozen: false, is_frozen: false,
is_strut: false is_strut: false

View file

@ -397,14 +397,14 @@ impl ${style_struct.gecko_struct_name} {
<%def name="impl_simple_setter(ident, gecko_ffi_name)"> <%def name="impl_simple_setter(ident, gecko_ffi_name)">
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
${set_gecko_property(gecko_ffi_name, "v")} ${set_gecko_property(gecko_ffi_name, "From::from(v)")}
} }
</%def> </%def>
<%def name="impl_simple_clone(ident, gecko_ffi_name)"> <%def name="impl_simple_clone(ident, gecko_ffi_name)">
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
self.gecko.${gecko_ffi_name} From::from(self.gecko.${gecko_ffi_name})
} }
</%def> </%def>
@ -1088,6 +1088,7 @@ impl Clone for ${style_struct.gecko_struct_name} {
predefined_types = { predefined_types = {
"length::LengthOrAuto": impl_style_coord, "length::LengthOrAuto": impl_style_coord,
"length::LengthOrNormal": impl_style_coord, "length::LengthOrNormal": impl_style_coord,
"GreaterThanOrEqualToOneNumber": impl_simple,
"Length": impl_absolute_length, "Length": impl_absolute_length,
"Position": impl_position, "Position": impl_position,
"LengthOrPercentage": impl_style_coord, "LengthOrPercentage": impl_style_coord,
@ -1097,6 +1098,7 @@ impl Clone for ${style_struct.gecko_struct_name} {
"LengthOrNormal": impl_style_coord, "LengthOrNormal": impl_style_coord,
"MaxLength": impl_style_coord, "MaxLength": impl_style_coord,
"MozLength": impl_style_coord, "MozLength": impl_style_coord,
"NonNegativeNumber": impl_simple,
"Number": impl_simple, "Number": impl_simple,
"Integer": impl_simple, "Integer": impl_simple,
"Opacity": impl_simple, "Opacity": impl_simple,

View file

@ -43,6 +43,8 @@ use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone
use values::computed::{BorderCornerRadius, ClipRect}; use values::computed::{BorderCornerRadius, ClipRect};
use values::computed::{CalcLengthOrPercentage, Color, Context, ComputedValueAsSpecified}; use values::computed::{CalcLengthOrPercentage, Color, Context, ComputedValueAsSpecified};
use values::computed::{LengthOrPercentage, MaxLength, MozLength, Percentage, ToComputedValue}; use values::computed::{LengthOrPercentage, MaxLength, MozLength, Percentage, ToComputedValue};
use values::computed::NonNegativeNumber;
use values::generics::{GreaterThanOrEqualToOne, NonNegative};
use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius; use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
use values::generics::effects::Filter; use values::generics::effects::Filter;
use values::generics::position as generic_position; use values::generics::position as generic_position;
@ -3366,3 +3368,49 @@ sorted_shorthands = [(p, position) for position, p in enumerate(sorted_shorthand
% endfor % endfor
} }
} }
impl<T> Animatable for NonNegative<T>
where T: Animatable + Clone
{
#[inline]
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
self.0.add_weighted(&other.0, self_portion, other_portion).map(NonNegative::<T>)
}
#[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
self.0.compute_distance(&other.0)
}
}
impl<T> ToAnimatedZero for NonNegative<T>
where T: ToAnimatedZero
{
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
self.0.to_animated_zero().map(NonNegative::<T>)
}
}
impl<T> Animatable for GreaterThanOrEqualToOne<T>
where T: Animatable + Clone
{
#[inline]
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
self.0.add_weighted(&other.0, self_portion, other_portion).map(GreaterThanOrEqualToOne::<T>)
}
#[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
self.0.compute_distance(&other.0)
}
}
impl<T> ToAnimatedZero for GreaterThanOrEqualToOne<T>
where T: ToAnimatedZero
{
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
self.0.to_animated_zero().map(GreaterThanOrEqualToOne::<T>)
}
}

View file

@ -80,9 +80,10 @@ ${helpers.single_keyword("stroke-linejoin", "miter round bevel",
products="gecko", animation_value_type="discrete", products="gecko", animation_value_type="discrete",
spec="https://www.w3.org/TR/SVG11/painting.html#StrokeLinejoinProperty")} spec="https://www.w3.org/TR/SVG11/painting.html#StrokeLinejoinProperty")}
${helpers.predefined_type("stroke-miterlimit", "Number", "4.0", ${helpers.predefined_type("stroke-miterlimit", "GreaterThanOrEqualToOneNumber",
"parse_at_least_one", products="gecko", "From::from(4.0)",
animation_value_type="ComputedValue", products="gecko",
animation_value_type="::values::computed::GreaterThanOrEqualToOneNumber",
spec="https://www.w3.org/TR/SVG11/painting.html#StrokeMiterlimitProperty")} spec="https://www.w3.org/TR/SVG11/painting.html#StrokeMiterlimitProperty")}
${helpers.predefined_type("stroke-opacity", "SVGOpacity", "Default::default()", ${helpers.predefined_type("stroke-opacity", "SVGOpacity", "Default::default()",

View file

@ -117,17 +117,17 @@ ${helpers.single_keyword("flex-wrap", "nowrap wrap wrap-reverse",
% endif % endif
// Flex item properties // Flex item properties
${helpers.predefined_type("flex-grow", "Number", ${helpers.predefined_type("flex-grow", "NonNegativeNumber",
"0.0", "parse_non_negative", "From::from(0.0)",
spec="https://drafts.csswg.org/css-flexbox/#flex-grow-property", spec="https://drafts.csswg.org/css-flexbox/#flex-grow-property",
extra_prefixes="webkit", extra_prefixes="webkit",
animation_value_type="ComputedValue")} animation_value_type="NonNegativeNumber")}
${helpers.predefined_type("flex-shrink", "Number", ${helpers.predefined_type("flex-shrink", "NonNegativeNumber",
"1.0", "parse_non_negative", "From::from(1.0)",
spec="https://drafts.csswg.org/css-flexbox/#flex-shrink-property", spec="https://drafts.csswg.org/css-flexbox/#flex-shrink-property",
extra_prefixes="webkit", extra_prefixes="webkit",
animation_value_type="ComputedValue")} animation_value_type="NonNegativeNumber")}
// https://drafts.csswg.org/css-align/#align-self-property // https://drafts.csswg.org/css-align/#align-self-property
% if product == "servo": % if product == "servo":

View file

@ -24,9 +24,9 @@ ${helpers.single_keyword("-moz-box-direction", "normal reverse",
alias="-webkit-box-direction", alias="-webkit-box-direction",
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-direction)")} spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-direction)")}
${helpers.predefined_type("-moz-box-flex", "Number", "0.0", "parse_non_negative", ${helpers.predefined_type("-moz-box-flex", "NonNegativeNumber", "From::from(0.)",
products="gecko", gecko_ffi_name="mBoxFlex", products="gecko", gecko_ffi_name="mBoxFlex",
animation_value_type="ComputedValue", animation_value_type="NonNegativeNumber",
alias="-webkit-box-flex", alias="-webkit-box-flex",
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-flex)")} spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-flex)")}

View file

@ -46,12 +46,13 @@
extra_prefixes="webkit" extra_prefixes="webkit"
derive_serialize="True" derive_serialize="True"
spec="https://drafts.csswg.org/css-flexbox/#flex-property"> spec="https://drafts.csswg.org/css-flexbox/#flex-property">
use values::specified::Number; use parser::Parse;
use values::specified::NonNegativeNumber;
fn parse_flexibility<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) fn parse_flexibility<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<(Number, Option<Number>),ParseError<'i>> { -> Result<(NonNegativeNumber, Option<NonNegativeNumber>),ParseError<'i>> {
let grow = Number::parse_non_negative(context, input)?; let grow = NonNegativeNumber::parse(context, input)?;
let shrink = input.try(|i| Number::parse_non_negative(context, i)).ok(); let shrink = input.try(|i| NonNegativeNumber::parse(context, i)).ok();
Ok((grow, shrink)) Ok((grow, shrink))
} }
@ -63,8 +64,8 @@
if input.try(|input| input.expect_ident_matching("none")).is_ok() { if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(expanded! { return Ok(expanded! {
flex_grow: Number::new(0.0), flex_grow: NonNegativeNumber::new(0.0),
flex_shrink: Number::new(0.0), flex_shrink: NonNegativeNumber::new(0.0),
flex_basis: longhands::flex_basis::SpecifiedValue::auto(), flex_basis: longhands::flex_basis::SpecifiedValue::auto(),
}) })
} }
@ -89,8 +90,8 @@
return Err(StyleParseError::UnspecifiedError.into()) return Err(StyleParseError::UnspecifiedError.into())
} }
Ok(expanded! { Ok(expanded! {
flex_grow: grow.unwrap_or(Number::new(1.0)), flex_grow: grow.unwrap_or(NonNegativeNumber::new(1.0)),
flex_shrink: shrink.unwrap_or(Number::new(1.0)), flex_shrink: shrink.unwrap_or(NonNegativeNumber::new(1.0)),
// Per spec, this should be SpecifiedValue::zero(), but all // Per spec, this should be SpecifiedValue::zero(), but all
// browsers currently agree on using `0%`. This is a spec // browsers currently agree on using `0%`. This is a spec
// change which hasn't been adopted by browsers: // change which hasn't been adopted by browsers:

View file

@ -10,6 +10,8 @@
use app_units::Au; use app_units::Au;
use values::computed::Angle as ComputedAngle; use values::computed::Angle as ComputedAngle;
use values::computed::GreaterThanOrEqualToOneNumber as ComputedGreaterThanOrEqualToOneNumber;
use values::computed::NonNegativeNumber as ComputedNonNegativeNumber;
use values::specified::url::SpecifiedUrl; use values::specified::url::SpecifiedUrl;
pub mod effects; pub mod effects;
@ -88,6 +90,34 @@ where
} }
} }
impl ToAnimatedValue for ComputedNonNegativeNumber {
type AnimatedValue = Self;
#[inline]
fn to_animated_value(self) -> Self {
self
}
#[inline]
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
animated.0.max(0.).into()
}
}
impl ToAnimatedValue for ComputedGreaterThanOrEqualToOneNumber {
type AnimatedValue = Self;
#[inline]
fn to_animated_value(self) -> Self {
self
}
#[inline]
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
animated.0.max(1.).into()
}
}
/// Returns a value similar to `self` that represents zero. /// Returns a value similar to `self` that represents zero.
pub trait ToAnimatedZero: Sized { pub trait ToAnimatedZero: Sized {
/// Returns a value that, when added with an underlying value, will produce the underlying /// Returns a value that, when added with an underlying value, will produce the underlying

View file

@ -18,6 +18,7 @@ use std::f64::consts::PI;
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use super::{CSSFloat, CSSInteger}; use super::{CSSFloat, CSSInteger};
use super::generics::{GreaterThanOrEqualToOne, NonNegative};
use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize}; use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize};
use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent; use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent;
use super::generics::grid::TrackList as GenericTrackList; use super::generics::grid::TrackList as GenericTrackList;
@ -425,6 +426,40 @@ impl ComputedValueAsSpecified for specified::BorderStyle {}
/// A `<number>` value. /// A `<number>` value.
pub type Number = CSSFloat; pub type Number = CSSFloat;
/// A wrapper of Number, but the value >= 0.
pub type NonNegativeNumber = NonNegative<CSSFloat>;
impl From<CSSFloat> for NonNegativeNumber {
#[inline]
fn from(number: CSSFloat) -> NonNegativeNumber {
NonNegative::<CSSFloat>(number)
}
}
impl From<NonNegativeNumber> for CSSFloat {
#[inline]
fn from(number: NonNegativeNumber) -> CSSFloat {
number.0
}
}
/// A wrapper of Number, but the value >= 1.
pub type GreaterThanOrEqualToOneNumber = GreaterThanOrEqualToOne<CSSFloat>;
impl From<CSSFloat> for GreaterThanOrEqualToOneNumber {
#[inline]
fn from(number: CSSFloat) -> GreaterThanOrEqualToOneNumber {
GreaterThanOrEqualToOne::<CSSFloat>(number)
}
}
impl From<GreaterThanOrEqualToOneNumber> for CSSFloat {
#[inline]
fn from(number: GreaterThanOrEqualToOneNumber) -> CSSFloat {
number.0
}
}
#[allow(missing_docs)] #[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Copy, Debug, PartialEq, ToCss)] #[derive(Clone, Copy, Debug, PartialEq, ToCss)]

View file

@ -252,3 +252,13 @@ impl ToCss for FontSettingTagFloat {
self.0.to_css(dest) self.0.to_css(dest)
} }
} }
/// A wrapper of Non-negative values.
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, PartialOrd, ToComputedValue, ToCss)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
pub struct NonNegative<T>(pub T);
/// A wrapper of greater-than-or-equal-to-one values.
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, PartialOrd, ToComputedValue, ToCss)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
pub struct GreaterThanOrEqualToOne<T>(pub T);

View file

@ -18,6 +18,7 @@ use style_traits::{ToCss, ParseError, StyleParseError};
use style_traits::values::specified::AllowedNumericType; use style_traits::values::specified::AllowedNumericType;
use super::{Auto, CSSFloat, CSSInteger, Either, None_}; use super::{Auto, CSSFloat, CSSInteger, Either, None_};
use super::computed::{self, Context, ToComputedValue}; use super::computed::{self, Context, ToComputedValue};
use super::generics::{GreaterThanOrEqualToOne, NonNegative};
use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize}; use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize};
use super::generics::grid::TrackList as GenericTrackList; use super::generics::grid::TrackList as GenericTrackList;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
@ -509,6 +510,33 @@ impl ToCss for Number {
} }
} }
/// A Number which is >= 0.0.
pub type NonNegativeNumber = NonNegative<Number>;
impl Parse for NonNegativeNumber {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
parse_number_with_clamping_mode(context, input, AllowedNumericType::NonNegative)
.map(NonNegative::<Number>)
}
}
impl NonNegativeNumber {
/// Returns a new non-negative number with the value `val`.
pub fn new(val: CSSFloat) -> Self {
NonNegative::<Number>(Number::new(val.max(0.)))
}
}
/// A Number which is >= 1.0.
pub type GreaterThanOrEqualToOneNumber = GreaterThanOrEqualToOne<Number>;
impl Parse for GreaterThanOrEqualToOneNumber {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
parse_number_with_clamping_mode(context, input, AllowedNumericType::AtLeastOne)
.map(GreaterThanOrEqualToOne::<Number>)
}
}
/// <number> | <percentage> /// <number> | <percentage>
/// ///
/// Accepts only non-negative numbers. /// Accepts only non-negative numbers.

View file

@ -556,12 +556,12 @@ mod shorthand_serialization {
#[test] #[test]
fn flex_should_serialize_all_available_properties() { fn flex_should_serialize_all_available_properties() {
use style::values::specified::{Number, Percentage}; use style::values::specified::{NonNegativeNumber, Percentage};
let mut properties = Vec::new(); let mut properties = Vec::new();
let grow = Number::new(2f32); let grow = NonNegativeNumber::new(2f32);
let shrink = Number::new(3f32); let shrink = NonNegativeNumber::new(3f32);
let basis = let basis =
FlexBasis::Length(Percentage::new(0.5f32).into()); FlexBasis::Length(Percentage::new(0.5f32).into());