postscript/compact1/
character_set.rs

1//! The character sets.
2
3use crate::compact1::{GlyphID, StringID};
4use crate::Result;
5
6/// A character set.
7#[derive(Clone, Debug)]
8pub enum CharacterSet {
9    ISOAdobe,
10    Expert,
11    ExpertSubset,
12    Format0(CharacterSet0),
13    Format1(CharacterSet1),
14    Format2(CharacterSet2),
15}
16
17/// A character set in format 0.
18#[derive(Clone, Debug)]
19pub struct CharacterSet0 {
20    pub format: u8,            // format
21    pub glyphs: Vec<StringID>, // glyph
22}
23
24/// A character set in format 1.
25#[derive(Clone, Debug)]
26pub struct CharacterSet1 {
27    pub format: u8,          // format
28    pub ranges: Vec<Range1>, // Range1
29}
30
31/// A character set in format 2.
32#[derive(Clone, Debug)]
33pub struct CharacterSet2 {
34    pub format: u8,          // format
35    pub ranges: Vec<Range2>, // Range2
36}
37
38table! {
39    /// A range of a character set in format 1.
40    #[derive(Copy)]
41    pub Range1 {
42        first_string_id (StringID), // first
43        left_count      (u8      ), // nLeft
44    }
45}
46
47table! {
48    /// A range of a character set in format 2.
49    #[derive(Copy)]
50    pub Range2 {
51        first_string_id (StringID), // first
52        left_count      (u16     ), // nLeft
53    }
54}
55
56impl CharacterSet {
57    /// Return the name of a glyph.
58    #[inline]
59    pub fn get(&self, glyph_id: GlyphID) -> Option<&'static str> {
60        match self {
61            CharacterSet::ISOAdobe => get_iso_adobe(glyph_id),
62            CharacterSet::Expert => get_expert(glyph_id),
63            CharacterSet::ExpertSubset => get_expert_subset(glyph_id),
64            CharacterSet::Format0(ref char_set) => char_set.get(glyph_id),
65            CharacterSet::Format1(ref char_set) => char_set.get(glyph_id),
66            CharacterSet::Format2(ref char_set) => char_set.get(glyph_id),
67        }
68    }
69}
70
71impl crate::walue::Read<'static> for CharacterSet {
72    type Parameter = usize;
73
74    fn read<T: crate::tape::Read>(tape: &mut T, glyph_count: usize) -> Result<Self> {
75        Ok(match tape.peek::<u8>()? {
76            0 => CharacterSet::Format0(tape.take_given(glyph_count)?),
77            1 => CharacterSet::Format1(tape.take_given(glyph_count)?),
78            2 => CharacterSet::Format2(tape.take_given(glyph_count)?),
79            format => raise!("found an unknown format of character sets ({format})"),
80        })
81    }
82}
83
84impl CharacterSet0 {
85    #[inline]
86    fn get(&self, _: GlyphID) -> Option<&'static str> {
87        None
88    }
89}
90
91impl crate::walue::Read<'static> for CharacterSet0 {
92    type Parameter = usize;
93
94    fn read<T: crate::tape::Read>(tape: &mut T, glyph_count: usize) -> Result<Self> {
95        let format = tape.take::<u8>()?;
96        if format != 0 {
97            raise!("found a malformed character set");
98        }
99        Ok(CharacterSet0 {
100            format,
101            glyphs: tape.take_given(glyph_count - 1)?,
102        })
103    }
104}
105
106impl CharacterSet1 {
107    #[inline]
108    fn get(&self, _: GlyphID) -> Option<&'static str> {
109        None
110    }
111}
112
113impl crate::walue::Read<'static> for CharacterSet1 {
114    type Parameter = usize;
115
116    fn read<T: crate::tape::Read>(tape: &mut T, glyph_count: usize) -> Result<Self> {
117        let format = tape.take::<u8>()?;
118        if format != 1 {
119            raise!("found a malformed character set");
120        }
121        let mut ranges = vec![];
122        #[allow(clippy::identity_op)]
123        let mut found_count = 0 + 1;
124        while found_count < glyph_count {
125            let range = tape.take::<Range1>()?;
126            found_count += 1 + range.left_count as usize;
127            ranges.push(range);
128        }
129        if found_count != glyph_count {
130            raise!("found a malformed character set");
131        }
132        Ok(CharacterSet1 { format, ranges })
133    }
134}
135
136impl CharacterSet2 {
137    #[inline]
138    fn get(&self, _: GlyphID) -> Option<&'static str> {
139        None
140    }
141}
142
143impl crate::walue::Read<'static> for CharacterSet2 {
144    type Parameter = usize;
145
146    fn read<T: crate::tape::Read>(tape: &mut T, glyph_count: usize) -> Result<Self> {
147        macro_rules! reject(() => (raise!("found a malformed character set")));
148        let format = tape.take::<u8>()?;
149        if format != 2 {
150            reject!();
151        }
152        let mut ranges = vec![];
153        #[allow(clippy::identity_op)]
154        let mut found_count = 0 + 1;
155        while found_count < glyph_count {
156            let range = tape.take::<Range2>()?;
157            found_count += 1 + range.left_count as usize;
158            ranges.push(range);
159        }
160        if found_count != glyph_count {
161            reject!();
162        }
163        Ok(CharacterSet2 { format, ranges })
164    }
165}
166
167fn get_iso_adobe(glyph_id: GlyphID) -> Option<&'static str> {
168    Some(match glyph_id {
169        1 => "space",
170        2 => "exclam",
171        3 => "quotedbl",
172        4 => "numbersign",
173        5 => "dollar",
174        6 => "percent",
175        7 => "ampersand",
176        8 => "quoteright",
177        9 => "parenleft",
178        10 => "parenright",
179        11 => "asterisk",
180        12 => "plus",
181        13 => "comma",
182        14 => "hyphen",
183        15 => "period",
184        16 => "slash",
185        17 => "zero",
186        18 => "one",
187        19 => "two",
188        20 => "three",
189        21 => "four",
190        22 => "five",
191        23 => "six",
192        24 => "seven",
193        25 => "eight",
194        26 => "nine",
195        27 => "colon",
196        28 => "semicolon",
197        29 => "less",
198        30 => "equal",
199        31 => "greater",
200        32 => "question",
201        33 => "at",
202        34 => "A",
203        35 => "B",
204        36 => "C",
205        37 => "D",
206        38 => "E",
207        39 => "F",
208        40 => "G",
209        41 => "H",
210        42 => "I",
211        43 => "J",
212        44 => "K",
213        45 => "L",
214        46 => "M",
215        47 => "N",
216        48 => "O",
217        49 => "P",
218        50 => "Q",
219        51 => "R",
220        52 => "S",
221        53 => "T",
222        54 => "U",
223        55 => "V",
224        56 => "W",
225        57 => "X",
226        58 => "Y",
227        59 => "Z",
228        60 => "bracketleft",
229        61 => "backslash",
230        62 => "bracketright",
231        63 => "asciicircum",
232        64 => "underscore",
233        65 => "quoteleft",
234        66 => "a",
235        67 => "b",
236        68 => "c",
237        69 => "d",
238        70 => "e",
239        71 => "f",
240        72 => "g",
241        73 => "h",
242        74 => "i",
243        75 => "j",
244        76 => "k",
245        77 => "l",
246        78 => "m",
247        79 => "n",
248        80 => "o",
249        81 => "p",
250        82 => "q",
251        83 => "r",
252        84 => "s",
253        85 => "t",
254        86 => "u",
255        87 => "v",
256        88 => "w",
257        89 => "x",
258        90 => "y",
259        91 => "z",
260        92 => "braceleft",
261        93 => "bar",
262        94 => "braceright",
263        95 => "asciitilde",
264        96 => "exclamdown",
265        97 => "cent",
266        98 => "sterling",
267        99 => "fraction",
268        100 => "yen",
269        101 => "florin",
270        102 => "section",
271        103 => "currency",
272        104 => "quotesingle",
273        105 => "quotedblleft",
274        106 => "guillemotleft",
275        107 => "guilsinglleft",
276        108 => "guilsinglright",
277        109 => "fi",
278        110 => "fl",
279        111 => "endash",
280        112 => "dagger",
281        113 => "daggerdbl",
282        114 => "periodcentered",
283        115 => "paragraph",
284        116 => "bullet",
285        117 => "quotesinglbase",
286        118 => "quotedblbase",
287        119 => "quotedblright",
288        120 => "guillemotright",
289        121 => "ellipsis",
290        122 => "perthousand",
291        123 => "questiondown",
292        124 => "grave",
293        125 => "acute",
294        126 => "circumflex",
295        127 => "tilde",
296        128 => "macron",
297        129 => "breve",
298        130 => "dotaccent",
299        131 => "dieresis",
300        132 => "ring",
301        133 => "cedilla",
302        134 => "hungarumlaut",
303        135 => "ogonek",
304        136 => "caron",
305        137 => "emdash",
306        138 => "AE",
307        139 => "ordfeminine",
308        140 => "Lslash",
309        141 => "Oslash",
310        142 => "OE",
311        143 => "ordmasculine",
312        144 => "ae",
313        145 => "dotlessi",
314        146 => "lslash",
315        147 => "oslash",
316        148 => "oe",
317        149 => "germandbls",
318        150 => "onesuperior",
319        151 => "logicalnot",
320        152 => "mu",
321        153 => "trademark",
322        154 => "Eth",
323        155 => "onehalf",
324        156 => "plusminus",
325        157 => "Thorn",
326        158 => "onequarter",
327        159 => "divide",
328        160 => "brokenbar",
329        161 => "degree",
330        162 => "thorn",
331        163 => "threequarters",
332        164 => "twosuperior",
333        165 => "registered",
334        166 => "minus",
335        167 => "eth",
336        168 => "multiply",
337        169 => "threesuperior",
338        170 => "copyright",
339        171 => "Aacute",
340        172 => "Acircumflex",
341        173 => "Adieresis",
342        174 => "Agrave",
343        175 => "Aring",
344        176 => "Atilde",
345        177 => "Ccedilla",
346        178 => "Eacute",
347        179 => "Ecircumflex",
348        180 => "Edieresis",
349        181 => "Egrave",
350        182 => "Iacute",
351        183 => "Icircumflex",
352        184 => "Idieresis",
353        185 => "Igrave",
354        186 => "Ntilde",
355        187 => "Oacute",
356        188 => "Ocircumflex",
357        189 => "Odieresis",
358        190 => "Ograve",
359        191 => "Otilde",
360        192 => "Scaron",
361        193 => "Uacute",
362        194 => "Ucircumflex",
363        195 => "Udieresis",
364        196 => "Ugrave",
365        197 => "Yacute",
366        198 => "Ydieresis",
367        199 => "Zcaron",
368        200 => "aacute",
369        201 => "acircumflex",
370        202 => "adieresis",
371        203 => "agrave",
372        204 => "aring",
373        205 => "atilde",
374        206 => "ccedilla",
375        207 => "eacute",
376        208 => "ecircumflex",
377        209 => "edieresis",
378        210 => "egrave",
379        211 => "iacute",
380        212 => "icircumflex",
381        213 => "idieresis",
382        214 => "igrave",
383        215 => "ntilde",
384        216 => "oacute",
385        217 => "ocircumflex",
386        218 => "odieresis",
387        219 => "ograve",
388        220 => "otilde",
389        221 => "scaron",
390        222 => "uacute",
391        223 => "ucircumflex",
392        224 => "udieresis",
393        225 => "ugrave",
394        226 => "yacute",
395        227 => "ydieresis",
396        228 => "zcaron",
397        _ => return None,
398    })
399}
400
401fn get_expert(glyph_id: GlyphID) -> Option<&'static str> {
402    Some(match glyph_id {
403        1 => "space",
404        229 => "exclamsmall",
405        230 => "Hungarumlautsmall",
406        231 => "dollaroldstyle",
407        232 => "dollarsuperior",
408        233 => "ampersandsmall",
409        234 => "Acutesmall",
410        235 => "parenleftsuperior",
411        236 => "parenrightsuperior",
412        237 => "twodotenleader",
413        238 => "onedotenleader",
414        13 => "comma",
415        14 => "hyphen",
416        15 => "period",
417        99 => "fraction",
418        239 => "zerooldstyle",
419        240 => "oneoldstyle",
420        241 => "twooldstyle",
421        242 => "threeoldstyle",
422        243 => "fouroldstyle",
423        244 => "fiveoldstyle",
424        245 => "sixoldstyle",
425        246 => "sevenoldstyle",
426        247 => "eightoldstyle",
427        248 => "nineoldstyle",
428        27 => "colon",
429        28 => "semicolon",
430        249 => "commasuperior",
431        250 => "threequartersemdash",
432        251 => "periodsuperior",
433        252 => "questionsmall",
434        253 => "asuperior",
435        254 => "bsuperior",
436        255 => "centsuperior",
437        256 => "dsuperior",
438        257 => "esuperior",
439        258 => "isuperior",
440        259 => "lsuperior",
441        260 => "msuperior",
442        261 => "nsuperior",
443        262 => "osuperior",
444        263 => "rsuperior",
445        264 => "ssuperior",
446        265 => "tsuperior",
447        266 => "ff",
448        109 => "fi",
449        110 => "fl",
450        267 => "ffi",
451        268 => "ffl",
452        269 => "parenleftinferior",
453        270 => "parenrightinferior",
454        271 => "Circumflexsmall",
455        272 => "hyphensuperior",
456        273 => "Gravesmall",
457        274 => "Asmall",
458        275 => "Bsmall",
459        276 => "Csmall",
460        277 => "Dsmall",
461        278 => "Esmall",
462        279 => "Fsmall",
463        280 => "Gsmall",
464        281 => "Hsmall",
465        282 => "Ismall",
466        283 => "Jsmall",
467        284 => "Ksmall",
468        285 => "Lsmall",
469        286 => "Msmall",
470        287 => "Nsmall",
471        288 => "Osmall",
472        289 => "Psmall",
473        290 => "Qsmall",
474        291 => "Rsmall",
475        292 => "Ssmall",
476        293 => "Tsmall",
477        294 => "Usmall",
478        295 => "Vsmall",
479        296 => "Wsmall",
480        297 => "Xsmall",
481        298 => "Ysmall",
482        299 => "Zsmall",
483        300 => "colonmonetary",
484        301 => "onefitted",
485        302 => "rupiah",
486        303 => "Tildesmall",
487        304 => "exclamdownsmall",
488        305 => "centoldstyle",
489        306 => "Lslashsmall",
490        307 => "Scaronsmall",
491        308 => "Zcaronsmall",
492        309 => "Dieresissmall",
493        310 => "Brevesmall",
494        311 => "Caronsmall",
495        312 => "Dotaccentsmall",
496        313 => "Macronsmall",
497        314 => "figuredash",
498        315 => "hypheninferior",
499        316 => "Ogoneksmall",
500        317 => "Ringsmall",
501        318 => "Cedillasmall",
502        158 => "onequarter",
503        155 => "onehalf",
504        163 => "threequarters",
505        319 => "questiondownsmall",
506        320 => "oneeighth",
507        321 => "threeeighths",
508        322 => "fiveeighths",
509        323 => "seveneighths",
510        324 => "onethird",
511        325 => "twothirds",
512        326 => "zerosuperior",
513        150 => "onesuperior",
514        164 => "twosuperior",
515        169 => "threesuperior",
516        327 => "foursuperior",
517        328 => "fivesuperior",
518        329 => "sixsuperior",
519        330 => "sevensuperior",
520        331 => "eightsuperior",
521        332 => "ninesuperior",
522        333 => "zeroinferior",
523        334 => "oneinferior",
524        335 => "twoinferior",
525        336 => "threeinferior",
526        337 => "fourinferior",
527        338 => "fiveinferior",
528        339 => "sixinferior",
529        340 => "seveninferior",
530        341 => "eightinferior",
531        342 => "nineinferior",
532        343 => "centinferior",
533        344 => "dollarinferior",
534        345 => "periodinferior",
535        346 => "commainferior",
536        347 => "Agravesmall",
537        348 => "Aacutesmall",
538        349 => "Acircumflexsmall",
539        350 => "Atildesmall",
540        351 => "Adieresissmall",
541        352 => "Aringsmall",
542        353 => "AEsmall",
543        354 => "Ccedillasmall",
544        355 => "Egravesmall",
545        356 => "Eacutesmall",
546        357 => "Ecircumflexsmall",
547        358 => "Edieresissmall",
548        359 => "Igravesmall",
549        360 => "Iacutesmall",
550        361 => "Icircumflexsmall",
551        362 => "Idieresissmall",
552        363 => "Ethsmall",
553        364 => "Ntildesmall",
554        365 => "Ogravesmall",
555        366 => "Oacutesmall",
556        367 => "Ocircumflexsmall",
557        368 => "Otildesmall",
558        369 => "Odieresissmall",
559        370 => "OEsmall",
560        371 => "Oslashsmall",
561        372 => "Ugravesmall",
562        373 => "Uacutesmall",
563        374 => "Ucircumflexsmall",
564        375 => "Udieresissmall",
565        376 => "Yacutesmall",
566        377 => "Thornsmall",
567        378 => "Ydieresissmall",
568        _ => return None,
569    })
570}
571
572fn get_expert_subset(glyph_id: GlyphID) -> Option<&'static str> {
573    Some(match glyph_id {
574        1 => "space",
575        231 => "dollaroldstyle",
576        232 => "dollarsuperior",
577        235 => "parenleftsuperior",
578        236 => "parenrightsuperior",
579        237 => "twodotenleader",
580        238 => "onedotenleader",
581        13 => "comma",
582        14 => "hyphen",
583        15 => "period",
584        99 => "fraction",
585        239 => "zerooldstyle",
586        240 => "oneoldstyle",
587        241 => "twooldstyle",
588        242 => "threeoldstyle",
589        243 => "fouroldstyle",
590        244 => "fiveoldstyle",
591        245 => "sixoldstyle",
592        246 => "sevenoldstyle",
593        247 => "eightoldstyle",
594        248 => "nineoldstyle",
595        27 => "colon",
596        28 => "semicolon",
597        249 => "commasuperior",
598        250 => "threequartersemdash",
599        251 => "periodsuperior",
600        253 => "asuperior",
601        254 => "bsuperior",
602        255 => "centsuperior",
603        256 => "dsuperior",
604        257 => "esuperior",
605        258 => "isuperior",
606        259 => "lsuperior",
607        260 => "msuperior",
608        261 => "nsuperior",
609        262 => "osuperior",
610        263 => "rsuperior",
611        264 => "ssuperior",
612        265 => "tsuperior",
613        266 => "ff",
614        109 => "fi",
615        110 => "fl",
616        267 => "ffi",
617        268 => "ffl",
618        269 => "parenleftinferior",
619        270 => "parenrightinferior",
620        272 => "hyphensuperior",
621        300 => "colonmonetary",
622        301 => "onefitted",
623        302 => "rupiah",
624        305 => "centoldstyle",
625        314 => "figuredash",
626        315 => "hypheninferior",
627        158 => "onequarter",
628        155 => "onehalf",
629        163 => "threequarters",
630        320 => "oneeighth",
631        321 => "threeeighths",
632        322 => "fiveeighths",
633        323 => "seveneighths",
634        324 => "onethird",
635        325 => "twothirds",
636        326 => "zerosuperior",
637        150 => "onesuperior",
638        164 => "twosuperior",
639        169 => "threesuperior",
640        327 => "foursuperior",
641        328 => "fivesuperior",
642        329 => "sixsuperior",
643        330 => "sevensuperior",
644        331 => "eightsuperior",
645        332 => "ninesuperior",
646        333 => "zeroinferior",
647        334 => "oneinferior",
648        335 => "twoinferior",
649        336 => "threeinferior",
650        337 => "fourinferior",
651        338 => "fiveinferior",
652        339 => "sixinferior",
653        340 => "seveninferior",
654        341 => "eightinferior",
655        342 => "nineinferior",
656        343 => "centinferior",
657        344 => "dollarinferior",
658        345 => "periodinferior",
659        346 => "commainferior",
660        _ => return None,
661    })
662}