ttfunk 1.7.0 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +74 -0
  4. data/README.md +17 -15
  5. data/lib/ttfunk/aggregate.rb +5 -0
  6. data/lib/ttfunk/bin_utils.rb +27 -8
  7. data/lib/ttfunk/bit_field.rb +25 -2
  8. data/lib/ttfunk/collection.rb +27 -3
  9. data/lib/ttfunk/directory.rb +7 -1
  10. data/lib/ttfunk/encoded_string.rb +58 -4
  11. data/lib/ttfunk/max.rb +14 -0
  12. data/lib/ttfunk/min.rb +14 -0
  13. data/lib/ttfunk/one_based_array.rb +20 -0
  14. data/lib/ttfunk/otf_encoder.rb +5 -14
  15. data/lib/ttfunk/placeholder.rb +15 -1
  16. data/lib/ttfunk/reader.rb +6 -4
  17. data/lib/ttfunk/resource_file.rb +29 -5
  18. data/lib/ttfunk/sci_form.rb +20 -3
  19. data/lib/ttfunk/sub_table.rb +29 -4
  20. data/lib/ttfunk/subset/base.rb +48 -0
  21. data/lib/ttfunk/subset/code_page.rb +49 -2
  22. data/lib/ttfunk/subset/mac_roman.rb +2 -0
  23. data/lib/ttfunk/subset/unicode.rb +32 -0
  24. data/lib/ttfunk/subset/unicode_8bit.rb +32 -0
  25. data/lib/ttfunk/subset/windows_1252.rb +2 -0
  26. data/lib/ttfunk/subset.rb +8 -0
  27. data/lib/ttfunk/subset_collection.rb +39 -14
  28. data/lib/ttfunk/sum.rb +13 -0
  29. data/lib/ttfunk/table/cff/charset.rb +96 -18
  30. data/lib/ttfunk/table/cff/charsets/expert.rb +3 -2
  31. data/lib/ttfunk/table/cff/charsets/expert_subset.rb +3 -2
  32. data/lib/ttfunk/table/cff/charsets/iso_adobe.rb +3 -2
  33. data/lib/ttfunk/table/cff/charsets/standard_strings.rb +3 -2
  34. data/lib/ttfunk/table/cff/charsets.rb +1 -0
  35. data/lib/ttfunk/table/cff/charstring.rb +33 -12
  36. data/lib/ttfunk/table/cff/charstrings_index.rb +17 -11
  37. data/lib/ttfunk/table/cff/dict.rb +53 -23
  38. data/lib/ttfunk/table/cff/encoding.rb +82 -24
  39. data/lib/ttfunk/table/cff/encodings/expert.rb +3 -2
  40. data/lib/ttfunk/table/cff/encodings/standard.rb +3 -2
  41. data/lib/ttfunk/table/cff/encodings.rb +1 -0
  42. data/lib/ttfunk/table/cff/fd_selector.rb +61 -21
  43. data/lib/ttfunk/table/cff/font_dict.rb +30 -18
  44. data/lib/ttfunk/table/cff/font_index.rb +22 -10
  45. data/lib/ttfunk/table/cff/header.rb +16 -3
  46. data/lib/ttfunk/table/cff/index.rb +97 -65
  47. data/lib/ttfunk/table/cff/one_based_index.rb +11 -1
  48. data/lib/ttfunk/table/cff/path.rb +43 -4
  49. data/lib/ttfunk/table/cff/private_dict.rb +31 -11
  50. data/lib/ttfunk/table/cff/subr_index.rb +7 -2
  51. data/lib/ttfunk/table/cff/top_dict.rb +82 -59
  52. data/lib/ttfunk/table/cff/top_index.rb +10 -6
  53. data/lib/ttfunk/table/cff.rb +41 -21
  54. data/lib/ttfunk/table/cmap/format00.rb +27 -6
  55. data/lib/ttfunk/table/cmap/format04.rb +34 -14
  56. data/lib/ttfunk/table/cmap/format06.rb +28 -1
  57. data/lib/ttfunk/table/cmap/format10.rb +29 -2
  58. data/lib/ttfunk/table/cmap/format12.rb +29 -2
  59. data/lib/ttfunk/table/cmap/subtable.rb +50 -6
  60. data/lib/ttfunk/table/cmap.rb +21 -0
  61. data/lib/ttfunk/table/dsig.rb +47 -6
  62. data/lib/ttfunk/table/glyf/compound.rb +73 -6
  63. data/lib/ttfunk/table/glyf/path_based.rb +40 -3
  64. data/lib/ttfunk/table/glyf/simple.rb +50 -5
  65. data/lib/ttfunk/table/glyf.rb +15 -7
  66. data/lib/ttfunk/table/head.rb +84 -6
  67. data/lib/ttfunk/table/hhea.rb +71 -10
  68. data/lib/ttfunk/table/hmtx.rb +32 -5
  69. data/lib/ttfunk/table/kern/format0.rb +25 -7
  70. data/lib/ttfunk/table/kern.rb +16 -4
  71. data/lib/ttfunk/table/loca.rb +21 -8
  72. data/lib/ttfunk/table/maxp.rb +195 -10
  73. data/lib/ttfunk/table/name.rb +126 -9
  74. data/lib/ttfunk/table/os2.rb +150 -26
  75. data/lib/ttfunk/table/post/format10.rb +7 -0
  76. data/lib/ttfunk/table/post/format20.rb +9 -0
  77. data/lib/ttfunk/table/post/format30.rb +6 -0
  78. data/lib/ttfunk/table/post/format40.rb +5 -0
  79. data/lib/ttfunk/table/post.rb +63 -7
  80. data/lib/ttfunk/table/sbix.rb +50 -14
  81. data/lib/ttfunk/table/simple.rb +5 -0
  82. data/lib/ttfunk/table/vorg.rb +31 -3
  83. data/lib/ttfunk/table.rb +20 -1
  84. data/lib/ttfunk/ttf_encoder.rb +39 -41
  85. data/lib/ttfunk.rb +154 -1
  86. data.tar.gz.sig +0 -0
  87. metadata +50 -28
  88. metadata.gz.sig +0 -0
@@ -3,10 +3,30 @@
3
3
  module TTFunk
4
4
  class Table
5
5
  class Cmap
6
+ # Format 12: Segmented coverage.
7
+ #
8
+ # This module conditionally extends {TTFunk::Table::Cmap::Subtable}.
6
9
  module Format12
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 12.
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 }
@@ -32,23 +52,30 @@ module TTFunk
32
52
  end
33
53
 
34
54
  subtable = [
35
- 12, 0, 16 + 12 * range_lengths.size, 0, range_lengths.size
55
+ 12, 0, 16 + (12 * range_lengths.size), 0, range_lengths.size,
36
56
  ].pack('nnNNN')
37
57
  range_lengths.each_with_index do |length, i|
38
58
  firstglyph = range_firstglyphs[i]
39
59
  firstcode = range_firstcodes[i]
40
60
  subtable << [
41
- firstcode, firstcode + length - 1, firstglyph
61
+ firstcode, firstcode + length - 1, firstglyph,
42
62
  ].pack('NNN')
43
63
  end
44
64
 
45
65
  { charmap: new_map, subtable: subtable, max_glyph_id: next_id + 1 }
46
66
  end
47
67
 
68
+ # Get glyph ID for character code.
69
+ #
70
+ # @param code [Integer] character code.
71
+ # @return [Integer] glyph ID.
48
72
  def [](code)
49
73
  @code_map[code] || 0
50
74
  end
51
75
 
76
+ # Is this encoding record format supported?
77
+ #
78
+ # @return [true]
52
79
  def supported?
53
80
  true
54
81
  end
@@ -5,21 +5,54 @@ require_relative '../../reader'
5
5
  module TTFunk
6
6
  class Table
7
7
  class Cmap
8
+ # Character to Glyph Index encoding record.
9
+ # This class can be extended with a format-specific
10
+ #
11
+ # @see TTFunk::Table::Cmap::Format00
12
+ # @see TTFunk::Table::Cmap::Format04
13
+ # @see TTFunk::Table::Cmap::Format06
14
+ # @see TTFunk::Table::Cmap::Format10
15
+ # @see TTFunk::Table::Cmap::Format12
8
16
  class Subtable
9
17
  include Reader
10
18
 
19
+ # Platform ID.
20
+ # @return [Integer]
11
21
  attr_reader :platform_id
22
+
23
+ # Platform-specific encoding ID.
24
+ # @return [Integere]
12
25
  attr_reader :encoding_id
26
+
27
+ # Record encoding format.
28
+ # @return [Integer]
13
29
  attr_reader :format
14
30
 
31
+ # Most used encoding mappings.
15
32
  ENCODING_MAPPINGS = {
16
33
  mac_roman: { platform_id: 1, encoding_id: 0 }.freeze,
17
34
  # Use microsoft unicode, instead of generic unicode, for optimal
18
35
  # Windows support
19
36
  unicode: { platform_id: 3, encoding_id: 1 }.freeze,
20
- unicode_ucs4: { platform_id: 3, encoding_id: 10 }.freeze
37
+ unicode_ucs4: { platform_id: 3, encoding_id: 10 }.freeze,
21
38
  }.freeze
22
39
 
40
+ # Encode encoding record.
41
+ #
42
+ # @param charmap [Hash{Integer => Integer}] keys are code points in the
43
+ # used encoding, values are Unicode code points.
44
+ # @param encoding [Symbol] - one of the encodign mapping in
45
+ # {ENCODING_MAPPINGS}
46
+ # @return [Hash]
47
+ # * `:platform_id` (<tt>Integer</tt>) - Platform ID of this encoding record.
48
+ # * `:encoding_id` (<tt>Integer</tt>) - Encodign ID of this encoding record.
49
+ # * `:subtable` (<tt>String</tt>) - encoded encoding record.
50
+ # * `:max_glyph_id` (<tt>Integer</tt>) - maximum glyph ID in this encoding
51
+ # record.
52
+ # * `:charmap` (<tt>Hash{Integer => Hash}</tt>) - keys are codepoints in this
53
+ # encoding record, values are hashes:
54
+ # * `:new` - new glyph ID.
55
+ # * `:old` - glyph ID in the original font.
23
56
  def self.encode(charmap, encoding)
24
57
  case encoding
25
58
  when :mac_roman
@@ -43,11 +76,13 @@ module TTFunk
43
76
  mapping[:platform_id],
44
77
  mapping[:encoding_id],
45
78
  12,
46
- result[:subtable]
47
- ].pack('nnNA*')
79
+ result[:subtable],
80
+ ].pack('nnNA*'),
48
81
  )
49
82
  end
50
83
 
84
+ # @param file [TTFunk::File]
85
+ # @param table_start [Integer]
51
86
  def initialize(file, table_start)
52
87
  @file = file
53
88
  @platform_id, @encoding_id, @offset = read(8, 'nnN')
@@ -68,16 +103,25 @@ module TTFunk
68
103
  end
69
104
  end
70
105
 
106
+ # Is this an encoding record for Unicode?
107
+ #
108
+ # @return [Boolean]
71
109
  def unicode?
72
- platform_id == 3 && (encoding_id == 1 || encoding_id == 10) &&
73
- format != 0 ||
74
- platform_id.zero? && format != 0
110
+ (platform_id == 3 && (encoding_id == 1 || encoding_id == 10) && format != 0) ||
111
+ (platform_id.zero? && format != 0)
75
112
  end
76
113
 
114
+ # Is this encoding record format supported?
115
+ #
116
+ # @return [Boolean]
77
117
  def supported?
78
118
  false
79
119
  end
80
120
 
121
+ # Get glyph ID for character code.
122
+ #
123
+ # @param _code [Integer] character code.
124
+ # @return [Integer] glyph ID.
81
125
  def [](_code)
82
126
  raise NotImplementedError, "cmap format #{@format} is not supported"
83
127
  end
@@ -2,10 +2,28 @@
2
2
 
3
3
  module TTFunk
4
4
  class Table
5
+ # Character to Glyph Index Mapping (`cmap`) table.
5
6
  class Cmap < Table
7
+ # Table version.
8
+ # @return [Integer]
6
9
  attr_reader :version
10
+
11
+ # Encoding tables.
12
+ # @return [Array<TTFunk::Table::Cmap::Subtable>]
7
13
  attr_reader :tables
8
14
 
15
+ # Encode table.
16
+ #
17
+ # @param charmap [Hash{Integer => Integer}]
18
+ # @param encoding [Symbol]
19
+ # @return [Hash]
20
+ # * `:charmap` (<tt>Hash{Integer => Hash}</tt>) keys are the characrers in
21
+ # `charset`, values are hashes:
22
+ # * `:old` (<tt>Integer</tt>) - glyph ID in the original font.
23
+ # * `:new` (<tt>Integer</tt>) - glyph ID in the subset font.
24
+ # that maps the characters in charmap to a
25
+ # * `:table` (<tt>String</tt>) - serialized table.
26
+ # * `:max_glyph_id` (<tt>Integer</tt>) - maximum glyph ID in the new font.
9
27
  def self.encode(charmap, encoding)
10
28
  result = Cmap::Subtable.encode(charmap, encoding)
11
29
 
@@ -14,6 +32,9 @@ module TTFunk
14
32
  result
15
33
  end
16
34
 
35
+ # Get Unicode encoding records.
36
+ #
37
+ # @return [Array<TTFunk::Table::Cmap::Subtable>]
17
38
  def unicode
18
39
  # Because most callers just call .first on the result, put tables with
19
40
  # highest-number format first. Unsupported formats will be ignored.
@@ -2,10 +2,30 @@
2
2
 
3
3
  module TTFunk
4
4
  class Table
5
+ # Digital Signature (`DSIG`) table.
5
6
  class Dsig < Table
7
+ # Signature record.
6
8
  class SignatureRecord
7
- attr_reader :format, :length, :offset, :signature
9
+ # Format of the signature.
10
+ # @return [Integer]
11
+ attr_reader :format
8
12
 
13
+ # Length of signature in bytes.
14
+ # @return [Integer]
15
+ attr_reader :length
16
+
17
+ # Offset to the signature block from the beginning of the table.
18
+ # @return [Integer]
19
+ attr_reader :offset
20
+
21
+ # Signature PKCS#7 packet.
22
+ # @return [String]
23
+ attr_reader :signature
24
+
25
+ # @param format [Integer]
26
+ # @param length [Integer]
27
+ # @param offset [Integer]
28
+ # @param signature [String]
9
29
  def initialize(format, length, offset, signature)
10
30
  @format = format
11
31
  @length = length
@@ -14,10 +34,28 @@ module TTFunk
14
34
  end
15
35
  end
16
36
 
17
- attr_reader :version, :flags, :signatures
37
+ # Version umber of this table.
38
+ # @return [Integer]
39
+ attr_reader :version
40
+
41
+ # Permission flags.
42
+ # @return [Integer]
43
+ attr_reader :flags
44
+
45
+ # Signature records.
46
+ # @return [Array<SignatureRecord>]
47
+ attr_reader :signatures
18
48
 
49
+ # Table tag.
19
50
  TAG = 'DSIG'
20
51
 
52
+ # Encode table.
53
+ #
54
+ # **Note**: all signatures will be lost. This encodes an empty table
55
+ # regardless whether the supplied table contains any signtaures or not.
56
+ #
57
+ # @param dsig [TTFunk::Table::Dsig]
58
+ # @return [String]
21
59
  def self.encode(dsig)
22
60
  return unless dsig
23
61
 
@@ -26,6 +64,9 @@ module TTFunk
26
64
  [dsig.version, 0, 0].pack('Nnn')
27
65
  end
28
66
 
67
+ # Table tag.
68
+ #
69
+ # @return [String]
29
70
  def tag
30
71
  TAG
31
72
  end
@@ -36,16 +77,16 @@ module TTFunk
36
77
  @version, num_signatures, @flags = read(8, 'Nnn')
37
78
 
38
79
  @signatures =
39
- Array.new(num_signatures) do
80
+ Array.new(num_signatures) {
40
81
  format, length, sig_offset = read(12, 'N3')
41
82
  signature =
42
- parse_from(offset + sig_offset) do
83
+ parse_from(offset + sig_offset) {
43
84
  _, _, sig_length = read(8, 'nnN')
44
85
  read(sig_length, 'C*')
45
- end
86
+ }
46
87
 
47
88
  SignatureRecord.new(format, length, sig_offset, signature)
48
- end
89
+ }
49
90
  end
50
91
  end
51
92
  end
@@ -5,32 +5,92 @@ require_relative '../../reader'
5
5
  module TTFunk
6
6
  class Table
7
7
  class Glyf
8
+ # Composite TrueType glyph.
8
9
  class Compound
9
10
  include Reader
10
11
 
12
+ # Flags bit 0: arg1 and arg2 are words.
11
13
  ARG_1_AND_2_ARE_WORDS = 0x0001
14
+
15
+ # Flags bit 3: there is a simple scale for the component.
12
16
  WE_HAVE_A_SCALE = 0x0008
17
+
18
+ # Flags bit 5: at least one more glyph after this one.
13
19
  MORE_COMPONENTS = 0x0020
20
+
21
+ # Flags bit 6: the x direction will use a different scale from the
22
+ # y direction.
14
23
  WE_HAVE_AN_X_AND_Y_SCALE = 0x0040
24
+
25
+ # Flags bit 7: there is a 2 by 2 transformation that will be used to
26
+ # scale the component.
15
27
  WE_HAVE_A_TWO_BY_TWO = 0x0080
28
+
29
+ # Flags bit 8: following the last component are instructions for the
30
+ # composite character.
16
31
  WE_HAVE_INSTRUCTIONS = 0x0100
17
32
 
18
- attr_reader :id, :raw
33
+ # Glyph ID.
34
+ # @return [Integer]
35
+ attr_reader :id
36
+
37
+ # Binary serialization of this glyph.
38
+ # @return [String]
39
+ attr_reader :raw
40
+
41
+ # Number of contours in this glyph.
42
+ # @return [Integer]
19
43
  attr_reader :number_of_contours
20
- attr_reader :x_min, :y_min, :x_max, :y_max
44
+
45
+ # Minimum x for coordinate.
46
+ # @return [Integer]
47
+ attr_reader :x_min
48
+
49
+ # Minimum y for coordinate.
50
+ # @return [Integer]
51
+ attr_reader :y_min
52
+
53
+ # Maximum x for coordinate.
54
+ # @return [Integer]
55
+ attr_reader :x_max
56
+
57
+ # Maximum y for coordinate.
58
+ # @return [Integer]
59
+ attr_reader :y_max
60
+
61
+ # IDs of compound glyphs.
21
62
  attr_reader :glyph_ids
22
63
 
64
+ # Component glyph.
65
+ #
66
+ # @!attribute [rw] flags
67
+ # Component flag.
68
+ # @return [Integer]
69
+ # @!attribute [rw] glyph_index
70
+ # Glyph index of component.
71
+ # @return [Integer]
72
+ # @!attribute [rw] arg1
73
+ # x-offset for component or point number.
74
+ # @return [Integer]
75
+ # @!attribute [rw] arg2
76
+ # y-offset for component or point number.
77
+ # @return [Integer]
78
+ # @!attribute [rw] transform
79
+ # Transformation.
80
+ # @return []
23
81
  Component = Struct.new(:flags, :glyph_index, :arg1, :arg2, :transform)
24
82
 
83
+ # @param id [Integer] glyph ID.
84
+ # @param raw [String]
25
85
  def initialize(id, raw)
26
86
  @id = id
27
87
  @raw = raw
28
88
  io = StringIO.new(raw)
29
89
 
30
90
  @number_of_contours, @x_min, @y_min, @x_max, @y_max =
31
- io.read(10).unpack('n*').map do |i|
91
+ io.read(10).unpack('n*').map { |i|
32
92
  BinUtils.twos_comp_to_int(i, bit_width: 16)
33
- end
93
+ }
34
94
 
35
95
  # Because TTFunk only cares about glyphs insofar as they (1) provide
36
96
  # a bounding box for each glyph, and (2) can be rewritten into a
@@ -48,9 +108,9 @@ module TTFunk
48
108
  loop do
49
109
  flags, glyph_id = @raw[offset, 4].unpack('n*')
50
110
  @glyph_ids << glyph_id
51
- @glyph_id_offsets << offset + 2
111
+ @glyph_id_offsets << (offset + 2)
52
112
 
53
- break unless flags & MORE_COMPONENTS != 0
113
+ break if (flags & MORE_COMPONENTS).zero?
54
114
 
55
115
  offset += 4
56
116
 
@@ -71,10 +131,17 @@ module TTFunk
71
131
  end
72
132
  end
73
133
 
134
+ # Is this a composite glyph?
135
+ # @return [true]
74
136
  def compound?
75
137
  true
76
138
  end
77
139
 
140
+ # Recode glyph.
141
+ #
142
+ # @param mapping [Hash{Integer => Integer}] a hash mapping old glyph IDs
143
+ # to new glyph IDs.
144
+ # @return [String]
78
145
  def recode(mapping)
79
146
  result = raw.dup
80
147
  new_ids = glyph_ids.map { |id| mapping[id] }
@@ -3,11 +3,42 @@
3
3
  module TTFunk
4
4
  class Table
5
5
  class Glyf
6
+ # TrueType-compatible representation of a CFF glyph.
6
7
  class PathBased
7
- attr_reader :path, :horizontal_metrics
8
- attr_reader :x_min, :y_min, :x_max, :y_max
9
- attr_reader :left_side_bearing, :right_side_bearing
8
+ # Glyph outline.
9
+ # @return [TTFunk::Table::Cff::Path]
10
+ attr_reader :path
10
11
 
12
+ # Glyph horizontal metrics.
13
+ # @return [TTFunk::Table::Hmtx::HorizontalMetric]
14
+ attr_reader :horizontal_metrics
15
+
16
+ # Minimum X.
17
+ # @return [Integer, Float]
18
+ attr_reader :x_min
19
+
20
+ # Minimum Y.
21
+ # @return [Integer, Float]
22
+ attr_reader :y_min
23
+
24
+ # Maximum X.
25
+ # @return [Integer, Float]
26
+ attr_reader :x_max
27
+
28
+ # Maximum Y.
29
+ # @return [Integer, Float]
30
+ attr_reader :y_max
31
+
32
+ # Left side bearing.
33
+ # @return [Integer, Float]
34
+ attr_reader :left_side_bearing
35
+
36
+ # Rigth side bearing.
37
+ # @return [Integer, Float]
38
+ attr_reader :right_side_bearing
39
+
40
+ # @param path [TTFunk::Table::Cff::Path]
41
+ # @param horizontal_metrics [TTFunk::Table::Hmtx::HorizontalMetric]
11
42
  def initialize(path, horizontal_metrics)
12
43
  @path = path
13
44
  @horizontal_metrics = horizontal_metrics
@@ -34,10 +65,16 @@ module TTFunk
34
65
  (@x_max - @x_min)
35
66
  end
36
67
 
68
+ # Number of contour.
69
+ #
70
+ # @return [Integer]
37
71
  def number_of_contours
38
72
  path.number_of_contours
39
73
  end
40
74
 
75
+ # Is this glyph compound?
76
+ #
77
+ # @return [false]
41
78
  def compound?
42
79
  false
43
80
  end
@@ -5,36 +5,81 @@ require_relative '../../reader'
5
5
  module TTFunk
6
6
  class Table
7
7
  class Glyf
8
+ # Simple TrueType glyph
8
9
  class Simple
9
- attr_reader :id, :raw
10
+ # Glyph ID.
11
+ # @return [Integer]
12
+ attr_reader :id
13
+
14
+ # Binary serialization of this glyph.
15
+ # @return [String]
16
+ attr_reader :raw
17
+
18
+ # Number of contours in this glyph.
19
+ # @return [Integer]
10
20
  attr_reader :number_of_contours
11
- attr_reader :x_min, :y_min, :x_max, :y_max
21
+
22
+ # Minimum x for coordinate.
23
+ # @return [Integer]
24
+ attr_reader :x_min
25
+
26
+ # Minimum y for coordinate.
27
+ # @return [Integer]
28
+ attr_reader :y_min
29
+
30
+ # Maximum x for coordinate.
31
+ # @return [Integer]
32
+ attr_reader :x_max
33
+
34
+ # Maximum y for coordinate.
35
+ # @return [Integer]
36
+ attr_reader :y_max
37
+
38
+ # Point indices for the last point of each contour.
39
+ # @return [Array<Integer>]
12
40
  attr_reader :end_points_of_contours
13
- attr_reader :instruction_length, :instructions
14
41
 
42
+ # Total number of bytes for instructions.
43
+ # @return [Integer]
44
+ attr_reader :instruction_length
45
+
46
+ # Instruction byte code.
47
+ # @return [Array<Integer>]
48
+ attr_reader :instructions
49
+
50
+ # @param id [Integer] glyph ID.
51
+ # @param raw [String]
15
52
  def initialize(id, raw)
16
53
  @id = id
17
54
  @raw = raw
18
55
  io = StringIO.new(raw)
19
56
 
20
57
  @number_of_contours, @x_min, @y_min, @x_max, @y_max =
21
- io.read(10).unpack('n*').map do |i|
58
+ io.read(10).unpack('n*').map { |i|
22
59
  BinUtils.twos_comp_to_int(i, bit_width: 16)
23
- end
60
+ }
24
61
 
25
62
  @end_points_of_contours = io.read(number_of_contours * 2).unpack('n*')
26
63
  @instruction_length = io.read(2).unpack1('n')
27
64
  @instructions = io.read(instruction_length).unpack('C*')
28
65
  end
29
66
 
67
+ # Is this glyph compound?
68
+ # @return [false]
30
69
  def compound?
31
70
  false
32
71
  end
33
72
 
73
+ # Recode glyph.
74
+ #
75
+ # @param _mapping Unused, here for API compatibility.
76
+ # @return [String]
34
77
  def recode(_mapping)
35
78
  raw
36
79
  end
37
80
 
81
+ # End point index of last contour.
82
+ # @return [Integer]
38
83
  def end_point_of_last_contour
39
84
  end_points_of_contours.last + 1
40
85
  end
@@ -4,15 +4,18 @@ require_relative '../table'
4
4
 
5
5
  module TTFunk
6
6
  class Table
7
+ # Glyph Data (`glyf`) table.
7
8
  class Glyf < Table
8
- # Accepts a hash mapping (old) glyph-ids to glyph objects, and a hash
9
- # mapping old glyph-ids to new glyph-ids.
9
+ # Encode table.
10
10
  #
11
- # Returns a hash containing:
12
- #
13
- # * :table - a string representing the encoded 'glyf' table containing
14
- # the given glyphs.
15
- # * :offsets - an array of offsets for each glyph
11
+ # @param glyphs [Hash] a hash mapping (old) glyph-ids to glyph objects
12
+ # @param new_to_old [Hash{Integer => Integer}] a hash mapping new glyph
13
+ # IDs to glyph IDs in the original font.
14
+ # @param old_to_new [Hash{Integer => Integer}] a hash mapping old glyph
15
+ # IDs to new glyph IDs.
16
+ # @return [Hash]
17
+ # * `:table` (<tt>String</tt>) - encoded table.
18
+ # * `:offsets` (<tt>Array\<Integer></tt>) - glyph offsets in the table.
16
19
  def self.encode(glyphs, new_to_old, old_to_new)
17
20
  result = { table: +'', offsets: [] }
18
21
 
@@ -28,6 +31,11 @@ module TTFunk
28
31
  result
29
32
  end
30
33
 
34
+ # Get glyph by ID.
35
+ #
36
+ # @param glyph_id [Integer]
37
+ # @return [TTFunk::Table::Glyf::Simple, TTFunk::Table::Glyf::Compound,
38
+ # nil]
31
39
  def for(glyph_id)
32
40
  return @cache[glyph_id] if @cache.key?(glyph_id)
33
41