pub use crate::backend::path::*;
use crate::{
device::{DeviceContext, DeviceContextBackend},
error::GraphicsError,
geometry::FRect,
DefaultDeviceContext, DefaultPath, Float,
};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum FillType {
Winding,
EvenOdd,
}
pub trait PathBackend {
type DeviceContextType: DeviceContextBackend;
fn new(context: Option<&Self::DeviceContextType>) -> Result<Self, GraphicsError>
where
Self: Sized;
fn get_fill_type(&self) -> FillType;
fn set_fill_type(&mut self, fill_type: FillType);
fn begin(&mut self);
fn close(&mut self);
fn move_to(&mut self, x: Float, y: Float);
fn line_to(&mut self, x: Float, y: Float);
fn arc_to(&mut self, x1: Float, y1: Float, x2: Float, y2: Float, radius: Float);
fn bezier_curve_to(&mut self, cpx1: Float, cpy1: Float, cpx2: Float, cpy2: Float, x: Float, y: Float);
fn quad_curve_to(&mut self, cpx: Float, cpy: Float, x: Float, y: Float);
fn add_arc(&mut self, x: Float, y: Float, radius: Float, start_angle: Float, end_angle: Float, clockwise: bool);
fn add_rect(&mut self, x: Float, y: Float, width: Float, height: Float);
fn add_circle(&mut self, x: Float, y: Float, radius: Float);
fn add_ellipse(&mut self, x: Float, y: Float, width: Float, height: Float);
fn add_rounded_rect(&mut self, x: Float, y: Float, width: Float, height: Float, radius: Float);
fn bounds(&self) -> FRect;
fn is_empty(&self) -> bool;
}
pub struct Path<T: PathBackend> {
pub(crate) backend: T,
}
impl<T: PathBackend> Path<T> {
pub fn new(context: Option<&DeviceContext<T::DeviceContextType>>) -> Result<Self, GraphicsError> {
Ok(Self {
backend: T::new(context.map(|ctx| &ctx.backend))?,
})
}
pub fn get_fill_type(&self) -> FillType {
self.backend.get_fill_type()
}
pub fn set_fill_type(&mut self, fill_type: FillType) {
self.backend.set_fill_type(fill_type);
}
pub fn begin(&mut self) {
self.backend.begin();
}
pub fn close(&mut self) {
self.backend.close();
}
pub fn move_to(&mut self, x: Float, y: Float) {
self.backend.move_to(x, y);
}
pub fn line_to(&mut self, x: Float, y: Float) {
self.backend.line_to(x, y);
}
pub fn arc_to(&mut self, x1: Float, y1: Float, x2: Float, y2: Float, radius: Float) {
self.backend.arc_to(x1, y1, x2, y2, radius);
}
pub fn bezier_curve_to(&mut self, cpx1: Float, cpy1: Float, cpx2: Float, cpy2: Float, x: Float, y: Float) {
self.backend.bezier_curve_to(cpx1, cpy1, cpx2, cpy2, x, y);
}
pub fn quad_curve_to(&mut self, cpx: Float, cpy: Float, x: Float, y: Float) {
self.backend.quad_curve_to(cpx, cpy, x, y);
}
pub fn add_arc(&mut self, x: Float, y: Float, radius: Float, start_angle: Float, end_angle: Float, clockwise: bool) {
self.backend.add_arc(x, y, radius, start_angle, end_angle, clockwise);
}
pub fn add_rect(&mut self, x: Float, y: Float, width: Float, height: Float) {
self.backend.add_rect(x, y, width, height);
}
pub fn add_circle(&mut self, x: Float, y: Float, radius: Float) {
self.backend.add_circle(x, y, radius);
}
pub fn add_ellipse(&mut self, x: Float, y: Float, width: Float, height: Float) {
self.backend.add_ellipse(x, y, width, height);
}
pub fn add_rounded_rect(&mut self, x: Float, y: Float, width: Float, height: Float, radius: Float) {
self.backend.add_rounded_rect(x, y, width, height, radius);
}
pub fn bounds(&self) -> FRect {
self.backend.bounds()
}
pub fn is_empty(&self) -> bool {
self.backend.is_empty()
}
}
impl Path<DefaultPath> {
pub fn new_default(context: Option<&DeviceContext<DefaultDeviceContext>>) -> Result<Self, GraphicsError> {
Self::new(context)
}
}