Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(467)

Side by Side Diff: Source/core/platform/animation/TimingFunction.h

Issue 54743002: Adding a reverse function to the TimingFunctions and tests to prove it works. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@timing-function-helper
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/core.gypi ('k') | Source/core/platform/animation/TimingFunctionTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
3 * (C) 2000 Antti Koivisto (koivisto@kde.org) 3 * (C) 2000 Antti Koivisto (koivisto@kde.org)
4 * (C) 2000 Dirk Mueller (mueller@kde.org) 4 * (C) 2000 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 5 * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
6 * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) 6 * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 21 matching lines...) Expand all
32 #include "wtf/PassOwnPtr.h" 32 #include "wtf/PassOwnPtr.h"
33 #include "wtf/PassRefPtr.h" 33 #include "wtf/PassRefPtr.h"
34 #include "wtf/RefCounted.h" 34 #include "wtf/RefCounted.h"
35 #include "wtf/Vector.h" 35 #include "wtf/Vector.h"
36 #include <algorithm> 36 #include <algorithm>
37 #include <iosfwd> 37 #include <iosfwd>
38 38
39 39
40 namespace WebCore { 40 namespace WebCore {
41 41
42 class TimingFunction;
43
42 class TimingFunction : public RefCounted<TimingFunction> { 44 class TimingFunction : public RefCounted<TimingFunction> {
43 public: 45 public:
44 46
45 enum Type { 47 enum Type {
46 LinearFunction, CubicBezierFunction, StepsFunction, ChainedFunction 48 LinearFunction, CubicBezierFunction, StepsFunction, ChainedFunction
47 }; 49 };
48 50
49 virtual ~TimingFunction() { } 51 virtual ~TimingFunction() { }
50 52
51 Type type() const { return m_type; } 53 Type type() const { return m_type; }
52 54
53 // Evaluates the timing function at the given fraction. The accuracy paramet er provides a hint as to the required 55 // Evaluates the timing function at the given fraction. The accuracy paramet er provides a hint as to the required
54 // accuracy and is not guaranteed. 56 // accuracy and is not guaranteed.
55 virtual double evaluate(double fraction, double accuracy) const = 0; 57 virtual double evaluate(double fraction, double accuracy) const = 0;
56 virtual bool operator==(const TimingFunction& other) const = 0; 58 virtual bool operator==(const TimingFunction& other) const = 0;
59 virtual bool operator!=(const TimingFunction& other) const { return !operato r==(other); }
60
61 virtual PassRefPtr<TimingFunction> reverse() const = 0;
Steve Block 2013/11/03 09:52:32 Can you add a comment describing exactly what you
57 62
58 protected: 63 protected:
59 TimingFunction(Type type) 64 TimingFunction(Type type)
60 : m_type(type) 65 : m_type(type)
61 { 66 {
62 } 67 }
63 68
64 private: 69 private:
65 Type m_type; 70 Type m_type;
66 }; 71 };
(...skipping 12 matching lines...) Expand all
79 ASSERT(RuntimeEnabledFeatures::webAnimationsEnabled() || (fraction >= 0 && fraction <= 1)); 84 ASSERT(RuntimeEnabledFeatures::webAnimationsEnabled() || (fraction >= 0 && fraction <= 1));
80 RELEASE_ASSERT_WITH_MESSAGE(!RuntimeEnabledFeatures::webAnimationsEnable d() || (fraction >= 0 && fraction <= 1), "Web Animations not yet implemented: Ti ming function behavior outside the range [0, 1] is not yet specified"); 85 RELEASE_ASSERT_WITH_MESSAGE(!RuntimeEnabledFeatures::webAnimationsEnable d() || (fraction >= 0 && fraction <= 1), "Web Animations not yet implemented: Ti ming function behavior outside the range [0, 1] is not yet specified");
81 return fraction; 86 return fraction;
82 } 87 }
83 88
84 virtual bool operator==(const TimingFunction& other) const 89 virtual bool operator==(const TimingFunction& other) const
85 { 90 {
86 return other.type() == LinearFunction; 91 return other.type() == LinearFunction;
87 } 92 }
88 93
94 virtual PassRefPtr<TimingFunction> reverse() const
95 {
96 return const_cast<LinearTimingFunction*>(this);
97 }
98
89 private: 99 private:
90 LinearTimingFunction() 100 LinearTimingFunction()
91 : TimingFunction(LinearFunction) 101 : TimingFunction(LinearFunction)
92 { 102 {
93 } 103 }
94 }; 104 };
95 105
96 class CubicBezierTimingFunction : public TimingFunction { 106 class CubicBezierTimingFunction : public TimingFunction {
97 public: 107 public:
98 enum SubType { 108 enum SubType {
99 Ease, 109 Ease,
100 EaseIn, 110 EaseIn,
101 EaseOut, 111 EaseOut,
102 EaseInOut, 112 EaseInOut,
103 Custom 113 Custom
104 }; 114 };
105 115
106 static PassRefPtr<CubicBezierTimingFunction> create(double x1, double y1, do uble x2, double y2) 116 static PassRefPtr<CubicBezierTimingFunction> create(double x1, double y1, do uble x2, double y2)
107 { 117 {
118 // Prevent accidental creation of presets via this method (makes operato r== easier too).
119 if (x1 == 0.25 && y1 == 0.1 && x2 == 0.25 && y2 == 1.0) {
120 return preset(Ease);
121 }
122 if (x1 == 0.42 && y1 == 0.0 && x2 == 1.0 && y2 == 1.0) {
123 return preset(EaseIn);
124 }
125 if (x1 == 0.0 && y1 == 0.0 && x2 == 0.58 && y2 == 1.0) {
126 return preset(EaseOut);
127 }
128 if (x1 == 0.42 && y1 == 0.0 && x2 == 0.58 && y2 == 1.0) {
129 return preset(EaseInOut);
130 }
131
Steve Block 2013/11/03 09:52:32 This introduces a change in behavior for CSS. The
108 return adoptRef(new CubicBezierTimingFunction(Custom, x1, y1, x2, y2)); 132 return adoptRef(new CubicBezierTimingFunction(Custom, x1, y1, x2, y2));
109 } 133 }
110 134
111 static CubicBezierTimingFunction* preset(SubType subType) 135 static CubicBezierTimingFunction* preset(SubType subType)
112 { 136 {
113 switch (subType) { 137 switch (subType) {
114 case Ease: 138 case Ease:
115 { 139 {
116 static CubicBezierTimingFunction* ease = adoptRef(new CubicBezie rTimingFunction(Ease, 0.25, 0.1, 0.25, 1.0)).leakRef(); 140 static CubicBezierTimingFunction* ease = adoptRef(new CubicBezie rTimingFunction(Ease, 0.25, 0.1, 0.25, 1.0)).leakRef();
117 return ease; 141 return ease;
(...skipping 25 matching lines...) Expand all
143 { 167 {
144 ASSERT(RuntimeEnabledFeatures::webAnimationsEnabled() || (fraction >= 0 && fraction <= 1)); 168 ASSERT(RuntimeEnabledFeatures::webAnimationsEnabled() || (fraction >= 0 && fraction <= 1));
145 RELEASE_ASSERT_WITH_MESSAGE(!RuntimeEnabledFeatures::webAnimationsEnable d() || (fraction >= 0 && fraction <= 1), "Web Animations not yet implemented: Ti ming function behavior outside the range [0, 1] is not yet specified"); 169 RELEASE_ASSERT_WITH_MESSAGE(!RuntimeEnabledFeatures::webAnimationsEnable d() || (fraction >= 0 && fraction <= 1), "Web Animations not yet implemented: Ti ming function behavior outside the range [0, 1] is not yet specified");
146 if (!m_bezier) 170 if (!m_bezier)
147 m_bezier = adoptPtr(new UnitBezier(m_x1, m_y1, m_x2, m_y2)); 171 m_bezier = adoptPtr(new UnitBezier(m_x1, m_y1, m_x2, m_y2));
148 return m_bezier->solve(fraction, accuracy); 172 return m_bezier->solve(fraction, accuracy);
149 } 173 }
150 174
151 virtual bool operator==(const TimingFunction& other) const 175 virtual bool operator==(const TimingFunction& other) const
152 { 176 {
153 if (other.type() == CubicBezierFunction) { 177 if (other.type() != CubicBezierFunction)
154 const CubicBezierTimingFunction* ctf = static_cast<const CubicBezier TimingFunction*>(&other); 178 return false;
155 if (m_subType != Custom)
156 return m_subType == ctf->m_subType;
157 179
Steve Block 2013/11/03 09:52:32 Why don't you test for 'this == &other' here, like
180 const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimi ngFunction*>(&other);
181 if (m_subType == Custom && ctf->m_subType == Custom)
158 return m_x1 == ctf->m_x1 && m_y1 == ctf->m_y1 && m_x2 == ctf->m_x2 & & m_y2 == ctf->m_y2; 182 return m_x1 == ctf->m_x1 && m_y1 == ctf->m_y1 && m_x2 == ctf->m_x2 & & m_y2 == ctf->m_y2;
159 } 183
160 return false; 184 return m_subType == ctf->m_subType;
161 } 185 }
162 186
163 double x1() const { return m_x1; } 187 double x1() const { return m_x1; }
164 double y1() const { return m_y1; } 188 double y1() const { return m_y1; }
165 double x2() const { return m_x2; } 189 double x2() const { return m_x2; }
166 double y2() const { return m_y2; } 190 double y2() const { return m_y2; }
167 191
168 SubType subType() const { return m_subType; } 192 SubType subType() const { return m_subType; }
169 193
194 virtual PassRefPtr<TimingFunction> reverse() const
195 {
196 switch (m_subType) {
197 case Ease:
198 return const_cast<CubicBezierTimingFunction*>(this);
Steve Block 2013/11/03 09:52:32 This is incorrect. 'Ease' is not symmetric about x
199 case EaseIn:
200 return preset(EaseOut);
201 case EaseOut:
202 return preset(EaseIn);
203 case EaseInOut:
204 return const_cast<CubicBezierTimingFunction*>(this);
205 case Custom:
206 // Flip the timing function in x. We also have to flip it in y to
207 // maintain the invariant that it runs from (0, 0) to (1, 1).
208 return create(1 - m_x2, 1 - m_y2, 1 - m_x1, 1 - m_y1);
209 default:
210 ASSERT_NOT_REACHED();
211 }
212 }
213
170 private: 214 private:
171 explicit CubicBezierTimingFunction(SubType subType, double x1, double y1, do uble x2, double y2) 215 explicit CubicBezierTimingFunction(SubType subType, double x1, double y1, do uble x2, double y2)
172 : TimingFunction(CubicBezierFunction) 216 : TimingFunction(CubicBezierFunction)
173 , m_x1(x1) 217 , m_x1(x1)
174 , m_y1(y1) 218 , m_y1(y1)
175 , m_x2(x2) 219 , m_x2(x2)
176 , m_y2(y2) 220 , m_y2(y2)
177 , m_subType(subType) 221 , m_subType(subType)
178 { 222 {
179 } 223 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 { 255 {
212 static StepsTimingFunction* end = adoptRef(new StepsTimingFuncti on(End, 1, false)).leakRef(); 256 static StepsTimingFunction* end = adoptRef(new StepsTimingFuncti on(End, 1, false)).leakRef();
213 return end; 257 return end;
214 } 258 }
215 default: 259 default:
216 ASSERT_NOT_REACHED(); 260 ASSERT_NOT_REACHED();
217 return 0; 261 return 0;
218 } 262 }
219 } 263 }
220 264
221
222 ~StepsTimingFunction() { } 265 ~StepsTimingFunction() { }
223 266
224 virtual double evaluate(double fraction, double) const 267 virtual double evaluate(double fraction, double) const
225 { 268 {
226 ASSERT(RuntimeEnabledFeatures::webAnimationsEnabled() || (fraction >= 0 && fraction <= 1)); 269 ASSERT(RuntimeEnabledFeatures::webAnimationsEnabled() || (fraction >= 0 && fraction <= 1));
227 RELEASE_ASSERT_WITH_MESSAGE(!RuntimeEnabledFeatures::webAnimationsEnable d() || (fraction >= 0 && fraction <= 1), "Web Animations not yet implemented: Ti ming function behavior outside the range [0, 1] is not yet specified"); 270 RELEASE_ASSERT_WITH_MESSAGE(!RuntimeEnabledFeatures::webAnimationsEnable d() || (fraction >= 0 && fraction <= 1), "Web Animations not yet implemented: Ti ming function behavior outside the range [0, 1] is not yet specified");
228 return std::min(1.0, (floor(m_steps * fraction) + m_stepAtStart) / m_ste ps); 271 return std::min(1.0, (floor(m_steps * fraction) + m_stepAtStart) / m_ste ps);
229 } 272 }
230 273
231 virtual bool operator==(const TimingFunction& other) const 274 virtual bool operator==(const TimingFunction& other) const
232 { 275 {
233 if (other.type() == StepsFunction) { 276 if (other.type() != StepsFunction)
234 const StepsTimingFunction* stf = static_cast<const StepsTimingFuncti on*>(&other); 277 return false;
235 if (m_subType != Custom) 278
236 return m_subType == stf->m_subType; 279 if (this == &other)
237 return m_steps == stf->m_steps && m_stepAtStart == stf->m_stepAtStar t; 280 return true;
238 } 281
239 return false; 282 const StepsTimingFunction* stf = static_cast<const StepsTimingFunction*> (&other);
283 if (m_subType != Custom)
284 return m_subType == stf->m_subType;
285 return m_steps == stf->m_steps && m_stepAtStart == stf->m_stepAtStart;
240 } 286 }
241 287
242 int numberOfSteps() const { return m_steps; } 288 int numberOfSteps() const { return m_steps; }
243 bool stepAtStart() const { return m_stepAtStart; } 289 bool stepAtStart() const { return m_stepAtStart; }
244 290
245 SubType subType() const { return m_subType; } 291 SubType subType() const { return m_subType; }
246 292
293 virtual PassRefPtr<TimingFunction> reverse() const
294 {
295 switch (m_subType) {
296 case Start:
297 return preset(End);
Steve Block 2013/11/03 09:52:32 If I'm right about how I think you intend to use r
Steve Block 2013/11/04 04:36:08 Sorry, should be ... A step-start has output 1 for
Steve Block 2013/11/04 04:40:57 step-start has an output of 1 at input 0. See http
298 case End:
299 return preset(Start);
300 case Custom:
301 return create(m_steps, !m_stepAtStart);
302 default:
303 ASSERT_NOT_REACHED();
304 return 0;
305 }
306 }
307
247 private: 308 private:
248 StepsTimingFunction(SubType subType, int steps, bool stepAtStart) 309 StepsTimingFunction(SubType subType, int steps, bool stepAtStart)
249 : TimingFunction(StepsFunction) 310 : TimingFunction(StepsFunction)
250 , m_steps(steps) 311 , m_steps(steps)
251 , m_stepAtStart(stepAtStart) 312 , m_stepAtStart(stepAtStart)
252 , m_subType(subType) 313 , m_subType(subType)
253 { 314 {
254 } 315 }
255 316
256 int m_steps; 317 int m_steps;
257 bool m_stepAtStart; 318 bool m_stepAtStart;
258 SubType m_subType; 319 SubType m_subType;
259 }; 320 };
260 321
261 class ChainedTimingFunction : public TimingFunction { 322 class ChainedTimingFunction : public TimingFunction {
262 public: 323 public:
263 static PassRefPtr<ChainedTimingFunction> create() 324 static PassRefPtr<ChainedTimingFunction> create()
264 { 325 {
265 return adoptRef(new ChainedTimingFunction); 326 return adoptRef(new ChainedTimingFunction);
266 } 327 }
267 328
268 void appendSegment(double upperBound, TimingFunction* timingFunction) 329 void appendSegment(double upperBound, TimingFunction* timingFunction)
269 { 330 {
270 double max = m_segments.isEmpty() ? 0 : m_segments.last().max(); 331 double max = m_segments.isEmpty() ? 0 : m_segments.last().max();
271 ASSERT(upperBound > max); 332 ASSERT(upperBound > max);
272 m_segments.append(Segment(max, upperBound, timingFunction)); 333 m_segments.append(Segment(max, upperBound, timingFunction));
273 } 334 }
335
274 virtual double evaluate(double fraction, double accuracy) const 336 virtual double evaluate(double fraction, double accuracy) const
275 { 337 {
276 RELEASE_ASSERT_WITH_MESSAGE(fraction >= 0 && fraction <= 1, "Web Animati ons not yet implemented: Timing function behavior outside the range [0, 1] is no t yet specified"); 338 RELEASE_ASSERT_WITH_MESSAGE(fraction >= 0 && fraction <= 1, "Web Animati ons not yet implemented: Timing function behavior outside the range [0, 1] is no t yet specified");
277 ASSERT(!m_segments.isEmpty()); 339 ASSERT(!m_segments.isEmpty());
278 ASSERT(m_segments.last().max() == 1); 340 ASSERT(m_segments.last().max() == 1);
279 size_t i = 0; 341 size_t i = 0;
280 const Segment* segment = &m_segments[i++]; 342 const Segment* segment = &m_segments[i++];
281 while (fraction >= segment->max() && i < m_segments.size()) { 343 while (fraction >= segment->max() && i < m_segments.size()) {
282 segment = &m_segments[i++]; 344 segment = &m_segments[i++];
283 } 345 }
284 return segment->evaluate(fraction, accuracy); 346 return segment->evaluate(fraction, accuracy);
285 } 347 }
286 348
287 virtual bool operator==(const TimingFunction& other) const 349 virtual bool operator==(const TimingFunction& other) const
Steve Block 2013/11/03 09:52:32 What exactly do you need operator==() for? Current
288 { 350 {
289 // This class is not exposed to CSS, so this method is not required. 351 if (other.type() != ChainedFunction)
290 ASSERT_NOT_REACHED(); 352 return false;
291 return false; 353
354 if (this == &other)
355 return true;
356
357 const ChainedTimingFunction* ctf = static_cast<const ChainedTimingFuncti on*>(&other);
358 if (ctf->m_segments.size() != m_segments.size())
359 return false;
360
361 for (size_t i = 0; i < m_segments.size(); i++) {
362 if (m_segments[i] != ctf->m_segments[i])
363 return false;
364 }
365 return true;
366 }
367
368 virtual PassRefPtr<TimingFunction> reverse() const
369 {
370 RefPtr<ChainedTimingFunction> reversed = create();
371 for (size_t i = 0; i < m_segments.size(); i++) {
372 size_t index = m_segments.size() - i - 1;
373
374 reversed->appendSegment(1 - m_segments[index].m_min, m_segments[inde x].m_timingFunction->reverse().get());
375 }
376 return reversed;
292 } 377 }
293 378
294 private: 379 private:
295 class Segment { 380 class Segment {
296 public: 381 public:
297 Segment(double min, double max, TimingFunction* timingFunction) 382 Segment(double min, double max, TimingFunction* timingFunction)
298 : m_min(min) 383 : m_min(min)
299 , m_max(max) 384 , m_max(max)
300 , m_timingFunction(timingFunction) 385 , m_timingFunction(timingFunction)
301 { } 386 { }
302 387
303 double max() const { return m_max; } 388 double max() const { return m_max; }
304 double evaluate(double fraction, double accuracy) const 389 double evaluate(double fraction, double accuracy) const
305 { 390 {
306 return scaleFromLocal(m_timingFunction->evaluate(scaleToLocal(fracti on), accuracy)); 391 return scaleFromLocal(m_timingFunction->evaluate(scaleToLocal(fracti on), accuracy));
307 } 392 }
308 393
394 bool operator==(const Segment& other) const
395 {
396 if (this == &other)
397 return true;
398
399 return m_min == other.m_min && m_max == other.m_max && m_timingFunct ion == other.m_timingFunction;
400 }
401 bool operator!=(const Segment& other) const
402 {
403 return !operator==(other);
404 }
309 private: 405 private:
310 double scaleToLocal(double x) const { return (x - m_min) / (m_max - m_mi n); } 406 double scaleToLocal(double x) const { return (x - m_min) / (m_max - m_mi n); }
311 double scaleFromLocal(double x) const { return blend(m_min, m_max, x); } 407 double scaleFromLocal(double x) const { return blend(m_min, m_max, x); }
312 408
313 double m_min; 409 double m_min;
314 double m_max; 410 double m_max;
315 RefPtr<TimingFunction> m_timingFunction; 411 RefPtr<TimingFunction> m_timingFunction;
316 412
413 friend class ChainedTimingFunction;
414
317 // Allow printing of our segments. Can be removed once 415 // Allow printing of our segments. Can be removed once
318 // ChainedTimingFunction has a public API for segments. 416 // ChainedTimingFunction has a public API for segments.
319 friend void PrintTo(const ChainedTimingFunction&, ::std::ostream*, bool) ; 417 friend void PrintTo(const ChainedTimingFunction&, ::std::ostream*, bool) ;
320 }; 418 };
321 419
322 ChainedTimingFunction() 420 ChainedTimingFunction()
323 : TimingFunction(ChainedFunction) 421 : TimingFunction(ChainedFunction)
324 { 422 {
325 ASSERT(RuntimeEnabledFeatures::webAnimationsEnabled()); 423 ASSERT(RuntimeEnabledFeatures::webAnimationsEnabled());
326 } 424 }
327 425
328 Vector<Segment> m_segments; 426 Vector<Segment> m_segments;
329 427
330 // Allow printing of our segments. Can be removed once 428 // Allow printing of our segments. Can be removed once
331 // ChainedTimingFunction has a public API for segments. 429 // ChainedTimingFunction has a public API for segments.
332 friend void PrintTo(const ChainedTimingFunction&, ::std::ostream*, bool); 430 friend void PrintTo(const ChainedTimingFunction&, ::std::ostream*, bool);
333 }; 431 };
334 432
335 } // namespace WebCore 433 } // namespace WebCore
336 434
337 #endif // TimingFunction_h 435 #endif // TimingFunction_h
OLDNEW
« no previous file with comments | « Source/core/core.gypi ('k') | Source/core/platform/animation/TimingFunctionTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698