qr_reader 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,224 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Generated by script/generate_font_tables.py from fontTools (MIT); do not edit.
4
+ module QrReader
5
+ module Formats
6
+ module PDF
7
+ # Glyph name tables for PDF fonts: Adobe's standard encodings, the CFF
8
+ # standard strings and the Unicode values of the glyph names in them.
9
+ module FontTables
10
+ # SID -> name for SIDs 0..390 of CFF fonts.
11
+ CFF_STANDARD_STRINGS = [
12
+ nil, "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand",
13
+ "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period",
14
+ "slash", "zero", "one", "two", "three", "four", "five", "six",
15
+ "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater",
16
+ "question", "at", "A", "B", "C", "D", "E", "F",
17
+ "G", "H", "I", "J", "K", "L", "M", "N",
18
+ "O", "P", "Q", "R", "S", "T", "U", "V",
19
+ "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum",
20
+ "underscore", "quoteleft", "a", "b", "c", "d", "e", "f",
21
+ "g", "h", "i", "j", "k", "l", "m", "n",
22
+ "o", "p", "q", "r", "s", "t", "u", "v",
23
+ "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde",
24
+ "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section", "currency",
25
+ "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "endash",
26
+ "dagger", "daggerdbl", "periodcentered", "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright",
27
+ "guillemotright", "ellipsis", "perthousand", "questiondown", "grave", "acute", "circumflex", "tilde",
28
+ "macron", "breve", "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut", "ogonek",
29
+ "caron", "emdash", "AE", "ordfeminine", "Lslash", "Oslash", "OE", "ordmasculine",
30
+ "ae", "dotlessi", "lslash", "oslash", "oe", "germandbls", "onesuperior", "logicalnot",
31
+ "mu", "trademark", "Eth", "onehalf", "plusminus", "Thorn", "onequarter", "divide",
32
+ "brokenbar", "degree", "thorn", "threequarters", "twosuperior", "registered", "minus", "eth",
33
+ "multiply", "threesuperior", "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring",
34
+ "Atilde", "Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave", "Iacute", "Icircumflex",
35
+ "Idieresis", "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", "Ograve", "Otilde",
36
+ "Scaron", "Uacute", "Ucircumflex", "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron",
37
+ "aacute", "acircumflex", "adieresis", "agrave", "aring", "atilde", "ccedilla", "eacute",
38
+ "ecircumflex", "edieresis", "egrave", "iacute", "icircumflex", "idieresis", "igrave", "ntilde",
39
+ "oacute", "ocircumflex", "odieresis", "ograve", "otilde", "scaron", "uacute", "ucircumflex",
40
+ "udieresis", "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall", "Hungarumlautsmall", "dollaroldstyle",
41
+ "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "zerooldstyle",
42
+ "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle",
43
+ "nineoldstyle", "commasuperior", "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior", "centsuperior",
44
+ "dsuperior", "esuperior", "isuperior", "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior",
45
+ "ssuperior", "tsuperior", "ff", "ffi", "ffl", "parenleftinferior", "parenrightinferior", "Circumflexsmall",
46
+ "hyphensuperior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall",
47
+ "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall",
48
+ "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall",
49
+ "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall",
50
+ "exclamdownsmall", "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall",
51
+ "Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall",
52
+ "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "zerosuperior", "foursuperior",
53
+ "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior",
54
+ "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior",
55
+ "dollarinferior", "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall",
56
+ "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall",
57
+ "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall",
58
+ "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall", "Udieresissmall",
59
+ "Yacutesmall", "Thornsmall", "Ydieresissmall", "001.000", "001.001", "001.002", "001.003", "Black",
60
+ "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold",
61
+ ].freeze
62
+
63
+ # Code -> glyph name (nil: .notdef).
64
+ STANDARD_ENCODING = [
65
+ nil, nil, nil, nil, nil, nil, nil, nil,
66
+ nil, nil, nil, nil, nil, nil, nil, nil,
67
+ nil, nil, nil, nil, nil, nil, nil, nil,
68
+ nil, nil, nil, nil, nil, nil, nil, nil,
69
+ "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright",
70
+ "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash",
71
+ "zero", "one", "two", "three", "four", "five", "six", "seven",
72
+ "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question",
73
+ "at", "A", "B", "C", "D", "E", "F", "G",
74
+ "H", "I", "J", "K", "L", "M", "N", "O",
75
+ "P", "Q", "R", "S", "T", "U", "V", "W",
76
+ "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
77
+ "quoteleft", "a", "b", "c", "d", "e", "f", "g",
78
+ "h", "i", "j", "k", "l", "m", "n", "o",
79
+ "p", "q", "r", "s", "t", "u", "v", "w",
80
+ "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", nil,
81
+ nil, nil, nil, nil, nil, nil, nil, nil,
82
+ nil, nil, nil, nil, nil, nil, nil, nil,
83
+ nil, nil, nil, nil, nil, nil, nil, nil,
84
+ nil, nil, nil, nil, nil, nil, nil, nil,
85
+ nil, "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section",
86
+ "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl",
87
+ nil, "endash", "dagger", "daggerdbl", "periodcentered", nil, "paragraph", "bullet",
88
+ "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", nil, "questiondown",
89
+ nil, "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent",
90
+ "dieresis", nil, "ring", "cedilla", nil, "hungarumlaut", "ogonek", "caron",
91
+ "emdash", nil, nil, nil, nil, nil, nil, nil,
92
+ nil, nil, nil, nil, nil, nil, nil, nil,
93
+ nil, "AE", nil, "ordfeminine", nil, nil, nil, nil,
94
+ "Lslash", "Oslash", "OE", "ordmasculine", nil, nil, nil, nil,
95
+ nil, "ae", nil, nil, nil, "dotlessi", nil, nil,
96
+ "lslash", "oslash", "oe", "germandbls", nil, nil, nil, nil,
97
+ ].freeze
98
+
99
+ MAC_ROMAN_ENCODING = [
100
+ "NUL", "Eth", "eth", "Lslash", "lslash", "Scaron", "scaron", "Yacute",
101
+ "yacute", "HT", "LF", "Thorn", "thorn", "CR", "Zcaron", "zcaron",
102
+ "DLE", "DC1", "DC2", "DC3", "DC4", "onehalf", "onequarter", "onesuperior",
103
+ "threequarters", "threesuperior", "twosuperior", "brokenbar", "minus", "multiply", "RS", "US",
104
+ "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quotesingle",
105
+ "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash",
106
+ "zero", "one", "two", "three", "four", "five", "six", "seven",
107
+ "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question",
108
+ "at", "A", "B", "C", "D", "E", "F", "G",
109
+ "H", "I", "J", "K", "L", "M", "N", "O",
110
+ "P", "Q", "R", "S", "T", "U", "V", "W",
111
+ "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
112
+ "grave", "a", "b", "c", "d", "e", "f", "g",
113
+ "h", "i", "j", "k", "l", "m", "n", "o",
114
+ "p", "q", "r", "s", "t", "u", "v", "w",
115
+ "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "DEL",
116
+ "Adieresis", "Aring", "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", "aacute",
117
+ "agrave", "acircumflex", "adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave",
118
+ "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", "idieresis", "ntilde", "oacute",
119
+ "ograve", "ocircumflex", "odieresis", "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
120
+ "dagger", "degree", "cent", "sterling", "section", "bullet", "paragraph", "germandbls",
121
+ "registered", "copyright", "trademark", "acute", "dieresis", "notequal", "AE", "Oslash",
122
+ "infinity", "plusminus", "lessequal", "greaterequal", "yen", "mu", "partialdiff", "summation",
123
+ "product", "pi", "integral", "ordfeminine", "ordmasculine", "Omega", "ae", "oslash",
124
+ "questiondown", "exclamdown", "logicalnot", "radical", "florin", "approxequal", "Delta", "guillemotleft",
125
+ "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde", "Otilde", "OE", "oe",
126
+ "endash", "emdash", "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", "lozenge",
127
+ "ydieresis", "Ydieresis", "fraction", "currency", "guilsinglleft", "guilsinglright", "fi", "fl",
128
+ "daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", "Ecircumflex", "Aacute",
129
+ "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
130
+ "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi", "circumflex", "tilde",
131
+ "macron", "breve", "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", "caron",
132
+ ].freeze
133
+
134
+ WIN_ANSI_ENCODING = [
135
+ nil, nil, nil, nil, nil, nil, nil, nil,
136
+ nil, nil, nil, nil, nil, nil, nil, nil,
137
+ nil, nil, nil, nil, nil, nil, nil, nil,
138
+ nil, nil, nil, nil, nil, nil, nil, nil,
139
+ "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quotesingle",
140
+ "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash",
141
+ "zero", "one", "two", "three", "four", "five", "six", "seven",
142
+ "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question",
143
+ "at", "A", "B", "C", "D", "E", "F", "G",
144
+ "H", "I", "J", "K", "L", "M", "N", "O",
145
+ "P", "Q", "R", "S", "T", "U", "V", "W",
146
+ "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
147
+ "grave", "a", "b", "c", "d", "e", "f", "g",
148
+ "h", "i", "j", "k", "l", "m", "n", "o",
149
+ "p", "q", "r", "s", "t", "u", "v", "w",
150
+ "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "bullet",
151
+ "Euro", "bullet", "quotesinglbase", "florin", "quotedblbase", "ellipsis", "dagger", "daggerdbl",
152
+ "circumflex", "perthousand", "Scaron", "guilsinglleft", "OE", "bullet", "Zcaron", "bullet",
153
+ "bullet", "quoteleft", "quoteright", "quotedblleft", "quotedblright", "bullet", "endash", "emdash",
154
+ "tilde", "trademark", "scaron", "guilsinglright", "oe", "bullet", "zcaron", "Ydieresis",
155
+ "space", "exclamdown", "cent", "sterling", "currency", "yen", "brokenbar", "section",
156
+ "dieresis", "copyright", "ordfeminine", "guillemotleft", "logicalnot", "hyphen", "registered", "macron",
157
+ "degree", "plusminus", "uni00B2", "uni00B3", "acute", "mu", "paragraph", "periodcentered",
158
+ "cedilla", "uni00B9", "ordmasculine", "guillemotright", "onequarter", "onehalf", "threequarters", "questiondown",
159
+ "Agrave", "Aacute", "Acircumflex", "Atilde", "Adieresis", "Aring", "AE", "Ccedilla",
160
+ "Egrave", "Eacute", "Ecircumflex", "Edieresis", "Igrave", "Iacute", "Icircumflex", "Idieresis",
161
+ "Eth", "Ntilde", "Ograve", "Oacute", "Ocircumflex", "Otilde", "Odieresis", "multiply",
162
+ "Oslash", "Ugrave", "Uacute", "Ucircumflex", "Udieresis", "Yacute", "Thorn", "germandbls",
163
+ "agrave", "aacute", "acircumflex", "atilde", "adieresis", "aring", "ae", "ccedilla",
164
+ "egrave", "eacute", "ecircumflex", "edieresis", "igrave", "iacute", "icircumflex", "idieresis",
165
+ "eth", "ntilde", "ograve", "oacute", "ocircumflex", "otilde", "odieresis", "divide",
166
+ "oslash", "ugrave", "uacute", "ucircumflex", "udieresis", "yacute", "thorn", "ydieresis",
167
+ ].freeze
168
+
169
+ # Glyph name -> Unicode code point (Adobe Glyph List).
170
+ UNICODE = {
171
+ "A" => 0x0041, "AE" => 0x00C6, "Aacute" => 0x00C1, "Acircumflex" => 0x00C2, "Adieresis" => 0x00C4,
172
+ "Agrave" => 0x00C0, "Aring" => 0x00C5, "Atilde" => 0x00C3, "B" => 0x0042, "C" => 0x0043,
173
+ "Ccedilla" => 0x00C7, "D" => 0x0044, "Delta" => 0x2206, "E" => 0x0045, "Eacute" => 0x00C9,
174
+ "Ecircumflex" => 0x00CA, "Edieresis" => 0x00CB, "Egrave" => 0x00C8, "Eth" => 0x00D0, "Euro" => 0x20AC,
175
+ "F" => 0x0046, "G" => 0x0047, "H" => 0x0048, "I" => 0x0049, "Iacute" => 0x00CD,
176
+ "Icircumflex" => 0x00CE, "Idieresis" => 0x00CF, "Igrave" => 0x00CC, "J" => 0x004A, "K" => 0x004B,
177
+ "L" => 0x004C, "Lslash" => 0x0141, "M" => 0x004D, "N" => 0x004E, "Ntilde" => 0x00D1,
178
+ "O" => 0x004F, "OE" => 0x0152, "Oacute" => 0x00D3, "Ocircumflex" => 0x00D4, "Odieresis" => 0x00D6,
179
+ "Ograve" => 0x00D2, "Omega" => 0x2126, "Oslash" => 0x00D8, "Otilde" => 0x00D5, "P" => 0x0050,
180
+ "Q" => 0x0051, "R" => 0x0052, "S" => 0x0053, "Scaron" => 0x0160, "T" => 0x0054,
181
+ "Thorn" => 0x00DE, "U" => 0x0055, "Uacute" => 0x00DA, "Ucircumflex" => 0x00DB, "Udieresis" => 0x00DC,
182
+ "Ugrave" => 0x00D9, "V" => 0x0056, "W" => 0x0057, "X" => 0x0058, "Y" => 0x0059,
183
+ "Yacute" => 0x00DD, "Ydieresis" => 0x0178, "Z" => 0x005A, "Zcaron" => 0x017D, "a" => 0x0061,
184
+ "aacute" => 0x00E1, "acircumflex" => 0x00E2, "acute" => 0x00B4, "adieresis" => 0x00E4, "ae" => 0x00E6,
185
+ "agrave" => 0x00E0, "ampersand" => 0x0026, "approxequal" => 0x2248, "aring" => 0x00E5, "asciicircum" => 0x005E,
186
+ "asciitilde" => 0x007E, "asterisk" => 0x002A, "at" => 0x0040, "atilde" => 0x00E3, "b" => 0x0062,
187
+ "backslash" => 0x005C, "bar" => 0x007C, "braceleft" => 0x007B, "braceright" => 0x007D, "bracketleft" => 0x005B,
188
+ "bracketright" => 0x005D, "breve" => 0x02D8, "brokenbar" => 0x00A6, "bullet" => 0x2022, "c" => 0x0063,
189
+ "caron" => 0x02C7, "ccedilla" => 0x00E7, "cedilla" => 0x00B8, "cent" => 0x00A2, "circumflex" => 0x02C6,
190
+ "colon" => 0x003A, "comma" => 0x002C, "copyright" => 0x00A9, "currency" => 0x00A4, "d" => 0x0064,
191
+ "dagger" => 0x2020, "daggerdbl" => 0x2021, "degree" => 0x00B0, "dieresis" => 0x00A8, "divide" => 0x00F7,
192
+ "dollar" => 0x0024, "dotaccent" => 0x02D9, "dotlessi" => 0x0131, "e" => 0x0065, "eacute" => 0x00E9,
193
+ "ecircumflex" => 0x00EA, "edieresis" => 0x00EB, "egrave" => 0x00E8, "eight" => 0x0038, "ellipsis" => 0x2026,
194
+ "emdash" => 0x2014, "endash" => 0x2013, "equal" => 0x003D, "eth" => 0x00F0, "exclam" => 0x0021,
195
+ "exclamdown" => 0x00A1, "f" => 0x0066, "five" => 0x0035, "florin" => 0x0192, "four" => 0x0034,
196
+ "fraction" => 0x2044, "g" => 0x0067, "germandbls" => 0x00DF, "grave" => 0x0060, "greater" => 0x003E,
197
+ "greaterequal" => 0x2265, "guillemotleft" => 0x00AB, "guillemotright" => 0x00BB, "guilsinglleft" => 0x2039, "guilsinglright" => 0x203A,
198
+ "h" => 0x0068, "hungarumlaut" => 0x02DD, "hyphen" => 0x002D, "i" => 0x0069, "iacute" => 0x00ED,
199
+ "icircumflex" => 0x00EE, "idieresis" => 0x00EF, "igrave" => 0x00EC, "infinity" => 0x221E, "integral" => 0x222B,
200
+ "j" => 0x006A, "k" => 0x006B, "l" => 0x006C, "less" => 0x003C, "lessequal" => 0x2264,
201
+ "logicalnot" => 0x00AC, "lozenge" => 0x25CA, "lslash" => 0x0142, "m" => 0x006D, "macron" => 0x00AF,
202
+ "minus" => 0x2212, "mu" => 0x00B5, "multiply" => 0x00D7, "n" => 0x006E, "nine" => 0x0039,
203
+ "notequal" => 0x2260, "ntilde" => 0x00F1, "numbersign" => 0x0023, "o" => 0x006F, "oacute" => 0x00F3,
204
+ "ocircumflex" => 0x00F4, "odieresis" => 0x00F6, "oe" => 0x0153, "ogonek" => 0x02DB, "ograve" => 0x00F2,
205
+ "one" => 0x0031, "onehalf" => 0x00BD, "onequarter" => 0x00BC, "ordfeminine" => 0x00AA, "ordmasculine" => 0x00BA,
206
+ "oslash" => 0x00F8, "otilde" => 0x00F5, "p" => 0x0070, "paragraph" => 0x00B6, "parenleft" => 0x0028,
207
+ "parenright" => 0x0029, "partialdiff" => 0x2202, "percent" => 0x0025, "period" => 0x002E, "periodcentered" => 0x00B7,
208
+ "perthousand" => 0x2030, "pi" => 0x03C0, "plus" => 0x002B, "plusminus" => 0x00B1, "product" => 0x220F,
209
+ "q" => 0x0071, "question" => 0x003F, "questiondown" => 0x00BF, "quotedbl" => 0x0022, "quotedblbase" => 0x201E,
210
+ "quotedblleft" => 0x201C, "quotedblright" => 0x201D, "quoteleft" => 0x2018, "quoteright" => 0x2019, "quotesinglbase" => 0x201A,
211
+ "quotesingle" => 0x0027, "r" => 0x0072, "radical" => 0x221A, "registered" => 0x00AE, "ring" => 0x02DA,
212
+ "s" => 0x0073, "scaron" => 0x0161, "section" => 0x00A7, "semicolon" => 0x003B, "seven" => 0x0037,
213
+ "six" => 0x0036, "slash" => 0x002F, "space" => 0x0020, "sterling" => 0x00A3, "summation" => 0x2211,
214
+ "t" => 0x0074, "thorn" => 0x00FE, "three" => 0x0033, "threequarters" => 0x00BE, "tilde" => 0x02DC,
215
+ "trademark" => 0x2122, "two" => 0x0032, "u" => 0x0075, "uacute" => 0x00FA, "ucircumflex" => 0x00FB,
216
+ "udieresis" => 0x00FC, "ugrave" => 0x00F9, "underscore" => 0x005F, "uni00B2" => 0x00B2, "uni00B3" => 0x00B3,
217
+ "uni00B9" => 0x00B9, "v" => 0x0076, "w" => 0x0077, "x" => 0x0078, "y" => 0x0079,
218
+ "yacute" => 0x00FD, "ydieresis" => 0x00FF, "yen" => 0x00A5, "z" => 0x007A, "zcaron" => 0x017E,
219
+ "zero" => 0x0030,
220
+ }.freeze
221
+ end
222
+ end
223
+ end
224
+ end
@@ -0,0 +1,412 @@
1
+ # frozen_string_literal: true
2
+
3
+ module QrReader
4
+ module Formats
5
+ module PDF
6
+ # A PDF font as drawing text in a barcode font needs it: the codes of
7
+ # a string, their widths, and the outline of each glyph (from the
8
+ # embedded font program) or its glyph procedure (Type 3). Fonts that
9
+ # are not embedded draw nothing.
10
+ #
11
+ # Only glyphs whose outlines are all right-angled polygons (see
12
+ # VectorRenderer.rectilinear?), as in barcode fonts, are returned by
13
+ # #glyph: ordinary text (with curves) never becomes part of a rendered
14
+ # code and costs only a lookup.
15
+ class Font
16
+ # Largest font program decoded.
17
+ PROGRAM_LIMIT = 1 << 24
18
+ # Most glyphs (outlines or procedures) prepared per font.
19
+ MAX_GLYPHS = 4096
20
+ IDENTITY = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0].freeze
21
+
22
+ # The Font of font dictionary +value+, or nil.
23
+ def self.load(doc, value)
24
+ dict = doc.dict_value(value)
25
+ dict ? new(doc, dict) : nil
26
+ rescue Error, *INTERNAL_ERRORS
27
+ nil
28
+ end
29
+
30
+ # Glyph space -> text space (Type 3: the FontMatrix).
31
+ attr_reader :matrix
32
+ # Resources of a Type 3 font's glyph procedures (nil: the page's).
33
+ attr_reader :resources
34
+
35
+ def initialize(doc, dict)
36
+ @doc = doc
37
+ @glyphs = {}
38
+ @matrix = IDENTITY
39
+ @widths = {}
40
+ @default_width = 0.0
41
+ @code_bytes = 1
42
+ case doc.resolve(dict[:Subtype])
43
+ when :Type3 then init_type3(dict)
44
+ when :Type0 then init_type0(dict)
45
+ else init_simple(dict)
46
+ end
47
+ end
48
+
49
+ def type3?
50
+ !@procs.nil?
51
+ end
52
+
53
+ # Yields code, width (text space, before the font size) and whether
54
+ # word spacing applies, for each character code of +string+.
55
+ def each_code(string)
56
+ if @ranges
57
+ pos = 0
58
+ while pos < string.bytesize
59
+ code, length = split(string, pos)
60
+ yield code, width(code), length == 1 && code == 32
61
+ pos += length
62
+ end
63
+ elsif @code_bytes == 2
64
+ pos = 0
65
+ while pos + 1 < string.bytesize
66
+ code = (string.getbyte(pos) << 8) | string.getbyte(pos + 1)
67
+ yield code, width(code), false
68
+ pos += 2
69
+ end
70
+ else
71
+ string.each_byte { |code| yield code, width(code), code == 32 }
72
+ end
73
+ end
74
+
75
+ # Outline of +code+ in text space (closed flat polygons) when it is
76
+ # made of module-like shapes, else nil.
77
+ def glyph(code)
78
+ return @glyphs[code] if @glyphs.key?(code)
79
+ return nil if @glyphs.size >= MAX_GLYPHS
80
+
81
+ @glyphs[code] = begin
82
+ polys = outline(code)
83
+ if polys && !polys.empty? && polys.all? { |p| VectorRenderer.rectilinear?(p) }
84
+ a, b, c, d, e, f = @matrix
85
+ polys.map do |p|
86
+ q = Array.new(p.size)
87
+ i = 0
88
+ while i < p.size
89
+ x = p[i]
90
+ y = p[i + 1]
91
+ q[i] = a * x + c * y + e
92
+ q[i + 1] = b * x + d * y + f
93
+ i += 2
94
+ end
95
+ q
96
+ end
97
+ end
98
+ rescue Error, *INTERNAL_ERRORS
99
+ nil
100
+ end
101
+ end
102
+
103
+ # Decoded content of the Type 3 glyph procedure of +code+, or nil.
104
+ def procedure(code)
105
+ return nil unless @procs
106
+ return @glyphs[code] if @glyphs.key?(code)
107
+ return nil if @glyphs.size >= MAX_GLYPHS
108
+
109
+ name = @names[code]
110
+ stream = name && @doc.resolve(@procs[name])
111
+ @glyphs[code] = stream.is_a?(Stream) ? @doc.content(stream) : nil
112
+ end
113
+
114
+ private
115
+
116
+ def value(dict, key)
117
+ @doc.resolve(dict[key])
118
+ end
119
+
120
+ def number(v)
121
+ Util.number(@doc.resolve(v))
122
+ end
123
+
124
+ # Widths of composite fonts are by CID.
125
+ def width(code)
126
+ @widths.fetch(@cids ? cid_for(code) : code, @default_width)
127
+ end
128
+
129
+ # --- Simple fonts (Type1, MMType1, TrueType) ------------------------
130
+
131
+ def init_simple(dict)
132
+ descriptor = @doc.dict_value(dict[:FontDescriptor]) || {}
133
+ @program, @kind = program(descriptor)
134
+ @names = encoding(dict)
135
+ @symbolic = ((Util.int(value(descriptor, :Flags)) || 0) & 4) != 0
136
+ read_simple_widths(dict, descriptor, 0.001)
137
+ @matrix = program_matrix
138
+ end
139
+
140
+ def read_simple_widths(dict, descriptor, scale)
141
+ first = Util.int(value(dict, :FirstChar)) || 0
142
+ widths = value(dict, :Widths)
143
+ if widths.is_a?(Array)
144
+ widths.first(256).each_with_index do |w, i|
145
+ w = number(w)
146
+ @widths[first + i] = w * scale if w
147
+ end
148
+ end
149
+ missing = number(value(descriptor, :MissingWidth))
150
+ @default_width = missing ? missing * scale : 0.0
151
+ end
152
+
153
+ # [program, kind] from a FontDescriptor (nil when not embedded).
154
+ def program(descriptor)
155
+ %i[FontFile FontFile2 FontFile3].each do |key|
156
+ stream = value(descriptor, key)
157
+ next unless stream.is_a?(Stream)
158
+
159
+ data = @doc.decode_stream(stream, PROGRAM_LIMIT)
160
+ return parse_program(data, stream.dict)
161
+ end
162
+ [nil, nil]
163
+ rescue Error, *INTERNAL_ERRORS
164
+ [nil, nil]
165
+ end
166
+
167
+ def parse_program(data, dict)
168
+ head = data.byteslice(0, 4)
169
+ if ["\x00\x01\x00\x00".b, "true", "OTTO"].include?(head)
170
+ [FontPrograms::TrueType.new(data), :truetype]
171
+ elsif data.start_with?("%!") || data.getbyte(0) == 0x80
172
+ data, clear = pfb(data)
173
+ [FontPrograms::Type1.new(data, clear || Util.int(@doc.resolve(dict[:Length1]))), :type1]
174
+ else
175
+ [FontPrograms::CFF.new(data), :cff]
176
+ end
177
+ end
178
+
179
+ # PFB segments joined; [data, length of the clear-text part].
180
+ def pfb(data)
181
+ return [data, nil] unless data.getbyte(0) == 0x80
182
+
183
+ out = String.new(encoding: Encoding::BINARY)
184
+ clear = nil
185
+ pos = 0
186
+ while data.getbyte(pos) == 0x80 && [1, 2].include?(data.getbyte(pos + 1))
187
+ length = data.byteslice(pos + 2, 4).unpack1("V")
188
+ out << data.byteslice(pos + 6, length).to_s
189
+ clear ||= out.bytesize
190
+ pos += 6 + length
191
+ end
192
+ [out, clear]
193
+ end
194
+
195
+ def program_matrix
196
+ upem = @program.respond_to?(:units_per_em) && !@program.cff ? @program.units_per_em : nil
197
+ return [1.0 / upem, 0.0, 0.0, 1.0 / upem, 0.0, 0.0] if upem
198
+
199
+ cff = @program.respond_to?(:cff) ? @program.cff : @program
200
+ m = cff.respond_to?(:font_matrix) ? cff.font_matrix : nil
201
+ m.is_a?(Array) && m.size == 6 && m.all?(Numeric) ? m.map(&:to_f) : [0.001, 0.0, 0.0, 0.001, 0.0, 0.0]
202
+ end
203
+
204
+ # code -> glyph name from /Encoding (Differences over a base
205
+ # encoding over the font program's own).
206
+ def encoding(dict)
207
+ names = Array.new(256)
208
+ builtin = @program.is_a?(FontPrograms::Type1) ? @program.encoding : nil
209
+ case builtin
210
+ when :standard then FontTables::STANDARD_ENCODING.each_with_index { |name, code| names[code] = name }
211
+ when Hash then builtin.each { |code, name| names[code] = name if code < 256 }
212
+ end
213
+ enc = value(dict, :Encoding)
214
+ base = enc.is_a?(Hash) ? value(enc, :BaseEncoding) : enc
215
+ if (table = base_table(base))
216
+ table.each_with_index { |name, code| names[code] = name if name }
217
+ end
218
+ if enc.is_a?(Hash) && (diffs = value(enc, :Differences)).is_a?(Array)
219
+ code = 0
220
+ diffs.each do |item|
221
+ item = @doc.resolve(item)
222
+ case item
223
+ when Integer then code = item
224
+ when Symbol
225
+ names[code] = item.to_s if code.between?(0, 255)
226
+ code += 1
227
+ end
228
+ end
229
+ end
230
+ names
231
+ end
232
+
233
+ def base_table(name)
234
+ case name
235
+ when :WinAnsiEncoding then FontTables::WIN_ANSI_ENCODING
236
+ when :MacRomanEncoding then FontTables::MAC_ROMAN_ENCODING
237
+ when :StandardEncoding then FontTables::STANDARD_ENCODING
238
+ end
239
+ end
240
+
241
+ # Glyph outline of +code+ in glyph space.
242
+ def outline(code)
243
+ return nil unless @program
244
+
245
+ if @cid_font
246
+ gid = cid_gid(cid_for(code)) or return nil
247
+ return @program.outline(gid)
248
+ end
249
+ name = @names[code]
250
+ case @kind
251
+ when :type1
252
+ @program.outline(name) if name
253
+ when :cff
254
+ gid = (name && @program.gid_for_name(name)) || @program.gid_for_code(code)
255
+ gid ? @program.outline(gid) : nil
256
+ when :truetype
257
+ gid = truetype_gid(code, name) or return nil
258
+ @program.outline(gid)
259
+ end
260
+ end
261
+
262
+ def truetype_gid(code, name)
263
+ tt = @program
264
+ if @symbolic || !name
265
+ [code, 0xF000 | code, 0xF100 | code, 0xF200 | code].each do |c|
266
+ gid = tt.lookup(3, 0, c) and return gid
267
+ end
268
+ gid = tt.lookup(1, 0, code) and return gid
269
+ end
270
+ if name
271
+ unicode = FontTables::UNICODE[name] || name[/\Auni(\h{4})\z/, 1]&.hex || name[/\Au(\h{4,6})\z/, 1]&.hex
272
+ gid = unicode && tt.lookup(3, 1, unicode) and return gid
273
+ gid = tt.cff&.gid_for_name(name) and return gid
274
+ end
275
+ gid = tt.lookup(3, 1, code) and return gid
276
+ code.positive? && code < tt.glyph_count ? code : nil
277
+ end
278
+
279
+ # --- Type 3 ---------------------------------------------------------
280
+
281
+ def init_type3(dict)
282
+ m = value(dict, :FontMatrix)
283
+ m = m.map { |v| number(v) } if m.is_a?(Array)
284
+ @matrix = m.is_a?(Array) && m.size == 6 && m.none?(&:nil?) ? m : [0.001, 0.0, 0.0, 0.001, 0.0, 0.0]
285
+ @procs = @doc.dict_value(dict[:CharProcs]) || {}
286
+ @resources = dict[:Resources]
287
+ @names = Array.new(256)
288
+ enc = @doc.dict_value(dict[:Encoding])
289
+ if enc && (diffs = value(enc, :Differences)).is_a?(Array)
290
+ code = 0
291
+ diffs.each do |item|
292
+ item = @doc.resolve(item)
293
+ case item
294
+ when Integer then code = item
295
+ when Symbol
296
+ @names[code] = item if code.between?(0, 255)
297
+ code += 1
298
+ end
299
+ end
300
+ end
301
+ # Widths are in glyph space.
302
+ read_simple_widths(dict, {}, @matrix[0])
303
+ end
304
+
305
+ # --- Type 0 (composite) ---------------------------------------------
306
+
307
+ def init_type0(dict)
308
+ descendant = value(dict, :DescendantFonts)
309
+ cid = @doc.dict_value(descendant.is_a?(Array) ? descendant.first : descendant) || {}
310
+ descriptor = @doc.dict_value(cid[:FontDescriptor]) || {}
311
+ @program, @kind = program(descriptor)
312
+ @cid_font = true
313
+ @matrix = @program ? program_matrix : IDENTITY
314
+ read_cmap(value(dict, :Encoding))
315
+ map = value(cid, :CIDToGIDMap)
316
+ @cid_to_gid = map.is_a?(Stream) ? @doc.decode_stream(map, 1 << 18) : nil
317
+ read_cid_widths(cid)
318
+ end
319
+
320
+ # Identity-H/V and other predefined CMaps: 2-byte codes, CID = code;
321
+ # embedded CMaps: their code space and CID ranges.
322
+ def read_cmap(enc)
323
+ @code_bytes = 2
324
+ return unless enc.is_a?(Stream)
325
+
326
+ text = @doc.decode_stream(enc, 1 << 20)
327
+ @ranges = []
328
+ text.scan(/begincodespacerange(.*?)endcodespacerange/m) do |(body)|
329
+ body.scan(/<(\h+)>\s*<(\h+)>/) { |lo, hi| @ranges << [lo.size / 2, lo.hex, hi.hex] if lo.size == hi.size }
330
+ end
331
+ @ranges = nil if @ranges.empty?
332
+ @cids = []
333
+ text.scan(/begincidrange(.*?)endcidrange/m) do |(body)|
334
+ body.scan(/<(\h+)>\s*<(\h+)>\s*(\d+)/) { |lo, hi, cid| @cids << [lo.hex, hi.hex, cid.to_i] }
335
+ end
336
+ text.scan(/begincidchar(.*?)endcidchar/m) do |(body)|
337
+ body.scan(/<(\h+)>\s*(\d+)/) { |c, cid| @cids << [c.hex, c.hex, cid.to_i] }
338
+ end
339
+ @cids = nil if @cids.empty?
340
+ end
341
+
342
+ # [code, length] of the code at +pos+ (code space ranges).
343
+ def split(string, pos)
344
+ (1..4).each do |n|
345
+ break if pos + n > string.bytesize
346
+
347
+ code = 0
348
+ n.times { |i| code = (code << 8) | string.getbyte(pos + i) }
349
+ return [code, n] if @ranges.any? { |len, lo, hi| len == n && code.between?(lo, hi) }
350
+ end
351
+ [string.getbyte(pos), 1]
352
+ end
353
+
354
+ def cid_for(code)
355
+ return code unless @cids
356
+
357
+ @cids.each { |lo, hi, cid| return cid + code - lo if code.between?(lo, hi) }
358
+ 0
359
+ end
360
+
361
+ def cid_gid(cid)
362
+ if @cid_to_gid
363
+ return nil if 2 * cid + 1 >= @cid_to_gid.bytesize
364
+
365
+ return (@cid_to_gid.getbyte(2 * cid) << 8) | @cid_to_gid.getbyte(2 * cid + 1)
366
+ end
367
+ if @kind == :cff && @program.cid?
368
+ @program.gid_for_cid(cid)
369
+ elsif @program.is_a?(FontPrograms::TrueType) && @program.cff&.cid?
370
+ @program.cff.gid_for_cid(cid)
371
+ else
372
+ cid
373
+ end
374
+ end
375
+
376
+ def read_cid_widths(cid)
377
+ dw = number(value(cid, :DW))
378
+ @default_width = (dw || 1000.0) * 0.001
379
+ w = value(cid, :W)
380
+ return unless w.is_a?(Array)
381
+
382
+ i = 0
383
+ entries = 0
384
+ while i < w.size && entries < 65_536
385
+ first = Util.int(@doc.resolve(w[i]))
386
+ nxt = @doc.resolve(w[i + 1])
387
+ break unless first
388
+
389
+ if nxt.is_a?(Array)
390
+ nxt.each_with_index do |v, j|
391
+ v = number(v)
392
+ @widths[first + j] = v * 0.001 if v
393
+ entries += 1
394
+ end
395
+ i += 2
396
+ else
397
+ last = Util.int(nxt)
398
+ v = number(w[i + 2])
399
+ break unless last && v
400
+
401
+ (first..[last, first + 65_536].min).each { |c| @widths[c] = v * 0.001 }
402
+ entries += last - first + 1
403
+ i += 3
404
+ end
405
+ end
406
+ end
407
+ end
408
+
409
+ private_constant :Font, :FontPrograms, :FontTables
410
+ end
411
+ end
412
+ end