mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Get all animated properties in *all* keyframes.
@keyframes anim { from { transform: none; } to { opacity: 0; transform: none; } } In above case, we have to add opacity property and value in the 'from' keyframe.
This commit is contained in:
parent
279a50fb74
commit
501edfdbdb
2 changed files with 193 additions and 13 deletions
|
@ -15,6 +15,7 @@ use properties::{PropertyDeclarationId, LonghandId, DeclaredValue};
|
|||
use properties::PropertyDeclarationParseResult;
|
||||
use properties::animated_properties::TransitionProperty;
|
||||
use properties::longhands::transition_timing_function::single_value::SpecifiedValue as SpecifiedTimingFunction;
|
||||
use properties::property_bit_field::PropertyBitField;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use style_traits::ToCss;
|
||||
|
@ -244,21 +245,23 @@ pub struct KeyframesAnimation {
|
|||
pub properties_changed: Vec<TransitionProperty>,
|
||||
}
|
||||
|
||||
/// Get all the animated properties in a keyframes animation. Note that it's not
|
||||
/// defined what happens when a property is not on a keyframe, so we only peek
|
||||
/// the props of the first one.
|
||||
///
|
||||
/// In practice, browsers seem to try to do their best job at it, so we might
|
||||
/// want to go through all the actual keyframes and deduplicate properties.
|
||||
fn get_animated_properties(keyframe: &Keyframe) -> Vec<TransitionProperty> {
|
||||
/// Get all the animated properties in a keyframes animation.
|
||||
fn get_animated_properties(keyframes: &[Arc<RwLock<Keyframe>>]) -> Vec<TransitionProperty> {
|
||||
let mut ret = vec![];
|
||||
let mut seen = PropertyBitField::new();
|
||||
// NB: declarations are already deduplicated, so we don't have to check for
|
||||
// it here.
|
||||
for keyframe in keyframes {
|
||||
let keyframe = keyframe.read();
|
||||
for &(ref declaration, importance) in keyframe.block.read().declarations.iter() {
|
||||
assert!(!importance.important());
|
||||
|
||||
if let Some(property) = TransitionProperty::from_declaration(declaration) {
|
||||
if !seen.has_transition_property_bit(&property) {
|
||||
ret.push(property);
|
||||
seen.set_transition_property_bit(&property);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,7 +287,7 @@ impl KeyframesAnimation {
|
|||
return result;
|
||||
}
|
||||
|
||||
result.properties_changed = get_animated_properties(&keyframes[0].read());
|
||||
result.properties_changed = get_animated_properties(keyframes);
|
||||
if result.properties_changed.is_empty() {
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
use parking_lot::RwLock;
|
||||
use std::sync::Arc;
|
||||
use style::keyframes::{Keyframe, KeyframesAnimation, KeyframePercentage, KeyframeSelector};
|
||||
use style::properties::PropertyDeclarationBlock;
|
||||
use style::keyframes::{KeyframesStep, KeyframesStepValue};
|
||||
use style::properties::{DeclaredValue, PropertyDeclaration, PropertyDeclarationBlock, Importance};
|
||||
use style::properties::animated_properties::TransitionProperty;
|
||||
use style::values::specified::{LengthOrPercentageOrAuto, NoCalcLength};
|
||||
|
||||
#[test]
|
||||
fn test_empty_keyframe() {
|
||||
|
@ -38,3 +41,177 @@ fn test_no_property_in_keyframe() {
|
|||
|
||||
assert_eq!(format!("{:#?}", animation), format!("{:#?}", expected));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_missing_property_in_initial_keyframe() {
|
||||
let declarations_on_initial_keyframe =
|
||||
Arc::new(RwLock::new(PropertyDeclarationBlock {
|
||||
declarations: vec![
|
||||
(PropertyDeclaration::Width(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
],
|
||||
important_count: 0,
|
||||
}));
|
||||
|
||||
let declarations_on_final_keyframe =
|
||||
Arc::new(RwLock::new(PropertyDeclarationBlock {
|
||||
declarations: vec![
|
||||
(PropertyDeclaration::Width(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
|
||||
(PropertyDeclaration::Height(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
],
|
||||
important_count: 0,
|
||||
}));
|
||||
|
||||
let keyframes = vec![
|
||||
Arc::new(RwLock::new(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(vec![KeyframePercentage::new(0.)]),
|
||||
block: declarations_on_initial_keyframe.clone(),
|
||||
})),
|
||||
|
||||
Arc::new(RwLock::new(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(vec![KeyframePercentage::new(1.)]),
|
||||
block: declarations_on_final_keyframe.clone(),
|
||||
})),
|
||||
];
|
||||
let animation = KeyframesAnimation::from_keyframes(&keyframes);
|
||||
let expected = KeyframesAnimation {
|
||||
steps: vec![
|
||||
KeyframesStep {
|
||||
start_percentage: KeyframePercentage(0.),
|
||||
value: KeyframesStepValue::Declarations { block: declarations_on_initial_keyframe },
|
||||
declared_timing_function: false,
|
||||
},
|
||||
KeyframesStep {
|
||||
start_percentage: KeyframePercentage(1.),
|
||||
value: KeyframesStepValue::Declarations { block: declarations_on_final_keyframe },
|
||||
declared_timing_function: false,
|
||||
},
|
||||
],
|
||||
properties_changed: vec![TransitionProperty::Width, TransitionProperty::Height],
|
||||
};
|
||||
|
||||
assert_eq!(format!("{:#?}", animation), format!("{:#?}", expected));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_missing_property_in_final_keyframe() {
|
||||
let declarations_on_initial_keyframe =
|
||||
Arc::new(RwLock::new(PropertyDeclarationBlock {
|
||||
declarations: vec![
|
||||
(PropertyDeclaration::Width(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
|
||||
(PropertyDeclaration::Height(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
],
|
||||
important_count: 0,
|
||||
}));
|
||||
|
||||
let declarations_on_final_keyframe =
|
||||
Arc::new(RwLock::new(PropertyDeclarationBlock {
|
||||
declarations: vec![
|
||||
(PropertyDeclaration::Height(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
],
|
||||
important_count: 0,
|
||||
}));
|
||||
|
||||
let keyframes = vec![
|
||||
Arc::new(RwLock::new(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(vec![KeyframePercentage::new(0.)]),
|
||||
block: declarations_on_initial_keyframe.clone(),
|
||||
})),
|
||||
|
||||
Arc::new(RwLock::new(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(vec![KeyframePercentage::new(1.)]),
|
||||
block: declarations_on_final_keyframe.clone(),
|
||||
})),
|
||||
];
|
||||
let animation = KeyframesAnimation::from_keyframes(&keyframes);
|
||||
let expected = KeyframesAnimation {
|
||||
steps: vec![
|
||||
KeyframesStep {
|
||||
start_percentage: KeyframePercentage(0.),
|
||||
value: KeyframesStepValue::Declarations { block: declarations_on_initial_keyframe },
|
||||
declared_timing_function: false,
|
||||
},
|
||||
KeyframesStep {
|
||||
start_percentage: KeyframePercentage(1.),
|
||||
value: KeyframesStepValue::Declarations { block: declarations_on_final_keyframe },
|
||||
declared_timing_function: false,
|
||||
},
|
||||
],
|
||||
properties_changed: vec![TransitionProperty::Width, TransitionProperty::Height],
|
||||
};
|
||||
|
||||
assert_eq!(format!("{:#?}", animation), format!("{:#?}", expected));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_missing_keyframe_in_both_of_initial_and_final_keyframe() {
|
||||
let declarations =
|
||||
Arc::new(RwLock::new(PropertyDeclarationBlock {
|
||||
declarations: vec![
|
||||
(PropertyDeclaration::Width(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
|
||||
(PropertyDeclaration::Height(
|
||||
DeclaredValue::Value(LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(20f32)))),
|
||||
Importance::Normal),
|
||||
],
|
||||
important_count: 0,
|
||||
}));
|
||||
|
||||
let keyframes = vec![
|
||||
Arc::new(RwLock::new(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(vec![KeyframePercentage::new(0.)]),
|
||||
block: Arc::new(RwLock::new(PropertyDeclarationBlock {
|
||||
declarations: vec![],
|
||||
important_count: 0,
|
||||
}))
|
||||
})),
|
||||
Arc::new(RwLock::new(Keyframe {
|
||||
selector: KeyframeSelector::new_for_unit_testing(vec![KeyframePercentage::new(0.5)]),
|
||||
block: declarations.clone(),
|
||||
})),
|
||||
];
|
||||
let animation = KeyframesAnimation::from_keyframes(&keyframes);
|
||||
let expected = KeyframesAnimation {
|
||||
steps: vec![
|
||||
KeyframesStep {
|
||||
start_percentage: KeyframePercentage(0.),
|
||||
value: KeyframesStepValue::Declarations {
|
||||
block: Arc::new(RwLock::new(PropertyDeclarationBlock {
|
||||
// XXX: Should we use ComputedValues in this case?
|
||||
declarations: vec![],
|
||||
important_count: 0,
|
||||
}))
|
||||
},
|
||||
declared_timing_function: false,
|
||||
},
|
||||
KeyframesStep {
|
||||
start_percentage: KeyframePercentage(0.5),
|
||||
value: KeyframesStepValue::Declarations { block: declarations },
|
||||
declared_timing_function: false,
|
||||
},
|
||||
KeyframesStep {
|
||||
start_percentage: KeyframePercentage(1.),
|
||||
value: KeyframesStepValue::ComputedValues,
|
||||
declared_timing_function: false,
|
||||
}
|
||||
],
|
||||
properties_changed: vec![TransitionProperty::Width, TransitionProperty::Height],
|
||||
};
|
||||
|
||||
assert_eq!(format!("{:#?}", animation), format!("{:#?}", expected));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue