| /* | 
 |  * Copyright 2023 Google LLC | 
 |  * | 
 |  * Use of this source code is governed by a BSD-style license that can be | 
 |  * found in the LICENSE file. | 
 |  */ | 
 | #ifndef SkBezierCurves_DEFINED | 
 | #define SkBezierCurves_DEFINED | 
 |  | 
 | #include "include/private/base/SkSpan_impl.h" | 
 |  | 
 | #include <array> | 
 |  | 
 | struct SkPoint; | 
 |  | 
 | /** | 
 |  * Utilities for dealing with cubic Bézier curves. These have a start XY | 
 |  * point, an end XY point, and two control XY points in between. They take | 
 |  * a parameter t which is between 0 and 1 (inclusive) which is used to | 
 |  * interpolate between the start and end points, via a route dictated by | 
 |  * the control points, and return a new XY point. | 
 |  * | 
 |  * We store a Bézier curve as an array of 8 floats or doubles, where | 
 |  * the even indices are the X coordinates, and the odd indices are the Y | 
 |  * coordinates. | 
 |  */ | 
 | class SkBezierCubic { | 
 | public: | 
 |  | 
 |     /** | 
 |      * Evaluates the cubic Bézier curve for a given t. It returns an X and Y coordinate | 
 |      * following the formula, which does the interpolation mentioned above. | 
 |      *     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 | 
 |      *     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 | 
 |      * | 
 |      * t is typically in the range [0, 1], but this function will not assert that, | 
 |      * as Bézier curves are well-defined for any real number input. | 
 |      */ | 
 |     static std::array<double, 2> EvalAt(const double curve[8], double t); | 
 |  | 
 |     /** | 
 |      * Splits the provided Bézier curve at the location t, resulting in two | 
 |      * Bézier curves that share a point (the end point from curve 1 | 
 |      * and the start point from curve 2 are the same). | 
 |      * | 
 |      * t must be in the interval [0, 1]. | 
 |      * | 
 |      * The provided twoCurves array will be filled such that indices | 
 |      * 0-7 are the first curve (representing the interval [0, t]), and | 
 |      * indices 6-13 are the second curve (representing [t, 1]). | 
 |      */ | 
 |     static void Subdivide(const double curve[8], double t, | 
 |                           double twoCurves[14]); | 
 |  | 
 |     /** | 
 |      * Converts the provided Bézier curve into the the equivalent cubic | 
 |      *    f(t) = A*t^3 + B*t^2 + C*t + D | 
 |      * where f(t) will represent Y coordinates over time if yValues is | 
 |      * true and the X coordinates if yValues is false. | 
 |      * | 
 |      * In effect, this turns the control points into an actual line, representing | 
 |      * the x or y values. | 
 |      */ | 
 |     static std::array<double, 4> ConvertToPolynomial(const double curve[8], bool yValues); | 
 |  | 
 |     static SkSpan<const float> IntersectWithHorizontalLine( | 
 |             SkSpan<const SkPoint> controlPoints, float yIntercept, | 
 |             float intersectionStorage[3]); | 
 |  | 
 |     static SkSpan<const float> Intersect( | 
 |             double AX, double BX, double CX, double DX, | 
 |             double AY, double BY, double CY, double DY, | 
 |             float toIntersect, float intersectionsStorage[3]); | 
 | }; | 
 |  | 
 | class SkBezierQuad { | 
 | public: | 
 |     static SkSpan<const float> IntersectWithHorizontalLine( | 
 |             SkSpan<const SkPoint> controlPoints, float yIntercept, | 
 |             float intersectionStorage[2]); | 
 |  | 
 |     /** | 
 |      * Given | 
 |      *    AY*t^2 -2*BY*t + CY = 0 and AX*t^2 - 2*BX*t + CX = 0, | 
 |      * | 
 |      * Find the t where AY*t^2 - 2*BY*t + CY - y = 0, then return AX*t^2 + - 2*BX*t + CX | 
 |      * where t is on [0, 1]. | 
 |      * | 
 |      * - y - is the height of the line which intersects the quadratic. | 
 |      * - intersectionStorage - is the array to hold the return data pointed to in the span. | 
 |      * | 
 |      * Returns a span with the intersections of yIntercept, and the quadratic formed by A, B, | 
 |      * and C. | 
 |      */ | 
 |     static SkSpan<const float> Intersect( | 
 |             double AX, double BX, double CX, | 
 |             double AY, double BY, double CY, | 
 |             double yIntercept, | 
 |             float intersectionStorage[2]); | 
 | }; | 
 |  | 
 | #endif  // SkBezierCurves_DEFINED |