ttf_parser/tables/
loca.rs
1use core::num::NonZeroU16;
4use core::ops::Range;
5
6use crate::{GlyphId, IndexToLocationFormat};
7use crate::parser::{Stream, LazyArray16, NumFrom};
8
9#[derive(Clone, Copy)]
10pub(crate) enum Table<'a> {
11 Short(LazyArray16<'a, u16>),
12 Long(LazyArray16<'a, u32>),
13}
14
15impl<'a> Table<'a> {
16 pub fn parse(
17 data: &'a [u8],
18 number_of_glyphs: NonZeroU16,
19 format: IndexToLocationFormat,
20 ) -> Option<Self> {
21 let total = if number_of_glyphs.get() == core::u16::MAX {
25 number_of_glyphs.get()
26 } else {
27 number_of_glyphs.get() + 1
28 };
29
30 let mut s = Stream::new(data);
31 match format {
32 IndexToLocationFormat::Short => {
33 Some(Table::Short(s.read_array16::<u16>(total)?))
34 }
35 IndexToLocationFormat::Long => {
36 Some(Table::Long(s.read_array16::<u32>(total)?))
37 }
38 }
39 }
40
41 #[inline]
42 fn len(&self) -> u16 {
43 match self {
44 Table::Short(ref array) => array.len(),
45 Table::Long(ref array) => array.len(),
46 }
47 }
48
49 #[inline]
50 pub fn glyph_range(&self, glyph_id: GlyphId) -> Option<Range<usize>> {
51 let glyph_id = glyph_id.0;
52 if glyph_id == core::u16::MAX {
53 return None;
54 }
55
56 if glyph_id + 1 >= self.len() {
58 return None;
59 }
60
61 let range = match self {
62 Table::Short(ref array) => {
63 usize::from(array.get(glyph_id)?) * 2 .. usize::from(array.get(glyph_id + 1)?) * 2
65 }
66 Table::Long(ref array) => {
67 usize::num_from(array.get(glyph_id)?) .. usize::num_from(array.get(glyph_id + 1)?)
68 }
69 };
70
71 if range.start >= range.end {
72 None
75 } else {
76 Some(range)
77 }
78 }
79}