Skip to main content

ttf_view/tables/glyf/
mod.rs

1use crate::{
2    tables::{Table, TableDirectory, TableError, cmap::GlyphId, loca::Loca},
3    types::{Tag, int16, tags},
4};
5use std::{ops::Range, ptr::NonNull};
6
7mod composite;
8mod simple;
9
10pub use composite::*;
11pub use simple::*;
12
13impl<'a> Table<'a> for Glyf<'a> {
14    const TAG: Tag = tags::glyf;
15    fn new_in(dir: &'a TableDirectory) -> Result<Self, TableError> {
16        let rec = dir.table_record(Self::TAG).ok_or(TableError::NotFound)?;
17
18        let loca = dir.loca().map_err(|_| TableError::Dependency(tags::loca))?;
19
20        let req_len = loca.iter_raw().last().ok_or(TableError::Malformed(&"no glyphs"))?;
21        if rec.length.get() < req_len {
22            return Err(TableError::InvalidLen);
23        }
24
25        let ptr = NonNull::from_ref(rec.raw_as::<()>().unwrap()).cast::<u8>();
26        Ok(Self { ptr, loca })
27    }
28}
29
30#[derive(Copy)]
31#[derive_const(Clone)]
32pub struct Glyf<'a> {
33    ptr: NonNull<u8>,
34    loca: Loca<'a>,
35}
36
37impl<'a> Glyf<'a> {
38    pub fn glyph_as_bytes(&self, glyph_id: GlyphId) -> Option<&'a [u8]> {
39        let Range { start, end } = self.loca.range(glyph_id)?;
40        if start == end {
41            return Some(&[]);
42        }
43        let ptr = self.ptr.as_ptr().cast_const();
44        Some(unsafe { std::slice::from_raw_parts(ptr.byte_add(start as _), (end - start) as _) })
45    }
46}
47
48#[repr(C)]
49pub struct Glyph {
50    _exhaustive_but_dont_instantiate: (),
51    pub number_of_contours: int16,
52    pub x_min: int16,
53    pub y_min: int16,
54    pub x_max: int16,
55    pub y_max: int16,
56    // : [more info as SimpleGlyph or CompositeGlyph],
57}
58
59impl Glyph {
60    pub const fn is_simple(&self) -> bool {
61        self.number_of_contours.get() >= 0
62    }
63    pub const fn is_composite(&self) -> bool {
64        !self.is_simple()
65    }
66
67    pub const fn as_simple(&self) -> Option<&SimpleGlyph> {
68        if self.is_simple() {
69            Some(unsafe { std::mem::transmute::<&Self, &SimpleGlyph>(self) })
70        } else {
71            None
72        }
73    }
74    pub const fn as_composite(&self) -> Option<&CompositeGlyph> {
75        if self.is_composite() {
76            Some(unsafe { std::mem::transmute::<&Self, &CompositeGlyph>(self) })
77        } else {
78            None
79        }
80    }
81}