Skip to main content

ttf_rs/
stream.rs

1use std::io;
2
3/// Helper struct for reading TTF data with proper endianness handling
4pub struct FontReader {
5    data: Vec<u8>,
6    pos: usize,
7}
8
9impl FontReader {
10    pub fn new(data: Vec<u8>) -> Self {
11        Self { data, pos: 0 }
12    }
13
14    pub fn from_slice(slice: &[u8]) -> Self {
15        Self {
16            data: slice.to_vec(),
17            pos: 0,
18        }
19    }
20
21    pub fn position(&self) -> usize {
22        self.pos
23    }
24
25    pub fn set_position(&mut self, pos: usize) -> Result<(), io::Error> {
26        if pos > self.data.len() {
27            return Err(io::Error::new(
28                io::ErrorKind::UnexpectedEof,
29                "Position out of bounds",
30            ));
31        }
32        self.pos = pos;
33        Ok(())
34    }
35
36    pub fn skip(&mut self, bytes: usize) -> Result<(), io::Error> {
37        self.set_position(self.pos + bytes)
38    }
39
40    pub fn remaining(&self) -> usize {
41        self.data.len().saturating_sub(self.pos)
42    }
43
44    pub fn is_empty(&self) -> bool {
45        self.pos >= self.data.len()
46    }
47
48    pub fn into_inner(self) -> Vec<u8> {
49        self.data
50    }
51
52    pub fn read_u8(&mut self) -> Result<u8, io::Error> {
53        if self.pos + 1 > self.data.len() {
54            return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "Not enough bytes"));
55        }
56        let val = self.data[self.pos];
57        self.pos += 1;
58        Ok(val)
59    }
60
61    pub fn read_i8(&mut self) -> Result<i8, io::Error> {
62        self.read_u8().map(|b| b as i8)
63    }
64
65    pub fn read_u16(&mut self) -> Result<u16, io::Error> {
66        if self.pos + 2 > self.data.len() {
67            return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "Not enough bytes"));
68        }
69        let val = u16::from_be_bytes([self.data[self.pos], self.data[self.pos + 1]]);
70        self.pos += 2;
71        Ok(val)
72    }
73
74    pub fn read_i16(&mut self) -> Result<i16, io::Error> {
75        self.read_u16().map(|b| b as i16)
76    }
77
78    pub fn read_u24(&mut self) -> Result<u32, io::Error> {
79        if self.pos + 3 > self.data.len() {
80            return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "Not enough bytes"));
81        }
82        let val = u32::from_be_bytes([
83            0,
84            self.data[self.pos],
85            self.data[self.pos + 1],
86            self.data[self.pos + 2],
87        ]);
88        self.pos += 3;
89        Ok(val)
90    }
91
92    pub fn read_u32(&mut self) -> Result<u32, io::Error> {
93        if self.pos + 4 > self.data.len() {
94            return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "Not enough bytes"));
95        }
96        let val = u32::from_be_bytes([
97            self.data[self.pos],
98            self.data[self.pos + 1],
99            self.data[self.pos + 2],
100            self.data[self.pos + 3],
101        ]);
102        self.pos += 4;
103        Ok(val)
104    }
105
106    pub fn read_i32(&mut self) -> Result<i32, io::Error> {
107        self.read_u32().map(|b| b as i32)
108    }
109
110    pub fn read_u64(&mut self) -> Result<u64, io::Error> {
111        if self.pos + 8 > self.data.len() {
112            return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "Not enough bytes"));
113        }
114        let val = u64::from_be_bytes([
115            self.data[self.pos],
116            self.data[self.pos + 1],
117            self.data[self.pos + 2],
118            self.data[self.pos + 3],
119            self.data[self.pos + 4],
120            self.data[self.pos + 5],
121            self.data[self.pos + 6],
122            self.data[self.pos + 7],
123        ]);
124        self.pos += 8;
125        Ok(val)
126    }
127
128    pub fn read_i64(&mut self) -> Result<i64, io::Error> {
129        self.read_u64().map(|b| b as i64)
130    }
131
132    pub fn read_fixed(&mut self) -> Result<f32, io::Error> {
133        self.read_i32().map(|i| i as f32 / 65536.0)
134    }
135
136    pub fn read_f2dot14(&mut self) -> Result<f32, io::Error> {
137        self.read_i16().map(|i| i as f32 / 16384.0)
138    }
139
140    pub fn read_long_datetime(&mut self) -> Result<u64, io::Error> {
141        // Long datetime is a 64-bit integer representing seconds since 1904
142        self.read_u64()
143    }
144
145    pub fn read_tag(&mut self) -> Result<[u8; 4], io::Error> {
146        if self.pos + 4 > self.data.len() {
147            return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "Not enough bytes"));
148        }
149        let mut tag = [0u8; 4];
150        tag.copy_from_slice(&self.data[self.pos..self.pos + 4]);
151        self.pos += 4;
152        Ok(tag)
153    }
154
155    pub fn read_bytes(&mut self, len: usize) -> Result<Vec<u8>, io::Error> {
156        if self.pos + len > self.data.len() {
157            return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "Not enough bytes"));
158        }
159        let bytes = self.data[self.pos..self.pos + len].to_vec();
160        self.pos += len;
161        Ok(bytes)
162    }
163
164    pub fn read_string(&mut self, len: usize) -> Result<String, io::Error> {
165        let bytes = self.read_bytes(len)?;
166        String::from_utf8(bytes)
167            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))
168    }
169}
170
171/// Helper struct for writing TTF data with proper endianness handling
172pub struct FontWriter {
173    data: Vec<u8>,
174}
175
176impl FontWriter {
177    pub fn new() -> Self {
178        Self { data: Vec::new() }
179    }
180
181    pub fn with_capacity(capacity: usize) -> Self {
182        Self {
183            data: Vec::with_capacity(capacity),
184        }
185    }
186
187    pub fn position(&self) -> usize {
188        self.data.len()
189    }
190
191    pub fn into_inner(self) -> Vec<u8> {
192        self.data
193    }
194
195    pub fn as_slice(&self) -> &[u8] {
196        &self.data
197    }
198
199    pub fn write_u8(&mut self, val: u8) {
200        self.data.push(val);
201    }
202
203    pub fn write_i8(&mut self, val: i8) {
204        self.data.push(val as u8);
205    }
206
207    pub fn write_u16(&mut self, val: u16) {
208        self.data.extend_from_slice(&val.to_be_bytes());
209    }
210
211    pub fn write_i16(&mut self, val: i16) {
212        self.data.extend_from_slice(&val.to_be_bytes());
213    }
214
215    pub fn write_u24(&mut self, val: u32) {
216        self.data.extend_from_slice(&val.to_be_bytes()[1..]);
217    }
218
219    pub fn write_u32(&mut self, val: u32) {
220        self.data.extend_from_slice(&val.to_be_bytes());
221    }
222
223    pub fn write_i32(&mut self, val: i32) {
224        self.data.extend_from_slice(&val.to_be_bytes());
225    }
226
227    pub fn write_u64(&mut self, val: u64) {
228        self.data.extend_from_slice(&val.to_be_bytes());
229    }
230
231    pub fn write_i64(&mut self, val: i64) {
232        self.data.extend_from_slice(&val.to_be_bytes());
233    }
234
235    pub fn write_fixed(&mut self, val: f32) {
236        let fixed = (val * 65536.0) as i32;
237        self.write_i32(fixed);
238    }
239
240    pub fn write_f2dot14(&mut self, val: f32) {
241        let f2dot14 = (val * 16384.0) as i16;
242        self.write_i16(f2dot14);
243    }
244
245    pub fn write_long_datetime(&mut self, val: u64) {
246        self.write_u64(val);
247    }
248
249    pub fn write_tag(&mut self, tag: &[u8; 4]) {
250        self.data.extend_from_slice(tag);
251    }
252
253    pub fn write_bytes(&mut self, bytes: &[u8]) {
254        self.data.extend_from_slice(bytes);
255    }
256
257    pub fn write_padding(&mut self, align: usize) {
258        let pos = self.data.len();
259        let padding = (align - (pos % align)) % align;
260        self.data.extend(vec![0u8; padding]);
261    }
262
263    pub fn pad_to(&mut self, target_len: usize) {
264        while self.data.len() < target_len {
265            self.data.push(0);
266        }
267    }
268}
269
270impl Default for FontWriter {
271    fn default() -> Self {
272        Self::new()
273    }
274}
275
276/// Calculate TTF checksum
277pub fn calculate_checksum(data: &[u8]) -> u32 {
278    let mut sum: u32 = 0;
279    let mut len = data.len();
280
281    // Handle data that's not a multiple of 4 bytes
282    if len % 4 != 0 {
283        len += 4 - (len % 4);
284    }
285
286    for i in (0..len).step_by(4) {
287        let mut val: u32 = 0;
288        for j in 0..4 {
289            if i + j < data.len() {
290                val = (val << 8) | data[i + j] as u32;
291            } else {
292                val <<= 8;
293            }
294        }
295        sum = sum.wrapping_add(val);
296    }
297
298    sum
299}