summaryrefslogtreecommitdiffstats
path: root/dom/smil/SMILTimeContainer.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/smil/SMILTimeContainer.h299
1 files changed, 299 insertions, 0 deletions
diff --git a/dom/smil/SMILTimeContainer.h b/dom/smil/SMILTimeContainer.h
new file mode 100644
index 0000000000..62ea7ad2c4
--- /dev/null
+++ b/dom/smil/SMILTimeContainer.h
@@ -0,0 +1,299 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef DOM_SMIL_SMILTIMECONTAINER_H_
+#define DOM_SMIL_SMILTIMECONTAINER_H_
+
+#include "mozilla/dom/SVGAnimationElement.h"
+#include "mozilla/SMILMilestone.h"
+#include "mozilla/SMILTypes.h"
+#include "nscore.h"
+#include "nsTPriorityQueue.h"
+
+namespace mozilla {
+
+class SMILTimeValue;
+
+//----------------------------------------------------------------------
+// SMILTimeContainer
+//
+// Common base class for a time base that can be paused, resumed, and sampled.
+//
+class SMILTimeContainer {
+ public:
+ SMILTimeContainer();
+ virtual ~SMILTimeContainer();
+
+ /*
+ * Pause request types.
+ */
+ enum {
+ PAUSE_BEGIN = 1, // Paused because timeline has yet to begin.
+ PAUSE_SCRIPT = 2, // Paused by script.
+ PAUSE_PAGEHIDE = 4, // Paused because our doc is hidden.
+ PAUSE_USERPREF = 8, // Paused because animations are disabled in prefs.
+ PAUSE_IMAGE = 16 // Paused becuase we're in an image that's suspended.
+ };
+
+ /*
+ * Cause the time container to record its begin time.
+ */
+ void Begin();
+
+ /*
+ * Pause this time container
+ *
+ * @param aType The source of the pause request. Successive calls to Pause
+ * with the same aType will be ignored. The container will remain paused until
+ * each call to Pause of a given aType has been matched by at least one call
+ * to Resume with the same aType.
+ */
+ virtual void Pause(uint32_t aType);
+
+ /*
+ * Resume this time container
+ *
+ * param @aType The source of the resume request. Clears the pause flag for
+ * this particular type of pause request. When all pause flags have been
+ * cleared the time container will be resumed.
+ */
+ virtual void Resume(uint32_t aType);
+
+ /**
+ * Returns true if this time container is paused by the specified type.
+ * Note that the time container may also be paused by other types; this method
+ * does not test if aType is the exclusive pause source.
+ *
+ * @param @aType The pause source to test for.
+ * @return true if this container is paused by aType.
+ */
+ bool IsPausedByType(uint32_t aType) const { return mPauseState & aType; }
+
+ /**
+ * Returns true if this time container is paused.
+ * Generally you should test for a specific type of pausing using
+ * IsPausedByType.
+ *
+ * @return true if this container is paused, false otherwise.
+ */
+ bool IsPaused() const { return mPauseState != 0; }
+
+ /*
+ * Return the time elapsed since this time container's begin time (expressed
+ * in parent time) minus any accumulated offset from pausing.
+ */
+ SMILTime GetCurrentTimeAsSMILTime() const;
+
+ /*
+ * Seek the document timeline to the specified time.
+ *
+ * @param aSeekTo The time to seek to, expressed in this time container's time
+ * base (i.e. the same units as GetCurrentTime).
+ */
+ void SetCurrentTime(SMILTime aSeekTo);
+
+ /*
+ * Return the current time for the parent time container if any.
+ */
+ virtual SMILTime GetParentTime() const;
+
+ /*
+ * Convert container time to parent time.
+ *
+ * @param aContainerTime The container time to convert.
+ * @return The equivalent parent time or indefinite if the container is
+ * paused and the time is in the future.
+ */
+ SMILTimeValue ContainerToParentTime(SMILTime aContainerTime) const;
+
+ /*
+ * Convert from parent time to container time.
+ *
+ * @param aParentTime The parent time to convert.
+ * @return The equivalent container time or indefinite if the container is
+ * paused and aParentTime is after the time when the pause began.
+ */
+ SMILTimeValue ParentToContainerTime(SMILTime aParentTime) const;
+
+ /*
+ * If the container is paused, causes the pause time to be updated to the
+ * current parent time. This should be called before updating
+ * cross-container dependencies that will call ContainerToParentTime in order
+ * to provide more intuitive results.
+ */
+ void SyncPauseTime();
+
+ /*
+ * Updates the current time of this time container and calls DoSample to
+ * perform any sample-operations.
+ */
+ void Sample();
+
+ /*
+ * Return if this time container should be sampled or can be skipped.
+ *
+ * This is most useful as an optimisation for skipping time containers that
+ * don't require a sample.
+ */
+ bool NeedsSample() const { return !mPauseState || mNeedsPauseSample; }
+
+ /*
+ * Indicates if the elements of this time container need to be rewound.
+ * This occurs during a backwards seek.
+ */
+ bool NeedsRewind() const { return mNeedsRewind; }
+ void ClearNeedsRewind() { mNeedsRewind = false; }
+
+ /*
+ * Indicates the time container is currently processing a SetCurrentTime
+ * request and appropriate seek behaviour should be applied by child elements
+ * (e.g. not firing time events).
+ */
+ bool IsSeeking() const { return mIsSeeking; }
+ void MarkSeekFinished() { mIsSeeking = false; }
+
+ /*
+ * Sets the parent time container.
+ *
+ * The callee still retains ownership of the time container.
+ */
+ nsresult SetParent(SMILTimeContainer* aParent);
+
+ /*
+ * Registers an element for a sample at the given time.
+ *
+ * @param aMilestone The milestone to register in container time.
+ * @param aElement The timebase element that needs a sample at
+ * aMilestone.
+ */
+ void AddMilestone(const SMILMilestone& aMilestone,
+ mozilla::dom::SVGAnimationElement& aElement);
+
+ /*
+ * Resets the list of milestones.
+ */
+ void ClearMilestones();
+
+ /*
+ * Returns the next significant transition from amongst the registered
+ * milestones.
+ *
+ * @param[out] aNextMilestone The next milestone with time in parent time.
+ *
+ * @return true if there exists another milestone, false otherwise in
+ * which case aNextMilestone will be unmodified.
+ */
+ bool GetNextMilestoneInParentTime(SMILMilestone& aNextMilestone) const;
+
+ using AnimElemArray = nsTArray<RefPtr<dom::SVGAnimationElement>>;
+
+ /*
+ * Removes and returns the timebase elements from the start of the list of
+ * timebase elements that match the given time.
+ *
+ * @param aMilestone The milestone time to match in parent time. This
+ * must be <= GetNextMilestoneInParentTime.
+ * @param[out] aMatchedElements The array to which matching elements will be
+ * appended.
+ * @return true if one or more elements match, false otherwise.
+ */
+ bool PopMilestoneElementsAtMilestone(const SMILMilestone& aMilestone,
+ AnimElemArray& aMatchedElements);
+
+ // Cycle-collection support
+ void Traverse(nsCycleCollectionTraversalCallback* aCallback);
+ void Unlink();
+
+ protected:
+ /*
+ * Per-sample operations to be performed whenever Sample() is called and
+ * NeedsSample() is true. Called after updating mCurrentTime;
+ */
+ virtual void DoSample() {}
+
+ /*
+ * Adding and removing child containers is not implemented in the base class
+ * because not all subclasses need this.
+ */
+
+ /*
+ * Adds a child time container.
+ */
+ virtual nsresult AddChild(SMILTimeContainer& aChild) {
+ return NS_ERROR_FAILURE;
+ }
+
+ /*
+ * Removes a child time container.
+ */
+ virtual void RemoveChild(SMILTimeContainer& aChild) {}
+
+ /*
+ * Implementation helper to update the current time.
+ */
+ void UpdateCurrentTime();
+
+ /*
+ * Implementation helper to notify timed elements with dependencies that the
+ * container time has changed with respect to the document time.
+ */
+ void NotifyTimeChange();
+
+ // The parent time container, if any
+ SMILTimeContainer* mParent;
+
+ // The current time established at the last call to Sample()
+ SMILTime mCurrentTime;
+
+ // The number of milliseconds for which the container has been paused
+ // (excluding the current pause interval if the container is currently
+ // paused).
+ //
+ // Current time = parent time - mParentOffset
+ //
+ SMILTime mParentOffset;
+
+ // The timestamp in parent time when the container was paused
+ SMILTime mPauseStart;
+
+ // Whether or not a pause sample is required
+ bool mNeedsPauseSample;
+
+ bool mNeedsRewind; // Backwards seek performed
+ bool mIsSeeking; // Currently in the middle of a seek operation
+
+#ifdef DEBUG
+ bool mHoldingEntries; // True if there's a raw pointer to mMilestoneEntries
+ // on the stack.
+#endif
+
+ // A bitfield of the pause state for all pause requests
+ uint32_t mPauseState;
+
+ struct MilestoneEntry {
+ MilestoneEntry(const SMILMilestone& aMilestone,
+ mozilla::dom::SVGAnimationElement& aElement)
+ : mMilestone(aMilestone), mTimebase(&aElement) {}
+
+ bool operator<(const MilestoneEntry& aOther) const {
+ return mMilestone < aOther.mMilestone;
+ }
+
+ SMILMilestone mMilestone; // In container time.
+ RefPtr<mozilla::dom::SVGAnimationElement> mTimebase;
+ };
+
+ // Queue of elements with registered milestones. Used to update the model with
+ // significant transitions that occur between two samples. Since timed element
+ // re-register their milestones when they're sampled this is reset once we've
+ // taken care of the milestones before the current sample time but before we
+ // actually do the full sample.
+ nsTPriorityQueue<MilestoneEntry> mMilestoneEntries;
+};
+
+} // namespace mozilla
+
+#endif // DOM_SMIL_SMILTIMECONTAINER_H_