use crate::number::q32;
use crate::{Result, Tape, Value};
#[derive(Clone, Debug)]
pub enum PostScript {
Version1(PostScript1),
Version2(PostScript2),
Version3(PostScript3),
}
table! {
#[doc = "PostScript information of version 1."]
#[derive(Copy)]
pub PostScript1 {
version (q32), italic_angle (q32), underline_position (i16), underline_thickness (i16), is_fixed_pitch (u32), min_memory_type42 (u32), max_memory_type42 (u32), min_memory_type1 (u32), max_memory_type1 (u32), }
}
table! {
#[doc = "PostScript information of version 2."]
pub PostScript2 {
version (q32), italic_angle (q32), underline_position (i16), underline_thickness (i16), is_fixed_pitch (u32), min_memory_type42 (u32), max_memory_type42 (u32), min_memory_type1 (u32), max_memory_type1 (u32), glyph_count (u16), glyph_name_indices (Vec<u16>) |this, tape| { tape.take_given(this.glyph_count as usize)
},
glyph_names (Vec<String>) |this, tape| { read_pascal_strings(tape, &this.glyph_name_indices)
},
}
}
pub type PostScript3 = PostScript1;
impl Value for PostScript {
fn read<T: Tape>(tape: &mut T) -> Result<Self> {
Ok(match tape.peek::<q32>()? {
q32(0x00010000) => PostScript::Version1(tape.take()?),
q32(0x00020000) => PostScript::Version2(tape.take()?),
q32(0x00030000) => PostScript::Version3(tape.take()?),
_ => raise!("found an unknown version of the PostScript information"),
})
}
}
fn read_pascal_strings<T: Tape>(tape: &mut T, indices: &[u16]) -> Result<Vec<String>> {
let count = indices.iter().fold(
0,
|n, &i| if (258..=32767).contains(&i) { n + 1 } else { n },
);
let mut names = Vec::with_capacity(count);
for _ in 0..count {
let size = tape.take::<u8>()? as usize;
match String::from_utf8(tape.take_bytes(size)?) {
Ok(name) => names.push(name),
_ => names.push("<malformed>".into()),
}
}
Ok(names)
}