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,31 +3,41 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Cff < TTFunk::Table
|
6
|
+
# CFF top dict.
|
6
7
|
class TopDict < TTFunk::Table::Cff::Dict
|
8
|
+
# Default charstring type.
|
7
9
|
DEFAULT_CHARSTRING_TYPE = 2
|
10
|
+
|
11
|
+
# Length of placeholders for pointer operators.
|
8
12
|
POINTER_PLACEHOLDER_LENGTH = 5
|
13
|
+
|
14
|
+
# Length of placeholders for other operators.
|
9
15
|
PLACEHOLDER_LENGTH = 5
|
10
16
|
|
11
|
-
#
|
12
|
-
# of the file
|
17
|
+
# Operators whose values are offsets that point to other parts
|
18
|
+
# of the file.
|
13
19
|
POINTER_OPERATORS = {
|
14
20
|
charset: 15,
|
15
21
|
encoding: 16,
|
16
22
|
charstrings_index: 17,
|
17
23
|
private: 18,
|
18
24
|
font_index: 1236,
|
19
|
-
font_dict_selector: 1237
|
25
|
+
font_dict_selector: 1237,
|
20
26
|
}.freeze
|
21
27
|
|
22
|
-
#
|
28
|
+
# All the operators we currently care about.
|
23
29
|
OPERATORS = {
|
24
30
|
**POINTER_OPERATORS,
|
25
31
|
ros: 1230,
|
26
|
-
charstring_type: 1206
|
32
|
+
charstring_type: 1206,
|
27
33
|
}.freeze
|
28
34
|
|
35
|
+
# Inverse operator mapping.
|
29
36
|
OPERATOR_CODES = OPERATORS.invert
|
30
37
|
|
38
|
+
# Encode dict.
|
39
|
+
#
|
40
|
+
# @return [TTFunk::EncodedString]
|
31
41
|
def encode(*)
|
32
42
|
EncodedString.new do |result|
|
33
43
|
each_with_index do |(operator, operands), _idx|
|
@@ -36,7 +46,7 @@ module TTFunk
|
|
36
46
|
elsif pointer_operator?(operator)
|
37
47
|
result << Placeholder.new(
|
38
48
|
OPERATOR_CODES[operator],
|
39
|
-
length: POINTER_PLACEHOLDER_LENGTH
|
49
|
+
length: POINTER_PLACEHOLDER_LENGTH,
|
40
50
|
)
|
41
51
|
else
|
42
52
|
operands.each { |operand| result << encode_operand(operand) }
|
@@ -47,75 +57,69 @@ module TTFunk
|
|
47
57
|
end
|
48
58
|
end
|
49
59
|
|
50
|
-
|
60
|
+
# Finalize the table.
|
61
|
+
#
|
62
|
+
# @param new_cff_data [TTFunk::EncodedString]
|
63
|
+
# @param charmap [Hash{Integer => Hash}] keys are the charac codes,
|
64
|
+
# values are hashes:
|
65
|
+
# * `:old` (<tt>Integer</tt>) - glyph ID in the original font.
|
66
|
+
# * `:new` (<tt>Integer</tt>) - glyph ID in the subset font.
|
67
|
+
# @return [void]
|
68
|
+
def finalize(new_cff_data, charmap)
|
51
69
|
if charset
|
52
|
-
finalize_subtable(
|
53
|
-
new_cff_data, :charset, charset.encode(new_to_old)
|
54
|
-
)
|
70
|
+
finalize_subtable(new_cff_data, :charset, charset.encode(charmap))
|
55
71
|
end
|
56
72
|
|
57
73
|
if encoding
|
58
|
-
finalize_subtable(
|
59
|
-
new_cff_data, :encoding, encoding.encode(new_to_old, old_to_new)
|
60
|
-
)
|
74
|
+
finalize_subtable(new_cff_data, :encoding, encoding.encode(charmap))
|
61
75
|
end
|
62
76
|
|
63
77
|
if charstrings_index
|
64
|
-
finalize_subtable(
|
65
|
-
new_cff_data,
|
66
|
-
:charstrings_index,
|
67
|
-
charstrings_index.encode(new_to_old, &:encode)
|
68
|
-
)
|
78
|
+
finalize_subtable(new_cff_data, :charstrings_index, charstrings_index.encode(charmap))
|
69
79
|
end
|
70
80
|
|
71
81
|
if font_index
|
72
|
-
finalize_subtable(
|
73
|
-
new_cff_data,
|
74
|
-
:font_index,
|
75
|
-
font_index.encode do |font_dict|
|
76
|
-
font_dict.encode(new_to_old)
|
77
|
-
end
|
78
|
-
)
|
82
|
+
finalize_subtable(new_cff_data, :font_index, font_index.encode)
|
79
83
|
|
80
|
-
font_index.finalize(new_cff_data
|
84
|
+
font_index.finalize(new_cff_data)
|
81
85
|
end
|
82
86
|
|
83
87
|
if font_dict_selector
|
84
|
-
finalize_subtable(
|
85
|
-
new_cff_data,
|
86
|
-
:font_dict_selector,
|
87
|
-
font_dict_selector.encode(new_to_old)
|
88
|
-
)
|
88
|
+
finalize_subtable(new_cff_data, :font_dict_selector, font_dict_selector.encode(charmap))
|
89
89
|
end
|
90
90
|
|
91
91
|
if private_dict
|
92
|
-
encoded_private_dict = private_dict.encode
|
92
|
+
encoded_private_dict = private_dict.encode
|
93
93
|
encoded_offset = encode_integer32(new_cff_data.length)
|
94
94
|
encoded_length = encode_integer32(encoded_private_dict.length)
|
95
95
|
|
96
|
-
new_cff_data.resolve_placeholder(
|
97
|
-
|
98
|
-
)
|
99
|
-
|
100
|
-
new_cff_data.resolve_placeholder(
|
101
|
-
:"private_offset_#{@table_offset}", encoded_offset
|
102
|
-
)
|
96
|
+
new_cff_data.resolve_placeholder(:"private_length_#{@table_offset}", encoded_length)
|
97
|
+
new_cff_data.resolve_placeholder(:"private_offset_#{@table_offset}", encoded_offset)
|
103
98
|
|
104
99
|
private_dict.finalize(encoded_private_dict)
|
105
100
|
new_cff_data << encoded_private_dict
|
106
101
|
end
|
107
102
|
end
|
108
103
|
|
104
|
+
# Registry Ordering Supplement.
|
105
|
+
#
|
106
|
+
# @return [Array(Integer, Integer, Integer), nil]
|
109
107
|
def ros
|
110
108
|
self[OPERATORS[:ros]]
|
111
109
|
end
|
112
110
|
|
111
|
+
# Is Registry Ordering Supplement present in this dict?
|
112
|
+
#
|
113
|
+
# @return [Boolean]
|
113
114
|
def ros?
|
114
115
|
!ros.nil?
|
115
116
|
end
|
116
117
|
|
117
118
|
alias is_cid_font? ros?
|
118
119
|
|
120
|
+
# Charset specified in this dict.
|
121
|
+
#
|
122
|
+
# @return [TTFunk::Table::Cff::Charset, nil]
|
119
123
|
def charset
|
120
124
|
@charset ||=
|
121
125
|
if (charset_offset_or_id = self[OPERATORS[:charset]])
|
@@ -127,38 +131,47 @@ module TTFunk
|
|
127
131
|
end
|
128
132
|
end
|
129
133
|
|
134
|
+
# Encoding specified in this dict.
|
135
|
+
#
|
136
|
+
# @return [TTFunk::Table::Cff::Encoding, nil]
|
130
137
|
def encoding
|
138
|
+
# PostScript type 1 fonts, i.e. CID fonts, i.e. some fonts that use
|
139
|
+
# the CFF table, don't specify an encoding, so this can be nil
|
131
140
|
@encoding ||=
|
132
|
-
|
133
|
-
|
134
|
-
# the CFF table, don't specify an encoding, so this can be nil
|
135
|
-
if (encoding_offset_or_id = self[OPERATORS[:encoding]])
|
136
|
-
Encoding.new(self, file, encoding_offset_or_id.first)
|
137
|
-
end
|
141
|
+
if (encoding_offset_or_id = self[OPERATORS[:encoding]])
|
142
|
+
Encoding.new(self, file, encoding_offset_or_id.first)
|
138
143
|
end
|
139
144
|
end
|
140
145
|
|
141
|
-
#
|
146
|
+
# Charstrings index specified in this dict.
|
147
|
+
#
|
148
|
+
# > OpenType fonts with TrueType outlines use a glyph index to specify
|
149
|
+
# and access glyphs within a font; e.g., to index within the `loca`
|
150
|
+
# table and thereby access glyph data in the `glyf` table. This
|
151
|
+
# concept is retained in OpenType CFF fonts, except that glyph data is
|
152
|
+
# accessed through the CharStrings INDEX of the CFF table.
|
153
|
+
#
|
154
|
+
# > --- [CFF — Compact Font Format Table](https://www.microsoft.com/typography/otspec/cff.htm)
|
142
155
|
#
|
143
|
-
#
|
144
|
-
# and access glyphs within a font; e.g., to index within the 'loca'
|
145
|
-
# table and thereby access glyph data in the 'glyf' table. This concept
|
146
|
-
# is retained in OpenType CFF fonts, except that glyph data is accessed
|
147
|
-
# through the CharStrings INDEX of the CFF table."
|
156
|
+
# @return [TTFunk::Table::Cff::CharstringsIndex, nil]
|
148
157
|
def charstrings_index
|
149
158
|
@charstrings_index ||=
|
150
159
|
if (charstrings_offset = self[OPERATORS[:charstrings_index]])
|
151
|
-
CharstringsIndex.new(
|
152
|
-
self, file, cff_offset + charstrings_offset.first
|
153
|
-
)
|
160
|
+
CharstringsIndex.new(self, file, cff_offset + charstrings_offset.first)
|
154
161
|
end
|
155
162
|
end
|
156
163
|
|
164
|
+
# Charstring type specified in this dict.
|
165
|
+
#
|
166
|
+
# @return [Integer]
|
157
167
|
def charstring_type
|
158
168
|
@charstring_type =
|
159
169
|
self[OPERATORS[:charstring_type]] || DEFAULT_CHARSTRING_TYPE
|
160
170
|
end
|
161
171
|
|
172
|
+
# Font index specified in this dict.
|
173
|
+
#
|
174
|
+
# @return [TTFunk::Table::Cff::FontIndex, nil]
|
162
175
|
def font_index
|
163
176
|
@font_index ||=
|
164
177
|
if (font_index_offset = self[OPERATORS[:font_index]])
|
@@ -166,6 +179,9 @@ module TTFunk
|
|
166
179
|
end
|
167
180
|
end
|
168
181
|
|
182
|
+
# Font dict selector specified in this dict.
|
183
|
+
#
|
184
|
+
# @return [TTFunk::Table::Cff::FdSelector, nil]
|
169
185
|
def font_dict_selector
|
170
186
|
@font_dict_selector ||=
|
171
187
|
if (fd_select_offset = self[OPERATORS[:font_dict_selector]])
|
@@ -173,21 +189,28 @@ module TTFunk
|
|
173
189
|
end
|
174
190
|
end
|
175
191
|
|
192
|
+
# Private dict specified in this dict.
|
193
|
+
#
|
194
|
+
# @return [TTFunk::Table::Cff::PrivateDict, nil]
|
176
195
|
def private_dict
|
177
196
|
@private_dict ||=
|
178
197
|
if (info = self[OPERATORS[:private]])
|
179
198
|
private_dict_length, private_dict_offset = info
|
180
199
|
|
181
|
-
PrivateDict.new(
|
182
|
-
file, cff_offset + private_dict_offset, private_dict_length
|
183
|
-
)
|
200
|
+
PrivateDict.new(file, cff_offset + private_dict_offset, private_dict_length)
|
184
201
|
end
|
185
202
|
end
|
186
203
|
|
204
|
+
# CFF table in this file.
|
205
|
+
#
|
206
|
+
# @return [TTFunk::Table::Cff]
|
187
207
|
def cff
|
188
208
|
file.cff
|
189
209
|
end
|
190
210
|
|
211
|
+
# Ofsset of CFF table in the file.
|
212
|
+
#
|
213
|
+
# @return [Integer]
|
191
214
|
def cff_offset
|
192
215
|
cff.offset
|
193
216
|
end
|
@@ -198,12 +221,12 @@ module TTFunk
|
|
198
221
|
EncodedString.new do |result|
|
199
222
|
result << Placeholder.new(
|
200
223
|
:"private_length_#{@table_offset}",
|
201
|
-
length: PLACEHOLDER_LENGTH
|
224
|
+
length: PLACEHOLDER_LENGTH,
|
202
225
|
)
|
203
226
|
|
204
227
|
result << Placeholder.new(
|
205
228
|
:"private_offset_#{@table_offset}",
|
206
|
-
length: PLACEHOLDER_LENGTH
|
229
|
+
length: PLACEHOLDER_LENGTH,
|
207
230
|
)
|
208
231
|
end
|
209
232
|
end
|
@@ -3,13 +3,17 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Cff < TTFunk::Table
|
6
|
+
# CFF Index conatining Top dict.
|
6
7
|
class TopIndex < TTFunk::Table::Cff::Index
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
private
|
9
|
+
|
10
|
+
def decode_item(_index, offset, length)
|
11
|
+
TTFunk::Table::Cff::TopDict.new(file, offset, length)
|
12
|
+
end
|
13
|
+
|
14
|
+
def encode_items(*)
|
15
|
+
# Re-encode the top dict
|
16
|
+
map(&:encode)
|
13
17
|
end
|
14
18
|
end
|
15
19
|
end
|
data/lib/ttfunk/table/cff.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
|
+
# Compact Font Format (`CFF `) table
|
5
6
|
class Cff < TTFunk::Table
|
6
7
|
autoload :Charset, 'ttfunk/table/cff/charset'
|
7
8
|
autoload :Charsets, 'ttfunk/table/cff/charsets'
|
@@ -22,27 +23,55 @@ module TTFunk
|
|
22
23
|
autoload :TopDict, 'ttfunk/table/cff/top_dict'
|
23
24
|
autoload :TopIndex, 'ttfunk/table/cff/top_index'
|
24
25
|
|
25
|
-
|
26
|
+
# Table tag. The extra space is important.
|
27
|
+
TAG = 'CFF '
|
26
28
|
|
27
|
-
|
29
|
+
# Table header.
|
30
|
+
# @return [TTFunk::Table::Cff::Header]
|
31
|
+
attr_reader :header
|
32
|
+
|
33
|
+
# Name index.
|
34
|
+
# @return [TTFunk::Table::Cff::Index]
|
35
|
+
attr_reader :name_index
|
36
|
+
|
37
|
+
# Top dict index.
|
38
|
+
# @return [TTFunk::Table::Cff::TopIndex]
|
39
|
+
attr_reader :top_index
|
40
|
+
|
41
|
+
# Strings index.
|
42
|
+
# @return [TTFunk::Table::Cff::OneBasedIndex]
|
43
|
+
attr_reader :string_index
|
44
|
+
|
45
|
+
# Global subroutine index.
|
46
|
+
# @return [TTFunk::Table::Cff::SubrIndex]
|
28
47
|
attr_reader :global_subr_index
|
29
48
|
|
49
|
+
# Table tag.
|
50
|
+
# @return [String]
|
30
51
|
def tag
|
31
52
|
TAG
|
32
53
|
end
|
33
54
|
|
34
|
-
|
55
|
+
# Encode table.
|
56
|
+
#
|
57
|
+
# @param subset [TTFunk::Subset::MacRoman, TTFunk::Subset::Windows1252,
|
58
|
+
# TTFunk::Subset::Unicode, TTFunk::Subset::Unicode8Bit]
|
59
|
+
# @return [TTFunk::EncodedString]
|
60
|
+
def encode(subset)
|
61
|
+
# Make sure TopDict has an entry for encoding so it could be properly replaced
|
62
|
+
top_index[0][TopDict::OPERATORS[:encoding]] = 0
|
63
|
+
|
35
64
|
EncodedString.new do |result|
|
36
|
-
|
65
|
+
result.concat(
|
37
66
|
header.encode,
|
38
67
|
name_index.encode,
|
39
|
-
top_index.encode
|
68
|
+
top_index.encode,
|
40
69
|
string_index.encode,
|
41
|
-
global_subr_index.encode
|
42
|
-
|
70
|
+
global_subr_index.encode,
|
71
|
+
)
|
43
72
|
|
44
|
-
|
45
|
-
top_index[0].finalize(result,
|
73
|
+
charmap = subset.new_cmap_table[:charmap]
|
74
|
+
top_index[0].finalize(result, charmap)
|
46
75
|
end
|
47
76
|
end
|
48
77
|
|
@@ -51,18 +80,9 @@ module TTFunk
|
|
51
80
|
def parse!
|
52
81
|
@header = Header.new(file, offset)
|
53
82
|
@name_index = Index.new(file, @header.table_offset + @header.length)
|
54
|
-
|
55
|
-
@
|
56
|
-
|
57
|
-
)
|
58
|
-
|
59
|
-
@string_index = OneBasedIndex.new(
|
60
|
-
file, @top_index.table_offset + @top_index.length
|
61
|
-
)
|
62
|
-
|
63
|
-
@global_subr_index = SubrIndex.new(
|
64
|
-
file, @string_index.table_offset + @string_index.length
|
65
|
-
)
|
83
|
+
@top_index = TopIndex.new(file, @name_index.table_offset + @name_index.length)
|
84
|
+
@string_index = OneBasedIndex.new(file, @top_index.table_offset + @top_index.length)
|
85
|
+
@global_subr_index = SubrIndex.new(file, @string_index.table_offset + @string_index.length)
|
66
86
|
end
|
67
87
|
end
|
68
88
|
end
|
@@ -3,16 +3,30 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Cmap
|
6
|
+
# Format 0: Byte encoding table.
|
7
|
+
#
|
8
|
+
# This module conditionally extends {TTFunk::Table::Cmap::Subtable}.
|
6
9
|
module Format00
|
10
|
+
# Language.
|
11
|
+
# @return [Integer]
|
7
12
|
attr_reader :language
|
13
|
+
|
14
|
+
# Code map.
|
15
|
+
# @return [Array<Integer>]
|
8
16
|
attr_reader :code_map
|
9
17
|
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
18
|
+
# Encode the encoding record to format 0.
|
19
|
+
#
|
20
|
+
# @param charmap [Hash{Integer => Integer}] a hash mapping character
|
21
|
+
# codes to glyph ids (where the glyph ids are from the original font).
|
22
|
+
# @return [Hash]
|
23
|
+
# * `:charmap` (<tt>Hash{Integer => Hash}</tt>) keys are the characrers in
|
24
|
+
# `charset`, values are hashes:
|
25
|
+
# * `:old` (<tt>Integer</tt>) - glyph ID in the original font.
|
26
|
+
# * `:new` (<tt>Integer</tt>) - glyph ID in the subset font.
|
27
|
+
# that maps the characters in charmap to a
|
28
|
+
# * `:subtable` (<tt>String</tt>) - serialized encoding record.
|
29
|
+
# * `:max_glyph_id` (<tt>Integer</tt>) - maximum glyph ID in the new font.
|
16
30
|
def self.encode(charmap)
|
17
31
|
next_id = 0
|
18
32
|
glyph_indexes = Array.new(256, 0)
|
@@ -32,10 +46,17 @@ module TTFunk
|
|
32
46
|
{ charmap: new_map, subtable: subtable, max_glyph_id: next_id + 1 }
|
33
47
|
end
|
34
48
|
|
49
|
+
# Get glyph ID for character code.
|
50
|
+
#
|
51
|
+
# @param code [Integer] character code.
|
52
|
+
# @return [Integer] glyph ID.
|
35
53
|
def [](code)
|
36
54
|
@code_map[code] || 0
|
37
55
|
end
|
38
56
|
|
57
|
+
# Is this encoding record format supported?
|
58
|
+
#
|
59
|
+
# @return [true]
|
39
60
|
def supported?
|
40
61
|
true
|
41
62
|
end
|
@@ -3,16 +3,30 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Cmap
|
6
|
+
# Format 4: Segment mapping to delta values.
|
7
|
+
#
|
8
|
+
# This module conditionally extends {TTFunk::Table::Cmap::Subtable}.
|
6
9
|
module Format04
|
10
|
+
# Language.
|
11
|
+
# @return [Integer]
|
7
12
|
attr_reader :language
|
13
|
+
|
14
|
+
# Code map.
|
15
|
+
# @return [Hash{Integer => Integer}]
|
8
16
|
attr_reader :code_map
|
9
17
|
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
18
|
+
# Encode the encoding record to format 4.
|
19
|
+
#
|
20
|
+
# @param charmap [Hash{Integer => Integer}] a hash mapping character
|
21
|
+
# codes to glyph IDs from the original font.
|
22
|
+
# @return [Hash]
|
23
|
+
# * `:charmap` (<tt>Hash{Integer => Hash}</tt>) keys are the characrers in
|
24
|
+
# `charset`, values are hashes:
|
25
|
+
# * `:old` (<tt>Integer</tt>) - glyph ID in the original font.
|
26
|
+
# * `:new` (<tt>Integer</tt>) - glyph ID in the subset font.
|
27
|
+
# that maps the characters in charmap to a
|
28
|
+
# * `:subtable` (<tt>String</tt>) - serialized encoding record.
|
29
|
+
# * `:max_glyph_id` (<tt>Integer</tt>) - maximum glyph ID in the new font.
|
16
30
|
def self.encode(charmap)
|
17
31
|
end_codes = []
|
18
32
|
start_codes = []
|
@@ -63,10 +77,10 @@ module TTFunk
|
|
63
77
|
|
64
78
|
if a - start_glyph_id >= 0x8000
|
65
79
|
deltas << 0
|
66
|
-
range_offsets << 2 * (glyph_indices.length + segcount - segment)
|
80
|
+
range_offsets << (2 * (glyph_indices.length + segcount - segment))
|
67
81
|
a.upto(b) { |code| glyph_indices << new_map[code][:new] }
|
68
82
|
else
|
69
|
-
deltas << -a + start_glyph_id
|
83
|
+
deltas << (-a + start_glyph_id)
|
70
84
|
range_offsets << 0
|
71
85
|
end
|
72
86
|
|
@@ -75,14 +89,14 @@ module TTFunk
|
|
75
89
|
|
76
90
|
# format, length, language
|
77
91
|
subtable = [
|
78
|
-
4, 16 + 8 * segcount + 2 * glyph_indices.length, 0
|
92
|
+
4, 16 + (8 * segcount) + (2 * glyph_indices.length), 0,
|
79
93
|
].pack('nnn')
|
80
94
|
|
81
|
-
search_range = 2 * 2**(Math.log(segcount) / Math.log(2))
|
82
|
-
entry_selector = (Math.log(search_range / 2) / Math.log(2))
|
95
|
+
search_range = 2 * (2**Integer(Math.log(segcount) / Math.log(2)))
|
96
|
+
entry_selector = Integer(Math.log(search_range / 2) / Math.log(2))
|
83
97
|
range_shift = (2 * segcount) - search_range
|
84
98
|
subtable << [
|
85
|
-
segcount * 2, search_range, entry_selector, range_shift
|
99
|
+
segcount * 2, search_range, entry_selector, range_shift,
|
86
100
|
].pack('nnnn')
|
87
101
|
|
88
102
|
subtable << end_codes.pack('n*') << "\0\0" << start_codes.pack('n*')
|
@@ -92,10 +106,17 @@ module TTFunk
|
|
92
106
|
{ charmap: new_map, subtable: subtable, max_glyph_id: next_id + 1 }
|
93
107
|
end
|
94
108
|
|
109
|
+
# Get glyph ID for character code.
|
110
|
+
#
|
111
|
+
# @param code [Integer] character code.
|
112
|
+
# @return [Integer] glyph ID.
|
95
113
|
def [](code)
|
96
114
|
@code_map[code] || 0
|
97
115
|
end
|
98
116
|
|
117
|
+
# Is this encoding record format supported?
|
118
|
+
#
|
119
|
+
# @return [true]
|
99
120
|
def supported?
|
100
121
|
true
|
101
122
|
end
|
@@ -123,8 +144,7 @@ module TTFunk
|
|
123
144
|
if (id_range_offset[i]).zero?
|
124
145
|
glyph_id = code + id_delta[i]
|
125
146
|
else
|
126
|
-
index = id_range_offset[i] / 2 +
|
127
|
-
(code - start_code[i]) - (segcount - i)
|
147
|
+
index = (id_range_offset[i] / 2) + (code - start_code[i]) - (segcount - i)
|
128
148
|
# Because some TTF fonts are broken
|
129
149
|
glyph_id = glyph_ids[index] || 0
|
130
150
|
glyph_id += id_delta[i] if glyph_id != 0
|
@@ -3,10 +3,30 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Cmap
|
6
|
+
# Format 6: Trimmed table mapping.
|
7
|
+
#
|
8
|
+
# This module conditionally extends {TTFunk::Table::Cmap::Subtable}.
|
6
9
|
module Format06
|
10
|
+
# Language.
|
11
|
+
# @return [Integer]
|
7
12
|
attr_reader :language
|
13
|
+
|
14
|
+
# Code map.
|
15
|
+
# @return [Hash{Integer => Integer}]
|
8
16
|
attr_reader :code_map
|
9
17
|
|
18
|
+
# Encode the encoding record to format 6.
|
19
|
+
#
|
20
|
+
# @param charmap [Hash{Integer => Integer}] a hash mapping character
|
21
|
+
# codes to glyph IDs from the original font.
|
22
|
+
# @return [Hash]
|
23
|
+
# * `:charmap` (<tt>Hash{Integer => Hash}</tt>) keys are the characrers in
|
24
|
+
# `charset`, values are hashes:
|
25
|
+
# * `:old` (<tt>Integer</tt>) - glyph ID in the original font.
|
26
|
+
# * `:new` (<tt>Integer</tt>) - glyph ID in the subset font.
|
27
|
+
# that maps the characters in charmap to a
|
28
|
+
# * `:subtable` (<tt>String</tt>) - serialized encoding record.
|
29
|
+
# * `:max_glyph_id` (<tt>Integer</tt>) - maximum glyph ID in the new font.
|
10
30
|
def self.encode(charmap)
|
11
31
|
next_id = 0
|
12
32
|
glyph_map = { 0 => 0 }
|
@@ -25,16 +45,23 @@ module TTFunk
|
|
25
45
|
end
|
26
46
|
|
27
47
|
subtable = [
|
28
|
-
6, 10 + entry_count * 2, 0, low_char, entry_count, *glyph_indexes
|
48
|
+
6, 10 + (entry_count * 2), 0, low_char, entry_count, *glyph_indexes,
|
29
49
|
].pack('n*')
|
30
50
|
|
31
51
|
{ charmap: new_map, subtable: subtable, max_glyph_id: next_id + 1 }
|
32
52
|
end
|
33
53
|
|
54
|
+
# Get glyph ID for character code.
|
55
|
+
#
|
56
|
+
# @param code [Integer] character code.
|
57
|
+
# @return [Integer] glyph ID.
|
34
58
|
def [](code)
|
35
59
|
@code_map[code] || 0
|
36
60
|
end
|
37
61
|
|
62
|
+
# Is this encoding record format supported?
|
63
|
+
#
|
64
|
+
# @return [true]
|
38
65
|
def supported?
|
39
66
|
true
|
40
67
|
end
|
@@ -3,10 +3,30 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Cmap
|
6
|
+
# Format 10: Trimmed array.
|
7
|
+
#
|
8
|
+
# This module conditionally extends {TTFunk::Table::Cmap::Subtable}.
|
6
9
|
module Format10
|
10
|
+
# Language.
|
11
|
+
# @return [Integer]
|
7
12
|
attr_reader :language
|
13
|
+
|
14
|
+
# Code map.
|
15
|
+
# @return [Hash{Integer => Integer}]
|
8
16
|
attr_reader :code_map
|
9
17
|
|
18
|
+
# Encode the encoding record to format 10.
|
19
|
+
#
|
20
|
+
# @param charmap [Hash{Integer => Integer}] a hash mapping character
|
21
|
+
# codes to glyph IDs from the original font.
|
22
|
+
# @return [Hash]
|
23
|
+
# * `:charmap` (<tt>Hash{Integer => Hash}</tt>) keys are the characrers in
|
24
|
+
# `charset`, values are hashes:
|
25
|
+
# * `:old` (<tt>Integer</tt>) - glyph ID in the original font.
|
26
|
+
# * `:new` (<tt>Integer</tt>) - glyph ID in the subset font.
|
27
|
+
# that maps the characters in charmap to a
|
28
|
+
# * `:subtable` (<tt>String</tt>) - serialized encoding record.
|
29
|
+
# * `:max_glyph_id` (<tt>Integer</tt>) - maximum glyph ID in the new font.
|
10
30
|
def self.encode(charmap)
|
11
31
|
next_id = 0
|
12
32
|
glyph_map = { 0 => 0 }
|
@@ -25,17 +45,24 @@ module TTFunk
|
|
25
45
|
end
|
26
46
|
|
27
47
|
subtable = [
|
28
|
-
10, 0, 20 + entry_count * 4, 0, low_char, entry_count,
|
29
|
-
*glyph_indexes
|
48
|
+
10, 0, 20 + (entry_count * 4), 0, low_char, entry_count,
|
49
|
+
*glyph_indexes,
|
30
50
|
].pack('nnN*')
|
31
51
|
|
32
52
|
{ charmap: new_map, subtable: subtable, max_glyph_id: next_id + 1 }
|
33
53
|
end
|
34
54
|
|
55
|
+
# Get glyph ID for character code.
|
56
|
+
#
|
57
|
+
# @param code [Integer] character code.
|
58
|
+
# @return [Integer] glyph ID.
|
35
59
|
def [](code)
|
36
60
|
@code_map[code] || 0
|
37
61
|
end
|
38
62
|
|
63
|
+
# Is this encoding record format supported?
|
64
|
+
#
|
65
|
+
# @return [true]
|
39
66
|
def supported?
|
40
67
|
true
|
41
68
|
end
|