1 /* 2 * Copyright 2023 Google LLC 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 #ifndef SkBezierCurves_DEFINED 8 #define SkBezierCurves_DEFINED 9 10 #include <array> 11 12 /** 13 * Utilities for dealing with cubic Bézier curves. These have a start XY 14 * point, an end XY point, and two control XY points in between. They take 15 * a parameter t which is between 0 and 1 (inclusive) which is used to 16 * interpolate between the start and end points, via a route dictated by 17 * the control points, and return a new XY point. 18 * 19 * We store a Bézier curve as an array of 8 floats or doubles, where 20 * the even indices are the X coordinates, and the odd indices are the Y 21 * coordinates. 22 */ 23 class SkBezierCubic { 24 public: 25 26 /** 27 * Evaluates the cubic Bézier curve for a given t. It returns an X and Y coordinate 28 * following the formula, which does the interpolation mentioned above. 29 * X(t) = X_0*(1-t)^3 + 3*X_1*t(1-t)^2 + 3*X_2*t^2(1-t) + X_3*t^3 30 * Y(t) = Y_0*(1-t)^3 + 3*Y_1*t(1-t)^2 + 3*Y_2*t^2(1-t) + Y_3*t^3 31 * 32 * t is typically in the range [0, 1], but this function will not assert that, 33 * as Bézier curves are well-defined for any real number input. 34 */ 35 static std::array<double, 2> EvalAt(const double curve[8], double t); 36 37 /** 38 * Splits the provided Bézier curve at the location t, resulting in two 39 * Bézier curves that share a point (the end point from curve 1 40 * and the start point from curve 2 are the same). 41 * 42 * t must be in the interval [0, 1]. 43 * 44 * The provided twoCurves array will be filled such that indices 45 * 0-7 are the first curve (representing the interval [0, t]), and 46 * indices 6-13 are the second curve (representing [t, 1]). 47 */ 48 static void Subdivide(const double curve[8], double t, 49 double twoCurves[14]); 50 51 /** 52 * Converts the provided Bézier curve into the the equivalent cubic 53 * f(t) = A*t^3 + B*t^2 + C*t + D 54 * where f(t) will represent Y coordinates over time if yValues is 55 * true and the X coordinates if yValues is false. 56 * 57 * In effect, this turns the control points into an actual line, representing 58 * the x or y values. 59 */ 60 static std::array<double, 4> ConvertToPolynomial(const double curve[8], bool yValues); 61 }; 62 63 #endif 64