use lyon::lyon_tessellation::Attributes;
use lyon::path::builder::NoAttributes;
use crate::geom::Point2;
pub struct Path {
path: lyon::path::Path,
}
pub struct Builder {
builder: NoAttributes<lyon::path::Builder>,
}
impl Default for Path {
fn default() -> Self {
Self::new()
}
}
impl Path {
pub fn builder() -> Builder {
Builder::new()
}
pub fn new() -> Self {
lyon::path::Path::new().into()
}
pub fn as_slice(&self) -> lyon::path::PathSlice<'_> {
self.path.as_slice()
}
pub fn attributes(&self, endpoint: lyon::path::EndpointId) -> &[f32] {
self.path.attributes(endpoint)
}
pub fn iter(&self) -> lyon::path::Iter<'_> {
self.path.iter()
}
pub fn id_iter(&self) -> lyon::path::IdIter<'_> {
self.path.id_iter()
}
pub fn iter_with_attributes(&self) -> lyon::path::IterWithAttributes<'_> {
self.path.iter_with_attributes()
}
pub fn transformed<T>(self, transform: &T) -> Self
where
T: lyon::geom::traits::Transformation<f32>,
{
self.path.transformed(transform).into()
}
pub fn reversed(&self) -> Self {
let path = self.path.reversed().collect();
Path { path }
}
pub fn merge(&self, other: &Self) -> Self {
Self {
path: self.path.iter().chain(other.iter()).collect(),
}
}
}
impl Default for Builder {
fn default() -> Self {
Self::new()
}
}
impl Builder {
pub fn new() -> Self {
lyon::path::Builder::new().into()
}
pub fn with_capacity(points: usize, edges: usize) -> Self {
lyon::path::Builder::with_capacity(points, edges).into()
}
pub fn with_svg(self) -> lyon::path::builder::WithSvg<Self> {
lyon::path::builder::WithSvg::new(self)
}
pub fn flattened(self, tolerance: f32) -> lyon::path::builder::Flattened<Self> {
lyon::path::builder::Flattened::new(self, tolerance)
}
pub fn begin(mut self, to: Point2) -> Self {
self.builder.begin(to.to_array().into());
self
}
pub fn line_to(mut self, to: Point2) -> Self {
self.builder.line_to(to.to_array().into());
self
}
pub fn close(mut self) -> Self {
self.builder.close();
self
}
pub fn quadratic_bezier_to(mut self, ctrl: Point2, to: Point2) -> Self {
self.builder
.quadratic_bezier_to(ctrl.to_array().into(), to.to_array().into());
self
}
pub fn cubic_bezier_to(mut self, ctrl1: Point2, ctrl2: Point2, to: Point2) -> Self {
self.builder.cubic_bezier_to(
ctrl1.to_array().into(),
ctrl2.to_array().into(),
to.to_array().into(),
);
self
}
pub fn build(self) -> Path {
self.builder.build().into()
}
pub fn inner(&self) -> &lyon::path::Builder {
self.builder.inner()
}
pub fn inner_mut(&mut self) -> &mut lyon::path::Builder {
self.builder.inner_mut()
}
}
impl lyon::path::builder::Build for Builder {
type PathType = Path;
fn build(self) -> Self::PathType {
self.builder.build().into()
}
}
impl lyon::path::builder::PathBuilder for Builder {
fn num_attributes(&self) -> usize {
0
}
fn begin(
&mut self,
at: lyon::math::Point,
_custom_attributes: Attributes,
) -> lyon::path::EndpointId {
self.builder.begin(at)
}
fn end(&mut self, close: bool) {
self.builder.end(close)
}
fn line_to(
&mut self,
to: lyon::math::Point,
_custom_attributes: Attributes,
) -> lyon::path::EndpointId {
self.builder.line_to(to)
}
fn quadratic_bezier_to(
&mut self,
ctrl: lyon::math::Point,
to: lyon::math::Point,
_custom_attributes: Attributes,
) -> lyon::path::EndpointId {
self.builder.quadratic_bezier_to(ctrl, to)
}
fn cubic_bezier_to(
&mut self,
ctrl1: lyon::math::Point,
ctrl2: lyon::math::Point,
to: lyon::math::Point,
_custom_attributes: Attributes,
) -> lyon::path::EndpointId {
self.builder.cubic_bezier_to(ctrl1, ctrl2, to)
}
}
impl std::ops::Index<lyon::path::ControlPointId> for Path {
type Output = Point2;
fn index(&self, id: lyon::path::ControlPointId) -> &Self::Output {
point_lyon_to_nannou(self.path.index(id))
}
}
impl std::ops::Index<lyon::path::EndpointId> for Path {
type Output = Point2;
fn index(&self, id: lyon::path::EndpointId) -> &Self::Output {
point_lyon_to_nannou(self.path.index(id))
}
}
impl<'a> IntoIterator for &'a Path {
type Item = lyon::path::PathEvent;
type IntoIter = lyon::path::Iter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl From<lyon::path::Path> for Path {
fn from(path: lyon::path::Path) -> Self {
Path { path }
}
}
impl From<lyon::path::Builder> for Builder {
fn from(builder: lyon::path::Builder) -> Self {
Builder {
builder: NoAttributes::wrap(builder),
}
}
}
impl From<Path> for lyon::path::Path {
fn from(val: Path) -> Self {
val.path
}
}
impl From<Builder> for lyon::path::Builder {
fn from(val: Builder) -> Self {
val.builder.into_inner()
}
}
impl<'a> From<&'a Path> for lyon::path::PathSlice<'a> {
fn from(val: &'a Path) -> Self {
val.as_slice()
}
}
pub fn path() -> Builder {
Builder::new()
}
pub fn path_with_capacity(points: usize, edges: usize) -> Builder {
Builder::with_capacity(points, edges)
}
fn point_lyon_to_nannou(p: &lyon::math::Point) -> &Point2 {
unsafe { std::mem::transmute(p) }
}