blob: 0781c4fbe6f96f7350e83819039a51c219811b6d [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include "platform/animation/TimingFunction.h"
#include "wtf/MathExtras.h"
namespace WebCore {
String LinearTimingFunction::toString() const
{
return "linear";
}
double LinearTimingFunction::evaluate(double fraction, double) const
{
return fraction;
}
String CubicBezierTimingFunction::toString() const
{
switch (this->subType()) {
case CubicBezierTimingFunction::Ease:
return "ease";
case CubicBezierTimingFunction::EaseIn:
return "ease-in";
case CubicBezierTimingFunction::EaseOut:
return "ease-out";
case CubicBezierTimingFunction::EaseInOut:
return "ease-in-out";
case CubicBezierTimingFunction::Custom:
return "cubic-bezier(" + String::numberToStringECMAScript(this->x1()) + ", " +
String::numberToStringECMAScript(this->y1()) + ", " + String::numberToStringECMAScript(this->x2()) +
", " + String::numberToStringECMAScript(this->y2()) + ")";
default:
ASSERT_NOT_REACHED();
}
return "";
}
double CubicBezierTimingFunction::evaluate(double fraction, double accuracy) const
{
if (!m_bezier)
m_bezier = adoptPtr(new UnitBezier(m_x1, m_y1, m_x2, m_y2));
return m_bezier->solve(fraction, accuracy);
}
String StepsTimingFunction::toString() const
{
StringBuilder builder;
switch (this->subType()) {
case StepsTimingFunction::Start:
return "step-start";
case StepsTimingFunction::Middle:
return "step-middle";
case StepsTimingFunction::End:
return "step-end";
case StepsTimingFunction::Custom:
builder.append("steps(" + String::numberToStringECMAScript(this->numberOfSteps()) + ", ");
if (this->stepAtPosition() == StepsTimingFunction::StepAtStart)
builder.append("start");
else if (this->stepAtPosition() == StepsTimingFunction::StepAtMiddle)
builder.append("middle");
else if (this->stepAtPosition() == StepsTimingFunction::StepAtEnd)
builder.append("end");
else
ASSERT_NOT_REACHED();
builder.append(")");
break;
default:
ASSERT_NOT_REACHED();
}
return builder.toString();
}
double StepsTimingFunction::evaluate(double fraction, double) const
{
double startOffset = 0;
switch (m_stepAtPosition) {
case StepAtStart:
startOffset = 1;
break;
case StepAtMiddle:
startOffset = 0.5;
break;
case StepAtEnd:
startOffset = 0;
break;
default:
ASSERT_NOT_REACHED();
break;
}
return clampTo(floor((m_steps * fraction) + startOffset) / m_steps, 0.0, 1.0);
}
// Equals operators
bool operator==(const LinearTimingFunction& lhs, const TimingFunction& rhs)
{
return rhs.type() == TimingFunction::LinearFunction;
}
bool operator==(const CubicBezierTimingFunction& lhs, const TimingFunction& rhs)
{
if (rhs.type() != TimingFunction::CubicBezierFunction)
return false;
const CubicBezierTimingFunction& ctf = toCubicBezierTimingFunction(rhs);
if ((lhs.subType() == CubicBezierTimingFunction::Custom) && (ctf.subType() == CubicBezierTimingFunction::Custom))
return (lhs.x1() == ctf.x1()) && (lhs.y1() == ctf.y1()) && (lhs.x2() == ctf.x2()) && (lhs.y2() == ctf.y2());
return lhs.subType() == ctf.subType();
}
bool operator==(const StepsTimingFunction& lhs, const TimingFunction& rhs)
{
if (rhs.type() != TimingFunction::StepsFunction)
return false;
const StepsTimingFunction& stf = toStepsTimingFunction(rhs);
if ((lhs.subType() == StepsTimingFunction::Custom) && (stf.subType() == StepsTimingFunction::Custom))
return (lhs.numberOfSteps() == stf.numberOfSteps()) && (lhs.stepAtPosition() == stf.stepAtPosition());
return lhs.subType() == stf.subType();
}
// The generic operator== *must* come after the
// non-generic operator== otherwise it will end up calling itself.
bool operator==(const TimingFunction& lhs, const TimingFunction& rhs)
{
switch (lhs.type()) {
case TimingFunction::LinearFunction: {
const LinearTimingFunction& linear = toLinearTimingFunction(lhs);
return (linear == rhs);
}
case TimingFunction::CubicBezierFunction: {
const CubicBezierTimingFunction& cubic = toCubicBezierTimingFunction(lhs);
return (cubic == rhs);
}
case TimingFunction::StepsFunction: {
const StepsTimingFunction& step = toStepsTimingFunction(lhs);
return (step == rhs);
}
default:
ASSERT_NOT_REACHED();
}
return false;
}
// No need to define specific operator!= as they can all come via this function.
bool operator!=(const TimingFunction& lhs, const TimingFunction& rhs)
{
return !(lhs == rhs);
}
} // namespace WebCore