postscript/compact1/
operation.rs

1//! The operations.
2
3use std::collections::HashMap;
4
5use crate::compact1::number::Number;
6use crate::Result;
7
8/// An operand.
9pub type Operand = Number;
10
11/// A collection of operations.
12#[derive(Clone, Debug, Default)]
13pub struct Operations(pub HashMap<Operator, Vec<Operand>>);
14
15struct Operation(Operator, Vec<Operand>);
16
17impl Operations {
18    /// Return the operands of an operation.
19    #[inline]
20    pub fn get(&self, operator: Operator) -> Option<&[Operand]> {
21        match self.0.get(&operator) {
22            Some(operands) => Some(operands),
23            _ => operator.default(),
24        }
25    }
26
27    #[doc(hidden)]
28    #[inline]
29    pub fn get_single(&self, operator: Operator) -> Option<Operand> {
30        self.get(operator).and_then(|operands| {
31            if !operands.is_empty() {
32                Some(operands[0])
33            } else {
34                None
35            }
36        })
37    }
38
39    #[doc(hidden)]
40    #[inline]
41    pub fn get_double(&self, operator: Operator) -> Option<(Operand, Operand)> {
42        self.get(operator).and_then(|operands| {
43            if operands.len() > 1 {
44                Some((operands[0], operands[1]))
45            } else {
46                None
47            }
48        })
49    }
50}
51
52impl crate::value::Read for Operations {
53    fn read<T: crate::tape::Read>(tape: &mut T) -> Result<Self> {
54        use std::io::ErrorKind;
55
56        let mut operations = HashMap::new();
57        loop {
58            match tape.take() {
59                Ok(Operation(operator, operands)) => {
60                    operations.insert(operator, operands);
61                }
62                Err(error) => {
63                    if error.kind() == ErrorKind::UnexpectedEof {
64                        return Ok(Operations(operations));
65                    } else {
66                        return Err(error);
67                    }
68                }
69            }
70        }
71    }
72}
73
74dereference! { Operations::0 => HashMap<Operator, Vec<Operand>> }
75
76impl crate::value::Read for Operation {
77    fn read<T: crate::tape::Read>(tape: &mut T) -> Result<Self> {
78        let mut operands = vec![];
79        loop {
80            match tape.peek::<u8>()? {
81                0x1c | 0x1d | 0x1e | 0x20..=0xfe => operands.push(tape.take()?),
82                code => {
83                    let code = if code == 0x0c {
84                        tape.take::<u16>()?
85                    } else {
86                        tape.take::<u8>()? as u16
87                    };
88                    return Ok(Self(Operator::from(code)?, operands));
89                }
90            }
91        }
92    }
93}
94
95macro_rules! default(
96    ([$($operand:expr),+ $(,)?]) => ({
97        const OPERANDS: &'static [Operand] = &[$($operand),+];
98        Some(OPERANDS)
99    });
100    ([]) => (None);
101);
102
103macro_rules! operator {
104    (pub $name:ident { $($code:pat => $variant:ident $default:tt,)+ }) => (
105        operator! { @define pub $name { $($variant,)+ } }
106        operator! { @implement pub $name { $($code => $variant $default,)+ } }
107    );
108    (@define pub $name:ident { $($variant:ident,)* }) => (
109        /// An operator.
110        #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
111        pub enum $name { $($variant,)* }
112    );
113    (@implement pub $name:ident { $($code:pat => $variant:ident $default:tt,)* }) => (impl $name {
114        #[doc(hidden)]
115        pub fn from(code: u16) -> Result<Self> {
116            use self::$name::*;
117
118            Ok(match code {
119                $($code => $variant,)+
120                code => raise!("found an unknown operator ({code})"),
121            })
122        }
123
124        /// Return the default operands.
125        pub fn default(&self) -> Option<&'static [Operand]> {
126            use self::$name::*;
127
128            match *self {
129                $($variant => default!($default),)+
130            }
131        }
132    });
133}
134
135operator! {
136    pub Operator {
137        0x00 => Version [],
138        0x01 => Notice [],
139        0x02 => FullName [],
140        0x03 => FamilyName [],
141        0x04 => Weight [],
142        0x05 => FontBBox [
143            Number::Integer(0),
144            Number::Integer(0),
145            Number::Integer(0),
146            Number::Integer(0),
147        ],
148        0x06 => BlueValues [],
149        0x07 => OtherBlues [],
150        0x08 => FamilyBlues [],
151        0x09 => FamilyOtherBlues [],
152        0x0a => StdHW [],
153        0x0b => StdVW [],
154        // 0x0c => Escape,
155        0x0d => UniqueID [],
156        0x0e => XUID [],
157        0x0f => CharSet [Number::Integer(0)],
158        0x10 => Encoding [Number::Integer(0)],
159        0x11 => CharStrings [],
160        0x12 => Private [],
161        0x13 => Subrs [],
162        0x14 => DefaultWidthX [Number::Integer(0)],
163        0x15 => NominalWidthX [Number::Integer(0)],
164        // 0x16..=0x1b => Reserved,
165        // 0x1c => ShortInt,
166        // 0x1d => LongInt,
167        // 0x1e => BCD,
168        // 0x1f => Reserved,
169        // 0x20..=0xf6 => <numbers>,
170        // 0xf7..=0xfe => <numbers>,
171        // 0xff => Reserved,
172        0x0c00 => Copyright [],
173        0x0c01 => IsFixedPitch [Number::Integer(false as i32)],
174        0x0c02 => ItalicAngle [Number::Integer(0)],
175        0x0c03 => UnderlinePosition [Number::Integer(-100)],
176        0x0c04 => UnderlineThickness [Number::Integer(50)],
177        0x0c05 => PaintType [Number::Integer(0)],
178        0x0c06 => CharStringType [Number::Integer(2)],
179        0x0c07 => FontMatrix [
180            Number::Real(0.001),
181            Number::Real(0.0),
182            Number::Real(0.0),
183            Number::Real(0.001),
184            Number::Real(0.0),
185            Number::Real(0.0),
186        ],
187        0x0c08 => StrokeWidth [Number::Integer(0)],
188        0x0c09 => BlueScale [Number::Real(0.039625)],
189        0x0c0a => BlueShift [Number::Integer(7)],
190        0x0c0b => BlueFuzz [Number::Integer(1)],
191        0x0c0c => StemSnapH [],
192        0x0c0d => StemSnapV [],
193        0x0c0e => ForceBold [Number::Integer(false as i32)],
194        // 0x0c0f..=0x0c10 => Reserved,
195        0x0c11 => LanguageGroup [Number::Integer(0)],
196        0x0c12 => ExpansionFactor [Number::Real(0.06)],
197        0x0c13 => InitialRandomSeed [Number::Integer(0)],
198        0x0c14 => SyntheticBase [],
199        0x0c15 => PostScript [],
200        0x0c16 => BaseFontName [],
201        0x0c17 => BaseFontBlend [],
202        // 0x0c18..=0x0c1d => Reserved,
203        0x0c1e => ROS [],
204        0x0c1f => CIDFontVersion [Number::Integer(0)],
205        0x0c20 => CIDFontRevision [Number::Integer(0)],
206        0x0c21 => CIDFontType [Number::Integer(0)],
207        0x0c22 => CIDCount [Number::Integer(8720)],
208        0x0c23 => UIDBase [],
209        0x0c24 => FDArray [],
210        0x0c25 => FDSelect [],
211        0x0c26 => FontName [],
212        // 0x0c27..=0x0cff => Reserved,
213    }
214}