Bug 1846516 - [css-properties-values-api] Introduce AnimatedPropertyID/AnimatedPropertIDSet. r=firefox-animation-reviewers,firefox-style-system-reviewers,layout-reviewers,emilio,hiro
This will make possible to animate custom properties on Gecko side. For now, the animation code keeps only dealing with nsCSSPropertyID, so behavior is unchanged. Co-authored-by: Frederic Wang <fred.wang@free.fr> Depends on D190816 Differential Revision: https://phabricator.services.mozilla.com/D191059
This commit is contained in:
@@ -868,10 +868,11 @@ void Animation::CommitStyles(ErrorResult& aRv) {
|
||||
|
||||
// Set the animated styles
|
||||
bool changed = false;
|
||||
nsCSSPropertyIDSet properties = keyframeEffect->GetPropertySet();
|
||||
for (nsCSSPropertyID property : properties) {
|
||||
const AnimatedPropertyIDSet& properties = keyframeEffect->GetPropertySet();
|
||||
for (const AnimatedPropertyID& property : properties) {
|
||||
// TODO(zrhoffman, bug 1846516): Handle custom properties
|
||||
RefPtr<StyleAnimationValue> computedValue =
|
||||
Servo_AnimationValueMap_GetValue(animationValues.get(), property)
|
||||
Servo_AnimationValueMap_GetValue(animationValues.get(), property.mID)
|
||||
.Consume();
|
||||
if (computedValue) {
|
||||
changed |= Servo_DeclarationBlock_SetPropertyToAnimationValue(
|
||||
|
||||
@@ -92,7 +92,7 @@ void AnimationEventInfo::MaybeAddMarker() const {
|
||||
if (dom::KeyframeEffect* keyFrameEffect = effect->AsKeyframeEffect()) {
|
||||
keyFrameEffect->GetTarget()->Describe(target, true);
|
||||
for (const AnimationProperty& property : keyFrameEffect->Properties()) {
|
||||
propertySet.AddProperty(property.mProperty);
|
||||
propertySet.AddProperty(property.mProperty.mID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,7 +136,7 @@ void AnimationEventInfo::MaybeAddMarker() const {
|
||||
mAnimation->GetOwner()
|
||||
? MarkerInnerWindowId(mAnimation->GetOwner()->WindowID())
|
||||
: MarkerInnerWindowId::NoId()),
|
||||
CSSTransitionMarker, NS_ConvertUTF16toUTF8(target), data.mPropertyId,
|
||||
CSSTransitionMarker, NS_ConvertUTF16toUTF8(target), data.mProperty.mID,
|
||||
message == eTransitionCancel);
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ struct AnimationEventInfo {
|
||||
|
||||
struct CssTransitionData : public CssAnimationOrTransitionData {
|
||||
// For transition events only.
|
||||
const nsCSSPropertyID mPropertyId = eCSSProperty_UNKNOWN;
|
||||
const AnimatedPropertyID mProperty;
|
||||
};
|
||||
|
||||
struct WebAnimationData {
|
||||
@@ -150,7 +150,7 @@ struct AnimationEventInfo {
|
||||
void MaybeAddMarker() const;
|
||||
|
||||
// For CSS animation events
|
||||
AnimationEventInfo(nsAtom* aAnimationName,
|
||||
AnimationEventInfo(RefPtr<nsAtom> aAnimationName,
|
||||
const NonOwningAnimationTarget& aTarget,
|
||||
EventMessage aMessage, double aElapsedTime,
|
||||
const TimeStamp& aScheduledEventTimeStamp,
|
||||
@@ -160,14 +160,14 @@ struct AnimationEventInfo {
|
||||
mData(CssAnimationData{
|
||||
{OwningAnimationTarget(aTarget.mElement, aTarget.mPseudoType),
|
||||
aMessage, aElapsedTime},
|
||||
aAnimationName}) {
|
||||
std::move(aAnimationName)}) {
|
||||
if (profiler_thread_is_being_profiled_for_markers()) {
|
||||
MaybeAddMarker();
|
||||
}
|
||||
}
|
||||
|
||||
// For CSS transition events
|
||||
AnimationEventInfo(nsCSSPropertyID aProperty,
|
||||
AnimationEventInfo(const AnimatedPropertyID& aProperty,
|
||||
const NonOwningAnimationTarget& aTarget,
|
||||
EventMessage aMessage, double aElapsedTime,
|
||||
const TimeStamp& aScheduledEventTimeStamp,
|
||||
@@ -242,8 +242,7 @@ struct AnimationEventInfo {
|
||||
}
|
||||
|
||||
InternalTransitionEvent event(true, data.mMessage);
|
||||
CopyUTF8toUTF16(nsCSSProps::GetStringValue(data.mPropertyId),
|
||||
event.mPropertyName);
|
||||
data.mProperty.ToString(event.mPropertyName);
|
||||
event.mElapsedTime = data.mElapsedTime;
|
||||
event.mPseudoElement =
|
||||
nsCSSPseudoElements::PseudoTypeAsString(data.mTarget.mPseudoType);
|
||||
|
||||
@@ -21,10 +21,9 @@ JSObject* CSSTransition::WrapObject(JSContext* aCx,
|
||||
}
|
||||
|
||||
void CSSTransition::GetTransitionProperty(nsString& aRetVal) const {
|
||||
MOZ_ASSERT(eCSSProperty_UNKNOWN != mTransitionProperty,
|
||||
MOZ_ASSERT(mTransitionProperty.IsValid(),
|
||||
"Transition Property should be initialized");
|
||||
aRetVal =
|
||||
NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(mTransitionProperty));
|
||||
mTransitionProperty.ToString(aRetVal);
|
||||
}
|
||||
|
||||
AnimationPlayState CSSTransition::PlayStateFromJS() const {
|
||||
@@ -194,8 +193,8 @@ void CSSTransition::Tick(TickState& aState) {
|
||||
QueueEvents();
|
||||
}
|
||||
|
||||
nsCSSPropertyID CSSTransition::TransitionProperty() const {
|
||||
MOZ_ASSERT(eCSSProperty_UNKNOWN != mTransitionProperty,
|
||||
const AnimatedPropertyID& CSSTransition::TransitionProperty() const {
|
||||
MOZ_ASSERT(mTransitionProperty.IsValid(),
|
||||
"Transition property should be initialized");
|
||||
return mTransitionProperty;
|
||||
}
|
||||
@@ -231,8 +230,10 @@ bool CSSTransition::HasLowerCompositeOrderThan(
|
||||
}
|
||||
|
||||
// 3. (Same transition generation): Sort by transition property
|
||||
return nsCSSProps::GetStringValue(TransitionProperty()) <
|
||||
nsCSSProps::GetStringValue(aOther.TransitionProperty());
|
||||
nsAutoString name, otherName;
|
||||
GetTransitionProperty(name);
|
||||
aOther.GetTransitionProperty(otherName);
|
||||
return name < otherName;
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "mozilla/ComputedTiming.h"
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "mozilla/AnimatedPropertyID.h"
|
||||
#include "mozilla/StyleAnimationValue.h"
|
||||
#include "AnimationCommon.h"
|
||||
|
||||
@@ -19,11 +20,12 @@ namespace dom {
|
||||
|
||||
class CSSTransition final : public Animation {
|
||||
public:
|
||||
explicit CSSTransition(nsIGlobalObject* aGlobal)
|
||||
explicit CSSTransition(nsIGlobalObject* aGlobal,
|
||||
const AnimatedPropertyID& aProperty)
|
||||
: Animation(aGlobal),
|
||||
mPreviousTransitionPhase(TransitionPhase::Idle),
|
||||
mNeedsNewAnimationIndexWhenRun(false),
|
||||
mTransitionProperty(eCSSProperty_UNKNOWN) {}
|
||||
mTransitionProperty(aProperty) {}
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
@@ -72,7 +74,7 @@ class CSSTransition final : public Animation {
|
||||
|
||||
void Tick(TickState&) override;
|
||||
|
||||
nsCSSPropertyID TransitionProperty() const;
|
||||
const AnimatedPropertyID& TransitionProperty() const;
|
||||
AnimationValue ToValue() const;
|
||||
|
||||
bool HasLowerCompositeOrderThan(const CSSTransition& aOther) const;
|
||||
@@ -197,7 +199,7 @@ class CSSTransition final : public Animation {
|
||||
// information in order to determine if there is an existing transition
|
||||
// for a given style change. We can't store that information on the
|
||||
// effect however since it can be replaced using the Web Animations API.
|
||||
nsCSSPropertyID mTransitionProperty;
|
||||
AnimatedPropertyID mTransitionProperty;
|
||||
AnimationValue mTransitionToValue;
|
||||
|
||||
// This is the start value to be used for a check for whether a
|
||||
|
||||
@@ -608,11 +608,11 @@ nsCSSPropertyIDSet EffectCompositor::GetOverriddenProperties(
|
||||
nsCSSPropertyIDSet propertiesToTrackAsSet;
|
||||
for (KeyframeEffect* effect : aEffectSet) {
|
||||
for (const AnimationProperty& property : effect->Properties()) {
|
||||
if (nsCSSProps::PropHasFlags(property.mProperty,
|
||||
if (nsCSSProps::PropHasFlags(property.mProperty.mID,
|
||||
CSSPropFlags::CanAnimateOnCompositor) &&
|
||||
!propertiesToTrackAsSet.HasProperty(property.mProperty)) {
|
||||
propertiesToTrackAsSet.AddProperty(property.mProperty);
|
||||
propertiesToTrack.AppendElement(property.mProperty);
|
||||
!propertiesToTrackAsSet.HasProperty(property.mProperty.mID)) {
|
||||
propertiesToTrackAsSet.AddProperty(property.mProperty.mID);
|
||||
propertiesToTrack.AppendElement(property.mProperty.mID);
|
||||
}
|
||||
}
|
||||
// Skip iterating over the rest of the effects if we've already
|
||||
@@ -684,16 +684,16 @@ void EffectCompositor::UpdateCascadeResults(EffectSet& aEffectSet,
|
||||
CascadeLevel cascadeLevel = effect->GetAnimation()->CascadeLevel();
|
||||
|
||||
for (const AnimationProperty& prop : effect->Properties()) {
|
||||
if (overriddenProperties.HasProperty(prop.mProperty)) {
|
||||
propertiesWithImportantRules.AddProperty(prop.mProperty);
|
||||
if (overriddenProperties.HasProperty(prop.mProperty.mID)) {
|
||||
propertiesWithImportantRules.AddProperty(prop.mProperty.mID);
|
||||
}
|
||||
|
||||
switch (cascadeLevel) {
|
||||
case EffectCompositor::CascadeLevel::Animations:
|
||||
propertiesForAnimationsLevel.AddProperty(prop.mProperty);
|
||||
propertiesForAnimationsLevel.AddProperty(prop.mProperty.mID);
|
||||
break;
|
||||
case EffectCompositor::CascadeLevel::Transitions:
|
||||
propertiesForTransitionsLevel.AddProperty(prop.mProperty);
|
||||
propertiesForTransitionsLevel.AddProperty(prop.mProperty.mID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -912,7 +912,7 @@ static void ReduceEffectSet(EffectSet& aEffectSet) {
|
||||
}
|
||||
sortedEffectList.Sort(EffectCompositeOrderComparator());
|
||||
|
||||
nsCSSPropertyIDSet setProperties;
|
||||
AnimatedPropertyIDSet setProperties;
|
||||
|
||||
// Iterate in reverse
|
||||
for (auto iter = sortedEffectList.rbegin(); iter != sortedEffectList.rend();
|
||||
@@ -925,7 +925,7 @@ static void ReduceEffectSet(EffectSet& aEffectSet) {
|
||||
effect.GetPropertySet().IsSubsetOf(setProperties)) {
|
||||
animation.Remove();
|
||||
} else if (animation.IsReplaceable()) {
|
||||
setProperties |= effect.GetPropertySet();
|
||||
setProperties.AddProperties(effect.GetPropertySet());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ void KeyframeEffect::ReplaceTransitionStartValue(AnimationValue&& aStartValue) {
|
||||
// Check that the value we are about to substitute in is actually for the
|
||||
// same property.
|
||||
if (Servo_AnimationValue_GetPropertyId(aStartValue.mServo) !=
|
||||
mProperties[0].mProperty) {
|
||||
mProperties[0].mProperty.mID) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -309,14 +309,14 @@ const AnimationProperty* KeyframeEffect::GetEffectiveAnimationOfProperty(
|
||||
mTarget.mPseudoType));
|
||||
|
||||
for (const AnimationProperty& property : mProperties) {
|
||||
if (aProperty != property.mProperty) {
|
||||
if (aProperty != property.mProperty.mID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const AnimationProperty* result = nullptr;
|
||||
// Only include the property if it is not overridden by !important rules in
|
||||
// the transitions level.
|
||||
if (IsEffectiveProperty(aEffects, property.mProperty)) {
|
||||
if (IsEffectiveProperty(aEffects, property.mProperty.mID)) {
|
||||
result = &property;
|
||||
}
|
||||
return result;
|
||||
@@ -327,8 +327,8 @@ const AnimationProperty* KeyframeEffect::GetEffectiveAnimationOfProperty(
|
||||
bool KeyframeEffect::HasEffectiveAnimationOfPropertySet(
|
||||
const nsCSSPropertyIDSet& aPropertySet, const EffectSet& aEffectSet) const {
|
||||
for (const AnimationProperty& property : mProperties) {
|
||||
if (aPropertySet.HasProperty(property.mProperty) &&
|
||||
IsEffectiveProperty(aEffectSet, property.mProperty)) {
|
||||
if (aPropertySet.HasProperty(property.mProperty.mID) &&
|
||||
IsEffectiveProperty(aEffectSet, property.mProperty.mID)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -355,26 +355,27 @@ nsCSSPropertyIDSet KeyframeEffect::GetPropertiesForCompositor(
|
||||
AnimationPerformanceWarning::Type dummyWarning;
|
||||
|
||||
for (const AnimationProperty& property : mProperties) {
|
||||
if (!compositorAnimatables.HasProperty(property.mProperty)) {
|
||||
if (!compositorAnimatables.HasProperty(property.mProperty.mID)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Transform-like properties are combined together on the compositor so we
|
||||
// need to evaluate them as a group. We build up a separate set here then
|
||||
// evaluate it as a separate step below.
|
||||
if (transformLikeProperties.HasProperty(property.mProperty)) {
|
||||
transformSet.AddProperty(property.mProperty);
|
||||
if (transformLikeProperties.HasProperty(property.mProperty.mID)) {
|
||||
transformSet.AddProperty(property.mProperty.mID);
|
||||
continue;
|
||||
}
|
||||
|
||||
KeyframeEffect::MatchForCompositor matchResult = IsMatchForCompositor(
|
||||
nsCSSPropertyIDSet{property.mProperty}, aFrame, aEffects, dummyWarning);
|
||||
KeyframeEffect::MatchForCompositor matchResult =
|
||||
IsMatchForCompositor(nsCSSPropertyIDSet{property.mProperty.mID}, aFrame,
|
||||
aEffects, dummyWarning);
|
||||
if (matchResult ==
|
||||
KeyframeEffect::MatchForCompositor::NoAndBlockThisProperty ||
|
||||
matchResult == KeyframeEffect::MatchForCompositor::No) {
|
||||
continue;
|
||||
}
|
||||
properties.AddProperty(property.mProperty);
|
||||
properties.AddProperty(property.mProperty.mID);
|
||||
}
|
||||
|
||||
if (!transformSet.IsEmpty()) {
|
||||
@@ -389,8 +390,8 @@ nsCSSPropertyIDSet KeyframeEffect::GetPropertiesForCompositor(
|
||||
return properties;
|
||||
}
|
||||
|
||||
nsCSSPropertyIDSet KeyframeEffect::GetPropertySet() const {
|
||||
nsCSSPropertyIDSet result;
|
||||
AnimatedPropertyIDSet KeyframeEffect::GetPropertySet() const {
|
||||
AnimatedPropertyIDSet result;
|
||||
|
||||
for (const AnimationProperty& property : mProperties) {
|
||||
result.AddProperty(property.mProperty);
|
||||
@@ -455,7 +456,7 @@ void KeyframeEffect::UpdateProperties(const ComputedStyle* aStyle,
|
||||
|
||||
for (const AnimationProperty& property : mProperties) {
|
||||
if (property.mIsRunningOnCompositor) {
|
||||
runningOnCompositorProperties.AddProperty(property.mProperty);
|
||||
runningOnCompositorProperties.AddProperty(property.mProperty.mID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,7 +466,7 @@ void KeyframeEffect::UpdateProperties(const ComputedStyle* aStyle,
|
||||
mCumulativeChanges = {};
|
||||
for (AnimationProperty& property : mProperties) {
|
||||
property.mIsRunningOnCompositor =
|
||||
runningOnCompositorProperties.HasProperty(property.mProperty);
|
||||
runningOnCompositorProperties.HasProperty(property.mProperty.mID);
|
||||
CalculateCumulativeChangesForProperty(property);
|
||||
}
|
||||
|
||||
@@ -551,7 +552,7 @@ void KeyframeEffect::EnsureBaseStyle(
|
||||
// delay on the compositor.
|
||||
return aTimeline && aTimeline->IsScrollTimeline() &&
|
||||
nsCSSPropertyIDSet::CompositorAnimatables().HasProperty(
|
||||
aProperty.mProperty) &&
|
||||
aProperty.mProperty.mID) &&
|
||||
(timing.Delay() > zeroDuration ||
|
||||
timing.EndDelay() > zeroDuration);
|
||||
};
|
||||
@@ -586,9 +587,9 @@ void KeyframeEffect::EnsureBaseStyle(
|
||||
}
|
||||
RefPtr<StyleAnimationValue> baseValue =
|
||||
Servo_ComputedValues_ExtractAnimationValue(aBaseComputedStyle,
|
||||
aProperty.mProperty)
|
||||
aProperty.mProperty.mID)
|
||||
.Consume();
|
||||
mBaseValues.InsertOrUpdate(aProperty.mProperty, std::move(baseValue));
|
||||
mBaseValues.InsertOrUpdate(aProperty.mProperty.mID, std::move(baseValue));
|
||||
}
|
||||
|
||||
void KeyframeEffect::WillComposeStyle() {
|
||||
@@ -603,9 +604,10 @@ void KeyframeEffect::ComposeStyleRule(StyleAnimationValueMap& aAnimationValues,
|
||||
const ComputedTiming& aComputedTiming) {
|
||||
auto* opaqueTable =
|
||||
reinterpret_cast<RawServoAnimationValueTable*>(&mBaseValues);
|
||||
Servo_AnimationCompose(&aAnimationValues, opaqueTable, aProperty.mProperty,
|
||||
&aSegment, &aProperty.mSegments.LastElement(),
|
||||
&aComputedTiming, mEffectOptions.mIterationComposite);
|
||||
Servo_AnimationCompose(&aAnimationValues, opaqueTable,
|
||||
aProperty.mProperty.mID, &aSegment,
|
||||
&aProperty.mSegments.LastElement(), &aComputedTiming,
|
||||
mEffectOptions.mIterationComposite);
|
||||
}
|
||||
|
||||
void KeyframeEffect::ComposeStyle(StyleAnimationValueMap& aComposeResult,
|
||||
@@ -626,7 +628,7 @@ void KeyframeEffect::ComposeStyle(StyleAnimationValueMap& aComposeResult,
|
||||
MOZ_ASSERT(prop.mSegments[prop.mSegments.Length() - 1].mToKey == 1.0,
|
||||
"incorrect last to key");
|
||||
|
||||
if (aPropertiesToSkip.HasProperty(prop.mProperty)) {
|
||||
if (aPropertiesToSkip.HasProperty(prop.mProperty.mID)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -690,7 +692,7 @@ void KeyframeEffect::SetIsRunningOnCompositor(nsCSSPropertyID aProperty,
|
||||
"Property being animated on compositor is a recognized "
|
||||
"compositor-animatable property");
|
||||
for (AnimationProperty& property : mProperties) {
|
||||
if (property.mProperty == aProperty) {
|
||||
if (property.mProperty.mID == aProperty) {
|
||||
property.mIsRunningOnCompositor = aIsRunning;
|
||||
// We currently only set a performance warning message when animations
|
||||
// cannot be run on the compositor, so if this animation is running
|
||||
@@ -708,8 +710,8 @@ void KeyframeEffect::SetIsRunningOnCompositor(nsCSSPropertyID aProperty,
|
||||
void KeyframeEffect::SetIsRunningOnCompositor(
|
||||
const nsCSSPropertyIDSet& aPropertySet, bool aIsRunning) {
|
||||
for (AnimationProperty& property : mProperties) {
|
||||
if (aPropertySet.HasProperty(property.mProperty)) {
|
||||
MOZ_ASSERT(nsCSSProps::PropHasFlags(property.mProperty,
|
||||
if (aPropertySet.HasProperty(property.mProperty.mID)) {
|
||||
MOZ_ASSERT(nsCSSProps::PropHasFlags(property.mProperty.mID,
|
||||
CSSPropFlags::CanAnimateOnCompositor),
|
||||
"Property being animated on compositor is a recognized "
|
||||
"compositor-animatable property");
|
||||
@@ -1036,7 +1038,8 @@ void DumpAnimationProperties(
|
||||
const StylePerDocumentStyleData* aRawData,
|
||||
nsTArray<AnimationProperty>& aAnimationProperties) {
|
||||
for (auto& p : aAnimationProperties) {
|
||||
printf("%s\n", nsCString(nsCSSProps::GetStringValue(p.mProperty)).get());
|
||||
printf("%s\n",
|
||||
nsCString(nsCSSProps::GetStringValue(p.mProperty.mID)).get());
|
||||
for (auto& s : p.mSegments) {
|
||||
nsAutoCString fromValue, toValue;
|
||||
s.mFromValue.SerializeSpecifiedValue(p.mProperty, aRawData, fromValue);
|
||||
@@ -1120,7 +1123,7 @@ void KeyframeEffect::SetPseudoElement(const nsAString& aPseudoElement,
|
||||
}
|
||||
|
||||
static void CreatePropertyValue(
|
||||
nsCSSPropertyID aProperty, float aOffset,
|
||||
const AnimatedPropertyID& aProperty, float aOffset,
|
||||
const Maybe<StyleComputedTimingFunction>& aTimingFunction,
|
||||
const AnimationValue& aValue, dom::CompositeOperation aComposite,
|
||||
const StylePerDocumentStyleData* aRawData,
|
||||
@@ -1150,8 +1153,7 @@ void KeyframeEffect::GetProperties(
|
||||
|
||||
for (const AnimationProperty& property : mProperties) {
|
||||
AnimationPropertyDetails propertyDetails;
|
||||
propertyDetails.mProperty =
|
||||
NS_ConvertASCIItoUTF16(nsCSSProps::GetStringValue(property.mProperty));
|
||||
property.mProperty.ToString(propertyDetails.mProperty);
|
||||
propertyDetails.mRunningOnCompositor = property.mIsRunningOnCompositor;
|
||||
|
||||
nsAutoString localizedString;
|
||||
@@ -1475,7 +1477,7 @@ bool KeyframeEffect::CanThrottle() const {
|
||||
}
|
||||
|
||||
MOZ_ASSERT(nsCSSPropertyIDSet::CompositorAnimatables().HasProperty(
|
||||
property.mProperty),
|
||||
property.mProperty.mID),
|
||||
"The property should be able to run on the compositor");
|
||||
if (!effectSet) {
|
||||
effectSet = EffectSet::Get(mTarget.mElement, mTarget.mPseudoType);
|
||||
@@ -1483,12 +1485,14 @@ bool KeyframeEffect::CanThrottle() const {
|
||||
"CanThrottle should be called on an effect "
|
||||
"associated with a target element");
|
||||
}
|
||||
MOZ_ASSERT(HasEffectiveAnimationOfProperty(property.mProperty, *effectSet),
|
||||
"There should be an effective animation of the property while "
|
||||
"it is marked as being run on the compositor");
|
||||
MOZ_ASSERT(
|
||||
HasEffectiveAnimationOfProperty(property.mProperty.mID, *effectSet),
|
||||
"There should be an effective animation of the property while "
|
||||
"it is marked as being run on the compositor");
|
||||
|
||||
DisplayItemType displayItemType =
|
||||
LayerAnimationInfo::GetDisplayItemTypeForProperty(property.mProperty);
|
||||
LayerAnimationInfo::GetDisplayItemTypeForProperty(
|
||||
property.mProperty.mID);
|
||||
|
||||
// Note that AnimationInfo::GetGenarationFromFrame() is supposed to work
|
||||
// with the primary frame instead of the style frame.
|
||||
@@ -1714,14 +1718,14 @@ bool KeyframeEffect::ShouldBlockAsyncTransformAnimations(
|
||||
// !important rules.
|
||||
if (effectSet &&
|
||||
effectSet->PropertiesWithImportantRules().HasProperty(
|
||||
property.mProperty) &&
|
||||
property.mProperty.mID) &&
|
||||
effectSet->PropertiesForAnimationsLevel().HasProperty(
|
||||
property.mProperty)) {
|
||||
property.mProperty.mID)) {
|
||||
continue;
|
||||
}
|
||||
// Check for geometric properties
|
||||
if (enableMainthreadSynchronizationWithGeometricAnimations &&
|
||||
IsGeometricProperty(property.mProperty)) {
|
||||
IsGeometricProperty(property.mProperty.mID)) {
|
||||
aPerformanceWarning =
|
||||
AnimationPerformanceWarning::Type::TransformWithGeometricProperties;
|
||||
return true;
|
||||
@@ -1729,7 +1733,7 @@ bool KeyframeEffect::ShouldBlockAsyncTransformAnimations(
|
||||
|
||||
// Check for unsupported transform animations
|
||||
if (LayerAnimationInfo::GetCSSPropertiesFor(DisplayItemType::TYPE_TRANSFORM)
|
||||
.HasProperty(property.mProperty)) {
|
||||
.HasProperty(property.mProperty.mID)) {
|
||||
if (!CanAnimateTransformOnCompositor(aFrame, aPerformanceWarning)) {
|
||||
return true;
|
||||
}
|
||||
@@ -1737,7 +1741,7 @@ bool KeyframeEffect::ShouldBlockAsyncTransformAnimations(
|
||||
|
||||
// If there are any offset-path animations whose animation values are url(),
|
||||
// we have to sync with the main thread when resolving it.
|
||||
if (property.mProperty == eCSSProperty_offset_path) {
|
||||
if (property.mProperty.mID == eCSSProperty_offset_path) {
|
||||
for (const auto& seg : property.mSegments) {
|
||||
if (seg.mFromValue.IsOffsetPathUrl() ||
|
||||
seg.mToValue.IsOffsetPathUrl()) {
|
||||
@@ -1752,7 +1756,7 @@ bool KeyframeEffect::ShouldBlockAsyncTransformAnimations(
|
||||
|
||||
bool KeyframeEffect::HasGeometricProperties() const {
|
||||
for (const AnimationProperty& property : mProperties) {
|
||||
if (IsGeometricProperty(property.mProperty)) {
|
||||
if (IsGeometricProperty(property.mProperty.mID)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1765,11 +1769,11 @@ void KeyframeEffect::SetPerformanceWarning(
|
||||
const AnimationPerformanceWarning& aWarning) {
|
||||
nsCSSPropertyIDSet curr = aPropertySet;
|
||||
for (AnimationProperty& property : mProperties) {
|
||||
if (!curr.HasProperty(property.mProperty)) {
|
||||
if (!curr.HasProperty(property.mProperty.mID)) {
|
||||
continue;
|
||||
}
|
||||
property.SetPerformanceWarning(aWarning, mTarget.mElement);
|
||||
curr.RemoveProperty(property.mProperty);
|
||||
curr.RemoveProperty(property.mProperty.mID);
|
||||
if (curr.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
@@ -1778,19 +1782,24 @@ void KeyframeEffect::SetPerformanceWarning(
|
||||
|
||||
void KeyframeEffect::CalculateCumulativeChangesForProperty(
|
||||
const AnimationProperty& aProperty) {
|
||||
if (aProperty.mProperty.IsCustom()) {
|
||||
// Custom properties don't affect rendering on their own.
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr auto kInterestingFlags =
|
||||
CSSPropFlags::AffectsLayout | CSSPropFlags::AffectsOverflow;
|
||||
if (aProperty.mProperty == eCSSProperty_opacity) {
|
||||
if (aProperty.mProperty.mID == eCSSProperty_opacity) {
|
||||
mCumulativeChanges.mOpacity = true;
|
||||
return; // We know opacity is visual-only.
|
||||
}
|
||||
|
||||
if (aProperty.mProperty == eCSSProperty_visibility) {
|
||||
if (aProperty.mProperty.mID == eCSSProperty_visibility) {
|
||||
mCumulativeChanges.mVisibility = true;
|
||||
return; // We know visibility is visual-only.
|
||||
}
|
||||
|
||||
if (aProperty.mProperty == eCSSProperty_background_color) {
|
||||
if (aProperty.mProperty.mID == eCSSProperty_background_color) {
|
||||
if (!mCumulativeChanges.mHasBackgroundColorCurrentColor) {
|
||||
mCumulativeChanges.mHasBackgroundColorCurrentColor =
|
||||
HasCurrentColor(aProperty.mSegments);
|
||||
@@ -1798,7 +1807,7 @@ void KeyframeEffect::CalculateCumulativeChangesForProperty(
|
||||
return; // We know background-color is visual-only.
|
||||
}
|
||||
|
||||
auto flags = nsCSSProps::PropFlags(aProperty.mProperty);
|
||||
auto flags = nsCSSProps::PropFlags(aProperty.mProperty.mID);
|
||||
if (!(flags & kInterestingFlags)) {
|
||||
return; // Property is visual-only.
|
||||
}
|
||||
@@ -1906,9 +1915,9 @@ bool KeyframeEffect::ContainsAnimatedScale(const nsIFrame* aFrame) const {
|
||||
}
|
||||
|
||||
for (const AnimationProperty& prop : mProperties) {
|
||||
if (prop.mProperty != eCSSProperty_transform &&
|
||||
prop.mProperty != eCSSProperty_scale &&
|
||||
prop.mProperty != eCSSProperty_rotate) {
|
||||
if (prop.mProperty.mID != eCSSProperty_transform &&
|
||||
prop.mProperty.mID != eCSSProperty_scale &&
|
||||
prop.mProperty.mID != eCSSProperty_rotate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/AnimatedPropertyID.h"
|
||||
#include "mozilla/AnimatedPropertyIDSet.h"
|
||||
#include "mozilla/AnimationPerformanceWarning.h"
|
||||
#include "mozilla/AnimationPropertySegment.h"
|
||||
#include "mozilla/AnimationTarget.h"
|
||||
@@ -55,7 +57,7 @@ struct AnimationPropertyDetails;
|
||||
} // namespace dom
|
||||
|
||||
struct AnimationProperty {
|
||||
nsCSSPropertyID mProperty = eCSSProperty_UNKNOWN;
|
||||
AnimatedPropertyID mProperty;
|
||||
|
||||
// If true, the propery is currently being animated on the compositor.
|
||||
//
|
||||
@@ -74,7 +76,7 @@ struct AnimationProperty {
|
||||
|
||||
// The copy constructor/assignment doesn't copy mIsRunningOnCompositor and
|
||||
// mPerformanceWarning.
|
||||
AnimationProperty() = default;
|
||||
AnimationProperty() : mProperty(eCSSProperty_UNKNOWN){};
|
||||
AnimationProperty(const AnimationProperty& aOther)
|
||||
: mProperty(aOther.mProperty), mSegments(aOther.mSegments.Clone()) {}
|
||||
AnimationProperty& operator=(const AnimationProperty& aOther) {
|
||||
@@ -199,7 +201,7 @@ class KeyframeEffect : public AnimationEffect {
|
||||
|
||||
// Returns the set of properties affected by this effect regardless of
|
||||
// whether any of these properties is overridden by an !important rule.
|
||||
nsCSSPropertyIDSet GetPropertySet() const;
|
||||
AnimatedPropertyIDSet GetPropertySet() const;
|
||||
|
||||
// Returns true if the effect includes a property in |aPropertySet| regardless
|
||||
// of whether any property in the set is overridden by an !important rule.
|
||||
@@ -325,13 +327,13 @@ class KeyframeEffect : public AnimationEffect {
|
||||
// |aFrame| is used for calculation of scale values.
|
||||
bool ContainsAnimatedScale(const nsIFrame* aFrame) const;
|
||||
|
||||
AnimationValue BaseStyle(nsCSSPropertyID aProperty) const {
|
||||
AnimationValue BaseStyle(const AnimatedPropertyID& aProperty) const {
|
||||
AnimationValue result;
|
||||
bool hasProperty = false;
|
||||
// We cannot use getters_AddRefs on StyleAnimationValue because it is
|
||||
// an incomplete type, so Get() doesn't work. Instead, use GetWeak, and
|
||||
// then assign the raw pointer to a RefPtr.
|
||||
result.mServo = mBaseValues.GetWeak(aProperty, &hasProperty);
|
||||
result.mServo = mBaseValues.GetWeak(aProperty.mID, &hasProperty);
|
||||
MOZ_ASSERT(hasProperty || result.IsNull());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "jsapi.h" // For most JSAPI
|
||||
#include "js/ForOfIterator.h" // For JS::ForOfIterator
|
||||
#include "js/PropertyAndElement.h" // JS_Enumerate, JS_GetProperty, JS_GetPropertyById
|
||||
#include "mozilla/AnimatedPropertyID.h"
|
||||
#include "mozilla/ComputedStyle.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/RangedArray.h"
|
||||
@@ -34,6 +35,7 @@
|
||||
#include "nsContentUtils.h" // For GetContextForContent
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsPresContextInlines.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
using mozilla::dom::Nullable;
|
||||
@@ -59,7 +61,9 @@ enum class ListAllowance { eDisallow, eAllow };
|
||||
* mValues.
|
||||
*/
|
||||
struct PropertyValuesPair {
|
||||
nsCSSPropertyID mProperty;
|
||||
PropertyValuesPair() : mProperty(eCSSProperty_UNKNOWN) {}
|
||||
|
||||
AnimatedPropertyID mProperty;
|
||||
nsTArray<nsCString> mValues;
|
||||
};
|
||||
|
||||
@@ -68,7 +72,9 @@ struct PropertyValuesPair {
|
||||
* BaseKeyframe or BasePropertyIndexedKeyframe object.
|
||||
*/
|
||||
struct AdditionalProperty {
|
||||
nsCSSPropertyID mProperty;
|
||||
AdditionalProperty() : mProperty(eCSSProperty_UNKNOWN), mJsidIndex() {}
|
||||
|
||||
AnimatedPropertyID mProperty;
|
||||
size_t mJsidIndex; // Index into |ids| in GetPropertyValuesPairs.
|
||||
|
||||
struct PropertyComparator {
|
||||
@@ -78,8 +84,24 @@ struct AdditionalProperty {
|
||||
}
|
||||
bool LessThan(const AdditionalProperty& aLhs,
|
||||
const AdditionalProperty& aRhs) const {
|
||||
return nsCSSProps::PropertyIDLNameSortPosition(aLhs.mProperty) <
|
||||
nsCSSProps::PropertyIDLNameSortPosition(aRhs.mProperty);
|
||||
bool customLhs =
|
||||
aLhs.mProperty.mID == nsCSSPropertyID::eCSSPropertyExtra_variable;
|
||||
bool customRhs =
|
||||
aRhs.mProperty.mID == nsCSSPropertyID::eCSSPropertyExtra_variable;
|
||||
if (!customLhs && !customRhs) {
|
||||
// Compare by IDL names.
|
||||
return nsCSSProps::PropertyIDLNameSortPosition(aLhs.mProperty.mID) <
|
||||
nsCSSProps::PropertyIDLNameSortPosition(aRhs.mProperty.mID);
|
||||
}
|
||||
if (customLhs && customRhs) {
|
||||
// Compare by custom property names.
|
||||
return nsDependentAtomString(aLhs.mProperty.mCustomName) <
|
||||
nsDependentAtomString(aRhs.mProperty.mCustomName);
|
||||
}
|
||||
// Custom properties should be ordered before normal CSS properties, as if
|
||||
// the custom property name starts with `--`.
|
||||
// <https://drafts.csswg.org/web-animations-1/#idl-attribute-name-to-animation-property-name>
|
||||
return !customLhs && customRhs;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -92,7 +114,10 @@ struct AdditionalProperty {
|
||||
* to gather data for each individual segment.
|
||||
*/
|
||||
struct KeyframeValueEntry {
|
||||
nsCSSPropertyID mProperty;
|
||||
KeyframeValueEntry()
|
||||
: mProperty(eCSSProperty_UNKNOWN), mOffset(), mComposite() {}
|
||||
|
||||
AnimatedPropertyID mProperty;
|
||||
AnimationValue mValue;
|
||||
|
||||
float mOffset;
|
||||
@@ -106,11 +131,28 @@ struct KeyframeValueEntry {
|
||||
}
|
||||
static bool LessThan(const KeyframeValueEntry& aLhs,
|
||||
const KeyframeValueEntry& aRhs) {
|
||||
// First, sort by property IDL name.
|
||||
int32_t order = nsCSSProps::PropertyIDLNameSortPosition(aLhs.mProperty) -
|
||||
nsCSSProps::PropertyIDLNameSortPosition(aRhs.mProperty);
|
||||
if (order != 0) {
|
||||
return order < 0;
|
||||
// First, sort by property name.
|
||||
bool customLhs =
|
||||
aLhs.mProperty.mID == nsCSSPropertyID::eCSSPropertyExtra_variable;
|
||||
bool customRhs =
|
||||
aRhs.mProperty.mID == nsCSSPropertyID::eCSSPropertyExtra_variable;
|
||||
if (!customLhs && !customRhs) {
|
||||
// Compare by IDL names.
|
||||
int32_t order =
|
||||
nsCSSProps::PropertyIDLNameSortPosition(aLhs.mProperty.mID) -
|
||||
nsCSSProps::PropertyIDLNameSortPosition(aRhs.mProperty.mID);
|
||||
if (order != 0) {
|
||||
return order < 0;
|
||||
}
|
||||
} else if (customLhs && customRhs) {
|
||||
// Compare by custom property names.
|
||||
int order = Compare(nsDependentAtomString(aLhs.mProperty.mCustomName),
|
||||
nsDependentAtomString(aRhs.mProperty.mCustomName));
|
||||
if (order != 0) {
|
||||
return order < 0;
|
||||
}
|
||||
} else {
|
||||
return !customLhs && customRhs;
|
||||
}
|
||||
|
||||
// Then, by offset.
|
||||
@@ -159,7 +201,7 @@ static bool AppendValueAsString(JSContext* aCx, nsTArray<nsCString>& aValues,
|
||||
JS::Handle<JS::Value> aValue);
|
||||
|
||||
static Maybe<PropertyValuePair> MakePropertyValuePair(
|
||||
nsCSSPropertyID aProperty, const nsACString& aStringValue,
|
||||
const AnimatedPropertyID& aProperty, const nsACString& aStringValue,
|
||||
dom::Document* aDocument);
|
||||
|
||||
static bool HasValidOffsets(const nsTArray<Keyframe>& aKeyframes);
|
||||
@@ -292,7 +334,7 @@ nsTArray<AnimationProperty> KeyframeUtils::GetAnimationPropertiesFromKeyframes(
|
||||
"Invalid computed offset");
|
||||
KeyframeValueEntry* entry = entries.AppendElement();
|
||||
entry->mOffset = frame.mComputedOffset;
|
||||
entry->mProperty = value.mProperty;
|
||||
entry->mProperty.mID = value.mProperty;
|
||||
entry->mValue = value.mValue;
|
||||
entry->mTimingFunction = frame.mTimingFunction;
|
||||
// The following assumes that CompositeOperation is a strict subset of
|
||||
@@ -309,14 +351,18 @@ nsTArray<AnimationProperty> KeyframeUtils::GetAnimationPropertiesFromKeyframes(
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool KeyframeUtils::IsAnimatableProperty(nsCSSPropertyID aProperty) {
|
||||
bool KeyframeUtils::IsAnimatableProperty(const AnimatedPropertyID& aProperty) {
|
||||
// Regardless of the backend type, treat the 'display' property as not
|
||||
// animatable. (Servo will report it as being animatable, since it is
|
||||
// in fact animatable by SMIL.)
|
||||
if (aProperty == eCSSProperty_display) {
|
||||
if (aProperty.mID == eCSSProperty_display) {
|
||||
return false;
|
||||
}
|
||||
return Servo_Property_IsAnimatable(aProperty);
|
||||
// TODO(bug 1846516): handle custom property.
|
||||
if (!aProperty.IsCustom()) {
|
||||
return false;
|
||||
}
|
||||
return Servo_Property_IsAnimatable(aProperty.mID);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
@@ -461,7 +507,7 @@ static bool ConvertKeyframeSequence(JSContext* aCx, dom::Document* aDocument,
|
||||
// includes a chrome-only member that can be set to indicate that
|
||||
// ComputeValues should fail for shorthand property values on that
|
||||
// keyframe.
|
||||
if (nsCSSProps::IsShorthand(pair.mProperty) &&
|
||||
if (nsCSSProps::IsShorthand(pair.mProperty.mID) &&
|
||||
keyframeDict.mSimulateComputeValuesFailure) {
|
||||
MarkAsComputeValuesFailureKey(keyframe->mPropertyValues.LastElement());
|
||||
}
|
||||
@@ -517,20 +563,32 @@ static bool GetPropertyValuesPairs(JSContext* aCx,
|
||||
// This means if the attribute is the string "cssOffset"/"cssFloat", we use
|
||||
// CSS "offset"/"float" property.
|
||||
// https://drafts.csswg.org/web-animations/#property-name-conversion
|
||||
nsCSSPropertyID property = nsCSSPropertyID::eCSSProperty_UNKNOWN;
|
||||
if (propName.EqualsLiteral("cssOffset")) {
|
||||
property = nsCSSPropertyID::eCSSProperty_offset;
|
||||
nsCSSPropertyID propertyID = nsCSSPropertyID::eCSSProperty_UNKNOWN;
|
||||
if (nsCSSProps::IsCustomPropertyName(propName)) {
|
||||
propertyID = eCSSPropertyExtra_variable;
|
||||
} else if (propName.EqualsLiteral("cssOffset")) {
|
||||
propertyID = nsCSSPropertyID::eCSSProperty_offset;
|
||||
} else if (propName.EqualsLiteral("cssFloat")) {
|
||||
property = nsCSSPropertyID::eCSSProperty_float;
|
||||
propertyID = nsCSSPropertyID::eCSSProperty_float;
|
||||
} else if (!propName.EqualsLiteral("offset") &&
|
||||
!propName.EqualsLiteral("float")) {
|
||||
property = nsCSSProps::LookupPropertyByIDLName(
|
||||
propertyID = nsCSSProps::LookupPropertyByIDLName(
|
||||
propName, CSSEnabledState::ForAllContent);
|
||||
}
|
||||
|
||||
if (KeyframeUtils::IsAnimatableProperty(property)) {
|
||||
AnimatedPropertyID* property;
|
||||
if (propertyID == eCSSPropertyExtra_variable) {
|
||||
// TODO(zrhoffman, bug 1811897) Add test coverage for removing the `--`
|
||||
// prefix here.
|
||||
property = new AnimatedPropertyID(
|
||||
NS_Atomize(Substring(propName, 2, propName.Length() - 2)));
|
||||
} else {
|
||||
property = new AnimatedPropertyID(propertyID);
|
||||
}
|
||||
|
||||
if (KeyframeUtils::IsAnimatableProperty(*property)) {
|
||||
AdditionalProperty* p = properties.AppendElement();
|
||||
p->mProperty = property;
|
||||
p->mProperty = *property;
|
||||
p->mJsidIndex = i;
|
||||
}
|
||||
}
|
||||
@@ -611,12 +669,11 @@ static bool AppendValueAsString(JSContext* aCx, nsTArray<nsCString>& aValues,
|
||||
}
|
||||
|
||||
static void ReportInvalidPropertyValueToConsole(
|
||||
nsCSSPropertyID aProperty, const nsACString& aInvalidPropertyValue,
|
||||
dom::Document* aDoc) {
|
||||
const AnimatedPropertyID& aProperty,
|
||||
const nsACString& aInvalidPropertyValue, dom::Document* aDoc) {
|
||||
AutoTArray<nsString, 2> params;
|
||||
params.AppendElement(NS_ConvertUTF8toUTF16(aInvalidPropertyValue));
|
||||
CopyASCIItoUTF16(nsCSSProps::GetStringValue(aProperty),
|
||||
*params.AppendElement());
|
||||
aProperty.ToString(*params.AppendElement());
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "Animation"_ns,
|
||||
aDoc, nsContentUtils::eDOM_PROPERTIES,
|
||||
"InvalidKeyframePropertyValue", params);
|
||||
@@ -633,7 +690,7 @@ static void ReportInvalidPropertyValueToConsole(
|
||||
* an invalid property value.
|
||||
*/
|
||||
static Maybe<PropertyValuePair> MakePropertyValuePair(
|
||||
nsCSSPropertyID aProperty, const nsACString& aStringValue,
|
||||
const AnimatedPropertyID& aProperty, const nsACString& aStringValue,
|
||||
dom::Document* aDocument) {
|
||||
MOZ_ASSERT(aDocument);
|
||||
Maybe<PropertyValuePair> result;
|
||||
@@ -641,11 +698,11 @@ static Maybe<PropertyValuePair> MakePropertyValuePair(
|
||||
ServoCSSParser::ParsingEnvironment env =
|
||||
ServoCSSParser::GetParsingEnvironment(aDocument);
|
||||
RefPtr<StyleLockedDeclarationBlock> servoDeclarationBlock =
|
||||
ServoCSSParser::ParseProperty(aProperty, aStringValue, env,
|
||||
ServoCSSParser::ParseProperty(aProperty.mID, aStringValue, env,
|
||||
StyleParsingMode::DEFAULT);
|
||||
|
||||
if (servoDeclarationBlock) {
|
||||
result.emplace(aProperty, std::move(servoDeclarationBlock));
|
||||
result.emplace(aProperty.mID, std::move(servoDeclarationBlock));
|
||||
} else {
|
||||
ReportInvalidPropertyValueToConsole(aProperty, aStringValue, aDocument);
|
||||
}
|
||||
@@ -814,7 +871,7 @@ static void BuildSegmentsFromValueEntries(
|
||||
// care to identify properties that lack a value at offset 0.0/1.0 and drops
|
||||
// those properties from |aResult|.
|
||||
|
||||
nsCSSPropertyID lastProperty = eCSSProperty_UNKNOWN;
|
||||
AnimatedPropertyID lastProperty(eCSSProperty_UNKNOWN);
|
||||
AnimationProperty* animationProperty = nullptr;
|
||||
|
||||
size_t i = 0, n = aEntries.Length();
|
||||
@@ -835,9 +892,9 @@ static void BuildSegmentsFromValueEntries(
|
||||
break;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aEntries[i].mProperty != eCSSProperty_UNKNOWN &&
|
||||
aEntries[i + 1].mProperty != eCSSProperty_UNKNOWN,
|
||||
"Each entry should specify a valid property");
|
||||
MOZ_ASSERT(
|
||||
aEntries[i].mProperty.IsValid() && aEntries[i + 1].mProperty.IsValid(),
|
||||
"Each entry should specify a valid property");
|
||||
|
||||
// No keyframe for this property at offset 0.
|
||||
if (aEntries[i].mProperty != lastProperty && aEntries[i].mOffset != 0.0f) {
|
||||
|
||||
@@ -16,6 +16,7 @@ struct JSContext;
|
||||
class JSObject;
|
||||
|
||||
namespace mozilla {
|
||||
struct AnimatedPropertyID;
|
||||
struct AnimationProperty;
|
||||
class ComputedStyle;
|
||||
|
||||
@@ -102,7 +103,7 @@ class KeyframeUtils {
|
||||
* if the property is animatable or not.
|
||||
* @return true if |aProperty| is animatable.
|
||||
*/
|
||||
static bool IsAnimatableProperty(nsCSSPropertyID aProperty);
|
||||
static bool IsAnimatableProperty(const AnimatedPropertyID& aProperty);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -3206,6 +3206,7 @@ nsDOMWindowUtils::GetUnanimatedComputedStyle(Element* aElement,
|
||||
nsCSSProps::IsShorthand(propertyID)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
// TODO(bug 1846516): Handle custom properties.
|
||||
|
||||
switch (aFlushType) {
|
||||
case FLUSH_NONE:
|
||||
|
||||
@@ -453,7 +453,9 @@ void AnimationInfo::AddAnimationForProperty(
|
||||
static_cast<float>(computedTiming.mIterationStart);
|
||||
animation->direction() = static_cast<uint8_t>(timing.Direction());
|
||||
animation->fillMode() = static_cast<uint8_t>(computedTiming.mFill);
|
||||
animation->property() = aProperty.mProperty;
|
||||
MOZ_ASSERT(!aProperty.mProperty.IsCustom(),
|
||||
"We don't animate custom properties in the compositor");
|
||||
animation->property() = aProperty.mProperty.mID;
|
||||
animation->playbackRate() =
|
||||
static_cast<float>(aAnimation->CurrentOrPendingPlaybackRate());
|
||||
animation->previousPlaybackRate() =
|
||||
@@ -478,7 +480,7 @@ void AnimationInfo::AddAnimationForProperty(
|
||||
aAnimation->GetEffect()->AsKeyframeEffect()->BaseStyle(
|
||||
aProperty.mProperty);
|
||||
if (!baseStyle.IsNull()) {
|
||||
SetAnimatable(aProperty.mProperty, baseStyle, aFrame, refBox,
|
||||
SetAnimatable(aProperty.mProperty.mID, baseStyle, aFrame, refBox,
|
||||
animation->baseStyle());
|
||||
} else {
|
||||
animation->baseStyle() = null_t();
|
||||
@@ -488,9 +490,9 @@ void AnimationInfo::AddAnimationForProperty(
|
||||
const AnimationPropertySegment& segment = aProperty.mSegments[segIdx];
|
||||
|
||||
AnimationSegment* animSegment = animation->segments().AppendElement();
|
||||
SetAnimatable(aProperty.mProperty, segment.mFromValue, aFrame, refBox,
|
||||
SetAnimatable(aProperty.mProperty.mID, segment.mFromValue, aFrame, refBox,
|
||||
animSegment->startState());
|
||||
SetAnimatable(aProperty.mProperty, segment.mToValue, aFrame, refBox,
|
||||
SetAnimatable(aProperty.mProperty.mID, segment.mToValue, aFrame, refBox,
|
||||
animSegment->endState());
|
||||
|
||||
animSegment->startPortion() = segment.mFromKey;
|
||||
@@ -541,14 +543,16 @@ GroupAnimationsByProperty(const nsTArray<RefPtr<dom::Animation>>& aAnimations,
|
||||
const dom::KeyframeEffect* effect = anim->GetEffect()->AsKeyframeEffect();
|
||||
MOZ_ASSERT(effect);
|
||||
for (const AnimationProperty& property : effect->Properties()) {
|
||||
if (!aPropertySet.HasProperty(property.mProperty)) {
|
||||
// TODO(zrhoffman, bug 1869475): Handle custom properties
|
||||
if (!aPropertySet.HasProperty(property.mProperty.mID)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto animsForPropertyPtr = groupedAnims.lookupForAdd(property.mProperty);
|
||||
auto animsForPropertyPtr =
|
||||
groupedAnims.lookupForAdd(property.mProperty.mID);
|
||||
if (!animsForPropertyPtr) {
|
||||
DebugOnly<bool> rv =
|
||||
groupedAnims.add(animsForPropertyPtr, property.mProperty,
|
||||
groupedAnims.add(animsForPropertyPtr, property.mProperty.mID,
|
||||
nsTArray<RefPtr<dom::Animation>>());
|
||||
MOZ_ASSERT(rv, "Should have enough memory");
|
||||
}
|
||||
|
||||
@@ -416,15 +416,15 @@ static Array<MinAndMaxScale, 2> GetMinAndMaxScaleForAnimationProperty(
|
||||
anim->GetEffect() ? anim->GetEffect()->AsKeyframeEffect() : nullptr;
|
||||
MOZ_ASSERT(effect, "A playing animation should have a keyframe effect");
|
||||
for (const AnimationProperty& prop : effect->Properties()) {
|
||||
if (prop.mProperty != eCSSProperty_transform &&
|
||||
prop.mProperty != eCSSProperty_scale) {
|
||||
if (prop.mProperty.mID != eCSSProperty_transform &&
|
||||
prop.mProperty.mID != eCSSProperty_scale) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 0: eCSSProperty_transform.
|
||||
// 1: eCSSProperty_scale.
|
||||
MinAndMaxScale& scales =
|
||||
minAndMaxScales[prop.mProperty == eCSSProperty_transform ? 0 : 1];
|
||||
minAndMaxScales[prop.mProperty.mID == eCSSProperty_transform ? 0 : 1];
|
||||
|
||||
// We need to factor in the scale of the base style if the base style
|
||||
// will be used on the compositor.
|
||||
|
||||
63
layout/style/AnimatedPropertyID.h
Normal file
63
layout/style/AnimatedPropertyID.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_AnimatedPropertyID_h
|
||||
#define mozilla_AnimatedPropertyID_h
|
||||
|
||||
#include "nsCSSPropertyID.h"
|
||||
#include "nsCSSProps.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/ServoBindings.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct AnimatedPropertyID {
|
||||
explicit AnimatedPropertyID(nsCSSPropertyID aProperty) : mID(aProperty) {
|
||||
MOZ_ASSERT(aProperty != eCSSPropertyExtra_variable,
|
||||
"Cannot create an AnimatedPropertyID from only a "
|
||||
"eCSSPropertyExtra_variable.");
|
||||
}
|
||||
|
||||
explicit AnimatedPropertyID(RefPtr<nsAtom> aCustomName)
|
||||
: mID(eCSSPropertyExtra_variable), mCustomName(std::move(aCustomName)) {}
|
||||
|
||||
nsCSSPropertyID mID = eCSSProperty_UNKNOWN;
|
||||
RefPtr<nsAtom> mCustomName;
|
||||
|
||||
bool IsCustom() const { return mID == eCSSPropertyExtra_variable; }
|
||||
bool operator==(const AnimatedPropertyID& aOther) const {
|
||||
return mID == aOther.mID &&
|
||||
(!IsCustom() || mCustomName == aOther.mCustomName);
|
||||
}
|
||||
bool operator!=(const AnimatedPropertyID& aOther) const {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
bool IsValid() const {
|
||||
if (mID == eCSSProperty_UNKNOWN) {
|
||||
return false;
|
||||
}
|
||||
return IsCustom() == !!mCustomName;
|
||||
}
|
||||
|
||||
void ToString(nsAString& aString) const {
|
||||
if (IsCustom()) {
|
||||
MOZ_ASSERT(mCustomName, "Custom property should have a name");
|
||||
mCustomName->ToString(aString);
|
||||
} else {
|
||||
aString.Assign(NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(mID)));
|
||||
}
|
||||
}
|
||||
|
||||
HashNumber Hash() const {
|
||||
HashNumber hash = mCustomName ? mCustomName->hash() : 0;
|
||||
return AddToHash(hash, mID);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_AnimatedPropertyID_h
|
||||
150
layout/style/AnimatedPropertyIDSet.h
Normal file
150
layout/style/AnimatedPropertyIDSet.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_AnimatedPropertyIDSet_h
|
||||
#define mozilla_AnimatedPropertyIDSet_h
|
||||
|
||||
#include "mozilla/ServoBindings.h"
|
||||
|
||||
#include "AnimatedPropertyID.h"
|
||||
#include "nsTHashSet.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class AnimatedPropertyIDSet {
|
||||
public:
|
||||
void AddProperty(const AnimatedPropertyID& aProperty) {
|
||||
if (aProperty.IsCustom()) {
|
||||
mCustomNames.Insert(aProperty.mCustomName);
|
||||
} else {
|
||||
mIDs.AddProperty(aProperty.mID);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveProperty(const AnimatedPropertyID& aProperty) {
|
||||
if (aProperty.IsCustom()) {
|
||||
mCustomNames.Remove(aProperty.mCustomName);
|
||||
} else {
|
||||
mIDs.RemoveProperty(aProperty.mID);
|
||||
}
|
||||
}
|
||||
|
||||
bool HasProperty(const AnimatedPropertyID& aProperty) const {
|
||||
if (aProperty.IsCustom()) {
|
||||
return mCustomNames.Contains(aProperty.mCustomName);
|
||||
}
|
||||
return mIDs.HasProperty(aProperty.mID);
|
||||
}
|
||||
|
||||
bool Intersects(const nsCSSPropertyIDSet& aIDs) const {
|
||||
return mIDs.Intersects(aIDs);
|
||||
}
|
||||
|
||||
bool IsSubsetOf(const AnimatedPropertyIDSet& aOther) const {
|
||||
if (!mIDs.IsSubsetOf(aOther.mIDs) ||
|
||||
mCustomNames.Count() > aOther.mCustomNames.Count()) {
|
||||
return false;
|
||||
}
|
||||
for (const auto& name : mCustomNames) {
|
||||
if (!aOther.mCustomNames.Contains(name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddProperties(const AnimatedPropertyIDSet& aOther) {
|
||||
mIDs |= aOther.mIDs;
|
||||
for (const auto& name : aOther.mCustomNames) {
|
||||
mCustomNames.Insert(name);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
using CustomNameSet = nsTHashSet<RefPtr<nsAtom>>;
|
||||
|
||||
public:
|
||||
// Iterator for use in range-based for loops
|
||||
class Iterator {
|
||||
public:
|
||||
Iterator(Iterator&& aOther)
|
||||
: mPropertySet(aOther.mPropertySet),
|
||||
mIDIterator(std::move(aOther.mIDIterator)),
|
||||
mCustomNameIterator(std::move(aOther.mCustomNameIterator)),
|
||||
mPropertyID(eCSSProperty_UNKNOWN) {}
|
||||
Iterator() = delete;
|
||||
Iterator(const Iterator&) = delete;
|
||||
Iterator& operator=(const Iterator&) = delete;
|
||||
Iterator& operator=(const Iterator&&) = delete;
|
||||
|
||||
static Iterator BeginIterator(const AnimatedPropertyIDSet& aPropertySet) {
|
||||
return Iterator(aPropertySet, aPropertySet.mIDs.begin(),
|
||||
aPropertySet.mCustomNames.begin());
|
||||
}
|
||||
|
||||
static Iterator EndIterator(const AnimatedPropertyIDSet& aPropertySet) {
|
||||
return Iterator(aPropertySet, aPropertySet.mIDs.end(),
|
||||
aPropertySet.mCustomNames.end());
|
||||
}
|
||||
|
||||
bool operator!=(const Iterator& aOther) const {
|
||||
return mIDIterator != aOther.mIDIterator ||
|
||||
mCustomNameIterator != aOther.mCustomNameIterator;
|
||||
}
|
||||
|
||||
Iterator& operator++() {
|
||||
MOZ_ASSERT(mIDIterator != mPropertySet.mIDs.end() ||
|
||||
mCustomNameIterator != mPropertySet.mCustomNames.end(),
|
||||
"Should not iterate beyond end");
|
||||
if (mIDIterator != mPropertySet.mIDs.end()) {
|
||||
++mIDIterator;
|
||||
} else {
|
||||
++mCustomNameIterator;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
AnimatedPropertyID operator*() {
|
||||
if (mIDIterator != mPropertySet.mIDs.end()) {
|
||||
mPropertyID.mID = *mIDIterator;
|
||||
mPropertyID.mCustomName = nullptr;
|
||||
} else if (mCustomNameIterator != mPropertySet.mCustomNames.end()) {
|
||||
mPropertyID.mID = eCSSPropertyExtra_variable;
|
||||
mPropertyID.mCustomName = *mCustomNameIterator;
|
||||
} else {
|
||||
MOZ_ASSERT_UNREACHABLE("Should not dereference beyond end");
|
||||
mPropertyID.mID = eCSSProperty_UNKNOWN;
|
||||
mPropertyID.mCustomName = nullptr;
|
||||
}
|
||||
return mPropertyID;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit Iterator(const AnimatedPropertyIDSet& aPropertySet,
|
||||
nsCSSPropertyIDSet::Iterator aIDIterator,
|
||||
CustomNameSet::const_iterator aCustomNameIterator)
|
||||
: mPropertySet(aPropertySet),
|
||||
mIDIterator(std::move(aIDIterator)),
|
||||
mCustomNameIterator(std::move(aCustomNameIterator)),
|
||||
mPropertyID(eCSSProperty_UNKNOWN) {}
|
||||
|
||||
const AnimatedPropertyIDSet& mPropertySet;
|
||||
nsCSSPropertyIDSet::Iterator mIDIterator;
|
||||
CustomNameSet::const_iterator mCustomNameIterator;
|
||||
AnimatedPropertyID mPropertyID;
|
||||
};
|
||||
|
||||
Iterator begin() const { return Iterator::BeginIterator(*this); }
|
||||
Iterator end() const { return Iterator::EndIterator(*this); }
|
||||
|
||||
private:
|
||||
nsCSSPropertyIDSet mIDs;
|
||||
CustomNameSet mCustomNames;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_AnimatedPropertyIDSet_h
|
||||
@@ -651,7 +651,7 @@ static CSSTransition* GetCurrentTransitionAt(const Element* aElement,
|
||||
nsCSSPropertyID Gecko_ElementTransitions_PropertyAt(const Element* aElement,
|
||||
size_t aIndex) {
|
||||
CSSTransition* transition = GetCurrentTransitionAt(aElement, aIndex);
|
||||
return transition ? transition->TransitionProperty()
|
||||
return transition ? transition->TransitionProperty().mID
|
||||
: nsCSSPropertyID::eCSSProperty_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/AnimatedPropertyID.h"
|
||||
#include "mozilla/ComputedStyle.h"
|
||||
#include "nsComputedDOMStyle.h"
|
||||
#include "nsCSSPseudoElements.h"
|
||||
@@ -155,13 +156,13 @@ MatrixScales AnimationValue::GetScaleValue(const nsIFrame* aFrame) const {
|
||||
}
|
||||
|
||||
void AnimationValue::SerializeSpecifiedValue(
|
||||
nsCSSPropertyID aProperty, const StylePerDocumentStyleData* aRawData,
|
||||
nsACString& aString) const {
|
||||
const AnimatedPropertyID& aProperty,
|
||||
const StylePerDocumentStyleData* aRawData, nsACString& aString) const {
|
||||
MOZ_ASSERT(mServo);
|
||||
Servo_AnimationValue_Serialize(mServo, aProperty, aRawData, &aString);
|
||||
Servo_AnimationValue_Serialize(mServo, aProperty.mID, aRawData, &aString);
|
||||
}
|
||||
|
||||
bool AnimationValue::IsInterpolableWith(nsCSSPropertyID aProperty,
|
||||
bool AnimationValue::IsInterpolableWith(const AnimatedPropertyID& aProperty,
|
||||
const AnimationValue& aToValue) const {
|
||||
if (IsNull() || aToValue.IsNull()) {
|
||||
return false;
|
||||
|
||||
@@ -43,6 +43,7 @@ class Animatable;
|
||||
|
||||
enum class PseudoStyleType : uint8_t;
|
||||
struct PropertyStyleAnimationValuePair;
|
||||
struct AnimatedPropertyID;
|
||||
|
||||
struct AnimationValue {
|
||||
explicit AnimationValue(const RefPtr<StyleAnimationValue>& aValue)
|
||||
@@ -91,12 +92,12 @@ struct AnimationValue {
|
||||
mozilla::gfx::MatrixScales GetScaleValue(const nsIFrame* aFrame) const;
|
||||
|
||||
// Uncompute this AnimationValue and then serialize it.
|
||||
void SerializeSpecifiedValue(nsCSSPropertyID aProperty,
|
||||
void SerializeSpecifiedValue(const AnimatedPropertyID& aProperty,
|
||||
const StylePerDocumentStyleData* aRawData,
|
||||
nsACString& aString) const;
|
||||
|
||||
// Check if |*this| and |aToValue| can be interpolated.
|
||||
bool IsInterpolableWith(nsCSSPropertyID aProperty,
|
||||
bool IsInterpolableWith(const AnimatedPropertyID& aProperty,
|
||||
const AnimationValue& aToValue) const;
|
||||
|
||||
// Compute the distance between *this and aOther.
|
||||
|
||||
@@ -22,6 +22,9 @@ with Files("nsDOM*"):
|
||||
with Files("AnimationCollection.*"):
|
||||
BUG_COMPONENT = ("Core", "CSS Transitions and Animations")
|
||||
|
||||
with Files("AnimatedPropertyID*"):
|
||||
BUG_COMPONENT = ("Core", "CSS Transitions and Animations")
|
||||
|
||||
with Files("AnimationCommon.*"):
|
||||
BUG_COMPONENT = ("Core", "CSS Transitions and Animations")
|
||||
|
||||
@@ -67,6 +70,8 @@ EXPORTS += [
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
"!ServoCSSPropList.h",
|
||||
"AnimatedPropertyID.h",
|
||||
"AnimatedPropertyIDSet.h",
|
||||
"AnimationCollection.h",
|
||||
"AttributeStyles.h",
|
||||
"CachedInheritingStyles.h",
|
||||
|
||||
@@ -67,9 +67,12 @@ class nsCSSProps {
|
||||
static bool IsCustomPropertyName(const nsACString& aProperty);
|
||||
|
||||
static bool IsShorthand(nsCSSPropertyID aProperty) {
|
||||
if (aProperty == eCSSPropertyExtra_variable) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT,
|
||||
"out of range");
|
||||
return (aProperty >= eCSSProperty_COUNT_no_shorthands);
|
||||
return aProperty >= eCSSProperty_COUNT_no_shorthands;
|
||||
}
|
||||
|
||||
// Same but for @font-face descriptors
|
||||
|
||||
@@ -1661,6 +1661,9 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset {
|
||||
nsCSSPropertyID GetTransitionProperty(uint32_t aIndex) const {
|
||||
return mTransitions[aIndex % mTransitionPropertyCount].GetProperty();
|
||||
}
|
||||
nsAtom* GetTransitionUnknownProperty(uint32_t aIndex) const {
|
||||
return mTransitions[aIndex % mTransitionPropertyCount].GetUnknownProperty();
|
||||
}
|
||||
const mozilla::StyleTime& GetTransitionDelay(uint32_t aIndex) const {
|
||||
return mTransitions[aIndex % mTransitionDelayCount].GetDelay();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "nsAnimationManager.h"
|
||||
|
||||
#include "nsIContent.h"
|
||||
#include "AnimatedPropertyID.h"
|
||||
#include "AnimatedPropertyIDSet.h"
|
||||
#include "mozilla/ComputedStyle.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "nsCSSPropertyIDSet.h"
|
||||
@@ -60,14 +62,19 @@ bool nsTransitionManager::UpdateTransitions(dom::Element* aElement,
|
||||
// transition-property, and then execute |aHandler| on the expanded longhand.
|
||||
// |aHandler| should be a lamda function which accepts nsCSSPropertyID.
|
||||
template <typename T>
|
||||
static void ExpandTransitionProperty(nsCSSPropertyID aProperty, T aHandler) {
|
||||
static void ExpandTransitionProperty(nsCSSPropertyID aProperty,
|
||||
nsAtom* aCustomName, T aHandler) {
|
||||
if (aProperty == eCSSPropertyExtra_no_properties ||
|
||||
aProperty == eCSSPropertyExtra_variable ||
|
||||
aProperty == eCSSProperty_UNKNOWN) {
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
if (aProperty == eCSSPropertyExtra_variable) {
|
||||
AnimatedPropertyID property(aCustomName);
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME(emilio): This should probably just use the "all" shorthand id, and we
|
||||
// should probably remove eCSSPropertyExtra_all_properties.
|
||||
if (aProperty == eCSSPropertyExtra_all_properties) {
|
||||
@@ -76,15 +83,18 @@ static void ExpandTransitionProperty(nsCSSPropertyID aProperty, T aHandler) {
|
||||
if (!nsCSSProps::IsEnabled(p, CSSEnabledState::ForAllContent)) {
|
||||
continue;
|
||||
}
|
||||
aHandler(p);
|
||||
AnimatedPropertyID property(p);
|
||||
aHandler(property);
|
||||
}
|
||||
} else if (nsCSSProps::IsShorthand(aProperty)) {
|
||||
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subprop, aProperty,
|
||||
CSSEnabledState::ForAllContent) {
|
||||
aHandler(*subprop);
|
||||
AnimatedPropertyID property(*subprop);
|
||||
aHandler(property);
|
||||
}
|
||||
} else {
|
||||
aHandler(aProperty);
|
||||
AnimatedPropertyID property(aProperty);
|
||||
aHandler(property);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +110,7 @@ bool nsTransitionManager::DoUpdateTransitions(
|
||||
// 'transition-property' on down, and later ones will override earlier
|
||||
// ones (tracked using |propertiesChecked|).
|
||||
bool startedAny = false;
|
||||
nsCSSPropertyIDSet propertiesChecked;
|
||||
AnimatedPropertyIDSet propertiesChecked;
|
||||
for (uint32_t i = aStyle.mTransitionPropertyCount; i--;) {
|
||||
// We're not going to look at any further transitions, so we can just avoid
|
||||
// looking at this if we know it will not start any transitions.
|
||||
@@ -109,7 +119,8 @@ bool nsTransitionManager::DoUpdateTransitions(
|
||||
}
|
||||
|
||||
ExpandTransitionProperty(
|
||||
aStyle.GetTransitionProperty(i), [&](nsCSSPropertyID aProperty) {
|
||||
aStyle.GetTransitionProperty(i), aStyle.GetTransitionUnknownProperty(i),
|
||||
[&](const AnimatedPropertyID& aProperty) {
|
||||
// We might have something to transition. See if any of the
|
||||
// properties in question changed and are animatable.
|
||||
startedAny |= ConsiderInitiatingTransition(
|
||||
@@ -128,13 +139,16 @@ bool nsTransitionManager::DoUpdateTransitions(
|
||||
if (aElementTransitions) {
|
||||
bool checkProperties =
|
||||
aStyle.GetTransitionProperty(0) != eCSSPropertyExtra_all_properties;
|
||||
nsCSSPropertyIDSet allTransitionProperties;
|
||||
AnimatedPropertyIDSet allTransitionProperties;
|
||||
if (checkProperties) {
|
||||
for (uint32_t i = aStyle.mTransitionPropertyCount; i-- != 0;) {
|
||||
ExpandTransitionProperty(
|
||||
aStyle.GetTransitionProperty(i), [&](nsCSSPropertyID aProperty) {
|
||||
allTransitionProperties.AddProperty(
|
||||
nsCSSProps::Physicalize(aProperty, aNewStyle));
|
||||
aStyle.GetTransitionProperty(i),
|
||||
aStyle.GetTransitionUnknownProperty(i),
|
||||
[&](const AnimatedPropertyID& aProperty) {
|
||||
AnimatedPropertyID property = aProperty;
|
||||
property.mID = nsCSSProps::Physicalize(aProperty.mID, aNewStyle);
|
||||
allTransitionProperties.AddProperty(aProperty);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -146,7 +160,7 @@ bool nsTransitionManager::DoUpdateTransitions(
|
||||
do {
|
||||
--i;
|
||||
CSSTransition* anim = animations[i];
|
||||
const nsCSSPropertyID property = anim->TransitionProperty();
|
||||
const AnimatedPropertyID& property = anim->TransitionProperty();
|
||||
if (
|
||||
// Properties no longer in `transition-property`.
|
||||
(checkProperties && !allTransitionProperties.HasProperty(property)) ||
|
||||
@@ -155,7 +169,7 @@ bool nsTransitionManager::DoUpdateTransitions(
|
||||
// or because the new value is not interpolable); a new transition
|
||||
// would have anim->ToValue() matching currentValue.
|
||||
!Servo_ComputedValues_TransitionValueMatches(
|
||||
&aNewStyle, property, anim->ToValue().mServo.get())) {
|
||||
&aNewStyle, property.mID, anim->ToValue().mServo.get())) {
|
||||
// Stop the transition.
|
||||
DoCancelTransition(aElement, aPseudoType, aElementTransitions, i);
|
||||
}
|
||||
@@ -165,7 +179,8 @@ bool nsTransitionManager::DoUpdateTransitions(
|
||||
return startedAny;
|
||||
}
|
||||
|
||||
static Keyframe& AppendKeyframe(double aOffset, nsCSSPropertyID aProperty,
|
||||
static Keyframe& AppendKeyframe(double aOffset,
|
||||
const AnimatedPropertyID& aProperty,
|
||||
AnimationValue&& aValue,
|
||||
nsTArray<Keyframe>& aKeyframes) {
|
||||
Keyframe& frame = *aKeyframes.AppendElement();
|
||||
@@ -174,13 +189,13 @@ static Keyframe& AppendKeyframe(double aOffset, nsCSSPropertyID aProperty,
|
||||
RefPtr<StyleLockedDeclarationBlock> decl =
|
||||
Servo_AnimationValue_Uncompute(aValue.mServo).Consume();
|
||||
frame.mPropertyValues.AppendElement(
|
||||
PropertyValuePair(aProperty, std::move(decl)));
|
||||
PropertyValuePair(aProperty.mID, std::move(decl)));
|
||||
return frame;
|
||||
}
|
||||
|
||||
static nsTArray<Keyframe> GetTransitionKeyframes(nsCSSPropertyID aProperty,
|
||||
AnimationValue&& aStartValue,
|
||||
AnimationValue&& aEndValue) {
|
||||
static nsTArray<Keyframe> GetTransitionKeyframes(
|
||||
const AnimatedPropertyID& aProperty, AnimationValue&& aStartValue,
|
||||
AnimationValue&& aEndValue) {
|
||||
nsTArray<Keyframe> keyframes(2);
|
||||
|
||||
AppendKeyframe(0.0, aProperty, std::move(aStartValue), keyframes);
|
||||
@@ -189,8 +204,12 @@ static nsTArray<Keyframe> GetTransitionKeyframes(nsCSSPropertyID aProperty,
|
||||
return keyframes;
|
||||
}
|
||||
|
||||
static bool IsTransitionable(nsCSSPropertyID aProperty) {
|
||||
return Servo_Property_IsTransitionable(aProperty);
|
||||
static bool IsTransitionable(const AnimatedPropertyID& aProperty) {
|
||||
// TODO(bug 1846516): handle custom property.
|
||||
if (aProperty.IsCustom()) {
|
||||
return false;
|
||||
}
|
||||
return Servo_Property_IsTransitionable(aProperty.mID);
|
||||
}
|
||||
|
||||
static Maybe<CSSTransition::ReplacedTransitionProperties>
|
||||
@@ -240,30 +259,34 @@ GetReplacedTransitionProperties(const CSSTransition* aTransition,
|
||||
}
|
||||
|
||||
bool nsTransitionManager::ConsiderInitiatingTransition(
|
||||
nsCSSPropertyID aProperty, const nsStyleUIReset& aStyle,
|
||||
const AnimatedPropertyID& aProperty, const nsStyleUIReset& aStyle,
|
||||
uint32_t transitionIdx, dom::Element* aElement, PseudoStyleType aPseudoType,
|
||||
CSSTransitionCollection*& aElementTransitions,
|
||||
const ComputedStyle& aOldStyle, const ComputedStyle& aNewStyle,
|
||||
nsCSSPropertyIDSet& aPropertiesChecked) {
|
||||
AnimatedPropertyIDSet& aPropertiesChecked) {
|
||||
// IsShorthand itself will assert if aProperty is not a property.
|
||||
MOZ_ASSERT(!nsCSSProps::IsShorthand(aProperty), "property out of range");
|
||||
MOZ_ASSERT(aProperty.IsCustom() || !nsCSSProps::IsShorthand(aProperty.mID),
|
||||
"property out of range");
|
||||
NS_ASSERTION(
|
||||
!aElementTransitions || &aElementTransitions->mElement == aElement,
|
||||
"Element mismatch");
|
||||
|
||||
aProperty = nsCSSProps::Physicalize(aProperty, aNewStyle);
|
||||
AnimatedPropertyID property = aProperty;
|
||||
if (!property.IsCustom()) {
|
||||
property.mID = nsCSSProps::Physicalize(property.mID, aNewStyle);
|
||||
}
|
||||
|
||||
// A later item in transition-property already specified a transition for
|
||||
// this property, so we ignore this one.
|
||||
//
|
||||
// See http://lists.w3.org/Archives/Public/www-style/2009Aug/0109.html .
|
||||
if (aPropertiesChecked.HasProperty(aProperty)) {
|
||||
if (aPropertiesChecked.HasProperty(property)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aPropertiesChecked.AddProperty(aProperty);
|
||||
aPropertiesChecked.AddProperty(property);
|
||||
|
||||
if (!IsTransitionable(aProperty)) {
|
||||
if (!IsTransitionable(property)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -287,7 +310,7 @@ bool nsTransitionManager::ConsiderInitiatingTransition(
|
||||
const OwningCSSTransitionPtrArray& animations =
|
||||
aElementTransitions->mAnimations;
|
||||
for (size_t i = 0, i_end = animations.Length(); i < i_end; ++i) {
|
||||
if (animations[i]->TransitionProperty() == aProperty) {
|
||||
if (animations[i]->TransitionProperty() == property) {
|
||||
currentIndex = i;
|
||||
return animations[i];
|
||||
}
|
||||
@@ -298,7 +321,7 @@ bool nsTransitionManager::ConsiderInitiatingTransition(
|
||||
AnimationValue startValue, endValue;
|
||||
const StyleShouldTransitionResult result =
|
||||
Servo_ComputedValues_ShouldTransition(
|
||||
&aOldStyle, &aNewStyle, aProperty,
|
||||
&aOldStyle, &aNewStyle, aProperty.mID,
|
||||
oldTransition ? oldTransition->ToValue().mServo.get() : nullptr,
|
||||
&startValue.mServo, &endValue.mServo);
|
||||
|
||||
@@ -389,7 +412,7 @@ bool nsTransitionManager::ConsiderInitiatingTransition(
|
||||
}
|
||||
|
||||
RefPtr<CSSTransition> transition = DoCreateTransition(
|
||||
aProperty, aElement, aPseudoType, aNewStyle, aElementTransitions,
|
||||
property, aElement, aPseudoType, aNewStyle, aElementTransitions,
|
||||
std::move(timing), std::move(startValue), std::move(endValue),
|
||||
std::move(startForReversingTest), reversePortion);
|
||||
if (!transition) {
|
||||
@@ -400,7 +423,7 @@ bool nsTransitionManager::ConsiderInitiatingTransition(
|
||||
#ifdef DEBUG
|
||||
for (size_t i = 0, i_end = transitions.Length(); i < i_end; ++i) {
|
||||
MOZ_ASSERT(
|
||||
i == currentIndex || transitions[i]->TransitionProperty() != aProperty,
|
||||
i == currentIndex || transitions[i]->TransitionProperty() != property,
|
||||
"duplicate transitions for property");
|
||||
}
|
||||
#endif
|
||||
@@ -436,7 +459,7 @@ bool nsTransitionManager::ConsiderInitiatingTransition(
|
||||
}
|
||||
|
||||
already_AddRefed<CSSTransition> nsTransitionManager::DoCreateTransition(
|
||||
nsCSSPropertyID aProperty, dom::Element* aElement,
|
||||
const AnimatedPropertyID& aProperty, dom::Element* aElement,
|
||||
PseudoStyleType aPseudoType, const mozilla::ComputedStyle& aNewStyle,
|
||||
CSSTransitionCollection*& aElementTransitions, TimingParams&& aTiming,
|
||||
AnimationValue&& aStartValue, AnimationValue&& aEndValue,
|
||||
@@ -457,7 +480,7 @@ already_AddRefed<CSSTransition> nsTransitionManager::DoCreateTransition(
|
||||
}
|
||||
|
||||
RefPtr<CSSTransition> animation =
|
||||
new CSSTransition(mPresContext->Document()->GetScopeObject());
|
||||
new CSSTransition(mPresContext->Document()->GetScopeObject(), aProperty);
|
||||
animation->SetOwningElement(OwningElementRef(*aElement, aPseudoType));
|
||||
animation->SetTimelineNoUpdate(timeline);
|
||||
animation->SetCreationSequence(
|
||||
|
||||
@@ -18,6 +18,7 @@ class nsCSSPropertyIDSet;
|
||||
struct nsStyleUIReset;
|
||||
|
||||
namespace mozilla {
|
||||
class AnimatedPropertyIDSet;
|
||||
class ComputedStyle;
|
||||
enum class PseudoStyleType : uint8_t;
|
||||
} // namespace mozilla
|
||||
@@ -60,17 +61,17 @@ class nsTransitionManager final
|
||||
|
||||
// Returns whether the transition actually started.
|
||||
bool ConsiderInitiatingTransition(
|
||||
nsCSSPropertyID aProperty, const nsStyleUIReset& aStyle,
|
||||
const mozilla::AnimatedPropertyID&, const nsStyleUIReset& aStyle,
|
||||
uint32_t transitionIdx, mozilla::dom::Element* aElement,
|
||||
mozilla::PseudoStyleType aPseudoType,
|
||||
CSSTransitionCollection*& aElementTransitions,
|
||||
const mozilla::ComputedStyle& aOldStyle,
|
||||
const mozilla::ComputedStyle& aNewStyle,
|
||||
nsCSSPropertyIDSet& aPropertiesChecked);
|
||||
mozilla::AnimatedPropertyIDSet& aPropertiesChecked);
|
||||
|
||||
already_AddRefed<mozilla::dom::CSSTransition> DoCreateTransition(
|
||||
nsCSSPropertyID aProperty, mozilla::dom::Element* aElement,
|
||||
mozilla::PseudoStyleType aPseudoType,
|
||||
const mozilla::AnimatedPropertyID& aProperty,
|
||||
mozilla::dom::Element* aElement, mozilla::PseudoStyleType aPseudoType,
|
||||
const mozilla::ComputedStyle& aNewStyle,
|
||||
CSSTransitionCollection*& aElementTransitions,
|
||||
mozilla::TimingParams&& aTiming, mozilla::AnimationValue&& aStartValue,
|
||||
|
||||
Reference in New Issue
Block a user