dom/smil/nsSMILAnimationController.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/smil/nsSMILAnimationController.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,231 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef NS_SMILANIMATIONCONTROLLER_H_
    1.10 +#define NS_SMILANIMATIONCONTROLLER_H_
    1.11 +
    1.12 +#include "mozilla/Attributes.h"
    1.13 +#include "nsAutoPtr.h"
    1.14 +#include "nsCOMPtr.h"
    1.15 +#include "nsTArray.h"
    1.16 +#include "nsITimer.h"
    1.17 +#include "nsTHashtable.h"
    1.18 +#include "nsHashKeys.h"
    1.19 +#include "nsSMILTimeContainer.h"
    1.20 +#include "nsSMILCompositorTable.h"
    1.21 +#include "nsSMILMilestone.h"
    1.22 +#include "nsRefreshDriver.h"
    1.23 +
    1.24 +struct nsSMILTargetIdentifier;
    1.25 +class nsIDocument;
    1.26 +
    1.27 +namespace mozilla {
    1.28 +namespace dom {
    1.29 +class SVGAnimationElement;
    1.30 +}
    1.31 +}
    1.32 +
    1.33 +//----------------------------------------------------------------------
    1.34 +// nsSMILAnimationController
    1.35 +//
    1.36 +// The animation controller maintains the animation timer and determines the
    1.37 +// sample times and sample rate for all SMIL animations in a document. There is
    1.38 +// at most one animation controller per nsDocument so that frame-rate tuning can
    1.39 +// be performed at a document-level.
    1.40 +//
    1.41 +// The animation controller can contain many child time containers (timed
    1.42 +// document root objects) which may correspond to SVG document fragments within
    1.43 +// a compound document. These time containers can be paused individually or
    1.44 +// here, at the document level.
    1.45 +//
    1.46 +class nsSMILAnimationController : public nsSMILTimeContainer,
    1.47 +                                  public nsARefreshObserver
    1.48 +{
    1.49 +public:
    1.50 +  nsSMILAnimationController(nsIDocument* aDoc);
    1.51 +  ~nsSMILAnimationController();
    1.52 +
    1.53 +  // Clears mDocument pointer. (Called by our nsIDocument when it's going away)
    1.54 +  void Disconnect();
    1.55 +
    1.56 +  // nsSMILContainer
    1.57 +  virtual void Pause(uint32_t aType) MOZ_OVERRIDE;
    1.58 +  virtual void Resume(uint32_t aType) MOZ_OVERRIDE;
    1.59 +  virtual nsSMILTime GetParentTime() const MOZ_OVERRIDE;
    1.60 +
    1.61 +  // nsARefreshObserver
    1.62 +  NS_IMETHOD_(MozExternalRefCountType) AddRef() MOZ_OVERRIDE;
    1.63 +  NS_IMETHOD_(MozExternalRefCountType) Release() MOZ_OVERRIDE;
    1.64 +
    1.65 +  virtual void WillRefresh(mozilla::TimeStamp aTime) MOZ_OVERRIDE;
    1.66 +
    1.67 +  // Methods for registering and enumerating animation elements
    1.68 +  void RegisterAnimationElement(mozilla::dom::SVGAnimationElement* aAnimationElement);
    1.69 +  void UnregisterAnimationElement(mozilla::dom::SVGAnimationElement* aAnimationElement);
    1.70 +
    1.71 +  // Methods for resampling all animations
    1.72 +  // (A resample performs the same operations as a sample but doesn't advance
    1.73 +  // the current time and doesn't check if the container is paused)
    1.74 +  // This will flush pending style changes for the document.
    1.75 +  void Resample() { DoSample(false); }
    1.76 +
    1.77 +  void SetResampleNeeded()
    1.78 +  {
    1.79 +    if (!mRunningSample) {
    1.80 +      if (!mResampleNeeded) {
    1.81 +        FlagDocumentNeedsFlush();
    1.82 +      }
    1.83 +      mResampleNeeded = true;
    1.84 +    }
    1.85 +  }
    1.86 +
    1.87 +  // This will flush pending style changes for the document.
    1.88 +  void FlushResampleRequests()
    1.89 +  {
    1.90 +    if (!mResampleNeeded)
    1.91 +      return;
    1.92 +
    1.93 +    Resample();
    1.94 +  }
    1.95 +
    1.96 +  // Methods for handling page transitions
    1.97 +  void OnPageShow();
    1.98 +  void OnPageHide();
    1.99 +
   1.100 +  // Methods for supporting cycle-collection
   1.101 +  void Traverse(nsCycleCollectionTraversalCallback* aCallback);
   1.102 +  void Unlink();
   1.103 +
   1.104 +  // Methods for relaying the availability of the refresh driver
   1.105 +  void NotifyRefreshDriverCreated(nsRefreshDriver* aRefreshDriver);
   1.106 +  void NotifyRefreshDriverDestroying(nsRefreshDriver* aRefreshDriver);
   1.107 +
   1.108 +  // Helper to check if we have any animation elements at all
   1.109 +  bool HasRegisteredAnimations()
   1.110 +  { return mAnimationElementTable.Count() != 0; }
   1.111 +
   1.112 +protected:
   1.113 +  // Typedefs
   1.114 +  typedef nsPtrHashKey<nsSMILTimeContainer> TimeContainerPtrKey;
   1.115 +  typedef nsTHashtable<TimeContainerPtrKey> TimeContainerHashtable;
   1.116 +  typedef nsPtrHashKey<mozilla::dom::SVGAnimationElement> AnimationElementPtrKey;
   1.117 +  typedef nsTHashtable<AnimationElementPtrKey> AnimationElementHashtable;
   1.118 +
   1.119 +  struct SampleTimeContainerParams
   1.120 +  {
   1.121 +    TimeContainerHashtable* mActiveContainers;
   1.122 +    bool                    mSkipUnchangedContainers;
   1.123 +  };
   1.124 +
   1.125 +  struct SampleAnimationParams
   1.126 +  {
   1.127 +    TimeContainerHashtable* mActiveContainers;
   1.128 +    nsSMILCompositorTable*  mCompositorTable;
   1.129 +  };
   1.130 +
   1.131 +  struct GetMilestoneElementsParams
   1.132 +  {
   1.133 +    nsTArray<nsRefPtr<mozilla::dom::SVGAnimationElement> > mElements;
   1.134 +    nsSMILMilestone                                        mMilestone;
   1.135 +  };
   1.136 +
   1.137 +  // Cycle-collection implementation helpers
   1.138 +  static PLDHashOperator CompositorTableEntryTraverse(
   1.139 +      nsSMILCompositor* aCompositor, void* aArg);
   1.140 +
   1.141 +  // Returns mDocument's refresh driver, if it's got one.
   1.142 +  nsRefreshDriver* GetRefreshDriver();
   1.143 +
   1.144 +  // Methods for controlling whether we're sampling
   1.145 +  void StartSampling(nsRefreshDriver* aRefreshDriver);
   1.146 +  void StopSampling(nsRefreshDriver* aRefreshDriver);
   1.147 +
   1.148 +  // Wrapper for StartSampling that defers if no animations are registered.
   1.149 +  void MaybeStartSampling(nsRefreshDriver* aRefreshDriver);
   1.150 +
   1.151 +  // Sample-related callbacks and implementation helpers
   1.152 +  virtual void DoSample() MOZ_OVERRIDE;
   1.153 +  void DoSample(bool aSkipUnchangedContainers);
   1.154 +
   1.155 +  void RewindElements();
   1.156 +  static PLDHashOperator RewindNeeded(
   1.157 +      TimeContainerPtrKey* aKey, void* aData);
   1.158 +  static PLDHashOperator RewindAnimation(
   1.159 +      AnimationElementPtrKey* aKey, void* aData);
   1.160 +  static PLDHashOperator ClearRewindNeeded(
   1.161 +      TimeContainerPtrKey* aKey, void* aData);
   1.162 +
   1.163 +  void DoMilestoneSamples();
   1.164 +  static PLDHashOperator GetNextMilestone(
   1.165 +      TimeContainerPtrKey* aKey, void* aData);
   1.166 +  static PLDHashOperator GetMilestoneElements(
   1.167 +      TimeContainerPtrKey* aKey, void* aData);
   1.168 +
   1.169 +  static PLDHashOperator SampleTimeContainer(
   1.170 +      TimeContainerPtrKey* aKey, void* aData);
   1.171 +  static PLDHashOperator SampleAnimation(
   1.172 +      AnimationElementPtrKey* aKey, void* aData);
   1.173 +  static void SampleTimedElement(mozilla::dom::SVGAnimationElement* aElement,
   1.174 +                                 TimeContainerHashtable* aActiveContainers);
   1.175 +  static void AddAnimationToCompositorTable(
   1.176 +    mozilla::dom::SVGAnimationElement* aElement, nsSMILCompositorTable* aCompositorTable);
   1.177 +  static bool GetTargetIdentifierForAnimation(
   1.178 +      mozilla::dom::SVGAnimationElement* aAnimElem, nsSMILTargetIdentifier& aResult);
   1.179 +
   1.180 +  // Methods for adding/removing time containers
   1.181 +  virtual nsresult AddChild(nsSMILTimeContainer& aChild) MOZ_OVERRIDE;
   1.182 +  virtual void     RemoveChild(nsSMILTimeContainer& aChild) MOZ_OVERRIDE;
   1.183 +
   1.184 +  void FlagDocumentNeedsFlush();
   1.185 +
   1.186 +  // Members
   1.187 +  nsAutoRefCnt mRefCnt;
   1.188 +  NS_DECL_OWNINGTHREAD
   1.189 +
   1.190 +  AnimationElementHashtable  mAnimationElementTable;
   1.191 +  TimeContainerHashtable     mChildContainerTable;
   1.192 +  mozilla::TimeStamp         mCurrentSampleTime;
   1.193 +  mozilla::TimeStamp         mStartTime;
   1.194 +
   1.195 +  // Average time between samples from the refresh driver. This is used to
   1.196 +  // detect large unexpected gaps between samples such as can occur when the
   1.197 +  // computer sleeps. The nature of the SMIL model means that catching up these
   1.198 +  // large gaps can be expensive as, for example, many events may need to be
   1.199 +  // dispatched for the intervening time when no samples were received.
   1.200 +  //
   1.201 +  // In such cases, we ignore the intervening gap and continue sampling from
   1.202 +  // when we were expecting the next sample to arrive.
   1.203 +  //
   1.204 +  // Note that we only do this for SMIL and not CSS transitions (which doesn't
   1.205 +  // have so much work to do to catch up) nor scripted animations (which expect
   1.206 +  // animation time to follow real time).
   1.207 +  //
   1.208 +  // This behaviour does not affect pausing (since we're not *expecting* any
   1.209 +  // samples then) nor seeking (where the SMIL model behaves somewhat
   1.210 +  // differently such as not dispatching events).
   1.211 +  nsSMILTime                 mAvgTimeBetweenSamples;
   1.212 +
   1.213 +  bool                       mResampleNeeded;
   1.214 +  // If we're told to start sampling but there are no animation elements we just
   1.215 +  // record the time, set the following flag, and then wait until we have an
   1.216 +  // animation element. Then we'll reset this flag and actually start sampling.
   1.217 +  bool                       mDeferredStartSampling;
   1.218 +  bool                       mRunningSample;
   1.219 +
   1.220 +  // Are we registered with our document's refresh driver?
   1.221 +  bool                       mRegisteredWithRefreshDriver;
   1.222 +
   1.223 +  // Store raw ptr to mDocument.  It owns the controller, so controller
   1.224 +  // shouldn't outlive it
   1.225 +  nsIDocument* mDocument;
   1.226 +
   1.227 +  // Contains compositors used in our last sample.  We keep this around
   1.228 +  // so we can detect when an element/attribute used to be animated,
   1.229 +  // but isn't anymore for some reason. (e.g. if its <animate> element is
   1.230 +  // removed or retargeted)
   1.231 +  nsAutoPtr<nsSMILCompositorTable> mLastCompositorTable;
   1.232 +};
   1.233 +
   1.234 +#endif // NS_SMILANIMATIONCONTROLLER_H_

mercurial