SMILTimeContainer.h (9842B)
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 DOM_SMIL_SMILTIMECONTAINER_H_ 8 #define DOM_SMIL_SMILTIMECONTAINER_H_ 9 10 #include "mozilla/SMILMilestone.h" 11 #include "mozilla/SMILTypes.h" 12 #include "mozilla/dom/SVGAnimationElement.h" 13 #include "nsTPriorityQueue.h" 14 #include "nscore.h" 15 16 namespace mozilla { 17 18 class SMILTimeValue; 19 20 //---------------------------------------------------------------------- 21 // SMILTimeContainer 22 // 23 // Common base class for a time base that can be paused, resumed, and sampled. 24 // 25 class SMILTimeContainer { 26 public: 27 SMILTimeContainer(); 28 virtual ~SMILTimeContainer(); 29 30 /* 31 * Pause request types. 32 */ 33 enum { 34 PAUSE_BEGIN = 1, // Paused because timeline has yet to begin. 35 PAUSE_SCRIPT = 2, // Paused by script. 36 PAUSE_PAGEHIDE = 4, // Paused because our doc is hidden. 37 PAUSE_USERPREF = 8, // Paused because animations are disabled in prefs. 38 PAUSE_IMAGE = 16 // Paused becuase we're in an image that's suspended. 39 }; 40 41 /* 42 * Cause the time container to record its begin time. 43 */ 44 void Begin(); 45 46 /* 47 * Pause this time container 48 * 49 * @param aType The source of the pause request. Successive calls to Pause 50 * with the same aType will be ignored. The container will remain paused until 51 * each call to Pause of a given aType has been matched by at least one call 52 * to Resume with the same aType. 53 */ 54 virtual void Pause(uint32_t aType); 55 56 /* 57 * Pause this time container when it reaches the specified time. 58 * 59 */ 60 void PauseAt(SMILTime aTime); 61 62 /* 63 * Resume this time container 64 * 65 * param @aType The source of the resume request. Clears the pause flag for 66 * this particular type of pause request. When all pause flags have been 67 * cleared the time container will be resumed. 68 */ 69 virtual void Resume(uint32_t aType); 70 71 /** 72 * Returns true if this time container is paused by the specified type. 73 * Note that the time container may also be paused by other types; this method 74 * does not test if aType is the exclusive pause source. 75 * 76 * @param @aType The pause source to test for. 77 * @return true if this container is paused by aType. 78 */ 79 bool IsPausedByType(uint32_t aType) const { return mPauseState & aType; } 80 81 /** 82 * Returns true if this time container is paused. 83 * Generally you should test for a specific type of pausing using 84 * IsPausedByType. 85 * 86 * @return true if this container is paused, false otherwise. 87 */ 88 bool IsPaused() const { return mPauseState != 0; } 89 90 /* 91 * Return the time elapsed since this time container's begin time (expressed 92 * in parent time) minus any accumulated offset from pausing. 93 */ 94 SMILTime GetCurrentTimeAsSMILTime() const; 95 96 /* 97 * Seek the document timeline to the specified time. 98 * 99 * @param aSeekTo The time to seek to, expressed in this time container's time 100 * base (i.e. the same units as GetCurrentTime). 101 */ 102 void SetCurrentTime(SMILTime aSeekTo); 103 104 /* 105 * Return the current time for the parent time container if any. 106 */ 107 virtual SMILTime GetParentTime() const; 108 109 /* 110 * Convert container time to parent time. 111 * 112 * @param aContainerTime The container time to convert. 113 * @return The equivalent parent time or indefinite if the container is 114 * paused and the time is in the future. 115 */ 116 SMILTimeValue ContainerToParentTime(SMILTime aContainerTime) const; 117 118 /* 119 * Convert from parent time to container time. 120 * 121 * @param aParentTime The parent time to convert. 122 * @return The equivalent container time or indefinite if the container is 123 * paused and aParentTime is after the time when the pause began. 124 */ 125 SMILTimeValue ParentToContainerTime(SMILTime aParentTime) const; 126 127 /* 128 * If the container is paused, causes the pause time to be updated to the 129 * current parent time. This should be called before updating 130 * cross-container dependencies that will call ContainerToParentTime in order 131 * to provide more intuitive results. 132 */ 133 void SyncPauseTime(); 134 135 /* 136 * Updates the current time of this time container and calls DoSample to 137 * perform any sample-operations. 138 */ 139 void Sample(); 140 141 /* 142 * Return if this time container should be sampled or can be skipped. 143 * 144 * This is most useful as an optimisation for skipping time containers that 145 * don't require a sample. 146 */ 147 bool NeedsSample() const { return !mPauseState || mNeedsPauseSample; } 148 149 /* 150 * Indicates if the elements of this time container need to be rewound. 151 * This occurs during a backwards seek. 152 */ 153 bool NeedsRewind() const { return mNeedsRewind; } 154 void ClearNeedsRewind() { mNeedsRewind = false; } 155 156 /* 157 * Indicates the time container is currently processing a SetCurrentTime 158 * request and appropriate seek behaviour should be applied by child elements 159 * (e.g. not firing time events). 160 */ 161 bool IsSeeking() const { return mIsSeeking; } 162 void MarkSeekFinished() { mIsSeeking = false; } 163 164 /* 165 * Sets the parent time container. 166 * 167 * The callee still retains ownership of the time container. 168 */ 169 nsresult SetParent(SMILTimeContainer* aParent); 170 171 /* 172 * Registers an element for a sample at the given time. 173 * 174 * @param aMilestone The milestone to register in container time. 175 * @param aElement The timebase element that needs a sample at 176 * aMilestone. 177 */ 178 void AddMilestone(const SMILMilestone& aMilestone, 179 mozilla::dom::SVGAnimationElement& aElement); 180 181 /* 182 * Resets the list of milestones. 183 */ 184 void ClearMilestones(); 185 186 /* 187 * Returns the next significant transition from amongst the registered 188 * milestones. 189 * 190 * @param[out] aNextMilestone The next milestone with time in parent time. 191 * 192 * @return true if there exists another milestone, false otherwise in 193 * which case aNextMilestone will be unmodified. 194 */ 195 bool GetNextMilestoneInParentTime(SMILMilestone& aNextMilestone) const; 196 197 using AnimElemArray = nsTArray<RefPtr<dom::SVGAnimationElement>>; 198 199 /* 200 * Removes and returns the timebase elements from the start of the list of 201 * timebase elements that match the given time. 202 * 203 * @param aMilestone The milestone time to match in parent time. This 204 * must be <= GetNextMilestoneInParentTime. 205 * @param[out] aMatchedElements The array to which matching elements will be 206 * appended. 207 * @return true if one or more elements match, false otherwise. 208 */ 209 bool PopMilestoneElementsAtMilestone(const SMILMilestone& aMilestone, 210 AnimElemArray& aMatchedElements); 211 212 // Cycle-collection support 213 void Traverse(nsCycleCollectionTraversalCallback* aCallback); 214 void Unlink(); 215 216 protected: 217 /* 218 * Per-sample operations to be performed whenever Sample() is called and 219 * NeedsSample() is true. Called after updating mCurrentTime; 220 */ 221 virtual void DoSample() {} 222 223 /* 224 * Adding and removing child containers is not implemented in the base class 225 * because not all subclasses need this. 226 */ 227 228 /* 229 * Adds a child time container. 230 */ 231 virtual nsresult AddChild(SMILTimeContainer& aChild) { 232 return NS_ERROR_FAILURE; 233 } 234 235 /* 236 * Removes a child time container. 237 */ 238 virtual void RemoveChild(SMILTimeContainer& aChild) {} 239 240 /* 241 * Implementation helper to update the current time. 242 */ 243 void UpdateCurrentTime(); 244 245 /* 246 * Implementation helper to notify timed elements with dependencies that the 247 * container time has changed with respect to the document time. 248 */ 249 void NotifyTimeChange(); 250 251 // The parent time container, if any 252 SMILTimeContainer* mParent; 253 254 // The current time established at the last call to Sample() 255 SMILTime mCurrentTime; 256 257 // The number of milliseconds for which the container has been paused 258 // (excluding the current pause interval if the container is currently 259 // paused). 260 // 261 // Current time = parent time - mParentOffset 262 // 263 SMILTime mParentOffset; 264 265 // The time the time container will pause when it reaches this point. 266 Maybe<SMILTime> mPauseTime; 267 268 // The timestamp in parent time when the container was paused 269 SMILTime mPauseStart; 270 271 // Whether or not a pause sample is required 272 bool mNeedsPauseSample; 273 274 bool mNeedsRewind; // Backwards seek performed 275 bool mIsSeeking; // Currently in the middle of a seek operation 276 277 #ifdef DEBUG 278 bool mHoldingEntries; // True if there's a raw pointer to mMilestoneEntries 279 // on the stack. 280 #endif 281 282 // A bitfield of the pause state for all pause requests 283 uint32_t mPauseState; 284 285 struct MilestoneEntry { 286 MilestoneEntry(const SMILMilestone& aMilestone, 287 mozilla::dom::SVGAnimationElement& aElement) 288 : mMilestone(aMilestone), mTimebase(&aElement) {} 289 290 bool operator<(const MilestoneEntry& aOther) const { 291 return mMilestone < aOther.mMilestone; 292 } 293 294 SMILMilestone mMilestone; // In container time. 295 RefPtr<mozilla::dom::SVGAnimationElement> mTimebase; 296 }; 297 298 // Queue of elements with registered milestones. Used to update the model with 299 // significant transitions that occur between two samples. Since timed element 300 // re-register their milestones when they're sampled this is reset once we've 301 // taken care of the milestones before the current sample time but before we 302 // actually do the full sample. 303 nsTPriorityQueue<MilestoneEntry> mMilestoneEntries; 304 }; 305 306 } // namespace mozilla 307 308 #endif // DOM_SMIL_SMILTIMECONTAINER_H_