1#![doc = include_str!("../README.md")]
2
3pub use ttf_parser;
4
5extern crate nalgebra as na;
6
7use ttf_parser::{Face, GlyphId, OutlineBuilder};
8
9use fdsm::{
10 bezier::{Point, Segment},
11 shape::{Contour, Shape},
12};
13
14#[cfg(test)]
15mod tests;
16
17pub fn load_shape_from_face(face: &Face, glyph_id: GlyphId) -> Option<Shape<Contour>> {
19 let mut builder = ShapeBuilder {
20 shape: Shape::default(),
21 start_point: None,
22 last_point: None,
23 };
24 face.outline_glyph(glyph_id, &mut builder)?;
25 Some(builder.shape)
26}
27
28#[derive(Debug)]
29struct ShapeBuilder {
30 shape: Shape<Contour>,
31 start_point: Option<Point>,
32 last_point: Option<Point>,
33}
34
35impl OutlineBuilder for ShapeBuilder {
36 fn move_to(&mut self, x: f32, y: f32) {
37 if let Some(contour) = self.shape.contours.last_mut() {
39 if self.start_point != self.last_point {
40 contour.segments.push(Segment::line(
41 self.last_point.unwrap(),
42 self.start_point.unwrap(),
43 ));
44 }
45 }
46 self.start_point = Some(Point::new(x.into(), y.into()));
47 self.last_point = self.start_point;
48 self.shape.contours.push(Contour::default());
49 }
50
51 fn line_to(&mut self, x: f32, y: f32) {
52 let next_point = Point::new(x.into(), y.into());
54 self.shape
55 .contours
56 .last_mut()
57 .unwrap()
58 .segments
59 .push(Segment::line(self.last_point.unwrap(), next_point));
60 self.last_point = Some(next_point);
61 }
62
63 fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32) {
64 let next_point = Point::new(x.into(), y.into());
66 self.shape
67 .contours
68 .last_mut()
69 .unwrap()
70 .segments
71 .push(Segment::quad(
72 self.last_point.unwrap(),
73 Point::new(x1.into(), y1.into()),
74 next_point,
75 ));
76 self.last_point = Some(next_point);
77 }
78
79 fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) {
80 let next_point = Point::new(x.into(), y.into());
82 self.shape
83 .contours
84 .last_mut()
85 .unwrap()
86 .segments
87 .push(Segment::cubic(
88 self.last_point.unwrap(),
89 Point::new(x1.into(), y1.into()),
90 Point::new(x2.into(), y2.into()),
91 next_point,
92 ));
93 self.last_point = Some(next_point);
94 }
95
96 fn close(&mut self) {
97 if let Some(contour) = self.shape.contours.last_mut() {
99 if self.start_point != self.last_point {
100 contour.segments.push(Segment::line(
101 self.last_point.take().unwrap(),
102 self.start_point.take().unwrap(),
103 ));
104 }
105 }
106 }
107}