Skip to main content

fdsm_skrifa/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use fdsm::{
4    bezier::{Point, Segment},
5    shape::{Contour, Shape},
6};
7use skrifa::{
8    FontRef, GlyphId, MetadataProvider, OutlineGlyph,
9    outline::{AdjustedMetrics, DrawError, DrawSettings, OutlinePen},
10    prelude::{LocationRef, Size},
11};
12
13extern crate nalgebra as na;
14
15#[cfg(test)]
16mod tests;
17
18/// Loads a glyph from a [`skrifa::FontRef`] as a [`Shape`].
19pub fn load_shape_from_face<'a>(
20    face: &FontRef<'_>,
21    glyph_id: GlyphId,
22    location_ref: impl Into<LocationRef<'a>>,
23) -> Result<(Shape<Contour>, AdjustedMetrics), DrawError> {
24    let glyph = face
25        .outline_glyphs()
26        .get(glyph_id)
27        .ok_or(DrawError::GlyphNotFound(glyph_id))?;
28    load_shape_from_glyph(glyph, location_ref)
29}
30
31/// Loads a glyph from a [`skrifa::OutlineGlyph`] as a [`Shape`].
32pub fn load_shape_from_glyph<'a>(
33    glyph: OutlineGlyph<'_>,
34    location_ref: impl Into<LocationRef<'a>>,
35) -> Result<(Shape<Contour>, AdjustedMetrics), DrawError> {
36    //
37    let mut builder = ShapeBuilder {
38        shape: Shape::default(),
39        start_point: None,
40        last_point: None,
41    };
42    let am = glyph.draw(
43        DrawSettings::unhinted(Size::unscaled(), location_ref),
44        &mut builder,
45    )?;
46    Ok((builder.shape, am))
47}
48
49#[derive(Debug)]
50struct ShapeBuilder {
51    shape: Shape<Contour>,
52    start_point: Option<Point>,
53    last_point: Option<Point>,
54}
55
56impl OutlinePen for ShapeBuilder {
57    fn move_to(&mut self, x: f32, y: f32) {
58        // eprintln!("move_to {x} {y}");
59        if let Some(contour) = self.shape.contours.last_mut()
60            && self.start_point != self.last_point
61        {
62            contour.segments.push(Segment::line(
63                self.last_point.unwrap(),
64                self.start_point.unwrap(),
65            ));
66        }
67        self.start_point = Some(Point::new(x.into(), y.into()));
68        self.last_point = self.start_point;
69        self.shape.contours.push(Contour::default());
70    }
71
72    fn line_to(&mut self, x: f32, y: f32) {
73        // eprintln!("line_to {x} {y}");
74        let next_point = Point::new(x.into(), y.into());
75        self.shape
76            .contours
77            .last_mut()
78            .unwrap()
79            .segments
80            .push(Segment::line(self.last_point.unwrap(), next_point));
81        self.last_point = Some(next_point);
82    }
83
84    fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32) {
85        // eprintln!("quad_to {x1} {y1} {x} {y}");
86        let next_point = Point::new(x.into(), y.into());
87        self.shape
88            .contours
89            .last_mut()
90            .unwrap()
91            .segments
92            .push(Segment::quad(
93                self.last_point.unwrap(),
94                Point::new(x1.into(), y1.into()),
95                next_point,
96            ));
97        self.last_point = Some(next_point);
98    }
99
100    fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) {
101        // eprintln!("curve_to {x1} {y1} {x2} {y2} {x} {y}");
102        let next_point = Point::new(x.into(), y.into());
103        self.shape
104            .contours
105            .last_mut()
106            .unwrap()
107            .segments
108            .push(Segment::cubic(
109                self.last_point.unwrap(),
110                Point::new(x1.into(), y1.into()),
111                Point::new(x2.into(), y2.into()),
112                next_point,
113            ));
114        self.last_point = Some(next_point);
115    }
116
117    fn close(&mut self) {
118        // eprintln!("close");
119        if let Some(contour) = self.shape.contours.last_mut()
120            && self.start_point != self.last_point
121        {
122            contour.segments.push(Segment::line(
123                self.last_point.take().unwrap(),
124                self.start_point.take().unwrap(),
125            ));
126        }
127    }
128}