forked from mirrors/gecko-dev
However, We don't lookup the object of view-timeline-name for CSS animations until we finish its implementation in the patch series. Note: this patch assumes `view-timeline-inset` is not animatable. We will fix it in Bug 1817073. Differential Revision: https://phabricator.services.mozilla.com/D170001
262 lines
8.9 KiB
C++
262 lines
8.9 KiB
C++
/* -*- 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_ElementAnimationData_h
|
|
#define mozilla_ElementAnimationData_h
|
|
|
|
#include "mozilla/UniquePtr.h"
|
|
#include "mozilla/PseudoStyleType.h"
|
|
|
|
class nsCycleCollectionTraversalCallback;
|
|
|
|
namespace mozilla {
|
|
enum class PseudoStyleType : uint8_t;
|
|
class EffectSet;
|
|
template <typename Animation>
|
|
class AnimationCollection;
|
|
template <typename TimelineType>
|
|
class TimelineCollection;
|
|
namespace dom {
|
|
class Element;
|
|
class CSSAnimation;
|
|
class CSSTransition;
|
|
class ProgressTimelineScheduler;
|
|
class ScrollTimeline;
|
|
class ViewTimeline;
|
|
} // namespace dom
|
|
using CSSAnimationCollection = AnimationCollection<dom::CSSAnimation>;
|
|
using CSSTransitionCollection = AnimationCollection<dom::CSSTransition>;
|
|
using ScrollTimelineCollection = TimelineCollection<dom::ScrollTimeline>;
|
|
using ViewTimelineCollection = TimelineCollection<dom::ViewTimeline>;
|
|
|
|
// The animation data for a given element (and its pseudo-elements).
|
|
class ElementAnimationData {
|
|
struct PerElementOrPseudoData {
|
|
UniquePtr<EffectSet> mEffectSet;
|
|
UniquePtr<CSSAnimationCollection> mAnimations;
|
|
UniquePtr<CSSTransitionCollection> mTransitions;
|
|
|
|
// Note: scroll-timeline-name is applied to elements which could be
|
|
// scroll containers, or replaced elements. view-timeline-name is applied to
|
|
// all elements. However, the named timeline is referenceable in
|
|
// animation-timeline by the tree order scope.
|
|
// Spec: https://drafts.csswg.org/scroll-animations-1/#timeline-scope.
|
|
//
|
|
// So it should be fine to create timeline objects only on the elements and
|
|
// pseudo elements which support animations.
|
|
UniquePtr<ScrollTimelineCollection> mScrollTimelines;
|
|
UniquePtr<ViewTimelineCollection> mViewTimelines;
|
|
|
|
// This is different from |mScrollTimelines|. We use this to schedule all
|
|
// scroll-driven animations (which use anonymous/named scroll timelines or
|
|
// anonymous/name view timelines) for a specific scroll source (which is the
|
|
// element with nsIScrollableFrame).
|
|
//
|
|
// TimelineCollection owns and manages the named progress timeline generated
|
|
// by specifying scroll-timeline-name property and view-timeline-name
|
|
// property on this element. However, the anonymous progress timelines (e.g.
|
|
// animation-timeline:scroll()) are owned by Animation objects only.
|
|
//
|
|
// Note:
|
|
// 1. For named scroll timelines. The element which specifies
|
|
// scroll-timeline-name is the scroll source. However, for named view
|
|
// timelines, the element which specifies view-timeline-name may not be
|
|
// the scroll source because we use its nearest scroll container as the
|
|
// scroll source.
|
|
// 2. For anonymous progress timelines, we don't keep their timeline obejcts
|
|
// in TimelineCollection.
|
|
// So, per 1) and 2), we use |mProgressTimelineScheduler| for the scroll
|
|
// source element to schedule scroll-driven animations.
|
|
UniquePtr<dom::ProgressTimelineScheduler> mProgressTimelineScheduler;
|
|
|
|
PerElementOrPseudoData();
|
|
~PerElementOrPseudoData();
|
|
|
|
EffectSet& DoEnsureEffectSet();
|
|
CSSTransitionCollection& DoEnsureTransitions(dom::Element&,
|
|
PseudoStyleType);
|
|
CSSAnimationCollection& DoEnsureAnimations(dom::Element&, PseudoStyleType);
|
|
ScrollTimelineCollection& DoEnsureScrollTimelines(dom::Element&,
|
|
PseudoStyleType);
|
|
ViewTimelineCollection& DoEnsureViewTimelines(dom::Element&,
|
|
PseudoStyleType);
|
|
dom::ProgressTimelineScheduler& DoEnsureProgressTimelineScheduler(
|
|
dom::Element&, PseudoStyleType);
|
|
|
|
void DoClearEffectSet();
|
|
void DoClearTransitions();
|
|
void DoClearAnimations();
|
|
void DoClearScrollTimelines();
|
|
void DoClearViewTimelines();
|
|
void DoClearProgressTimelineScheduler();
|
|
|
|
void Traverse(nsCycleCollectionTraversalCallback&);
|
|
};
|
|
|
|
PerElementOrPseudoData mElementData;
|
|
|
|
// TODO(emilio): Maybe this should be a hash map eventually, once we allow
|
|
// animating all pseudo-elements.
|
|
PerElementOrPseudoData mBeforeData;
|
|
PerElementOrPseudoData mAfterData;
|
|
PerElementOrPseudoData mMarkerData;
|
|
|
|
const PerElementOrPseudoData& DataFor(PseudoStyleType aType) const {
|
|
switch (aType) {
|
|
case PseudoStyleType::NotPseudo:
|
|
break;
|
|
case PseudoStyleType::before:
|
|
return mBeforeData;
|
|
case PseudoStyleType::after:
|
|
return mAfterData;
|
|
case PseudoStyleType::marker:
|
|
return mMarkerData;
|
|
default:
|
|
MOZ_ASSERT_UNREACHABLE(
|
|
"Should not try to get animation effects for "
|
|
"a pseudo other that :before, :after or ::marker");
|
|
break;
|
|
}
|
|
return mElementData;
|
|
}
|
|
|
|
PerElementOrPseudoData& DataFor(PseudoStyleType aType) {
|
|
const auto& data =
|
|
const_cast<const ElementAnimationData*>(this)->DataFor(aType);
|
|
return const_cast<PerElementOrPseudoData&>(data);
|
|
}
|
|
|
|
public:
|
|
void Traverse(nsCycleCollectionTraversalCallback&);
|
|
|
|
void ClearAllAnimationCollections();
|
|
|
|
EffectSet* GetEffectSetFor(PseudoStyleType aType) const {
|
|
return DataFor(aType).mEffectSet.get();
|
|
}
|
|
|
|
void ClearEffectSetFor(PseudoStyleType aType) {
|
|
auto& data = DataFor(aType);
|
|
if (data.mEffectSet) {
|
|
data.DoClearEffectSet();
|
|
}
|
|
}
|
|
|
|
EffectSet& EnsureEffectSetFor(PseudoStyleType aType) {
|
|
auto& data = DataFor(aType);
|
|
if (auto* set = data.mEffectSet.get()) {
|
|
return *set;
|
|
}
|
|
return data.DoEnsureEffectSet();
|
|
}
|
|
|
|
CSSTransitionCollection* GetTransitionCollection(PseudoStyleType aType) {
|
|
return DataFor(aType).mTransitions.get();
|
|
}
|
|
|
|
void ClearTransitionCollectionFor(PseudoStyleType aType) {
|
|
auto& data = DataFor(aType);
|
|
if (data.mTransitions) {
|
|
data.DoClearTransitions();
|
|
}
|
|
}
|
|
|
|
CSSTransitionCollection& EnsureTransitionCollection(dom::Element& aOwner,
|
|
PseudoStyleType aType) {
|
|
auto& data = DataFor(aType);
|
|
if (auto* collection = data.mTransitions.get()) {
|
|
return *collection;
|
|
}
|
|
return data.DoEnsureTransitions(aOwner, aType);
|
|
}
|
|
|
|
CSSAnimationCollection* GetAnimationCollection(PseudoStyleType aType) {
|
|
return DataFor(aType).mAnimations.get();
|
|
}
|
|
|
|
void ClearAnimationCollectionFor(PseudoStyleType aType) {
|
|
auto& data = DataFor(aType);
|
|
if (data.mAnimations) {
|
|
data.DoClearAnimations();
|
|
}
|
|
}
|
|
|
|
CSSAnimationCollection& EnsureAnimationCollection(dom::Element& aOwner,
|
|
PseudoStyleType aType) {
|
|
auto& data = DataFor(aType);
|
|
if (auto* collection = data.mAnimations.get()) {
|
|
return *collection;
|
|
}
|
|
return data.DoEnsureAnimations(aOwner, aType);
|
|
}
|
|
|
|
ScrollTimelineCollection* GetScrollTimelineCollection(PseudoStyleType aType) {
|
|
return DataFor(aType).mScrollTimelines.get();
|
|
}
|
|
|
|
void ClearScrollTimelineCollectionFor(PseudoStyleType aType) {
|
|
auto& data = DataFor(aType);
|
|
if (data.mScrollTimelines) {
|
|
data.DoClearScrollTimelines();
|
|
}
|
|
}
|
|
|
|
ScrollTimelineCollection& EnsureScrollTimelineCollection(
|
|
dom::Element& aOwner, PseudoStyleType aType) {
|
|
auto& data = DataFor(aType);
|
|
if (auto* collection = data.mScrollTimelines.get()) {
|
|
return *collection;
|
|
}
|
|
return data.DoEnsureScrollTimelines(aOwner, aType);
|
|
}
|
|
|
|
ViewTimelineCollection* GetViewTimelineCollection(PseudoStyleType aType) {
|
|
return DataFor(aType).mViewTimelines.get();
|
|
}
|
|
|
|
void ClearViewTimelineCollectionFor(PseudoStyleType aType) {
|
|
auto& data = DataFor(aType);
|
|
if (data.mViewTimelines) {
|
|
data.DoClearViewTimelines();
|
|
}
|
|
}
|
|
|
|
ViewTimelineCollection& EnsureViewTimelineCollection(dom::Element& aOwner,
|
|
PseudoStyleType aType) {
|
|
auto& data = DataFor(aType);
|
|
if (auto* collection = data.mViewTimelines.get()) {
|
|
return *collection;
|
|
}
|
|
return data.DoEnsureViewTimelines(aOwner, aType);
|
|
}
|
|
|
|
dom::ProgressTimelineScheduler* GetProgressTimelineScheduler(
|
|
PseudoStyleType aType) {
|
|
return DataFor(aType).mProgressTimelineScheduler.get();
|
|
}
|
|
|
|
void ClearProgressTimelineScheduler(PseudoStyleType aType) {
|
|
auto& data = DataFor(aType);
|
|
if (data.mProgressTimelineScheduler) {
|
|
data.DoClearProgressTimelineScheduler();
|
|
}
|
|
}
|
|
|
|
dom::ProgressTimelineScheduler& EnsureProgressTimelineScheduler(
|
|
dom::Element& aOwner, PseudoStyleType aType) {
|
|
auto& data = DataFor(aType);
|
|
if (auto* collection = data.mProgressTimelineScheduler.get()) {
|
|
return *collection;
|
|
}
|
|
return data.DoEnsureProgressTimelineScheduler(aOwner, aType);
|
|
}
|
|
|
|
ElementAnimationData() = default;
|
|
};
|
|
|
|
} // namespace mozilla
|
|
|
|
#endif
|