mp4_atom/moov/trak/mdia/minf/stbl/stsd/
ftab.rs1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq, Default)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct FontEntry {
11 pub font_id: u16,
12 pub font: String,
13}
14
15#[derive(Debug, Clone, PartialEq, Eq, Default)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17pub struct Ftab {
18 pub font_entries: Vec<FontEntry>,
19}
20
21impl Atom for Ftab {
22 const KIND: FourCC = FourCC::new(b"ftab");
23
24 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
25 let entry_count = u16::decode(buf)?;
26 let mut font_entries = Vec::with_capacity(std::cmp::min(8, entry_count as usize));
27 for _ in 0..entry_count {
28 let font_id = u16::decode(buf)?;
29 let font_name_length = u8::decode(buf)?;
30 let font_bytes = Vec::decode_exact(buf, font_name_length as usize)?;
31 let font = if font_bytes.len() >= 4 && font_bytes[0] == 0xFF && font_bytes[1] == 0xFE {
32 if font_name_length % 2 != 0 {
34 return Err(Error::InvalidSize);
35 }
36 let utf_16_len: usize = ((font_name_length - 2) / 2) as usize;
37 let mut utf_16 = Vec::with_capacity(utf_16_len);
38 for i in 1..=utf_16_len {
39 let bytes = [font_bytes[i * 2], font_bytes[i * 2 + 1]];
40 utf_16.push(u16::from_le_bytes(bytes));
41 }
42 String::from_utf16(&utf_16).map_err(|_| {
43 Error::InvalidString("Failed to parse UTF-16 LE font id in ftab".into())
44 })?
45 } else if font_bytes.len() >= 4 && font_bytes[0] == 0xFE && font_bytes[1] == 0xFF {
46 if font_name_length % 2 != 0 {
48 return Err(Error::InvalidSize);
49 }
50 let utf_16_len: usize = ((font_name_length - 2) / 2) as usize;
51 let mut utf_16 = Vec::with_capacity(utf_16_len);
52 for i in 1..=utf_16_len {
53 let bytes = [font_bytes[i * 2], font_bytes[i * 2 + 1]];
54 utf_16.push(u16::from_be_bytes(bytes));
55 }
56 String::from_utf16(&utf_16).map_err(|_| {
57 Error::InvalidString("Failed to parse UTF-16 BE font id in ftab".into())
58 })?
59 } else {
60 String::from_utf8(font_bytes)
61 .map_err(|_| Error::InvalidString("Failed to parse font id in ftab".into()))?
62 };
63 let font_entry = FontEntry { font_id, font };
64 font_entries.push(font_entry);
65 }
66 Ok(Ftab { font_entries })
67 }
68
69 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
70 let entry_count: u16 = self
71 .font_entries
72 .len()
73 .try_into()
74 .map_err(|_| Error::TooLarge(Self::KIND))?;
75 entry_count.encode(buf)?;
76 for font_entry in &self.font_entries {
77 font_entry.font_id.encode(buf)?;
78 let font_bytes = font_entry.font.as_bytes();
80 let font_name_length: u8 = font_bytes
81 .len()
82 .try_into()
83 .map_err(|_| Error::TooLarge(Self::KIND))?;
84 font_name_length.encode(buf)?;
85 font_bytes.encode(buf)?;
86 }
87
88 Ok(())
89 }
90}