Home | History | Annotate | Download | only in animation
      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