зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1260655 - Add KeyframeEffectReadOnly::SetFrames; r=heycam
Earlier in this patch series we divided keyframe processing into two stages: (1) Turning javascript objects into an array of Keyframe objects (2) Calculating AnimationProperty arrays from the Keyframe objects This patch creates a SetFrames method so that CSS animations and CSS transitions can skip (1) and pass the frames constructed from CSS syntax into (2). It also adds the following additional processing: a. Notifying animation mutation observers when the set of frames has changed. This is currently performed by nsAnimationManager but ultimately we should encapsulate this logic inside the effect itself. Furthermore, it will be needed when we implement effect.setFrames() (i.e. the Javascript-facing wrapper for this method). b. Preserving the mWinsInCascade and mIsRunningOnCompositor state on properties when updating them. This is currently performed by: bool KeyframeEffectReadOnly::UpdateProperties( const InfallibleTArray<AnimationProperty>& aProperties) which is what nsAnimationManager currently uses. We will ultimately remove the above method and here we are just moving this code to the new version of UpdateProperties. c. Requesting a restyle when the set of AnimationProperty objects has changed. Again, this is currently performed by the existing UpdateProperties method so we are just moving it here. This behavior will also be required when we implement effect.setFrames() and when we call UpdateProperties from elsewhere in restyling code. This is bug 1235002 but we fix it here and leave that bug to just do further cleanup work (e.g. re-instating the check for an empty property set before requesting a restyle in NotifyAnimationTimingUpdated). d. Marking the cascade as needing an update when the set of AnimationProperty objects has changed. This is in preparation for calling UpdateProperties from elsewhere in restyling (e.g. when the nsStyleContext is updated). MozReview-Commit-ID: 2ll26lsWZTm
This commit is contained in:
Родитель
99a1a632e3
Коммит
bdacb97d48
|
@ -457,6 +457,46 @@ KeyframeEffectReadOnly::SetAnimation(Animation* aAnimation)
|
|||
NotifyAnimationTimingUpdated();
|
||||
}
|
||||
|
||||
static bool
|
||||
KeyframesEqualIgnoringComputedOffsets(const nsTArray<Keyframe>& aLhs,
|
||||
const nsTArray<Keyframe>& aRhs)
|
||||
{
|
||||
if (aLhs.Length() != aRhs.Length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0, len = aLhs.Length(); i < len; ++i) {
|
||||
const Keyframe& a = aLhs[i];
|
||||
const Keyframe& b = aRhs[i];
|
||||
if (a.mOffset != b.mOffset ||
|
||||
a.mTimingFunction != b.mTimingFunction ||
|
||||
a.mPropertyValues != b.mPropertyValues) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
KeyframeEffectReadOnly::SetFrames(nsTArray<Keyframe>&& aFrames,
|
||||
nsStyleContext* aStyleContext)
|
||||
{
|
||||
if (KeyframesEqualIgnoringComputedOffsets(aFrames, mFrames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mFrames = Move(aFrames);
|
||||
KeyframeUtils::ApplyDistributeSpacing(mFrames);
|
||||
|
||||
if (mAnimation && mAnimation->IsRelevant()) {
|
||||
nsNodeUtils::AnimationChanged(mAnimation);
|
||||
}
|
||||
|
||||
if (aStyleContext) {
|
||||
UpdateProperties(aStyleContext);
|
||||
}
|
||||
}
|
||||
|
||||
const AnimationProperty*
|
||||
KeyframeEffectReadOnly::GetAnimationOfProperty(nsCSSProperty aProperty) const
|
||||
{
|
||||
|
@ -531,6 +571,64 @@ KeyframeEffectReadOnly::UpdateProperties(
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
KeyframeEffectReadOnly::UpdateProperties(nsStyleContext* aStyleContext)
|
||||
{
|
||||
MOZ_ASSERT(aStyleContext);
|
||||
|
||||
nsTArray<AnimationProperty> properties;
|
||||
if (mTarget) {
|
||||
properties =
|
||||
KeyframeUtils::GetAnimationPropertiesFromKeyframes(aStyleContext,
|
||||
mTarget,
|
||||
mPseudoType,
|
||||
mFrames);
|
||||
}
|
||||
|
||||
if (mProperties == properties) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Preserve the state of mWinsInCascade and mIsRunningOnCompositor flags.
|
||||
nsCSSPropertySet winningInCascadeProperties;
|
||||
nsCSSPropertySet runningOnCompositorProperties;
|
||||
|
||||
for (const AnimationProperty& property : mProperties) {
|
||||
if (property.mWinsInCascade) {
|
||||
winningInCascadeProperties.AddProperty(property.mProperty);
|
||||
}
|
||||
if (property.mIsRunningOnCompositor) {
|
||||
runningOnCompositorProperties.AddProperty(property.mProperty);
|
||||
}
|
||||
}
|
||||
|
||||
mProperties = Move(properties);
|
||||
|
||||
for (AnimationProperty& property : mProperties) {
|
||||
property.mWinsInCascade =
|
||||
winningInCascadeProperties.HasProperty(property.mProperty);
|
||||
property.mIsRunningOnCompositor =
|
||||
runningOnCompositorProperties.HasProperty(property.mProperty);
|
||||
}
|
||||
|
||||
if (mTarget) {
|
||||
EffectSet* effectSet = EffectSet::GetEffectSet(mTarget, mPseudoType);
|
||||
if (effectSet) {
|
||||
effectSet->MarkCascadeNeedsUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
if (mAnimation) {
|
||||
nsPresContext* presContext = GetPresContext();
|
||||
if (presContext) {
|
||||
presContext->EffectCompositor()->
|
||||
RequestRestyle(mTarget, mPseudoType,
|
||||
EffectCompositor::RestyleType::Layer,
|
||||
mAnimation->CascadeLevel());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
KeyframeEffectReadOnly::ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
|
||||
nsCSSPropertySet& aSetProperties)
|
||||
|
@ -721,7 +819,10 @@ KeyframeEffectReadOnly::ConstructKeyframeEffect(
|
|||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
KeyframeUtils::ApplyDistributeSpacing(keyframes);
|
||||
|
||||
RefPtr<KeyframeEffectType> effect =
|
||||
new KeyframeEffectType(targetElement->OwnerDoc(), targetElement,
|
||||
pseudoType, timingParams);
|
||||
|
||||
RefPtr<nsStyleContext> styleContext;
|
||||
nsIPresShell* shell = doc->GetShell();
|
||||
|
@ -733,20 +834,8 @@ KeyframeEffectReadOnly::ConstructKeyframeEffect(
|
|||
nsComputedDOMStyle::GetStyleContextForElement(targetElement, pseudo,
|
||||
shell);
|
||||
}
|
||||
effect->SetFrames(Move(keyframes), styleContext);
|
||||
|
||||
nsTArray<AnimationProperty> animationProperties;
|
||||
if (styleContext) {
|
||||
animationProperties =
|
||||
KeyframeUtils::GetAnimationPropertiesFromKeyframes(styleContext,
|
||||
targetElement,
|
||||
pseudoType,
|
||||
keyframes);
|
||||
}
|
||||
|
||||
RefPtr<KeyframeEffectType> effect =
|
||||
new KeyframeEffectType(targetElement->OwnerDoc(), targetElement,
|
||||
pseudoType, timingParams);
|
||||
effect->mProperties = Move(animationProperties);
|
||||
return effect.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,11 @@ struct PropertyValuePair
|
|||
// property values, we store the specified property value as a token stream
|
||||
// (string).
|
||||
nsCSSValue mValue;
|
||||
|
||||
bool operator==(const PropertyValuePair& aOther) const {
|
||||
return mProperty == aOther.mProperty &&
|
||||
mValue == aOther.mValue;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -274,6 +279,7 @@ public:
|
|||
void SetAnimation(Animation* aAnimation);
|
||||
Animation* GetAnimation() const { return mAnimation; }
|
||||
|
||||
void SetFrames(nsTArray<Keyframe>&& aFrames, nsStyleContext* aStyleContext);
|
||||
const AnimationProperty*
|
||||
GetAnimationOfProperty(nsCSSProperty aProperty) const;
|
||||
bool HasAnimationOfProperty(nsCSSProperty aProperty) const {
|
||||
|
@ -294,6 +300,10 @@ public:
|
|||
bool UpdateProperties(
|
||||
const InfallibleTArray<AnimationProperty>& aProperties);
|
||||
|
||||
// Update |mProperties| by recalculating from |mFrames| using |aStyleContext|
|
||||
// to resolve specified values.
|
||||
void UpdateProperties(nsStyleContext* aStyleContext);
|
||||
|
||||
// Updates |aStyleRule| with the animation values produced by this
|
||||
// AnimationEffect for the current time except any properties already
|
||||
// contained in |aSetProperties|.
|
||||
|
@ -363,7 +373,11 @@ protected:
|
|||
OwningNonNull<AnimationEffectTimingReadOnly> mTiming;
|
||||
CSSPseudoElementType mPseudoType;
|
||||
|
||||
InfallibleTArray<AnimationProperty> mProperties;
|
||||
// The specified keyframes.
|
||||
nsTArray<Keyframe> mFrames;
|
||||
|
||||
// A set of per-property value arrays, derived from |mFrames|.
|
||||
nsTArray<AnimationProperty> mProperties;
|
||||
|
||||
// The computed progress last time we composed the style rule. This is
|
||||
// used to detect when the progress is not changing (e.g. due to a step
|
||||
|
|
|
@ -467,6 +467,9 @@ KeyframeUtils::GetAnimationPropertiesFromKeyframes(
|
|||
CSSPseudoElementType aPseudoType,
|
||||
const nsTArray<Keyframe>& aFrames)
|
||||
{
|
||||
MOZ_ASSERT(aStyleContext);
|
||||
MOZ_ASSERT(aElement);
|
||||
|
||||
nsTArray<KeyframeValueEntry> entries;
|
||||
|
||||
for (const Keyframe& frame : aFrames) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче