1 | use crate::geom::traits::Transformation; |
2 | use crate::math::Point; |
3 | use crate::{ControlPointId, EndpointId, Position}; |
4 | |
5 | /// Represents an event or edge of path. |
6 | #[derive (Copy, Clone, Debug, PartialEq, Eq, Hash)] |
7 | #[cfg_attr (feature = "serialization" , derive(Serialize, Deserialize))] |
8 | pub enum Event<Endpoint, ControlPoint> { |
9 | Begin { |
10 | at: Endpoint, |
11 | }, |
12 | Line { |
13 | from: Endpoint, |
14 | to: Endpoint, |
15 | }, |
16 | Quadratic { |
17 | from: Endpoint, |
18 | ctrl: ControlPoint, |
19 | to: Endpoint, |
20 | }, |
21 | Cubic { |
22 | from: Endpoint, |
23 | ctrl1: ControlPoint, |
24 | ctrl2: ControlPoint, |
25 | to: Endpoint, |
26 | }, |
27 | End { |
28 | last: Endpoint, |
29 | first: Endpoint, |
30 | close: bool, |
31 | }, |
32 | } |
33 | |
34 | /// A path event representing endpoints and control points as positions. |
35 | pub type PathEvent = Event<Point, Point>; |
36 | |
37 | /// A path event representing endpoints and control points as IDs. |
38 | pub type IdEvent = Event<EndpointId, ControlPointId>; |
39 | |
40 | impl<Ep, Cp> Event<Ep, Cp> { |
41 | pub fn is_edge(&self) -> bool { |
42 | match self { |
43 | &Event::Line { .. } |
44 | | &Event::Quadratic { .. } |
45 | | &Event::Cubic { .. } |
46 | | &Event::End { close: true, .. } => true, |
47 | _ => false, |
48 | } |
49 | } |
50 | |
51 | pub fn from(&self) -> Ep |
52 | where |
53 | Ep: Clone, |
54 | { |
55 | match &self { |
56 | &Event::Line { from, .. } |
57 | | &Event::Quadratic { from, .. } |
58 | | &Event::Cubic { from, .. } |
59 | | &Event::Begin { at: from } |
60 | | &Event::End { last: from, .. } => from.clone(), |
61 | } |
62 | } |
63 | |
64 | pub fn to(&self) -> Ep |
65 | where |
66 | Ep: Clone, |
67 | { |
68 | match &self { |
69 | &Event::Line { to, .. } |
70 | | &Event::Quadratic { to, .. } |
71 | | &Event::Cubic { to, .. } |
72 | | &Event::Begin { at: to } |
73 | | &Event::End { first: to, .. } => to.clone(), |
74 | } |
75 | } |
76 | |
77 | pub fn with_points(&self) -> PathEvent |
78 | where |
79 | Ep: Position, |
80 | Cp: Position, |
81 | { |
82 | match self { |
83 | Event::Line { from, to } => Event::Line { |
84 | from: from.position(), |
85 | to: to.position(), |
86 | }, |
87 | Event::Quadratic { from, ctrl, to } => Event::Quadratic { |
88 | from: from.position(), |
89 | ctrl: ctrl.position(), |
90 | to: to.position(), |
91 | }, |
92 | Event::Cubic { |
93 | from, |
94 | ctrl1, |
95 | ctrl2, |
96 | to, |
97 | } => Event::Cubic { |
98 | from: from.position(), |
99 | ctrl1: ctrl1.position(), |
100 | ctrl2: ctrl2.position(), |
101 | to: to.position(), |
102 | }, |
103 | Event::Begin { at } => Event::Begin { at: at.position() }, |
104 | Event::End { last, first, close } => Event::End { |
105 | last: last.position(), |
106 | first: first.position(), |
107 | close: *close, |
108 | }, |
109 | } |
110 | } |
111 | } |
112 | |
113 | impl PathEvent { |
114 | pub fn transformed<T: Transformation<f32>>(&self, mat: &T) -> Self { |
115 | match self { |
116 | Event::Line { from, to } => Event::Line { |
117 | from: mat.transform_point(*from), |
118 | to: mat.transform_point(*to), |
119 | }, |
120 | Event::Quadratic { from, ctrl, to } => Event::Quadratic { |
121 | from: mat.transform_point(*from), |
122 | ctrl: mat.transform_point(*ctrl), |
123 | to: mat.transform_point(*to), |
124 | }, |
125 | Event::Cubic { |
126 | from, |
127 | ctrl1, |
128 | ctrl2, |
129 | to, |
130 | } => Event::Cubic { |
131 | from: mat.transform_point(*from), |
132 | ctrl1: mat.transform_point(*ctrl1), |
133 | ctrl2: mat.transform_point(*ctrl2), |
134 | to: mat.transform_point(*to), |
135 | }, |
136 | Event::Begin { at } => Event::Begin { |
137 | at: mat.transform_point(*at), |
138 | }, |
139 | Event::End { first, last, close } => Event::End { |
140 | last: mat.transform_point(*last), |
141 | first: mat.transform_point(*first), |
142 | close: *close, |
143 | }, |
144 | } |
145 | } |
146 | } |
147 | |