pdf_canvas/
encoding.rs

1use std::collections::BTreeMap;
2
3/// Represent a text encoding used in PDF.
4/// An encoding maintains the connection between unicode code points,
5/// bytes in PDF strings, and glyph names.
6///
7/// Currently, only WIN_ANSI_ENCODING, SYMBOL_ENCODING, and
8/// ZAPFDINGBATS_ENCODING are supported, and they are provided as
9/// built-in.
10///
11/// # Example
12/// ````
13/// use pdf_canvas::{BuiltinFont, FontSource};
14/// assert_eq!("WinAnsiEncoding",
15///            BuiltinFont::Helvetica.get_encoding().get_name());
16/// assert_eq!("SymbolEncoding",
17///            BuiltinFont::Symbol.get_encoding().get_name());
18/// ````
19#[derive(Debug, PartialEq, Eq, Hash, Clone)]
20pub struct Encoding {
21    name: String,
22    name_to_code: BTreeMap<&'static str, u8>,
23    unicode_to_code: BTreeMap<char, u8>,
24}
25
26impl Encoding {
27    /// The name of the encoding, as used in the font object.
28    pub fn get_name(&self) -> String {
29        self.name.clone()
30    }
31
32    /// Get the encoded code point from a type1 character name.
33    /// Character names are case sensitive and contains only ascii letters.
34    /// If the name is not available in the encoding, or is not a proper
35    /// character name, None is returned.
36    ///
37    /// # Example
38    /// ````
39    /// use pdf_canvas::{BuiltinFont, FontSource};
40    /// let enc = BuiltinFont::Helvetica.get_encoding();
41    /// assert_eq!(Some(32),  enc.get_code("space"));
42    /// assert_eq!(Some(65),  enc.get_code("A"));
43    /// assert_eq!(Some(229), enc.get_code("aring"));
44    /// assert_eq!(None,      enc.get_code("Lslash"));
45    /// assert_eq!(None,      enc.get_code(""));
46    /// assert_eq!(None,      enc.get_code("☺"));
47    /// ````
48    pub fn get_code(&self, name: &str) -> Option<u8> {
49        self.name_to_code.get(name).cloned()
50    }
51
52    /// Get the encoded code point from a (unicode) character.
53    /// If the character is not available in the encoding, None is returned.
54    ///
55    /// # Example
56    /// ````
57    /// use pdf_canvas::{BuiltinFont, FontSource};
58    /// let enc = BuiltinFont::Helvetica.get_encoding();
59    /// assert_eq!(Some(b' '),  enc.encode_char(' '));
60    /// assert_eq!(Some(b'A'),  enc.encode_char('A'));
61    /// assert_eq!(Some(b'\\'),  enc.encode_char('\\'));
62    /// assert_eq!(Some(229), enc.encode_char('å'));
63    /// assert_eq!(None,      enc.encode_char('Ł'));
64    /// assert_eq!(None,      enc.encode_char(char::from(0)));
65    /// assert_eq!(None,      enc.encode_char('☺'));
66    /// ````
67    pub fn encode_char(&self, ch: char) -> Option<u8> {
68        self.unicode_to_code.get(&ch).cloned()
69    }
70
71    /// Convert a rust string to a vector of bytes in the encoding.
72    /// # Example
73    /// ````
74    /// use pdf_canvas::{BuiltinFont, FontSource};
75    /// let enc = BuiltinFont::Helvetica.get_encoding();
76    /// let symb_enc = BuiltinFont::Symbol.get_encoding();
77    /// assert_eq!(vec![b'A', b'B', b'C'], enc.encode_string("ABC"));
78    /// assert_eq!(vec![b'R', 228, b'k',
79    ///                 b's', b'm', 246, b'r', b'g', 229, b's'],
80    ///            enc.encode_string("Räksmörgås"));
81    /// assert_eq!(vec![b'C', b'o', b'f', b'f', b'e', b'e', b' ',
82    ///                 128, b'1', b'.', b'2', b'0'],
83    ///            enc.encode_string("Coffee €1.20"));
84    /// assert_eq!(vec![b'a', b' ', 206, b' ', 194],
85    ///            symb_enc.encode_string("α ∈ ℜ"));
86    /// ````
87    pub fn encode_string(&self, text: &str) -> Vec<u8> {
88        let size = text.len()
89            + text
90                .chars()
91                .filter(|&c| c == '\\' || c == '(' || c == ')')
92                .count();
93        let mut result = Vec::with_capacity(size);
94        for ch in text.chars() {
95            match self.encode_char(ch) {
96                Some(b'\\') => {
97                    result.push(b'\\');
98                    result.push(b'\\')
99                }
100                Some(b'(') => {
101                    result.push(b'\\');
102                    result.push(b'(')
103                }
104                Some(b')') => {
105                    result.push(b'\\');
106                    result.push(b')')
107                }
108                Some(ch) => result.push(ch),
109                None => result.push(b'?'),
110            }
111        }
112        result
113    }
114
115    fn init_block(&mut self, start: u8, data: &[&'static str]) {
116        for (i, name) in data.iter().enumerate() {
117            self.name_to_code.insert(name, start + (i as u8));
118        }
119    }
120}
121
122lazy_static! {
123    pub static ref WIN_ANSI_ENCODING: Encoding = {
124        let mut codes = BTreeMap::new();
125        // /WinAnsiEncoding is kind of close to first byte of unicode
126        // Except for the 16 chars that are reserved in 8859-1 and
127        // used in Windows-1252.
128        for code in 32..255 {
129            codes.insert(code as char, code);
130        }
131        codes.insert('€', 128);
132        codes.insert('‚', 130);
133        codes.insert('ƒ', 131);
134        codes.insert('„', 132);
135        codes.insert('…', 133);
136        codes.insert('†', 134);
137        codes.insert('‡', 135);
138        codes.insert('ˆ', 136);
139        codes.insert('‰', 137);
140        codes.insert('Š', 138);
141        codes.insert('‹', 139);
142        codes.insert('Œ', 140);
143        codes.insert('Ž', 142);
144        codes.insert('‘', 145);
145        codes.insert('’', 146);
146        codes.insert('“', 147);
147        codes.insert('”', 148);
148        codes.insert('•', 149);
149        codes.insert('–', 150);
150        codes.insert('—', 151);
151        codes.insert('˜', 152);
152        codes.insert('™', 153);
153        codes.insert('š', 154);
154        codes.insert('›', 155);
155        codes.insert('ž', 158);
156        codes.insert('Ÿ', 159);
157        let mut result = Encoding {
158            name: "WinAnsiEncoding".to_string(),
159            name_to_code: BTreeMap::new(),
160            unicode_to_code: codes
161        };
162        result.init_block(0o40, &[
163            "space", "exclam", "quotedbl", "numbersign",
164            "dollar", "percent", "ampersand", "quotesingle"]);
165        result.init_block(0o50, &[
166            "parenleft", "parenright", "asterisk", "plus",
167            "comma", "hyphen", "period", "slash"]);
168        result.init_block(0o60, &[
169            "zero", "one", "two", "three", "four", "five", "six", "seven"]);
170        result.init_block(0o70, &[
171            "eight", "nine", "colon", "semicolon",
172            "less", "equal", "greater", "question"]);
173        result.init_block(0o100, &[
174            "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
175            "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
176            "W", "X", "Y", "Z"]);
177        result.init_block(0o133, &[
178            "bracketleft",
179            "backslash", "bracketright", "asciicircum", "underscore"]);
180        result.init_block(0o140, &[
181            "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
182            "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
183            "w", "x", "y", "z"]);
184        result.init_block(0o173, &[
185            "braceleft", "bar", "braceright", "asciitilde"]);
186        result.init_block(0o200, &[
187            "Euro", "..1", "quotesinglbase", "florin",
188            "quotedblbase", "ellipsis", "dagger", "daggerdbl"]);
189        result.init_block(0o210, &[
190            "circumflex", "perthousand", "Scaron", "guilsinglleft",
191            "OE", "..5", "Zcaron", "..7"]);
192        result.init_block(0o220, &[
193            "..0", "quoteleft", "quoteright", "quotedblleft",
194            "quotedblright", "bullet", "endash", "emdash"]);
195        result.init_block(0o230, &[
196            "tilde", "trademark", "scaron", "guilsinglright",
197            "oe", "..5", "zcaron", "Ydieresis"]);
198        result.init_block(0o240, &[
199            "..0", "exclamdown", "cent", "sterling",
200            "currency", "yen", "brokenbar", "section"]);
201        result.init_block(0o250, &[
202            "dieresis", "copyright", "ordfeminine", "guillemotleft",
203            "logicalnot", "..5", "registered", "macron"]);
204        result.init_block(0o260, &[
205            "degree", "plusminus", "twosuperior", "threesuperior",
206            "acute", "mu", "paragraph", "periodcentered"]);
207        result.init_block(0o270, &[
208            "cedilla", "onesuperior", "ordmasculine", "guillemotright",
209            "onequarter", "onehalf", "threequarters", "questiondown"]);
210        result.init_block(0o300, &[
211            "Agrave", "Aacute", "Acircumflex", "Atilde",
212            "Adieresis", "Aring", "AE", "Ccedilla"]);
213        result.init_block(0o310, &[
214            "Egrave", "Eacute", "Ecircumflex", "Edieresis",
215            "Igrave", "Iacute", "Icircumflex", "Idieresis"]);
216        result.init_block(0o320, &[
217            "Eth", "Ntilde", "Ograve", "Oacute",
218            "Ocircumflex", "Otilde", "Odieresis", "multiply"]);
219        result.init_block(0o330, &[
220            "Oslash", "Ugrave", "Uacute", "Ucircumflex",
221            "Udieresis", "Yacute", "Thorn", "germandbls"]);
222        result.init_block(0o340, &[
223            "agrave", "aacute", "acircumflex", "atilde",
224            "adieresis", "aring", "ae", "ccedilla"]);
225        result.init_block(0o350, &[
226            "egrave", "eacute", "ecircumflex", "edieresis",
227            "igrave", "iacute", "icircumflex", "idieresis"]);
228        result.init_block(0o360, &[
229            "eth", "ntilde", "ograve", "oacute",
230            "ocircumflex", "otilde", "odieresis", "divide"]);
231        result.init_block(0o370, &[
232            "oslash", "ugrave", "uacute", "ucircumflex",
233            "udieresis", "yacute", "thorn", "ydieresis"]);
234        result
235    };
236
237    pub static ref SYMBOL_ENCODING: Encoding = {
238        let mut codes = BTreeMap::new();
239        let mut names = BTreeMap::new();
240        for code in 32..255 {
241            codes.insert(code as char, code);
242        }
243        {
244            let mut enc = |ch: char, name: &'static str, code: u8| {
245                codes.insert(ch, code);
246                names.insert(name, code);
247            };
248            enc('Α', "Alpha",          0o101);
249            enc('Β', "Beta",           0o102);
250            enc('Χ', "Chi",            0o103);
251            enc('Δ', "Delta",          0o104);
252            enc('Ε', "Epsilon",        0o105);
253            enc('Η', "Eta",            0o110);
254            enc('€', "Euro",           0o240);
255            enc('Γ', "Gamma",          0o107);
256            enc('ℑ', "Ifraktur",       0o301);
257            enc('Ι', "Iota",           0o111);
258            enc('Κ', "Kappa",          0o113);
259            enc('Λ', "Lambda",         0o114);
260            enc('Μ', "Mu",             0o115);
261            enc('Ν', "Nu",             0o116);
262            enc('Ω', "Omega",          0o127);
263            enc('Ο', "Omicron",        0o117);
264            enc('Φ', "Phi",            0o106);
265            enc('Π', "Pi",             0o120);
266            enc('Ψ', "Psi",            0o131);
267            enc('ℜ', "Rfraktur",       0o302);
268            enc('Ρ', "Rho",            0o122);
269            enc('Σ', "Sigma",          0o123);
270            enc('Τ', "Tau",            0o124);
271            enc('Θ', "Theta",          0o121);
272            enc('Υ', "Upsilon",        0o125);
273            enc('ϒ', "Upsilon1",       0o241);
274            enc('Ξ', "Xi",             0o130);
275            enc('Ζ', "Zeta",           0o132);
276            enc('ℵ', "aleph",          0o141);
277            enc('α', "alpha",          0o141);
278            enc('&', "ampersand",      0o046);
279            enc('∠', "angle",          0o320);
280            enc('〈', "angleleft",      0o341);
281            enc('〉', "angleright",     0o361);
282            enc('≈', "approxequal",    0o273);
283            enc('↔', "arrowboth",      0o253);
284            enc('⇔', "arrowdblboth",   0o333);
285            enc('⇓', "arrowdbldown",   0o337);
286            enc('⇐', "arrowdblleft",   0o334);
287            enc('⇒', "arrowdblright",  0o336);
288            enc('⇑', "arrowdblup",     0o335);
289            enc('↓', "arrowdown",      0o257);
290            enc('\u{23af}', "arrowhorizex", 0o276);
291            enc('←', "arrowleft",      0o254);
292            enc('→', "arrowright",     0o256);
293            enc('↑', "arrowup",        0o255);
294            enc('\u{23d0}', "arrowvertex", 0o275);
295            enc('*', "asteriskmath",   0o052);
296            enc('|', "bar",            0o175);
297            enc('β', "beta",           0o142);
298            enc('{', "braceleft",      0o173);
299            enc('}', "braceright",     0o175);
300            enc('⎧', "bracelefttp",    0o354);
301            enc('⎨', "braceleftmid",   0o355);
302            enc('⎩', "braceleftbt",    0o356);
303            enc('⎫', "bracerighttp",   0o374);
304            enc('⎬', "bracerightmid",  0o375);
305            enc('⎭', "bracerightbt",   0o376);
306            enc('⎪', "braceex",        0o357);
307            enc('[', "bracketleft",    0o133);
308            enc(']', "bracketright",   0o135);
309            enc('⎡', "bracketlefttp",  0o351);
310            enc('⎢', "bracketleftex",  0o352);
311            enc('⎣', "bracketleftbt",  0o353);
312            enc('⎤', "bracketrighttp", 0o371);
313            enc('⎥', "bracketrightex", 0o372);
314            enc('⎦', "bracketrightbt", 0o373);
315            enc('•', "bullet",         0o267);
316            enc('↵', "carriagereturn", 0o277);
317            enc('χ', "chi",            0o143);
318            enc('⊗', "circlemultiply", 0o304);
319            enc('⊕', "circleplus",     0o305);
320            enc('♣', "club",           0o247);
321            enc(':', "colon",          0o072);
322            enc(',', "comma",          0o054);
323            enc('≅', "congruent",      0o100);
324            // NOTE: copyrightsans and copyrightserif is a single unicode point
325            enc('©', "copyrightsans",  0o343);
326            enc('©', "copyrightserif", 0o323);
327            enc('°', "degree",         0o260);
328            enc('δ', "delta",          0o144);
329            enc('♦', "diamond",        0o250);
330            enc('÷', "divide",         0o270);
331            enc('⋅', "dotmath",        0o327);
332            enc('8', "eight",          0o070);
333            enc('∈', "element",        0o316); // NOTE: and ∊ ?
334            enc('…', "ellipsis",       0o274);
335            enc('∅', "emptyset",       0o306);
336            enc('ε', "epsilon",        0o145);
337            enc('=', "equal",          0o075);
338            enc('≡', "equivalence",    0o272);
339            enc('η', "eta",            0o150);
340            enc('!', "exclam",         0o041);
341            enc('∃', "existential",    0o044);
342            enc('5', "five",           0o065);
343            enc('ƒ', "florin",         0o246);
344            enc('4', "four",           0o064);
345            enc('⁄', "fraction",       0o244);
346            enc('γ', "gamma",          0o147);
347            enc('∇', "gradient",       0o321);
348            enc('>', "greater",        0o076);
349            enc('≥', "greaterequal",   0o263);
350            enc('♥', "heart",          0o251);
351            enc('∞', "infinity",       0o245);
352            enc('∫', "integral",       0o362);
353            enc('⌠', "integraltp",     0o363);
354            enc('⎮', "integralex",     0o364);
355            enc('⌡', "integralbt",     0o365);
356            enc('∩', "intersection",   0o307);
357            enc('ι', "iota",           0o151);
358            enc('κ', "kappa",          0o153);
359            enc('λ', "lambda",         0o154);
360            enc('<', "less",           0o074);
361            enc('≤', "lessequal",      0o243);
362            enc('∧', "logicaland",     0o331);
363            enc('¬', "logicalnot",     0o330);
364            enc('∨', "logicalor",      0o332);
365            enc('◊', "lozenge",        0o340);
366            enc('-', "minus",          0o055);
367            enc('\u{2032}', "minute",  0o242); // prime / minutes / feet
368            enc('μ', "mu",             0o155);
369            enc('×', "multiply",       0o264); // small and large in unicode
370            enc('⨯', "multiply",       0o264); // only one in symbol
371            enc('9', "nine",           0o071);
372            enc('∉', "notelement",     0o317);
373            enc('≠', "notequal",       0o271);
374            enc('⊄', "notsubset",      0o313);
375            enc('ν', "nu",             0o156);
376            enc('#', "numbersign",     0o043);
377            enc('ω', "omega",          0o167);
378            enc('ϖ', "omega1",         0o166);
379            enc('ο', "omicron",        0o157);
380            enc('1', "one",            0o060);
381            enc('(', "parenleft",      0o050);
382            enc(')', "parenright",     0o051);
383            enc('⎛', "parenlefttp",    0o346);
384            enc('⎜', "parenleftex",    0o347);
385            enc('⎝', "parenleftbt",    0o350);
386            enc('⎞', "parenrighttp",   0o366);
387            enc('⎟', "parenrightex",   0o367);
388            enc('⎠', "parenrightbt",   0o360);
389            enc('∂', "partialdiff",    0o266);
390            enc('%', "percent",        0o045);
391            enc('.', "period",         0o056);
392            enc('⟂', "perpendicular",  0o136);
393            enc('ɸ', "phi",            0o146);
394            enc('φ', "phi1",           0o152);
395            enc('π', "pi",             0o160);
396            enc('+', "plus",           0o053);
397            enc('±', "plusminus",      0o261);
398            enc('∏', "product",        0o325);
399            enc('⊂', "propersubset",   0o314);
400            enc('⊃', "propersuperset", 0o311);
401            enc('∝', "proportional",   0o265);
402            enc('ψ', "psi",            0o171);
403            enc('?', "question",       0o077);
404            enc('√', "radical",        0o326);
405            enc('⎺', "radicalex",      0o140); // Very approximate unicode
406            enc('⊆', "reflexsubset",   0o315);
407            enc('⊇', "reflexsuperset", 0o312);
408            enc('®', "registersans",   0o342);
409            enc('®', "registerserif",  0o322); // NOTE No distinct unicode?
410            enc('ρ', "rho",            0o162);
411            enc('\u{2033}', "second",  0o262); // Double prime/seconds/inches
412            enc(';', "semicolon",      0o073);
413            enc('7', "seven",          0o067);
414            enc('σ', "sigma",          0o163);
415            enc('ς', "sigma1",         0o126);
416            enc('∼', "similar",        0o176);
417            enc('6', "six",            0o066);
418            enc('/', "slash",          0o057);
419            enc(' ', "space",          0o040);
420            enc('♠', "spade",          0o252);
421            enc('∋', "suchthat",       0o047);
422            enc('∑', "summation",      0o345);
423            enc('τ', "tau",            0o164);
424            enc('∴', "therefore",      0o134);
425            enc('θ', "theta",          0o161);
426            enc('ϑ', "theta1",         0o112);
427            enc('3', "three",          0o063);
428            enc('™', "trademarksans",  0o344);
429            enc('™', "trademarkserif", 0o324); // NOTE No distinct unicode?
430            enc('2', "two",            0o062);
431            enc('_', "underscore",     0o137);
432            enc('∪', "union",          0o310);
433            enc('∀', "universal",      0o042);
434            enc('υ', "upsilon",        0o165);
435            enc('℘', "weierstrass",    0o303); // Maybe not correct unicode?
436            enc('ξ', "xi",             0o170);
437            enc('0', "zero",           0o060);
438            enc('ζ', "zeta",           0o172);
439        }
440        Encoding {
441            name: "SymbolEncoding".to_string(),
442            name_to_code: names,
443            unicode_to_code: codes
444        }
445    };
446
447    // https://unicode.org/Public/MAPPINGS/VENDORS/ADOBE/zdingbat.txt
448    pub static ref ZAPFDINGBATS_ENCODING: Encoding = {
449        let mut codes = BTreeMap::new();
450        let mut names = BTreeMap::new();
451        for code in 32..255 {
452            codes.insert(code as char, code);
453        }
454        {
455            let mut enc = |ch: char, name: &'static str, code: u8| {
456                codes.insert(ch, code);
457                names.insert(name, code);
458            };
459            enc(' ', "space", 0o40);
460            enc(' ', "space", 0o40);
461            enc('✁', "a1", 0o41);
462            enc('✂', "a2", 0o42);
463            enc('✃', "a202", 0o43);
464            enc('✄', "a3", 0o44);
465            enc('☎', "a4", 0o45);
466            enc('✆', "a5", 0o46);
467            enc('✇', "a119", 0o47);
468            enc('✈', "a118", 0o50);
469            enc('✉', "a117", 0o51);
470            enc('☛', "a11", 0o52);
471            enc('☞', "a12", 0o53);
472            enc('✌', "a13", 0o54);
473            enc('✍', "a14", 0o55);
474            enc('✎', "a15", 0o56);
475            enc('✏', "a16", 0o57);
476            enc('✐', "a105", 0o60);
477            enc('✑', "a17", 0o61);
478            enc('✒', "a18", 0o62);
479            enc('✓', "a19", 0o63);
480            enc('✔', "a20", 0o64);
481            enc('✕', "a21", 0o65);
482            enc('✖', "a22", 0o66);
483            enc('✗', "a23", 0o67);
484            enc('✘', "a24", 0o70);
485            enc('✙', "a25", 0o71);
486            enc('✚', "a26", 0o72);
487            enc('✛', "a27", 0o73);
488            enc('✜', "a28", 0o74);
489            enc('✝', "a6", 0o75);
490            enc('✞', "a7", 0o76);
491            enc('✟', "a8", 0o77);
492            enc('✠', "a9", 0o100);
493            enc('✡', "a10", 0o101);
494            enc('✢', "a29", 0o102);
495            enc('✣', "a30", 0o103);
496            enc('✤', "a31", 0o104);
497            enc('✥', "a32", 0o105);
498            enc('✦', "a33", 0o106);
499            enc('✧', "a34", 0o107);
500            enc('★', "a35", 0o110);
501            enc('✩', "a36", 0o111);
502            enc('✪', "a37", 0o112);
503            enc('✫', "a38", 0o113);
504            enc('✬', "a39", 0o114);
505            enc('✭', "a40", 0o115);
506            enc('✮', "a41", 0o116);
507            enc('✯', "a42", 0o117);
508            enc('✰', "a43", 0o120);
509            enc('✱', "a44", 0o121);
510            enc('✲', "a45", 0o122);
511            enc('✳', "a46", 0o123);
512            enc('✴', "a47", 0o124);
513            enc('✵', "a48", 0o125);
514            enc('✶', "a49", 0o126);
515            enc('✷', "a50", 0o127);
516            enc('✸', "a51", 0o130);
517            enc('✹', "a52", 0o131);
518            enc('✺', "a53", 0o132);
519            enc('✻', "a54", 0o133);
520            enc('✼', "a55", 0o134);
521            enc('✽', "a56", 0o135);
522            enc('✾', "a57", 0o136);
523            enc('✿', "a58", 0o137);
524            enc('❀', "a59", 0o140);
525            enc('❁', "a60", 0o141);
526            enc('❂', "a61", 0o142);
527            enc('❃', "a62", 0o143);
528            enc('❄', "a63", 0o144);
529            enc('❅', "a64", 0o145);
530            enc('❆', "a65", 0o146);
531            enc('❇', "a66", 0o147);
532            enc('❈', "a67", 0o150);
533            enc('❉', "a68", 0o151);
534            enc('❊', "a69", 0o152);
535            enc('❋', "a70", 0o153);
536            enc('●', "a71", 0o154);
537            enc('❍', "a72", 0o155);
538            enc('■', "a73", 0o156);
539            enc('❏', "a74", 0o157);
540            enc('❐', "a203", 0o160);
541            enc('❑', "a75", 0o161);
542            enc('❒', "a204", 0o162);
543            enc('▲', "a76", 0o163);
544            enc('▼', "a77", 0o164);
545            enc('◆', "a78", 0o165);
546            enc('❖', "a79", 0o166);
547            enc('◗', "a81", 0o167);
548            enc('❘', "a82", 0o170);
549            enc('❙', "a83", 0o171);
550            enc('❚', "a84", 0o172);
551            enc('❛', "a97", 0o173);
552            enc('❜', "a98", 0o174);
553            enc('❝', "a99", 0o175);
554            enc('❞', "a100", 0o176);
555            enc('❨', "a89", 0o200); // Note: (CUS) cannot be displayed
556            enc('❩', "a90", 0o201); // Note: (CUS) cannot be displayed
557            enc('❪', "a93", 0o202); // Note: (CUS) cannot be displayed
558            enc('❫', "a94", 0o203); // Note: (CUS) cannot be displayed
559            enc('❬', "a91", 0o204); // Note: (CUS) cannot be displayed
560            enc('❭', "a92", 0o205); // Note: (CUS) cannot be displayed
561            enc('❮', "a205", 0o206); // Note: (CUS) cannot be displayed
562            enc('❯', "a85", 0o207); // Note: (CUS) cannot be displayed
563            enc('❰', "a206", 0o210); // Note: (CUS) cannot be displayed
564            enc('❱', "a86", 0o211); // Note: (CUS) cannot be displayed
565            enc('❲', "a87", 0o212); // Note: (CUS) cannot be displayed
566            enc('❳', "a88", 0o213); // Note: (CUS) cannot be displayed
567            enc('❴', "a95", 0o214); // Note: (CUS) cannot be displayed
568            enc('❵', "a96", 0o215); // Note: (CUS) cannot be displayed
569            enc('❡', "a101", 0o241);
570            enc('❢', "a102", 0o242);
571            enc('❣', "a103", 0o243);
572            enc('❤', "a104", 0o244);
573            enc('❥', "a106", 0o245);
574            enc('❦', "a107", 0o246);
575            enc('❧', "a108", 0o247);
576            enc('♣', "a112", 0o250);
577            enc('♦', "a111", 0o251);
578            enc('♥', "a110", 0o252);
579            enc('♠', "a109", 0o253);
580            enc('①', "a120", 0o254);
581            enc('②', "a121", 0o255);
582            enc('③', "a122", 0o256);
583            enc('④', "a123", 0o257);
584            enc('⑤', "a124", 0o260);
585            enc('⑥', "a125", 0o261);
586            enc('⑦', "a126", 0o262);
587            enc('⑧', "a127", 0o263);
588            enc('⑨', "a128", 0o264);
589            enc('⑩', "a129", 0o265);
590            enc('❶', "a130", 0o266);
591            enc('❷', "a131", 0o267);
592            enc('❸', "a132", 0o270);
593            enc('❹', "a133", 0o271);
594            enc('❺', "a134", 0o272);
595            enc('❻', "a135", 0o273);
596            enc('❼', "a136", 0o274);
597            enc('❽', "a137", 0o275);
598            enc('❾', "a138", 0o276);
599            enc('❿', "a139", 0o277);
600            enc('➀', "a140", 0o300);
601            enc('➁', "a141", 0o301);
602            enc('➂', "a142", 0o302);
603            enc('➃', "a143", 0o303);
604            enc('➄', "a144", 0o304);
605            enc('➅', "a145", 0o305);
606            enc('➆', "a146", 0o306);
607            enc('➇', "a147", 0o307);
608            enc('➈', "a148", 0o310);
609            enc('➉', "a149", 0o311);
610            enc('➊', "a150", 0o312);
611            enc('➋', "a151", 0o313);
612            enc('➌', "a152", 0o314);
613            enc('➍', "a153", 0o315);
614            enc('➎', "a154", 0o316);
615            enc('➏', "a155", 0o317);
616            enc('➐', "a156", 0o320);
617            enc('➑', "a157", 0o321);
618            enc('➒', "a158", 0o322);
619            enc('➓', "a159", 0o323);
620            enc('➔', "a160", 0o324);
621            enc('→', "a161", 0o325);
622            enc('↔', "a163", 0o326);
623            enc('↕', "a164", 0o327);
624            enc('➘', "a196", 0o330);
625            enc('➙', "a165", 0o331);
626            enc('➚', "a192", 0o332);
627            enc('➛', "a166", 0o333);
628            enc('➜', "a167", 0o334);
629            enc('➝', "a168", 0o335);
630            enc('➞', "a169", 0o336);
631            enc('➟', "a170", 0o337);
632            enc('➠', "a171", 0o340);
633            enc('➡', "a172", 0o341);
634            enc('➢', "a173", 0o342);
635            enc('➣', "a162", 0o343);
636            enc('➤', "a174", 0o344);
637            enc('➥', "a175", 0o345);
638            enc('➦', "a176", 0o346);
639            enc('➧', "a177", 0o347);
640            enc('➨', "a178", 0o350);
641            enc('➩', "a179", 0o351);
642            enc('➪', "a193", 0o352);
643            enc('➫', "a180", 0o353);
644            enc('➬', "a199", 0o354);
645            enc('➭', "a181", 0o355);
646            enc('➮', "a200", 0o356);
647            enc('➯', "a182", 0o357);
648            enc('➱', "a201", 0o361);
649            enc('➲', "a183", 0o362);
650            enc('➳', "a184", 0o363);
651            enc('➴', "a197", 0o364);
652            enc('➵', "a185", 0o365);
653            enc('➶', "a194", 0o366);
654            enc('➷', "a198", 0o367);
655            enc('➸', "a186", 0o370);
656            enc('➹', "a195", 0o371);
657            enc('➺', "a187", 0o372);
658            enc('➻', "a188", 0o373);
659            enc('➼', "a189", 0o374);
660            enc('➽', "a190", 0o375);
661            enc('➾', "a191", 0o376);
662        }
663        Encoding {
664            name: "ZapfDingbatsEncoding".to_string(),
665            name_to_code: names,
666            unicode_to_code: codes
667        }
668    };
669}
670
671#[test]
672fn test_get_winansi_points() {
673    let ref enc = WIN_ANSI_ENCODING;
674    assert_eq!(Some('A' as u8), enc.get_code("A"));
675    assert_eq!(Some('Z' as u8), enc.get_code("Z"));
676    assert_eq!(Some('a' as u8), enc.get_code("a"));
677    assert_eq!(Some('z' as u8), enc.get_code("z"));
678    assert_eq!(Some(' ' as u8), enc.get_code("space"));
679    assert_eq!(Some('&' as u8), enc.get_code("ampersand"));
680}