mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This caused us to lose our gn check certification. :( Turns out gn check was just ignoring all the header paths it didn't understand and so gn check passing for sky wasn't meaning much. I tried to straighten out some of the mess in this CL, but its going to take several more rounds of massaging before gn check passes again. On the bright side (almost) all of our headers are absolute now. Turns out my script (attached to the bug) didn't notice ../ includes but I'll fix that in the next patch. R=abarth@chromium.org BUG=435361 Review URL: https://codereview.chromium.org/746023002
230 lines
7.3 KiB
C++
230 lines
7.3 KiB
C++
// 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 "sky/engine/config.h"
|
|
#include "sky/engine/platform/animation/TimingFunction.h"
|
|
|
|
#include "sky/engine/wtf/MathExtras.h"
|
|
|
|
namespace blink {
|
|
|
|
String LinearTimingFunction::toString() const
|
|
{
|
|
return "linear";
|
|
}
|
|
|
|
double LinearTimingFunction::evaluate(double fraction, double) const
|
|
{
|
|
return fraction;
|
|
}
|
|
|
|
void LinearTimingFunction::range(double* minValue, double* maxValue) const
|
|
{
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
// This works by taking taking the derivative of the cubic bezier, on the y
|
|
// axis. We can then solve for where the derivative is zero to find the min
|
|
// and max distace along the line. We the have to solve those in terms of time
|
|
// rather than distance on the x-axis
|
|
void CubicBezierTimingFunction::range(double* minValue, double* maxValue) const
|
|
{
|
|
if (0 <= m_y1 && m_y2 < 1 && 0 <= m_y2 && m_y2 <= 1) {
|
|
return;
|
|
}
|
|
|
|
double a = 3.0 * (m_y1 - m_y2) + 1.0;
|
|
double b = 2.0 * (m_y2 - 2.0 * m_y1);
|
|
double c = m_y1;
|
|
|
|
if (std::abs(a) < std::numeric_limits<double>::epsilon()
|
|
&& std::abs(b) < std::numeric_limits<double>::epsilon()) {
|
|
return;
|
|
}
|
|
|
|
double t1 = 0.0;
|
|
double t2 = 0.0;
|
|
|
|
if (std::abs(a) < std::numeric_limits<double>::epsilon()) {
|
|
t1 = -c / b;
|
|
} else {
|
|
double discriminant = b * b - 4 * a * c;
|
|
if (discriminant < 0)
|
|
return;
|
|
double discriminantSqrt = sqrt(discriminant);
|
|
t1 = (-b + discriminantSqrt) / (2 * a);
|
|
t2 = (-b - discriminantSqrt) / (2 * a);
|
|
}
|
|
|
|
double solution1 = 0.0;
|
|
double solution2 = 0.0;
|
|
|
|
// If the solution is in the range [0,1] then we include it, otherwise we
|
|
// ignore it.
|
|
if (!m_bezier)
|
|
m_bezier = adoptPtr(new UnitBezier(m_x1, m_y1, m_x2, m_y2));
|
|
|
|
// An interesting fact about these beziers is that they are only
|
|
// actually evaluated in [0,1]. After that we take the tangent at that point
|
|
// and linearly project it out.
|
|
if (0 < t1 && t1 < 1)
|
|
solution1= m_bezier->sampleCurveY(t1);
|
|
|
|
if (0 < t2 && t2 < 1)
|
|
solution2 = m_bezier->sampleCurveY(t2);
|
|
|
|
// Since our input values can be out of the range 0->1 so we must also
|
|
// consider the minimum and maximum points.
|
|
double solutionMin = m_bezier->solve(*minValue, std::numeric_limits<double>::epsilon());
|
|
double solutionMax = m_bezier->solve(*maxValue, std::numeric_limits<double>::epsilon());
|
|
*minValue = std::min(std::min(solutionMin, solutionMax), 0.0);
|
|
*maxValue = std::max(std::max(solutionMin, solutionMax), 1.0);
|
|
*minValue = std::min(std::min(*minValue, solution1), solution2);
|
|
*maxValue = std::max(std::max(*maxValue, solution1), solution2);
|
|
}
|
|
|
|
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.appendLiteral("start");
|
|
else if (this->stepAtPosition() == StepsTimingFunction::StepAtMiddle)
|
|
builder.appendLiteral("middle");
|
|
else if (this->stepAtPosition() == StepsTimingFunction::StepAtEnd)
|
|
builder.appendLiteral("end");
|
|
else
|
|
ASSERT_NOT_REACHED();
|
|
|
|
builder.append(')');
|
|
break;
|
|
default:
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
return builder.toString();
|
|
}
|
|
|
|
void StepsTimingFunction::range(double* minValue, double* maxValue) const
|
|
{
|
|
*minValue = 0;
|
|
*maxValue = 1;
|
|
}
|
|
|
|
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 blink
|