mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
style: Support animation-composition in keyframe at rules
So we can specify the keyframe-specific composite operation. However, these is a spec issue about the default composite for CSS Animations: https://github.com/w3c/csswg-drafts/issues/7476. I choose to use auto as the default composite for missing keyframes to match the definition in web-animations-1 because I think this makes more sense: > If the keyframe-specific composite operation for a keyframe is not set, the > composite operation specified for the keyframe effect as a whole is used for > values specified in that keyframe. Differential Revision: https://phabricator.services.mozilla.com/D150808
This commit is contained in:
parent
06f81aea07
commit
e53f4ee4c7
2 changed files with 87 additions and 36 deletions
|
@ -287,7 +287,6 @@ ${helpers.single_keyword(
|
|||
gecko_inexhaustive=True,
|
||||
gecko_pref="layout.css.animation-composition.enabled",
|
||||
spec="https://drafts.csswg.org/css-animations-2/#animation-composition",
|
||||
rule_types_allowed=DEFAULT_RULES_EXCEPT_KEYFRAME,
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
use crate::error_reporting::ContextualParseError;
|
||||
use crate::parser::ParserContext;
|
||||
use crate::properties::longhands::animation_composition::single_value::SpecifiedValue as SpecifiedComposition;
|
||||
use crate::properties::longhands::transition_timing_function::single_value::SpecifiedValue as SpecifiedTimingFunction;
|
||||
use crate::properties::LonghandIdSet;
|
||||
use crate::properties::{Importance, PropertyDeclaration};
|
||||
|
@ -279,40 +280,81 @@ pub struct KeyframesStep {
|
|||
/// Declarations that will determine the final style during the step, or
|
||||
/// `ComputedValues` if this is an autogenerated step.
|
||||
pub value: KeyframesStepValue,
|
||||
/// Wether a animation-timing-function declaration exists in the list of
|
||||
/// Whether an animation-timing-function declaration exists in the list of
|
||||
/// declarations.
|
||||
///
|
||||
/// This is used to know when to override the keyframe animation style.
|
||||
pub declared_timing_function: bool,
|
||||
/// Whether an animation-composition declaration exists in the list of
|
||||
/// declarations.
|
||||
///
|
||||
/// This is used to know when to override the keyframe animation style.
|
||||
pub declared_composition: bool,
|
||||
}
|
||||
|
||||
impl KeyframesStep {
|
||||
#[inline]
|
||||
fn new(
|
||||
percentage: KeyframePercentage,
|
||||
start_percentage: KeyframePercentage,
|
||||
value: KeyframesStepValue,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
) -> Self {
|
||||
let declared_timing_function = match value {
|
||||
KeyframesStepValue::Declarations { ref block } => block
|
||||
.read_with(guard)
|
||||
.declarations()
|
||||
.iter()
|
||||
.any(|prop_decl| match *prop_decl {
|
||||
PropertyDeclaration::AnimationTimingFunction(..) => true,
|
||||
_ => false,
|
||||
}),
|
||||
_ => false,
|
||||
};
|
||||
let mut declared_timing_function = false;
|
||||
let mut declared_composition = false;
|
||||
if let KeyframesStepValue::Declarations { ref block } = value {
|
||||
for prop_decl in block.read_with(guard).declarations().iter() {
|
||||
match *prop_decl {
|
||||
PropertyDeclaration::AnimationTimingFunction(..) => {
|
||||
declared_timing_function = true;
|
||||
},
|
||||
PropertyDeclaration::AnimationComposition(..) => {
|
||||
declared_composition = true;
|
||||
},
|
||||
_ => continue,
|
||||
}
|
||||
// Don't need to continue the loop if both are found.
|
||||
if declared_timing_function && declared_composition {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KeyframesStep {
|
||||
start_percentage: percentage,
|
||||
value: value,
|
||||
declared_timing_function: declared_timing_function,
|
||||
start_percentage,
|
||||
value,
|
||||
declared_timing_function,
|
||||
declared_composition,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return specified TransitionTimingFunction if this KeyframesSteps has 'animation-timing-function'.
|
||||
/// Return specified PropertyDeclaration.
|
||||
#[inline]
|
||||
fn get_declared_property<'a>(
|
||||
&'a self,
|
||||
guard: &'a SharedRwLockReadGuard,
|
||||
property: LonghandId,
|
||||
) -> Option<&'a PropertyDeclaration> {
|
||||
match self.value {
|
||||
KeyframesStepValue::Declarations { ref block } => {
|
||||
let guard = block.read_with(guard);
|
||||
let (declaration, _) = guard
|
||||
.get(PropertyDeclarationId::Longhand(property))
|
||||
.unwrap();
|
||||
match *declaration {
|
||||
PropertyDeclaration::CSSWideKeyword(..) => None,
|
||||
// FIXME: Bug 1710735: Support css variable in @keyframes rule.
|
||||
PropertyDeclaration::WithVariables(..) => None,
|
||||
_ => Some(declaration),
|
||||
}
|
||||
},
|
||||
KeyframesStepValue::ComputedValues => {
|
||||
panic!("Shouldn't happen to set this property in missing keyframes")
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Return specified TransitionTimingFunction if this KeyframesSteps has
|
||||
/// 'animation-timing-function'.
|
||||
pub fn get_animation_timing_function(
|
||||
&self,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
|
@ -320,28 +362,38 @@ impl KeyframesStep {
|
|||
if !self.declared_timing_function {
|
||||
return None;
|
||||
}
|
||||
match self.value {
|
||||
KeyframesStepValue::Declarations { ref block } => {
|
||||
let guard = block.read_with(guard);
|
||||
let (declaration, _) = guard
|
||||
.get(PropertyDeclarationId::Longhand(
|
||||
LonghandId::AnimationTimingFunction,
|
||||
))
|
||||
.unwrap();
|
||||
match *declaration {
|
||||
|
||||
self.get_declared_property(guard, LonghandId::AnimationTimingFunction)
|
||||
.map(|decl| {
|
||||
match *decl {
|
||||
PropertyDeclaration::AnimationTimingFunction(ref value) => {
|
||||
// Use the first value.
|
||||
Some(value.0[0].clone())
|
||||
// Use the first value
|
||||
value.0[0].clone()
|
||||
},
|
||||
PropertyDeclaration::CSSWideKeyword(..) => None,
|
||||
PropertyDeclaration::WithVariables(..) => None,
|
||||
_ => panic!(),
|
||||
_ => unreachable!("Unexpected PropertyDeclaration"),
|
||||
}
|
||||
},
|
||||
KeyframesStepValue::ComputedValues => {
|
||||
panic!("Shouldn't happen to set animation-timing-function in missing keyframes")
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/// Return CompositeOperation if this KeyframesSteps has 'animation-composition'.
|
||||
pub fn get_animation_composition(
|
||||
&self,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
) -> Option<SpecifiedComposition> {
|
||||
if !self.declared_composition {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.get_declared_property(guard, LonghandId::AnimationComposition)
|
||||
.map(|decl| {
|
||||
match *decl {
|
||||
PropertyDeclaration::AnimationComposition(ref value) => {
|
||||
// Use the first value
|
||||
value.0[0].clone()
|
||||
},
|
||||
_ => unreachable!("Unexpected PropertyDeclaration"),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue