Line data Source code
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 mozilla_TimingParams_h
8 : #define mozilla_TimingParams_h
9 :
10 : #include "nsStringFwd.h"
11 : #include "mozilla/dom/Nullable.h"
12 : #include "mozilla/dom/UnionTypes.h" // For OwningUnrestrictedDoubleOrString
13 : #include "mozilla/ComputedTimingFunction.h"
14 : #include "mozilla/Maybe.h"
15 : #include "mozilla/StickyTimeDuration.h"
16 : #include "mozilla/TimeStamp.h" // for TimeDuration
17 :
18 : // X11 has a #define for None
19 : #ifdef None
20 : #undef None
21 : #endif
22 : #include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for FillMode
23 : // and PlaybackDirection
24 :
25 : class nsIDocument;
26 :
27 : namespace mozilla {
28 :
29 : namespace dom {
30 : class UnrestrictedDoubleOrKeyframeEffectOptions;
31 : class UnrestrictedDoubleOrKeyframeAnimationOptions;
32 : }
33 :
34 4 : struct TimingParams
35 : {
36 0 : TimingParams() = default;
37 :
38 2 : TimingParams(float aDuration, float aDelay,
39 : float aIterationCount,
40 : dom::PlaybackDirection aDirection,
41 : dom::FillMode aFillMode)
42 2 : : mIterations(aIterationCount)
43 : , mDirection(aDirection)
44 2 : , mFill(aFillMode)
45 : {
46 2 : mDuration.emplace(StickyTimeDuration::FromMilliseconds(aDuration));
47 2 : mDelay = TimeDuration::FromMilliseconds(aDelay);
48 2 : Update();
49 2 : }
50 :
51 0 : TimingParams(const TimeDuration& aDuration,
52 : const TimeDuration& aDelay,
53 : const TimeDuration& aEndDelay,
54 : float aIterations,
55 : float aIterationStart,
56 : dom::PlaybackDirection aDirection,
57 : dom::FillMode aFillMode,
58 : Maybe<ComputedTimingFunction>&& aFunction)
59 0 : : mDelay(aDelay)
60 : , mEndDelay(aEndDelay)
61 : , mIterations(aIterations)
62 : , mIterationStart(aIterationStart)
63 : , mDirection(aDirection)
64 : , mFill(aFillMode)
65 0 : , mFunction(aFunction)
66 : {
67 0 : mDuration.emplace(aDuration);
68 0 : Update();
69 0 : }
70 :
71 : template <class OptionsType>
72 : static TimingParams FromOptionsType(
73 : const OptionsType& aOptions,
74 : nsIDocument* aDocument,
75 : ErrorResult& aRv);
76 : static TimingParams FromOptionsUnion(
77 : const dom::UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
78 : nsIDocument* aDocument, ErrorResult& aRv);
79 : static TimingParams FromOptionsUnion(
80 : const dom::UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
81 : nsIDocument* aDocument, ErrorResult& aRv);
82 :
83 : // Range-checks and validates an UnrestrictedDoubleOrString or
84 : // OwningUnrestrictedDoubleOrString object and converts to a
85 : // StickyTimeDuration value or Nothing() if aDuration is "auto".
86 : // Caller must check aRv.Failed().
87 : template <class DoubleOrString>
88 0 : static Maybe<StickyTimeDuration> ParseDuration(DoubleOrString& aDuration,
89 : ErrorResult& aRv)
90 : {
91 0 : Maybe<StickyTimeDuration> result;
92 0 : if (aDuration.IsUnrestrictedDouble()) {
93 0 : double durationInMs = aDuration.GetAsUnrestrictedDouble();
94 0 : if (durationInMs >= 0) {
95 0 : result.emplace(StickyTimeDuration::FromMilliseconds(durationInMs));
96 : } else {
97 0 : aRv.ThrowTypeError<dom::MSG_ENFORCE_RANGE_OUT_OF_RANGE>(
98 : NS_LITERAL_STRING("duration"));
99 : }
100 0 : } else if (!aDuration.GetAsString().EqualsLiteral("auto")) {
101 0 : aRv.ThrowTypeError<dom::MSG_INVALID_DURATION_ERROR>(
102 : aDuration.GetAsString());
103 : }
104 0 : return result;
105 : }
106 :
107 0 : static void ValidateIterationStart(double aIterationStart,
108 : ErrorResult& aRv)
109 : {
110 0 : if (aIterationStart < 0) {
111 0 : aRv.ThrowTypeError<dom::MSG_ENFORCE_RANGE_OUT_OF_RANGE>(
112 0 : NS_LITERAL_STRING("iterationStart"));
113 : }
114 0 : }
115 :
116 0 : static void ValidateIterations(double aIterations, ErrorResult& aRv)
117 : {
118 0 : if (IsNaN(aIterations) || aIterations < 0) {
119 0 : aRv.ThrowTypeError<dom::MSG_ENFORCE_RANGE_OUT_OF_RANGE>(
120 0 : NS_LITERAL_STRING("iterations"));
121 : }
122 0 : }
123 :
124 : static Maybe<ComputedTimingFunction> ParseEasing(const nsAString& aEasing,
125 : nsIDocument* aDocument,
126 : ErrorResult& aRv);
127 :
128 474 : static StickyTimeDuration CalcActiveDuration(
129 : const Maybe<StickyTimeDuration>& aDuration,
130 : double aIterations)
131 : {
132 : // If either the iteration duration or iteration count is zero,
133 : // Web Animations says that the active duration is zero. This is to
134 : // ensure that the result is defined when the other argument is Infinity.
135 : static const StickyTimeDuration zeroDuration;
136 474 : if (!aDuration || *aDuration == zeroDuration || aIterations == 0.0) {
137 0 : return zeroDuration;
138 : }
139 :
140 474 : return aDuration->MultDouble(aIterations);
141 : }
142 : // Return the duration of the active interval calculated by duration and
143 : // iteration count.
144 472 : StickyTimeDuration ActiveDuration() const
145 : {
146 472 : MOZ_ASSERT(CalcActiveDuration(mDuration, mIterations) == mActiveDuration,
147 : "Cached value of active duration should be up to date");
148 472 : return mActiveDuration;
149 : }
150 :
151 286 : StickyTimeDuration EndTime() const
152 : {
153 286 : MOZ_ASSERT(mEndTime == std::max(mDelay + ActiveDuration() + mEndDelay,
154 : StickyTimeDuration()),
155 : "Cached value of end time should be up to date");
156 286 : return mEndTime;
157 : }
158 :
159 : bool operator==(const TimingParams& aOther) const;
160 0 : bool operator!=(const TimingParams& aOther) const
161 : {
162 0 : return !(*this == aOther);
163 : }
164 :
165 0 : void SetDuration(Maybe<StickyTimeDuration>&& aDuration)
166 : {
167 0 : mDuration = Move(aDuration);
168 0 : Update();
169 0 : }
170 558 : const Maybe<StickyTimeDuration>& Duration() const { return mDuration; }
171 :
172 0 : void SetDelay(const TimeDuration& aDelay)
173 : {
174 0 : mDelay = aDelay;
175 0 : Update();
176 0 : }
177 584 : const TimeDuration& Delay() const { return mDelay; }
178 :
179 0 : void SetEndDelay(const TimeDuration& aEndDelay)
180 : {
181 0 : mEndDelay = aEndDelay;
182 0 : Update();
183 0 : }
184 0 : const TimeDuration& EndDelay() const { return mEndDelay; }
185 :
186 0 : void SetIterations(double aIterations)
187 : {
188 0 : mIterations = aIterations;
189 0 : Update();
190 0 : }
191 558 : double Iterations() const { return mIterations; }
192 :
193 0 : void SetIterationStart(double aIterationStart)
194 : {
195 0 : mIterationStart = aIterationStart;
196 0 : }
197 372 : double IterationStart() const { return mIterationStart; }
198 :
199 0 : void SetDirection(dom::PlaybackDirection aDirection)
200 : {
201 0 : mDirection = aDirection;
202 0 : }
203 156 : dom::PlaybackDirection Direction() const { return mDirection; }
204 :
205 0 : void SetFill(dom::FillMode aFill)
206 : {
207 0 : mFill = aFill;
208 0 : }
209 372 : dom::FillMode Fill() const { return mFill; }
210 :
211 0 : void SetTimingFunction(Maybe<ComputedTimingFunction>&& aFunction)
212 : {
213 0 : mFunction = Move(aFunction);
214 0 : }
215 156 : const Maybe<ComputedTimingFunction>& TimingFunction() const
216 : {
217 156 : return mFunction;
218 : }
219 :
220 : private:
221 2 : void Update()
222 : {
223 2 : mActiveDuration = CalcActiveDuration(mDuration, mIterations);
224 :
225 4 : mEndTime = std::max(mDelay + mActiveDuration + mEndDelay,
226 6 : StickyTimeDuration());
227 2 : }
228 :
229 : // mDuration.isNothing() represents the "auto" value
230 : Maybe<StickyTimeDuration> mDuration;
231 : TimeDuration mDelay; // Initializes to zero
232 : TimeDuration mEndDelay;
233 : double mIterations = 1.0; // Can be NaN, negative, +/-Infinity
234 : double mIterationStart = 0.0;
235 : dom::PlaybackDirection mDirection = dom::PlaybackDirection::Normal;
236 : dom::FillMode mFill = dom::FillMode::Auto;
237 : Maybe<ComputedTimingFunction> mFunction;
238 : StickyTimeDuration mActiveDuration = StickyTimeDuration();
239 : StickyTimeDuration mEndTime = StickyTimeDuration();
240 : };
241 :
242 : } // namespace mozilla
243 :
244 : #endif // mozilla_TimingParams_h
|