ttfunk 1.5.1 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +60 -0
- data/README.md +2 -1
- data/lib/ttfunk.rb +45 -0
- data/lib/ttfunk/aggregate.rb +15 -0
- data/lib/ttfunk/bin_utils.rb +47 -0
- data/lib/ttfunk/bit_field.rb +31 -0
- data/lib/ttfunk/collection.rb +3 -1
- data/lib/ttfunk/directory.rb +6 -0
- data/lib/ttfunk/encoded_string.rb +97 -0
- data/lib/ttfunk/max.rb +25 -0
- data/lib/ttfunk/min.rb +25 -0
- data/lib/ttfunk/one_based_array.rb +36 -0
- data/lib/ttfunk/otf_encoder.rb +61 -0
- data/lib/ttfunk/placeholder.rb +13 -0
- data/lib/ttfunk/reader.rb +34 -32
- data/lib/ttfunk/resource_file.rb +7 -5
- data/lib/ttfunk/sci_form.rb +29 -0
- data/lib/ttfunk/sub_table.rb +38 -0
- data/lib/ttfunk/subset.rb +2 -0
- data/lib/ttfunk/subset/base.rb +61 -120
- data/lib/ttfunk/subset/code_page.rb +89 -0
- data/lib/ttfunk/subset/mac_roman.rb +5 -42
- data/lib/ttfunk/subset/unicode.rb +12 -6
- data/lib/ttfunk/subset/unicode_8bit.rb +14 -12
- data/lib/ttfunk/subset/windows_1252.rb +5 -47
- data/lib/ttfunk/subset_collection.rb +4 -0
- data/lib/ttfunk/sum.rb +20 -0
- data/lib/ttfunk/table.rb +4 -0
- data/lib/ttfunk/table/cff.rb +69 -0
- data/lib/ttfunk/table/cff/charset.rb +212 -0
- data/lib/ttfunk/table/cff/charsets.rb +14 -0
- data/lib/ttfunk/table/cff/charsets/expert.rb +189 -0
- data/lib/ttfunk/table/cff/charsets/expert_subset.rb +119 -0
- data/lib/ttfunk/table/cff/charsets/iso_adobe.rb +241 -0
- data/lib/ttfunk/table/cff/charsets/standard_strings.rb +404 -0
- data/lib/ttfunk/table/cff/charstring.rb +487 -0
- data/lib/ttfunk/table/cff/charstrings_index.rb +39 -0
- data/lib/ttfunk/table/cff/dict.rb +266 -0
- data/lib/ttfunk/table/cff/encoding.rb +220 -0
- data/lib/ttfunk/table/cff/encodings.rb +12 -0
- data/lib/ttfunk/table/cff/encodings/expert.rb +206 -0
- data/lib/ttfunk/table/cff/encodings/standard.rb +181 -0
- data/lib/ttfunk/table/cff/fd_selector.rb +150 -0
- data/lib/ttfunk/table/cff/font_dict.rb +79 -0
- data/lib/ttfunk/table/cff/font_index.rb +29 -0
- data/lib/ttfunk/table/cff/header.rb +33 -0
- data/lib/ttfunk/table/cff/index.rb +125 -0
- data/lib/ttfunk/table/cff/one_based_index.rb +31 -0
- data/lib/ttfunk/table/cff/path.rb +66 -0
- data/lib/ttfunk/table/cff/private_dict.rb +84 -0
- data/lib/ttfunk/table/cff/subr_index.rb +19 -0
- data/lib/ttfunk/table/cff/top_dict.rb +230 -0
- data/lib/ttfunk/table/cff/top_index.rb +16 -0
- data/lib/ttfunk/table/cmap.rb +4 -4
- data/lib/ttfunk/table/cmap/format00.rb +1 -2
- data/lib/ttfunk/table/cmap/format04.rb +11 -3
- data/lib/ttfunk/table/cmap/format06.rb +2 -0
- data/lib/ttfunk/table/cmap/format10.rb +2 -0
- data/lib/ttfunk/table/cmap/format12.rb +2 -0
- data/lib/ttfunk/table/cmap/subtable.rb +12 -8
- data/lib/ttfunk/table/dsig.rb +50 -0
- data/lib/ttfunk/table/glyf.rb +11 -9
- data/lib/ttfunk/table/glyf/compound.rb +14 -7
- data/lib/ttfunk/table/glyf/path_based.rb +47 -0
- data/lib/ttfunk/table/glyf/simple.rb +21 -15
- data/lib/ttfunk/table/head.rb +43 -5
- data/lib/ttfunk/table/hhea.rb +47 -4
- data/lib/ttfunk/table/hmtx.rb +11 -4
- data/lib/ttfunk/table/kern.rb +3 -0
- data/lib/ttfunk/table/kern/format0.rb +3 -0
- data/lib/ttfunk/table/loca.rb +2 -0
- data/lib/ttfunk/table/maxp.rb +144 -10
- data/lib/ttfunk/table/name.rb +75 -37
- data/lib/ttfunk/table/os2.rb +327 -4
- data/lib/ttfunk/table/post.rb +8 -1
- data/lib/ttfunk/table/post/format10.rb +2 -0
- data/lib/ttfunk/table/post/format20.rb +5 -1
- data/lib/ttfunk/table/post/format30.rb +2 -0
- data/lib/ttfunk/table/post/format40.rb +2 -0
- data/lib/ttfunk/table/sbix.rb +2 -0
- data/lib/ttfunk/table/simple.rb +2 -0
- data/lib/ttfunk/table/vorg.rb +54 -0
- data/lib/ttfunk/ttf_encoder.rb +220 -0
- metadata +88 -20
- metadata.gz.sig +0 -0
- data/lib/ttfunk/encoding/mac_roman.rb +0 -100
- data/lib/ttfunk/encoding/windows_1252.rb +0 -76
@@ -0,0 +1,404 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TTFunk
|
4
|
+
class Table
|
5
|
+
class Cff < TTFunk::Table
|
6
|
+
module Charsets
|
7
|
+
STANDARD_STRINGS = OneBasedArray.new(
|
8
|
+
[
|
9
|
+
'space',
|
10
|
+
'exclam',
|
11
|
+
'quotedbl',
|
12
|
+
'numbersign',
|
13
|
+
'dollar',
|
14
|
+
'percent',
|
15
|
+
'ampersand',
|
16
|
+
'quoteright',
|
17
|
+
'parenleft',
|
18
|
+
'parenright',
|
19
|
+
'asterisk',
|
20
|
+
'plus',
|
21
|
+
'comma',
|
22
|
+
'hyphen',
|
23
|
+
'period',
|
24
|
+
'slash',
|
25
|
+
'zero',
|
26
|
+
'one',
|
27
|
+
'two',
|
28
|
+
'three',
|
29
|
+
'four',
|
30
|
+
'five',
|
31
|
+
'six',
|
32
|
+
'seven',
|
33
|
+
'eight',
|
34
|
+
'nine',
|
35
|
+
'colon',
|
36
|
+
'semicolon',
|
37
|
+
'less',
|
38
|
+
'equal',
|
39
|
+
'greater',
|
40
|
+
'question',
|
41
|
+
'at',
|
42
|
+
'A',
|
43
|
+
'B',
|
44
|
+
'C',
|
45
|
+
'D',
|
46
|
+
'E',
|
47
|
+
'F',
|
48
|
+
'G',
|
49
|
+
'H',
|
50
|
+
'I',
|
51
|
+
'J',
|
52
|
+
'K',
|
53
|
+
'L',
|
54
|
+
'M',
|
55
|
+
'N',
|
56
|
+
'O',
|
57
|
+
'P',
|
58
|
+
'Q',
|
59
|
+
'R',
|
60
|
+
'S',
|
61
|
+
'T',
|
62
|
+
'U',
|
63
|
+
'V',
|
64
|
+
'W',
|
65
|
+
'X',
|
66
|
+
'Y',
|
67
|
+
'Z',
|
68
|
+
'bracketleft',
|
69
|
+
'backslash',
|
70
|
+
'bracketright',
|
71
|
+
'asciicircum',
|
72
|
+
'underscore',
|
73
|
+
'quoteleft',
|
74
|
+
'a',
|
75
|
+
'b',
|
76
|
+
'c',
|
77
|
+
'd',
|
78
|
+
'e',
|
79
|
+
'f',
|
80
|
+
'g',
|
81
|
+
'h',
|
82
|
+
'i',
|
83
|
+
'j',
|
84
|
+
'k',
|
85
|
+
'l',
|
86
|
+
'm',
|
87
|
+
'n',
|
88
|
+
'o',
|
89
|
+
'p',
|
90
|
+
'q',
|
91
|
+
'r',
|
92
|
+
's',
|
93
|
+
't',
|
94
|
+
'u',
|
95
|
+
'v',
|
96
|
+
'w',
|
97
|
+
'x',
|
98
|
+
'y',
|
99
|
+
'z',
|
100
|
+
'braceleft',
|
101
|
+
'bar',
|
102
|
+
'braceright',
|
103
|
+
'asciitilde',
|
104
|
+
'exclamdown',
|
105
|
+
'cent',
|
106
|
+
'sterling',
|
107
|
+
'fraction',
|
108
|
+
'yen',
|
109
|
+
'florin',
|
110
|
+
'section',
|
111
|
+
'currency',
|
112
|
+
'quotesingle',
|
113
|
+
'quotedblleft',
|
114
|
+
'guillemotleft',
|
115
|
+
'guilsinglleft',
|
116
|
+
'guilsinglright',
|
117
|
+
'fi',
|
118
|
+
'fl',
|
119
|
+
'endash',
|
120
|
+
'dagger',
|
121
|
+
'daggerdbl',
|
122
|
+
'periodcentered',
|
123
|
+
'paragraph',
|
124
|
+
'bullet',
|
125
|
+
'quotesinglbase',
|
126
|
+
'quotedblbase',
|
127
|
+
'quotedblright',
|
128
|
+
'guillemotright',
|
129
|
+
'ellipsis',
|
130
|
+
'perthousand',
|
131
|
+
'questiondown',
|
132
|
+
'grave',
|
133
|
+
'acute',
|
134
|
+
'circumflex',
|
135
|
+
'tilde',
|
136
|
+
'macron',
|
137
|
+
'breve',
|
138
|
+
'dotaccent',
|
139
|
+
'dieresis',
|
140
|
+
'ring',
|
141
|
+
'cedilla',
|
142
|
+
'hungarumlaut',
|
143
|
+
'ogonek',
|
144
|
+
'caron',
|
145
|
+
'emdash',
|
146
|
+
'AE',
|
147
|
+
'ordfeminine',
|
148
|
+
'Lslash',
|
149
|
+
'Oslash',
|
150
|
+
'OE',
|
151
|
+
'ordmasculine',
|
152
|
+
'ae',
|
153
|
+
'dotlessi',
|
154
|
+
'lslash',
|
155
|
+
'oslash',
|
156
|
+
'oe',
|
157
|
+
'germandbls',
|
158
|
+
'onesuperior',
|
159
|
+
'logicalnot',
|
160
|
+
'mu',
|
161
|
+
'trademark',
|
162
|
+
'Eth',
|
163
|
+
'onehalf',
|
164
|
+
'plusminus',
|
165
|
+
'Thorn',
|
166
|
+
'onequarter',
|
167
|
+
'divide',
|
168
|
+
'brokenbar',
|
169
|
+
'degree',
|
170
|
+
'thorn',
|
171
|
+
'threequarters',
|
172
|
+
'twosuperior',
|
173
|
+
'registered',
|
174
|
+
'minus',
|
175
|
+
'eth',
|
176
|
+
'multiply',
|
177
|
+
'threesuperior',
|
178
|
+
'copyright',
|
179
|
+
'Aacute',
|
180
|
+
'Acircumflex',
|
181
|
+
'Adieresis',
|
182
|
+
'Agrave',
|
183
|
+
'Aring',
|
184
|
+
'Atilde',
|
185
|
+
'Ccedilla',
|
186
|
+
'Eacute',
|
187
|
+
'Ecircumflex',
|
188
|
+
'Edieresis',
|
189
|
+
'Egrave',
|
190
|
+
'Iacute',
|
191
|
+
'Icircumflex',
|
192
|
+
'Idieresis',
|
193
|
+
'Igrave',
|
194
|
+
'Ntilde',
|
195
|
+
'Oacute',
|
196
|
+
'Ocircumflex',
|
197
|
+
'Odieresis',
|
198
|
+
'Ograve',
|
199
|
+
'Otilde',
|
200
|
+
'Scaron',
|
201
|
+
'Uacute',
|
202
|
+
'Ucircumflex',
|
203
|
+
'Udieresis',
|
204
|
+
'Ugrave',
|
205
|
+
'Yacute',
|
206
|
+
'Ydieresis',
|
207
|
+
'Zcaron',
|
208
|
+
'aacute',
|
209
|
+
'acircumflex',
|
210
|
+
'adieresis',
|
211
|
+
'agrave',
|
212
|
+
'aring',
|
213
|
+
'atilde',
|
214
|
+
'ccedilla',
|
215
|
+
'eacute',
|
216
|
+
'ecircumflex',
|
217
|
+
'edieresis',
|
218
|
+
'egrave',
|
219
|
+
'iacute',
|
220
|
+
'icircumflex',
|
221
|
+
'idieresis',
|
222
|
+
'igrave',
|
223
|
+
'ntilde',
|
224
|
+
'oacute',
|
225
|
+
'ocircumflex',
|
226
|
+
'odieresis',
|
227
|
+
'ograve',
|
228
|
+
'otilde',
|
229
|
+
'scaron',
|
230
|
+
'uacute',
|
231
|
+
'ucircumflex',
|
232
|
+
'udieresis',
|
233
|
+
'ugrave',
|
234
|
+
'yacute',
|
235
|
+
'ydieresis',
|
236
|
+
'zcaron',
|
237
|
+
'exclamsmall',
|
238
|
+
'Hungarumlautsmall',
|
239
|
+
'dollaroldstyle',
|
240
|
+
'dollarsuperior',
|
241
|
+
'ampersandsmall',
|
242
|
+
'Acutesmall',
|
243
|
+
'parenleftsuperior',
|
244
|
+
'parenrightsuperior',
|
245
|
+
'266 ff',
|
246
|
+
'onedotenleader',
|
247
|
+
'zerooldstyle',
|
248
|
+
'oneoldstyle',
|
249
|
+
'twooldstyle',
|
250
|
+
'threeoldstyle',
|
251
|
+
'fouroldstyle',
|
252
|
+
'fiveoldstyle',
|
253
|
+
'sixoldstyle',
|
254
|
+
'sevenoldstyle',
|
255
|
+
'eightoldstyle',
|
256
|
+
'nineoldstyle',
|
257
|
+
'commasuperior',
|
258
|
+
'threequartersemdash',
|
259
|
+
'periodsuperior',
|
260
|
+
'questionsmall',
|
261
|
+
'asuperior',
|
262
|
+
'bsuperior',
|
263
|
+
'centsuperior',
|
264
|
+
'dsuperior',
|
265
|
+
'esuperior',
|
266
|
+
'isuperior',
|
267
|
+
'lsuperior',
|
268
|
+
'msuperior',
|
269
|
+
'nsuperior',
|
270
|
+
'osuperior',
|
271
|
+
'rsuperior',
|
272
|
+
'ssuperior',
|
273
|
+
'tsuperior',
|
274
|
+
'ff',
|
275
|
+
'ffi',
|
276
|
+
'ffl',
|
277
|
+
'parenleftinferior',
|
278
|
+
'parenrightinferior',
|
279
|
+
'Circumflexsmall',
|
280
|
+
'hyphensuperior',
|
281
|
+
'Gravesmall',
|
282
|
+
'Asmall',
|
283
|
+
'Bsmall',
|
284
|
+
'Csmall',
|
285
|
+
'Dsmall',
|
286
|
+
'Esmall',
|
287
|
+
'Fsmall',
|
288
|
+
'Gsmall',
|
289
|
+
'Hsmall',
|
290
|
+
'Ismall',
|
291
|
+
'Jsmall',
|
292
|
+
'Ksmall',
|
293
|
+
'Lsmall',
|
294
|
+
'Msmall',
|
295
|
+
'Nsmall',
|
296
|
+
'Osmall',
|
297
|
+
'Psmall',
|
298
|
+
'Qsmall',
|
299
|
+
'Rsmall',
|
300
|
+
'Ssmall',
|
301
|
+
'Tsmall',
|
302
|
+
'Usmall',
|
303
|
+
'Vsmall',
|
304
|
+
'Wsmall',
|
305
|
+
'Xsmall',
|
306
|
+
'Ysmall',
|
307
|
+
'Zsmall',
|
308
|
+
'colonmonetary',
|
309
|
+
'onefitted',
|
310
|
+
'rupiah',
|
311
|
+
'Tildesmall',
|
312
|
+
'exclamdownsmall',
|
313
|
+
'centoldstyle',
|
314
|
+
'Lslashsmall',
|
315
|
+
'Scaronsmall',
|
316
|
+
'Zcaronsmall',
|
317
|
+
'Dieresissmall',
|
318
|
+
'Brevesmall',
|
319
|
+
'Caronsmall',
|
320
|
+
'Dotaccentsmall',
|
321
|
+
'Macronsmall',
|
322
|
+
'figuredash',
|
323
|
+
'hypheninferior',
|
324
|
+
'Ogoneksmall',
|
325
|
+
'Ringsmall',
|
326
|
+
'Cedillasmall',
|
327
|
+
'questiondownsmall',
|
328
|
+
'oneeighth',
|
329
|
+
'threeeighths',
|
330
|
+
'fiveeighths',
|
331
|
+
'seveneighths',
|
332
|
+
'onethird',
|
333
|
+
'twothirds',
|
334
|
+
'zerosuperior',
|
335
|
+
'foursuperior',
|
336
|
+
'fivesuperior',
|
337
|
+
'sixsuperior',
|
338
|
+
'sevensuperior',
|
339
|
+
'eightsuperior',
|
340
|
+
'ninesuperior',
|
341
|
+
'zeroinferior',
|
342
|
+
'oneinferior',
|
343
|
+
'twoinferior',
|
344
|
+
'threeinferior',
|
345
|
+
'fourinferior',
|
346
|
+
'fiveinferior',
|
347
|
+
'sixinferior',
|
348
|
+
'seveninferior',
|
349
|
+
'eightinferior',
|
350
|
+
'nineinferior',
|
351
|
+
'centinferior',
|
352
|
+
'dollarinferior',
|
353
|
+
'periodinferior',
|
354
|
+
'commainferior',
|
355
|
+
'Agravesmall',
|
356
|
+
'Aacutesmall',
|
357
|
+
'Acircumflexsmall',
|
358
|
+
'Atildesmall',
|
359
|
+
'Adieresissmall',
|
360
|
+
'Aringsmall',
|
361
|
+
'AEsmall',
|
362
|
+
'Ccedillasmall',
|
363
|
+
'Egravesmall',
|
364
|
+
'Eacutesmall',
|
365
|
+
'Ecircumflexsmall',
|
366
|
+
'Edieresissmall',
|
367
|
+
'Igravesmall',
|
368
|
+
'Iacutesmall',
|
369
|
+
'Icircumflexsmall',
|
370
|
+
'Idieresissmall',
|
371
|
+
'Ethsmall',
|
372
|
+
'Ntildesmall',
|
373
|
+
'Ogravesmall',
|
374
|
+
'Oacutesmall',
|
375
|
+
'Ocircumflexsmall',
|
376
|
+
'Otildesmall',
|
377
|
+
'Odieresissmall',
|
378
|
+
'OEsmall',
|
379
|
+
'Oslashsmall',
|
380
|
+
'Ugravesmall',
|
381
|
+
'Uacutesmall',
|
382
|
+
'Ucircumflexsmall',
|
383
|
+
'Udieresissmall',
|
384
|
+
'Yacutesmall',
|
385
|
+
'Thornsmall',
|
386
|
+
'Ydieresissmall',
|
387
|
+
'001.000',
|
388
|
+
'001.001',
|
389
|
+
'001.002',
|
390
|
+
'001.003',
|
391
|
+
'Black',
|
392
|
+
'Bold',
|
393
|
+
'Book',
|
394
|
+
'Light',
|
395
|
+
'Medium',
|
396
|
+
'Regular',
|
397
|
+
'Roman',
|
398
|
+
'Semibold'
|
399
|
+
]
|
400
|
+
).freeze
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
@@ -0,0 +1,487 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TTFunk
|
4
|
+
class Table
|
5
|
+
class Cff < TTFunk::Table
|
6
|
+
class Charstring
|
7
|
+
CODE_MAP = {
|
8
|
+
1 => :hstem,
|
9
|
+
3 => :vstem,
|
10
|
+
4 => :vmoveto,
|
11
|
+
5 => :rlineto,
|
12
|
+
6 => :hlineto,
|
13
|
+
7 => :vlineto,
|
14
|
+
8 => :rrcurveto,
|
15
|
+
10 => :callsubr,
|
16
|
+
12 => :flex_select,
|
17
|
+
14 => :endchar,
|
18
|
+
18 => :hstemhm,
|
19
|
+
19 => :hintmask,
|
20
|
+
20 => :cntrmask,
|
21
|
+
21 => :rmoveto,
|
22
|
+
22 => :hmoveto,
|
23
|
+
23 => :vstemhm,
|
24
|
+
24 => :rcurveline,
|
25
|
+
25 => :rlinecurve,
|
26
|
+
26 => :vvcurveto,
|
27
|
+
27 => :hhcurveto,
|
28
|
+
28 => :shortint,
|
29
|
+
29 => :callgsubr,
|
30
|
+
30 => :vhcurveto,
|
31
|
+
31 => :hvcurveto
|
32
|
+
}.freeze
|
33
|
+
|
34
|
+
FLEX_CODE_MAP = {
|
35
|
+
35 => :flex,
|
36
|
+
34 => :hflex,
|
37
|
+
36 => :hflex1,
|
38
|
+
37 => :flex1
|
39
|
+
}.freeze
|
40
|
+
|
41
|
+
attr_reader :glyph_id, :raw
|
42
|
+
|
43
|
+
def initialize(glyph_id, top_dict, font_dict, raw)
|
44
|
+
@glyph_id = glyph_id
|
45
|
+
@top_dict = top_dict
|
46
|
+
@font_dict = font_dict
|
47
|
+
@raw = raw
|
48
|
+
|
49
|
+
default_width_x = (@font_dict || @top_dict)
|
50
|
+
.private_dict.default_width_x
|
51
|
+
|
52
|
+
@nominal_width_x = (@font_dict || @top_dict)
|
53
|
+
.private_dict.nominal_width_x
|
54
|
+
|
55
|
+
@subrs = (@font_dict || @top_dict).private_dict.subr_index
|
56
|
+
@gsubrs = @top_dict.cff.global_subr_index
|
57
|
+
@subrs_bias = @subrs.bias if @subrs
|
58
|
+
@gsubrs_bias = @gsubrs.bias if @gsubrs
|
59
|
+
|
60
|
+
@stack = []
|
61
|
+
@data = raw.bytes
|
62
|
+
@index = 0
|
63
|
+
@n_stems = 0
|
64
|
+
@have_width = false
|
65
|
+
@open = false
|
66
|
+
@width = default_width_x
|
67
|
+
@x = 0
|
68
|
+
@y = 0
|
69
|
+
end
|
70
|
+
|
71
|
+
def path
|
72
|
+
@path || begin
|
73
|
+
@path = Path.new
|
74
|
+
parse!
|
75
|
+
@path
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def glyph
|
80
|
+
@glyph ||= begin
|
81
|
+
horizontal_metrics = @top_dict.file.horizontal_metrics.for(glyph_id)
|
82
|
+
Glyf::PathBased.new(path, horizontal_metrics)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def render(x: 0, y: 0, font_size: 72)
|
87
|
+
path.render(
|
88
|
+
x: x,
|
89
|
+
y: y,
|
90
|
+
font_size: font_size,
|
91
|
+
units_per_em: @top_dict.file.header.units_per_em
|
92
|
+
)
|
93
|
+
end
|
94
|
+
|
95
|
+
def encode
|
96
|
+
raw
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def parse!
|
102
|
+
until @index >= @data.size
|
103
|
+
code = @data[@index]
|
104
|
+
@index += 1
|
105
|
+
|
106
|
+
# return from callgsubr - do nothing since we inline subrs
|
107
|
+
next if code == 11
|
108
|
+
|
109
|
+
if code >= 32 && code <= 246
|
110
|
+
@stack << code - 139
|
111
|
+
elsif (m = CODE_MAP[code])
|
112
|
+
send(m)
|
113
|
+
elsif code >= 247 && code <= 250
|
114
|
+
b0 = code
|
115
|
+
b1 = @data[@index]
|
116
|
+
@index += 1
|
117
|
+
@stack << (b0 - 247) * 256 + b1 + 108
|
118
|
+
elsif code >= 251 && code <= 254
|
119
|
+
b0 = code
|
120
|
+
b1 = @data[@index]
|
121
|
+
@index += 1
|
122
|
+
@stack << -(b0 - 251) * 256 - b1 - 108
|
123
|
+
else
|
124
|
+
b1, b2, b3, b4 = read_bytes(4)
|
125
|
+
@stack << ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) / 65_536
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def read_bytes(length)
|
131
|
+
bytes = @data[@index, length]
|
132
|
+
@index += length
|
133
|
+
bytes
|
134
|
+
end
|
135
|
+
|
136
|
+
def hstem
|
137
|
+
stem
|
138
|
+
end
|
139
|
+
|
140
|
+
def vstem
|
141
|
+
stem
|
142
|
+
end
|
143
|
+
|
144
|
+
# rubocop:disable Style/EvenOdd
|
145
|
+
def stem
|
146
|
+
# The number of stem operators on the stack is always even.
|
147
|
+
# If the value is uneven, that means a width is specified.
|
148
|
+
has_width_arg = @stack.size % 2 == 1
|
149
|
+
|
150
|
+
if has_width_arg && !@have_width
|
151
|
+
@width = @stack.shift + @nominal_width_x
|
152
|
+
end
|
153
|
+
|
154
|
+
@n_stems += @stack.length >> 1
|
155
|
+
@stack.clear
|
156
|
+
@have_width = true
|
157
|
+
end
|
158
|
+
# rubocop:enable Style/EvenOdd
|
159
|
+
|
160
|
+
def vmoveto
|
161
|
+
if @stack.size > 1 && !@have_width
|
162
|
+
@width = @stack.shift + @nominal_width_x
|
163
|
+
@have_width = true
|
164
|
+
end
|
165
|
+
|
166
|
+
@y += @stack.pop
|
167
|
+
add_contour(@x, @y)
|
168
|
+
end
|
169
|
+
|
170
|
+
def add_contour(x, y)
|
171
|
+
if @open
|
172
|
+
@path.close_path
|
173
|
+
end
|
174
|
+
|
175
|
+
@path.move_to(x, y)
|
176
|
+
@open = true
|
177
|
+
end
|
178
|
+
|
179
|
+
def rlineto
|
180
|
+
until @stack.empty?
|
181
|
+
@x += @stack.shift
|
182
|
+
@y += @stack.shift
|
183
|
+
@path.line_to(@x, @y)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def hlineto
|
188
|
+
until @stack.empty?
|
189
|
+
@x += @stack.shift
|
190
|
+
@path.line_to(@x, @y)
|
191
|
+
|
192
|
+
break if @stack.empty?
|
193
|
+
|
194
|
+
@y += @stack.shift
|
195
|
+
@path.line_to(@x, @y)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def vlineto
|
200
|
+
until @stack.empty?
|
201
|
+
@y += @stack.shift
|
202
|
+
@path.line_to(@x, @y)
|
203
|
+
|
204
|
+
break if @stack.empty?
|
205
|
+
|
206
|
+
@x += @stack.shift
|
207
|
+
@path.line_to(@x, @y)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def rrcurveto
|
212
|
+
until @stack.empty?
|
213
|
+
c1x = @x + @stack.shift
|
214
|
+
c1y = @y + @stack.shift
|
215
|
+
c2x = c1x + @stack.shift
|
216
|
+
c2y = c1y + @stack.shift
|
217
|
+
@x = c2x + @stack.shift
|
218
|
+
@y = c2y + @stack.shift
|
219
|
+
@path.curve_to(c1x, c1y, c2x, c2y, @x, @y)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def callsubr
|
224
|
+
code_index = @stack.pop + @subrs_bias
|
225
|
+
subr_code = @subrs[code_index].bytes
|
226
|
+
@data[@index, 0] = subr_code
|
227
|
+
end
|
228
|
+
|
229
|
+
def flex_select
|
230
|
+
flex_code = @data[@index]
|
231
|
+
@index += 1
|
232
|
+
send(FLEX_CODE_MAP[flex_code])
|
233
|
+
end
|
234
|
+
|
235
|
+
def flex
|
236
|
+
c1x = @x + @stack.shift # dx1
|
237
|
+
c1y = @y + @stack.shift # dy1
|
238
|
+
c2x = c1x + @stack.shift # dx2
|
239
|
+
c2y = c1y + @stack.shift # dy2
|
240
|
+
jpx = c2x + @stack.shift # dx3
|
241
|
+
jpy = c2y + @stack.shift # dy3
|
242
|
+
c3x = jpx + @stack.shift # dx4
|
243
|
+
c3y = jpy + @stack.shift # dy4
|
244
|
+
c4x = c3x + @stack.shift # dx5
|
245
|
+
c4y = c3y + @stack.shift # dy5
|
246
|
+
@x = c4x + @stack.shift # dx6
|
247
|
+
@y = c4y + @stack.shift # dy6
|
248
|
+
@stack.shift # flex depth
|
249
|
+
|
250
|
+
@path.curve_to(c1x, c1y, c2x, c2y, jpx, jpy)
|
251
|
+
@path.curve_to(c3x, c3y, c4x, c4y, @x, @y)
|
252
|
+
end
|
253
|
+
|
254
|
+
def hflex
|
255
|
+
c1x = @x + @stack.shift # dx1
|
256
|
+
c1y = @y # dy1
|
257
|
+
c2x = c1x + @stack.shift # dx2
|
258
|
+
c2y = c1y + @stack.shift # dy2
|
259
|
+
jpx = c2x + @stack.shift # dx3
|
260
|
+
jpy = c2y # dy3
|
261
|
+
c3x = jpx + stack.shift # dx4
|
262
|
+
c3y = c2y # dy4
|
263
|
+
c4x = c3x + stack.shift # dx5
|
264
|
+
c4y = @y # dy5
|
265
|
+
@x = c4x + stack.shift # dx6
|
266
|
+
|
267
|
+
@path.curve_to(c1x, c1y, c2x, c2y, jpx, jpy)
|
268
|
+
@path.curve_to(c3x, c3y, c4x, c4y, @x, @y)
|
269
|
+
end
|
270
|
+
|
271
|
+
def hflex1
|
272
|
+
c1x = @x + @stack.shift # dx1
|
273
|
+
c1y = @y + @stack.shift # dy1
|
274
|
+
c2x = c1x + @stack.shift # dx2
|
275
|
+
c2y = c1y + @stack.shift # dy2
|
276
|
+
jpx = c2x + @stack.shift # dx3
|
277
|
+
jpy = c2y # dy3
|
278
|
+
c3x = jpx + @stack.shift # dx4
|
279
|
+
c3y = c2y # dy4
|
280
|
+
c4x = c3x + @stack.shift # dx5
|
281
|
+
c4y = c3y + @stack.shift # dy5
|
282
|
+
@x = c4x + @stack.shift # dx6
|
283
|
+
|
284
|
+
@path.curve_to(c1x, c1y, c2x, c2y, jpx, jpy)
|
285
|
+
@path.curve_to(c3x, c3y, c4x, c4y, @x, @y)
|
286
|
+
end
|
287
|
+
|
288
|
+
def flex1
|
289
|
+
c1x = @x + @stack.shift # dx1
|
290
|
+
c1y = @y + @stack.shift # dy1
|
291
|
+
c2x = c1x + @stack.shift # dx2
|
292
|
+
c2y = c1y + @stack.shift # dy2
|
293
|
+
jpx = c2x + @stack.shift # dx3
|
294
|
+
jpy = c2y + @stack.shift # dy3
|
295
|
+
c3x = jpx + @stack.shift # dx4
|
296
|
+
c3y = jpy + @stack.shift # dy4
|
297
|
+
c4x = c3x + @stack.shift # dx5
|
298
|
+
c4y = c3y + @stack.shift # dy5
|
299
|
+
|
300
|
+
if (c4x - @x).abs > (c4y - @y).abs
|
301
|
+
@x = c4x + @stack.shift
|
302
|
+
else
|
303
|
+
@y = c4y + @stack.shift
|
304
|
+
end
|
305
|
+
|
306
|
+
@path.curve_to(c1x, c1y, c2x, c2y, jpx, jpy)
|
307
|
+
@path.curve_to(c3x, c3y, c4x, c4y, @x, @y)
|
308
|
+
end
|
309
|
+
|
310
|
+
def endchar
|
311
|
+
if !@stack.empty? && !@have_width
|
312
|
+
@width = @stack.shift + @nominal_width_x
|
313
|
+
@have_width = true
|
314
|
+
end
|
315
|
+
|
316
|
+
if @open
|
317
|
+
@path.close_path
|
318
|
+
@open = false
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
def hstemhm
|
323
|
+
stem
|
324
|
+
end
|
325
|
+
|
326
|
+
def hintmask
|
327
|
+
cntrmask
|
328
|
+
end
|
329
|
+
|
330
|
+
def cntrmask
|
331
|
+
stem
|
332
|
+
|
333
|
+
# skip past hinting data, no need to worry about it since we're not
|
334
|
+
# very concerned about rendering glyphs
|
335
|
+
read_bytes((@n_stems + 7) >> 3)
|
336
|
+
end
|
337
|
+
|
338
|
+
def rmoveto
|
339
|
+
if @stack.size > 2 && !@have_width
|
340
|
+
@width = @stack.shift + @nominal_width_x
|
341
|
+
@have_width = true
|
342
|
+
end
|
343
|
+
|
344
|
+
@y += @stack.pop
|
345
|
+
@x += @stack.pop
|
346
|
+
add_contour(@x, @y)
|
347
|
+
end
|
348
|
+
|
349
|
+
def hmoveto
|
350
|
+
if @stack.size > 1 && !@have_width
|
351
|
+
@width = @stack.shift + @nominal_width_x
|
352
|
+
@have_width = true
|
353
|
+
end
|
354
|
+
|
355
|
+
@x += @stack.pop
|
356
|
+
add_contour(@x, @y)
|
357
|
+
end
|
358
|
+
|
359
|
+
def vstemhm
|
360
|
+
stem
|
361
|
+
end
|
362
|
+
|
363
|
+
def rcurveline
|
364
|
+
while @stack.size > 2
|
365
|
+
c1x = @x + @stack.shift
|
366
|
+
c1y = @y + @stack.shift
|
367
|
+
c2x = c1x + @stack.shift
|
368
|
+
c2y = c1y + @stack.shift
|
369
|
+
@x = c2x + @stack.shift
|
370
|
+
@y = c2y + @stack.shift
|
371
|
+
@path.curve_to(c1x, c1y, c2x, c2y, @x, @y)
|
372
|
+
end
|
373
|
+
|
374
|
+
@x += @stack.shift
|
375
|
+
@y += @stack.shift
|
376
|
+
@path.line_to(@x, @y)
|
377
|
+
end
|
378
|
+
|
379
|
+
def rlinecurve
|
380
|
+
while @stack.size > 6
|
381
|
+
@x += @stack.shift
|
382
|
+
@y += @stack.shift
|
383
|
+
@path.line_to(@x, @y)
|
384
|
+
end
|
385
|
+
|
386
|
+
c1x = @x + @stack.shift
|
387
|
+
c1y = @y + @stack.shift
|
388
|
+
c2x = c1x + @stack.shift
|
389
|
+
c2y = c1y + @stack.shift
|
390
|
+
@x = c2x + @stack.shift
|
391
|
+
@y = c2y + @stack.shift
|
392
|
+
|
393
|
+
@path.curve_to(c1x, c1y, c2x, c2y, @x, @y)
|
394
|
+
end
|
395
|
+
|
396
|
+
# rubocop:disable Style/EvenOdd
|
397
|
+
def vvcurveto
|
398
|
+
if @stack.size % 2 == 1
|
399
|
+
@x += @stack.shift
|
400
|
+
end
|
401
|
+
|
402
|
+
until @stack.empty?
|
403
|
+
c1x = @x
|
404
|
+
c1y = @y + @stack.shift
|
405
|
+
c2x = c1x + @stack.shift
|
406
|
+
c2y = c1y + @stack.shift
|
407
|
+
@x = c2x
|
408
|
+
@y = c2y + @stack.shift
|
409
|
+
@path.curve_to(c1x, c1y, c2x, c2y, @x, @y)
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
def hhcurveto
|
414
|
+
if @stack.size % 2 == 1
|
415
|
+
@y += @stack.shift
|
416
|
+
end
|
417
|
+
|
418
|
+
until @stack.empty?
|
419
|
+
c1x = @x + @stack.shift
|
420
|
+
c1y = @y
|
421
|
+
c2x = c1x + @stack.shift
|
422
|
+
c2y = c1y + @stack.shift
|
423
|
+
@x = c2x + @stack.shift
|
424
|
+
@y = c2y
|
425
|
+
@path.curve_to(c1x, c1y, c2x, c2y, @x, @y)
|
426
|
+
end
|
427
|
+
end
|
428
|
+
# rubocop:enable Style/EvenOdd
|
429
|
+
|
430
|
+
def shortint
|
431
|
+
b1, b2 = read_bytes(2)
|
432
|
+
@stack << (((b1 << 24) | (b2 << 16)) >> 16)
|
433
|
+
end
|
434
|
+
|
435
|
+
def callgsubr
|
436
|
+
code_index = @stack.pop + @gsubrs_bias
|
437
|
+
subr_code = @gsubrs[code_index].bytes
|
438
|
+
@data[@index, 0] = subr_code
|
439
|
+
end
|
440
|
+
|
441
|
+
def vhcurveto
|
442
|
+
until @stack.empty?
|
443
|
+
c1x = @x
|
444
|
+
c1y = @y + @stack.shift
|
445
|
+
c2x = c1x + @stack.shift
|
446
|
+
c2y = c1y + @stack.shift
|
447
|
+
@x = c2x + @stack.shift
|
448
|
+
@y = c2y + (@stack.size == 1 ? @stack.shift : 0)
|
449
|
+
@path.curve_to(c1x, c1y, c2x, c2y, @x, @y)
|
450
|
+
|
451
|
+
break if @stack.empty?
|
452
|
+
|
453
|
+
c1x = @x + @stack.shift
|
454
|
+
c1y = @y
|
455
|
+
c2x = c1x + @stack.shift
|
456
|
+
c2y = c1y + @stack.shift
|
457
|
+
@y = c2y + @stack.shift
|
458
|
+
@x = c2x + (@stack.size == 1 ? @stack.shift : 0)
|
459
|
+
@path.curve_to(c1x, c1y, c2x, c2y, @x, @y)
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
def hvcurveto
|
464
|
+
until @stack.empty?
|
465
|
+
c1x = @x + @stack.shift
|
466
|
+
c1y = @y
|
467
|
+
c2x = c1x + @stack.shift
|
468
|
+
c2y = c1y + @stack.shift
|
469
|
+
@y = c2y + @stack.shift
|
470
|
+
@x = c2x + (@stack.size == 1 ? @stack.shift : 0)
|
471
|
+
@path.curve_to(c1x, c1y, c2x, c2y, @x, @y)
|
472
|
+
|
473
|
+
break if @stack.empty?
|
474
|
+
|
475
|
+
c1x = @x
|
476
|
+
c1y = @y + @stack.shift
|
477
|
+
c2x = c1x + @stack.shift
|
478
|
+
c2y = c1y + @stack.shift
|
479
|
+
@x = c2x + @stack.shift
|
480
|
+
@y = c2y + (@stack.size == 1 ? @stack.shift : 0)
|
481
|
+
@path.curve_to(c1x, c1y, c2x, c2y, @x, @y)
|
482
|
+
end
|
483
|
+
end
|
484
|
+
end
|
485
|
+
end
|
486
|
+
end
|
487
|
+
end
|