1use std::collections::BTreeSet;
2
3#[cfg(feature = "tables")]
4use crate::error::{Error, PackingError};
5#[cfg(feature = "tables")]
6use crate::graph::Graph;
7use crate::object::{ObjectId, ObjectStore};
8use crate::offsets::OffsetLen;
9use crate::table_type::TableType;
10#[cfg(feature = "tables")]
11use crate::validate::Validate;
12#[cfg(feature = "tables")]
13use font_types::{FixedSize, Scalar};
14#[cfg(feature = "tables")]
15use read_fonts::{FontData, FontRead, FontReadWithArgs, ReadError};
16
17pub trait FontWrite {
22 fn write_into(&self, writer: &mut TableWriter);
24
25 fn table_type(&self) -> TableType {
30 TableType::Unknown
31 }
32}
33
34#[derive(Debug)]
38pub struct TableWriter {
39 tables: ObjectStore,
41 stack: Vec<TableData>,
45 offset_adjustment: u32,
53}
54
55#[cfg(feature = "tables")]
60pub fn dump_table<T: FontWrite + Validate>(table: &T) -> Result<Vec<u8>, Error> {
61 log::trace!("writing table '{}'", table.table_type());
62 table.validate()?;
63 let mut graph = TableWriter::make_graph(table);
64
65 if !graph.pack_objects() {
66 return Err(Error::PackingFailed(PackingError {
67 graph: graph.into(),
68 }));
69 }
70 Ok(graph.serialize())
71}
72
73impl TableWriter {
74 #[cfg(feature = "tables")]
76 pub(crate) fn make_graph(root: &impl FontWrite) -> Graph {
77 let mut writer = TableWriter::default();
78 let root_id = writer.add_table(root);
79 Graph::from_obj_store(writer.tables, root_id)
80 }
81
82 fn add_table(&mut self, table: &dyn FontWrite) -> ObjectId {
83 self.stack.push(TableData::default());
84 table.write_into(self);
85 let mut table_data = self.stack.pop().unwrap();
86 table_data.type_ = table.table_type();
87 self.tables.add(table_data)
88 }
89
90 #[cfg(feature = "tables")]
92 pub(crate) fn adjust_offsets(&mut self, adjustment: u32, f: impl FnOnce(&mut TableWriter)) {
93 self.offset_adjustment = adjustment;
94 f(self);
95 self.offset_adjustment = 0;
96 }
97
98 #[inline]
102 pub fn write_slice(&mut self, bytes: &[u8]) {
103 self.stack.last_mut().unwrap().write_bytes(bytes)
104 }
105
106 pub fn write_offset(&mut self, obj: &dyn FontWrite, width: usize) {
117 let obj_id = self.add_table(obj);
118 let data = self.stack.last_mut().unwrap();
119 data.add_offset(obj_id, width, self.offset_adjustment);
120 }
121
122 #[cfg(feature = "tables")]
127 pub fn pad_to_2byte_aligned(&mut self) {
128 if self.stack.last().unwrap().bytes.len() % 2 != 0 {
129 self.write_slice(&[0]);
130 }
131 }
132
133 pub(crate) fn into_data(mut self) -> TableData {
135 assert_eq!(self.stack.len(), 1);
136 let result = self.stack.pop().unwrap();
137 assert!(result.offsets.is_empty());
138 result
139 }
140
141 #[cfg(feature = "tables")]
146 pub(crate) fn current_data(&self) -> &TableData {
147 self.stack.last().unwrap() }
149}
150
151impl Default for TableWriter {
152 fn default() -> Self {
153 TableWriter {
154 tables: ObjectStore::default(),
155 stack: vec![TableData::default()],
156 offset_adjustment: 0,
157 }
158 }
159}
160
161#[derive(Debug, Default, Clone)] pub(crate) struct TableData {
164 pub(crate) type_: TableType,
165 pub(crate) bytes: Vec<u8>,
166 pub(crate) offsets: Vec<OffsetRecord>,
167}
168
169impl std::hash::Hash for TableData {
170 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
171 self.bytes.hash(state);
172 self.offsets.hash(state);
173 }
174}
175
176impl PartialEq for TableData {
177 fn eq(&self, other: &Self) -> bool {
178 self.bytes == other.bytes && self.offsets == other.offsets
179 }
180}
181
182impl Eq for TableData {}
183
184#[derive(Debug, Clone, Hash, PartialEq, Eq)]
186pub(crate) struct OffsetRecord {
187 pub(crate) pos: u32,
189 pub(crate) len: OffsetLen,
191 pub(crate) object: ObjectId,
193 pub(crate) adjustment: u32,
199}
200
201impl TableData {
202 #[cfg(feature = "tables")]
203 pub(crate) fn new(type_: TableType) -> Self {
204 TableData {
205 type_,
206 ..Default::default()
207 }
208 }
209
210 pub(crate) fn add_offset(&mut self, object: ObjectId, width: usize, adjustment: u32) {
212 const PLACEHOLDER_BYTES: &[u8] = &[0xff; 4];
213 self.offsets.push(OffsetRecord {
214 pos: self.bytes.len() as u32,
215 len: match width {
216 2 => OffsetLen::Offset16,
217 3 => OffsetLen::Offset24,
218 _ => OffsetLen::Offset32,
219 },
220 object,
221 adjustment,
222 });
223
224 let placeholder = PLACEHOLDER_BYTES.get(..width.min(4)).unwrap();
228 self.write_bytes(placeholder);
229 }
230
231 #[cfg(feature = "tables")]
232 pub(crate) fn write<T: Scalar>(&mut self, value: T) {
233 self.write_bytes(value.to_raw().as_ref())
234 }
235
236 #[cfg(feature = "tables")]
241 pub(crate) fn write_over<T: Scalar>(&mut self, value: T, pos: usize) {
242 let raw = value.to_raw();
243 let len = raw.as_ref().len();
244 self.bytes[pos..pos + len].copy_from_slice(raw.as_ref());
245 }
246
247 fn write_bytes(&mut self, bytes: &[u8]) {
248 self.bytes.extend_from_slice(bytes)
249 }
250
251 #[cfg(feature = "tables")]
256 pub(crate) fn reparse<'a, T: FontRead<'a>>(&'a self) -> Result<T, ReadError> {
257 let data = FontData::new(&self.bytes);
258 T::read(data)
259 }
260
261 #[cfg(feature = "tables")]
263 pub(crate) fn reparse_with_args<'a, A, T: FontReadWithArgs<'a, Args = A>>(
264 &'a self,
265 args: &A,
266 ) -> Result<T, ReadError> {
267 let data = FontData::new(&self.bytes);
268 T::read_with_args(data, args)
269 }
270
271 #[cfg(feature = "tables")]
273 pub(crate) fn read_at<T: Scalar>(&self, pos: usize) -> Option<T> {
274 let len = T::RAW_BYTE_LEN;
275 self.bytes.get(pos..pos + len).and_then(T::read)
276 }
277
278 #[cfg(all(test, feature = "tables"))]
279 pub fn make_mock(size: usize) -> Self {
280 TableData {
281 bytes: vec![0xca; size], offsets: Vec::new(),
283 type_: TableType::MockTable,
284 }
285 }
286
287 #[cfg(all(test, feature = "tables"))]
288 pub fn add_mock_offset(&mut self, object: ObjectId, len: OffsetLen) {
289 let pos = self.offsets.iter().map(|off| off.len as u8 as u32).sum();
290 self.offsets.push(OffsetRecord {
291 pos,
292 len,
293 object,
294 adjustment: 0,
295 });
296 }
297}
298
299macro_rules! write_be_bytes {
300 ($ty:ty) => {
301 impl FontWrite for $ty {
302 #[inline]
303 fn write_into(&self, writer: &mut TableWriter) {
304 writer.write_slice(&self.to_be_bytes())
305 }
306 }
307 };
308}
309
310write_be_bytes!(u8);
312write_be_bytes!(i8);
313write_be_bytes!(u16);
314write_be_bytes!(i16);
315write_be_bytes!(u32);
316write_be_bytes!(i32);
317write_be_bytes!(i64);
318write_be_bytes!(types::Uint24);
319write_be_bytes!(types::Int24);
320write_be_bytes!(types::F2Dot14);
321write_be_bytes!(types::F4Dot12);
322write_be_bytes!(types::F6Dot10);
323write_be_bytes!(types::Fixed);
324write_be_bytes!(types::FWord);
325write_be_bytes!(types::UfWord);
326write_be_bytes!(types::LongDateTime);
327write_be_bytes!(types::Tag);
328write_be_bytes!(types::Version16Dot16);
329write_be_bytes!(types::MajorMinor);
330write_be_bytes!(types::GlyphId16);
331write_be_bytes!(types::NameId);
332
333impl<T: FontWrite> FontWrite for [T] {
334 fn write_into(&self, writer: &mut TableWriter) {
335 self.iter().for_each(|item| item.write_into(writer))
336 }
337}
338
339impl<T: FontWrite> FontWrite for BTreeSet<T> {
340 fn write_into(&self, writer: &mut TableWriter) {
341 self.iter().for_each(|item| item.write_into(writer))
342 }
343}
344
345impl<T: FontWrite> FontWrite for Vec<T> {
346 fn write_into(&self, writer: &mut TableWriter) {
347 self.iter().for_each(|item| item.write_into(writer))
348 }
349}
350
351impl<T: FontWrite> FontWrite for Option<T> {
352 fn write_into(&self, writer: &mut TableWriter) {
353 if let Some(obj) = self {
354 obj.write_into(writer)
355 }
356 }
357}