use skia_safe::{Path as SkPath, PathFillType, utils::parse_path};
use crate::error::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum FillRule {
#[default]
NonZero,
EvenOdd,
}
impl FillRule {
pub(crate) fn to_skia(self) -> PathFillType {
match self {
Self::NonZero => PathFillType::Winding,
Self::EvenOdd => PathFillType::EvenOdd,
}
}
}
pub struct Path {
pub(crate) inner: SkPath,
}
impl Path {
pub fn from_svg(data: &str, fill_rule: FillRule) -> Result<Self, Error> {
let mut path = parse_path::from_svg(data).ok_or_else(|| {
Error::InvalidSvgPath {
reason: format!("could not parse SVG path data: {data:?}"),
}
})?;
path.set_fill_type(fill_rule.to_skia());
Ok(Self { inner: path })
}
pub fn fill_rule(&self) -> FillRule {
match self.inner.fill_type() {
PathFillType::EvenOdd | PathFillType::InverseEvenOdd => {
FillRule::EvenOdd
}
_ => FillRule::NonZero,
}
}
pub fn set_fill_rule(&mut self, fill_rule: FillRule) {
self.inner.set_fill_type(fill_rule.to_skia());
}
}
impl Clone for Path {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl std::fmt::Debug for Path {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Path")
.field("fill_rule", &self.fill_rule())
.finish()
}
}