Bug 1374233 - Part 6: Add PositiveInteger and PositiveIntegerOrAuto for column-count. draft
authorBoris Chiou <boris.chiou@gmail.com>
Thu, 20 Jul 2017 17:32:56 +0800
changeset 614997 8a2d21f3348c00e86ce2149f5240b13e4b0afe1d
parent 614996 2d07c4faed1715015d4a1cd94812f3ee4d96d22c
child 614998 6d0a21f50687384fc91b93f9a158338748e14376
push id70205
push userbmo:boris.chiou@gmail.com
push dateTue, 25 Jul 2017 08:53:17 +0000
bugs1374233
milestone56.0a1
Bug 1374233 - Part 6: Add PositiveInteger and PositiveIntegerOrAuto for column-count. column-count should be a positive integer or auto. MozReview-Commit-ID: 9LFvrYo8De5
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/helpers/animated_properties.mako.rs
servo/components/style/properties/longhand/column.mako.rs
servo/components/style/values/animated/mod.rs
servo/components/style/values/computed/mod.rs
servo/components/style/values/specified/mod.rs
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -4793,31 +4793,32 @@ clip-path
 <%self:impl_trait style_struct_name="Column"
                   skip_longhands="column-count column-rule-width">
 
     #[allow(unused_unsafe)]
     pub fn set_column_count(&mut self, v: longhands::column_count::computed_value::T) {
         use gecko_bindings::structs::{NS_STYLE_COLUMN_COUNT_AUTO, nsStyleColumn_kMaxColumnCount};
 
         self.gecko.mColumnCount = match v {
-            Either::First(number) => unsafe {
-                cmp::min(number as u32, nsStyleColumn_kMaxColumnCount)
+            Either::First(integer) => unsafe {
+                cmp::min(integer.0 as u32, nsStyleColumn_kMaxColumnCount)
             },
             Either::Second(Auto) => NS_STYLE_COLUMN_COUNT_AUTO
         };
     }
 
     ${impl_simple_copy('column_count', 'mColumnCount')}
 
     pub fn clone_column_count(&self) -> longhands::column_count::computed_value::T {
         use gecko_bindings::structs::NS_STYLE_COLUMN_COUNT_AUTO;
+        use values::computed::PositiveInteger;
         if self.gecko.mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO {
             debug_assert!((self.gecko.mColumnCount as i32) >= 0 &&
                           (self.gecko.mColumnCount as i32) < i32::max_value());
-            Either::First(self.gecko.mColumnCount as i32)
+            Either::First(PositiveInteger(self.gecko.mColumnCount as i32))
         } else {
             Either::Second(Auto)
         }
     }
 
     <% impl_non_negative_app_units("column_rule_width", "mColumnRuleWidth", need_clone=True,
                                    round_to_pixels=True) %>
 </%self:impl_trait>
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -41,16 +41,17 @@ use values::animated::effects::BoxShadow
 use values::animated::effects::Filter as AnimatedFilter;
 use values::animated::effects::FilterList as AnimatedFilterList;
 use values::animated::effects::TextShadowList as AnimatedTextShadowList;
 use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
 use values::computed::{BorderCornerRadius, ClipRect};
 use values::computed::{CalcLengthOrPercentage, Color, Context, ComputedValueAsSpecified};
 use values::computed::{LengthOrPercentage, MaxLength, MozLength, Percentage, ToComputedValue};
 use values::computed::{GreaterThanOrEqualToOneNumber, NonNegativeAu, NonNegativeNumber};
+use values::computed::{PositiveInteger, PositiveIntegerOrAuto};
 use values::computed::length::{NonNegativeLengthOrAuto, NonNegativeLengthOrNormal};
 use values::computed::length::NonNegativeLengthOrNumber;
 use values::generics::{SVGPaint, SVGPaintKind};
 use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
 use values::generics::effects::Filter;
 use values::generics::position as generic_position;
 
 /// A trait used to implement various procedures used during animation.
@@ -945,16 +946,29 @@ impl Animatable for GreaterThanOrEqualTo
     }
 
     #[inline]
     fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
         self.0.compute_distance(&other.0)
     }
 }
 
+/// https://drafts.csswg.org/css-transitions/#animtype-integer
+impl Animatable for PositiveInteger {
+    #[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(PositiveInteger)
+    }
+
+    #[inline]
+    fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+        self.0.compute_distance(&other.0)
+    }
+}
+
 /// https://drafts.csswg.org/css-transitions/#animtype-number
 impl Animatable for Angle {
     #[inline]
     fn add_weighted(&self, other: &Angle, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
         match (*self, *other) {
             % for angle_type in [ 'Degree', 'Gradian', 'Turn' ]:
             (Angle::${angle_type}(val1), Angle::${angle_type}(val2)) => {
                 Ok(Angle::${angle_type}(
--- a/servo/components/style/properties/longhand/column.mako.rs
+++ b/servo/components/style/properties/longhand/column.mako.rs
@@ -12,22 +12,21 @@
                           initial_specified_value="Either::Second(Auto)",
                           extra_prefixes="moz",
                           animation_value_type="NonNegativeLengthOrAuto",
                           experimental=True,
                           spec="https://drafts.csswg.org/css-multicol/#propdef-column-width")}
 
 
 ${helpers.predefined_type("column-count",
-                          "IntegerOrAuto",
+                          "PositiveIntegerOrAuto",
                           "Either::Second(Auto)",
-                          parse_method="parse_positive",
                           initial_specified_value="Either::Second(Auto)",
                           experimental="True",
-                          animation_value_type="ComputedValue",
+                          animation_value_type="PositiveIntegerOrAuto",
                           extra_prefixes="moz",
                           spec="https://drafts.csswg.org/css-multicol/#propdef-column-count")}
 
 ${helpers.predefined_type("column-gap",
                           "length::NonNegativeLengthOrNormal",
                           "Either::Second(Normal)",
                           extra_prefixes="moz",
                           experimental=True,
--- a/servo/components/style/values/animated/mod.rs
+++ b/servo/components/style/values/animated/mod.rs
@@ -8,16 +8,17 @@
 //! computed values and need yet another intermediate representation. This
 //! module's raison d'ĂȘtre is to ultimately contain all these types.
 
 use app_units::Au;
 use values::computed::Angle as ComputedAngle;
 use values::computed::NonNegativeAu;
 use values::computed::NonNegativeNumber as ComputedNonNegativeNumber;
 use values::computed::GreaterThanOrEqualToOneNumber as ComputedGreaterThanOrEqualToOneNumber;
+use values::computed::PositiveInteger as ComputedPositiveInteger;
 use values::specified::url::SpecifiedUrl;
 
 pub mod effects;
 
 /// Conversion between computed values and intermediate values for animations.
 ///
 /// Notably, colors are represented as four floats during animations.
 pub trait ToAnimatedValue {
@@ -128,16 +129,30 @@ impl ToAnimatedValue for NonNegativeAu {
     }
 
     #[inline]
     fn from_animated_value(animated: Self::AnimatedValue) -> Self {
         animated.max(NonNegativeAu(Au(0)))
     }
 }
 
+impl ToAnimatedValue for ComputedPositiveInteger {
+    type AnimatedValue = Self;
+
+    #[inline]
+    fn to_animated_value(self) -> Self {
+        self
+    }
+
+    #[inline]
+    fn from_animated_value(animated: Self::AnimatedValue) -> Self {
+        animated.max(ComputedPositiveInteger(1))
+    }
+}
+
 /// Returns a value similar to `self` that represents zero.
 pub trait ToAnimatedZero: Sized {
     /// Returns a value that, when added with an underlying value, will produce the underlying
     /// value. This is used for SMIL animation's "by-animation" where SMIL first interpolates from
     /// the zero value to the 'by' value, and then adds the result to the underlying value.
     ///
     /// This is not the necessarily the same as the initial value of a property. For example, the
     /// initial value of 'stroke-width' is 1, but the zero value is 0, since adding 1 to the
@@ -170,12 +185,17 @@ impl ToAnimatedZero for ComputedNonNegat
     fn to_animated_zero(&self) -> Result<Self, ()> { Ok(ComputedNonNegativeNumber(0.)) }
 }
 
 impl ToAnimatedZero for ComputedGreaterThanOrEqualToOneNumber {
     #[inline]
     fn to_animated_zero(&self) -> Result<Self, ()> { Ok(ComputedGreaterThanOrEqualToOneNumber(0.)) }
 }
 
+impl ToAnimatedZero for ComputedPositiveInteger {
+    #[inline]
+    fn to_animated_zero(&self) -> Result<Self, ()> { Ok(ComputedPositiveInteger(0)) }
+}
+
 impl ToAnimatedZero for NonNegativeAu {
     #[inline]
     fn to_animated_zero(&self) -> Result<Self, ()> { Ok(NonNegativeAu(Au(0))) }
 }
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.rs
@@ -484,16 +484,31 @@ impl IntegerOrAuto {
     pub fn integer_or(&self, auto_value: CSSInteger) -> CSSInteger {
         match *self {
             Either::First(n) => n,
             Either::Second(Auto) => auto_value,
         }
     }
 }
 
+/// A wrapper of Integer, but only accept a value >= 0.
+#[derive(Clone, PartialEq, PartialOrd, Copy, Debug, ToCss)]
+pub struct PositiveInteger(pub CSSInteger);
+
+impl PositiveInteger {
+    /// Returns the maximum of |self| and |other|.
+    #[inline]
+    pub fn max(self, other: Self) -> Self {
+        PositiveInteger(::std::cmp::max(self.0, other.0))
+    }
+}
+
+/// PositiveInteger | auto
+pub type PositiveIntegerOrAuto = Either<PositiveInteger, Auto>;
+
 /// Computed SVG Paint value
 pub type SVGPaint = ::values::generics::SVGPaint<RGBA>;
 /// Computed SVG Paint Kind value
 pub type SVGPaintKind = ::values::generics::SVGPaintKind<RGBA>;
 
 impl Default for SVGPaint {
     fn default() -> Self {
         SVGPaint {
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -734,16 +734,47 @@ impl IntegerOrAuto {
                                   -> Result<IntegerOrAuto, ParseError<'i>> {
         match IntegerOrAuto::parse(context, input) {
             Ok(Either::First(integer)) if integer.value() <= 0 => Err(StyleParseError::UnspecifiedError.into()),
             result => result,
         }
     }
 }
 
+/// A wrapper of Integer, with value >= 1.
+#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, ToCss)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+pub struct PositiveInteger(Integer);
+
+no_viewport_percentage!(PositiveInteger);
+
+impl Parse for PositiveInteger {
+    #[inline]
+    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
+        Integer::parse_positive(context, input).map(PositiveInteger)
+    }
+}
+
+impl ToComputedValue for PositiveInteger {
+    type ComputedValue = computed::PositiveInteger;
+
+    #[inline]
+    fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
+        computed::PositiveInteger(self.0.to_computed_value(context))
+    }
+
+    #[inline]
+    fn from_computed_value(computed: &Self::ComputedValue) -> Self {
+        PositiveInteger(Integer::from_computed_value(&computed.0))
+    }
+}
+
+/// PositiveInteger | auto
+pub type PositiveIntegerOrAuto = Either<PositiveInteger, Auto>;
+
 #[allow(missing_docs)]
 pub type UrlOrNone = Either<SpecifiedUrl, None_>;
 
 /// The specified value of a grid `<track-breadth>`
 pub type TrackBreadth = GenericTrackBreadth<LengthOrPercentage>;
 
 /// The specified value of a grid `<track-size>`
 pub type TrackSize = GenericTrackSize<LengthOrPercentage>;