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