1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_ElementAnimationData_h
8 #define mozilla_ElementAnimationData_h
10 #include "mozilla/UniquePtr.h"
11 #include "mozilla/PseudoStyleType.h"
13 class nsCycleCollectionTraversalCallback
;
16 enum class PseudoStyleType
: uint8_t;
18 template <typename Animation
>
19 class AnimationCollection
;
20 template <typename TimelineType
>
21 class TimelineCollection
;
26 class ProgressTimelineScheduler
;
30 using CSSAnimationCollection
= AnimationCollection
<dom::CSSAnimation
>;
31 using CSSTransitionCollection
= AnimationCollection
<dom::CSSTransition
>;
32 using ScrollTimelineCollection
= TimelineCollection
<dom::ScrollTimeline
>;
33 using ViewTimelineCollection
= TimelineCollection
<dom::ViewTimeline
>;
35 // The animation data for a given element (and its pseudo-elements).
36 class ElementAnimationData
{
37 struct PerElementOrPseudoData
{
38 UniquePtr
<EffectSet
> mEffectSet
;
39 UniquePtr
<CSSAnimationCollection
> mAnimations
;
40 UniquePtr
<CSSTransitionCollection
> mTransitions
;
42 // Note: scroll-timeline-name is applied to elements which could be
43 // scroll containers, or replaced elements. view-timeline-name is applied to
44 // all elements. However, the named timeline is referenceable in
45 // animation-timeline by the tree order scope.
46 // Spec: https://drafts.csswg.org/scroll-animations-1/#timeline-scope.
48 // So it should be fine to create timeline objects only on the elements and
49 // pseudo elements which support animations.
50 UniquePtr
<ScrollTimelineCollection
> mScrollTimelines
;
51 UniquePtr
<ViewTimelineCollection
> mViewTimelines
;
53 // This is different from |mScrollTimelines|. We use this to schedule all
54 // scroll-driven animations (which use anonymous/named scroll timelines or
55 // anonymous/name view timelines) for a specific scroll source (which is the
56 // element with nsIScrollableFrame).
58 // TimelineCollection owns and manages the named progress timeline generated
59 // by specifying scroll-timeline-name property and view-timeline-name
60 // property on this element. However, the anonymous progress timelines (e.g.
61 // animation-timeline:scroll()) are owned by Animation objects only.
64 // 1. For named scroll timelines. The element which specifies
65 // scroll-timeline-name is the scroll source. However, for named view
66 // timelines, the element which specifies view-timeline-name may not be
67 // the scroll source because we use its nearest scroll container as the
69 // 2. For anonymous progress timelines, we don't keep their timeline obejcts
70 // in TimelineCollection.
71 // So, per 1) and 2), we use |mProgressTimelineScheduler| for the scroll
72 // source element to schedule scroll-driven animations.
73 UniquePtr
<dom::ProgressTimelineScheduler
> mProgressTimelineScheduler
;
75 PerElementOrPseudoData();
76 ~PerElementOrPseudoData();
78 EffectSet
& DoEnsureEffectSet();
79 CSSTransitionCollection
& DoEnsureTransitions(dom::Element
&,
81 CSSAnimationCollection
& DoEnsureAnimations(dom::Element
&, PseudoStyleType
);
82 ScrollTimelineCollection
& DoEnsureScrollTimelines(dom::Element
&,
84 ViewTimelineCollection
& DoEnsureViewTimelines(dom::Element
&,
86 dom::ProgressTimelineScheduler
& DoEnsureProgressTimelineScheduler(
87 dom::Element
&, PseudoStyleType
);
89 void DoClearEffectSet();
90 void DoClearTransitions();
91 void DoClearAnimations();
92 void DoClearScrollTimelines();
93 void DoClearViewTimelines();
94 void DoClearProgressTimelineScheduler();
96 void Traverse(nsCycleCollectionTraversalCallback
&);
99 PerElementOrPseudoData mElementData
;
101 // TODO(emilio): Maybe this should be a hash map eventually, once we allow
102 // animating all pseudo-elements.
103 PerElementOrPseudoData mBeforeData
;
104 PerElementOrPseudoData mAfterData
;
105 PerElementOrPseudoData mMarkerData
;
107 const PerElementOrPseudoData
& DataFor(PseudoStyleType aType
) const {
109 case PseudoStyleType::NotPseudo
:
111 case PseudoStyleType::before
:
113 case PseudoStyleType::after
:
115 case PseudoStyleType::marker
:
118 MOZ_ASSERT_UNREACHABLE(
119 "Should not try to get animation effects for "
120 "a pseudo other that :before, :after or ::marker");
126 PerElementOrPseudoData
& DataFor(PseudoStyleType aType
) {
128 const_cast<const ElementAnimationData
*>(this)->DataFor(aType
);
129 return const_cast<PerElementOrPseudoData
&>(data
);
133 void Traverse(nsCycleCollectionTraversalCallback
&);
135 void ClearAllAnimationCollections();
137 EffectSet
* GetEffectSetFor(PseudoStyleType aType
) const {
138 return DataFor(aType
).mEffectSet
.get();
141 void ClearEffectSetFor(PseudoStyleType aType
) {
142 auto& data
= DataFor(aType
);
143 if (data
.mEffectSet
) {
144 data
.DoClearEffectSet();
148 EffectSet
& EnsureEffectSetFor(PseudoStyleType aType
) {
149 auto& data
= DataFor(aType
);
150 if (auto* set
= data
.mEffectSet
.get()) {
153 return data
.DoEnsureEffectSet();
156 CSSTransitionCollection
* GetTransitionCollection(PseudoStyleType aType
) {
157 return DataFor(aType
).mTransitions
.get();
160 void ClearTransitionCollectionFor(PseudoStyleType aType
) {
161 auto& data
= DataFor(aType
);
162 if (data
.mTransitions
) {
163 data
.DoClearTransitions();
167 CSSTransitionCollection
& EnsureTransitionCollection(dom::Element
& aOwner
,
168 PseudoStyleType aType
) {
169 auto& data
= DataFor(aType
);
170 if (auto* collection
= data
.mTransitions
.get()) {
173 return data
.DoEnsureTransitions(aOwner
, aType
);
176 CSSAnimationCollection
* GetAnimationCollection(PseudoStyleType aType
) {
177 return DataFor(aType
).mAnimations
.get();
180 void ClearAnimationCollectionFor(PseudoStyleType aType
) {
181 auto& data
= DataFor(aType
);
182 if (data
.mAnimations
) {
183 data
.DoClearAnimations();
187 CSSAnimationCollection
& EnsureAnimationCollection(dom::Element
& aOwner
,
188 PseudoStyleType aType
) {
189 auto& data
= DataFor(aType
);
190 if (auto* collection
= data
.mAnimations
.get()) {
193 return data
.DoEnsureAnimations(aOwner
, aType
);
196 ScrollTimelineCollection
* GetScrollTimelineCollection(PseudoStyleType aType
) {
197 return DataFor(aType
).mScrollTimelines
.get();
200 void ClearScrollTimelineCollectionFor(PseudoStyleType aType
) {
201 auto& data
= DataFor(aType
);
202 if (data
.mScrollTimelines
) {
203 data
.DoClearScrollTimelines();
207 ScrollTimelineCollection
& EnsureScrollTimelineCollection(
208 dom::Element
& aOwner
, PseudoStyleType aType
) {
209 auto& data
= DataFor(aType
);
210 if (auto* collection
= data
.mScrollTimelines
.get()) {
213 return data
.DoEnsureScrollTimelines(aOwner
, aType
);
216 ViewTimelineCollection
* GetViewTimelineCollection(PseudoStyleType aType
) {
217 return DataFor(aType
).mViewTimelines
.get();
220 void ClearViewTimelineCollectionFor(PseudoStyleType aType
) {
221 auto& data
= DataFor(aType
);
222 if (data
.mViewTimelines
) {
223 data
.DoClearViewTimelines();
227 ViewTimelineCollection
& EnsureViewTimelineCollection(dom::Element
& aOwner
,
228 PseudoStyleType aType
) {
229 auto& data
= DataFor(aType
);
230 if (auto* collection
= data
.mViewTimelines
.get()) {
233 return data
.DoEnsureViewTimelines(aOwner
, aType
);
236 dom::ProgressTimelineScheduler
* GetProgressTimelineScheduler(
237 PseudoStyleType aType
) {
238 return DataFor(aType
).mProgressTimelineScheduler
.get();
241 void ClearProgressTimelineScheduler(PseudoStyleType aType
) {
242 auto& data
= DataFor(aType
);
243 if (data
.mProgressTimelineScheduler
) {
244 data
.DoClearProgressTimelineScheduler();
248 dom::ProgressTimelineScheduler
& EnsureProgressTimelineScheduler(
249 dom::Element
& aOwner
, PseudoStyleType aType
) {
250 auto& data
= DataFor(aType
);
251 if (auto* collection
= data
.mProgressTimelineScheduler
.get()) {
254 return data
.DoEnsureProgressTimelineScheduler(aOwner
, aType
);
257 ElementAnimationData() = default;
260 } // namespace mozilla