summaryrefslogtreecommitdiffstats
path: root/dom/animation/ElementAnimationData.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/animation/ElementAnimationData.h262
1 files changed, 262 insertions, 0 deletions
diff --git a/dom/animation/ElementAnimationData.h b/dom/animation/ElementAnimationData.h
new file mode 100644
index 0000000000..9183f0f008
--- /dev/null
+++ b/dom/animation/ElementAnimationData.h
@@ -0,0 +1,262 @@
+/* -*- 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