blob: d7bf9f24e9bec399cad27e3dce302b5906614b72 [file] [log] [blame]
/*
* Copyright 2022 Rive
*/
#ifndef _RIVE_RAW_PATH_UTILS_HPP_
#define _RIVE_RAW_PATH_UTILS_HPP_
#include "rive/math/vec2d.hpp"
namespace rive {
static inline Vec2D two(Vec2D v) { return v + v; }
// Caches the setup to evaluate a quadratic bezier. Useful if you
// want to evaluate the save curve at multiple t values.
// clang-format off
struct EvalQuad {
const Vec2D a, b, c; // at^2 + bt + c
// pts are the 3 quadratic bezier control points
EvalQuad(const Vec2D pts[3]) :
a(pts[0] - two(pts[1]) + pts[2]),
b(two(pts[1] - pts[0])),
c(pts[0]) {}
Vec2D operator()(float t) const { return (a * t + b) * t + c; }
};
// clang-format on
// Caches the setup to evaluate a cubic bezier. Useful if you
// want to evaluate the save curve at multiple t values.
struct EvalCubic {
const Vec2D a, b, c, d; // at^3 + bt^2 + ct + d
// pts are the 4 cubic bezier control points
EvalCubic(const Vec2D pts[4]) :
a(pts[3] + 3 * (pts[1] - pts[2]) - pts[0]),
b(3 * (pts[2] - two(pts[1]) + pts[0])),
c(3 * (pts[1] - pts[0])),
d(pts[0]) {}
Vec2D operator()(float t) const { return ((a * t + b) * t + c) * t + d; }
};
// These compute the number of line segments need to apprixmate the bezier
// curve to the specified inverse-tolerance. We take inverse since we need
// to divide by the "tolerance", and we want to save the cost of the divide.
//
// At "standard" tolerance might be 0.5 (half a pixel error), so the caller
// would base 2.0 as its inverse.
//
// These always return at least 1
//
extern int computeApproximatingQuadLineSegments(const Vec2D bezier[3], float invTolerance);
extern int computeApproximatingCubicLineSegments(const Vec2D bezier[4], float invTolerance);
// Extract a subcurve from the curve (given start and end t-values)
extern void quad_subdivide(const Vec2D src[3], float t, Vec2D dst[5]);
extern void cubic_subdivide(const Vec2D src[4], float t, Vec2D dst[7]);
extern void line_extract(const Vec2D src[2], float startT, float endT, Vec2D dst[2]);
extern void quad_extract(const Vec2D src[3], float startT, float endT, Vec2D dst[3]);
extern void cubic_extract(const Vec2D src[4], float startT, float endT, Vec2D dst[4]);
} // namespace rive
#endif