fdsm_ttf_parser/
lib.rs

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