Add support for the frames() timing function
[WebKit-https.git] / Source / WebCore / platform / animation / TimingFunction.h
1 /*
2  * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
3  *           (C) 2000 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2000 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
6  * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  */
24
25 #pragma once
26
27 #include <wtf/Ref.h>
28 #include <wtf/RefCounted.h>
29
30 namespace WTF {
31 class TextStream;
32 }
33
34 namespace WebCore {
35
36 class TimingFunction : public RefCounted<TimingFunction> {
37 public:
38     virtual Ref<TimingFunction> clone() const = 0;
39
40     virtual ~TimingFunction() = default;
41
42     enum TimingFunctionType { LinearFunction, CubicBezierFunction, StepsFunction, FramesFunction, SpringFunction };
43     TimingFunctionType type() const { return m_type; }
44
45     bool isLinearTimingFunction() const { return m_type == LinearFunction; }
46     bool isCubicBezierTimingFunction() const { return m_type == CubicBezierFunction; }
47     bool isStepsTimingFunction() const { return m_type == StepsFunction; }
48     bool isFramesTimingFunction() const { return m_type == FramesFunction; }
49     bool isSpringTimingFunction() const { return m_type == SpringFunction; }
50
51     virtual bool operator==(const TimingFunction&) const = 0;
52     bool operator!=(const TimingFunction& other) const { return !(*this == other); }
53
54     double transformTime(double, double) const;
55
56 protected:
57     explicit TimingFunction(TimingFunctionType type)
58         : m_type(type)
59     {
60     }
61
62 private:
63     TimingFunctionType m_type;
64 };
65
66 class LinearTimingFunction final : public TimingFunction {
67 public:
68     static Ref<LinearTimingFunction> create()
69     {
70         return adoptRef(*new LinearTimingFunction);
71     }
72     
73     bool operator==(const TimingFunction& other) const final
74     {
75         return other.isLinearTimingFunction();
76     }
77
78 private:
79     LinearTimingFunction()
80         : TimingFunction(LinearFunction)
81     {
82     }
83
84     Ref<TimingFunction> clone() const final
85     {
86         return adoptRef(*new LinearTimingFunction);
87     }
88 };
89
90 class CubicBezierTimingFunction final : public TimingFunction {
91 public:
92     enum TimingFunctionPreset { Ease, EaseIn, EaseOut, EaseInOut, Custom };
93     
94     static Ref<CubicBezierTimingFunction> create(double x1, double y1, double x2, double y2)
95     {
96         return adoptRef(*new CubicBezierTimingFunction(Custom, x1, y1, x2, y2));
97     }
98
99     static Ref<CubicBezierTimingFunction> create()
100     {
101         return adoptRef(*new CubicBezierTimingFunction());
102     }
103     
104     static Ref<CubicBezierTimingFunction> create(TimingFunctionPreset preset)
105     {
106         switch (preset) {
107         case Ease:
108             return adoptRef(*new CubicBezierTimingFunction);
109         case EaseIn:
110             return adoptRef(*new CubicBezierTimingFunction(EaseIn, 0.42, 0.0, 1.0, 1.0));
111         case EaseOut:
112             return adoptRef(*new CubicBezierTimingFunction(EaseOut, 0.0, 0.0, 0.58, 1.0));
113         case EaseInOut:
114             return adoptRef(*new CubicBezierTimingFunction(EaseInOut, 0.42, 0.0, 0.58, 1.0));
115         case Custom:
116             break;
117         }
118         ASSERT_NOT_REACHED();
119         return adoptRef(*new CubicBezierTimingFunction);
120     }
121
122     bool operator==(const TimingFunction& other) const final
123     {
124         if (!other.isCubicBezierTimingFunction())
125             return false;
126         auto& otherCubic = static_cast<const CubicBezierTimingFunction&>(other);
127         if (m_timingFunctionPreset != otherCubic.m_timingFunctionPreset)
128             return false;
129         if (m_timingFunctionPreset != Custom)
130             return true;
131         return m_x1 == otherCubic.m_x1 && m_y1 == otherCubic.m_y1 && m_x2 == otherCubic.m_x2 && m_y2 == otherCubic.m_y2;
132     }
133
134     double x1() const { return m_x1; }
135     double y1() const { return m_y1; }
136     double x2() const { return m_x2; }
137     double y2() const { return m_y2; }
138     
139     void setValues(double x1, double y1, double x2, double y2)
140     {
141         m_x1 = x1;
142         m_y1 = y1;
143         m_x2 = x2;
144         m_y2 = y2;
145     }
146
147     TimingFunctionPreset timingFunctionPreset() const { return m_timingFunctionPreset; }
148     void setTimingFunctionPreset(TimingFunctionPreset preset) { m_timingFunctionPreset = preset; }
149
150     static const CubicBezierTimingFunction& defaultTimingFunction()
151     {
152         static const CubicBezierTimingFunction& function = create().leakRef();
153         return function;
154     }
155
156     Ref<CubicBezierTimingFunction> createReversed() const
157     {
158         return create(1.0 - m_x2, 1.0 - m_y2, 1.0 - m_x1, 1.0 - m_y1);
159     }
160
161 private:
162     explicit CubicBezierTimingFunction(TimingFunctionPreset preset = Ease, double x1 = 0.25, double y1 = 0.1, double x2 = 0.25, double y2 = 1.0)
163         : TimingFunction(CubicBezierFunction)
164         , m_x1(x1)
165         , m_y1(y1)
166         , m_x2(x2)
167         , m_y2(y2)
168         , m_timingFunctionPreset(preset)
169     {
170     }
171
172     Ref<TimingFunction> clone() const final
173     {
174         return adoptRef(*new CubicBezierTimingFunction(m_timingFunctionPreset, m_x1, m_y1, m_x2, m_y2));
175     }
176
177     double m_x1;
178     double m_y1;
179     double m_x2;
180     double m_y2;
181     TimingFunctionPreset m_timingFunctionPreset;
182 };
183
184 class StepsTimingFunction final : public TimingFunction {
185 public:
186     static Ref<StepsTimingFunction> create(int steps, bool stepAtStart)
187     {
188         return adoptRef(*new StepsTimingFunction(steps, stepAtStart));
189     }
190     static Ref<StepsTimingFunction> create()
191     {
192         return adoptRef(*new StepsTimingFunction(1, true));
193     }
194     
195     bool operator==(const TimingFunction& other) const final
196     {
197         if (!other.isStepsTimingFunction())
198             return false;
199         auto& otherSteps = static_cast<const StepsTimingFunction&>(other);
200         return m_steps == otherSteps.m_steps && m_stepAtStart == otherSteps.m_stepAtStart;
201     }
202     
203     int numberOfSteps() const { return m_steps; }
204     void setNumberOfSteps(int steps) { m_steps = steps; }
205
206     bool stepAtStart() const { return m_stepAtStart; }
207     void setStepAtStart(bool stepAtStart) { m_stepAtStart = stepAtStart; }
208
209 private:
210     StepsTimingFunction(int steps, bool stepAtStart)
211         : TimingFunction(StepsFunction)
212         , m_steps(steps)
213         , m_stepAtStart(stepAtStart)
214     {
215     }
216
217     Ref<TimingFunction> clone() const final
218     {
219         return adoptRef(*new StepsTimingFunction(m_steps, m_stepAtStart));
220     }
221     
222     int m_steps;
223     bool m_stepAtStart;
224 };
225
226 class FramesTimingFunction final : public TimingFunction {
227 public:
228     static Ref<FramesTimingFunction> create(unsigned frames)
229     {
230         return adoptRef(*new FramesTimingFunction(frames));
231     }
232     static Ref<FramesTimingFunction> create()
233     {
234         return adoptRef(*new FramesTimingFunction(2));
235     }
236
237     bool operator==(const TimingFunction& other) const final
238     {
239         if (!other.isFramesTimingFunction())
240             return false;
241         auto& otherFrames = static_cast<const FramesTimingFunction&>(other);
242         return m_frames == otherFrames.m_frames;
243     }
244     
245     unsigned numberOfFrames() const { return m_frames; }
246     void setNumberOfFrames(unsigned frames) { m_frames = frames; }
247
248 private:
249     FramesTimingFunction(unsigned frames)
250         : TimingFunction(FramesFunction)
251         , m_frames(frames)
252     {
253     }
254
255     Ref<TimingFunction> clone() const final
256     {
257         return adoptRef(*new FramesTimingFunction(m_frames));
258     }
259     
260     unsigned m_frames;
261 };
262
263 class SpringTimingFunction final : public TimingFunction {
264 public:
265     static Ref<SpringTimingFunction> create(double mass, double stiffness, double damping, double initialVelocity)
266     {
267         return adoptRef(*new SpringTimingFunction(mass, stiffness, damping, initialVelocity));
268     }
269
270     static Ref<SpringTimingFunction> create()
271     {
272         // This create() function should only be used by the argument decoders, and it is expected that
273         // real values will be filled in using setValues().
274         return create(0, 0, 0, 0);
275     }
276     
277     bool operator==(const TimingFunction& other) const final
278     {
279         if (!other.isSpringTimingFunction())
280             return false;
281         auto& otherSpring = static_cast<const SpringTimingFunction&>(other);
282         return m_mass == otherSpring.m_mass && m_stiffness == otherSpring.m_stiffness && m_damping == otherSpring.m_damping && m_initialVelocity == otherSpring.m_initialVelocity;
283     }
284
285     double mass() const { return m_mass; }
286     double stiffness() const { return m_stiffness; }
287     double damping() const { return m_damping; }
288     double initialVelocity() const { return m_initialVelocity; }
289     
290     void setValues(double mass, double stiffness, double damping, double initialVelocity)
291     {
292         m_mass = mass;
293         m_stiffness = stiffness;
294         m_damping = damping;
295         m_initialVelocity = initialVelocity;
296     }
297
298 private:
299     explicit SpringTimingFunction(double mass, double stiffness, double damping, double initialVelocity)
300         : TimingFunction(SpringFunction)
301         , m_mass(mass)
302         , m_stiffness(stiffness)
303         , m_damping(damping)
304         , m_initialVelocity(initialVelocity)
305     {
306     }
307
308     Ref<TimingFunction> clone() const final
309     {
310         return adoptRef(*new SpringTimingFunction(m_mass, m_stiffness, m_damping, m_initialVelocity));
311     }
312
313     double m_mass;
314     double m_stiffness;
315     double m_damping;
316     double m_initialVelocity;
317 };
318
319 WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const TimingFunction&);
320
321 } // namespace WebCore