servo: Merge #17186 - Use more generics and remove more code from mako files (from servo:derive-all-the-things); r=emilio
authorAnthony Ramine <n.oxyde@gmail.com>
Tue, 06 Jun 2017 10:28:26 -0700
changeset 410871 aaf5e23caa034838fcd04a5d983fca1cd8186b18
parent 410870 949533a9e987b90b9951d3aee4084af83baa262d
child 410872 e5060676549102c4659195d24df81c85c0dd1281
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
servo: Merge #17186 - Use more generics and remove more code from mako files (from servo:derive-all-the-things); r=emilio Source-Repo: https://github.com/servo/servo Source-Revision: 80488c4494911257e62c98388b36d94d74f9d330
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/helpers/animated_properties.mako.rs
servo/components/style/properties/longhand/box.mako.rs
servo/components/style/values/computed/gecko.rs
servo/components/style/values/computed/mod.rs
servo/components/style/values/generics/gecko.rs
servo/components/style/values/generics/mod.rs
servo/components/style/values/specified/gecko.rs
servo/components/style/values/specified/mod.rs
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -2227,33 +2227,26 @@ fn static_assert() {
 
         match self.gecko.mBreak${kind.title()} {
             true => T::always,
             false => T::auto,
         }
     }
     % endfor
 
-    pub fn set_scroll_snap_points_x(&mut self, v: longhands::scroll_snap_points_x::computed_value::T) {
-        match v.0 {
-            None => self.gecko.mScrollSnapPointsX.set_value(CoordDataValue::None),
-            Some(l) => l.to_gecko_style_coord(&mut self.gecko.mScrollSnapPointsX),
-        };
-    }
-
-    ${impl_coord_copy('scroll_snap_points_x', 'mScrollSnapPointsX')}
-
-    pub fn set_scroll_snap_points_y(&mut self, v: longhands::scroll_snap_points_y::computed_value::T) {
-        match v.0 {
-            None => self.gecko.mScrollSnapPointsY.set_value(CoordDataValue::None),
-            Some(l) => l.to_gecko_style_coord(&mut self.gecko.mScrollSnapPointsY),
-        };
-    }
-
-    ${impl_coord_copy('scroll_snap_points_y', 'mScrollSnapPointsY')}
+    % for axis in ["x", "y"]:
+        pub fn set_scroll_snap_points_${axis}(&mut self, v: longhands::scroll_snap_points_${axis}::computed_value::T) {
+            match v.repeated() {
+                None => self.gecko.mScrollSnapPoints${axis.upper()}.set_value(CoordDataValue::None),
+                Some(l) => l.to_gecko_style_coord(&mut self.gecko.mScrollSnapPoints${axis.upper()}),
+            };
+        }
+
+        ${impl_coord_copy('scroll_snap_points_' + axis, 'mScrollSnapPoints' + axis.upper())}
+    % endfor
 
     pub fn set_scroll_snap_coordinate<I>(&mut self, v: I)
         where I: IntoIterator<Item = longhands::scroll_snap_coordinate::computed_value::single_value::T>,
               I::IntoIter: ExactSizeIterator
     {
         let v = v.into_iter();
 
         unsafe { self.gecko.mScrollSnapCoordinate.set_len_pod(v.len() as u32); }
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -34,19 +34,18 @@ use std::cmp;
 #[cfg(feature = "gecko")] use std::collections::HashMap;
 use std::fmt;
 use style_traits::ToCss;
 use super::ComputedValues;
 use values::CSSFloat;
 use values::{Auto, Either};
 use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
 use values::computed::{BorderCornerRadius, ClipRect};
-use values::computed::{CalcLengthOrPercentage, Context, LengthOrPercentage};
-use values::computed::{MaxLength, MozLength};
-use values::computed::ToComputedValue;
+use values::computed::{CalcLengthOrPercentage, Context, ComputedValueAsSpecified};
+use values::computed::{LengthOrPercentage, MaxLength, MozLength, ToComputedValue};
 use values::generics::{SVGPaint, SVGPaintKind};
 use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
 use values::generics::position as generic_position;
 
 
 /// A given transition property, that is either `All`, or an animatable
 /// property.
 // NB: This needs to be here because it needs all the longhands generated
@@ -68,16 +67,20 @@ pub enum TransitionProperty {
         /// ${prop.name}
         ${prop.camel_case},
     % endfor
     /// Unrecognized property which could be any non-animatable, custom property, or
     /// unknown property.
     Unsupported(Atom)
 }
 
+no_viewport_percentage!(TransitionProperty);
+
+impl ComputedValueAsSpecified for TransitionProperty {}
+
 impl TransitionProperty {
     /// Iterates over each longhand property.
     pub fn each<F: FnMut(&TransitionProperty) -> ()>(mut cb: F) {
         % for prop in data.longhands:
             % if prop.animatable:
                 cb(&TransitionProperty::${prop.camel_case});
             % endif
         % endfor
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -419,56 +419,37 @@
                           "computed::TimingFunction::ease()",
                           initial_specified_value="specified::TimingFunction::ease()",
                           vector=True,
                           need_index=True,
                           animation_value_type="none",
                           extra_prefixes="moz webkit",
                           spec="https://drafts.csswg.org/css-transitions/#propdef-transition-timing-function")}
 
-<%helpers:vector_longhand name="transition-property"
-                          allow_empty="True"
-                          need_index="True"
-                          animation_value_type="none"
-                          extra_prefixes="moz webkit"
-                          spec="https://drafts.csswg.org/css-transitions/#propdef-transition-property">
-
-    use values::computed::ComputedValueAsSpecified;
-
-    pub use properties::animated_properties::TransitionProperty;
-    pub use properties::animated_properties::TransitionProperty as SpecifiedValue;
-
-    pub mod computed_value {
-        // NB: Can't generate the type here because it needs all the longhands
-        // generated beforehand.
-        pub use super::SpecifiedValue as T;
-    }
-
-    pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
-        SpecifiedValue::parse(input)
-    }
-
-    pub fn get_initial_specified_value() -> SpecifiedValue {
-        TransitionProperty::All
-    }
-
-    no_viewport_percentage!(SpecifiedValue);
-
-    impl ComputedValueAsSpecified for SpecifiedValue { }
-</%helpers:vector_longhand>
+${helpers.predefined_type("transition-property",
+                          "TransitionProperty",
+                          "computed::TransitionProperty::All",
+                          initial_specified_value="specified::TransitionProperty::All",
+                          vector=True,
+                          allow_empty=True,
+                          need_index=True,
+                          needs_context=False,
+                          animation_value_type="none",
+                          extra_prefixes="moz webkit",
+                          spec="https://drafts.csswg.org/css-transitions/#propdef-transition-property")}
 
 ${helpers.predefined_type("transition-delay",
                           "Time",
                           "computed::Time::zero()",
                           initial_specified_value="specified::Time::zero()",
                           vector=True,
                           need_index=True,
                           animation_value_type="none",
                           extra_prefixes="moz webkit",
-                          spec="https://drafts.csswg.org/css-transitions/#propdef-transition-duration")}
+                          spec="https://drafts.csswg.org/css-transitions/#propdef-transition-delay")}
 
 <%helpers:vector_longhand name="animation-name"
                           need_index="True"
                           animation_value_type="none",
                           extra_prefixes="moz webkit"
                           allowed_in_keyframe_block="False"
                           spec="https://drafts.csswg.org/css-animations/#propdef-animation-name">
     use Atom;
@@ -542,28 +523,26 @@
                           initial_specified_value="specified::Time::zero()",
                           parse_method="parse_non_negative",
                           vector=True,
                           need_index=True,
                           animation_value_type="none",
                           extra_prefixes="moz webkit",
                           spec="https://drafts.csswg.org/css-transitions/#propdef-transition-duration")}
 
-<%helpers:vector_longhand name="animation-timing-function"
-                          need_index="True"
+${helpers.predefined_type("animation-timing-function",
+                          "TimingFunction",
+                          "computed::TimingFunction::ease()",
+                          initial_specified_value="specified::TimingFunction::ease()",
+                          vector=True,
+                          need_index=True,
                           animation_value_type="none",
-                          extra_prefixes="moz webkit"
-                          spec="https://drafts.csswg.org/css-animations/#propdef-animation-timing-function",
-                          allowed_in_keyframe_block="True">
-    pub use properties::longhands::transition_timing_function::single_value::computed_value;
-    pub use properties::longhands::transition_timing_function::single_value::get_initial_value;
-    pub use properties::longhands::transition_timing_function::single_value::get_initial_specified_value;
-    pub use properties::longhands::transition_timing_function::single_value::parse;
-    pub use properties::longhands::transition_timing_function::single_value::SpecifiedValue;
-</%helpers:vector_longhand>
+                          extra_prefixes="moz webkit",
+                          allowed_in_keyframe_block=True,
+                          spec="https://drafts.csswg.org/css-transitions/#propdef-animation-timing-function")}
 
 <%helpers:vector_longhand name="animation-iteration-count"
                           need_index="True"
                           animation_value_type="none",
                           extra_prefixes="moz webkit"
                           spec="https://drafts.csswg.org/css-animations/#propdef-animation-iteration-count",
                           allowed_in_keyframe_block="False">
     use std::fmt;
@@ -655,121 +634,38 @@
                          need_index=True,
                          animation_value_type="none",
                          vector=True,
                          gecko_enum_prefix="FillMode",
                          extra_prefixes="moz webkit",
                          spec="https://drafts.csswg.org/css-animations/#propdef-animation-fill-mode",
                          allowed_in_keyframe_block=False)}
 
-<%helpers:vector_longhand name="animation-delay"
-                          need_index="True"
+${helpers.predefined_type("animation-delay",
+                          "Time",
+                          "computed::Time::zero()",
+                          initial_specified_value="specified::Time::zero()",
+                          vector=True,
+                          need_index=True,
                           animation_value_type="none",
                           extra_prefixes="moz webkit",
                           spec="https://drafts.csswg.org/css-animations/#propdef-animation-delay",
-                          allowed_in_keyframe_block="False">
-    pub use properties::longhands::transition_delay::single_value::computed_value;
-    pub use properties::longhands::transition_delay::single_value::get_initial_specified_value;
-    pub use properties::longhands::transition_delay::single_value::{get_initial_value, parse};
-    pub use properties::longhands::transition_delay::single_value::SpecifiedValue;
-</%helpers:vector_longhand>
-
-<%helpers:longhand products="gecko" name="scroll-snap-points-y" animation_value_type="none"
-                   spec="Nonstandard (https://www.w3.org/TR/2015/WD-css-snappoints-1-20150326/#scroll-snap-points)">
-    use std::fmt;
-    use style_traits::ToCss;
-    use values::specified::LengthOrPercentage;
-
-    pub mod computed_value {
-        use values::computed::LengthOrPercentage;
-
-        #[derive(Debug, Clone, PartialEq)]
-        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-        pub struct T(pub Option<LengthOrPercentage>);
-    }
-
-    #[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
-    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-    pub enum SpecifiedValue {
-        None,
-        Repeat(LengthOrPercentage),
-    }
+                          allowed_in_keyframe_block=False)}
 
-    impl ToCss for computed_value::T {
-        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-            match self.0 {
-                None => dest.write_str("none"),
-                Some(ref l) => {
-                    try!(dest.write_str("repeat("));
-                    try!(l.to_css(dest));
-                    dest.write_str(")")
-                },
-            }
-        }
-    }
-    impl ToCss for SpecifiedValue {
-        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-            match *self {
-                SpecifiedValue::None => dest.write_str("none"),
-                SpecifiedValue::Repeat(ref l) => {
-                    try!(dest.write_str("repeat("));
-                    try!(l.to_css(dest));
-                    dest.write_str(")")
-                },
-            }
-        }
-    }
-
-    #[inline]
-    pub fn get_initial_value() -> computed_value::T {
-        computed_value::T(None)
-    }
-
-    impl ToComputedValue for SpecifiedValue {
-        type ComputedValue = computed_value::T;
-
-        #[inline]
-        fn to_computed_value(&self, context: &Context) -> computed_value::T {
-            match *self {
-                SpecifiedValue::None => computed_value::T(None),
-                SpecifiedValue::Repeat(ref l) =>
-                    computed_value::T(Some(l.to_computed_value(context))),
-            }
-        }
-        #[inline]
-        fn from_computed_value(computed: &computed_value::T) -> Self {
-            match *computed {
-                computed_value::T(None) => SpecifiedValue::None,
-                computed_value::T(Some(l)) =>
-                    SpecifiedValue::Repeat(ToComputedValue::from_computed_value(&l))
-            }
-        }
-    }
-
-    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
-        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
-            Ok(SpecifiedValue::None)
-        } else if input.try(|input| input.expect_function_matching("repeat")).is_ok() {
-            input.parse_nested_block(|input| {
-                LengthOrPercentage::parse_non_negative(context, input).map(SpecifiedValue::Repeat)
-            })
-        } else {
-            Err(())
-        }
-    }
-</%helpers:longhand>
-
-<%helpers:longhand products="gecko" name="scroll-snap-points-x" animation_value_type="none"
-                   spec="Nonstandard (https://www.w3.org/TR/2015/WD-css-snappoints-1-20150326/#scroll-snap-points)">
-    pub use super::scroll_snap_points_y::SpecifiedValue;
-    pub use super::scroll_snap_points_y::computed_value;
-    pub use super::scroll_snap_points_y::get_initial_value;
-    pub use super::scroll_snap_points_y::parse;
-</%helpers:longhand>
-
+% for axis in ["x", "y"]:
+    ${helpers.predefined_type(
+        "scroll-snap-points-" + axis,
+        "ScrollSnapPoint",
+        "computed::ScrollSnapPoint::none()",
+        animation_value_type="none",
+        products="gecko",
+        disable_when_testing=True,
+        spec="Nonstandard (https://www.w3.org/TR/2015/WD-css-snappoints-1-20150326/#scroll-snap-points)",
+    )}
+% endfor
 
 ${helpers.predefined_type("scroll-snap-destination",
                           "Position",
                           "computed::Position::zero()",
                           products="gecko",
                           boxed="True",
                           spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-destination)",
                           animation_value_type="ComputedValue")}
new file mode 100644
--- /dev/null
+++ b/servo/components/style/values/computed/gecko.rs
@@ -0,0 +1,11 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//! Computed types for legacy Gecko-only properties.
+
+use values::computed::length::LengthOrPercentage;
+use values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint;
+
+/// A computed type for scroll snap points.
+pub type ScrollSnapPoint = GenericScrollSnapPoint<LengthOrPercentage>;
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.rs
@@ -18,20 +18,23 @@ use std::fmt;
 use style_traits::ToCss;
 use super::{CSSFloat, CSSInteger, RGBA};
 use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize};
 use super::generics::grid::TrackList as GenericTrackList;
 use super::specified;
 
 pub use app_units::Au;
 pub use cssparser::Color as CSSColor;
+pub use properties::animated_properties::TransitionProperty;
 pub use self::background::BackgroundSize;
 pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
 pub use self::border::{BorderRadius, BorderCornerRadius};
 pub use self::image::{Gradient, GradientItem, ImageLayer, LineDirection, Image, ImageRect};
+#[cfg(feature = "gecko")]
+pub use self::gecko::ScrollSnapPoint;
 pub use self::rect::LengthOrNumberRect;
 pub use super::{Auto, Either, None_};
 #[cfg(feature = "gecko")]
 pub use super::specified::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems};
 pub use super::specified::{BorderStyle, Percentage, UrlOrNone};
 pub use super::generics::grid::GridLine;
 pub use super::specified::url::SpecifiedUrl;
 pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto};
@@ -40,16 +43,18 @@ pub use self::length::{MaxLength, MozLen
 pub use self::position::Position;
 pub use self::text::{LetterSpacing, LineHeight, WordSpacing};
 pub use self::transform::{TimingFunction, TransformOrigin};
 
 pub mod background;
 pub mod basic_shape;
 pub mod border;
 pub mod image;
+#[cfg(feature = "gecko")]
+pub mod gecko;
 pub mod length;
 pub mod position;
 pub mod rect;
 pub mod text;
 pub mod transform;
 
 /// A `Context` is all the data a specified value could ever need to compute
 /// itself and be transformed to a computed value.
new file mode 100644
--- /dev/null
+++ b/servo/components/style/values/generics/gecko.rs
@@ -0,0 +1,54 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//! Generic types for legacy Gecko-only properties that should probably be
+//! unshipped at some point in the future.
+
+use std::fmt;
+use style_traits::ToCss;
+
+/// A generic value for scroll snap points.
+#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
+pub enum ScrollSnapPoint<LengthOrPercentage> {
+    /// `none`
+    None,
+    /// `repeat(<length-or-percentage>)`
+    Repeat(LengthOrPercentage)
+}
+
+impl<L> ScrollSnapPoint<L> {
+    /// Returns `none`.
+    #[inline]
+    pub fn none() -> Self {
+        ScrollSnapPoint::None
+    }
+
+    /// Returns the repeat argument, if any.
+    #[inline]
+    pub fn repeated(&self) -> Option<&L> {
+        match *self {
+            ScrollSnapPoint::None => None,
+            ScrollSnapPoint::Repeat(ref length) => Some(length),
+        }
+    }
+}
+
+impl<L> ToCss for ScrollSnapPoint<L>
+where
+    L: ToCss,
+{
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
+    where
+        W: fmt::Write,
+    {
+        match *self {
+            ScrollSnapPoint::None => dest.write_str("none"),
+            ScrollSnapPoint::Repeat(ref length) => {
+                dest.write_str("repeat(")?;
+                length.to_css(dest)?;
+                dest.write_str(")")
+            },
+        }
+    }
+}
--- a/servo/components/style/values/generics/mod.rs
+++ b/servo/components/style/values/generics/mod.rs
@@ -11,16 +11,18 @@ use parser::{Parse, ParserContext};
 use std::fmt;
 use style_traits::{OneOrMoreCommaSeparated, ToCss};
 use super::CustomIdent;
 use values::specified::url::SpecifiedUrl;
 
 pub mod background;
 pub mod basic_shape;
 pub mod border;
+#[cfg(feature = "gecko")]
+pub mod gecko;
 pub mod grid;
 pub mod image;
 pub mod position;
 pub mod rect;
 pub mod text;
 pub mod transform;
 
 // https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type
new file mode 100644
--- /dev/null
+++ b/servo/components/style/values/specified/gecko.rs
@@ -0,0 +1,26 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//! Specified types for legacy Gecko-only properties.
+
+use cssparser::Parser;
+use parser::{Parse, ParserContext};
+use values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint;
+use values::specified::length::LengthOrPercentage;
+
+/// A specified type for scroll snap points.
+pub type ScrollSnapPoint = GenericScrollSnapPoint<LengthOrPercentage>;
+
+impl Parse for ScrollSnapPoint {
+    fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
+        if input.try(|i| i.expect_ident_matching("none")).is_ok() {
+            return Ok(GenericScrollSnapPoint::None);
+        }
+        input.expect_function_matching("repeat")?;
+        let length = input.parse_nested_block(|i| {
+            LengthOrPercentage::parse_non_negative(context, i)
+        })?;
+        Ok(GenericScrollSnapPoint::Repeat(length))
+    }
+}
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -22,42 +22,47 @@ use style_traits::values::specified::All
 use super::{Auto, CSSFloat, CSSInteger, Either, None_};
 use super::computed::{self, Context};
 use super::computed::{Shadow as ComputedShadow, ToComputedValue};
 use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize};
 use super::generics::grid::TrackList as GenericTrackList;
 use values::computed::ComputedValueAsSpecified;
 use values::specified::calc::CalcNode;
 
+pub use properties::animated_properties::TransitionProperty;
 #[cfg(feature = "gecko")]
 pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems};
 pub use self::background::BackgroundSize;
 pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
 pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth};
 pub use self::color::Color;
 pub use self::rect::LengthOrNumberRect;
-pub use super::generics::grid::GridLine;
+#[cfg(feature = "gecko")]
+pub use self::gecko::ScrollSnapPoint;
 pub use self::image::{ColorStop, EndingShape as GradientEndingShape, Gradient};
 pub use self::image::{GradientItem, GradientKind, Image, ImageRect, ImageLayer};
 pub use self::length::AbsoluteLength;
 pub use self::length::{FontRelativeLength, ViewportPercentageLength, CharacterWidth, Length, CalcLengthOrPercentage};
 pub use self::length::{Percentage, LengthOrNone, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto};
 pub use self::length::{LengthOrPercentageOrNone, LengthOrPercentageOrAutoOrContent, NoCalcLength};
 pub use self::length::{MaxLength, MozLength};
 pub use self::position::{Position, PositionComponent};
 pub use self::text::{LetterSpacing, LineHeight, WordSpacing};
 pub use self::transform::{TimingFunction, TransformOrigin};
+pub use super::generics::grid::GridLine;
 
 #[cfg(feature = "gecko")]
 pub mod align;
 pub mod background;
 pub mod basic_shape;
 pub mod border;
 pub mod calc;
 pub mod color;
+#[cfg(feature = "gecko")]
+pub mod gecko;
 pub mod grid;
 pub mod image;
 pub mod length;
 pub mod position;
 pub mod rect;
 pub mod text;
 pub mod transform;