Index: Source/core/platform/animation/TimingFunction.h |
diff --git a/Source/core/platform/animation/TimingFunction.h b/Source/core/platform/animation/TimingFunction.h |
index cc9db512250d142bee9dc3ac1c9370bed1915aef..606fe4c4df2c1e65cbcb3b4621a49e8431e7635c 100644 |
--- a/Source/core/platform/animation/TimingFunction.h |
+++ b/Source/core/platform/animation/TimingFunction.h |
@@ -39,6 +39,8 @@ |
namespace WebCore { |
+class TimingFunction; |
+ |
class TimingFunction : public RefCounted<TimingFunction> { |
public: |
@@ -54,6 +56,9 @@ public: |
// accuracy and is not guaranteed. |
virtual double evaluate(double fraction, double accuracy) const = 0; |
virtual bool operator==(const TimingFunction& other) const = 0; |
+ virtual bool operator!=(const TimingFunction& other) const { return !operator==(other); } |
+ |
+ virtual PassRefPtr<TimingFunction> reverse() const = 0; |
Steve Block
2013/11/03 09:52:32
Can you add a comment describing exactly what you
|
protected: |
TimingFunction(Type type) |
@@ -86,6 +91,11 @@ public: |
return other.type() == LinearFunction; |
} |
+ virtual PassRefPtr<TimingFunction> reverse() const |
+ { |
+ return const_cast<LinearTimingFunction*>(this); |
+ } |
+ |
private: |
LinearTimingFunction() |
: TimingFunction(LinearFunction) |
@@ -105,6 +115,20 @@ public: |
static PassRefPtr<CubicBezierTimingFunction> create(double x1, double y1, double x2, double y2) |
{ |
+ // Prevent accidental creation of presets via this method (makes operator== easier too). |
+ if (x1 == 0.25 && y1 == 0.1 && x2 == 0.25 && y2 == 1.0) { |
+ return preset(Ease); |
+ } |
+ if (x1 == 0.42 && y1 == 0.0 && x2 == 1.0 && y2 == 1.0) { |
+ return preset(EaseIn); |
+ } |
+ if (x1 == 0.0 && y1 == 0.0 && x2 == 0.58 && y2 == 1.0) { |
+ return preset(EaseOut); |
+ } |
+ if (x1 == 0.42 && y1 == 0.0 && x2 == 0.58 && y2 == 1.0) { |
+ return preset(EaseInOut); |
+ } |
+ |
Steve Block
2013/11/03 09:52:32
This introduces a change in behavior for CSS. The
|
return adoptRef(new CubicBezierTimingFunction(Custom, x1, y1, x2, y2)); |
} |
@@ -150,14 +174,14 @@ public: |
virtual bool operator==(const TimingFunction& other) const |
{ |
- if (other.type() == CubicBezierFunction) { |
- const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(&other); |
- if (m_subType != Custom) |
- return m_subType == ctf->m_subType; |
+ if (other.type() != CubicBezierFunction) |
+ return false; |
Steve Block
2013/11/03 09:52:32
Why don't you test for 'this == &other' here, like
|
+ const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(&other); |
+ if (m_subType == Custom && ctf->m_subType == Custom) |
return m_x1 == ctf->m_x1 && m_y1 == ctf->m_y1 && m_x2 == ctf->m_x2 && m_y2 == ctf->m_y2; |
- } |
- return false; |
+ |
+ return m_subType == ctf->m_subType; |
} |
double x1() const { return m_x1; } |
@@ -167,6 +191,26 @@ public: |
SubType subType() const { return m_subType; } |
+ virtual PassRefPtr<TimingFunction> reverse() const |
+ { |
+ switch (m_subType) { |
+ case Ease: |
+ return const_cast<CubicBezierTimingFunction*>(this); |
Steve Block
2013/11/03 09:52:32
This is incorrect. 'Ease' is not symmetric about x
|
+ case EaseIn: |
+ return preset(EaseOut); |
+ case EaseOut: |
+ return preset(EaseIn); |
+ case EaseInOut: |
+ return const_cast<CubicBezierTimingFunction*>(this); |
+ case Custom: |
+ // Flip the timing function in x. We also have to flip it in y to |
+ // maintain the invariant that it runs from (0, 0) to (1, 1). |
+ return create(1 - m_x2, 1 - m_y2, 1 - m_x1, 1 - m_y1); |
+ default: |
+ ASSERT_NOT_REACHED(); |
+ } |
+ } |
+ |
private: |
explicit CubicBezierTimingFunction(SubType subType, double x1, double y1, double x2, double y2) |
: TimingFunction(CubicBezierFunction) |
@@ -218,7 +262,6 @@ public: |
} |
} |
- |
~StepsTimingFunction() { } |
virtual double evaluate(double fraction, double) const |
@@ -230,13 +273,16 @@ public: |
virtual bool operator==(const TimingFunction& other) const |
{ |
- if (other.type() == StepsFunction) { |
- const StepsTimingFunction* stf = static_cast<const StepsTimingFunction*>(&other); |
- if (m_subType != Custom) |
- return m_subType == stf->m_subType; |
- return m_steps == stf->m_steps && m_stepAtStart == stf->m_stepAtStart; |
- } |
- return false; |
+ if (other.type() != StepsFunction) |
+ return false; |
+ |
+ if (this == &other) |
+ return true; |
+ |
+ const StepsTimingFunction* stf = static_cast<const StepsTimingFunction*>(&other); |
+ if (m_subType != Custom) |
+ return m_subType == stf->m_subType; |
+ return m_steps == stf->m_steps && m_stepAtStart == stf->m_stepAtStart; |
} |
int numberOfSteps() const { return m_steps; } |
@@ -244,6 +290,21 @@ public: |
SubType subType() const { return m_subType; } |
+ virtual PassRefPtr<TimingFunction> reverse() const |
+ { |
+ switch (m_subType) { |
+ case Start: |
+ 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
|
+ case End: |
+ return preset(Start); |
+ case Custom: |
+ return create(m_steps, !m_stepAtStart); |
+ default: |
+ ASSERT_NOT_REACHED(); |
+ return 0; |
+ } |
+ } |
+ |
private: |
StepsTimingFunction(SubType subType, int steps, bool stepAtStart) |
: TimingFunction(StepsFunction) |
@@ -271,6 +332,7 @@ public: |
ASSERT(upperBound > max); |
m_segments.append(Segment(max, upperBound, timingFunction)); |
} |
+ |
virtual double evaluate(double fraction, double accuracy) const |
{ |
RELEASE_ASSERT_WITH_MESSAGE(fraction >= 0 && fraction <= 1, "Web Animations not yet implemented: Timing function behavior outside the range [0, 1] is not yet specified"); |
@@ -286,9 +348,32 @@ public: |
virtual bool operator==(const TimingFunction& other) const |
Steve Block
2013/11/03 09:52:32
What exactly do you need operator==() for? Current
|
{ |
- // This class is not exposed to CSS, so this method is not required. |
- ASSERT_NOT_REACHED(); |
- return false; |
+ if (other.type() != ChainedFunction) |
+ return false; |
+ |
+ if (this == &other) |
+ return true; |
+ |
+ const ChainedTimingFunction* ctf = static_cast<const ChainedTimingFunction*>(&other); |
+ if (ctf->m_segments.size() != m_segments.size()) |
+ return false; |
+ |
+ for (size_t i = 0; i < m_segments.size(); i++) { |
+ if (m_segments[i] != ctf->m_segments[i]) |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ virtual PassRefPtr<TimingFunction> reverse() const |
+ { |
+ RefPtr<ChainedTimingFunction> reversed = create(); |
+ for (size_t i = 0; i < m_segments.size(); i++) { |
+ size_t index = m_segments.size() - i - 1; |
+ |
+ reversed->appendSegment(1 - m_segments[index].m_min, m_segments[index].m_timingFunction->reverse().get()); |
+ } |
+ return reversed; |
} |
private: |
@@ -306,6 +391,17 @@ private: |
return scaleFromLocal(m_timingFunction->evaluate(scaleToLocal(fraction), accuracy)); |
} |
+ bool operator==(const Segment& other) const |
+ { |
+ if (this == &other) |
+ return true; |
+ |
+ return m_min == other.m_min && m_max == other.m_max && m_timingFunction == other.m_timingFunction; |
+ } |
+ bool operator!=(const Segment& other) const |
+ { |
+ return !operator==(other); |
+ } |
private: |
double scaleToLocal(double x) const { return (x - m_min) / (m_max - m_min); } |
double scaleFromLocal(double x) const { return blend(m_min, m_max, x); } |
@@ -314,6 +410,8 @@ private: |
double m_max; |
RefPtr<TimingFunction> m_timingFunction; |
+ friend class ChainedTimingFunction; |
+ |
// Allow printing of our segments. Can be removed once |
// ChainedTimingFunction has a public API for segments. |
friend void PrintTo(const ChainedTimingFunction&, ::std::ostream*, bool); |