read_fonts/generated/
generated_name.rs

1// THIS FILE IS AUTOGENERATED.
2// Any changes to this file will be overwritten.
3// For more information about how codegen works, see font-codegen/README.md
4
5#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8/// [Naming table version 1](https://docs.microsoft.com/en-us/typography/opentype/spec/name#naming-table-version-1)
9#[derive(Debug, Clone, Copy)]
10#[doc(hidden)]
11pub struct NameMarker {
12    name_record_byte_len: usize,
13    lang_tag_count_byte_start: Option<usize>,
14    lang_tag_record_byte_start: Option<usize>,
15    lang_tag_record_byte_len: Option<usize>,
16}
17
18impl NameMarker {
19    pub fn version_byte_range(&self) -> Range<usize> {
20        let start = 0;
21        start..start + u16::RAW_BYTE_LEN
22    }
23
24    pub fn count_byte_range(&self) -> Range<usize> {
25        let start = self.version_byte_range().end;
26        start..start + u16::RAW_BYTE_LEN
27    }
28
29    pub fn storage_offset_byte_range(&self) -> Range<usize> {
30        let start = self.count_byte_range().end;
31        start..start + u16::RAW_BYTE_LEN
32    }
33
34    pub fn name_record_byte_range(&self) -> Range<usize> {
35        let start = self.storage_offset_byte_range().end;
36        start..start + self.name_record_byte_len
37    }
38
39    pub fn lang_tag_count_byte_range(&self) -> Option<Range<usize>> {
40        let start = self.lang_tag_count_byte_start?;
41        Some(start..start + u16::RAW_BYTE_LEN)
42    }
43
44    pub fn lang_tag_record_byte_range(&self) -> Option<Range<usize>> {
45        let start = self.lang_tag_record_byte_start?;
46        Some(start..start + self.lang_tag_record_byte_len?)
47    }
48}
49
50impl MinByteRange for NameMarker {
51    fn min_byte_range(&self) -> Range<usize> {
52        0..self.name_record_byte_range().end
53    }
54}
55
56impl TopLevelTable for Name<'_> {
57    /// `name`
58    const TAG: Tag = Tag::new(b"name");
59}
60
61impl<'a> FontRead<'a> for Name<'a> {
62    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
63        let mut cursor = data.cursor();
64        let version: u16 = cursor.read()?;
65        let count: u16 = cursor.read()?;
66        cursor.advance::<u16>();
67        let name_record_byte_len = (count as usize)
68            .checked_mul(NameRecord::RAW_BYTE_LEN)
69            .ok_or(ReadError::OutOfBounds)?;
70        cursor.advance_by(name_record_byte_len);
71        let lang_tag_count_byte_start = version
72            .compatible(1u16)
73            .then(|| cursor.position())
74            .transpose()?;
75        let lang_tag_count = version
76            .compatible(1u16)
77            .then(|| cursor.read::<u16>())
78            .transpose()?
79            .unwrap_or_default();
80        let lang_tag_record_byte_start = version
81            .compatible(1u16)
82            .then(|| cursor.position())
83            .transpose()?;
84        let lang_tag_record_byte_len = version.compatible(1u16).then_some(
85            (lang_tag_count as usize)
86                .checked_mul(LangTagRecord::RAW_BYTE_LEN)
87                .ok_or(ReadError::OutOfBounds)?,
88        );
89        if let Some(value) = lang_tag_record_byte_len {
90            cursor.advance_by(value);
91        }
92        cursor.finish(NameMarker {
93            name_record_byte_len,
94            lang_tag_count_byte_start,
95            lang_tag_record_byte_start,
96            lang_tag_record_byte_len,
97        })
98    }
99}
100
101/// [Naming table version 1](https://docs.microsoft.com/en-us/typography/opentype/spec/name#naming-table-version-1)
102pub type Name<'a> = TableRef<'a, NameMarker>;
103
104#[allow(clippy::needless_lifetimes)]
105impl<'a> Name<'a> {
106    /// Table version number (0 or 1)
107    pub fn version(&self) -> u16 {
108        let range = self.shape.version_byte_range();
109        self.data.read_at(range.start).unwrap()
110    }
111
112    /// Number of name records.
113    pub fn count(&self) -> u16 {
114        let range = self.shape.count_byte_range();
115        self.data.read_at(range.start).unwrap()
116    }
117
118    /// Offset to start of string storage (from start of table).
119    pub fn storage_offset(&self) -> u16 {
120        let range = self.shape.storage_offset_byte_range();
121        self.data.read_at(range.start).unwrap()
122    }
123
124    /// The name records where count is the number of records.
125    pub fn name_record(&self) -> &'a [NameRecord] {
126        let range = self.shape.name_record_byte_range();
127        self.data.read_array(range).unwrap()
128    }
129
130    /// Number of language-tag records.
131    pub fn lang_tag_count(&self) -> Option<u16> {
132        let range = self.shape.lang_tag_count_byte_range()?;
133        Some(self.data.read_at(range.start).unwrap())
134    }
135
136    /// The language-tag records where langTagCount is the number of records.
137    pub fn lang_tag_record(&self) -> Option<&'a [LangTagRecord]> {
138        let range = self.shape.lang_tag_record_byte_range()?;
139        Some(self.data.read_array(range).unwrap())
140    }
141}
142
143#[cfg(feature = "experimental_traverse")]
144impl<'a> SomeTable<'a> for Name<'a> {
145    fn type_name(&self) -> &str {
146        "Name"
147    }
148    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
149        let version = self.version();
150        match idx {
151            0usize => Some(Field::new("version", self.version())),
152            1usize => Some(Field::new("count", self.count())),
153            2usize => Some(Field::new("storage_offset", self.storage_offset())),
154            3usize => Some(Field::new(
155                "name_record",
156                traversal::FieldType::array_of_records(
157                    stringify!(NameRecord),
158                    self.name_record(),
159                    self.string_data(),
160                ),
161            )),
162            4usize if version.compatible(1u16) => {
163                Some(Field::new("lang_tag_count", self.lang_tag_count().unwrap()))
164            }
165            5usize if version.compatible(1u16) => Some(Field::new(
166                "lang_tag_record",
167                traversal::FieldType::array_of_records(
168                    stringify!(LangTagRecord),
169                    self.lang_tag_record().unwrap(),
170                    self.string_data(),
171                ),
172            )),
173            _ => None,
174        }
175    }
176}
177
178#[cfg(feature = "experimental_traverse")]
179#[allow(clippy::needless_lifetimes)]
180impl<'a> std::fmt::Debug for Name<'a> {
181    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182        (self as &dyn SomeTable<'a>).fmt(f)
183    }
184}
185
186/// Part of [Name]
187#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
188#[repr(C)]
189#[repr(packed)]
190pub struct LangTagRecord {
191    /// Language-tag string length (in bytes)
192    pub length: BigEndian<u16>,
193    /// Language-tag string offset from start of storage area (in
194    /// bytes).
195    pub lang_tag_offset: BigEndian<Offset16>,
196}
197
198impl LangTagRecord {
199    /// Language-tag string length (in bytes)
200    pub fn length(&self) -> u16 {
201        self.length.get()
202    }
203
204    /// Language-tag string offset from start of storage area (in
205    /// bytes).
206    pub fn lang_tag_offset(&self) -> Offset16 {
207        self.lang_tag_offset.get()
208    }
209}
210
211impl FixedSize for LangTagRecord {
212    const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
213}
214
215#[cfg(feature = "experimental_traverse")]
216impl<'a> SomeRecord<'a> for LangTagRecord {
217    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
218        RecordResolver {
219            name: "LangTagRecord",
220            get_field: Box::new(move |idx, _data| match idx {
221                0usize => Some(Field::new("length", self.length())),
222                1usize => Some(Field::new("lang_tag_offset", self.traverse_lang_tag(_data))),
223                _ => None,
224            }),
225            data,
226        }
227    }
228}
229
230///[Name Records](https://docs.microsoft.com/en-us/typography/opentype/spec/name#name-records)
231#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
232#[repr(C)]
233#[repr(packed)]
234pub struct NameRecord {
235    /// Platform ID.
236    pub platform_id: BigEndian<u16>,
237    /// Platform-specific encoding ID.
238    pub encoding_id: BigEndian<u16>,
239    /// Language ID.
240    pub language_id: BigEndian<u16>,
241    /// Name ID.
242    pub name_id: BigEndian<NameId>,
243    /// String length (in bytes).
244    pub length: BigEndian<u16>,
245    /// String offset from start of storage area (in bytes).
246    pub string_offset: BigEndian<Offset16>,
247}
248
249impl NameRecord {
250    /// Platform ID.
251    pub fn platform_id(&self) -> u16 {
252        self.platform_id.get()
253    }
254
255    /// Platform-specific encoding ID.
256    pub fn encoding_id(&self) -> u16 {
257        self.encoding_id.get()
258    }
259
260    /// Language ID.
261    pub fn language_id(&self) -> u16 {
262        self.language_id.get()
263    }
264
265    /// Name ID.
266    pub fn name_id(&self) -> NameId {
267        self.name_id.get()
268    }
269
270    /// String length (in bytes).
271    pub fn length(&self) -> u16 {
272        self.length.get()
273    }
274
275    /// String offset from start of storage area (in bytes).
276    pub fn string_offset(&self) -> Offset16 {
277        self.string_offset.get()
278    }
279}
280
281impl FixedSize for NameRecord {
282    const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN
283        + u16::RAW_BYTE_LEN
284        + u16::RAW_BYTE_LEN
285        + NameId::RAW_BYTE_LEN
286        + u16::RAW_BYTE_LEN
287        + Offset16::RAW_BYTE_LEN;
288}
289
290#[cfg(feature = "experimental_traverse")]
291impl<'a> SomeRecord<'a> for NameRecord {
292    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
293        RecordResolver {
294            name: "NameRecord",
295            get_field: Box::new(move |idx, _data| match idx {
296                0usize => Some(Field::new("platform_id", self.platform_id())),
297                1usize => Some(Field::new("encoding_id", self.encoding_id())),
298                2usize => Some(Field::new("language_id", self.language_id())),
299                3usize => Some(Field::new("name_id", self.name_id())),
300                4usize => Some(Field::new("length", self.length())),
301                5usize => Some(Field::new("string_offset", self.traverse_string(_data))),
302                _ => None,
303            }),
304            data,
305        }
306    }
307}