makepad_vector/path/
path_iterator.rs1use crate::path::{LinePathCommand, PathCommand};
2use crate::geometry::{CubicSegment, QuadraticSegment};
3use crate::internal_iter::InternalIterator;
4
5pub trait PathIterator: InternalIterator<Item = PathCommand> {
7 fn linearize(self, epsilon: f64) -> Linearize<Self>
10 where
11 Self: Sized,
12 {
13 Linearize {
14 path: self,
15 epsilon,
16 }
17 }
18}
19
20impl<I> PathIterator for I where I: InternalIterator<Item = PathCommand> {}
21
22#[derive(Clone, Debug)]
24pub struct Linearize<P> {
25 path: P,
26 epsilon: f64,
27}
28
29impl<P> InternalIterator for Linearize<P>
30where
31 P: PathIterator,
32{
33 type Item = LinePathCommand;
34
35 fn for_each<F>(self, f: &mut F) -> bool
36 where
37 F: FnMut(LinePathCommand) -> bool,
38 {
39 let mut initial_point = None;
40 let mut current_point = None;
41 self.path.for_each({
42 let epsilon = self.epsilon;
43 &mut move |command| match command {
44 PathCommand::MoveTo(p) => {
45 initial_point = Some(p);
46 current_point = Some(p);
47 f(LinePathCommand::MoveTo(p))
48 }
49 PathCommand::LineTo(p) => {
50 current_point = Some(p);
51 f(LinePathCommand::LineTo(p))
52 }
53 PathCommand::QuadraticTo(p1, p) => {
54 QuadraticSegment::new(current_point.unwrap(), p1, p)
55 .linearize(epsilon)
56 .for_each(&mut |p| {
57 current_point = Some(p);
58 f(LinePathCommand::LineTo(p))
59 })
60 }
61 PathCommand::CubicTo(p1, p2, p) => {
62 CubicSegment::new(current_point.unwrap(), p1, p2, p)
63 .linearize(epsilon)
64 .for_each(&mut |p| {
65 current_point = Some(p);
66 f(LinePathCommand::LineTo(p))
67 })
68 }
69 PathCommand::Close => {
70 current_point = initial_point;
71 f(LinePathCommand::Close)
72 }
73 }
74 })
75 }
76}