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,48 @@
|
|
3
3
|
require_relative 'subset'
|
4
4
|
|
5
5
|
module TTFunk
|
6
|
+
# Subset collection.
|
7
|
+
#
|
8
|
+
# For many use cases a font subset can be efficiently encoded using MacRoman
|
9
|
+
# encoding. However, for full font coverage and characters that are not in
|
10
|
+
# MacRoman encoding an additional Unicode subset is used. There can be as many
|
11
|
+
# as needed Unicode subsets to fully cover glyphs provided by the original
|
12
|
+
# font. Ther resulting set of subsets all use 8-bit encoding helping to
|
13
|
+
# efficiently encode text in Prawn.
|
6
14
|
class SubsetCollection
|
15
|
+
# @param original [TTFunk::File]
|
7
16
|
def initialize(original)
|
8
17
|
@original = original
|
9
18
|
@subsets = [Subset.for(@original, :mac_roman)]
|
10
19
|
end
|
11
20
|
|
21
|
+
# Get subset by index.
|
22
|
+
#
|
23
|
+
# @param subset [Integer]
|
24
|
+
# @return [TTFunk::Subset::Unicode, TTFunk::Subset::Unicode8Bit,
|
25
|
+
# TTFunk::Subset::MacRoman, TTFunk::Subset::Windows1252]
|
12
26
|
def [](subset)
|
13
27
|
@subsets[subset]
|
14
28
|
end
|
15
29
|
|
16
|
-
#
|
30
|
+
# Add chracters to appropiate subsets.
|
31
|
+
#
|
32
|
+
# @param characters [Array<Integer>] should be an array of UTF-16 code
|
33
|
+
# points
|
34
|
+
# @return [void]
|
17
35
|
def use(characters)
|
18
36
|
characters.each do |char|
|
19
37
|
covered = false
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
subset
|
24
|
-
|
25
|
-
|
38
|
+
i = 0
|
39
|
+
length = @subsets.length
|
40
|
+
while i < length
|
41
|
+
subset = @subsets[i]
|
42
|
+
if subset.covers?(char)
|
43
|
+
subset.use(char)
|
44
|
+
covered = true
|
45
|
+
break
|
46
|
+
end
|
47
|
+
i += 1
|
26
48
|
end
|
27
49
|
|
28
50
|
unless covered
|
@@ -32,13 +54,16 @@ module TTFunk
|
|
32
54
|
end
|
33
55
|
end
|
34
56
|
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
57
|
+
# Encode characters into subset-character pairs.
|
58
|
+
#
|
59
|
+
# @param characters [Array<Integer>] should be an array of UTF-16 code
|
60
|
+
# points
|
61
|
+
# @return [Array<Array(Integer, String)>] subset chunks, where each chunk
|
62
|
+
# is another array of two elements. The first element is the subset
|
63
|
+
# number, and the second element is the string of characters to render
|
64
|
+
# with that font subset. The strings will be encoded for their subset
|
65
|
+
# font, and so may not look (in the raw) like what was passed in, but they
|
66
|
+
# will render correctly with the corresponding subset font.
|
42
67
|
def encode(characters)
|
43
68
|
return [] if characters.empty?
|
44
69
|
|
data/lib/ttfunk/sum.rb
CHANGED
@@ -1,18 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TTFunk
|
4
|
+
# Sum aggreaget. Is sums all pushed values.
|
4
5
|
class Sum < Aggregate
|
6
|
+
# Value
|
7
|
+
#
|
8
|
+
# @return [#+]
|
5
9
|
attr_reader :value
|
6
10
|
|
11
|
+
# @param init_value [#+] initial value
|
7
12
|
def initialize(init_value = 0)
|
8
13
|
super()
|
9
14
|
@value = init_value
|
10
15
|
end
|
11
16
|
|
17
|
+
# Push a value. It will be added to the current value.
|
18
|
+
#
|
19
|
+
# @param operand [any]
|
20
|
+
# @return [void]
|
12
21
|
def <<(operand)
|
13
22
|
@value += coerce(operand)
|
14
23
|
end
|
15
24
|
|
25
|
+
# Get the stored value or default.
|
26
|
+
#
|
27
|
+
# @param _default [any] Unused. Here for API compatibility.
|
28
|
+
# @return [any]
|
16
29
|
def value_or(_default)
|
17
30
|
# value should always be non-nil
|
18
31
|
value
|
@@ -3,25 +3,47 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Cff < TTFunk::Table
|
6
|
+
# CFF Charset
|
6
7
|
class Charset < TTFunk::SubTable
|
7
8
|
include Enumerable
|
8
9
|
|
10
|
+
# First glyph string. This is an implicit glyph present in all charsets.
|
9
11
|
FIRST_GLYPH_STRING = '.notdef'
|
12
|
+
|
13
|
+
# Format 0.
|
10
14
|
ARRAY_FORMAT = 0
|
15
|
+
|
16
|
+
# Format 1.
|
11
17
|
RANGE_FORMAT_8 = 1
|
18
|
+
|
19
|
+
# Format 2.
|
12
20
|
RANGE_FORMAT_16 = 2
|
13
21
|
|
22
|
+
# Predefined ISOAdobe charset ID.
|
14
23
|
ISO_ADOBE_CHARSET_ID = 0
|
24
|
+
|
25
|
+
# Predefined Expert charset ID.
|
15
26
|
EXPERT_CHARSET_ID = 1
|
27
|
+
|
28
|
+
# Predefined Expert Subset charset ID.
|
16
29
|
EXPERT_SUBSET_CHARSET_ID = 2
|
17
30
|
|
31
|
+
# Default charset ID.
|
18
32
|
DEFAULT_CHARSET_ID = ISO_ADOBE_CHARSET_ID
|
19
33
|
|
20
34
|
class << self
|
35
|
+
# Standard strings defined in the spec that do not need to be defined
|
36
|
+
# in the CFF.
|
37
|
+
#
|
38
|
+
# @return [TTFunk::OneBasedArray<String>]
|
21
39
|
def standard_strings
|
22
40
|
Charsets::STANDARD_STRINGS
|
23
41
|
end
|
24
42
|
|
43
|
+
# Strings for charset ID.
|
44
|
+
#
|
45
|
+
# @param charset_id [Integer]
|
46
|
+
# @return [TTFunk::OneBasedArray<String>]
|
25
47
|
def strings_for_charset_id(charset_id)
|
26
48
|
case charset_id
|
27
49
|
when ISO_ADOBE_CHARSET_ID
|
@@ -34,9 +56,39 @@ module TTFunk
|
|
34
56
|
end
|
35
57
|
end
|
36
58
|
|
37
|
-
|
38
|
-
|
39
|
-
|
59
|
+
# Encoded entries.
|
60
|
+
# @return [TTFunk::OneBasedArray<Integer>, Array<Range<Integer>>]
|
61
|
+
attr_reader :entries
|
62
|
+
|
63
|
+
# Length of encoded charset subtable.
|
64
|
+
# @return [Integer]
|
65
|
+
attr_reader :length
|
66
|
+
|
67
|
+
# Top dict.
|
68
|
+
# @return [TTFunk::Table::Cff::TopDict]
|
69
|
+
attr_reader :top_dict
|
70
|
+
|
71
|
+
# Encodign format.
|
72
|
+
# @return [Integer]
|
73
|
+
attr_reader :format
|
74
|
+
|
75
|
+
# Number of encoded items.
|
76
|
+
# @return [Integer]
|
77
|
+
attr_reader :items_count
|
78
|
+
|
79
|
+
# Offset or charset ID.
|
80
|
+
# @return [Integer]
|
81
|
+
attr_reader :offset_or_id
|
82
|
+
|
83
|
+
# @overload initialize(top_dict, file, offset = nil, length = nil)
|
84
|
+
# @param top_dict [TTFunk::Table:Cff::TopDict]
|
85
|
+
# @param file [TTFunk::File]
|
86
|
+
# @param offset [Integer]
|
87
|
+
# @param length [Integer]
|
88
|
+
# @overload initialize(top_dict, file, charset_id)
|
89
|
+
# @param top_dict [TTFunk::Table:Cff::TopDict]
|
90
|
+
# @param file [TTFunk::File]
|
91
|
+
# @param charset_id [Integer] 0, 1, or 2
|
40
92
|
def initialize(top_dict, file, offset_or_id = nil, length = nil)
|
41
93
|
@top_dict = top_dict
|
42
94
|
@offset_or_id = offset_or_id || DEFAULT_CHARSET_ID
|
@@ -44,23 +96,37 @@ module TTFunk
|
|
44
96
|
if offset
|
45
97
|
super(file, offset, length)
|
46
98
|
else
|
47
|
-
@
|
99
|
+
@items_count = self.class.strings_for_charset_id(offset_or_id).size
|
48
100
|
end
|
49
101
|
end
|
50
102
|
|
103
|
+
# Iterate over character names.
|
104
|
+
#
|
105
|
+
# @overload each()
|
106
|
+
# @yieldparam name [String]
|
107
|
+
# @return [void]
|
108
|
+
# @overload each()
|
109
|
+
# @return [Enumerator]
|
51
110
|
def each
|
52
111
|
return to_enum(__method__) unless block_given?
|
53
112
|
|
54
113
|
# +1 adjusts for the implicit .notdef glyph
|
55
|
-
(
|
114
|
+
(items_count + 1).times { |i| yield(self[i]) }
|
56
115
|
end
|
57
116
|
|
117
|
+
# Get character name for glyph index.
|
118
|
+
#
|
119
|
+
# @param glyph_id [Integer]
|
120
|
+
# @return [String, nil]
|
58
121
|
def [](glyph_id)
|
59
122
|
return FIRST_GLYPH_STRING if glyph_id.zero?
|
60
123
|
|
61
124
|
find_string(sid_for(glyph_id))
|
62
125
|
end
|
63
126
|
|
127
|
+
# Charset offset in the file.
|
128
|
+
#
|
129
|
+
# @return [Integer, nil]
|
64
130
|
def offset
|
65
131
|
# Numbers from 0..2 mean charset IDs instead of offsets. IDs are
|
66
132
|
# basically pre-defined sets of characters.
|
@@ -73,13 +139,25 @@ module TTFunk
|
|
73
139
|
end
|
74
140
|
end
|
75
141
|
|
76
|
-
#
|
77
|
-
|
142
|
+
# Encode charset.
|
143
|
+
#
|
144
|
+
# @param charmap [Hash{Integer => Hash}] keys are the charac codes,
|
145
|
+
# values are hashes:
|
146
|
+
# * `:old` (<tt>Integer</tt>) - glyph ID in the original font.
|
147
|
+
# * `:new` (<tt>Integer</tt>) - glyph ID in the subset font.
|
148
|
+
# @return [String]
|
149
|
+
def encode(charmap)
|
78
150
|
# no offset means no charset was specified (i.e. we're supposed to
|
79
151
|
# use a predefined charset) so there's nothing to encode
|
80
152
|
return '' unless offset
|
81
153
|
|
82
|
-
sids =
|
154
|
+
sids =
|
155
|
+
charmap
|
156
|
+
.values
|
157
|
+
.reject { |mapping| mapping[:new].zero? }
|
158
|
+
.sort_by { |mapping| mapping[:new] }
|
159
|
+
.map { |mapping| sid_for(mapping[:old]) }
|
160
|
+
|
83
161
|
ranges = TTFunk::BinUtils.rangify(sids)
|
84
162
|
range_max = ranges.map(&:last).max
|
85
163
|
|
@@ -138,7 +216,7 @@ module TTFunk
|
|
138
216
|
|
139
217
|
idx = sid - 390
|
140
218
|
|
141
|
-
if idx < file.cff.string_index.
|
219
|
+
if idx < file.cff.string_index.items_count
|
142
220
|
file.cff.string_index[idx]
|
143
221
|
end
|
144
222
|
else
|
@@ -153,23 +231,23 @@ module TTFunk
|
|
153
231
|
|
154
232
|
case format_sym
|
155
233
|
when :array_format
|
156
|
-
@
|
157
|
-
@length =
|
234
|
+
@items_count = top_dict.charstrings_index.items_count - 1
|
235
|
+
@length = @items_count * element_width
|
158
236
|
@entries = OneBasedArray.new(read(length, 'n*'))
|
159
237
|
|
160
238
|
when :range_format8, :range_format16
|
161
239
|
# The number of ranges is not explicitly specified in the font.
|
162
240
|
# Instead, software utilizing this data simply processes ranges
|
163
241
|
# until all glyphs in the font are covered.
|
164
|
-
@
|
242
|
+
@items_count = 0
|
165
243
|
@entries = []
|
166
244
|
@length = 0
|
167
245
|
|
168
|
-
until
|
246
|
+
until @items_count >= top_dict.charstrings_index.items_count - 1
|
169
247
|
@length += 1 + element_width
|
170
248
|
sid, num_left = read(element_width, element_format)
|
171
|
-
entries << (sid..(sid + num_left))
|
172
|
-
@
|
249
|
+
@entries << (sid..(sid + num_left))
|
250
|
+
@items_count += num_left + 1
|
173
251
|
end
|
174
252
|
end
|
175
253
|
end
|
@@ -178,7 +256,7 @@ module TTFunk
|
|
178
256
|
{
|
179
257
|
array_format: 2, # SID
|
180
258
|
range_format8: 3, # SID + Card8
|
181
|
-
range_format16: 4 # SID + Card16
|
259
|
+
range_format16: 4, # SID + Card16
|
182
260
|
}[fmt]
|
183
261
|
end
|
184
262
|
|
@@ -186,7 +264,7 @@ module TTFunk
|
|
186
264
|
{
|
187
265
|
array_format: 'n',
|
188
266
|
range_format8: 'nC',
|
189
|
-
range_format16: 'nn'
|
267
|
+
range_format16: 'nn',
|
190
268
|
}[fmt]
|
191
269
|
end
|
192
270
|
|
@@ -204,7 +282,7 @@ module TTFunk
|
|
204
282
|
{
|
205
283
|
array_format: ARRAY_FORMAT,
|
206
284
|
range_format8: RANGE_FORMAT_8,
|
207
|
-
range_format16: RANGE_FORMAT_16
|
285
|
+
range_format16: RANGE_FORMAT_16,
|
208
286
|
}[sym]
|
209
287
|
end
|
210
288
|
end
|
@@ -4,6 +4,7 @@ module TTFunk
|
|
4
4
|
class Table
|
5
5
|
class Cff < TTFunk::Table
|
6
6
|
module Charsets
|
7
|
+
# Predefinde CFF Expert charset
|
7
8
|
EXPERT = OneBasedArray.new(
|
8
9
|
[
|
9
10
|
'space',
|
@@ -180,8 +181,8 @@ module TTFunk
|
|
180
181
|
'Ucircumflexsmall',
|
181
182
|
'Udieresissmall',
|
182
183
|
'Yacutesmall',
|
183
|
-
'Thornsmall'
|
184
|
-
]
|
184
|
+
'Thornsmall',
|
185
|
+
],
|
185
186
|
).freeze
|
186
187
|
end
|
187
188
|
end
|
@@ -4,6 +4,7 @@ module TTFunk
|
|
4
4
|
class Table
|
5
5
|
class Cff < TTFunk::Table
|
6
6
|
module Charsets
|
7
|
+
# Predefined CFF Expert Subset charset
|
7
8
|
EXPERT_SUBSET = OneBasedArray.new(
|
8
9
|
[
|
9
10
|
'space',
|
@@ -110,8 +111,8 @@ module TTFunk
|
|
110
111
|
'nineinferior',
|
111
112
|
'centinferior',
|
112
113
|
'dollarinferior',
|
113
|
-
'periodinferior'
|
114
|
-
]
|
114
|
+
'periodinferior',
|
115
|
+
],
|
115
116
|
).freeze
|
116
117
|
end
|
117
118
|
end
|
@@ -4,6 +4,7 @@ module TTFunk
|
|
4
4
|
class Table
|
5
5
|
class Cff < TTFunk::Table
|
6
6
|
module Charsets
|
7
|
+
# Predefined CFF ISOAdobe charset
|
7
8
|
ISO_ADOBE = OneBasedArray.new(
|
8
9
|
[
|
9
10
|
'space',
|
@@ -232,8 +233,8 @@ module TTFunk
|
|
232
233
|
'ugrave',
|
233
234
|
'yacute',
|
234
235
|
'ydieresis',
|
235
|
-
'zcaron'
|
236
|
-
]
|
236
|
+
'zcaron',
|
237
|
+
],
|
237
238
|
).freeze
|
238
239
|
end
|
239
240
|
end
|
@@ -4,6 +4,7 @@ module TTFunk
|
|
4
4
|
class Table
|
5
5
|
class Cff < TTFunk::Table
|
6
6
|
module Charsets
|
7
|
+
# Standard CFF strings
|
7
8
|
STANDARD_STRINGS = OneBasedArray.new(
|
8
9
|
[
|
9
10
|
'space',
|
@@ -395,8 +396,8 @@ module TTFunk
|
|
395
396
|
'Medium',
|
396
397
|
'Regular',
|
397
398
|
'Roman',
|
398
|
-
'Semibold'
|
399
|
-
]
|
399
|
+
'Semibold',
|
400
|
+
],
|
400
401
|
).freeze
|
401
402
|
end
|
402
403
|
end
|
@@ -3,7 +3,9 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Cff < TTFunk::Table
|
6
|
+
# CFF Charstring.
|
6
7
|
class Charstring
|
8
|
+
# Type 2 charstring operators
|
7
9
|
CODE_MAP = {
|
8
10
|
1 => :hstem,
|
9
11
|
3 => :vstem,
|
@@ -28,18 +30,29 @@ module TTFunk
|
|
28
30
|
28 => :shortint,
|
29
31
|
29 => :callgsubr,
|
30
32
|
30 => :vhcurveto,
|
31
|
-
31 => :hvcurveto
|
33
|
+
31 => :hvcurveto,
|
32
34
|
}.freeze
|
33
35
|
|
36
|
+
# Type 2 Flex operators.
|
34
37
|
FLEX_CODE_MAP = {
|
35
38
|
35 => :flex,
|
36
39
|
34 => :hflex,
|
37
40
|
36 => :hflex1,
|
38
|
-
37 => :flex1
|
41
|
+
37 => :flex1,
|
39
42
|
}.freeze
|
40
43
|
|
41
|
-
|
44
|
+
# Glyph ID.
|
45
|
+
# @return [Integer]
|
46
|
+
attr_reader :glyph_id
|
42
47
|
|
48
|
+
# Encoded charstring.
|
49
|
+
# @return [String]
|
50
|
+
attr_reader :raw
|
51
|
+
|
52
|
+
# @param glyph_id [Integer]
|
53
|
+
# @param top_dict [TTFunk::Table:Cff::TopDict]
|
54
|
+
# @param font_dict [TTFunk::Table:Cff::FontDict]
|
55
|
+
# @param raw [String]
|
43
56
|
def initialize(glyph_id, top_dict, font_dict, raw)
|
44
57
|
@glyph_id = glyph_id
|
45
58
|
@top_dict = top_dict
|
@@ -66,6 +79,9 @@ module TTFunk
|
|
66
79
|
@y = 0
|
67
80
|
end
|
68
81
|
|
82
|
+
# Get path representation of this charstring.
|
83
|
+
#
|
84
|
+
# @return [TTFunk::Table::Cff::Path]
|
69
85
|
def path
|
70
86
|
@path || begin
|
71
87
|
@path = Path.new
|
@@ -74,6 +90,9 @@ module TTFunk
|
|
74
90
|
end
|
75
91
|
end
|
76
92
|
|
93
|
+
# Get a TrueType-compatible glyph representation of this charstring.
|
94
|
+
#
|
95
|
+
# @return [TTFunk::Table::Glyf::PathBased]
|
77
96
|
def glyph
|
78
97
|
@glyph ||=
|
79
98
|
begin
|
@@ -82,19 +101,21 @@ module TTFunk
|
|
82
101
|
end
|
83
102
|
end
|
84
103
|
|
104
|
+
# Get path representation of this charstring at the specified font size.
|
105
|
+
#
|
106
|
+
# @param x [Integer, Float] new horizontal position.
|
107
|
+
# @param y [Integer, Float] new vertical position.
|
108
|
+
# @param font_size [Integer, Float] font size.
|
109
|
+
# @return [TTFunk::Table::Cff::Path]
|
85
110
|
def render(x: 0, y: 0, font_size: 72)
|
86
111
|
path.render(
|
87
112
|
x: x,
|
88
113
|
y: y,
|
89
114
|
font_size: font_size,
|
90
|
-
units_per_em: @top_dict.file.header.units_per_em
|
115
|
+
units_per_em: @top_dict.file.header.units_per_em,
|
91
116
|
)
|
92
117
|
end
|
93
118
|
|
94
|
-
def encode
|
95
|
-
raw
|
96
|
-
end
|
97
|
-
|
98
119
|
private
|
99
120
|
|
100
121
|
def parse!
|
@@ -106,22 +127,22 @@ module TTFunk
|
|
106
127
|
next if code == 11
|
107
128
|
|
108
129
|
if code >= 32 && code <= 246
|
109
|
-
@stack << code - 139
|
130
|
+
@stack << (code - 139)
|
110
131
|
elsif (m = CODE_MAP[code])
|
111
132
|
__send__(m)
|
112
133
|
elsif code >= 247 && code <= 250
|
113
134
|
b0 = code
|
114
135
|
b1 = @data[@index]
|
115
136
|
@index += 1
|
116
|
-
@stack << (b0 - 247) * 256 + b1 + 108
|
137
|
+
@stack << (((b0 - 247) * 256) + b1 + 108)
|
117
138
|
elsif code >= 251 && code <= 254
|
118
139
|
b0 = code
|
119
140
|
b1 = @data[@index]
|
120
141
|
@index += 1
|
121
|
-
@stack << -(b0 - 251) * 256 - b1 - 108
|
142
|
+
@stack << ((-(b0 - 251) * 256) - b1 - 108)
|
122
143
|
else
|
123
144
|
b1, b2, b3, b4 = read_bytes(4)
|
124
|
-
@stack << ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) / 65_536
|
145
|
+
@stack << (((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) / 65_536)
|
125
146
|
end
|
126
147
|
end
|
127
148
|
end
|
@@ -3,28 +3,34 @@
|
|
3
3
|
module TTFunk
|
4
4
|
class Table
|
5
5
|
class Cff < TTFunk::Table
|
6
|
+
# CFF Charstrings Index.
|
6
7
|
class CharstringsIndex < TTFunk::Table::Cff::Index
|
8
|
+
# Top dict.
|
9
|
+
# @return [TTFunk::Table::Cff::TopDict]
|
7
10
|
attr_reader :top_dict
|
8
11
|
|
12
|
+
# @overload initialize(top_dict, file, offset, length = nil)
|
13
|
+
# @param top_dict [TTFunk::Table:Cff::TopDict]
|
14
|
+
# @param file [TTFunk::File]
|
15
|
+
# @param offset [Integer]
|
16
|
+
# @param length [Integer]
|
9
17
|
def initialize(top_dict, *remaining_args)
|
10
18
|
super(*remaining_args)
|
11
19
|
@top_dict = top_dict
|
12
20
|
end
|
13
21
|
|
14
|
-
|
15
|
-
entry_cache[index] ||= TTFunk::Table::Cff::Charstring.new(
|
16
|
-
index, top_dict, font_dict_for(index), super
|
17
|
-
)
|
18
|
-
end
|
22
|
+
private
|
19
23
|
|
20
|
-
|
21
|
-
|
22
|
-
super() do |_entry, index|
|
23
|
-
self[mapping[index]].encode if mapping.include?(index)
|
24
|
-
end
|
24
|
+
def decode_item(index, _offset, _length)
|
25
|
+
TTFunk::Table::Cff::Charstring.new(index, top_dict, font_dict_for(index), super)
|
25
26
|
end
|
26
27
|
|
27
|
-
|
28
|
+
def encode_items(charmap)
|
29
|
+
charmap
|
30
|
+
.reject { |code, mapping| mapping[:new].zero? && !code.zero? }
|
31
|
+
.sort_by { |_code, mapping| mapping[:new] }
|
32
|
+
.map { |(_code, mapping)| items[mapping[:old]] }
|
33
|
+
end
|
28
34
|
|
29
35
|
def font_dict_for(index)
|
30
36
|
# only CID-keyed fonts contain an FD selector and font dicts
|