Bug 1328787 - Part 10: Set Keyframe.mPropertyValues for the case where keyframe is not specified. r?heycam draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Fri, 27 Jan 2017 10:16:54 +0900
changeset 467025 d6226a0f5be2344ced0a44c4e85d31d4020b291e
parent 467024 250c2b40e250e9321f4e792425c3bfcb9d8fe398
child 467026 c2be81b19ec461eb66706406b980915b6f635cf6
push id43089
push userhikezoe@mozilla.com
push dateFri, 27 Jan 2017 01:33:18 +0000
reviewersheycam
bugs1328787
milestone54.0a1
Bug 1328787 - Part 10: Set Keyframe.mPropertyValues for the case where keyframe is not specified. r?heycam MozReview-Commit-ID: KozUNqxmjK9
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/helpers/animated_properties.mako.rs
servo/ports/geckolib/glue.rs
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -46,21 +46,24 @@ use gecko_bindings::structs::nsStyleVari
 use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
 use gecko_bindings::sugar::ownership::HasArcFFI;
 use gecko::values::convert_nscolor_to_rgba;
 use gecko::values::convert_rgba_to_nscolor;
 use gecko::values::GeckoStyleCoordConvertible;
 use gecko::values::round_border_to_device_pixels;
 use logical_geometry::WritingMode;
 use properties::longhands;
+use properties::{DeclaredValue, Importance, LonghandId};
+use properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyDeclarationId};
 use std::fmt::{self, Debug};
 use std::mem::{transmute, zeroed};
 use std::ptr;
 use std::sync::Arc;
 use std::cmp;
+use values::computed::ToComputedValue;
 
 pub mod style_structs {
     % for style_struct in data.style_structs:
     pub use super::${style_struct.gecko_struct_name} as ${style_struct.name};
     % endfor
 }
 
 #[derive(Clone, Debug)]
@@ -149,16 +152,38 @@ impl ComputedValues {
 
     pub fn root_font_size(&self) -> Au { self.root_font_size }
     pub fn set_root_font_size(&mut self, s: Au) { self.root_font_size = s; }
     pub fn set_writing_mode(&mut self, mode: WritingMode) { self.writing_mode = mode; }
 
     // FIXME(bholley): Implement this properly.
     #[inline]
     pub fn is_multicol(&self) -> bool { false }
+
+    pub fn to_declaration_block(&self, property: PropertyDeclarationId) -> PropertyDeclarationBlock {
+        match property {
+            % for prop in data.longhands:
+                % if prop.animatable:
+                    PropertyDeclarationId::Longhand(LonghandId::${prop.camel_case}) => {
+                        PropertyDeclarationBlock {
+                            declarations: vec![
+                                (PropertyDeclaration::${prop.camel_case}(DeclaredValue::Value(
+                                    longhands::${prop.ident}::SpecifiedValue::from_computed_value(
+                                      &self.get_${prop.style_struct.ident.strip("_")}().clone_${prop.ident}()))),
+                                 Importance::Normal)
+                            ],
+                            important_count: 0
+                        }
+                    },
+                % endif
+            % endfor
+            PropertyDeclarationId::Custom(_name) => unimplemented!(),
+            _ => unimplemented!()
+        }
+    }
 }
 
 <%def name="declare_style_struct(style_struct)">
 pub struct ${style_struct.gecko_struct_name} {
     gecko: ${style_struct.gecko_ffi_name},
 }
 </%def>
 
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -17,16 +17,17 @@ use properties::longhands::font_weight::
 use properties::longhands::line_height::computed_value::T as LineHeight;
 use properties::longhands::text_shadow::computed_value::T as TextShadowList;
 use properties::longhands::text_shadow::computed_value::TextShadow;
 use properties::longhands::box_shadow::computed_value::T as BoxShadowList;
 use properties::longhands::box_shadow::single_value::computed_value::T as BoxShadow;
 use properties::longhands::vertical_align::computed_value::T as VerticalAlign;
 use properties::longhands::visibility::computed_value::T as Visibility;
 use properties::longhands::z_index::computed_value::T as ZIndex;
+#[cfg(feature = "gecko")] use properties::{PropertyDeclarationId, LonghandId};
 use std::cmp;
 use std::fmt;
 use style_traits::ToCss;
 use super::ComputedValues;
 use values::Either;
 use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
 use values::computed::{BorderRadiusSize, LengthOrNone};
 use values::computed::{CalcLengthOrPercentage, Context, LengthOrPercentage};
@@ -116,16 +117,33 @@ impl From<TransitionProperty> for nsCSSP
                         => ${helpers.to_nscsspropertyid(prop.ident)},
                 % endif
             % endfor
             TransitionProperty::All => nsCSSPropertyID::eCSSPropertyExtra_all_properties,
         }
     }
 }
 
+/// Convert to PropertyDeclarationId.
+#[cfg(feature = "gecko")]
+#[allow(non_upper_case_globals)]
+impl<'a> From<TransitionProperty> for PropertyDeclarationId<'a> {
+    fn from(transition_property: TransitionProperty) -> PropertyDeclarationId<'a> {
+        match transition_property {
+            % for prop in data.longhands:
+                % if prop.animatable:
+                    TransitionProperty::${prop.camel_case}
+                        => PropertyDeclarationId::Longhand(LonghandId::${prop.camel_case}),
+                % endif
+            % endfor
+            TransitionProperty::All => panic!(),
+        }
+    }
+}
+
 /// An animated property interpolation between two computed values for that
 /// property.
 #[derive(Clone, Debug, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub enum AnimatedProperty {
     % for prop in data.longhands:
         % if prop.animatable:
             /// ${prop.name}
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -1142,21 +1142,22 @@ pub extern "C" fn Servo_AssertTreeIsClea
 
     assert_subtree_is_clean(root);
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_StyleSet_FillKeyframesForName(raw_data: RawServoStyleSetBorrowed,
                                                       name: *const nsACString,
                                                       timing_function: *const nsTimingFunction,
-                                                      _style: ServoComputedValuesBorrowed,
+                                                      style: ServoComputedValuesBorrowed,
                                                       keyframes: RawGeckoKeyframeListBorrowedMut) -> bool {
     let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
     let name = unsafe { Atom::from(name.as_ref().unwrap().as_str_unchecked()) };
     let style_timing_function = unsafe { timing_function.as_ref().unwrap() };
+    let style = ComputedValues::as_arc(&style);
 
     if let Some(ref animation) = data.stylist.animations().get(&name) {
        for step in &animation.steps {
           // Override timing_function if the keyframe has animation-timing-function.
           let timing_function = if let Some(val) = step.get_animation_timing_function() {
               val.into()
           } else {
               *style_timing_function
@@ -1165,17 +1166,25 @@ pub extern "C" fn Servo_StyleSet_FillKey
           let keyframe = unsafe {
                 Gecko_AnimationAppendKeyframe(keyframes,
                                               step.start_percentage.0 as f32,
                                               &timing_function)
           };
 
           match step.value {
               KeyframesStepValue::ComputedValues => {
-                  unimplemented!();
+                  for (index, property) in animation.properties_changed.iter().enumerate() {
+                      let block = style.to_declaration_block(property.clone().into());
+                      unsafe {
+                          (*keyframe).mPropertyValues.set_len((index + 1) as u32);
+                          (*keyframe).mPropertyValues[index].mProperty = property.clone().into();
+                          (*keyframe).mPropertyValues[index].mServoDeclarationBlock.set_arc_leaky(
+                              Arc::new(RwLock::new(block)));
+                      }
+                  }
               },
               KeyframesStepValue::Declarations { ref block } => {
                   let guard = block.read();
                   // Filter out non-animatable properties.
                   let animatable =
                       guard.declarations
                            .iter()
                            .filter(|&&(ref declaration, _)| {