use crate::bridge::ffi;
use crate::path::Path;
use crate::point::Point;
use cxx::UniquePtr;
pub use crate::bridge::ffi::PathVerb;
#[derive(Debug, Clone)]
pub enum PathVerbItem {
Move(Point),
Line(Point, Point),
Quad(Point, Point),
Conic(Point, Point, f32),
Cubic(Point, Point, Point),
Close,
}
impl PathVerbItem {
pub fn verb(&self) -> PathVerb {
match self {
PathVerbItem::Move(_) => PathVerb::Move,
PathVerbItem::Line(_, _) => PathVerb::Line,
PathVerbItem::Quad(_, _) => PathVerb::Quad,
PathVerbItem::Conic(_, _, _) => PathVerb::Conic,
PathVerbItem::Cubic(_, _, _) => PathVerb::Cubic,
PathVerbItem::Close => PathVerb::Close,
}
}
}
pub struct PathIter<'a> {
_path: &'a Path,
inner: UniquePtr<ffi::PathIterInner>,
p0: ffi::Point,
p1: ffi::Point,
p2: ffi::Point,
p3: ffi::Point,
}
impl<'a> PathIter<'a> {
pub(crate) fn new(path: &'a Path, force_close: bool) -> Self {
let inner = ffi::path_iter_new(path.as_raw(), force_close);
let z = ffi::Point { fX: 0.0, fY: 0.0 };
Self {
_path: path,
inner,
p0: z,
p1: z,
p2: z,
p3: z,
}
}
}
impl<'a> Iterator for PathIter<'a> {
type Item = PathVerbItem;
fn next(&mut self) -> Option<Self::Item> {
let v = ffi::path_iter_next(
self.inner.pin_mut(),
&mut self.p0,
&mut self.p1,
&mut self.p2,
&mut self.p3,
);
let item = match v {
PathVerb::Move => PathVerbItem::Move(self.p0.into()),
PathVerb::Line => PathVerbItem::Line(self.p0.into(), self.p1.into()),
PathVerb::Quad => PathVerbItem::Quad(self.p1.into(), self.p2.into()),
PathVerb::Conic => PathVerbItem::Conic(self.p1.into(), self.p2.into(), 1.0),
PathVerb::Cubic => PathVerbItem::Cubic(
self.p1.into(),
self.p2.into(),
self.p3.into(),
),
PathVerb::Close => PathVerbItem::Close,
PathVerb::Done => return None,
_ => return None,
};
Some(item)
}
}