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
@@ -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
|