1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "config.h" 6 #include "platform/animation/TimingFunction.h" 7 8 #include "wtf/MathExtras.h" 9 10 namespace WebCore { 11 12 String LinearTimingFunction::toString() const 13 { 14 return "linear"; 15 } 16 17 double LinearTimingFunction::evaluate(double fraction, double) const 18 { 19 return fraction; 20 } 21 22 String CubicBezierTimingFunction::toString() const 23 { 24 switch (this->subType()) { 25 case CubicBezierTimingFunction::Ease: 26 return "ease"; 27 case CubicBezierTimingFunction::EaseIn: 28 return "ease-in"; 29 case CubicBezierTimingFunction::EaseOut: 30 return "ease-out"; 31 case CubicBezierTimingFunction::EaseInOut: 32 return "ease-in-out"; 33 case CubicBezierTimingFunction::Custom: 34 return "cubic-bezier(" + String::numberToStringECMAScript(this->x1()) + ", " + 35 String::numberToStringECMAScript(this->y1()) + ", " + String::numberToStringECMAScript(this->x2()) + 36 ", " + String::numberToStringECMAScript(this->y2()) + ")"; 37 default: 38 ASSERT_NOT_REACHED(); 39 } 40 return ""; 41 } 42 43 double CubicBezierTimingFunction::evaluate(double fraction, double accuracy) const 44 { 45 if (!m_bezier) 46 m_bezier = adoptPtr(new UnitBezier(m_x1, m_y1, m_x2, m_y2)); 47 return m_bezier->solve(fraction, accuracy); 48 } 49 50 String StepsTimingFunction::toString() const 51 { 52 StringBuilder builder; 53 switch (this->subType()) { 54 case StepsTimingFunction::Start: 55 return "step-start"; 56 case StepsTimingFunction::Middle: 57 return "step-middle"; 58 case StepsTimingFunction::End: 59 return "step-end"; 60 case StepsTimingFunction::Custom: 61 builder.append("steps(" + String::numberToStringECMAScript(this->numberOfSteps()) + ", "); 62 63 if (this->stepAtPosition() == StepsTimingFunction::StepAtStart) 64 builder.append("start"); 65 else if (this->stepAtPosition() == StepsTimingFunction::StepAtMiddle) 66 builder.append("middle"); 67 else if (this->stepAtPosition() == StepsTimingFunction::StepAtEnd) 68 builder.append("end"); 69 else 70 ASSERT_NOT_REACHED(); 71 72 builder.append(")"); 73 break; 74 default: 75 ASSERT_NOT_REACHED(); 76 } 77 return builder.toString(); 78 } 79 80 double StepsTimingFunction::evaluate(double fraction, double) const 81 { 82 double startOffset = 0; 83 switch (m_stepAtPosition) { 84 case StepAtStart: 85 startOffset = 1; 86 break; 87 case StepAtMiddle: 88 startOffset = 0.5; 89 break; 90 case StepAtEnd: 91 startOffset = 0; 92 break; 93 default: 94 ASSERT_NOT_REACHED(); 95 break; 96 } 97 return clampTo(floor((m_steps * fraction) + startOffset) / m_steps, 0.0, 1.0); 98 } 99 100 // Equals operators 101 bool operator==(const LinearTimingFunction& lhs, const TimingFunction& rhs) 102 { 103 return rhs.type() == TimingFunction::LinearFunction; 104 } 105 106 bool operator==(const CubicBezierTimingFunction& lhs, const TimingFunction& rhs) 107 { 108 if (rhs.type() != TimingFunction::CubicBezierFunction) 109 return false; 110 111 const CubicBezierTimingFunction& ctf = toCubicBezierTimingFunction(rhs); 112 if ((lhs.subType() == CubicBezierTimingFunction::Custom) && (ctf.subType() == CubicBezierTimingFunction::Custom)) 113 return (lhs.x1() == ctf.x1()) && (lhs.y1() == ctf.y1()) && (lhs.x2() == ctf.x2()) && (lhs.y2() == ctf.y2()); 114 115 return lhs.subType() == ctf.subType(); 116 } 117 118 bool operator==(const StepsTimingFunction& lhs, const TimingFunction& rhs) 119 { 120 if (rhs.type() != TimingFunction::StepsFunction) 121 return false; 122 123 const StepsTimingFunction& stf = toStepsTimingFunction(rhs); 124 if ((lhs.subType() == StepsTimingFunction::Custom) && (stf.subType() == StepsTimingFunction::Custom)) 125 return (lhs.numberOfSteps() == stf.numberOfSteps()) && (lhs.stepAtPosition() == stf.stepAtPosition()); 126 127 return lhs.subType() == stf.subType(); 128 } 129 130 // The generic operator== *must* come after the 131 // non-generic operator== otherwise it will end up calling itself. 132 bool operator==(const TimingFunction& lhs, const TimingFunction& rhs) 133 { 134 switch (lhs.type()) { 135 case TimingFunction::LinearFunction: { 136 const LinearTimingFunction& linear = toLinearTimingFunction(lhs); 137 return (linear == rhs); 138 } 139 case TimingFunction::CubicBezierFunction: { 140 const CubicBezierTimingFunction& cubic = toCubicBezierTimingFunction(lhs); 141 return (cubic == rhs); 142 } 143 case TimingFunction::StepsFunction: { 144 const StepsTimingFunction& step = toStepsTimingFunction(lhs); 145 return (step == rhs); 146 } 147 default: 148 ASSERT_NOT_REACHED(); 149 } 150 return false; 151 } 152 153 // No need to define specific operator!= as they can all come via this function. 154 bool operator!=(const TimingFunction& lhs, const TimingFunction& rhs) 155 { 156 return !(lhs == rhs); 157 } 158 159 } // namespace WebCore 160