x_graphics/
path.rs

1pub use crate::backend::path::*;
2use crate::{
3    device::{DeviceContext, DeviceContextBackend},
4    error::GraphicsError,
5    geometry::FRect,
6    DefaultDeviceContext, DefaultPath, Float,
7};
8
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub enum FillType {
11    Winding,
12    EvenOdd,
13}
14
15pub trait PathBackend {
16    type DeviceContextType: DeviceContextBackend;
17
18    fn new(context: Option<&Self::DeviceContextType>) -> Result<Self, GraphicsError>
19    where
20        Self: Sized;
21    fn get_fill_type(&self) -> FillType;
22    fn set_fill_type(&mut self, fill_type: FillType);
23    fn begin(&mut self);
24    fn close(&mut self);
25    fn move_to(&mut self, x: Float, y: Float);
26    fn line_to(&mut self, x: Float, y: Float);
27    fn arc_to(&mut self, x1: Float, y1: Float, x2: Float, y2: Float, radius: Float);
28    fn bezier_curve_to(&mut self, cpx1: Float, cpy1: Float, cpx2: Float, cpy2: Float, x: Float, y: Float);
29    fn quad_curve_to(&mut self, cpx: Float, cpy: Float, x: Float, y: Float);
30    fn add_arc(&mut self, x: Float, y: Float, radius: Float, start_angle: Float, end_angle: Float, clockwise: bool);
31    fn add_rect(&mut self, x: Float, y: Float, width: Float, height: Float);
32    fn add_circle(&mut self, x: Float, y: Float, radius: Float);
33    fn add_ellipse(&mut self, x: Float, y: Float, width: Float, height: Float);
34    fn add_rounded_rect(&mut self, x: Float, y: Float, width: Float, height: Float, radius: Float);
35    fn bounds(&self) -> FRect;
36    fn is_empty(&self) -> bool;
37}
38
39pub struct Path<T: PathBackend> {
40    pub(crate) backend: T,
41}
42
43impl<T: PathBackend> Path<T> {
44    pub fn new(context: Option<&DeviceContext<T::DeviceContextType>>) -> Result<Self, GraphicsError> {
45        Ok(Self {
46            backend: T::new(context.map(|ctx| &ctx.backend))?,
47        })
48    }
49
50    pub fn get_fill_type(&self) -> FillType {
51        self.backend.get_fill_type()
52    }
53
54    pub fn set_fill_type(&mut self, fill_type: FillType) {
55        self.backend.set_fill_type(fill_type);
56    }
57
58    pub fn begin(&mut self) {
59        self.backend.begin();
60    }
61
62    pub fn close(&mut self) {
63        self.backend.close();
64    }
65
66    pub fn move_to(&mut self, x: Float, y: Float) {
67        self.backend.move_to(x, y);
68    }
69
70    pub fn line_to(&mut self, x: Float, y: Float) {
71        self.backend.line_to(x, y);
72    }
73
74    pub fn arc_to(&mut self, x1: Float, y1: Float, x2: Float, y2: Float, radius: Float) {
75        self.backend.arc_to(x1, y1, x2, y2, radius);
76    }
77
78    pub fn bezier_curve_to(&mut self, cpx1: Float, cpy1: Float, cpx2: Float, cpy2: Float, x: Float, y: Float) {
79        self.backend.bezier_curve_to(cpx1, cpy1, cpx2, cpy2, x, y);
80    }
81
82    pub fn quad_curve_to(&mut self, cpx: Float, cpy: Float, x: Float, y: Float) {
83        self.backend.quad_curve_to(cpx, cpy, x, y);
84    }
85
86    pub fn add_arc(&mut self, x: Float, y: Float, radius: Float, start_angle: Float, end_angle: Float, clockwise: bool) {
87        self.backend.add_arc(x, y, radius, start_angle, end_angle, clockwise);
88    }
89
90    pub fn add_rect(&mut self, x: Float, y: Float, width: Float, height: Float) {
91        self.backend.add_rect(x, y, width, height);
92    }
93
94    pub fn add_circle(&mut self, x: Float, y: Float, radius: Float) {
95        self.backend.add_circle(x, y, radius);
96    }
97
98    pub fn add_ellipse(&mut self, x: Float, y: Float, width: Float, height: Float) {
99        self.backend.add_ellipse(x, y, width, height);
100    }
101
102    pub fn add_rounded_rect(&mut self, x: Float, y: Float, width: Float, height: Float, radius: Float) {
103        self.backend.add_rounded_rect(x, y, width, height, radius);
104    }
105
106    pub fn bounds(&self) -> FRect {
107        self.backend.bounds()
108    }
109
110    pub fn is_empty(&self) -> bool {
111        self.backend.is_empty()
112    }
113}
114
115impl Path<DefaultPath> {
116    pub fn new_default(context: Option<&DeviceContext<DefaultDeviceContext>>) -> Result<Self, GraphicsError> {
117        Self::new(context)
118    }
119}