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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/README.md +23 -7
- data/exe/qr_reader +1 -1
- data/lib/qr_reader/formats/jpeg.rb +61 -2
- data/lib/qr_reader/formats/jpeg2000/codestream.rb +447 -0
- data/lib/qr_reader/formats/jpeg2000/container.rb +156 -0
- data/lib/qr_reader/formats/jpeg2000/dwt.rb +607 -0
- data/lib/qr_reader/formats/jpeg2000/tier1.rb +1084 -0
- data/lib/qr_reader/formats/jpeg2000/tile.rb +722 -0
- data/lib/qr_reader/formats/jpeg2000.rb +764 -0
- data/lib/qr_reader/formats/pdf/font_programs.rb +1205 -0
- data/lib/qr_reader/formats/pdf/font_tables.rb +224 -0
- data/lib/qr_reader/formats/pdf/fonts.rb +412 -0
- data/lib/qr_reader/formats/pdf/text.rb +151 -0
- data/lib/qr_reader/formats/pdf/vector.rb +799 -0
- data/lib/qr_reader/formats/pdf.rb +183 -44
- data/lib/qr_reader/formats.rb +13 -4
- data/lib/qr_reader/reader.rb +36 -10
- data/lib/qr_reader/version.rb +1 -1
- data/lib/qr_reader.rb +1 -1
- metadata +15 -4
|
@@ -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
|