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_