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}