fdsm_ttf_parser/
lib.rs

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
17/// Loads a glyph from a [`ttf_parser::Face`] as a [`Shape`].
18pub 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        // eprintln!("move_to {x} {y}");
38        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        // eprintln!("line_to {x} {y}");
53        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        // eprintln!("quad_to {x1} {y1} {x} {y}");
65        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        // eprintln!("curve_to {x1} {y1} {x2} {y2} {x} {y}");
81        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        // eprintln!("close");
98        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}