ttfunk 1.7.0 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +74 -0
- data/README.md +17 -15
- data/lib/ttfunk/aggregate.rb +5 -0
- data/lib/ttfunk/bin_utils.rb +27 -8
- data/lib/ttfunk/bit_field.rb +25 -2
- data/lib/ttfunk/collection.rb +27 -3
- data/lib/ttfunk/directory.rb +7 -1
- data/lib/ttfunk/encoded_string.rb +58 -4
- data/lib/ttfunk/max.rb +14 -0
- data/lib/ttfunk/min.rb +14 -0
- data/lib/ttfunk/one_based_array.rb +20 -0
- data/lib/ttfunk/otf_encoder.rb +5 -14
- data/lib/ttfunk/placeholder.rb +15 -1
- data/lib/ttfunk/reader.rb +6 -4
- data/lib/ttfunk/resource_file.rb +29 -5
- data/lib/ttfunk/sci_form.rb +20 -3
- data/lib/ttfunk/sub_table.rb +29 -4
- data/lib/ttfunk/subset/base.rb +48 -0
- data/lib/ttfunk/subset/code_page.rb +49 -2
- data/lib/ttfunk/subset/mac_roman.rb +2 -0
- data/lib/ttfunk/subset/unicode.rb +32 -0
- data/lib/ttfunk/subset/unicode_8bit.rb +32 -0
- data/lib/ttfunk/subset/windows_1252.rb +2 -0
- data/lib/ttfunk/subset.rb +8 -0
- data/lib/ttfunk/subset_collection.rb +39 -14
- data/lib/ttfunk/sum.rb +13 -0
- data/lib/ttfunk/table/cff/charset.rb +96 -18
- data/lib/ttfunk/table/cff/charsets/expert.rb +3 -2
- data/lib/ttfunk/table/cff/charsets/expert_subset.rb +3 -2
- data/lib/ttfunk/table/cff/charsets/iso_adobe.rb +3 -2
- data/lib/ttfunk/table/cff/charsets/standard_strings.rb +3 -2
- data/lib/ttfunk/table/cff/charsets.rb +1 -0
- data/lib/ttfunk/table/cff/charstring.rb +33 -12
- data/lib/ttfunk/table/cff/charstrings_index.rb +17 -11
- data/lib/ttfunk/table/cff/dict.rb +53 -23
- data/lib/ttfunk/table/cff/encoding.rb +82 -24
- data/lib/ttfunk/table/cff/encodings/expert.rb +3 -2
- data/lib/ttfunk/table/cff/encodings/standard.rb +3 -2
- data/lib/ttfunk/table/cff/encodings.rb +1 -0
- data/lib/ttfunk/table/cff/fd_selector.rb +61 -21
- data/lib/ttfunk/table/cff/font_dict.rb +30 -18
- data/lib/ttfunk/table/cff/font_index.rb +22 -10
- data/lib/ttfunk/table/cff/header.rb +16 -3
- data/lib/ttfunk/table/cff/index.rb +97 -65
- data/lib/ttfunk/table/cff/one_based_index.rb +11 -1
- data/lib/ttfunk/table/cff/path.rb +43 -4
- data/lib/ttfunk/table/cff/private_dict.rb +31 -11
- data/lib/ttfunk/table/cff/subr_index.rb +7 -2
- data/lib/ttfunk/table/cff/top_dict.rb +82 -59
- data/lib/ttfunk/table/cff/top_index.rb +10 -6
- data/lib/ttfunk/table/cff.rb +41 -21
- data/lib/ttfunk/table/cmap/format00.rb +27 -6
- data/lib/ttfunk/table/cmap/format04.rb +34 -14
- data/lib/ttfunk/table/cmap/format06.rb +28 -1
- data/lib/ttfunk/table/cmap/format10.rb +29 -2
- data/lib/ttfunk/table/cmap/format12.rb +29 -2
- data/lib/ttfunk/table/cmap/subtable.rb +50 -6
- data/lib/ttfunk/table/cmap.rb +21 -0
- data/lib/ttfunk/table/dsig.rb +47 -6
- data/lib/ttfunk/table/glyf/compound.rb +73 -6
- data/lib/ttfunk/table/glyf/path_based.rb +40 -3
- data/lib/ttfunk/table/glyf/simple.rb +50 -5
- data/lib/ttfunk/table/glyf.rb +15 -7
- data/lib/ttfunk/table/head.rb +84 -6
- data/lib/ttfunk/table/hhea.rb +71 -10
- data/lib/ttfunk/table/hmtx.rb +32 -5
- data/lib/ttfunk/table/kern/format0.rb +25 -7
- data/lib/ttfunk/table/kern.rb +16 -4
- data/lib/ttfunk/table/loca.rb +21 -8
- data/lib/ttfunk/table/maxp.rb +195 -10
- data/lib/ttfunk/table/name.rb +126 -9
- data/lib/ttfunk/table/os2.rb +150 -26
- data/lib/ttfunk/table/post/format10.rb +7 -0
- data/lib/ttfunk/table/post/format20.rb +9 -0
- data/lib/ttfunk/table/post/format30.rb +6 -0
- data/lib/ttfunk/table/post/format40.rb +5 -0
- data/lib/ttfunk/table/post.rb +63 -7
- data/lib/ttfunk/table/sbix.rb +50 -14
- data/lib/ttfunk/table/simple.rb +5 -0
- data/lib/ttfunk/table/vorg.rb +31 -3
- data/lib/ttfunk/table.rb +20 -1
- data/lib/ttfunk/ttf_encoder.rb +39 -41
- data/lib/ttfunk.rb +154 -1
- data.tar.gz.sig +0 -0
- metadata +50 -28
- metadata.gz.sig +0 -0
data/lib/ttfunk/table/os2.rb
CHANGED
@@ -5,44 +5,147 @@ require 'set'
|
|
5
5
|
|
6
6
|
module TTFunk
|
7
7
|
class Table
|
8
|
+
# OS/2 and Windows Metrics (`OS/2`) table
|
8
9
|
class OS2 < Table
|
10
|
+
# Table version.
|
11
|
+
# @return [Integer]
|
9
12
|
attr_reader :version
|
10
13
|
|
14
|
+
# Average weighted escapement.
|
15
|
+
# @return [Integer]
|
11
16
|
attr_reader :ave_char_width
|
17
|
+
|
18
|
+
# Weight class.
|
19
|
+
# @return [Integer]
|
12
20
|
attr_reader :weight_class
|
21
|
+
|
22
|
+
# Width class.
|
23
|
+
# @return [Integer]
|
13
24
|
attr_reader :width_class
|
25
|
+
|
26
|
+
# Type flags.
|
27
|
+
# @return [Integer]
|
14
28
|
attr_reader :type
|
29
|
+
|
30
|
+
# Subscript horizontal font size.
|
31
|
+
# @return [Integer]
|
15
32
|
attr_reader :y_subscript_x_size
|
33
|
+
|
34
|
+
# Subscript vertical font size.
|
35
|
+
# @return [Integer]
|
16
36
|
attr_reader :y_subscript_y_size
|
37
|
+
|
38
|
+
# Subscript x offset.
|
39
|
+
# @return [Integer]
|
17
40
|
attr_reader :y_subscript_x_offset
|
41
|
+
|
42
|
+
# Subscript y offset.
|
43
|
+
# @return [Integer]
|
18
44
|
attr_reader :y_subscript_y_offset
|
45
|
+
|
46
|
+
# Superscript horizontal font size.
|
47
|
+
# @return [Integer]
|
19
48
|
attr_reader :y_superscript_x_size
|
49
|
+
|
50
|
+
# Superscript vertical font size.
|
51
|
+
# @return [Integer]
|
20
52
|
attr_reader :y_superscript_y_size
|
53
|
+
|
54
|
+
# Superscript x offset.
|
55
|
+
# @return [Integer]
|
21
56
|
attr_reader :y_superscript_x_offset
|
57
|
+
|
58
|
+
# Superscript y offset.
|
59
|
+
# @return [Integer]
|
22
60
|
attr_reader :y_superscript_y_offset
|
61
|
+
|
62
|
+
# Strikeout size.
|
63
|
+
# @return [Integer]
|
23
64
|
attr_reader :y_strikeout_size
|
65
|
+
|
66
|
+
# Strikeout position.
|
67
|
+
# @return [Integer]
|
24
68
|
attr_reader :y_strikeout_position
|
69
|
+
|
70
|
+
# Font-family class and subclass.
|
71
|
+
# @return [Integer]
|
25
72
|
attr_reader :family_class
|
73
|
+
|
74
|
+
# PANOSE classification number.
|
75
|
+
# @return [Integer]
|
26
76
|
attr_reader :panose
|
77
|
+
|
78
|
+
# Unicode Character Range.
|
79
|
+
# @return [Integer]
|
27
80
|
attr_reader :char_range
|
81
|
+
|
82
|
+
# Font Vendor Identification.
|
83
|
+
# @return [String]
|
28
84
|
attr_reader :vendor_id
|
85
|
+
|
86
|
+
# Font selection flags.
|
87
|
+
# @return [Integer]
|
29
88
|
attr_reader :selection
|
89
|
+
|
90
|
+
# The minimum Unicode index (character code) in this font.
|
91
|
+
# @return [Integer]
|
30
92
|
attr_reader :first_char_index
|
93
|
+
|
94
|
+
# The maximum Unicode index (character code) in this font.
|
95
|
+
# @return [Integer]
|
31
96
|
attr_reader :last_char_index
|
32
97
|
|
98
|
+
# The typographic ascender for this font.
|
99
|
+
# @return [Integer]
|
33
100
|
attr_reader :ascent
|
101
|
+
|
102
|
+
# The typographic descender for this font.
|
103
|
+
# @return [Integer]
|
34
104
|
attr_reader :descent
|
105
|
+
|
106
|
+
# The typographic line gap for this font.
|
107
|
+
# @return [Integer]
|
35
108
|
attr_reader :line_gap
|
109
|
+
|
110
|
+
# The "Windows ascender" metric.
|
111
|
+
# @return [Integer]
|
36
112
|
attr_reader :win_ascent
|
113
|
+
|
114
|
+
# The "Windows descender" metric.
|
115
|
+
# @return [Integer]
|
37
116
|
attr_reader :win_descent
|
117
|
+
|
118
|
+
# Code Page Character Range.
|
119
|
+
# @return [Integer]
|
38
120
|
attr_reader :code_page_range
|
39
121
|
|
122
|
+
# The distance between the baseline and the approximate height of
|
123
|
+
# non-ascending lowercase letters.
|
124
|
+
# @return [Integer]
|
40
125
|
attr_reader :x_height
|
126
|
+
|
127
|
+
# The distance between the baseline and the approximate height of
|
128
|
+
# uppercase letters.
|
129
|
+
# @return [Integer]
|
41
130
|
attr_reader :cap_height
|
131
|
+
|
132
|
+
# The Unicode code point, in UTF-16 encoding, of a character that can be
|
133
|
+
# used for a default glyph if a requested character is not supported in
|
134
|
+
# the font.
|
135
|
+
# @return [Integer]
|
42
136
|
attr_reader :default_char
|
137
|
+
|
138
|
+
# The Unicode code point, in UTF-16 encoding, of a character that can be
|
139
|
+
# used as a default break character.
|
140
|
+
# @return [Integer]
|
43
141
|
attr_reader :break_char
|
142
|
+
|
143
|
+
# The maximum length of a target glyph context for any feature in this
|
144
|
+
# font.
|
145
|
+
# @return [Integer]
|
44
146
|
attr_reader :max_context
|
45
147
|
|
148
|
+
# Code page bits.
|
46
149
|
CODE_PAGE_BITS = {
|
47
150
|
1252 => 0,
|
48
151
|
1250 => 1,
|
@@ -75,9 +178,10 @@ module TTFunk
|
|
75
178
|
737 => 60,
|
76
179
|
708 => 61,
|
77
180
|
850 => 62,
|
78
|
-
437 => 63
|
181
|
+
437 => 63,
|
79
182
|
}.freeze
|
80
183
|
|
184
|
+
# Unicode blocks.
|
81
185
|
UNICODE_BLOCKS = {
|
82
186
|
(0x0000..0x007F) => 0,
|
83
187
|
(0x0080..0x00FF) => 1,
|
@@ -247,17 +351,29 @@ module TTFunk
|
|
247
351
|
(0x10280..0x1029F) => 121,
|
248
352
|
(0x10920..0x1093F) => 121,
|
249
353
|
(0x1F030..0x1F09F) => 122,
|
250
|
-
(0x1F000..0x1F02F) => 122
|
354
|
+
(0x1F000..0x1F02F) => 122,
|
251
355
|
}.freeze
|
252
356
|
|
357
|
+
# Indicates that font supports supplementary characters.
|
253
358
|
UNICODE_MAX = 0xFFFF
|
254
|
-
|
359
|
+
|
360
|
+
# Unicode block ranges.
|
361
|
+
UNICODE_RANGES = UNICODE_BLOCKS.keys.sort_by(&:max).freeze
|
362
|
+
|
363
|
+
# Start chracter for average character width calculation.
|
255
364
|
LOWERCASE_START = 'a'.ord
|
365
|
+
|
366
|
+
# End chracter for average character width calculation.
|
256
367
|
LOWERCASE_END = 'z'.ord
|
368
|
+
|
369
|
+
# Number of chracters for average character width calculation.
|
257
370
|
LOWERCASE_COUNT = (LOWERCASE_END - LOWERCASE_START) + 1
|
371
|
+
|
372
|
+
# Space character code point.
|
258
373
|
CODEPOINT_SPACE = 32
|
259
|
-
|
260
|
-
|
374
|
+
|
375
|
+
# Error message for missing space character.
|
376
|
+
SPACE_GLYPH_MISSING_ERROR = "Space glyph (0x#{CODEPOINT_SPACE.to_s(16)}) must be included in the font"
|
261
377
|
|
262
378
|
# Used to calculate the xAvgCharWidth field.
|
263
379
|
# From https://docs.microsoft.com/en-us/typography/opentype/spec/os2:
|
@@ -272,16 +388,26 @@ module TTFunk
|
|
272
388
|
# 26 letters in the Latin alphabet. Each weight is the relative
|
273
389
|
# frequency of that letter in the English language.
|
274
390
|
WEIGHT_SPACE = 166
|
391
|
+
|
392
|
+
# chracter weights for average character width calculation.
|
275
393
|
WEIGHT_LOWERCASE = [
|
276
394
|
64, 14, 27, 35, 100, 20, 14, 42, 63, 3, 6, 35, 20,
|
277
|
-
56, 56, 17, 4, 49, 56, 71, 31, 10, 18, 3, 18, 2
|
395
|
+
56, 56, 17, 4, 49, 56, 71, 31, 10, 18, 3, 18, 2,
|
278
396
|
].freeze
|
279
397
|
|
398
|
+
# Table tag.
|
399
|
+
# @return [String]
|
280
400
|
def tag
|
281
401
|
'OS/2'
|
282
402
|
end
|
283
403
|
|
284
404
|
class << self
|
405
|
+
# Encode table.
|
406
|
+
#
|
407
|
+
# @param os2 [TTFunk::Table::OS2]
|
408
|
+
# @param subset [TTFunk::Subset::MacRoman, TTFunk::Subset::Windows1252,
|
409
|
+
# TTFunk::Subset::Unicode, TTFunk::Subset::Unicode8Bit]
|
410
|
+
# @return [String]
|
285
411
|
def encode(os2, subset)
|
286
412
|
result = ''.b
|
287
413
|
result << [
|
@@ -291,7 +417,7 @@ module TTFunk
|
|
291
417
|
os2.y_subscript_y_offset, os2.y_superscript_x_size,
|
292
418
|
os2.y_superscript_y_size, os2.y_superscript_x_offset,
|
293
419
|
os2.y_superscript_y_offset, os2.y_strikeout_size,
|
294
|
-
os2.y_strikeout_position, os2.family_class
|
420
|
+
os2.y_strikeout_position, os2.family_class,
|
295
421
|
].pack('n*')
|
296
422
|
|
297
423
|
result << os2.panose
|
@@ -301,7 +427,7 @@ module TTFunk
|
|
301
427
|
.slice_int(
|
302
428
|
new_char_range.value,
|
303
429
|
bit_width: 32,
|
304
|
-
slice_count: 4
|
430
|
+
slice_count: 4,
|
305
431
|
)
|
306
432
|
.pack('N*')
|
307
433
|
|
@@ -322,27 +448,27 @@ module TTFunk
|
|
322
448
|
last_char_index = [code_points.last || 0, UNICODE_MAX].min
|
323
449
|
|
324
450
|
result << [
|
325
|
-
os2.selection, first_char_index, last_char_index
|
451
|
+
os2.selection, first_char_index, last_char_index,
|
326
452
|
].pack('n*')
|
327
453
|
|
328
454
|
if os2.version.positive?
|
329
455
|
result << [
|
330
456
|
os2.ascent, os2.descent, os2.line_gap,
|
331
|
-
os2.win_ascent, os2.win_descent
|
457
|
+
os2.win_ascent, os2.win_descent,
|
332
458
|
].pack('n*')
|
333
459
|
|
334
460
|
result << BinUtils
|
335
461
|
.slice_int(
|
336
462
|
code_pages_for(subset).value,
|
337
463
|
bit_width: 32,
|
338
|
-
slice_count: 2
|
464
|
+
slice_count: 2,
|
339
465
|
)
|
340
466
|
.pack('N*')
|
341
467
|
|
342
468
|
if os2.version > 1
|
343
469
|
result << [
|
344
470
|
os2.x_height, os2.cap_height, os2.default_char,
|
345
|
-
os2.break_char, os2.max_context
|
471
|
+
os2.break_char, os2.max_context,
|
346
472
|
].pack('n*')
|
347
473
|
end
|
348
474
|
end
|
@@ -380,13 +506,15 @@ module TTFunk
|
|
380
506
|
|
381
507
|
def group_original_code_points_by_bit(os2)
|
382
508
|
Hash.new { |h, k| h[k] = [] }.tap do |result|
|
383
|
-
os2.file.cmap.unicode.first.code_map.
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
509
|
+
code_points = os2.file.cmap.unicode.first.code_map.keys.sort
|
510
|
+
UNICODE_RANGES.each do |r|
|
511
|
+
code_points = code_points.drop_while { |p| p < r.min }
|
512
|
+
code_points.take_while { |p| p <= r.max }.each do |code_point|
|
513
|
+
if (bit = UNICODE_BLOCKS[r])
|
514
|
+
result[bit] << code_point
|
515
|
+
end
|
389
516
|
end
|
517
|
+
code_points = code_points.drop_while { |p| p <= r.max }
|
390
518
|
end
|
391
519
|
end
|
392
520
|
end
|
@@ -405,7 +533,7 @@ module TTFunk
|
|
405
533
|
|
406
534
|
# use new -> old glyph mapping in order to include compound glyphs
|
407
535
|
# in the calculation
|
408
|
-
subset.new_to_old_glyph.
|
536
|
+
subset.new_to_old_glyph.each_value do |old_gid|
|
409
537
|
if (metric = os2.file.horizontal_metrics.for(old_gid))
|
410
538
|
total_width += metric.advance_width
|
411
539
|
num_glyphs += 1 if metric.advance_width.positive?
|
@@ -456,7 +584,7 @@ module TTFunk
|
|
456
584
|
|
457
585
|
# use new -> old glyph mapping in order to include compound glyphs
|
458
586
|
# in the calculation
|
459
|
-
subset.new_to_old_glyph.
|
587
|
+
subset.new_to_old_glyph.each_value do |old_gid|
|
460
588
|
if (metric = os2.file.horizontal_metrics.for(old_gid))
|
461
589
|
total_width += metric.advance_width
|
462
590
|
end
|
@@ -481,9 +609,7 @@ module TTFunk
|
|
481
609
|
@y_strikeout_position, @family_class = read_signed(12)
|
482
610
|
@panose = io.read(10)
|
483
611
|
|
484
|
-
@char_range = BitField.new(
|
485
|
-
BinUtils.stitch_int(read(16, 'N*'), bit_width: 32)
|
486
|
-
)
|
612
|
+
@char_range = BitField.new(BinUtils.stitch_int(read(16, 'N*'), bit_width: 32))
|
487
613
|
|
488
614
|
@vendor_id = io.read(4)
|
489
615
|
@selection, @first_char_index, @last_char_index = read(6, 'n*')
|
@@ -491,9 +617,7 @@ module TTFunk
|
|
491
617
|
if @version.positive?
|
492
618
|
@ascent, @descent, @line_gap = read_signed(3)
|
493
619
|
@win_ascent, @win_descent = read(4, 'nn')
|
494
|
-
@code_page_range = BitField.new(
|
495
|
-
BinUtils.stitch_int(read(8, 'N*'), bit_width: 32)
|
496
|
-
)
|
620
|
+
@code_page_range = BitField.new(BinUtils.stitch_int(read(8, 'N*'), bit_width: 32))
|
497
621
|
|
498
622
|
if @version > 1
|
499
623
|
@x_height, @cap_height = read_signed(2)
|
@@ -3,7 +3,10 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Post
|
6
|
+
# Version 1.0 provides glyph names for standard 258 glyphs in the standard
|
7
|
+
# Macintosh TrueType font file.
|
6
8
|
module Format10
|
9
|
+
# Glyph names.
|
7
10
|
POSTSCRIPT_GLYPHS = %w[
|
8
11
|
.notdef .null nonmarkingreturn space exclam quotedbl numbersign dollar
|
9
12
|
percent ampersand quotesingle parenleft parenright asterisk plus comma
|
@@ -36,6 +39,10 @@ module TTFunk
|
|
36
39
|
scedilla Cacute cacute Ccaron ccaron dcroat
|
37
40
|
].freeze
|
38
41
|
|
42
|
+
# Get glyph name for character code.
|
43
|
+
#
|
44
|
+
# @param code [Integer]
|
45
|
+
# @return [String]
|
39
46
|
def glyph_for(code)
|
40
47
|
POSTSCRIPT_GLYPHS[code] || '.notdef'
|
41
48
|
end
|
@@ -6,9 +6,18 @@ require 'stringio'
|
|
6
6
|
module TTFunk
|
7
7
|
class Table
|
8
8
|
class Post
|
9
|
+
# Version 2.0 is used for fonts that use glyph names that are not in the
|
10
|
+
# set of Macintosh glyph names. A given font may map some of its glyphs to
|
11
|
+
# the standard Macintosh glyph names, and some to its own custom names.
|
12
|
+
# A version 2.0 `post` table can be used in fonts with TrueType or CFF
|
13
|
+
# version 2 outlines.
|
9
14
|
module Format20
|
10
15
|
include Format10
|
11
16
|
|
17
|
+
# Get glyph name for character code.
|
18
|
+
#
|
19
|
+
# @param code [Integer]
|
20
|
+
# @return [String]
|
12
21
|
def glyph_for(code)
|
13
22
|
index = @glyph_name_index[code]
|
14
23
|
return '.notdef' unless index
|
@@ -3,7 +3,13 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Post
|
6
|
+
# Version 3.0 specifies that no PostScript name information is provided
|
7
|
+
# for the glyphs in this font file.
|
6
8
|
module Format30
|
9
|
+
# Get glyph name for character code.
|
10
|
+
#
|
11
|
+
# @param _code [Integer]
|
12
|
+
# @return [String]
|
7
13
|
def glyph_for(_code)
|
8
14
|
'.notdef'
|
9
15
|
end
|
@@ -3,7 +3,12 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Post
|
6
|
+
# Version 4.0 names glyphs by their character code.
|
6
7
|
module Format40
|
8
|
+
# Get glyph name for character code.
|
9
|
+
#
|
10
|
+
# @param code [Integer]
|
11
|
+
# @return [String]
|
7
12
|
def glyph_for(code)
|
8
13
|
@map[code] || 0xFFFF
|
9
14
|
end
|
data/lib/ttfunk/table/post.rb
CHANGED
@@ -4,33 +4,93 @@ require_relative '../table'
|
|
4
4
|
|
5
5
|
module TTFunk
|
6
6
|
class Table
|
7
|
+
# PostScript (`post`) table.
|
8
|
+
#
|
9
|
+
# This class can be extended with version-specific modules.
|
10
|
+
#
|
11
|
+
# @see TTFunk::Table::Post::Format10
|
12
|
+
# @see TTFunk::Table::Post::Format20
|
13
|
+
# @see TTFunk::Table::Post::Format30
|
14
|
+
# @see TTFunk::Table::Post::Format40
|
7
15
|
class Post < Table
|
16
|
+
# Table version.
|
17
|
+
# @return [Integer]
|
8
18
|
attr_reader :format
|
19
|
+
|
20
|
+
# Italic angle in counter-clockwise degrees from the vertical.
|
21
|
+
# @return [Integer]
|
9
22
|
attr_reader :italic_angle
|
23
|
+
|
24
|
+
# Suggested distance of the top of the underline from the baseline
|
25
|
+
# @return [Integer]
|
10
26
|
attr_reader :underline_position
|
27
|
+
|
28
|
+
# Suggested values for the underline thickness.
|
29
|
+
# @return [Integer]
|
11
30
|
attr_reader :underline_thickness
|
31
|
+
|
32
|
+
# 0 if the font is proportionally spaced, non-zero if the font is not
|
33
|
+
# proportionally spaced.
|
34
|
+
# @return [Integer]
|
12
35
|
attr_reader :fixed_pitch
|
36
|
+
|
37
|
+
# Minimum memory usage when an OpenType font is downloaded.
|
38
|
+
# @return [Integer]
|
13
39
|
attr_reader :min_mem_type42
|
40
|
+
|
41
|
+
# Maximum memory usage when an OpenType font is downloaded.
|
42
|
+
# @return [Integer]
|
14
43
|
attr_reader :max_mem_type42
|
44
|
+
|
45
|
+
# Minimum memory usage when an OpenType font is downloaded as
|
46
|
+
# a Type 1 font.
|
47
|
+
# @return [Integer]
|
15
48
|
attr_reader :min_mem_type1
|
49
|
+
|
50
|
+
# Maximum memory usage when an OpenType font is downloaded as
|
51
|
+
# a Type 1 font.
|
52
|
+
# @return [Integer]
|
16
53
|
attr_reader :max_mem_type1
|
17
54
|
|
55
|
+
# Version-specific fields.
|
56
|
+
# @return [TTFunk::Table::Post::Format10, TTFunk::Table::Post::Format20,
|
57
|
+
# TTFunk::Table::Post::Format30, TTFunk::Table::Post::Format40]
|
18
58
|
attr_reader :subtable
|
19
59
|
|
60
|
+
# Encode table.
|
61
|
+
#
|
62
|
+
# @param post [TTFunk::Table::Post]
|
63
|
+
# @param mapping [Hash{Integer => Integer}] keys are new glyph IDs, values
|
64
|
+
# are old glyph IDs
|
65
|
+
# @return [String, nil]
|
20
66
|
def self.encode(post, mapping)
|
21
|
-
return
|
67
|
+
return if post.nil?
|
22
68
|
|
23
69
|
post.recode(mapping)
|
24
70
|
end
|
25
71
|
|
72
|
+
# Is this font monospaced?
|
73
|
+
#
|
74
|
+
# @return [Boolean]
|
26
75
|
def fixed_pitch?
|
27
76
|
@fixed_pitch != 0
|
28
77
|
end
|
29
78
|
|
79
|
+
# Get glyph name for character code.
|
80
|
+
#
|
81
|
+
# This is a placeholder.
|
82
|
+
#
|
83
|
+
# @param _code [Integer]
|
84
|
+
# @return [String]
|
30
85
|
def glyph_for(_code)
|
31
86
|
'.notdef'
|
32
87
|
end
|
33
88
|
|
89
|
+
# Re-encode this table.
|
90
|
+
#
|
91
|
+
# @param mapping [Hash{Integer => Integer}] keys are new glyph IDs, values
|
92
|
+
# are old glyph IDs
|
93
|
+
# @return [String]
|
34
94
|
def recode(mapping)
|
35
95
|
return raw if format == 0x00030000
|
36
96
|
|
@@ -46,7 +106,7 @@ module TTFunk
|
|
46
106
|
if position
|
47
107
|
index << position
|
48
108
|
else
|
49
|
-
index << 257 + strings.length
|
109
|
+
index << (257 + strings.length)
|
50
110
|
strings << post_glyph
|
51
111
|
end
|
52
112
|
end
|
@@ -85,11 +145,7 @@ module TTFunk
|
|
85
145
|
end
|
86
146
|
|
87
147
|
def parse_format!
|
88
|
-
warn(
|
89
|
-
Kernel.format(
|
90
|
-
'postscript table format 0x%08X is not supported', @format
|
91
|
-
)
|
92
|
-
)
|
148
|
+
warn(Kernel.format('postscript table format 0x%08X is not supported', @format))
|
93
149
|
end
|
94
150
|
end
|
95
151
|
end
|
data/lib/ttfunk/table/sbix.rb
CHANGED
@@ -4,14 +4,48 @@ require_relative '../table'
|
|
4
4
|
|
5
5
|
module TTFunk
|
6
6
|
class Table
|
7
|
+
# Standard Bitmap Graphics (`sbix`) table.
|
7
8
|
class Sbix < Table
|
9
|
+
# Table version.
|
10
|
+
# @return [Integer]
|
8
11
|
attr_reader :version
|
12
|
+
|
13
|
+
# Flags.
|
14
|
+
# @return [Integer]
|
9
15
|
attr_reader :flags
|
16
|
+
|
17
|
+
# Number of bitmap strikes.
|
18
|
+
# @return [Integer]
|
10
19
|
attr_reader :num_strikes
|
20
|
+
|
21
|
+
# Strikes.
|
22
|
+
# @return [Array<Hash>]
|
11
23
|
attr_reader :strikes
|
12
24
|
|
25
|
+
# Bitmap Data.
|
26
|
+
#
|
27
|
+
# @!attribute [rw] x
|
28
|
+
# The horizontal (x-axis) position of the left edge of the bitmap
|
29
|
+
# graphic in relation to the glyph design space origin.
|
30
|
+
# @!attribute [rw] y
|
31
|
+
# The vertical (y-axis) position of the bottom edge of the bitmap
|
32
|
+
# graphic in relation to the glyph design space origin.
|
33
|
+
# @!attribute [rw] type
|
34
|
+
# Indicates the format of the embedded graphic data: one of `jpg `,
|
35
|
+
# `png `, `tiff`, or the special format `dupe`.
|
36
|
+
# @!attribute [rw] data
|
37
|
+
# The actual embedded graphic data.
|
38
|
+
# @!attribute [rw] ppem
|
39
|
+
# The PPEM size for which this strike was designed.
|
40
|
+
# @!attribute [rw] resolution
|
41
|
+
# The device pixel density (in PPI) for which this strike was designed.
|
13
42
|
BitmapData = Struct.new(:x, :y, :type, :data, :ppem, :resolution)
|
14
43
|
|
44
|
+
# Get bitmap for glyph strike.
|
45
|
+
#
|
46
|
+
# @param glyph_id [Integer]
|
47
|
+
# @param strike_index [Integer]
|
48
|
+
# @return [BitmapData]
|
15
49
|
def bitmap_data_for(glyph_id, strike_index)
|
16
50
|
strike = strikes[strike_index]
|
17
51
|
return if strike.nil?
|
@@ -22,21 +56,23 @@ module TTFunk
|
|
22
56
|
if glyph_offset && next_glyph_offset
|
23
57
|
bytes = next_glyph_offset - glyph_offset
|
24
58
|
if bytes.positive?
|
25
|
-
parse_from(offset + strike[:offset] + glyph_offset)
|
59
|
+
parse_from(offset + strike[:offset] + glyph_offset) {
|
26
60
|
x, y, type = read(8, 's2A4')
|
27
61
|
data = StringIO.new(io.read(bytes - 8))
|
28
|
-
BitmapData.new(
|
29
|
-
|
30
|
-
)
|
31
|
-
end
|
62
|
+
BitmapData.new(x, y, type, data, strike[:ppem], strike[:resolution])
|
63
|
+
}
|
32
64
|
end
|
33
65
|
end
|
34
66
|
end
|
35
67
|
|
68
|
+
# Get all bitmaps for glyph.
|
69
|
+
#
|
70
|
+
# @param glyph_id [Integer]
|
71
|
+
# @return [Array<BitmapData>]
|
36
72
|
def all_bitmap_data_for(glyph_id)
|
37
|
-
strikes.each_index.
|
73
|
+
strikes.each_index.filter_map { |strike_index|
|
38
74
|
bitmap_data_for(glyph_id, strike_index)
|
39
|
-
|
75
|
+
}
|
40
76
|
end
|
41
77
|
|
42
78
|
private
|
@@ -46,21 +82,21 @@ module TTFunk
|
|
46
82
|
strike_offsets = Array.new(num_strikes) { read(4, 'N').first }
|
47
83
|
|
48
84
|
@strikes =
|
49
|
-
strike_offsets.map
|
50
|
-
parse_from(offset + strike_offset)
|
85
|
+
strike_offsets.map { |strike_offset|
|
86
|
+
parse_from(offset + strike_offset) {
|
51
87
|
ppem, resolution = read(4, 'n2')
|
52
88
|
data_offsets =
|
53
|
-
Array.new(file.maximum_profile.num_glyphs + 1)
|
89
|
+
Array.new(file.maximum_profile.num_glyphs + 1) {
|
54
90
|
read(4, 'N').first
|
55
|
-
|
91
|
+
}
|
56
92
|
{
|
57
93
|
ppem: ppem,
|
58
94
|
resolution: resolution,
|
59
95
|
offset: strike_offset,
|
60
|
-
glyph_data_offset: data_offsets
|
96
|
+
glyph_data_offset: data_offsets,
|
61
97
|
}
|
62
|
-
|
63
|
-
|
98
|
+
}
|
99
|
+
}
|
64
100
|
end
|
65
101
|
end
|
66
102
|
end
|
data/lib/ttfunk/table/simple.rb
CHANGED
@@ -4,9 +4,14 @@ require_relative '../table'
|
|
4
4
|
|
5
5
|
module TTFunk
|
6
6
|
class Table
|
7
|
+
# A table that TTFunk doesn't decode but preserve.
|
7
8
|
class Simple < Table
|
9
|
+
# Table tag
|
10
|
+
# @return [String]
|
8
11
|
attr_reader :tag
|
9
12
|
|
13
|
+
# @param file [TTFunk::File]
|
14
|
+
# @param tag [String]
|
10
15
|
def initialize(file, tag)
|
11
16
|
@tag = tag
|
12
17
|
super(file)
|