postscript/compact1/font_set/
mod.rs1macro_rules! get(
4 (@single $operations:expr, $operator:ident) => (
5 match $operations.get_single(crate::compact1::Operator::$operator) {
6 Some(crate::compact1::Number::Integer(value)) => value,
7 Some(_) => raise!(concat!("found a malformed operation with operator ", stringify!($operator))),
8 _ => raise!(concat!("found no operation with operator ", stringify!($operator))),
9 }
10 );
11 (@try @single $operations:expr, $operator:ident) => (
12 match $operations.get_single(crate::compact1::Operator::$operator) {
13 Some(crate::compact1::Number::Integer(value)) => Some(value),
14 Some(_) => raise!(concat!("found a malformed operation with operator ", stringify!($operator))),
15 _ => None,
16 }
17 );
18 (@double $operations:expr, $operator:ident) => (
19 match $operations.get_double(crate::compact1::Operator::$operator) {
20 Some((crate::compact1::Number::Integer(value0), crate::compact1::Number::Integer(value1))) => (value0, value1),
21 Some(_) => raise!(concat!("found a malformed operation with operator ", stringify!($operator))),
22 _ => raise!(concat!("found no operation with operator ", stringify!($operator))),
23 }
24 );
25);
26
27pub mod character_id_keyed;
28pub mod character_name_keyed;
29
30use crate::compact1::index::{CharacterStrings, Dictionaries, Names, Strings, Subroutines};
31use crate::compact1::{CharacterSet, Encoding, Header, Operations, Operator};
32use crate::Result;
33
34#[derive(Clone, Debug)]
36pub struct FontSet {
37 pub header: Header,
38 pub names: Names,
39 pub operations: Vec<Operations>,
40 pub strings: Strings,
41 pub subroutines: Subroutines,
42 pub encodings: Vec<Encoding>,
43 pub character_strings: Vec<CharacterStrings>,
44 pub character_sets: Vec<CharacterSet>,
45 pub records: Vec<Record>,
46}
47
48#[derive(Clone, Debug)]
50pub enum Record {
51 CharacterIDKeyed(character_id_keyed::Record),
52 CharacterNameKeyed(character_name_keyed::Record),
53}
54
55impl FontSet {
56 pub fn count<T: crate::tape::Read>(tape: &mut T) -> Result<usize> {
58 let position = tape.position()?;
59 let header = tape.take::<Header>()?;
60 let count: u16 = jump_take!(@unwrap tape, position, header.header_size);
61 Ok(count as usize)
62 }
63}
64
65impl crate::value::Read for FontSet {
66 fn read<T: crate::tape::Read>(tape: &mut T) -> Result<Self> {
67 let position = tape.position()?;
68 let header = tape.take::<Header>()?;
69 let names: Names = jump_take!(@unwrap tape, position, header.header_size);
70 let operations: Vec<_> = (&tape.take::<Dictionaries>()?).try_into()?;
71 let strings = tape.take::<Strings>()?;
72 let subroutines = tape.take::<Subroutines>()?;
73 let mut encodings = vec![];
74 let mut character_sets = vec![];
75 let mut character_strings: Vec<CharacterStrings> = vec![];
76 let mut records = vec![];
77 for (i, operations) in operations.iter().enumerate() {
78 character_strings.push(jump_take_given!(
79 @unwrap
80 tape,
81 position,
82 get!(@single operations, CharStrings),
83 get!(@single operations, CharStringType)
84 ));
85 character_sets.push(match get!(@single operations, CharSet) {
86 0 => CharacterSet::ISOAdobe,
87 1 => CharacterSet::Expert,
88 2 => CharacterSet::ExpertSubset,
89 offset => jump_take_given!(
90 @unwrap
91 tape,
92 position,
93 offset,
94 character_strings[i].count as usize
95 ),
96 });
97 encodings.push(match get!(@single operations, Encoding) {
98 0 => Encoding::Standard,
99 1 => Encoding::Expert,
100 offset => jump_take!(@unwrap tape, position, offset),
101 });
102 records.push(tape.take_given((position, operations, &character_strings[i]))?);
103 }
104 Ok(Self {
105 header,
106 names,
107 operations,
108 strings,
109 subroutines,
110 encodings,
111 character_strings,
112 character_sets,
113 records,
114 })
115 }
116}
117
118impl<'l> crate::walue::Read<'l> for Record {
119 type Parameter = (u64, &'l Operations, &'l CharacterStrings);
120
121 fn read<T: crate::tape::Read>(
122 tape: &mut T,
123 (position, operations, character_strings): Self::Parameter,
124 ) -> Result<Self> {
125 if operations.contains_key(&Operator::ROS) {
126 Ok(Record::CharacterIDKeyed(tape.take_given((
127 position,
128 operations,
129 character_strings,
130 ))?))
131 } else {
132 Ok(Record::CharacterNameKeyed(
133 tape.take_given((position, operations))?,
134 ))
135 }
136 }
137}