tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ElementAnimationData.h (7515B)


      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/. */
      6 
      7 #ifndef mozilla_ElementAnimationData_h
      8 #define mozilla_ElementAnimationData_h
      9 
     10 #include "mozilla/PseudoStyleType.h"
     11 #include "mozilla/UniquePtr.h"
     12 #include "nsTHashMap.h"
     13 
     14 class nsCycleCollectionTraversalCallback;
     15 
     16 namespace mozilla {
     17 class EffectSet;
     18 template <typename Animation>
     19 class AnimationCollection;
     20 template <typename TimelineType>
     21 class TimelineCollection;
     22 namespace dom {
     23 class Element;
     24 class CSSAnimation;
     25 class CSSTransition;
     26 class ScrollTimeline;
     27 class ViewTimeline;
     28 }  // namespace dom
     29 using CSSAnimationCollection = AnimationCollection<dom::CSSAnimation>;
     30 using CSSTransitionCollection = AnimationCollection<dom::CSSTransition>;
     31 using ScrollTimelineCollection = TimelineCollection<dom::ScrollTimeline>;
     32 using ViewTimelineCollection = TimelineCollection<dom::ViewTimeline>;
     33 
     34 // The animation data for a given element (and its pseudo-elements).
     35 class ElementAnimationData {
     36  struct PerElementOrPseudoData {
     37    UniquePtr<EffectSet> mEffectSet;
     38    UniquePtr<CSSAnimationCollection> mAnimations;
     39    UniquePtr<CSSTransitionCollection> mTransitions;
     40 
     41    // Note: scroll-timeline-name is applied to elements which could be
     42    // scroll containers, or replaced elements. view-timeline-name is applied to
     43    // all elements. However, the named timeline is referenceable in
     44    // animation-timeline by the tree order scope.
     45    // Spec: https://drafts.csswg.org/scroll-animations-1/#timeline-scope.
     46    //
     47    // So it should be fine to create timeline objects only on the elements and
     48    // pseudo elements which support animations.
     49    //
     50    // Note: TimelineCollection owns and manages the named progress timeline
     51    // generated by specifying scroll-timeline-name property and
     52    // view-timeline-name property on this element. However, the anonymous
     53    // progress timelines (e.g. animation-timeline:scroll()) are owned by
     54    // Animation objects only.
     55    UniquePtr<ScrollTimelineCollection> mScrollTimelines;
     56    UniquePtr<ViewTimelineCollection> mViewTimelines;
     57 
     58    PerElementOrPseudoData();
     59    ~PerElementOrPseudoData();
     60 
     61    EffectSet& DoEnsureEffectSet();
     62    CSSTransitionCollection& DoEnsureTransitions(dom::Element&,
     63                                                 const PseudoStyleRequest&);
     64    CSSAnimationCollection& DoEnsureAnimations(dom::Element&,
     65                                               const PseudoStyleRequest&);
     66    ScrollTimelineCollection& DoEnsureScrollTimelines(
     67        dom::Element&, const PseudoStyleRequest&);
     68    ViewTimelineCollection& DoEnsureViewTimelines(dom::Element&,
     69                                                  const PseudoStyleRequest&);
     70 
     71    bool IsEmpty() const {
     72      return !mEffectSet && !mAnimations && !mTransitions &&
     73             !mScrollTimelines && !mViewTimelines;
     74    }
     75 
     76    void Traverse(nsCycleCollectionTraversalCallback&);
     77  };
     78 
     79  PerElementOrPseudoData mElementData;
     80 
     81  using PseudoData =
     82      nsTHashMap<PseudoStyleRequestHashKey, UniquePtr<PerElementOrPseudoData>>;
     83  PseudoData mPseudoData;
     84  // Avoid remove hash entry while other people are still using it.
     85  bool mIsClearingPseudoData = false;
     86 
     87  const PerElementOrPseudoData* GetData(
     88      const PseudoStyleRequest& aRequest) const {
     89    if (aRequest.mType != PseudoStyleType::NotPseudo) {
     90      return GetPseudoData(aRequest);
     91    }
     92    return &mElementData;
     93  }
     94 
     95  PerElementOrPseudoData& GetOrCreateData(const PseudoStyleRequest& aRequest) {
     96    if (aRequest.mType != PseudoStyleType::NotPseudo) {
     97      return GetOrCreatePseudoData(aRequest);
     98    }
     99    return mElementData;
    100  }
    101 
    102  const PerElementOrPseudoData* GetPseudoData(
    103      const PseudoStyleRequest& aRequest) const;
    104  PerElementOrPseudoData& GetOrCreatePseudoData(
    105      const PseudoStyleRequest& aRequest);
    106  void MaybeClearEntry(PseudoData::LookupResult<PseudoData&>&& aEntry);
    107 
    108  // |aFn| is the removal function which accepts only |PerElementOrPseudoData&|
    109  // as the parameter.
    110  template <typename Fn>
    111  void WithDataForRemoval(const PseudoStyleRequest& aRequest, Fn&& aFn);
    112 
    113 public:
    114  void Traverse(nsCycleCollectionTraversalCallback&);
    115 
    116  void ClearAllAnimationCollections();
    117  void ClearAllPseudos(bool aOnlyViewTransitions);
    118  void ClearViewTransitionPseudos() { ClearAllPseudos(true); }
    119 
    120  EffectSet* GetEffectSetFor(const PseudoStyleRequest& aRequest) const {
    121    if (auto* data = GetData(aRequest)) {
    122      return data->mEffectSet.get();
    123    }
    124    return nullptr;
    125  }
    126 
    127  void ClearEffectSetFor(const PseudoStyleRequest& aRequest);
    128 
    129  EffectSet& EnsureEffectSetFor(const PseudoStyleRequest& aRequest) {
    130    auto& data = GetOrCreateData(aRequest);
    131    if (auto* set = data.mEffectSet.get()) {
    132      return *set;
    133    }
    134    return data.DoEnsureEffectSet();
    135  }
    136 
    137  CSSTransitionCollection* GetTransitionCollection(
    138      const PseudoStyleRequest& aRequest) const {
    139    if (auto* data = GetData(aRequest)) {
    140      return data->mTransitions.get();
    141    }
    142    return nullptr;
    143  }
    144 
    145  void ClearTransitionCollectionFor(const PseudoStyleRequest& aRequest);
    146 
    147  CSSTransitionCollection& EnsureTransitionCollection(
    148      dom::Element& aOwner, const PseudoStyleRequest& aRequest) {
    149    auto& data = GetOrCreateData(aRequest);
    150    if (auto* collection = data.mTransitions.get()) {
    151      return *collection;
    152    }
    153    return data.DoEnsureTransitions(aOwner, aRequest);
    154  }
    155 
    156  CSSAnimationCollection* GetAnimationCollection(
    157      const PseudoStyleRequest& aRequest) const {
    158    if (auto* data = GetData(aRequest)) {
    159      return data->mAnimations.get();
    160    }
    161    return nullptr;
    162  }
    163 
    164  void ClearAnimationCollectionFor(const PseudoStyleRequest& aRequest);
    165 
    166  CSSAnimationCollection& EnsureAnimationCollection(
    167      dom::Element& aOwner, const PseudoStyleRequest& aRequest) {
    168    auto& data = GetOrCreateData(aRequest);
    169    if (auto* collection = data.mAnimations.get()) {
    170      return *collection;
    171    }
    172    return data.DoEnsureAnimations(aOwner, aRequest);
    173  }
    174 
    175  ScrollTimelineCollection* GetScrollTimelineCollection(
    176      const PseudoStyleRequest& aRequest) const {
    177    if (auto* data = GetData(aRequest)) {
    178      return data->mScrollTimelines.get();
    179    }
    180    return nullptr;
    181  }
    182 
    183  void ClearScrollTimelineCollectionFor(const PseudoStyleRequest& aRequest);
    184 
    185  ScrollTimelineCollection& EnsureScrollTimelineCollection(
    186      dom::Element& aOwner, const PseudoStyleRequest& aRequest) {
    187    auto& data = GetOrCreateData(aRequest);
    188    if (auto* collection = data.mScrollTimelines.get()) {
    189      return *collection;
    190    }
    191    return data.DoEnsureScrollTimelines(aOwner, aRequest);
    192  }
    193 
    194  ViewTimelineCollection* GetViewTimelineCollection(
    195      const PseudoStyleRequest& aRequest) const {
    196    if (auto* data = GetData(aRequest)) {
    197      return data->mViewTimelines.get();
    198    }
    199    return nullptr;
    200  }
    201 
    202  void ClearViewTimelineCollectionFor(const PseudoStyleRequest& aRequest);
    203 
    204  ViewTimelineCollection& EnsureViewTimelineCollection(
    205      dom::Element& aOwner, const PseudoStyleRequest& aRequest) {
    206    auto& data = GetOrCreateData(aRequest);
    207    if (auto* collection = data.mViewTimelines.get()) {
    208      return *collection;
    209    }
    210    return data.DoEnsureViewTimelines(aOwner, aRequest);
    211  }
    212 
    213  ElementAnimationData() = default;
    214 };
    215 
    216 }  // namespace mozilla
    217 
    218 #endif