| Index: ui/gfx/geometry/cubic_bezier.cc
|
| diff --git a/ui/gfx/geometry/cubic_bezier.cc b/ui/gfx/geometry/cubic_bezier.cc
|
| index 3d7e8fe930349eb3ec743aeec2b6311b99c66108..f9f786e7326105174ccff060fdb2ae0d2a186ab4 100644
|
| --- a/ui/gfx/geometry/cubic_bezier.cc
|
| +++ b/ui/gfx/geometry/cubic_bezier.cc
|
| @@ -16,19 +16,26 @@ namespace {
|
| static const double kBezierEpsilon = 1e-7;
|
| static const int MAX_STEPS = 30;
|
|
|
| -static double eval_bezier(double x1, double x2, double t) {
|
| - const double x1_times_3 = 3.0 * x1;
|
| - const double x2_times_3 = 3.0 * x2;
|
| - const double h3 = x1_times_3;
|
| - const double h1 = x1_times_3 - x2_times_3 + 1.0;
|
| - const double h2 = x2_times_3 - 6.0 * x1;
|
| +static double eval_bezier(double p1, double p2, double t) {
|
| + const double p1_times_3 = 3.0 * p1;
|
| + const double p2_times_3 = 3.0 * p2;
|
| + const double h3 = p1_times_3;
|
| + const double h1 = p1_times_3 - p2_times_3 + 1.0;
|
| + const double h2 = p2_times_3 - 6.0 * p1;
|
| return t * (t * (t * h1 + h2) + h3);
|
| }
|
|
|
| +static double eval_bezier_derivative(double p1, double p2, double t) {
|
| + const double h1 = 9.0 * p1 - 9.0 * p2 + 3.0;
|
| + const double h2 = 6.0 * p2 - 12.0 * p1;
|
| + const double h3 = 3.0 * p1;
|
| + return t * (t * h1 + h2) + h3;
|
| +}
|
| +
|
| +// Finds t such that eval_bezier(x1, x2, t) = x.
|
| +// There is a unique solution if x1 and x2 lie within (0, 1).
|
| static double bezier_interp(double x1,
|
| - double y1,
|
| double x2,
|
| - double y2,
|
| double x) {
|
| DCHECK_GE(1.0, x1);
|
| DCHECK_LE(0.0, x1);
|
| @@ -39,10 +46,6 @@ static double bezier_interp(double x1,
|
| x2 = std::min(std::max(x2, 0.0), 1.0);
|
| x = std::min(std::max(x, 0.0), 1.0);
|
|
|
| - // Step 1. Find the t corresponding to the given x. I.e., we want t such that
|
| - // eval_bezier(x1, x2, t) = x. There is a unique solution if x1 and x2 lie
|
| - // within (0, 1).
|
| - //
|
| // We're just going to do bisection for now (for simplicity), but we could
|
| // easily do some newton steps if this turns out to be a bottleneck.
|
| double t = 0.0;
|
| @@ -58,8 +61,7 @@ static double bezier_interp(double x1,
|
| // because we exceeded MAX_STEPS. Do a DCHECK here to confirm.
|
| DCHECK_GT(kBezierEpsilon, std::abs(eval_bezier(x1, x2, t) - x));
|
|
|
| - // Step 2. Return the interpolated y values at the t we computed above.
|
| - return eval_bezier(y1, y2, t);
|
| + return t;
|
| }
|
|
|
| } // namespace
|
| @@ -75,7 +77,14 @@ CubicBezier::~CubicBezier() {
|
| }
|
|
|
| double CubicBezier::Solve(double x) const {
|
| - return bezier_interp(x1_, y1_, x2_, y2_, x);
|
| + return eval_bezier(y1_, y2_, bezier_interp(x1_, x2_, x));
|
| +}
|
| +
|
| +double CubicBezier::Slope(double x) const {
|
| + double t = bezier_interp(x1_, x2_, x);
|
| + double dx_dt = eval_bezier_derivative(x1_, x2_, t);
|
| + double dy_dt = eval_bezier_derivative(y1_, y2_, t);
|
| + return dy_dt / dx_dt;
|
| }
|
|
|
| void CubicBezier::Range(double* min, double* max) const {
|
| @@ -85,6 +94,8 @@ void CubicBezier::Range(double* min, double* max) const {
|
| return;
|
|
|
| // Represent the function's derivative in the form at^2 + bt + c.
|
| + // (Technically this is (dy/dt)*(1/3), which is suitable for finding zeros
|
| + // but does not actually give the slope of the curve.)
|
| double a = 3 * (y1_ - y2_) + 1;
|
| double b = 2 * (y2_ - 2 * y1_);
|
| double c = y1_;
|
|
|