// Copyright 2024 the Velato Authors // SPDX-License-Identifier: Apache-2.0 OR MIT use kurbo::{PathEl, Point}; /// Helper trait for converting cubic splines to paths. pub trait SplineToPath { fn get(&self, index: usize) -> Point; fn len(&self) -> usize; fn to_path(&self, is_closed: bool, path: &mut Vec) -> Option<()> { use PathEl::*; if self.len() == 0 { return None; } path.push(MoveTo(self.get(0))); let n_vertices = self.len() / 3; let mut add_element = |from_vertex, to_vertex| { let from_index = 3 * from_vertex; let to_index = 3 * to_vertex; let p0: Point = self.get(from_index); let p1: Point = self.get(to_index); let mut c0: Point = self.get(from_index + 2); c0.x += p0.x; c0.y += p0.y; let mut c1: Point = self.get(to_index + 1); c1.x += p1.x; c1.y += p1.y; if c0 == p0 && c1 == p1 { path.push(LineTo(p1)); } else { path.push(CurveTo(c0, c1, p1)); } }; for i in 1..n_vertices { add_element(i - 1, i); } if is_closed && n_vertices != 0 { add_element(n_vertices - 1, 0); path.push(ClosePath); } Some(()) } } /// Converts a static spline to a path. impl SplineToPath for &'_ [Point] { fn len(&self) -> usize { self.as_ref().len() } fn get(&self, index: usize) -> Point { self[index] } } /// Produces a path by lerping between two sets of points. impl SplineToPath for (&'_ [Point], &'_ [Point], f64) { fn len(&self) -> usize { self.0.len().min(self.1.len()) } fn get(&self, index: usize) -> Point { // TODO: This definitely shouldn't be a lerp self.0[index].lerp(self.1[index], self.2) } }