font_map_core/raw/ttf/glyf/
simple.rs

1#![allow(clippy::cast_possible_truncation)]
2use crate::error::ParseResult;
3use crate::reader::{BinaryReader, Parse};
4
5/// The outline features of a simple-type glyph
6#[derive(Debug, Clone)]
7pub struct SimpleGlyf {
8    /// The contours of the glyph
9    pub contours: Vec<Contour>,
10
11    /// The number of contours in the glyph
12    /// This field is used to prime the parser
13    pub num_contours: i16,
14
15    /// Horizontal bounds of the glyph
16    pub x: (i16, i16),
17
18    /// Vertical bounds of the glyph
19    pub y: (i16, i16),
20}
21
22impl Parse for SimpleGlyf {
23    fn parse(_: &mut BinaryReader) -> ParseResult<Self> {
24        unimplemented!("Use parse_with instead")
25    }
26
27    fn parse_with(&mut self, reader: &mut BinaryReader) -> ParseResult<()> {
28        // Simple glyph
29        let mut end_pts_of_contours = Vec::with_capacity(self.num_contours as usize);
30        let mut last_pt = 0;
31
32        for _ in 0..self.num_contours {
33            last_pt = reader.read_u16()?;
34            end_pts_of_contours.push(last_pt);
35        }
36
37        let instruction_length = reader.read_u16()?;
38        let _instructions = reader.read(instruction_length as usize)?;
39
40        let num_points = last_pt + 1;
41
42        //
43        // Parse instructions to get real point count
44        let mut flags = Vec::with_capacity(num_points as usize);
45        let mut remaining_pts = num_points;
46        while remaining_pts > 0 {
47            let flag = reader.read_u8()?;
48            let mut flag = Flag::from_byte(flag);
49            remaining_pts -= 1;
50
51            // Repeat the flag
52            if flag.repeats != 0 {
53                let n_times = reader.read_u8()?;
54                flag.repeats = n_times;
55                remaining_pts -= u16::from(n_times);
56            }
57
58            flags.push(flag);
59            flags.reserve(usize::from(flag.repeats));
60            for _ in 0..flag.repeats {
61                flags.push(flag);
62            }
63        }
64
65        //
66        // Parse X coords into objective coords
67        let mut x_coordinates = Vec::with_capacity(flags.len());
68        let mut last_x = 0;
69        for flag in &flags {
70            let delta = match flag.x_kind {
71                FlagCoordKind::NegShort => -i16::from(reader.read_u8()?),
72                FlagCoordKind::PosShort => i16::from(reader.read_u8()?),
73                FlagCoordKind::Long => reader.read_i16()?,
74                FlagCoordKind::Same => 0,
75            };
76
77            last_x += delta;
78            x_coordinates.push(last_x);
79        }
80
81        //
82        // Parse Y coords into objective coords
83        let mut y_coordinates = Vec::with_capacity(flags.len());
84        let mut last_y = 0;
85        for flag in &flags {
86            let delta = match flag.y_kind {
87                FlagCoordKind::NegShort => -i16::from(reader.read_u8()?),
88                FlagCoordKind::PosShort => i16::from(reader.read_u8()?),
89                FlagCoordKind::Long => reader.read_i16()?,
90                FlagCoordKind::Same => 0,
91            };
92
93            last_y += delta;
94            y_coordinates.push(last_y);
95        }
96
97        //
98        // Create points
99        let mut points = Vec::with_capacity(flags.len());
100        for i in 0..flags.len() {
101            let x = x_coordinates[i];
102            let y = y_coordinates[i];
103            let on_curve = flags[i].on_curve;
104            points.push(Point { x, y, on_curve });
105        }
106
107        //
108        // Map points to contours
109        let mut start = 0;
110        for end in &end_pts_of_contours {
111            let contour_points = points[start..=*end as usize].to_vec();
112            start = *end as usize + 1;
113            self.contours.push(Contour {
114                points: contour_points,
115            });
116        }
117
118        Ok(())
119    }
120}
121
122#[derive(Debug, Default, Clone, Copy)]
123pub enum FlagCoordKind {
124    NegShort,
125    PosShort,
126    Long,
127
128    #[default]
129    Same,
130}
131
132/// A flag describing a point in a glyph outline
133#[derive(Debug, Default, Clone, Copy)]
134pub struct Flag {
135    pub repeats: u8,
136    pub on_curve: bool,
137    pub x_kind: FlagCoordKind,
138    pub y_kind: FlagCoordKind,
139}
140impl Flag {
141    pub fn from_byte(flag: u8) -> Self {
142        //
143        // Extract flag components
144        let on_curve = (flag & 0x01) != 0;
145        let x_short_vec = (flag & 0x02) != 0;
146        let y_short_vec = (flag & 0x04) != 0;
147        let repeats = flag & 0x08;
148        let x_same_or_pos = (flag & 0x10) != 0;
149        let y_same_or_pos = (flag & 0x20) != 0;
150
151        //
152        // Parse out the meanings
153        let x_kind = match (x_short_vec, x_same_or_pos) {
154            (true, false) => FlagCoordKind::NegShort, /* 1 byte coord - pos */
155            (true, true) => FlagCoordKind::PosShort,  /* 1 byte coord - neg */
156            (false, false) => FlagCoordKind::Long,    /* 2 byte short */
157            _ => FlagCoordKind::Same,                 /* Same as previous */
158        };
159        let y_kind = match (y_short_vec, y_same_or_pos) {
160            (true, false) => FlagCoordKind::NegShort, /* 1 byte coord - pos */
161            (true, true) => FlagCoordKind::PosShort,  /* 1 byte coord - neg */
162            (false, false) => FlagCoordKind::Long,    /* 2 byte short */
163            _ => FlagCoordKind::Same,                 /* Same as previous */
164        };
165
166        Self {
167            repeats,
168            on_curve,
169            x_kind,
170            y_kind,
171        }
172    }
173}
174
175/// A point in a glyph outline
176#[derive(Debug, Default, Clone, Copy)]
177pub struct Point {
178    pub x: i16,
179    pub y: i16,
180    pub on_curve: bool,
181}
182
183/// A set of points making up a contour in a glyph
184#[derive(Debug, Clone)]
185pub struct Contour {
186    pub points: Vec<Point>,
187}