Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/smil/nsSMILAnimationController.h
Line
Count
Source (jump to first uncovered line)
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 NS_SMILANIMATIONCONTROLLER_H_
8
#define NS_SMILANIMATIONCONTROLLER_H_
9
10
#include "mozilla/Attributes.h"
11
#include "nsAutoPtr.h"
12
#include "nsCOMPtr.h"
13
#include "nsTArray.h"
14
#include "nsITimer.h"
15
#include "nsTHashtable.h"
16
#include "nsHashKeys.h"
17
#include "nsSMILTimeContainer.h"
18
#include "nsSMILCompositorTable.h"
19
#include "nsSMILMilestone.h"
20
#include "nsRefreshDriver.h"
21
22
struct nsSMILTargetIdentifier;
23
class nsIDocument;
24
25
namespace mozilla {
26
namespace dom {
27
class Element;
28
class SVGAnimationElement;
29
} // namespace dom
30
} // namespace mozilla
31
32
//----------------------------------------------------------------------
33
// nsSMILAnimationController
34
//
35
// The animation controller maintains the animation timer and determines the
36
// sample times and sample rate for all SMIL animations in a document. There is
37
// at most one animation controller per nsDocument so that frame-rate tuning can
38
// be performed at a document-level.
39
//
40
// The animation controller can contain many child time containers (timed
41
// document root objects) which may correspond to SVG document fragments within
42
// a compound document. These time containers can be paused individually or
43
// here, at the document level.
44
//
45
class nsSMILAnimationController final : public nsSMILTimeContainer,
46
                                        public nsARefreshObserver
47
{
48
public:
49
  explicit nsSMILAnimationController(nsIDocument* aDoc);
50
51
  // Clears mDocument pointer. (Called by our nsIDocument when it's going away)
52
  void Disconnect();
53
54
  // nsSMILContainer
55
  virtual void Pause(uint32_t aType) override;
56
  virtual void Resume(uint32_t aType) override;
57
  virtual nsSMILTime GetParentTime() const override;
58
59
  // nsARefreshObserver
60
  NS_IMETHOD_(MozExternalRefCountType) AddRef() override;
61
  NS_IMETHOD_(MozExternalRefCountType) Release() override;
62
63
  virtual void WillRefresh(mozilla::TimeStamp aTime) override;
64
65
  // Methods for registering and enumerating animation elements
66
  void RegisterAnimationElement(mozilla::dom::SVGAnimationElement* aAnimationElement);
67
  void UnregisterAnimationElement(mozilla::dom::SVGAnimationElement* aAnimationElement);
68
69
  // Methods for resampling all animations
70
  // (A resample performs the same operations as a sample but doesn't advance
71
  // the current time and doesn't check if the container is paused)
72
  // This will flush pending style changes for the document.
73
0
  void Resample() { DoSample(false); }
74
75
  void SetResampleNeeded()
76
0
  {
77
0
    if (!mRunningSample && !mResampleNeeded) {
78
0
      FlagDocumentNeedsFlush();
79
0
      mResampleNeeded = true;
80
0
    }
81
0
  }
82
83
  // This will flush pending style changes for the document.
84
  void FlushResampleRequests()
85
0
  {
86
0
    if (!mResampleNeeded)
87
0
      return;
88
0
89
0
    Resample();
90
0
  }
91
92
  // Methods for handling page transitions
93
  void OnPageShow();
94
  void OnPageHide();
95
96
  // Methods for supporting cycle-collection
97
  void Traverse(nsCycleCollectionTraversalCallback* aCallback);
98
  void Unlink();
99
100
  // Methods for relaying the availability of the refresh driver
101
  void NotifyRefreshDriverCreated(nsRefreshDriver* aRefreshDriver);
102
  void NotifyRefreshDriverDestroying(nsRefreshDriver* aRefreshDriver);
103
104
  // Helper to check if we have any animation elements at all
105
  bool HasRegisteredAnimations() const
106
  {
107
    return mAnimationElementTable.Count() != 0;
108
  }
109
110
  bool MightHavePendingStyleUpdates() const
111
  {
112
    return mMightHavePendingStyleUpdates;
113
  }
114
115
  bool PreTraverse();
116
  bool PreTraverseInSubtree(mozilla::dom::Element* aRoot);
117
118
protected:
119
  ~nsSMILAnimationController();
120
121
  // Typedefs
122
  typedef nsPtrHashKey<nsSMILTimeContainer> TimeContainerPtrKey;
123
  typedef nsTHashtable<TimeContainerPtrKey> TimeContainerHashtable;
124
  typedef nsPtrHashKey<mozilla::dom::SVGAnimationElement> AnimationElementPtrKey;
125
  typedef nsTHashtable<AnimationElementPtrKey> AnimationElementHashtable;
126
127
  // Returns mDocument's refresh driver, if it's got one.
128
  nsRefreshDriver* GetRefreshDriver();
129
130
  // Methods for controlling whether we're sampling
131
  void StartSampling(nsRefreshDriver* aRefreshDriver);
132
  void StopSampling(nsRefreshDriver* aRefreshDriver);
133
134
  // Wrapper for StartSampling that defers if no animations are registered.
135
  void MaybeStartSampling(nsRefreshDriver* aRefreshDriver);
136
137
  // Sample-related callbacks and implementation helpers
138
  virtual void DoSample() override;
139
  void DoSample(bool aSkipUnchangedContainers);
140
141
  void RewindElements();
142
143
  void DoMilestoneSamples();
144
145
  static void SampleTimedElement(mozilla::dom::SVGAnimationElement* aElement,
146
                                 TimeContainerHashtable* aActiveContainers);
147
148
  static void AddAnimationToCompositorTable(
149
      mozilla::dom::SVGAnimationElement* aElement,
150
      nsSMILCompositorTable* aCompositorTable,
151
      bool& aStyleFlushNeeded);
152
153
  static bool GetTargetIdentifierForAnimation(
154
      mozilla::dom::SVGAnimationElement* aAnimElem, nsSMILTargetIdentifier& aResult);
155
156
  // Methods for adding/removing time containers
157
  virtual nsresult AddChild(nsSMILTimeContainer& aChild) override;
158
  virtual void     RemoveChild(nsSMILTimeContainer& aChild) override;
159
160
  void FlagDocumentNeedsFlush();
161
162
  // Members
163
  nsAutoRefCnt mRefCnt;
164
  NS_DECL_OWNINGTHREAD
165
166
  AnimationElementHashtable  mAnimationElementTable;
167
  TimeContainerHashtable     mChildContainerTable;
168
  mozilla::TimeStamp         mCurrentSampleTime;
169
  mozilla::TimeStamp         mStartTime;
170
171
  // Average time between samples from the refresh driver. This is used to
172
  // detect large unexpected gaps between samples such as can occur when the
173
  // computer sleeps. The nature of the SMIL model means that catching up these
174
  // large gaps can be expensive as, for example, many events may need to be
175
  // dispatched for the intervening time when no samples were received.
176
  //
177
  // In such cases, we ignore the intervening gap and continue sampling from
178
  // when we were expecting the next sample to arrive.
179
  //
180
  // Note that we only do this for SMIL and not CSS transitions (which doesn't
181
  // have so much work to do to catch up) nor scripted animations (which expect
182
  // animation time to follow real time).
183
  //
184
  // This behaviour does not affect pausing (since we're not *expecting* any
185
  // samples then) nor seeking (where the SMIL model behaves somewhat
186
  // differently such as not dispatching events).
187
  nsSMILTime                 mAvgTimeBetweenSamples;
188
189
  bool                       mResampleNeeded;
190
  // If we're told to start sampling but there are no animation elements we just
191
  // record the time, set the following flag, and then wait until we have an
192
  // animation element. Then we'll reset this flag and actually start sampling.
193
  bool                       mDeferredStartSampling;
194
  bool                       mRunningSample;
195
196
  // Are we registered with our document's refresh driver?
197
  bool                       mRegisteredWithRefreshDriver;
198
199
  // Have we updated animated values without adding them to the restyle tracker?
200
  bool                       mMightHavePendingStyleUpdates;
201
202
  // Store raw ptr to mDocument.  It owns the controller, so controller
203
  // shouldn't outlive it
204
  nsIDocument* mDocument;
205
206
  // Contains compositors used in our last sample.  We keep this around
207
  // so we can detect when an element/attribute used to be animated,
208
  // but isn't anymore for some reason. (e.g. if its <animate> element is
209
  // removed or retargeted)
210
  nsAutoPtr<nsSMILCompositorTable> mLastCompositorTable;
211
};
212
213
#endif // NS_SMILANIMATIONCONTROLLER_H_