ttfunk 1.7.0 → 1.8.0
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
- 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
@@ -3,26 +3,38 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Cff < TTFunk::Table
|
6
|
+
# CFF Font Dict Index.
|
6
7
|
class FontIndex < TTFunk::Table::Cff::Index
|
8
|
+
# Top dict.
|
9
|
+
# @return [TTFunk::Table::Cff::TopDict]
|
7
10
|
attr_reader :top_dict
|
8
11
|
|
12
|
+
# @param top_dict [TTFunk::Table:Cff::TopDict]
|
13
|
+
# @param file [TTFunk::File]
|
14
|
+
# @param offset [Integer]
|
15
|
+
# @param length [Integer]
|
9
16
|
def initialize(top_dict, file, offset, length = nil)
|
10
17
|
super(file, offset, length)
|
11
18
|
@top_dict = top_dict
|
12
19
|
end
|
13
20
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
)
|
21
|
-
end
|
21
|
+
# Finalize index.
|
22
|
+
#
|
23
|
+
# @param new_cff_data [TTFunk::EncodedString]
|
24
|
+
# @return [void]
|
25
|
+
def finalize(new_cff_data)
|
26
|
+
each { |font_dict| font_dict.finalize(new_cff_data) }
|
22
27
|
end
|
23
28
|
|
24
|
-
|
25
|
-
|
29
|
+
private
|
30
|
+
|
31
|
+
def decode_item(_index, offset, length)
|
32
|
+
TTFunk::Table::Cff::FontDict.new(top_dict, file, offset, length)
|
33
|
+
end
|
34
|
+
|
35
|
+
def encode_items(*)
|
36
|
+
# Re-encode font dicts
|
37
|
+
map(&:encode)
|
26
38
|
end
|
27
39
|
end
|
28
40
|
end
|
@@ -3,21 +3,34 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Cff < TTFunk::Table
|
6
|
+
# CFF Header.
|
6
7
|
class Header < TTFunk::SubTable
|
7
|
-
#
|
8
|
+
# CFF table major version.
|
9
|
+
# @return [Integer]
|
8
10
|
attr_reader :major
|
11
|
+
|
12
|
+
# CFF table minor version.
|
13
|
+
# @return [Integer]
|
9
14
|
attr_reader :minor
|
10
15
|
|
11
|
-
#
|
16
|
+
# Size of the header itself.
|
17
|
+
# @return [Integer]
|
12
18
|
attr_reader :header_size
|
13
19
|
|
14
|
-
#
|
20
|
+
# Size of all offsets from beginning of table.
|
21
|
+
# @return [Integer]
|
15
22
|
attr_reader :absolute_offset_size
|
16
23
|
|
24
|
+
# Length of header.
|
25
|
+
#
|
26
|
+
# @return [Integer]
|
17
27
|
def length
|
18
28
|
4
|
19
29
|
end
|
20
30
|
|
31
|
+
# Encode header.
|
32
|
+
#
|
33
|
+
# @return [String]
|
21
34
|
def encode
|
22
35
|
[major, minor, header_size, absolute_offset_size].pack('C*')
|
23
36
|
end
|
@@ -3,75 +3,104 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Cff < TTFunk::Table
|
6
|
+
# CFF Index.
|
6
7
|
class Index < TTFunk::SubTable
|
7
8
|
include Enumerable
|
8
9
|
|
9
|
-
#
|
10
|
-
|
11
|
-
|
12
|
-
#
|
13
|
-
attr_reader :offset_size
|
14
|
-
|
15
|
-
attr_reader :raw_offset_length, :offsets, :raw_data
|
16
|
-
attr_reader :data_start_pos
|
17
|
-
|
10
|
+
# Get value by index.
|
11
|
+
#
|
12
|
+
# @param index [Integer]
|
13
|
+
# @return [any]
|
18
14
|
def [](index)
|
19
|
-
|
20
|
-
|
21
|
-
]
|
15
|
+
return if index >= items_count
|
16
|
+
|
17
|
+
entry_cache[index] ||=
|
18
|
+
decode_item(
|
19
|
+
index,
|
20
|
+
data_reference_offset + offsets[index],
|
21
|
+
offsets[index + 1] - offsets[index],
|
22
|
+
)
|
22
23
|
end
|
23
24
|
|
24
|
-
|
25
|
-
|
25
|
+
# Iterate over index items.
|
26
|
+
#
|
27
|
+
# @overload each()
|
28
|
+
# @yieldparam item [any]
|
29
|
+
# @return [void]
|
30
|
+
# @overload each()
|
31
|
+
# @return [Enumerator]
|
32
|
+
def each(&block)
|
33
|
+
return to_enum(__method__) unless block
|
34
|
+
|
35
|
+
items_count.times do |i|
|
36
|
+
yield(self[i])
|
37
|
+
end
|
38
|
+
end
|
26
39
|
|
27
|
-
|
40
|
+
# Numer of items in this index.
|
41
|
+
#
|
42
|
+
# @return [Integer]
|
43
|
+
def items_count
|
44
|
+
items.length
|
28
45
|
end
|
29
46
|
|
30
|
-
|
31
|
-
|
47
|
+
# Encode index.
|
48
|
+
#
|
49
|
+
# @param args all arguments are passed to `encode_item` method.
|
50
|
+
# @return [TTFunk::EncodedString]
|
51
|
+
def encode(*args)
|
52
|
+
new_items = encode_items(*args)
|
32
53
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
ret << new_entry if new_entry
|
37
|
-
end
|
54
|
+
if new_items.empty?
|
55
|
+
return [0].pack('n')
|
56
|
+
end
|
38
57
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
result << [entries.size].pack('n')
|
43
|
-
return result if entries.empty?
|
58
|
+
if new_items.length > 0xffff
|
59
|
+
raise Error, 'Too many items in a CFF index'
|
60
|
+
end
|
44
61
|
|
45
|
-
|
46
|
-
|
47
|
-
|
62
|
+
offsets_array =
|
63
|
+
new_items
|
64
|
+
.each_with_object([1]) { |item, offsets|
|
65
|
+
offsets << (offsets.last + item.length)
|
66
|
+
}
|
48
67
|
|
49
|
-
|
68
|
+
offset_size = (offsets_array.last.bit_length / 8.0).ceil
|
50
69
|
|
51
|
-
|
52
|
-
result << encode_offset(data_offset, offset_size)
|
53
|
-
data << entry
|
54
|
-
data_offset += entry.length
|
55
|
-
end
|
70
|
+
offsets_array.map! { |offset| encode_offset(offset, offset_size) }
|
56
71
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
72
|
+
EncodedString.new.concat(
|
73
|
+
[new_items.length, offset_size].pack('nC'),
|
74
|
+
*offsets_array,
|
75
|
+
*new_items,
|
76
|
+
)
|
62
77
|
end
|
63
78
|
|
64
79
|
private
|
65
80
|
|
81
|
+
attr_reader :items
|
82
|
+
attr_reader :offsets
|
83
|
+
attr_reader :data_reference_offset
|
84
|
+
|
66
85
|
def entry_cache
|
67
86
|
@entry_cache ||= {}
|
68
87
|
end
|
69
88
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
89
|
+
# Returns an array of EncodedString elements (plain strings,
|
90
|
+
# placeholders, or EncodedString instances). Each element is supposed to
|
91
|
+
# represent an encoded item.
|
92
|
+
#
|
93
|
+
# This is the place to do all the filtering, reordering, or individual
|
94
|
+
# item encoding.
|
95
|
+
#
|
96
|
+
# It gets all the arguments `encode` gets.
|
97
|
+
def encode_items(*)
|
98
|
+
items
|
99
|
+
end
|
100
|
+
|
101
|
+
# By default do nothing
|
102
|
+
def decode_item(index, _offset, _length)
|
103
|
+
items[index]
|
75
104
|
end
|
76
105
|
|
77
106
|
def encode_offset(offset, offset_size)
|
@@ -81,42 +110,45 @@ module TTFunk
|
|
81
110
|
when 2
|
82
111
|
[offset].pack('n')
|
83
112
|
when 3
|
84
|
-
[offset].pack('N')[1
|
113
|
+
[offset].pack('N')[1..]
|
85
114
|
when 4
|
86
115
|
[offset].pack('N')
|
87
116
|
end
|
88
117
|
end
|
89
118
|
|
90
119
|
def parse!
|
91
|
-
@
|
120
|
+
@entry_cache = {}
|
121
|
+
|
122
|
+
num_entries = read(2, 'n').first
|
92
123
|
|
93
|
-
if
|
124
|
+
if num_entries.zero?
|
94
125
|
@length = 2
|
95
|
-
@
|
126
|
+
@items = []
|
96
127
|
return
|
97
128
|
end
|
98
129
|
|
99
|
-
|
130
|
+
offset_size = read(1, 'C').first
|
100
131
|
|
101
|
-
|
102
|
-
|
103
|
-
|
132
|
+
@offsets =
|
133
|
+
Array.new(num_entries + 1) {
|
134
|
+
unpack_offset(io.read(offset_size), offset_size)
|
135
|
+
}
|
104
136
|
|
105
|
-
@
|
106
|
-
raw_offsets = io.read(raw_offset_length)
|
137
|
+
@data_reference_offset = table_offset + 3 + (offsets.length * offset_size) - 1
|
107
138
|
|
108
|
-
@
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
139
|
+
@length =
|
140
|
+
2 + # num entries
|
141
|
+
1 + # offset size
|
142
|
+
(offsets.length * offset_size) + # offsets
|
143
|
+
offsets.last - 1 # items
|
113
144
|
|
114
|
-
@
|
115
|
-
|
116
|
-
|
145
|
+
@items =
|
146
|
+
offsets.each_cons(2).map { |offset, next_offset|
|
147
|
+
io.read(next_offset - offset)
|
148
|
+
}
|
117
149
|
end
|
118
150
|
|
119
|
-
def unpack_offset(offset_data)
|
151
|
+
def unpack_offset(offset_data, offset_size)
|
120
152
|
padding = "\x00" * (4 - offset_size)
|
121
153
|
(padding + offset_data).unpack1('N')
|
122
154
|
end
|
@@ -5,22 +5,32 @@ require 'forwardable'
|
|
5
5
|
module TTFunk
|
6
6
|
class Table
|
7
7
|
class Cff < TTFunk::Table
|
8
|
+
# CFF Index with indexing starting at 1.
|
8
9
|
class OneBasedIndex
|
9
10
|
extend Forwardable
|
10
11
|
|
11
12
|
def_delegators :base_index,
|
12
13
|
:each,
|
13
14
|
:table_offset,
|
14
|
-
:
|
15
|
+
:items_count,
|
15
16
|
:length,
|
16
17
|
:encode
|
17
18
|
|
19
|
+
# Underlaying Index.
|
20
|
+
# @return [TTFunk::Table::Cff::Index]
|
18
21
|
attr_reader :base_index
|
19
22
|
|
23
|
+
# @param args [Array] all params are passed to the base index.
|
24
|
+
# @see Index
|
20
25
|
def initialize(*args)
|
21
26
|
@base_index = Index.new(*args)
|
22
27
|
end
|
23
28
|
|
29
|
+
# Get item by index.
|
30
|
+
#
|
31
|
+
# @param idx [Integer]
|
32
|
+
# @return [any]
|
33
|
+
# @raise [IndexError] when requested index is 0.
|
24
34
|
def [](idx)
|
25
35
|
if idx.zero?
|
26
36
|
raise IndexError,
|
@@ -3,33 +3,72 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Cff < TTFunk::Table
|
6
|
+
# Path. Mostly used for CFF glyph outlines.
|
6
7
|
class Path
|
8
|
+
# Close path command.
|
7
9
|
CLOSE_PATH_CMD = [:close].freeze
|
8
10
|
|
9
|
-
|
11
|
+
# Commands in this path.
|
12
|
+
# @return [Array]
|
13
|
+
attr_reader :commands
|
14
|
+
|
15
|
+
# Number of contours in this path.
|
16
|
+
# @return [Integer]
|
17
|
+
attr_reader :number_of_contours
|
10
18
|
|
11
19
|
def initialize
|
12
20
|
@commands = []
|
13
21
|
@number_of_contours = 0
|
14
22
|
end
|
15
23
|
|
24
|
+
# Move implicit cursor to coordinates.
|
25
|
+
#
|
26
|
+
# @param x [Integer, Float]
|
27
|
+
# @param y [Integer, Float]
|
28
|
+
# @return [void]
|
16
29
|
def move_to(x, y)
|
17
30
|
@commands << [:move, x, y]
|
18
31
|
end
|
19
32
|
|
33
|
+
# Add a line to coordinates.
|
34
|
+
#
|
35
|
+
# @param x [Integer, Float]
|
36
|
+
# @param y [Integer, Float]
|
37
|
+
# @return [void]
|
20
38
|
def line_to(x, y)
|
21
39
|
@commands << [:line, x, y]
|
22
40
|
end
|
23
41
|
|
24
|
-
|
42
|
+
# Add a Bézier curve. Current position is the first control point, (`x1`,
|
43
|
+
# `y1`) is the second, (`x2`, `y2`) is the third, and (`x`, `y`) is the
|
44
|
+
# last control point.
|
45
|
+
#
|
46
|
+
# @param x1 [Integer, Float]
|
47
|
+
# @param y1 [Integer, Float]
|
48
|
+
# @param x2 [Integer, Float]
|
49
|
+
# @param y2 [Integer, Float]
|
50
|
+
# @param x [Integer, Float]
|
51
|
+
# @param y [Integer, Float]
|
52
|
+
# @return [void]
|
53
|
+
def curve_to(x1, y1, x2, y2, x, y) # rubocop: disable Metrics/ParameterLists
|
25
54
|
@commands << [:curve, x1, y1, x2, y2, x, y]
|
26
55
|
end
|
27
56
|
|
57
|
+
# Close current contour.
|
58
|
+
#
|
59
|
+
# @return [void]
|
28
60
|
def close_path
|
29
61
|
@commands << CLOSE_PATH_CMD
|
30
62
|
@number_of_contours += 1
|
31
63
|
end
|
32
64
|
|
65
|
+
# Reposition and scale path.
|
66
|
+
#
|
67
|
+
# @param x [Integer, Float] new horizontal position.
|
68
|
+
# @param y [Integer, Float] new vertical position.
|
69
|
+
# @param font_size [Integer, Float] font size.
|
70
|
+
# @param units_per_em [Integer] units per Em as defined in the font.
|
71
|
+
# @return [TTFunk::Table::Cff::Path]
|
33
72
|
def render(x: 0, y: 0, font_size: 72, units_per_em: 1000)
|
34
73
|
new_path = self.class.new
|
35
74
|
scale = 1.0 / units_per_em * font_size
|
@@ -47,7 +86,7 @@ module TTFunk
|
|
47
86
|
x + (cmd[3] * scale),
|
48
87
|
y + (-cmd[4] * scale),
|
49
88
|
x + (cmd[5] * scale),
|
50
|
-
y + (-cmd[6] * scale)
|
89
|
+
y + (-cmd[6] * scale),
|
51
90
|
)
|
52
91
|
when :close
|
53
92
|
new_path.close_path
|
@@ -60,7 +99,7 @@ module TTFunk
|
|
60
99
|
private
|
61
100
|
|
62
101
|
def format_values(command)
|
63
|
-
command[1
|
102
|
+
command[1..].map { |k| format('%.2f', k) }.join(' ')
|
64
103
|
end
|
65
104
|
end
|
66
105
|
end
|
@@ -3,22 +3,33 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Cff < TTFunk::Table
|
6
|
+
# CFF Private dict.
|
6
7
|
class PrivateDict < TTFunk::Table::Cff::Dict
|
8
|
+
# Default value of Default Width X.
|
7
9
|
DEFAULT_WIDTH_X_DEFAULT = 0
|
10
|
+
|
11
|
+
# Default value of Nominal Width X.
|
8
12
|
DEFAULT_WIDTH_X_NOMINAL = 0
|
13
|
+
|
14
|
+
# Length of placeholders.
|
9
15
|
PLACEHOLDER_LENGTH = 5
|
10
16
|
|
17
|
+
# Operators we care about in this dict.
|
11
18
|
OPERATORS = {
|
12
19
|
subrs: 19,
|
13
20
|
default_width_x: 20,
|
14
|
-
nominal_width_x: 21
|
21
|
+
nominal_width_x: 21,
|
15
22
|
}.freeze
|
16
23
|
|
24
|
+
# Inverse operator mapping.
|
17
25
|
OPERATOR_CODES = OPERATORS.invert
|
18
26
|
|
19
|
-
#
|
20
|
-
#
|
21
|
-
|
27
|
+
# Encode dict.
|
28
|
+
#
|
29
|
+
# @return [TTFunk::EncodedString]
|
30
|
+
def encode
|
31
|
+
# TODO: use mapping to determine which subroutines are still used.
|
32
|
+
# For now, just encode them all.
|
22
33
|
EncodedString.new do |result|
|
23
34
|
each do |operator, operands|
|
24
35
|
case OPERATOR_CODES[operator]
|
@@ -33,19 +44,24 @@ module TTFunk
|
|
33
44
|
end
|
34
45
|
end
|
35
46
|
|
47
|
+
# Finalize dict.
|
48
|
+
#
|
49
|
+
# @param private_dict_data [TTFunk::EncodedString]
|
50
|
+
# @return [void]
|
36
51
|
def finalize(private_dict_data)
|
37
52
|
return unless subr_index
|
38
53
|
|
39
54
|
encoded_subr_index = subr_index.encode
|
40
55
|
encoded_offset = encode_integer32(private_dict_data.length)
|
41
56
|
|
42
|
-
private_dict_data.resolve_placeholder(
|
43
|
-
:"subrs_#{@table_offset}", encoded_offset
|
44
|
-
)
|
57
|
+
private_dict_data.resolve_placeholder(:"subrs_#{@table_offset}", encoded_offset)
|
45
58
|
|
46
59
|
private_dict_data << encoded_subr_index
|
47
60
|
end
|
48
61
|
|
62
|
+
# Subroutine index.
|
63
|
+
#
|
64
|
+
# @return [TTFunk::Table::Cff::SubrIndex, nil]
|
49
65
|
def subr_index
|
50
66
|
@subr_index ||=
|
51
67
|
if (subr_offset = self[OPERATORS[:subrs]])
|
@@ -53,6 +69,9 @@ module TTFunk
|
|
53
69
|
end
|
54
70
|
end
|
55
71
|
|
72
|
+
# Default Width X.
|
73
|
+
#
|
74
|
+
# @return [Integer]
|
56
75
|
def default_width_x
|
57
76
|
if (width = self[OPERATORS[:default_width_x]])
|
58
77
|
width.first
|
@@ -61,6 +80,9 @@ module TTFunk
|
|
61
80
|
end
|
62
81
|
end
|
63
82
|
|
83
|
+
# Nominal Width X.
|
84
|
+
#
|
85
|
+
# @return [Integer]
|
64
86
|
def nominal_width_x
|
65
87
|
if (width = self[OPERATORS[:nominal_width_x]])
|
66
88
|
width.first
|
@@ -72,10 +94,8 @@ module TTFunk
|
|
72
94
|
private
|
73
95
|
|
74
96
|
def encode_subrs
|
75
|
-
EncodedString.new
|
76
|
-
result << Placeholder.new(
|
77
|
-
:"subrs_#{@table_offset}", length: PLACEHOLDER_LENGTH
|
78
|
-
)
|
97
|
+
EncodedString.new do |result|
|
98
|
+
result << Placeholder.new(:"subrs_#{@table_offset}", length: PLACEHOLDER_LENGTH)
|
79
99
|
end
|
80
100
|
end
|
81
101
|
end
|
@@ -3,11 +3,16 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Cff < TTFunk::Table
|
6
|
+
# CFF Subroutine index.
|
6
7
|
class SubrIndex < TTFunk::Table::Cff::Index
|
8
|
+
# Subroutine index biase. For correct subroutine selection the
|
9
|
+
# calculated bias must be added to the subroutine number operand before
|
10
|
+
# accessing the index.
|
11
|
+
# @return [Integer]
|
7
12
|
def bias
|
8
|
-
if
|
13
|
+
if items.length < 1240
|
9
14
|
107
|
10
|
-
elsif
|
15
|
+
elsif items.length < 33_900
|
11
16
|
1131
|
12
17
|
else
|
13
18
|
32_768
|