Bug 1371115 - Part 2: implements nsStyleGridLine type properties animatable. r?hiro draft
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Wed, 28 Jun 2017 10:23:37 +0900
changeset 601110 c49a6fe42eb323eb904f5c6f050f389464d33e82
parent 601109 edc89d0f911eb4d1d5c3dcaf19058828e6d765b7
child 601111 8285e6415e561402adf006a162e92ecf5300d9cd
push id65962
push userbmo:dakatsuka@mozilla.com
push dateWed, 28 Jun 2017 01:27:06 +0000
reviewershiro
bugs1371115
milestone56.0a1
Bug 1371115 - Part 2: implements nsStyleGridLine type properties animatable. r?hiro In this patch, implements following properties: * grid-column-end * grid-column-start * grid-row-end * grid-row-start MozReview-Commit-ID: 2iG6aeuFsE4
servo/components/style/gecko/conversions.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/longhand/position.mako.rs
--- a/servo/components/style/gecko/conversions.rs
+++ b/servo/components/style/gecko/conversions.rs
@@ -9,20 +9,21 @@
 #![allow(unsafe_code)]
 
 use app_units::Au;
 use gecko::values::{convert_rgba_to_nscolor, GeckoStyleCoordConvertible};
 use gecko_bindings::bindings::{Gecko_CreateGradient, Gecko_SetGradientImageValue, Gecko_SetLayerImageImageValue};
 use gecko_bindings::bindings::{Gecko_InitializeImageCropRect, Gecko_SetImageElement};
 use gecko_bindings::structs::{nsCSSUnit, nsStyleCoord_CalcValue, nsStyleImage};
 use gecko_bindings::structs::{nsresult, SheetType};
-use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordDataMut};
+use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
 use stylesheets::{Origin, RulesMutateError};
 use values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image};
 use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
+use values::generics::grid::TrackSize;
 use values::generics::image::{CompatMode, Image as GenericImage, GradientItem};
 use values::specified::length::Percentage;
 
 impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
     fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
         let has_percentage = other.percentage.is_some();
         nsStyleCoord_CalcValue {
             mLength: other.unclamped_length().0,
@@ -555,8 +556,56 @@ impl From<Origin> for SheetType {
     fn from(other: Origin) -> Self {
         match other {
             Origin::UserAgent => SheetType::Agent,
             Origin::Author => SheetType::Doc,
             Origin::User => SheetType::User,
         }
     }
 }
+
+impl TrackSize<LengthOrPercentage> {
+    /// Return TrackSize from given two nsStyleCoord
+    pub fn from_gecko_style_coords<T: CoordData>(gecko_min: &T, gecko_max: &T) -> Self {
+        use gecko_bindings::structs::root::nsStyleUnit;
+        use values::computed::length::LengthOrPercentage;
+        use values::generics::grid::{TrackBreadth, TrackSize};
+
+        if gecko_min.unit() == nsStyleUnit::eStyleUnit_None {
+            debug_assert!(gecko_max.unit() == nsStyleUnit::eStyleUnit_Coord ||
+                          gecko_max.unit() == nsStyleUnit::eStyleUnit_Percent);
+            return TrackSize::FitContent(LengthOrPercentage::from_gecko_style_coord(gecko_max)
+                                         .expect("gecko_max contains valid style coord"));
+        }
+
+        let min = TrackBreadth::from_gecko_style_coord(gecko_min).expect("gecko_min contains valid style coord");
+        let max = TrackBreadth::from_gecko_style_coord(gecko_max).expect("gecko_max contains valid style coord");
+        if min == max {
+            TrackSize::Breadth(max)
+        } else {
+            TrackSize::MinMax(min, max)
+        }
+    }
+
+    /// Save TrackSize to given gecko fields.
+    pub fn to_gecko_style_coords<T: CoordDataMut>(&self, gecko_min: &mut T, gecko_max: &mut T) {
+        use values::generics::grid::TrackSize;
+
+        match *self {
+            TrackSize::FitContent(ref lop) => {
+                // Gecko sets min value to None and max value to the actual value in fit-content
+                // https://dxr.mozilla.org/mozilla-central/rev/0eef1d5/layout/style/nsRuleNode.cpp#8221
+                gecko_min.set_value(CoordDataValue::None);
+                lop.to_gecko_style_coord(gecko_max);
+            },
+            TrackSize::Breadth(ref breadth) => {
+                // Set the value to both fields if there's one breadth value
+                // https://dxr.mozilla.org/mozilla-central/rev/0eef1d5/layout/style/nsRuleNode.cpp#8230
+                breadth.to_gecko_style_coord(gecko_min);
+                breadth.to_gecko_style_coord(gecko_max);
+            },
+            TrackSize::MinMax(ref min, ref max) => {
+                min.to_gecko_style_coord(gecko_min);
+                max.to_gecko_style_coord(gecko_max);
+            },
+        }
+    }
+}
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -1211,79 +1211,67 @@ fn static_assert() {
         }).unwrap_or(0);
     }
 
     pub fn copy_${value.name}_from(&mut self, other: &Self) {
         self.gecko.${value.gecko}.mHasSpan = other.gecko.${value.gecko}.mHasSpan;
         self.gecko.${value.gecko}.mInteger = other.gecko.${value.gecko}.mInteger;
         self.gecko.${value.gecko}.mLineName.assign(&*other.gecko.${value.gecko}.mLineName);
     }
+
+    pub fn clone_${value.name}(&self) -> longhands::${value.name}::computed_value::T {
+        use gecko_bindings::structs::{nsStyleGridLine_kMinLine, nsStyleGridLine_kMaxLine};
+        use string_cache::Atom;
+        use values::specified::Integer;
+
+        longhands::${value.name}::computed_value::T {
+            is_span: self.gecko.${value.gecko}.mHasSpan,
+            ident: {
+                let name = self.gecko.${value.gecko}.mLineName.to_string();
+                if name.len() == 0 {
+                    None
+                } else {
+                    Some(CustomIdent(Atom::from(name)))
+                }
+            },
+            line_num:
+                if self.gecko.${value.gecko}.mInteger == 0 {
+                    None
+                } else {
+                    debug_assert!(nsStyleGridLine_kMinLine <= self.gecko.${value.gecko}.mInteger &&
+                                  self.gecko.${value.gecko}.mInteger <= nsStyleGridLine_kMaxLine);
+                    Some(Integer::new(self.gecko.${value.gecko}.mInteger))
+                },
+        }
+    }
     % endfor
 
     % for kind in ["rows", "columns"]:
     pub fn set_grid_auto_${kind}(&mut self, v: longhands::grid_auto_${kind}::computed_value::T) {
-        use values::generics::grid::TrackSize;
-
-        match v {
-            TrackSize::FitContent(lop) => {
-                // Gecko sets min value to None and max value to the actual value in fit-content
-                // https://dxr.mozilla.org/mozilla-central/rev/0eef1d5/layout/style/nsRuleNode.cpp#8221
-                self.gecko.mGridAuto${kind.title()}Min.set_value(CoordDataValue::None);
-                lop.to_gecko_style_coord(&mut self.gecko.mGridAuto${kind.title()}Max);
-            },
-            TrackSize::Breadth(breadth) => {
-                // Set the value to both fields if there's one breadth value
-                // https://dxr.mozilla.org/mozilla-central/rev/0eef1d5/layout/style/nsRuleNode.cpp#8230
-                breadth.to_gecko_style_coord(&mut self.gecko.mGridAuto${kind.title()}Min);
-                breadth.to_gecko_style_coord(&mut self.gecko.mGridAuto${kind.title()}Max);
-            },
-            TrackSize::MinMax(min, max) => {
-                min.to_gecko_style_coord(&mut self.gecko.mGridAuto${kind.title()}Min);
-                max.to_gecko_style_coord(&mut self.gecko.mGridAuto${kind.title()}Max);
-            },
-        }
+        v.to_gecko_style_coords(&mut self.gecko.mGridAuto${kind.title()}Min,
+                                &mut self.gecko.mGridAuto${kind.title()}Max)
     }
 
     pub fn copy_grid_auto_${kind}_from(&mut self, other: &Self) {
         self.gecko.mGridAuto${kind.title()}Min.copy_from(&other.gecko.mGridAuto${kind.title()}Min);
         self.gecko.mGridAuto${kind.title()}Max.copy_from(&other.gecko.mGridAuto${kind.title()}Max);
     }
 
     pub fn clone_grid_auto_${kind}(&self) -> longhands::grid_auto_${kind}::computed_value::T {
-        use gecko_bindings::structs::root::nsStyleUnit::eStyleUnit_None;
-        use values::computed::length::LengthOrPercentage;
-        use values::generics::grid::{TrackSize, TrackBreadth};
-
-        let ref min_gecko = self.gecko.mGridAuto${kind.title()}Min;
-        let ref max_gecko = self.gecko.mGridAuto${kind.title()}Max;
-        if min_gecko.unit() == eStyleUnit_None {
-            debug_assert!(max_gecko.unit() != eStyleUnit_None);
-            return TrackSize::FitContent(LengthOrPercentage::from_gecko_style_coord(max_gecko)
-                       .expect("mGridAuto${kind.title()}Max contains style coord"));
-        }
-
-        let min = TrackBreadth::from_gecko_style_coord(min_gecko)
-                      .expect("mGridAuto${kind.title()}Min contains style coord");
-        let max = TrackBreadth::from_gecko_style_coord(max_gecko)
-                      .expect("mGridAuto${kind.title()}Max contains style coord");
-        if min == max {
-            TrackSize::Breadth(max)
-        } else {
-            TrackSize::MinMax(min, max)
-        }
+        ::values::generics::grid::TrackSize::from_gecko_style_coords(&self.gecko.mGridAuto${kind.title()}Min,
+                                                                     &self.gecko.mGridAuto${kind.title()}Max)
     }
 
     pub fn set_grid_template_${kind}(&mut self, v: longhands::grid_template_${kind}::computed_value::T) {
         <% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %>
-        use gecko::values::GeckoStyleCoordConvertible;
         use gecko_bindings::structs::{nsTArray, nsStyleGridLine_kMaxLine};
         use nsstring::{nsCString, nsStringRepr};
         use std::usize;
         use values::generics::grid::TrackListType::Auto;
-        use values::generics::grid::{RepeatCount, TrackSize};
+        use values::generics::grid::RepeatCount;
 
         #[inline]
         fn set_bitfield(bitfield: &mut u8, pos: u8, val: bool) {
             let mask = 1 << (pos - 1);
             *bitfield &= !mask;
             *bitfield |= (val as u8) << (pos - 1);
         }
 
@@ -1293,35 +1281,16 @@ fn static_assert() {
                 bindings::Gecko_ResizeTArrayForStrings(gecko_names, servo_names.len() as u32);
             }
 
             for (servo_name, gecko_name) in servo_names.iter().zip(gecko_names.iter_mut()) {
                 gecko_name.assign_utf8(&nsCString::from(&*servo_name));
             }
         }
 
-        fn set_track_size<G, T>(value: TrackSize<T>, gecko_min: &mut G, gecko_max: &mut G)
-            where G: CoordDataMut, T: GeckoStyleCoordConvertible
-        {
-            match value {
-                TrackSize::FitContent(lop) => {
-                    gecko_min.set_value(CoordDataValue::None);
-                    lop.to_gecko_style_coord(gecko_max);
-                },
-                TrackSize::Breadth(breadth) => {
-                    breadth.to_gecko_style_coord(gecko_min);
-                    breadth.to_gecko_style_coord(gecko_max);
-                },
-                TrackSize::MinMax(min, max) => {
-                    min.to_gecko_style_coord(gecko_min);
-                    max.to_gecko_style_coord(gecko_max);
-                },
-            }
-        }
-
         // Set defaults
         ${self_grid}.mRepeatAutoIndex = -1;
         set_bitfield(&mut ${self_grid}._bitfield_1, 1, false);   // mIsAutoFill
         set_bitfield(&mut ${self_grid}._bitfield_1, 2, false);   // mIsSubgrid
         // FIXME: mIsSubgrid is false only for <none>, but we don't support subgrid name lists at the moment.
 
         match v {
             Either::First(track) => {
@@ -1365,23 +1334,23 @@ fn static_assert() {
                 let mut values_iter = track.values.into_iter();
                 let min_max_iter = ${self_grid}.mMinTrackSizingFunctions.iter_mut()
                                                .zip(${self_grid}.mMaxTrackSizingFunctions.iter_mut());
 
                 for (i, (gecko_min, gecko_max)) in min_max_iter.enumerate().take(max_lines) {
                     let name_list = line_names.next().expect("expected line-names");
                     set_line_names(&name_list, &mut ${self_grid}.mLineNameLists[i]);
                     if i == auto_idx {
-                        set_track_size(auto_track_size.take().expect("expected <track-size> for <auto-track-repeat>"),
-                                       gecko_min, gecko_max);
+                        let track_size = auto_track_size.take().expect("expected <track-size> for <auto-track-repeat>");
+                        track_size.to_gecko_style_coords(gecko_min, gecko_max);
                         continue
                     }
 
                     let track_size = values_iter.next().expect("expected <track-size> value");
-                    set_track_size(track_size, gecko_min, gecko_max);
+                    track_size.to_gecko_style_coords(gecko_min, gecko_max);
                 }
 
                 let final_names = line_names.next().unwrap();
                 set_line_names(&final_names, ${self_grid}.mLineNameLists.last_mut().unwrap());
             },
             Either::Second(_none) => {
                 unsafe {
                     bindings::Gecko_SetStyleGridTemplateArrayLengths(&mut ${self_grid}, 0);
--- a/servo/components/style/properties/longhand/position.mako.rs
+++ b/servo/components/style/properties/longhand/position.mako.rs
@@ -255,17 +255,17 @@ macro_rules! impl_align_conversions {
                               spec="https://drafts.csswg.org/css-grid/#propdef-grid-%s-gap" % kind,
                               animation_value_type="ComputedValue",
                               products="gecko")}
 
     % for range in ["start", "end"]:
         ${helpers.predefined_type("grid-%s-%s" % (kind, range),
                                   "GridLine",
                                   "Default::default()",
-                                  animation_value_type="none",
+                                  animation_value_type="discrete",
                                   spec="https://drafts.csswg.org/css-grid/#propdef-grid-%s-%s" % (kind, range),
                                   products="gecko",
                                   boxed=True)}
     % endfor
 
     // NOTE: According to the spec, this should handle multiple values of `<track-size>`,
     // but gecko supports only a single value
     ${helpers.predefined_type("grid-auto-%ss" % kind,