ttfunk 1.6.2.1 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -1
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG.md +15 -1
  5. data/lib/ttfunk.rb +3 -2
  6. data/lib/ttfunk/bit_field.rb +1 -1
  7. data/lib/ttfunk/collection.rb +8 -2
  8. data/lib/ttfunk/encoded_string.rb +3 -3
  9. data/lib/ttfunk/max.rb +1 -0
  10. data/lib/ttfunk/min.rb +1 -0
  11. data/lib/ttfunk/one_based_array.rb +1 -1
  12. data/lib/ttfunk/otf_encoder.rb +1 -1
  13. data/lib/ttfunk/reader.rb +3 -3
  14. data/lib/ttfunk/sci_form.rb +1 -1
  15. data/lib/ttfunk/subset.rb +3 -3
  16. data/lib/ttfunk/subset/base.rb +24 -21
  17. data/lib/ttfunk/subset/code_page.rb +16 -19
  18. data/lib/ttfunk/subset/unicode.rb +8 -6
  19. data/lib/ttfunk/subset/unicode_8bit.rb +14 -12
  20. data/lib/ttfunk/sum.rb +1 -0
  21. data/lib/ttfunk/table/cff.rb +17 -17
  22. data/lib/ttfunk/table/cff/charset.rb +31 -30
  23. data/lib/ttfunk/table/cff/charsets.rb +3 -3
  24. data/lib/ttfunk/table/cff/charstring.rb +54 -55
  25. data/lib/ttfunk/table/cff/dict.rb +6 -4
  26. data/lib/ttfunk/table/cff/encoding.rb +20 -21
  27. data/lib/ttfunk/table/cff/encodings.rb +1 -1
  28. data/lib/ttfunk/table/cff/fd_selector.rb +14 -11
  29. data/lib/ttfunk/table/cff/font_index.rb +7 -6
  30. data/lib/ttfunk/table/cff/index.rb +6 -5
  31. data/lib/ttfunk/table/cff/one_based_index.rb +7 -3
  32. data/lib/ttfunk/table/cff/path.rb +5 -3
  33. data/lib/ttfunk/table/cff/top_dict.rb +7 -6
  34. data/lib/ttfunk/table/cff/top_index.rb +5 -4
  35. data/lib/ttfunk/table/cmap.rb +8 -6
  36. data/lib/ttfunk/table/cmap/format00.rb +7 -6
  37. data/lib/ttfunk/table/cmap/format04.rb +16 -15
  38. data/lib/ttfunk/table/cmap/format06.rb +6 -5
  39. data/lib/ttfunk/table/cmap/format10.rb +6 -5
  40. data/lib/ttfunk/table/cmap/format12.rb +13 -12
  41. data/lib/ttfunk/table/cmap/subtable.rb +4 -4
  42. data/lib/ttfunk/table/dsig.rb +11 -9
  43. data/lib/ttfunk/table/glyf.rb +3 -3
  44. data/lib/ttfunk/table/glyf/compound.rb +8 -8
  45. data/lib/ttfunk/table/hmtx.rb +6 -5
  46. data/lib/ttfunk/table/kern.rb +4 -4
  47. data/lib/ttfunk/table/kern/format0.rb +1 -1
  48. data/lib/ttfunk/table/loca.rb +7 -6
  49. data/lib/ttfunk/table/name.rb +6 -5
  50. data/lib/ttfunk/table/os2.rb +261 -151
  51. data/lib/ttfunk/table/post.rb +1 -1
  52. data/lib/ttfunk/table/sbix.rb +15 -13
  53. data/lib/ttfunk/table/vorg.rb +1 -1
  54. data/lib/ttfunk/ttf_encoder.rb +4 -4
  55. metadata +29 -99
  56. metadata.gz.sig +0 -0
@@ -4,9 +4,9 @@ module TTFunk
4
4
  class Table
5
5
  class Cff < TTFunk::Table
6
6
  module Charsets
7
- autoload :EXPERT, 'ttfunk/table/cff/charsets/expert'
8
- autoload :EXPERT_SUBSET, 'ttfunk/table/cff/charsets/expert_subset'
9
- autoload :ISO_ADOBE, 'ttfunk/table/cff/charsets/iso_adobe'
7
+ autoload :EXPERT, 'ttfunk/table/cff/charsets/expert'
8
+ autoload :EXPERT_SUBSET, 'ttfunk/table/cff/charsets/expert_subset'
9
+ autoload :ISO_ADOBE, 'ttfunk/table/cff/charsets/iso_adobe'
10
10
  autoload :STANDARD_STRINGS, 'ttfunk/table/cff/charsets/standard_strings'
11
11
  end
12
12
  end
@@ -46,11 +46,9 @@ module TTFunk
46
46
  @font_dict = font_dict
47
47
  @raw = raw
48
48
 
49
- default_width_x = (@font_dict || @top_dict)
50
- .private_dict.default_width_x
49
+ default_width_x = (@font_dict || @top_dict).private_dict.default_width_x
51
50
 
52
- @nominal_width_x = (@font_dict || @top_dict)
53
- .private_dict.nominal_width_x
51
+ @nominal_width_x = (@font_dict || @top_dict).private_dict.nominal_width_x
54
52
 
55
53
  @subrs = (@font_dict || @top_dict).private_dict.subr_index
56
54
  @gsubrs = @top_dict.cff.global_subr_index
@@ -77,10 +75,11 @@ module TTFunk
77
75
  end
78
76
 
79
77
  def glyph
80
- @glyph ||= begin
81
- horizontal_metrics = @top_dict.file.horizontal_metrics.for(glyph_id)
82
- Glyf::PathBased.new(path, horizontal_metrics)
83
- end
78
+ @glyph ||=
79
+ begin
80
+ horizontal_metrics = @top_dict.file.horizontal_metrics.for(glyph_id)
81
+ Glyf::PathBased.new(path, horizontal_metrics)
82
+ end
84
83
  end
85
84
 
86
85
  def render(x: 0, y: 0, font_size: 72)
@@ -109,7 +108,7 @@ module TTFunk
109
108
  if code >= 32 && code <= 246
110
109
  @stack << code - 139
111
110
  elsif (m = CODE_MAP[code])
112
- send(m)
111
+ __send__(m)
113
112
  elsif code >= 247 && code <= 250
114
113
  b0 = code
115
114
  b1 = @data[@index]
@@ -229,73 +228,73 @@ module TTFunk
229
228
  def flex_select
230
229
  flex_code = @data[@index]
231
230
  @index += 1
232
- send(FLEX_CODE_MAP[flex_code])
231
+ __send__(FLEX_CODE_MAP[flex_code])
233
232
  end
234
233
 
235
234
  def flex
236
- c1x = @x + @stack.shift # dx1
237
- c1y = @y + @stack.shift # dy1
238
- c2x = c1x + @stack.shift # dx2
239
- c2y = c1y + @stack.shift # dy2
240
- jpx = c2x + @stack.shift # dx3
241
- jpy = c2y + @stack.shift # dy3
242
- c3x = jpx + @stack.shift # dx4
243
- c3y = jpy + @stack.shift # dy4
244
- c4x = c3x + @stack.shift # dx5
245
- c4y = c3y + @stack.shift # dy5
246
- @x = c4x + @stack.shift # dx6
247
- @y = c4y + @stack.shift # dy6
248
- @stack.shift # flex depth
235
+ c1x = @x + @stack.shift # dx1
236
+ c1y = @y + @stack.shift # dy1
237
+ c2x = c1x + @stack.shift # dx2
238
+ c2y = c1y + @stack.shift # dy2
239
+ jpx = c2x + @stack.shift # dx3
240
+ jpy = c2y + @stack.shift # dy3
241
+ c3x = jpx + @stack.shift # dx4
242
+ c3y = jpy + @stack.shift # dy4
243
+ c4x = c3x + @stack.shift # dx5
244
+ c4y = c3y + @stack.shift # dy5
245
+ @x = c4x + @stack.shift # dx6
246
+ @y = c4y + @stack.shift # dy6
247
+ @stack.shift # flex depth
249
248
 
250
249
  @path.curve_to(c1x, c1y, c2x, c2y, jpx, jpy)
251
250
  @path.curve_to(c3x, c3y, c4x, c4y, @x, @y)
252
251
  end
253
252
 
254
253
  def hflex
255
- c1x = @x + @stack.shift # dx1
256
- c1y = @y # dy1
257
- c2x = c1x + @stack.shift # dx2
258
- c2y = c1y + @stack.shift # dy2
259
- jpx = c2x + @stack.shift # dx3
260
- jpy = c2y # dy3
261
- c3x = jpx + stack.shift # dx4
262
- c3y = c2y # dy4
263
- c4x = c3x + stack.shift # dx5
264
- c4y = @y # dy5
265
- @x = c4x + stack.shift # dx6
254
+ c1x = @x + @stack.shift # dx1
255
+ c1y = @y # dy1
256
+ c2x = c1x + @stack.shift # dx2
257
+ c2y = c1y + @stack.shift # dy2
258
+ jpx = c2x + @stack.shift # dx3
259
+ jpy = c2y # dy3
260
+ c3x = jpx + stack.shift # dx4
261
+ c3y = c2y # dy4
262
+ c4x = c3x + stack.shift # dx5
263
+ c4y = @y # dy5
264
+ @x = c4x + stack.shift # dx6
266
265
 
267
266
  @path.curve_to(c1x, c1y, c2x, c2y, jpx, jpy)
268
267
  @path.curve_to(c3x, c3y, c4x, c4y, @x, @y)
269
268
  end
270
269
 
271
270
  def hflex1
272
- c1x = @x + @stack.shift # dx1
273
- c1y = @y + @stack.shift # dy1
274
- c2x = c1x + @stack.shift # dx2
275
- c2y = c1y + @stack.shift # dy2
276
- jpx = c2x + @stack.shift # dx3
277
- jpy = c2y # dy3
278
- c3x = jpx + @stack.shift # dx4
279
- c3y = c2y # dy4
280
- c4x = c3x + @stack.shift # dx5
281
- c4y = c3y + @stack.shift # dy5
282
- @x = c4x + @stack.shift # dx6
271
+ c1x = @x + @stack.shift # dx1
272
+ c1y = @y + @stack.shift # dy1
273
+ c2x = c1x + @stack.shift # dx2
274
+ c2y = c1y + @stack.shift # dy2
275
+ jpx = c2x + @stack.shift # dx3
276
+ jpy = c2y # dy3
277
+ c3x = jpx + @stack.shift # dx4
278
+ c3y = c2y # dy4
279
+ c4x = c3x + @stack.shift # dx5
280
+ c4y = c3y + @stack.shift # dy5
281
+ @x = c4x + @stack.shift # dx6
283
282
 
284
283
  @path.curve_to(c1x, c1y, c2x, c2y, jpx, jpy)
285
284
  @path.curve_to(c3x, c3y, c4x, c4y, @x, @y)
286
285
  end
287
286
 
288
287
  def flex1
289
- c1x = @x + @stack.shift # dx1
290
- c1y = @y + @stack.shift # dy1
291
- c2x = c1x + @stack.shift # dx2
292
- c2y = c1y + @stack.shift # dy2
293
- jpx = c2x + @stack.shift # dx3
294
- jpy = c2y + @stack.shift # dy3
295
- c3x = jpx + @stack.shift # dx4
296
- c3y = jpy + @stack.shift # dy4
297
- c4x = c3x + @stack.shift # dx5
298
- c4y = c3y + @stack.shift # dy5
288
+ c1x = @x + @stack.shift # dx1
289
+ c1y = @y + @stack.shift # dy1
290
+ c2x = c1x + @stack.shift # dx2
291
+ c2y = c1y + @stack.shift # dy2
292
+ jpx = c2x + @stack.shift # dx3
293
+ jpy = c2y + @stack.shift # dy3
294
+ c3x = jpx + @stack.shift # dx4
295
+ c3y = jpy + @stack.shift # dy4
296
+ c4x = c3x + @stack.shift # dx5
297
+ c4y = c3y + @stack.shift # dy5
299
298
 
300
299
  if (c4x - @x).abs > (c4y - @y).abs
301
300
  @x = c4x + @stack.shift
@@ -7,6 +7,7 @@ module TTFunk
7
7
  class Cff < TTFunk::Table
8
8
  class Dict < TTFunk::SubTable
9
9
  class InvalidOperandError < StandardError; end
10
+
10
11
  class TooManyOperandsError < StandardError; end
11
12
 
12
13
  # for regular single-byte operators
@@ -103,9 +104,9 @@ module TTFunk
103
104
  end
104
105
 
105
106
  def encode_exponent(exp)
106
- return [] if exp == 0
107
+ return [] if exp.zero?
107
108
 
108
- [exp > 0 ? 0xB : 0xC, *encode_significand(exp.abs)]
109
+ [exp.positive? ? 0xB : 0xC, *encode_significand(exp.abs)]
109
110
  end
110
111
 
111
112
  def encode_significand(sig)
@@ -154,11 +155,12 @@ module TTFunk
154
155
  operands << decode_operand(b_zero)
155
156
 
156
157
  if operands.size > MAX_OPERANDS
157
- raise TooManyOperandsError, 'found one too many operands at '\
158
+ raise TooManyOperandsError,
159
+ 'found one too many operands at '\
158
160
  "position #{io.pos} in dict at position #{table_offset}"
159
161
  end
160
162
  else
161
- raise "dict byte value #{b_zero} is reserved"
163
+ raise Error, "dict byte value #{b_zero} is reserved"
162
164
  end
163
165
  end
164
166
  end
@@ -43,7 +43,7 @@ module TTFunk
43
43
  end
44
44
 
45
45
  def [](glyph_id)
46
- return 0 if glyph_id == 0
46
+ return 0 if glyph_id.zero?
47
47
  return code_for(glyph_id) if offset
48
48
 
49
49
  self.class.codes_for_encoding_id(offset_or_id)[glyph_id]
@@ -68,9 +68,10 @@ module TTFunk
68
68
  return '' unless offset
69
69
  return encode_supplemental(new_to_old, old_to_new) if supplemental?
70
70
 
71
- codes = new_to_old.keys.sort.map do |new_gid|
72
- code_for(new_to_old[new_gid])
73
- end
71
+ codes =
72
+ new_to_old.keys.sort.map do |new_gid|
73
+ code_for(new_to_old[new_gid])
74
+ end
74
75
 
75
76
  ranges = TTFunk::BinUtils.rangify(codes)
76
77
 
@@ -100,11 +101,12 @@ module TTFunk
100
101
  private
101
102
 
102
103
  def encode_supplemental(_new_to_old, old_to_new)
103
- new_entries = @entries.each_with_object({}) do |(code, old_gid), ret|
104
- if (new_gid = old_to_new[old_gid])
105
- ret[code] = new_gid
104
+ new_entries =
105
+ @entries.each_with_object({}) do |(code, old_gid), ret|
106
+ if (new_gid = old_to_new[old_gid])
107
+ ret[code] = new_gid
108
+ end
106
109
  end
107
- end
108
110
 
109
111
  result = [format_int(:supplemental), new_entries.size].pack('CC')
110
112
  fmt = element_format(:supplemental)
@@ -117,14 +119,14 @@ module TTFunk
117
119
  end
118
120
 
119
121
  def code_for(glyph_id)
120
- return 0 if glyph_id == 0
122
+ return 0 if glyph_id.zero?
121
123
 
122
124
  # rather than validating the glyph as part of one of the predefined
123
125
  # encodings, just pass it through
124
126
  return glyph_id unless offset
125
127
 
126
128
  case format_sym
127
- when :array_format
129
+ when :array_format, :supplemental
128
130
  @entries[glyph_id]
129
131
 
130
132
  when :range_format
@@ -139,9 +141,6 @@ module TTFunk
139
141
  end
140
142
 
141
143
  0
142
-
143
- when :supplemental
144
- @entries[glyph_id]
145
144
  end
146
145
  end
147
146
 
@@ -176,11 +175,11 @@ module TTFunk
176
175
  end
177
176
 
178
177
  def element_format(fmt = format_sym)
179
- case fmt
180
- when :array_format then 'C'
181
- when :range_format then 'CC'
182
- when :supplemental then 'Cn'
183
- end
178
+ {
179
+ array_format: 'C',
180
+ range_format: 'CC',
181
+ supplemental: 'Cn'
182
+ }[fmt]
184
183
  end
185
184
 
186
185
  # @TODO: handle supplemental encoding (necessary?)
@@ -190,7 +189,7 @@ module TTFunk
190
189
  when :range_format then 2
191
190
  when :supplemental then 3
192
191
  else
193
- raise "'#{fmt}' is an unsupported encoding format"
192
+ raise Error, "'#{fmt}' is an unsupported encoding format"
194
193
  end
195
194
  end
196
195
 
@@ -201,7 +200,7 @@ module TTFunk
201
200
  when 0 then :array_format
202
201
  when 1 then :range_format
203
202
  else
204
- raise "unsupported charset format '#{fmt}'"
203
+ raise Error, "unsupported charset format '#{fmt}'"
205
204
  end
206
205
  end
207
206
 
@@ -211,7 +210,7 @@ module TTFunk
211
210
  when :range_format then 1
212
211
  when :supplemental then 129
213
212
  else
214
- raise "unsupported charset format '#{sym}'"
213
+ raise Error, "unsupported charset format '#{sym}'"
215
214
  end
216
215
  end
217
216
  end
@@ -4,7 +4,7 @@ module TTFunk
4
4
  class Table
5
5
  class Cff < TTFunk::Table
6
6
  module Encodings
7
- autoload :EXPERT, 'ttfunk/table/cff/encodings/expert'
7
+ autoload :EXPERT, 'ttfunk/table/cff/encodings/expert'
8
8
  autoload :STANDARD, 'ttfunk/table/cff/encodings/standard'
9
9
  end
10
10
  end
@@ -29,7 +29,8 @@ module TTFunk
29
29
  return entry
30
30
  end
31
31
 
32
- range, entry = entries.bsearch do |rng, _|
32
+ range, entry =
33
+ entries.bsearch do |rng, _|
33
34
  if rng.cover?(glyph_id)
34
35
  0
35
36
  elsif glyph_id < rng.first
@@ -53,9 +54,10 @@ module TTFunk
53
54
  # mapping is new -> old glyph ids
54
55
  def encode(mapping)
55
56
  # get list of [new_gid, fd_index] pairs
56
- new_indices = mapping.keys.sort.map do |new_gid|
57
- [new_gid, self[mapping[new_gid]]]
58
- end
57
+ new_indices =
58
+ mapping.keys.sort.map do |new_gid|
59
+ [new_gid, self[mapping[new_gid]]]
60
+ end
59
61
 
60
62
  ranges = rangify_gids(new_indices)
61
63
  total_range_size = ranges.size * RANGE_ENTRY_SIZE
@@ -119,11 +121,12 @@ module TTFunk
119
121
 
120
122
  ranges = Array.new(num_ranges) { read(RANGE_ENTRY_SIZE, 'nC') }
121
123
 
122
- @entries = ranges.each_cons(2).map do |first, second|
123
- first_gid, fd_index = first
124
- second_gid, = second
125
- [(first_gid...second_gid), fd_index]
126
- end
124
+ @entries =
125
+ ranges.each_cons(2).map do |first, second|
126
+ first_gid, fd_index = first
127
+ second_gid, = second
128
+ [(first_gid...second_gid), fd_index]
129
+ end
127
130
 
128
131
  # read the sentinel GID, otherwise known as the number of glyphs
129
132
  # in the font
@@ -132,7 +135,7 @@ module TTFunk
132
135
  last_start_gid, last_fd_index = ranges.last
133
136
  @entries << [(last_start_gid...(n_glyphs + 1)), last_fd_index]
134
137
 
135
- @count = entries.inject(0) { |sum, entry| sum + entry.first.size }
138
+ @count = entries.reduce(0) { |sum, entry| sum + entry.first.size }
136
139
  end
137
140
  end
138
141
 
@@ -141,7 +144,7 @@ module TTFunk
141
144
  when ARRAY_FORMAT then :array_format
142
145
  when RANGE_FORMAT then :range_format
143
146
  else
144
- raise "unsupported fd select format '#{@format}'"
147
+ raise Error, "unsupported fd select format '#{@format}'"
145
148
  end
146
149
  end
147
150
  end
@@ -12,12 +12,13 @@ module TTFunk
12
12
  end
13
13
 
14
14
  def [](index)
15
- entry_cache[index] ||= begin
16
- start, finish = absolute_offsets_for(index)
17
- TTFunk::Table::Cff::FontDict.new(
18
- top_dict, file, start, (finish - start) + 1
19
- )
20
- end
15
+ entry_cache[index] ||=
16
+ begin
17
+ start, finish = absolute_offsets_for(index)
18
+ TTFunk::Table::Cff::FontDict.new(
19
+ top_dict, file, start, (finish - start) + 1
20
+ )
21
+ end
21
22
  end
22
23
 
23
24
  def finalize(new_cff_data, mapping)
@@ -30,10 +30,11 @@ module TTFunk
30
30
  def encode
31
31
  result = EncodedString.new
32
32
 
33
- entries = each_with_object([]).with_index do |(entry, ret), index|
34
- new_entry = block_given? ? yield(entry, index) : entry
35
- ret << new_entry if new_entry
36
- end
33
+ entries =
34
+ each_with_object([]).with_index do |(entry, ret), index|
35
+ new_entry = block_given? ? yield(entry, index) : entry
36
+ ret << new_entry if new_entry
37
+ end
37
38
 
38
39
  # "An empty INDEX is represented by a count field with a 0 value and
39
40
  # no additional fields. Thus, the total size of an empty INDEX is 2
@@ -89,7 +90,7 @@ module TTFunk
89
90
  def parse!
90
91
  @count = read(2, 'n').first
91
92
 
92
- if count == 0
93
+ if count.zero?
93
94
  @length = 2
94
95
  @data = []
95
96
  return
@@ -8,8 +8,12 @@ module TTFunk
8
8
  class OneBasedIndex
9
9
  extend Forwardable
10
10
 
11
- def_delegators :base_index, :each, :table_offset,
12
- :count, :length, :encode
11
+ def_delegators :base_index,
12
+ :each,
13
+ :table_offset,
14
+ :count,
15
+ :length,
16
+ :encode
13
17
 
14
18
  attr_reader :base_index
15
19
 
@@ -18,7 +22,7 @@ module TTFunk
18
22
  end
19
23
 
20
24
  def [](idx)
21
- if idx == 0
25
+ if idx.zero?
22
26
  raise IndexError,
23
27
  "index #{idx} was outside the bounds of the index"
24
28
  end