blob: 87a092f9b17089306a4b37df38ea96df88b26208 [file]
/*
* Copyright 2022 Rive
*/
#include "rive/math/raw_path_utils.hpp"
#include "rive/math/bezier_utils.hpp"
#include <algorithm>
// Exact at t=0, t=1 and when a == b, so coincident points survive a chop.
static rive::Vec2D exact_lerp(rive::Vec2D a, rive::Vec2D b, float t)
{
return t < 0.5f ? a + (b - a) * t : b - (b - a) * (1 - t);
}
static void quad_subdivide(
const rive::Vec2D src[3],
float t,
rive::Vec2D dst[5])
{
assert(t >= 0 && t <= 1);
auto ab = exact_lerp(src[0], src[1], t);
auto bc = exact_lerp(src[1], src[2], t);
dst[0] = src[0];
dst[1] = ab;
dst[2] = exact_lerp(ab, bc, t);
dst[3] = bc;
dst[4] = src[2];
}
void rive::line_extract(
const rive::Vec2D src[2],
float startT,
float endT,
rive::Vec2D dst[2])
{
assert(startT <= endT);
assert(startT >= 0 && endT <= 1);
dst[0] = exact_lerp(src[0], src[1], startT);
dst[1] = exact_lerp(src[0], src[1], endT);
}
void rive::quad_extract(
const rive::Vec2D src[3],
float startT,
float endT,
rive::Vec2D dst[3])
{
assert(startT <= endT);
assert(startT >= 0 && endT <= 1);
rive::Vec2D tmp[5];
if (startT == 0 && endT == 1)
{
std::copy(src, src + 3, dst);
}
else if (startT == 0)
{
quad_subdivide(src, endT, tmp);
std::copy(tmp, tmp + 3, dst);
}
else if (endT == 1)
{
quad_subdivide(src, startT, tmp);
std::copy(tmp + 2, tmp + 5, dst);
}
else
{
assert(endT > 0);
quad_subdivide(src, endT, tmp);
rive::Vec2D tmp2[5];
quad_subdivide(tmp, startT / endT, tmp2);
std::copy(tmp2 + 2, tmp2 + 5, dst);
}
}
void rive::cubic_extract(
const rive::Vec2D src[4],
float startT,
float endT,
rive::Vec2D dst[4])
{
rive::Vec2D tmp[10];
rive::math::chopCubicAt(src, tmp, startT, endT);
std::copy(tmp + 3, tmp + 7, dst);
}