agg_rust/
vcgen_smooth_poly1.rs1use crate::array::{VertexDist, VertexSequence};
6use crate::basics::{
7 get_close_flag, is_move_to, is_stop, is_vertex, PATH_CMD_CURVE3, PATH_CMD_CURVE4,
8 PATH_CMD_END_POLY, PATH_CMD_LINE_TO, PATH_CMD_MOVE_TO, PATH_CMD_STOP,
9};
10use crate::conv_adaptor_vcgen::VcgenGenerator;
11
12#[derive(Debug, Clone, Copy, PartialEq)]
13enum Status {
14 Initial,
15 Ready,
16 Polygon,
17 CtrlB,
18 CtrlE,
19 Ctrl1,
20 Ctrl2,
21 EndPoly,
22 Stop,
23}
24
25pub struct VcgenSmoothPoly1 {
27 src_vertices: VertexSequence,
28 smooth_value: f64,
29 closed: u32,
30 status: Status,
31 src_vertex: usize,
32 ctrl1_x: f64,
33 ctrl1_y: f64,
34 ctrl2_x: f64,
35 ctrl2_y: f64,
36}
37
38impl VcgenSmoothPoly1 {
39 pub fn new() -> Self {
40 Self {
41 src_vertices: VertexSequence::new(),
42 smooth_value: 0.5,
43 closed: 0,
44 status: Status::Initial,
45 src_vertex: 0,
46 ctrl1_x: 0.0,
47 ctrl1_y: 0.0,
48 ctrl2_x: 0.0,
49 ctrl2_y: 0.0,
50 }
51 }
52
53 pub fn set_smooth_value(&mut self, v: f64) {
54 self.smooth_value = v * 0.5;
55 }
56
57 pub fn smooth_value(&self) -> f64 {
58 self.smooth_value * 2.0
59 }
60
61 pub fn remove_all(&mut self) {
62 self.src_vertices.remove_all();
63 self.closed = 0;
64 self.status = Status::Initial;
65 }
66
67 pub fn add_vertex(&mut self, x: f64, y: f64, cmd: u32) {
68 self.status = Status::Initial;
69 if is_move_to(cmd) {
70 self.src_vertices.modify_last(VertexDist::new(x, y));
71 } else if is_vertex(cmd) {
72 self.src_vertices.add(VertexDist::new(x, y));
73 } else {
74 self.closed = get_close_flag(cmd);
75 }
76 }
77
78 pub fn rewind(&mut self, _path_id: u32) {
79 if self.status == Status::Initial {
80 self.src_vertices.close(self.closed != 0);
81 }
82 self.status = Status::Ready;
83 self.src_vertex = 0;
84 }
85
86 fn calculate(&mut self, v0: &VertexDist, v1: &VertexDist, v2: &VertexDist, v3: &VertexDist) {
87 let k1 = v0.dist / (v0.dist + v1.dist);
88 let k2 = v1.dist / (v1.dist + v2.dist);
89
90 let xm1 = v0.x + (v2.x - v0.x) * k1;
91 let ym1 = v0.y + (v2.y - v0.y) * k1;
92 let xm2 = v1.x + (v3.x - v1.x) * k2;
93 let ym2 = v1.y + (v3.y - v1.y) * k2;
94
95 self.ctrl1_x = v1.x + self.smooth_value * (v2.x - xm1);
96 self.ctrl1_y = v1.y + self.smooth_value * (v2.y - ym1);
97 self.ctrl2_x = v2.x + self.smooth_value * (v1.x - xm2);
98 self.ctrl2_y = v2.y + self.smooth_value * (v1.y - ym2);
99 }
100
101 pub fn vertex(&mut self, x: &mut f64, y: &mut f64) -> u32 {
102 let mut cmd = PATH_CMD_LINE_TO;
103 loop {
104 if is_stop(cmd) {
105 return cmd;
106 }
107 match self.status {
108 Status::Initial => {
109 self.rewind(0);
110 continue;
111 }
112 Status::Ready => {
113 if self.src_vertices.size() < 2 {
114 cmd = PATH_CMD_STOP;
115 continue;
116 }
117 if self.src_vertices.size() == 2 {
118 *x = self.src_vertices[self.src_vertex].x;
119 *y = self.src_vertices[self.src_vertex].y;
120 self.src_vertex += 1;
121 if self.src_vertex == 1 {
122 return PATH_CMD_MOVE_TO;
123 }
124 if self.src_vertex == 2 {
125 return PATH_CMD_LINE_TO;
126 }
127 cmd = PATH_CMD_STOP;
128 continue;
129 }
130 cmd = PATH_CMD_MOVE_TO;
131 self.status = Status::Polygon;
132 self.src_vertex = 0;
133 continue;
134 }
135 Status::Polygon => {
136 if self.closed != 0 {
137 if self.src_vertex >= self.src_vertices.size() {
138 *x = self.src_vertices[0].x;
139 *y = self.src_vertices[0].y;
140 self.status = Status::EndPoly;
141 return PATH_CMD_CURVE4;
142 }
143 } else if self.src_vertex >= self.src_vertices.size() - 1 {
144 *x = self.src_vertices[self.src_vertices.size() - 1].x;
145 *y = self.src_vertices[self.src_vertices.size() - 1].y;
146 self.status = Status::EndPoly;
147 return PATH_CMD_CURVE3;
148 }
149
150 let v0 = *self.src_vertices.prev(self.src_vertex);
151 let v1 = *self.src_vertices.curr(self.src_vertex);
152 let v2 = *self.src_vertices.next(self.src_vertex);
153 let v3 = *self.src_vertices.next(self.src_vertex + 1);
154 self.calculate(&v0, &v1, &v2, &v3);
155
156 *x = self.src_vertices[self.src_vertex].x;
157 *y = self.src_vertices[self.src_vertex].y;
158 self.src_vertex += 1;
159
160 if self.closed != 0 {
161 self.status = Status::Ctrl1;
162 return if self.src_vertex == 1 {
163 PATH_CMD_MOVE_TO
164 } else {
165 PATH_CMD_CURVE4
166 };
167 }
168 if self.src_vertex == 1 {
169 self.status = Status::CtrlB;
170 return PATH_CMD_MOVE_TO;
171 }
172 if self.src_vertex >= self.src_vertices.size() - 1 {
173 self.status = Status::CtrlE;
174 return PATH_CMD_CURVE3;
175 }
176 self.status = Status::Ctrl1;
177 return PATH_CMD_CURVE4;
178 }
179 Status::CtrlB => {
180 *x = self.ctrl2_x;
181 *y = self.ctrl2_y;
182 self.status = Status::Polygon;
183 return PATH_CMD_CURVE3;
184 }
185 Status::CtrlE => {
186 *x = self.ctrl1_x;
187 *y = self.ctrl1_y;
188 self.status = Status::Polygon;
189 return PATH_CMD_CURVE3;
190 }
191 Status::Ctrl1 => {
192 *x = self.ctrl1_x;
193 *y = self.ctrl1_y;
194 self.status = Status::Ctrl2;
195 return PATH_CMD_CURVE4;
196 }
197 Status::Ctrl2 => {
198 *x = self.ctrl2_x;
199 *y = self.ctrl2_y;
200 self.status = Status::Polygon;
201 return PATH_CMD_CURVE4;
202 }
203 Status::EndPoly => {
204 self.status = Status::Stop;
205 return PATH_CMD_END_POLY | self.closed;
206 }
207 Status::Stop => {
208 return PATH_CMD_STOP;
209 }
210 }
211 }
212 }
213}
214
215impl Default for VcgenSmoothPoly1 {
216 fn default() -> Self {
217 Self::new()
218 }
219}
220
221impl VcgenGenerator for VcgenSmoothPoly1 {
222 fn remove_all(&mut self) {
223 self.remove_all();
224 }
225 fn add_vertex(&mut self, x: f64, y: f64, cmd: u32) {
226 self.add_vertex(x, y, cmd);
227 }
228 fn rewind(&mut self, path_id: u32) {
229 self.rewind(path_id);
230 }
231 fn vertex(&mut self, x: &mut f64, y: &mut f64) -> u32 {
232 self.vertex(x, y)
233 }
234}