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#ifndef TimingFunction_h
26#define TimingFunction_h
27
28#include <wtf/RefCounted.h>
29
30namespace WebCore {
31
32class TimingFunction : public RefCounted<TimingFunction> {
33public:
34
35    virtual PassRefPtr<TimingFunction> clone() const = 0;
36
37    enum TimingFunctionType {
38        LinearFunction, CubicBezierFunction, StepsFunction
39    };
40
41    virtual ~TimingFunction() { }
42
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
49    virtual bool operator==(const TimingFunction& other) = 0;
50
51protected:
52    TimingFunction(TimingFunctionType type)
53        : m_type(type)
54    {
55    }
56
57    TimingFunctionType m_type;
58};
59
60class LinearTimingFunction : public TimingFunction {
61public:
62    static PassRefPtr<LinearTimingFunction> create()
63    {
64        return adoptRef(new LinearTimingFunction);
65    }
66
67    virtual ~LinearTimingFunction() { }
68
69    virtual bool operator==(const TimingFunction& other) override
70    {
71        return other.isLinearTimingFunction();
72    }
73
74private:
75    LinearTimingFunction()
76        : TimingFunction(LinearFunction)
77    {
78    }
79
80    virtual PassRefPtr<TimingFunction> clone() const override
81    {
82        return adoptRef(new LinearTimingFunction);
83    }
84};
85
86class CubicBezierTimingFunction : public TimingFunction {
87public:
88    enum TimingFunctionPreset {
89        Ease,
90        EaseIn,
91        EaseOut,
92        EaseInOut,
93        Custom
94    };
95
96    static PassRefPtr<CubicBezierTimingFunction> create(double x1, double y1, double x2, double y2)
97    {
98        return adoptRef(new CubicBezierTimingFunction(Custom, x1, y1, x2, y2));
99    }
100
101    static PassRefPtr<CubicBezierTimingFunction> create()
102    {
103        return adoptRef(new CubicBezierTimingFunction());
104    }
105
106    static PassRefPtr<CubicBezierTimingFunction> create(TimingFunctionPreset preset)
107    {
108        switch (preset) {
109        case Ease:
110            return adoptRef(new CubicBezierTimingFunction());
111        case EaseIn:
112            return adoptRef(new CubicBezierTimingFunction(EaseIn, 0.42, 0.0, 1.0, 1.0));
113        case EaseOut:
114            return adoptRef(new CubicBezierTimingFunction(EaseOut, 0.0, 0.0, 0.58, 1.0));
115        case EaseInOut:
116            return adoptRef(new CubicBezierTimingFunction(EaseInOut, 0.42, 0.0, 0.58, 1.0));
117        default:
118            ASSERT_NOT_REACHED();
119            return 0;
120        }
121    }
122
123    virtual ~CubicBezierTimingFunction() { }
124
125    virtual bool operator==(const TimingFunction& other) override
126    {
127        if (other.isCubicBezierTimingFunction()) {
128            const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(&other);
129            if (m_timingFunctionPreset != Custom)
130                return m_timingFunctionPreset == ctf->m_timingFunctionPreset;
131
132            return m_x1 == ctf->m_x1 && m_y1 == ctf->m_y1 && m_x2 == ctf->m_x2 && m_y2 == ctf->m_y2;
133        }
134        return false;
135    }
136
137    double x1() const { return m_x1; }
138    double y1() const { return m_y1; }
139    double x2() const { return m_x2; }
140    double y2() const { return m_y2; }
141
142    void setValues(double x1, double y1, double x2, double y2)
143    {
144        m_x1 = x1;
145        m_y1 = y1;
146        m_x2 = x2;
147        m_y2 = y2;
148    }
149
150    TimingFunctionPreset timingFunctionPreset() const { return m_timingFunctionPreset; }
151    void setTimingFunctionPreset(TimingFunctionPreset preset) { m_timingFunctionPreset = preset; }
152
153    static const CubicBezierTimingFunction* defaultTimingFunction()
154    {
155        static const CubicBezierTimingFunction* dtf = create().leakRef();
156        return dtf;
157    }
158
159    PassRefPtr<CubicBezierTimingFunction> createReversed() const
160    {
161        return create(1.0 - m_x2, 1.0 - m_y2, 1.0 - m_x1, 1.0 - m_y1);
162    }
163
164private:
165    explicit CubicBezierTimingFunction(TimingFunctionPreset preset = Ease, double x1 = 0.25, double y1 = 0.1, double x2 = 0.25, double y2 = 1.0)
166        : TimingFunction(CubicBezierFunction)
167        , m_x1(x1)
168        , m_y1(y1)
169        , m_x2(x2)
170        , m_y2(y2)
171        , m_timingFunctionPreset(preset)
172    {
173    }
174
175    virtual PassRefPtr<TimingFunction> clone() const override
176    {
177        return adoptRef(new CubicBezierTimingFunction(m_timingFunctionPreset, m_x1, m_y1, m_x2, m_y2));
178    }
179
180    double m_x1;
181    double m_y1;
182    double m_x2;
183    double m_y2;
184    TimingFunctionPreset m_timingFunctionPreset;
185};
186
187class StepsTimingFunction : public TimingFunction {
188public:
189
190    static PassRefPtr<StepsTimingFunction> create(int steps, bool stepAtStart)
191    {
192        return adoptRef(new StepsTimingFunction(steps, stepAtStart));
193    }
194    static PassRefPtr<StepsTimingFunction> create()
195    {
196        return adoptRef(new StepsTimingFunction(1, true));
197    }
198
199    virtual ~StepsTimingFunction() { }
200
201    virtual bool operator==(const TimingFunction& other) override
202    {
203        if (other.isStepsTimingFunction()) {
204            const StepsTimingFunction* stf = static_cast<const StepsTimingFunction*>(&other);
205            return m_steps == stf->m_steps && m_stepAtStart == stf->m_stepAtStart;
206        }
207        return false;
208    }
209
210    int numberOfSteps() const { return m_steps; }
211    void setNumberOfSteps(int steps) { m_steps = steps; }
212
213    bool stepAtStart() const { return m_stepAtStart; }
214    void setStepAtStart(bool stepAtStart) { m_stepAtStart = stepAtStart; }
215
216private:
217    StepsTimingFunction(int steps, bool stepAtStart)
218        : TimingFunction(StepsFunction)
219        , m_steps(steps)
220        , m_stepAtStart(stepAtStart)
221    {
222    }
223
224    virtual PassRefPtr<TimingFunction> clone() const override
225    {
226        return adoptRef(new StepsTimingFunction(m_steps, m_stepAtStart));
227    }
228
229    int m_steps;
230    bool m_stepAtStart;
231};
232
233} // namespace WebCore
234
235#endif // TimingFunction_h
236