use super::*;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "snake_case")
)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum ClipMode {
#[default]
Coverage,
Geometric,
}
pub trait IntoShapeClip {
fn into_shape_clip(self) -> Result<ShapeClip, ValidationError>;
}
impl IntoShapeClip for ShapeClip {
fn into_shape_clip(self) -> Result<ShapeClip, ValidationError> {
Ok(self)
}
}
impl IntoShapeClip for PathClip {
fn into_shape_clip(self) -> Result<ShapeClip, ValidationError> {
Ok(ShapeClip {
geometry: ClipGeometry::Path(self.path),
transform: self.transform,
rule: self.rule,
})
}
}
impl IntoShapeClip for RectClip {
fn into_shape_clip(self) -> Result<ShapeClip, ValidationError> {
Ok(ShapeClip {
geometry: ClipGeometry::Rectangle(self.bounds),
transform: self.transform,
rule: FillRule::NonZero,
})
}
}
impl<Geometry: Shape> IntoShapeClip for Geometry {
fn into_shape_clip(self) -> Result<ShapeClip, ValidationError> {
ShapeClip::new(&self)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct PathClip {
pub path: Arc<Path2D>,
pub transform: Transform,
pub rule: FillRule,
}
impl PathClip {
pub fn new(path: Path2D) -> Self {
Self {
path: Arc::new(path),
transform: Transform::IDENTITY,
rule: FillRule::NonZero,
}
}
}
impl From<Path2D> for PathClip {
fn from(path: Path2D) -> Self {
Self::new(path)
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct RectClip {
pub bounds: Rect,
pub transform: Transform,
}
impl RectClip {
pub const fn new(bounds: Rect) -> Self {
Self {
bounds,
transform: Transform::IDENTITY,
}
}
}
impl From<Rect> for RectClip {
fn from(bounds: Rect) -> Self {
Self::new(bounds)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct ShapeClip {
pub geometry: ClipGeometry,
pub transform: Transform,
pub rule: FillRule,
}
#[derive(Clone, Debug, PartialEq)]
pub enum ClipGeometry {
Rectangle(Rect),
Path(Arc<Path2D>),
}
impl ShapeClip {
pub fn new(shape: &(impl Shape + ?Sized)) -> Result<Self, ValidationError> {
let geometry = match shape.as_rect() {
Some(bounds) => ClipGeometry::Rectangle(bounds),
None => ClipGeometry::Path(Arc::new(shape.path()?)),
};
Ok(Self {
geometry,
transform: Transform::IDENTITY,
rule: FillRule::NonZero,
})
}
pub fn validate(&self, path: &str) -> Result<usize, ValidationError> {
match &self.geometry {
ClipGeometry::Rectangle(bounds) => {
crate::display_list::mapped_bounds(*bounds, self.transform, path)?;
Ok(0)
}
ClipGeometry::Path(geometry) => {
crate::display_list::validate_path(geometry, self.transform, path)?;
Ok(geometry.verbs().len())
}
}
}
}