path_offset/path/conversions/
flo_curves.rs1use flo_curves::{
2 bezier::{
3 path::{BezierPathBuilder, SimpleBezierPath},
4 Curve,
5 },
6 BezierCurve, Coord2, Coordinate,
7};
8use lyon::path::Event;
9
10use crate::path::point::PointConvert;
11
12impl From<&crate::path::Path> for SimpleBezierPath {
13 fn from(path: &crate::path::Path) -> SimpleBezierPath {
14 let mut builder = BezierPathBuilder::<SimpleBezierPath>::start(Coord2::from((0.0, 0.0)));
15 let mut current_pos = Coord2::from((0.0, 0.0)); for event in path.inner.iter() {
18 match event {
19 Event::Begin { at } => {
20 let start_point = at.use_as();
21 builder = BezierPathBuilder::start(start_point);
22 current_pos = start_point;
23 }
24 Event::Line { to, .. } => {
25 let to_point = to.use_as();
26 builder = builder.line_to(to_point);
27 current_pos = to_point;
28 }
29 Event::Quadratic { ctrl, to, .. } => {
30 let cp1: Coord2 =
32 current_pos + (ctrl.use_as::<Coord2>() - current_pos) * (2.0 / 3.0);
33 let cp2: Coord2 = to.use_as::<Coord2>()
34 + (ctrl.use_as::<Coord2>() - to.use_as::<Coord2>()) * (2.0 / 3.0);
35
36 let to_point = to.use_as();
37 builder = builder.curve_to((cp1, cp2), to_point);
38 current_pos = to_point;
39 }
40 Event::Cubic {
41 ctrl1, ctrl2, to, ..
42 } => {
43 let to_point = to.use_as();
44 builder = builder.curve_to((ctrl1.use_as(), ctrl2.use_as()), to_point);
45 current_pos = to_point;
46 }
47 Event::End { first, close, .. } => {
49 if !close {
51 if current_pos.distance_to(&first.use_as()) > 1e-6 {
53 builder = builder.line_to(first.use_as());
54 }
55 }
56 }
58 }
59 }
60
61 builder.build()
62 }
63}
64
65impl From<&Vec<Curve<Coord2>>> for crate::path::Path {
66 fn from(value: &Vec<Curve<Coord2>>) -> Self {
67 let mut builder = lyon::path::Path::builder();
68
69 let mut points = vec![];
70 for curve in value {
71 let start_point = curve.start_point();
72 let end_point = curve.end_point();
73 let (ctrl1, ctrl2) = curve.control_points();
74
75 points.push((
76 start_point.use_as(),
77 ctrl1.use_as(),
78 ctrl2.use_as(),
79 end_point.use_as(),
80 ));
81 }
82
83 for (start, ctrl1, ctrl2, end) in points {
84 builder.begin(start);
85 builder.cubic_bezier_to(ctrl1, ctrl2, end);
86 builder.end(false);
87 }
88
89 Self {
90 inner: builder.build(),
91 }
92 }
93}
94
95impl From<&SimpleBezierPath> for crate::path::Path {
96 fn from(value: &SimpleBezierPath) -> Self {
97 let (start_point, segments) = value;
98 let mut builder = lyon::path::Path::builder();
99
100 builder.begin(start_point.use_as());
102
103 let mut last_point = start_point;
105
106 for (ctrl1, ctrl2, to) in segments {
107 if ctrl1.is_nan() || ctrl2.is_nan() || to.is_nan() {
108 continue;
109 }
110
111 let is_line = ctrl1 == last_point && ctrl2 == to;
112
113 if is_line {
114 builder.line_to(to.use_as());
115 } else {
116 builder.cubic_bezier_to(ctrl1.use_as(), ctrl2.use_as(), to.use_as());
117 }
118
119 last_point = to;
120 }
121
122 builder.line_to(start_point.use_as());
124 builder.close();
125
126 Self {
127 inner: builder.build(),
128 }
129 }
130}