diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index 7a349db0ff3..e219bcc69fc 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -11,6 +11,7 @@ use cssparser::{DeclarationListParser, parse_important}; use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter}; use error_reporting::ParseErrorReporter; use parser::{PARSING_MODE_DEFAULT, ParsingMode, ParserContext, log_css_error}; +use properties::animated_properties::AnimationValue; use shared_lock::Locked; use std::fmt; use std::slice::Iter; @@ -18,6 +19,7 @@ use style_traits::ToCss; use stylesheets::{CssRuleType, Origin, UrlExtraData}; use stylesheets::{MallocSizeOf, MallocSizeOfFn}; use super::*; +use values::computed::Context; #[cfg(feature = "gecko")] use properties::animated_properties::AnimationValueMap; /// The animation rules. @@ -102,6 +104,55 @@ impl<'a> Iterator for PropertyDeclarationIterator<'a> { } } +/// Iterator for AnimationValue to be generated from PropertyDeclarationBlock. +pub struct AnimationValueIterator<'a, 'cx, 'cx_a:'cx> { + iter: Iter<'a, (PropertyDeclaration, Importance)>, + context: &'cx mut Context<'cx_a>, + default_values: &'a Arc, +} + +impl<'a, 'cx, 'cx_a:'cx> AnimationValueIterator<'a, 'cx, 'cx_a> { + fn new(declarations: &'a PropertyDeclarationBlock, + context: &'cx mut Context<'cx_a>, + default_values: &'a Arc) -> AnimationValueIterator<'a, 'cx, 'cx_a> { + AnimationValueIterator { + iter: declarations.declarations().iter(), + context: context, + default_values: default_values, + } + } +} + +impl<'a, 'cx, 'cx_a:'cx> Iterator for AnimationValueIterator<'a, 'cx, 'cx_a> { + type Item = (TransitionProperty, AnimationValue); + #[inline] + fn next(&mut self) -> Option { + use properties::Importance; + + loop { + let next = self.iter.next(); + match next { + Some(&(ref decl, importance)) => { + if importance == Importance::Normal { + let property = TransitionProperty::from_declaration(decl); + let animation = AnimationValue::from_declaration(decl, &mut self.context, + self.default_values); + debug_assert!(property.is_none() == animation.is_none(), + "The failure condition of TransitionProperty::from_declaration \ + and AnimationValue::from_declaration should be the same"); + // Skip the property if either ::from_declaration fails. + match (property, animation) { + (Some(p), Some(a)) => return Some((p, a)), + (_, _) => {}, + } + } + }, + None => return None, + } + } + } +} + impl fmt::Debug for PropertyDeclarationBlock { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.declarations.fmt(f) @@ -148,6 +199,14 @@ impl PropertyDeclarationBlock { } } + /// Return an iterator of (TransitionProperty, AnimationValue). + pub fn to_animation_value_iter<'a, 'cx, 'cx_a:'cx>(&'a self, + context: &'cx mut Context<'cx_a>, + default_values: &'a Arc) + -> AnimationValueIterator<'a, 'cx, 'cx_a> { + AnimationValueIterator::new(self, context, default_values) + } + /// Returns whether this block contains any declaration with `!important`. /// /// This is based on the `important_count` counter, diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index fa08f50e4db..09badb03435 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -2581,7 +2581,6 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(keyframes: RawGeckoKeyframeLis { use std::mem; use style::properties::LonghandIdSet; - use style::properties::declaration_block::Importance; let data = PerDocumentStyleData::from_ffi(raw_data).borrow(); let metrics = get_metrics_provider_for_product(); @@ -2616,28 +2615,7 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(keyframes: RawGeckoKeyframeLis let declarations = Locked::::as_arc(&declarations); let guard = declarations.read_with(&guard); - let anim_iter = guard.declarations() - .iter() - .filter_map(|&(ref decl, imp)| { - if imp == Importance::Normal { - let property = TransitionProperty::from_declaration(decl); - let animation = AnimationValue::from_declaration(decl, &mut context, - default_values); - debug_assert!(property.is_none() == animation.is_none(), - "The failure condition of TransitionProperty::from_declaration \ - and AnimationValue::from_declaration should be the same"); - // Skip the property if either ::from_declaration fails. - if property.is_none() || animation.is_none() { - None - } else { - Some((property.unwrap(), animation.unwrap())) - } - } else { - None - } - }); - - for anim in anim_iter { + for anim in guard.to_animation_value_iter(&mut context, &default_values) { if !seen.has_transition_property_bit(&anim.0) { // This is safe since we immediately write to the uninitialized values. unsafe { animation_values.set_len((property_index + 1) as u32) };