Bug 1835710 - Cancel off-thread JIT compilation before changing nursery allocation...
[gecko.git] / dom / smil / SMILTimedElement.h
blobfc2792d1dc1f3d8ef5eee7032e25ef1756e6b7ff
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/. */
7 #ifndef DOM_SMIL_SMILTIMEDELEMENT_H_
8 #define DOM_SMIL_SMILTIMEDELEMENT_H_
10 #include <utility>
12 #include "mozilla/EventForwards.h"
13 #include "mozilla/SMILInstanceTime.h"
14 #include "mozilla/SMILInterval.h"
15 #include "mozilla/SMILMilestone.h"
16 #include "mozilla/SMILRepeatCount.h"
17 #include "mozilla/SMILTimeValueSpec.h"
18 #include "mozilla/SMILTypes.h"
19 #include "mozilla/UniquePtr.h"
20 #include "nsAttrValue.h"
21 #include "nsHashKeys.h"
22 #include "nsTArray.h"
23 #include "nsTHashtable.h"
25 class nsAtom;
27 namespace mozilla {
29 class SMILAnimationFunction;
30 class SMILTimeContainer;
31 class SMILTimeValue;
33 namespace dom {
34 class SVGAnimationElement;
35 } // namespace dom
37 //----------------------------------------------------------------------
38 // SMILTimedElement
40 class SMILTimedElement {
41 public:
42 SMILTimedElement();
43 ~SMILTimedElement();
45 using Element = dom::Element;
48 * Sets the owning animation element which this class uses to convert between
49 * container times and to register timebase elements.
51 void SetAnimationElement(mozilla::dom::SVGAnimationElement* aElement);
54 * Returns the time container with which this timed element is associated or
55 * nullptr if it is not associated with a time container.
57 SMILTimeContainer* GetTimeContainer();
60 * Returns the element targeted by the animation element. Needed for
61 * registering event listeners against the appropriate element.
63 Element* GetTargetElement();
65 /**
66 * Methods for supporting the ElementTimeControl interface.
70 * Adds a new begin instance time at the current container time plus or minus
71 * the specified offset.
73 * @param aOffsetSeconds A real number specifying the number of seconds to add
74 * to the current container time.
75 * @return NS_OK if the operation succeeeded, or an error code otherwise.
77 nsresult BeginElementAt(double aOffsetSeconds);
80 * Adds a new end instance time at the current container time plus or minus
81 * the specified offset.
83 * @param aOffsetSeconds A real number specifying the number of seconds to add
84 * to the current container time.
85 * @return NS_OK if the operation succeeeded, or an error code otherwise.
87 nsresult EndElementAt(double aOffsetSeconds);
89 /**
90 * Methods for supporting the SVGAnimationElement interface.
93 /**
94 * According to SVG 1.1 SE this returns
96 * the begin time, in seconds, for this animation element's current
97 * interval, if it exists, regardless of whether the interval has begun yet.
99 * @return the start time as defined above in milliseconds or an unresolved
100 * time if there is no current interval.
102 SMILTimeValue GetStartTime() const;
105 * Returns the simple duration of this element.
107 * @return the simple duration in milliseconds or INDEFINITE.
109 SMILTimeValue GetSimpleDuration() const { return mSimpleDur; }
112 * Methods for supporting hyperlinking
116 * Internal SMIL methods
120 * Returns the time to seek the document to when this element is targetted by
121 * a hyperlink.
123 * The behavior is defined here:
124 * http://www.w3.org/TR/smil-animation/#HyperlinkSemantics
126 * It is very similar to GetStartTime() with the exception that when the
127 * element is not active, the begin time of the *first* interval is returned.
129 * @return the time to seek the documen to in milliseconds or an unresolved
130 * time if there is no resolved interval.
132 SMILTimeValue GetHyperlinkTime() const;
135 * Adds an instance time object this element's list of instance times.
136 * These instance times are used when creating intervals.
138 * This method is typically called by an SMILTimeValueSpec.
140 * @param aInstanceTime The time to add, expressed in container time.
141 * @param aIsBegin true if the time to be added represents a begin
142 * time or false if it represents an end time.
144 void AddInstanceTime(SMILInstanceTime* aInstanceTime, bool aIsBegin);
147 * Requests this element update the given instance time.
149 * This method is typically called by a child SMILTimeValueSpec.
151 * @param aInstanceTime The instance time to update.
152 * @param aUpdatedTime The time to update aInstanceTime with.
153 * @param aDependentTime The instance time upon which aInstanceTime should be
154 * based.
155 * @param aIsBegin true if the time to be updated represents a begin
156 * instance time or false if it represents an end
157 * instance time.
159 void UpdateInstanceTime(SMILInstanceTime* aInstanceTime,
160 SMILTimeValue& aUpdatedTime, bool aIsBegin);
163 * Removes an instance time object from this element's list of instance times.
165 * This method is typically called by a child SMILTimeValueSpec.
167 * @param aInstanceTime The instance time to remove.
168 * @param aIsBegin true if the time to be removed represents a begin
169 * time or false if it represents an end time.
171 void RemoveInstanceTime(SMILInstanceTime* aInstanceTime, bool aIsBegin);
174 * Removes all the instance times associated with the given
175 * SMILTimeValueSpec object. Used when an ID assignment changes and hence
176 * all the previously associated instance times become invalid.
178 * @param aCreator The SMILTimeValueSpec object whose created
179 * SMILInstanceTime's should be removed.
180 * @param aIsBegin true if the times to be removed represent begin
181 * times or false if they are end times.
183 void RemoveInstanceTimesForCreator(const SMILTimeValueSpec* aCreator,
184 bool aIsBegin);
187 * Sets the object that will be called by this timed element each time it is
188 * sampled.
190 * In Schmitz's model it is possible to associate several time clients with
191 * a timed element but for now we only allow one.
193 * @param aClient The time client to associate. Any previous time client
194 * will be disassociated and no longer sampled. Setting this
195 * to nullptr will simply disassociate the previous client,
196 * if any.
198 void SetTimeClient(SMILAnimationFunction* aClient);
201 * Samples the object at the given container time. Timing intervals are
202 * updated and if this element is active at the given time the associated time
203 * client will be sampled with the appropriate simple time.
205 * @param aContainerTime The container time at which to sample.
207 void SampleAt(SMILTime aContainerTime);
210 * Performs a special sample for the end of an interval. Such a sample should
211 * only advance the timed element (and any dependent elements) to the waiting
212 * or postactive state. It should not cause a transition to the active state.
213 * Transition to the active state is only performed on a regular SampleAt.
215 * This allows all interval ends at a given time to be processed first and
216 * hence the new interval can be established based on full information of the
217 * available instance times.
219 * @param aContainerTime The container time at which to sample.
221 void SampleEndAt(SMILTime aContainerTime);
224 * Informs the timed element that its time container has changed time
225 * relative to document time. The timed element therefore needs to update its
226 * dependent elements (which may belong to a different time container) so they
227 * can re-resolve their times.
229 void HandleContainerTimeChange();
232 * Resets this timed element's accumulated times and intervals back to start
233 * up state.
235 * This is used for backwards seeking where rather than accumulating
236 * historical timing state and winding it back, we reset the element and seek
237 * forwards.
239 void Rewind();
242 * Marks this element as disabled or not. If the element is disabled, it
243 * will ignore any future samples and discard any accumulated timing state.
245 * This is used by SVG to "turn off" timed elements when the associated
246 * animation element has failing conditional processing tests.
248 * Returns true if the disabled state of the timed element was changed
249 * as a result of this call (i.e. it was not a redundant call).
251 bool SetIsDisabled(bool aIsDisabled);
254 * Attempts to set an attribute on this timed element.
256 * @param aAttribute The name of the attribute to set. The namespace of this
257 * attribute is not specified as it is checked by the host
258 * element. Only attributes in the namespace defined for
259 * SMIL attributes in the host language are passed to the
260 * timed element.
261 * @param aValue The attribute value.
262 * @param aResult The nsAttrValue object that may be used for storing the
263 * parsed result.
264 * @param aContextElement The element to use for context when resolving
265 * references to other elements.
266 * @param[out] aParseResult The result of parsing the attribute. Will be set
267 * to NS_OK if parsing is successful.
269 * @return true if the given attribute is a timing attribute, false
270 * otherwise.
272 bool SetAttr(nsAtom* aAttribute, const nsAString& aValue,
273 nsAttrValue& aResult, Element& aContextElement,
274 nsresult* aParseResult = nullptr);
277 * Attempts to unset an attribute on this timed element.
279 * @param aAttribute The name of the attribute to set. As with SetAttr the
280 * namespace of the attribute is not specified (see
281 * SetAttr).
283 * @return true if the given attribute is a timing attribute, false
284 * otherwise.
286 bool UnsetAttr(nsAtom* aAttribute);
289 * Adds a syncbase dependency to the list of dependents that will be notified
290 * when this timed element creates, deletes, or updates its current interval.
292 * @param aDependent The SMILTimeValueSpec object to notify. A raw pointer
293 * to this object will be stored. Therefore it is necessary
294 * for the object to be explicitly unregistered (with
295 * RemoveDependent) when it is destroyed.
297 void AddDependent(SMILTimeValueSpec& aDependent);
300 * Removes a syncbase dependency from the list of dependents that are notified
301 * when the current interval is modified.
303 * @param aDependent The SMILTimeValueSpec object to unregister.
305 void RemoveDependent(SMILTimeValueSpec& aDependent);
308 * Determines if this timed element is dependent on the given timed element's
309 * begin time for the interval currently in effect. Whilst the element is in
310 * the active state this is the current interval and in the postactive or
311 * waiting state this is the previous interval if one exists. In all other
312 * cases the element is not considered a time dependent of any other element.
314 * @param aOther The potential syncbase element.
315 * @return true if this timed element's begin time for the currently
316 * effective interval is directly or indirectly derived from aOther, false
317 * otherwise.
319 bool IsTimeDependent(const SMILTimedElement& aOther) const;
322 * Called when the timed element has been bound to the document so that
323 * references from this timed element to other elements can be resolved.
325 * @param aContextElement The element which provides the necessary context for
326 * resolving references. This is typically the element
327 * in the host language that owns this timed element.
329 void BindToTree(Element& aContextElement);
332 * Called when the target of the animation has changed so that event
333 * registrations can be updated.
335 void HandleTargetElementChange(Element* aNewTarget);
338 * Called when the timed element has been removed from a document so that
339 * references to other elements can be broken.
341 void DissolveReferences() { Unlink(); }
343 // Cycle collection
344 void Traverse(nsCycleCollectionTraversalCallback* aCallback);
345 void Unlink();
347 using RemovalTestFunction = bool (*)(SMILInstanceTime* aInstance);
349 protected:
350 // Typedefs
351 using TimeValueSpecList = nsTArray<UniquePtr<SMILTimeValueSpec>>;
352 using InstanceTimeList = nsTArray<RefPtr<SMILInstanceTime>>;
353 using IntervalList = nsTArray<UniquePtr<SMILInterval>>;
354 using TimeValueSpecPtrKey = nsPtrHashKey<SMILTimeValueSpec>;
355 using TimeValueSpecHashSet = nsTHashtable<TimeValueSpecPtrKey>;
357 // Helper classes
358 class InstanceTimeComparator {
359 public:
360 bool Equals(const SMILInstanceTime* aElem1,
361 const SMILInstanceTime* aElem2) const;
362 bool LessThan(const SMILInstanceTime* aElem1,
363 const SMILInstanceTime* aElem2) const;
366 // Templated helper functions
367 template <class TestFunctor>
368 void RemoveInstanceTimes(InstanceTimeList& aArray, TestFunctor& aTest);
371 // Implementation helpers
374 nsresult SetBeginSpec(const nsAString& aBeginSpec, Element& aContextElement,
375 RemovalTestFunction aRemove);
376 nsresult SetEndSpec(const nsAString& aEndSpec, Element& aContextElement,
377 RemovalTestFunction aRemove);
378 nsresult SetSimpleDuration(const nsAString& aDurSpec);
379 nsresult SetMin(const nsAString& aMinSpec);
380 nsresult SetMax(const nsAString& aMaxSpec);
381 nsresult SetRestart(const nsAString& aRestartSpec);
382 nsresult SetRepeatCount(const nsAString& aRepeatCountSpec);
383 nsresult SetRepeatDur(const nsAString& aRepeatDurSpec);
384 nsresult SetFillMode(const nsAString& aFillModeSpec);
386 void UnsetBeginSpec(RemovalTestFunction aRemove);
387 void UnsetEndSpec(RemovalTestFunction aRemove);
388 void UnsetSimpleDuration();
389 void UnsetMin();
390 void UnsetMax();
391 void UnsetRestart();
392 void UnsetRepeatCount();
393 void UnsetRepeatDur();
394 void UnsetFillMode();
396 nsresult SetBeginOrEndSpec(const nsAString& aSpec, Element& aContextElement,
397 bool aIsBegin, RemovalTestFunction aRemove);
398 void ClearSpecs(TimeValueSpecList& aSpecs, InstanceTimeList& aInstances,
399 RemovalTestFunction aRemove);
400 void ClearIntervals();
401 void DoSampleAt(SMILTime aContainerTime, bool aEndOnly);
404 * Helper function to check for an early end and, if necessary, update the
405 * current interval accordingly.
407 * See SMIL 3.0, section 5.4.5, Element life cycle, "Active Time - Playing an
408 * interval" for a description of ending early.
410 * @param aSampleTime The current sample time. Early ends should only be
411 * applied at the last possible moment (i.e. if they are at
412 * or before the current sample time) and only if the
413 * current interval is not already ending.
414 * @return true if the end time of the current interval was updated,
415 * false otherwise.
417 bool ApplyEarlyEnd(const SMILTimeValue& aSampleTime);
420 * Clears certain state in response to the element restarting.
422 * This state is described in SMIL 3.0, section 5.4.3, Resetting element state
424 void Reset();
427 * Clears all accumulated timing state except for those instance times for
428 * which aRemove does not return true.
430 * Unlike the Reset method which only clears instance times, this clears the
431 * element's state, intervals (including current interval), and tells the
432 * client animation function to stop applying a result. In effect, it returns
433 * the element to its initial state but preserves any instance times excluded
434 * by the passed-in function.
436 void ClearTimingState(RemovalTestFunction aRemove);
439 * Recreates timing state by re-applying begin/end attributes specified on
440 * the associated animation element.
442 * Note that this does not completely restore the information cleared by
443 * ClearTimingState since it leaves the element in the startup state.
444 * The element state will be updated on the next sample.
446 void RebuildTimingState(RemovalTestFunction aRemove);
449 * Completes a seek operation by sending appropriate events and, in the case
450 * of a backwards seek, updating the state of timing information that was
451 * previously considered historical.
453 void DoPostSeek();
456 * Unmarks instance times that were previously preserved because they were
457 * considered important historical milestones but are no longer such because
458 * a backwards seek has been performed.
460 void UnpreserveInstanceTimes(InstanceTimeList& aList);
463 * Helper function to iterate through this element's accumulated timing
464 * information (specifically old SMILIntervals and SMILTimeInstanceTimes)
465 * and discard items that are no longer needed or exceed some threshold of
466 * accumulated state.
468 void FilterHistory();
470 // Helper functions for FilterHistory to clear old SMILIntervals and
471 // SMILInstanceTimes respectively.
472 void FilterIntervals();
473 void FilterInstanceTimes(InstanceTimeList& aList);
476 * Calculates the next acceptable interval for this element after the
477 * specified interval, or, if no previous interval is specified, it will be
478 * the first interval with an end time after t=0.
480 * @see SMILANIM 3.6.8
482 * @param aPrevInterval The previous interval used. If supplied, the first
483 * interval that begins after aPrevInterval will be
484 * returned. May be nullptr.
485 * @param aReplacedInterval The interval that is being updated (if any). This
486 * used to ensure we don't return interval endpoints
487 * that are dependent on themselves. May be nullptr.
488 * @param aFixedBeginTime The time to use for the start of the interval. This
489 * is used when only the endpoint of the interval
490 * should be updated such as when the animation is in
491 * the ACTIVE state. May be nullptr.
492 * @param[out] aResult The next interval. Will be unchanged if no suitable
493 * interval was found (in which case false will be
494 * returned).
495 * @return true if a suitable interval was found, false otherwise.
497 bool GetNextInterval(const SMILInterval* aPrevInterval,
498 const SMILInterval* aReplacedInterval,
499 const SMILInstanceTime* aFixedBeginTime,
500 SMILInterval& aResult) const;
501 SMILInstanceTime* GetNextGreater(const InstanceTimeList& aList,
502 const SMILTimeValue& aBase,
503 int32_t& aPosition) const;
504 SMILInstanceTime* GetNextGreaterOrEqual(const InstanceTimeList& aList,
505 const SMILTimeValue& aBase,
506 int32_t& aPosition) const;
507 SMILTimeValue CalcActiveEnd(const SMILTimeValue& aBegin,
508 const SMILTimeValue& aEnd) const;
509 SMILTimeValue GetRepeatDuration() const;
510 SMILTimeValue ApplyMinAndMax(const SMILTimeValue& aDuration) const;
511 SMILTime ActiveTimeToSimpleTime(SMILTime aActiveTime,
512 uint32_t& aRepeatIteration);
513 SMILInstanceTime* CheckForEarlyEnd(const SMILTimeValue& aContainerTime) const;
514 void UpdateCurrentInterval(bool aForceChangeNotice = false);
515 void SampleSimpleTime(SMILTime aActiveTime);
516 void SampleFillValue();
517 nsresult AddInstanceTimeFromCurrentTime(SMILTime aCurrentTime,
518 double aOffsetSeconds, bool aIsBegin);
519 void RegisterMilestone();
520 bool GetNextMilestone(SMILMilestone& aNextMilestone) const;
522 // Notification methods. Note that these notifications can result in nested
523 // calls to this same object. Therefore,
524 // (i) we should not perform notification until this object is in
525 // a consistent state to receive callbacks, and
526 // (ii) after calling these methods we must assume that the state of the
527 // element may have changed.
528 void NotifyNewInterval();
529 void NotifyChangedInterval(SMILInterval* aInterval, bool aBeginObjectChanged,
530 bool aEndObjectChanged);
532 void FireTimeEventAsync(EventMessage aMsg, int32_t aDetail);
533 const SMILInstanceTime* GetEffectiveBeginInstance() const;
534 const SMILInterval* GetPreviousInterval() const;
535 bool HasPlayed() const { return !mOldIntervals.IsEmpty(); }
536 bool HasClientInFillRange() const;
537 bool EndHasEventConditions() const;
538 bool AreEndTimesDependentOn(const SMILInstanceTime* aBase) const;
540 // Reset the current interval by first passing ownership to a temporary
541 // variable so that if Unlink() results in us receiving a callback,
542 // mCurrentInterval will be nullptr and we will be in a consistent state.
543 void ResetCurrentInterval() {
544 if (mCurrentInterval) {
545 // Transfer ownership to temp var. (This sets mCurrentInterval to null.)
546 auto interval = std::move(mCurrentInterval);
547 interval->Unlink();
552 // Members
554 mozilla::dom::SVGAnimationElement* mAnimationElement; // [weak] won't outlive
555 // owner
556 TimeValueSpecList mBeginSpecs; // [strong]
557 TimeValueSpecList mEndSpecs; // [strong]
559 SMILTimeValue mSimpleDur;
561 SMILRepeatCount mRepeatCount;
562 SMILTimeValue mRepeatDur;
564 SMILTimeValue mMin;
565 SMILTimeValue mMax;
567 enum SMILFillMode : uint8_t { FILL_REMOVE, FILL_FREEZE };
568 SMILFillMode mFillMode;
569 static const nsAttrValue::EnumTable sFillModeTable[];
571 enum SMILRestartMode : uint8_t {
572 RESTART_ALWAYS,
573 RESTART_WHENNOTACTIVE,
574 RESTART_NEVER
576 SMILRestartMode mRestartMode;
577 static const nsAttrValue::EnumTable sRestartModeTable[];
579 InstanceTimeList mBeginInstances;
580 InstanceTimeList mEndInstances;
581 uint32_t mInstanceSerialIndex;
583 SMILAnimationFunction* mClient;
584 UniquePtr<SMILInterval> mCurrentInterval;
585 IntervalList mOldIntervals;
586 uint32_t mCurrentRepeatIteration;
587 SMILMilestone mPrevRegisteredMilestone;
588 static const SMILMilestone sMaxMilestone;
589 static const uint8_t sMaxNumIntervals;
590 static const uint8_t sMaxNumInstanceTimes;
592 // Set of dependent time value specs to be notified when establishing a new
593 // current interval. Change notifications and delete notifications are handled
594 // by the interval.
596 // [weak] The SMILTimeValueSpec objects register themselves and unregister
597 // on destruction. Likewise, we notify them when we are destroyed.
598 TimeValueSpecHashSet mTimeDependents;
601 * The state of the element in its life-cycle. These states are based on the
602 * element life-cycle described in SMILANIM 3.6.8
604 enum SMILElementState {
605 STATE_STARTUP,
606 STATE_WAITING,
607 STATE_ACTIVE,
608 STATE_POSTACTIVE
610 SMILElementState mElementState;
612 enum SMILSeekState {
613 SEEK_NOT_SEEKING,
614 SEEK_FORWARD_FROM_ACTIVE,
615 SEEK_FORWARD_FROM_INACTIVE,
616 SEEK_BACKWARD_FROM_ACTIVE,
617 SEEK_BACKWARD_FROM_INACTIVE
619 SMILSeekState mSeekState;
621 // Used to batch updates to the timing model
622 class AutoIntervalUpdateBatcher;
623 bool mDeferIntervalUpdates;
624 bool mDoDeferredUpdate; // Set if an update to the current interval was
625 // requested while mDeferIntervalUpdates was set
626 bool mIsDisabled;
628 // Stack-based helper class to call UpdateCurrentInterval when it is destroyed
629 class AutoIntervalUpdater;
631 // Recursion depth checking
632 uint8_t mDeleteCount;
633 uint8_t mUpdateIntervalRecursionDepth;
634 static const uint8_t sMaxUpdateIntervalRecursionDepth;
637 inline void ImplCycleCollectionUnlink(SMILTimedElement& aField) {
638 aField.Unlink();
641 inline void ImplCycleCollectionTraverse(
642 nsCycleCollectionTraversalCallback& aCallback, SMILTimedElement& aField,
643 const char* aName, uint32_t aFlags = 0) {
644 aField.Traverse(&aCallback);
647 } // namespace mozilla
649 #endif // DOM_SMIL_SMILTIMEDELEMENT_H_