From a80725c91b972577fcb888a75ab225305f3098e8 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Mon, 23 Jan 2017 13:14:24 +0900 Subject: [PATCH] Allow empty keyframe and keyframes with non-animatable properties. We need to create CSS animations that have empty keyframe or keyframes which have only invalid properties or non-animatable properties to fire animation events for such animations. --- components/style/keyframes.rs | 43 ++++++++++++++++++----------------- components/style/stylist.rs | 14 ++++-------- tests/unit/style/keyframes.rs | 40 ++++++++++++++++++++++++++++++++ tests/unit/style/lib.rs | 1 + 4 files changed, 67 insertions(+), 31 deletions(-) create mode 100644 tests/unit/style/keyframes.rs diff --git a/components/style/keyframes.rs b/components/style/keyframes.rs index 0eb0662c1281..eca73f1f848f 100644 --- a/components/style/keyframes.rs +++ b/components/style/keyframes.rs @@ -266,50 +266,51 @@ fn get_animated_properties(keyframe: &Keyframe) -> Vec { impl KeyframesAnimation { /// Create a keyframes animation from a given list of keyframes. /// - /// This will return `None` if the list of keyframes is empty, or there are - /// no animated properties obtained from the keyframes. + /// This will return a keyframe animation with empty steps and + /// properties_changed if the list of keyframes is empty, or there are no + // animated properties obtained from the keyframes. /// /// Otherwise, this will compute and sort the steps used for the animation, /// and return the animation object. - pub fn from_keyframes(keyframes: &[Arc>]) -> Option { + pub fn from_keyframes(keyframes: &[Arc>]) -> Self { + let mut result = KeyframesAnimation { + steps: vec![], + properties_changed: vec![], + }; + if keyframes.is_empty() { - return None; + return result; } - let animated_properties = get_animated_properties(&keyframes[0].read()); - if animated_properties.is_empty() { - return None; + result.properties_changed = get_animated_properties(&keyframes[0].read()); + if result.properties_changed.is_empty() { + return result; } - let mut steps = vec![]; - for keyframe in keyframes { let keyframe = keyframe.read(); for percentage in keyframe.selector.0.iter() { - steps.push(KeyframesStep::new(*percentage, KeyframesStepValue::Declarations { + result.steps.push(KeyframesStep::new(*percentage, KeyframesStepValue::Declarations { block: keyframe.block.clone(), })); } } // Sort by the start percentage, so we can easily find a frame. - steps.sort_by_key(|step| step.start_percentage); + result.steps.sort_by_key(|step| step.start_percentage); // Prepend autogenerated keyframes if appropriate. - if steps[0].start_percentage.0 != 0. { - steps.insert(0, KeyframesStep::new(KeyframePercentage::new(0.), - KeyframesStepValue::ComputedValues)); + if result.steps[0].start_percentage.0 != 0. { + result.steps.insert(0, KeyframesStep::new(KeyframePercentage::new(0.), + KeyframesStepValue::ComputedValues)); } - if steps.last().unwrap().start_percentage.0 != 1. { - steps.push(KeyframesStep::new(KeyframePercentage::new(1.), - KeyframesStepValue::ComputedValues)); + if result.steps.last().unwrap().start_percentage.0 != 1. { + result.steps.push(KeyframesStep::new(KeyframePercentage::new(1.), + KeyframesStepValue::ComputedValues)); } - Some(KeyframesAnimation { - steps: steps, - properties_changed: animated_properties, - }) + result } } diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 3d81e3897bc2..313d2dae76ea 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -182,6 +182,7 @@ impl Stylist { self.precomputed_pseudo_element_decls = Default::default(); self.rules_source_order = 0; self.state_deps.clear(); + self.animations.clear(); self.sibling_affecting_selectors.clear(); self.non_common_style_affecting_attributes_selectors.clear(); @@ -274,16 +275,9 @@ impl Stylist { CssRule::Keyframes(ref keyframes_rule) => { let keyframes_rule = keyframes_rule.read(); debug!("Found valid keyframes rule: {:?}", *keyframes_rule); - if let Some(animation) = KeyframesAnimation::from_keyframes(&keyframes_rule.keyframes) { - debug!("Found valid keyframe animation: {:?}", animation); - self.animations.insert(keyframes_rule.name.clone(), - animation); - } else { - // If there's a valid keyframes rule, even if it doesn't - // produce an animation, should shadow other animations - // with the same name. - self.animations.remove(&keyframes_rule.name); - } + let animation = KeyframesAnimation::from_keyframes(&keyframes_rule.keyframes); + debug!("Found valid keyframe animation: {:?}", animation); + self.animations.insert(keyframes_rule.name.clone(), animation); } // We don't care about any other rule. _ => {} diff --git a/tests/unit/style/keyframes.rs b/tests/unit/style/keyframes.rs new file mode 100644 index 000000000000..14c79bfa1bff --- /dev/null +++ b/tests/unit/style/keyframes.rs @@ -0,0 +1,40 @@ +/* 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/. */ + +use parking_lot::RwLock; +use std::sync::Arc; +use style::keyframes::{Keyframe, KeyframesAnimation, KeyframePercentage, KeyframeSelector}; +use style::properties::PropertyDeclarationBlock; + +#[test] +fn test_empty_keyframe() { + let keyframes = vec![]; + let animation = KeyframesAnimation::from_keyframes(&keyframes); + let expected = KeyframesAnimation { + steps: vec![], + properties_changed: vec![], + }; + + assert_eq!(format!("{:#?}", animation), format!("{:#?}", expected)); +} + +#[test] +fn test_no_property_in_keyframe() { + let keyframes = vec![ + Arc::new(RwLock::new(Keyframe { + selector: KeyframeSelector::new_for_unit_testing(vec![KeyframePercentage::new(1.)]), + block: Arc::new(RwLock::new(PropertyDeclarationBlock { + declarations: vec![], + important_count: 0, + })) + })), + ]; + let animation = KeyframesAnimation::from_keyframes(&keyframes); + let expected = KeyframesAnimation { + steps: vec![], + properties_changed: vec![], + }; + + assert_eq!(format!("{:#?}", animation), format!("{:#?}", expected)); +} diff --git a/tests/unit/style/lib.rs b/tests/unit/style/lib.rs index d15377f502e5..26d242b26b86 100644 --- a/tests/unit/style/lib.rs +++ b/tests/unit/style/lib.rs @@ -25,6 +25,7 @@ extern crate test; mod animated_properties; mod attr; mod cache; +mod keyframes; mod logical_geometry; mod media_queries; mod owning_handle;