font_map_core/raw/ttf/glyf/
simple.rs#![allow(clippy::cast_possible_truncation)]
use crate::error::ParseResult;
use crate::reader::{BinaryReader, Parse};
#[derive(Debug, Clone)]
pub struct SimpleGlyf {
pub contours: Vec<Contour>,
pub num_contours: i16,
pub x: (i16, i16),
pub y: (i16, i16),
}
impl Parse for SimpleGlyf {
fn parse(_: &mut BinaryReader) -> ParseResult<Self> {
unimplemented!("Use parse_with instead")
}
fn parse_with(&mut self, reader: &mut BinaryReader) -> ParseResult<()> {
let mut end_pts_of_contours = Vec::with_capacity(self.num_contours as usize);
let mut last_pt = 0;
for _ in 0..self.num_contours {
last_pt = reader.read_u16()?;
end_pts_of_contours.push(last_pt);
}
let instruction_length = reader.read_u16()?;
let _instructions = reader.read(instruction_length as usize)?;
let num_points = last_pt + 1;
let mut flags = Vec::with_capacity(num_points as usize);
let mut remaining_pts = num_points;
while remaining_pts > 0 {
let flag = reader.read_u8()?;
let mut flag = Flag::from_byte(flag);
remaining_pts -= 1;
if flag.repeats != 0 {
let n_times = reader.read_u8()?;
flag.repeats = n_times;
remaining_pts -= u16::from(n_times);
}
flags.push(flag);
flags.reserve(usize::from(flag.repeats));
for _ in 0..flag.repeats {
flags.push(flag);
}
}
let mut x_coordinates = Vec::with_capacity(flags.len());
let mut last_x = 0;
for flag in &flags {
let delta = match flag.x_kind {
FlagCoordKind::NegShort => -i16::from(reader.read_u8()?),
FlagCoordKind::PosShort => i16::from(reader.read_u8()?),
FlagCoordKind::Long => reader.read_i16()?,
FlagCoordKind::Same => 0,
};
last_x += delta;
x_coordinates.push(last_x);
}
let mut y_coordinates = Vec::with_capacity(flags.len());
let mut last_y = 0;
for flag in &flags {
let delta = match flag.y_kind {
FlagCoordKind::NegShort => -i16::from(reader.read_u8()?),
FlagCoordKind::PosShort => i16::from(reader.read_u8()?),
FlagCoordKind::Long => reader.read_i16()?,
FlagCoordKind::Same => 0,
};
last_y += delta;
y_coordinates.push(last_y);
}
let mut points = Vec::with_capacity(flags.len());
for i in 0..flags.len() {
let x = x_coordinates[i];
let y = y_coordinates[i];
let on_curve = flags[i].on_curve;
points.push(Point { x, y, on_curve });
}
let mut start = 0;
for end in &end_pts_of_contours {
let contour_points = points[start..=*end as usize].to_vec();
start = *end as usize + 1;
self.contours.push(Contour {
points: contour_points,
});
}
Ok(())
}
}
#[derive(Debug, Default, Clone, Copy)]
pub enum FlagCoordKind {
NegShort,
PosShort,
Long,
#[default]
Same,
}
#[derive(Debug, Default, Clone, Copy)]
pub struct Flag {
pub repeats: u8,
pub on_curve: bool,
pub x_kind: FlagCoordKind,
pub y_kind: FlagCoordKind,
}
impl Flag {
pub fn from_byte(flag: u8) -> Self {
let on_curve = (flag & 0x01) != 0;
let x_short_vec = (flag & 0x02) != 0;
let y_short_vec = (flag & 0x04) != 0;
let repeats = flag & 0x08;
let x_same_or_pos = (flag & 0x10) != 0;
let y_same_or_pos = (flag & 0x20) != 0;
let x_kind = match (x_short_vec, x_same_or_pos) {
(true, false) => FlagCoordKind::NegShort, (true, true) => FlagCoordKind::PosShort, (false, false) => FlagCoordKind::Long, _ => FlagCoordKind::Same, };
let y_kind = match (y_short_vec, y_same_or_pos) {
(true, false) => FlagCoordKind::NegShort, (true, true) => FlagCoordKind::PosShort, (false, false) => FlagCoordKind::Long, _ => FlagCoordKind::Same, };
Self {
repeats,
on_curve,
x_kind,
y_kind,
}
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct Point {
pub x: i16,
pub y: i16,
pub on_curve: bool,
}
#[derive(Debug, Clone)]
pub struct Contour {
pub points: Vec<Point>,
}