OLD | NEW |
| (Empty) |
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 "RuntimeEnabledFeatures.h" | |
29 #include "platform/animation/AnimationUtilities.h" // For blend() | |
30 #include "platform/animation/UnitBezier.h" | |
31 #include "wtf/OwnPtr.h" | |
32 #include "wtf/PassOwnPtr.h" | |
33 #include "wtf/PassRefPtr.h" | |
34 #include "wtf/RefCounted.h" | |
35 #include "wtf/Vector.h" | |
36 #include <algorithm> | |
37 | |
38 | |
39 namespace WebCore { | |
40 | |
41 class TimingFunction : public RefCounted<TimingFunction> { | |
42 public: | |
43 | |
44 enum Type { | |
45 LinearFunction, CubicBezierFunction, StepsFunction, ChainedFunction | |
46 }; | |
47 | |
48 virtual ~TimingFunction() { } | |
49 | |
50 Type type() const { return m_type; } | |
51 | |
52 // Evaluates the timing function at the given fraction. The accuracy paramet
er provides a hint as to the required | |
53 // accuracy and is not guaranteed. | |
54 virtual double evaluate(double fraction, double accuracy) const = 0; | |
55 | |
56 protected: | |
57 TimingFunction(Type type) | |
58 : m_type(type) | |
59 { | |
60 } | |
61 | |
62 private: | |
63 Type m_type; | |
64 }; | |
65 | |
66 class LinearTimingFunction : public TimingFunction { | |
67 public: | |
68 static PassRefPtr<LinearTimingFunction> create() | |
69 { | |
70 return adoptRef(new LinearTimingFunction); | |
71 } | |
72 | |
73 ~LinearTimingFunction() { } | |
74 | |
75 virtual double evaluate(double fraction, double) const | |
76 { | |
77 ASSERT(RuntimeEnabledFeatures::webAnimationsEnabled() || (fraction >= 0
&& fraction <= 1)); | |
78 ASSERT_WITH_MESSAGE(!RuntimeEnabledFeatures::webAnimationsEnabled() || (
fraction >= 0 && fraction <= 1), "Web Animations not yet implemented: Timing fun
ction behavior outside the range [0, 1] is not yet specified"); | |
79 return fraction; | |
80 } | |
81 | |
82 private: | |
83 LinearTimingFunction() | |
84 : TimingFunction(LinearFunction) | |
85 { | |
86 } | |
87 }; | |
88 | |
89 | |
90 // Forward declare so we can friend it below. Don't use in production code! | |
91 class ChainedTimingFunctionTestHelper; | |
92 | |
93 class CubicBezierTimingFunction : public TimingFunction { | |
94 public: | |
95 enum SubType { | |
96 Ease, | |
97 EaseIn, | |
98 EaseOut, | |
99 EaseInOut, | |
100 Custom | |
101 }; | |
102 | |
103 static PassRefPtr<CubicBezierTimingFunction> create(double x1, double y1, do
uble x2, double y2) | |
104 { | |
105 return adoptRef(new CubicBezierTimingFunction(Custom, x1, y1, x2, y2)); | |
106 } | |
107 | |
108 static CubicBezierTimingFunction* preset(SubType subType) | |
109 { | |
110 switch (subType) { | |
111 case Ease: | |
112 { | |
113 static CubicBezierTimingFunction* ease = adoptRef(new CubicBezie
rTimingFunction(Ease, 0.25, 0.1, 0.25, 1.0)).leakRef(); | |
114 return ease; | |
115 } | |
116 case EaseIn: | |
117 { | |
118 static CubicBezierTimingFunction* easeIn = adoptRef(new CubicBez
ierTimingFunction(EaseIn, 0.42, 0.0, 1.0, 1.0)).leakRef(); | |
119 return easeIn; | |
120 } | |
121 case EaseOut: | |
122 { | |
123 static CubicBezierTimingFunction* easeOut = adoptRef(new CubicBe
zierTimingFunction(EaseOut, 0.0, 0.0, 0.58, 1.0)).leakRef(); | |
124 return easeOut; | |
125 } | |
126 case EaseInOut: | |
127 { | |
128 static CubicBezierTimingFunction* easeInOut = adoptRef(new Cubic
BezierTimingFunction(EaseInOut, 0.42, 0.0, 0.58, 1.0)).leakRef(); | |
129 return easeInOut; | |
130 } | |
131 default: | |
132 ASSERT_NOT_REACHED(); | |
133 return 0; | |
134 } | |
135 } | |
136 | |
137 ~CubicBezierTimingFunction() { } | |
138 | |
139 virtual double evaluate(double fraction, double accuracy) const | |
140 { | |
141 ASSERT(RuntimeEnabledFeatures::webAnimationsEnabled() || (fraction >= 0
&& fraction <= 1)); | |
142 ASSERT_WITH_MESSAGE(!RuntimeEnabledFeatures::webAnimationsEnabled() || (
fraction >= 0 && fraction <= 1), "Web Animations not yet implemented: Timing fun
ction behavior outside the range [0, 1] is not yet specified"); | |
143 if (!m_bezier) | |
144 m_bezier = adoptPtr(new UnitBezier(m_x1, m_y1, m_x2, m_y2)); | |
145 return m_bezier->solve(fraction, accuracy); | |
146 } | |
147 | |
148 double x1() const { return m_x1; } | |
149 double y1() const { return m_y1; } | |
150 double x2() const { return m_x2; } | |
151 double y2() const { return m_y2; } | |
152 | |
153 SubType subType() const { return m_subType; } | |
154 | |
155 private: | |
156 explicit CubicBezierTimingFunction(SubType subType, double x1, double y1, do
uble x2, double y2) | |
157 : TimingFunction(CubicBezierFunction) | |
158 , m_x1(x1) | |
159 , m_y1(y1) | |
160 , m_x2(x2) | |
161 , m_y2(y2) | |
162 , m_subType(subType) | |
163 { | |
164 } | |
165 | |
166 double m_x1; | |
167 double m_y1; | |
168 double m_x2; | |
169 double m_y2; | |
170 SubType m_subType; | |
171 mutable OwnPtr<UnitBezier> m_bezier; | |
172 }; | |
173 | |
174 class StepsTimingFunction : public TimingFunction { | |
175 public: | |
176 enum SubType { | |
177 Start, | |
178 End, | |
179 Custom | |
180 }; | |
181 | |
182 static PassRefPtr<StepsTimingFunction> create(int steps, bool stepAtStart) | |
183 { | |
184 return adoptRef(new StepsTimingFunction(Custom, steps, stepAtStart)); | |
185 } | |
186 | |
187 static StepsTimingFunction* preset(SubType subType) | |
188 { | |
189 switch (subType) { | |
190 case Start: | |
191 { | |
192 static StepsTimingFunction* start = adoptRef(new StepsTimingFunc
tion(Start, 1, true)).leakRef(); | |
193 return start; | |
194 } | |
195 case End: | |
196 { | |
197 static StepsTimingFunction* end = adoptRef(new StepsTimingFuncti
on(End, 1, false)).leakRef(); | |
198 return end; | |
199 } | |
200 default: | |
201 ASSERT_NOT_REACHED(); | |
202 return 0; | |
203 } | |
204 } | |
205 | |
206 | |
207 ~StepsTimingFunction() { } | |
208 | |
209 virtual double evaluate(double fraction, double) const | |
210 { | |
211 ASSERT(RuntimeEnabledFeatures::webAnimationsEnabled() || (fraction >= 0
&& fraction <= 1)); | |
212 ASSERT_WITH_MESSAGE(!RuntimeEnabledFeatures::webAnimationsEnabled() || (
fraction >= 0 && fraction <= 1), "Web Animations not yet implemented: Timing fun
ction behavior outside the range [0, 1] is not yet specified"); | |
213 return std::min(1.0, (floor(m_steps * fraction) + m_stepAtStart) / m_ste
ps); | |
214 } | |
215 | |
216 int numberOfSteps() const { return m_steps; } | |
217 bool stepAtStart() const { return m_stepAtStart; } | |
218 | |
219 SubType subType() const { return m_subType; } | |
220 | |
221 private: | |
222 StepsTimingFunction(SubType subType, int steps, bool stepAtStart) | |
223 : TimingFunction(StepsFunction) | |
224 , m_steps(steps) | |
225 , m_stepAtStart(stepAtStart) | |
226 , m_subType(subType) | |
227 { | |
228 } | |
229 | |
230 int m_steps; | |
231 bool m_stepAtStart; | |
232 SubType m_subType; | |
233 }; | |
234 | |
235 class ChainedTimingFunction : public TimingFunction { | |
236 public: | |
237 static PassRefPtr<ChainedTimingFunction> create() | |
238 { | |
239 return adoptRef(new ChainedTimingFunction); | |
240 } | |
241 | |
242 void appendSegment(double upperBound, TimingFunction* timingFunction) | |
243 { | |
244 double max = m_segments.isEmpty() ? 0 : m_segments.last().max(); | |
245 ASSERT(upperBound > max); | |
246 m_segments.append(Segment(max, upperBound, timingFunction)); | |
247 } | |
248 virtual double evaluate(double fraction, double accuracy) const | |
249 { | |
250 ASSERT_WITH_MESSAGE(fraction >= 0 && fraction <= 1, "Web Animations not
yet implemented: Timing function behavior outside the range [0, 1] is not yet sp
ecified"); | |
251 ASSERT(!m_segments.isEmpty()); | |
252 ASSERT(m_segments.last().max() == 1); | |
253 size_t i = 0; | |
254 const Segment* segment = &m_segments[i++]; | |
255 while (fraction >= segment->max() && i < m_segments.size()) { | |
256 segment = &m_segments[i++]; | |
257 } | |
258 return segment->evaluate(fraction, accuracy); | |
259 } | |
260 | |
261 private: | |
262 class Segment { | |
263 public: | |
264 Segment(double min, double max, TimingFunction* timingFunction) | |
265 : m_min(min) | |
266 , m_max(max) | |
267 , m_timingFunction(timingFunction) | |
268 { ASSERT(timingFunction); } | |
269 | |
270 double max() const { return m_max; } | |
271 double evaluate(double fraction, double accuracy) const | |
272 { | |
273 return scaleFromLocal(m_timingFunction->evaluate(scaleToLocal(fracti
on), accuracy)); | |
274 } | |
275 | |
276 private: | |
277 double scaleToLocal(double x) const { return (x - m_min) / (m_max - m_mi
n); } | |
278 double scaleFromLocal(double x) const { return blend(m_min, m_max, x); } | |
279 | |
280 double m_min; | |
281 double m_max; | |
282 RefPtr<TimingFunction> m_timingFunction; | |
283 | |
284 // FIXME: Come up with a public API for the segments and remove this. | |
285 friend class CompositorAnimationsImpl; | |
286 | |
287 // Allow the compositor to reverse the timing function. | |
288 friend class CompositorAnimationsTimingFunctionReverser; | |
289 | |
290 // Allow PrintTo/operator== of the segments. Can be removed once | |
291 // ChainedTimingFunction has a public API for segments. | |
292 friend class ChainedTimingFunctionTestHelper; | |
293 }; | |
294 | |
295 ChainedTimingFunction() | |
296 : TimingFunction(ChainedFunction) | |
297 { | |
298 ASSERT(RuntimeEnabledFeatures::webAnimationsEnabled()); | |
299 } | |
300 | |
301 Vector<Segment> m_segments; | |
302 | |
303 // FIXME: Come up with a public API for the segments and remove this. | |
304 friend class CompositorAnimationsImpl; | |
305 | |
306 // Allow the compositor to reverse the timing function. | |
307 friend class CompositorAnimationsTimingFunctionReverser; | |
308 | |
309 // Allow PrintTo/operator== of the segments. Can be removed once | |
310 // ChainedTimingFunction has a public API for segments. | |
311 friend class ChainedTimingFunctionTestHelper; | |
312 }; | |
313 | |
314 } // namespace WebCore | |
315 | |
316 #endif // TimingFunction_h | |
OLD | NEW |