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.
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
@@ -4,19 +4,37 @@ require_relative '../table'
4
4
 
5
5
  module TTFunk
6
6
  class Table
7
+ # Vertical Origin (`VORG`) table.
7
8
  class Vorg < Table
9
+ # Table tag.
8
10
  TAG = 'VORG'
9
11
 
10
- attr_reader :major_version, :minor_version
11
- attr_reader :default_vert_origin_y, :count
12
+ # Table major version.
13
+ # @return [Integer]
14
+ attr_reader :major_version
12
15
 
16
+ # Table minor version.
17
+ # @return [Integer]
18
+ attr_reader :minor_version
19
+
20
+ # The default y coordinate of a glyph’s vertical origin.
21
+ # @return [Integer]
22
+ attr_reader :default_vert_origin_y
23
+
24
+ # Number of vertical origin metrics.
25
+ # @return [Integer]
26
+ attr_reader :count
27
+
28
+ # Encode table.
29
+ #
30
+ # @return [String]
13
31
  def self.encode(vorg)
14
32
  return unless vorg
15
33
 
16
34
  ''.b.tap do |table|
17
35
  table << [
18
36
  vorg.major_version, vorg.minor_version,
19
- vorg.default_vert_origin_y, vorg.count
37
+ vorg.default_vert_origin_y, vorg.count,
20
38
  ].pack('n*')
21
39
 
22
40
  vorg.origins.each_pair do |glyph_id, vert_origin_y|
@@ -25,14 +43,24 @@ module TTFunk
25
43
  end
26
44
  end
27
45
 
46
+ # Get vertical origina for glyph by ID.
47
+ #
48
+ # @param glyph_id [Integer]
49
+ # @return [Integer]
28
50
  def for(glyph_id)
29
51
  @origins.fetch(glyph_id, default_vert_origin_y)
30
52
  end
31
53
 
54
+ # Table tag.
55
+ #
56
+ # @return [String]
32
57
  def tag
33
58
  TAG
34
59
  end
35
60
 
61
+ # Origins map.
62
+ #
63
+ # @return [Hash{Integer => Integer}]
36
64
  def origins
37
65
  @origins ||= {}
38
66
  end
data/lib/ttfunk/table.rb CHANGED
@@ -3,13 +3,23 @@
3
3
  require_relative 'reader'
4
4
 
5
5
  module TTFunk
6
+ # SFNT table
6
7
  class Table
7
8
  include Reader
8
9
 
10
+ # File this table is in.
11
+ # @return [TTFunk::File]
9
12
  attr_reader :file
13
+
14
+ # This table's offset from the file beginning.
15
+ # @return [Integer]
10
16
  attr_reader :offset
17
+
18
+ # This table's length in byes.
19
+ # @return [Integer, nil]
11
20
  attr_reader :length
12
21
 
22
+ # @param file [TTFunk::File]
13
23
  def initialize(file)
14
24
  @file = file
15
25
  @offset = nil
@@ -25,18 +35,27 @@ module TTFunk
25
35
  end
26
36
  end
27
37
 
38
+ # Does this table exist in the file?
39
+ #
40
+ # @return [Boolean]
28
41
  def exists?
29
42
  !@offset.nil?
30
43
  end
31
44
 
45
+ # Raw bytes of this table in the file.
46
+ #
47
+ # @return [String, nil]
32
48
  def raw
33
49
  if exists?
34
50
  parse_from(offset) { io.read(length) }
35
51
  end
36
52
  end
37
53
 
54
+ # Table tag.
55
+ #
56
+ # @return [String]
38
57
  def tag
39
- self.class.name.split(/::/).last.downcase
58
+ self.class.name.split('::').last.downcase
40
59
  end
41
60
 
42
61
  private
@@ -1,26 +1,46 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTFunk
4
+ # Encodes a TrueType font subset to its binary representation.
4
5
  class TTFEncoder
6
+ # Optimal table order according to TrueType specification.
5
7
  OPTIMAL_TABLE_ORDER = [
6
8
  'head', 'hhea', 'maxp', 'OS/2', 'hmtx', 'LTSH', 'VDMX',
7
9
  'hdmx', 'cmap', 'fpgm', 'prep', 'cvt ', 'loca', 'glyf',
8
- 'kern', 'name', 'post', 'gasp', 'PCLT'
10
+ 'kern', 'name', 'post', 'gasp', 'PCLT',
9
11
  ].freeze
10
12
 
11
- attr_reader :original, :subset, :options
13
+ # Original font.
14
+ # @return [TTFunk::File]
15
+ attr_reader :original
12
16
 
17
+ # Subset to encode.
18
+ # @return [TTFunk::Subset]
19
+ attr_reader :subset
20
+
21
+ # Encoding options.
22
+ # @return [Hash]
23
+ attr_reader :options
24
+
25
+ # @param original [TTFunk::File]
26
+ # @param subset [TTFunk::Subset]
27
+ # @param options [Hash]
28
+ # @option options :kerning [Boolean] whether to encode Kerning (`kern`)
29
+ # table.
13
30
  def initialize(original, subset, options = {})
14
31
  @original = original
15
32
  @subset = subset
16
33
  @options = options
17
34
  end
18
35
 
36
+ # Encode the font subset.
37
+ #
38
+ # @return [String]
19
39
  def encode
20
40
  # https://www.microsoft.com/typography/otspec/otff.htm#offsetTable
21
- search_range = 2**Math.log2(tables.length).floor * 16
22
- entry_selector = Math.log2(2**Math.log2(tables.length).floor).to_i
23
- range_shift = tables.length * 16 - search_range
41
+ search_range = (2**Math.log2(tables.length).floor) * 16
42
+ entry_selector = Integer(Math.log2(2**Math.log2(tables.length).floor))
43
+ range_shift = (tables.length * 16) - search_range
24
44
  range_shift = 0 if range_shift.negative?
25
45
 
26
46
  newfont = EncodedString.new
@@ -30,7 +50,7 @@ module TTFunk
30
50
  tables.length,
31
51
  search_range,
32
52
  entry_selector,
33
- range_shift
53
+ range_shift,
34
54
  ].pack('Nn*')
35
55
 
36
56
  # Tables are supposed to be listed in ascending order whereas there is a
@@ -71,51 +91,35 @@ module TTFunk
71
91
  end
72
92
 
73
93
  def glyf_table
74
- @glyf_table ||= TTFunk::Table::Glyf.encode(
75
- glyphs, new_to_old_glyph, old_to_new_glyph
76
- )
94
+ @glyf_table ||= TTFunk::Table::Glyf.encode(glyphs, new_to_old_glyph, old_to_new_glyph)
77
95
  end
78
96
 
79
97
  def loca_table
80
- @loca_table ||= TTFunk::Table::Loca.encode(
81
- glyf_table[:offsets]
82
- )
98
+ @loca_table ||= TTFunk::Table::Loca.encode(glyf_table[:offsets])
83
99
  end
84
100
 
85
101
  def hmtx_table
86
- @hmtx_table ||= TTFunk::Table::Hmtx.encode(
87
- original.horizontal_metrics, new_to_old_glyph
88
- )
102
+ @hmtx_table ||= TTFunk::Table::Hmtx.encode(original.horizontal_metrics, new_to_old_glyph)
89
103
  end
90
104
 
91
105
  def hhea_table
92
- @hhea_table = TTFunk::Table::Hhea.encode(
93
- original.horizontal_header, hmtx_table, original, new_to_old_glyph
94
- )
106
+ @hhea_table = TTFunk::Table::Hhea.encode(original.horizontal_header, hmtx_table, original, new_to_old_glyph)
95
107
  end
96
108
 
97
109
  def maxp_table
98
- @maxp_table ||= TTFunk::Table::Maxp.encode(
99
- original.maximum_profile, old_to_new_glyph
100
- )
110
+ @maxp_table ||= TTFunk::Table::Maxp.encode(original.maximum_profile, old_to_new_glyph)
101
111
  end
102
112
 
103
113
  def post_table
104
- @post_table ||= TTFunk::Table::Post.encode(
105
- original.postscript, new_to_old_glyph
106
- )
114
+ @post_table ||= TTFunk::Table::Post.encode(original.postscript, new_to_old_glyph)
107
115
  end
108
116
 
109
117
  def name_table
110
- @name_table ||= TTFunk::Table::Name.encode(
111
- original.name, glyf_table.fetch(:table, '')
112
- )
118
+ @name_table ||= TTFunk::Table::Name.encode(original.name, glyf_table.fetch(:table, ''))
113
119
  end
114
120
 
115
121
  def head_table
116
- @head_table ||= TTFunk::Table::Head.encode(
117
- original.header, loca_table, new_to_old_glyph
118
- )
122
+ @head_table ||= TTFunk::Table::Head.encode(original.header, loca_table, new_to_old_glyph)
119
123
  end
120
124
 
121
125
  # "optional" tables. Fonts may omit these if they do not need them.
@@ -149,22 +153,16 @@ module TTFunk
149
153
  # generated subfont may need a kerning table... in that case, you need
150
154
  # to opt into it.
151
155
  if options[:kerning]
152
- @kern_table ||= TTFunk::Table::Kern.encode(
153
- original.kerning, old_to_new_glyph
154
- )
156
+ @kern_table ||= TTFunk::Table::Kern.encode(original.kerning, old_to_new_glyph)
155
157
  end
156
158
  end
157
159
 
158
160
  def vorg_table
159
- @vorg_table ||= TTFunk::Table::Vorg.encode(
160
- original.vertical_origins
161
- )
161
+ @vorg_table ||= TTFunk::Table::Vorg.encode(original.vertical_origins)
162
162
  end
163
163
 
164
164
  def dsig_table
165
- @dsig_table ||= TTFunk::Table::Dsig.encode(
166
- original.digital_signature
167
- )
165
+ @dsig_table ||= TTFunk::Table::Dsig.encode(original.digital_signature)
168
166
  end
169
167
 
170
168
  def tables
@@ -185,7 +183,7 @@ module TTFunk
185
183
  'cvt ' => cvt_table,
186
184
  'VORG' => vorg_table,
187
185
  'DSIG' => dsig_table,
188
- 'gasp' => gasp_table
186
+ 'gasp' => gasp_table,
189
187
  }.compact
190
188
  end
191
189
 
@@ -211,7 +209,7 @@ module TTFunk
211
209
 
212
210
  def align(data, width)
213
211
  if (data.length % width).positive?
214
- data + "\0" * (width - data.length % width)
212
+ data + ("\0" * (width - (data.length % width)))
215
213
  else
216
214
  data
217
215
  end
data/lib/ttfunk.rb CHANGED
@@ -20,25 +20,81 @@ require_relative 'ttfunk/max'
20
20
  require_relative 'ttfunk/sum'
21
21
  require_relative 'ttfunk/one_based_array'
22
22
 
23
+ # TTFunk is a TrueType and OpenType font library written in pure ruby. It
24
+ # supports both parsing and encoding of fonts. Also provides limited font
25
+ # subsetting.
26
+ #
27
+ # It supports a veriety of SFNT-based formats:
28
+ # * TrueType fonts (ttf)
29
+ # * OpenType fonts (otf), with both TrueType and CFF glyph outlines
30
+ # * DFont resources (dfont)
31
+ # * TrueType Collections (ttc)
32
+ #
33
+ # While not all TrueType and OpenType tables are implemented the most common
34
+ # ones are.
23
35
  module TTFunk
36
+ # TTFunk-specific exceptions
24
37
  class Error < StandardError; end
25
38
 
39
+ # File represents an individual font. It can represents both TrueType and
40
+ # OpenType fonts.
26
41
  class File
42
+ # Raw content of the font.
43
+ # @return [String]
27
44
  attr_reader :contents
45
+
46
+ # Font tables directory.
47
+ # @return [TTFunk::Directory]
28
48
  attr_reader :directory
29
49
 
50
+ # Open font file
51
+ #
52
+ # @overload open(io)
53
+ # @param io [IO] IO to read font content from. IO position and binmode
54
+ # might change.
55
+ # @return [TTFunk::File]
56
+ # @overload open(path)
57
+ # @param path [String, Pathname] Path to file to read the font from.
58
+ # @return [TTFunk::File]
30
59
  def self.open(io_or_path)
31
- new verify_and_open(io_or_path).read
60
+ new(verify_and_read(io_or_path))
32
61
  end
33
62
 
63
+ # Load a font from a resource file.
64
+ #
65
+ # @param file [String, Pathname] Path to the resource file.
66
+ # @param which [Integer, String] index or name of the font to load
67
+ # @return [TTFunk::File]]
34
68
  def self.from_dfont(file, which = 0)
35
69
  new(ResourceFile.open(file) { |dfont| dfont['sfnt', which] })
36
70
  end
37
71
 
72
+ # Load a font from a TrueType collection.
73
+ #
74
+ # @overload from_ttc(io, which = 0)
75
+ # @param file [IO] IO to read the collection from.
76
+ # @param which [Integer] index of the font to load
77
+ # @return [TTFunk::File]
78
+ # @overload from_ttc(file_path, which = 0)
79
+ # @param file_path [String, Pathname] Path to the resource file.
80
+ # @param which [Integer] index of the font to load
81
+ # @return [TTFunk::File]
38
82
  def self.from_ttc(file, which = 0)
39
83
  Collection.open(file) { |ttc| ttc[which] }
40
84
  end
41
85
 
86
+ # Turn a path or IO into an IO convenient for TTFunk. The resulting IO is
87
+ # going to be in bin mode and its position set to the beginning.
88
+ #
89
+ # @overload verify_and_open(io)
90
+ # @param io [IO] IO to prepare. Its position and binmode might
91
+ # change.
92
+ # @return [io]
93
+ # @overload verify_and_open(path)
94
+ # @param path [String, Pathname] path of the file to turn into an IO.
95
+ # @return [IO] newly opened IO for the path
96
+ # @deprecated This method might retain open files for longer than necessary.
97
+ # @see .verify_and_read
42
98
  def self.verify_and_open(io_or_path)
43
99
  # File or IO
44
100
  if io_or_path.respond_to?(:rewind)
@@ -58,86 +114,175 @@ module TTFunk
58
114
  io_or_path.open('rb')
59
115
  end
60
116
 
117
+ # Read contents of a path or IO.
118
+ #
119
+ # @overload verify_and_read(io)
120
+ # @param io [IO] IO to read from. Its position and binmode might
121
+ # change. IO is read from the beginning regardless of its initial
122
+ # position.
123
+ # @return [String]
124
+ # @overload verify_and_read(path)
125
+ # @param path [String, Pathname] path of the file to read.
126
+ # @return [String]
127
+ def self.verify_and_read(io_or_path)
128
+ # File or IO
129
+ if io_or_path.respond_to?(:rewind)
130
+ io = io_or_path
131
+ # Rewind if the object we're passed is an IO, so that multiple embeds of
132
+ # the same IO object will work
133
+ io.rewind
134
+ # read the file as binary so the size is calculated correctly
135
+ # guard binmode because some objects acting io-like don't implement it
136
+ io.binmode if io.respond_to?(:binmode)
137
+ return io.read
138
+ end
139
+ # String or Pathname
140
+ io_or_path = Pathname.new(io_or_path)
141
+ raise ArgumentError, "#{io_or_path} not found" unless io_or_path.file?
142
+
143
+ io_or_path.binread
144
+ end
145
+
146
+ # @param contents [String] binary string containg the font data
147
+ # @param offset [Integer] offset at which the font data starts
61
148
  def initialize(contents, offset = 0)
62
149
  @contents = StringIO.new(contents)
63
150
  @directory = Directory.new(@contents, offset)
64
151
  end
65
152
 
153
+ # Glyphs ascent as defined for in the font.
154
+ #
155
+ # @return [Integer]
66
156
  def ascent
67
157
  @ascent ||= (os2.exists? && os2.ascent && os2.ascent.nonzero?) ||
68
158
  horizontal_header.ascent
69
159
  end
70
160
 
161
+ # Glyphs descent as defined in the font.
162
+ #
163
+ # @return [Integer]
71
164
  def descent
72
165
  @descent ||= (os2.exists? && os2.descent && os2.descent.nonzero?) ||
73
166
  horizontal_header.descent
74
167
  end
75
168
 
169
+ # Line gap as defined in the font.
170
+ #
171
+ # @return [Integer]
76
172
  def line_gap
77
173
  @line_gap ||= (os2.exists? && os2.line_gap && os2.line_gap.nonzero?) ||
78
174
  horizontal_header.line_gap
79
175
  end
80
176
 
177
+ # Glyps bounding box as defined in the font.
178
+ #
179
+ # @return [Array(Integer, Integer, Integer, Integer)]
81
180
  def bbox
82
181
  [header.x_min, header.y_min, header.x_max, header.y_max]
83
182
  end
84
183
 
184
+ # Font directory entry for the table with the provided tag.
185
+ #
186
+ # @param tag [String] table tab
187
+ # @return [Hash, nil]
85
188
  def directory_info(tag)
86
189
  directory.tables[tag.to_s]
87
190
  end
88
191
 
192
+ # Font Header (`head`) table
193
+ #
194
+ # @return [TTFunk::Table::Head, nil]
89
195
  def header
90
196
  @header ||= TTFunk::Table::Head.new(self)
91
197
  end
92
198
 
199
+ # Character to Glyph Index Mapping (`cmap`) table
200
+ #
201
+ # @return [TTFunk::Tbale::Cmap, nil]
93
202
  def cmap
94
203
  @cmap ||= TTFunk::Table::Cmap.new(self)
95
204
  end
96
205
 
206
+ # Horizontal Header (`hhea`) table
207
+ #
208
+ # @return [TTFunk::Table::Hhea, nil]
97
209
  def horizontal_header
98
210
  @horizontal_header ||= TTFunk::Table::Hhea.new(self)
99
211
  end
100
212
 
213
+ # Horizontal Metrics (`hmtx`) table
214
+ #
215
+ # @return [TTFunk::Table::Hmtx, nil]
101
216
  def horizontal_metrics
102
217
  @horizontal_metrics ||= TTFunk::Table::Hmtx.new(self)
103
218
  end
104
219
 
220
+ # Maximum Profile (`maxp`) table
221
+ #
222
+ # @return [TTFunk::Table::Maxp, nil]
105
223
  def maximum_profile
106
224
  @maximum_profile ||= TTFunk::Table::Maxp.new(self)
107
225
  end
108
226
 
227
+ # Kerning (`kern`) table
228
+ #
229
+ # @return [TTFunk::Table::Kern, nil]
109
230
  def kerning
110
231
  @kerning ||= TTFunk::Table::Kern.new(self)
111
232
  end
112
233
 
234
+ # Naming (`name`) table
235
+ #
236
+ # @return [TTFunk::Table::Name, nil]
113
237
  def name
114
238
  @name ||= TTFunk::Table::Name.new(self)
115
239
  end
116
240
 
241
+ # OS/2 and Windows Metrics (`OS/2`) table
242
+ #
243
+ # @return [TTFunk::Table:OS2, nil]
117
244
  def os2
118
245
  @os2 ||= TTFunk::Table::OS2.new(self)
119
246
  end
120
247
 
248
+ # PostScript (`post`) table
249
+ #
250
+ # @return [TTFunk::Table::Post, nil]
121
251
  def postscript
122
252
  @postscript ||= TTFunk::Table::Post.new(self)
123
253
  end
124
254
 
255
+ # Index to Location (`loca`) table
256
+ #
257
+ # @return [TTFunk::Table::Loca, nil]
125
258
  def glyph_locations
126
259
  @glyph_locations ||= TTFunk::Table::Loca.new(self)
127
260
  end
128
261
 
262
+ # Glyph Data (`glyf`) table
263
+ #
264
+ # @return [TTFunk::Table::Glyf, nil]
129
265
  def glyph_outlines
130
266
  @glyph_outlines ||= TTFunk::Table::Glyf.new(self)
131
267
  end
132
268
 
269
+ # Standard Bitmap Graphics (`sbix`) table
270
+ #
271
+ # @return [TTFunk::Table::Sbix, nil]
133
272
  def sbix
134
273
  @sbix ||= TTFunk::Table::Sbix.new(self)
135
274
  end
136
275
 
276
+ # Compact Font Format (`CFF `) table
277
+ #
278
+ # @return [Table::Table::Cff, nil]
137
279
  def cff
138
280
  @cff ||= TTFunk::Table::Cff.new(self)
139
281
  end
140
282
 
283
+ # Vertical Origin (`VORG`) table
284
+ #
285
+ # @return [TTFunk::Table::Vorg, nil]
141
286
  def vertical_origins
142
287
  @vertical_origins ||=
143
288
  if directory.tables.include?(TTFunk::Table::Vorg::TAG)
@@ -145,6 +290,9 @@ module TTFunk
145
290
  end
146
291
  end
147
292
 
293
+ # Digital Signature (`DSIG`) table
294
+ #
295
+ # @return [TTFunk::Table::Dsig, nil]
148
296
  def digital_signature
149
297
  @digital_signature ||=
150
298
  if directory.tables.include?(TTFunk::Table::Dsig::TAG)
@@ -152,6 +300,11 @@ module TTFunk
152
300
  end
153
301
  end
154
302
 
303
+ # Find glyph by its index.
304
+ #
305
+ # @return [TTFunk::Table::Cff::Charstring] if it's a CFF-based OpenType font
306
+ # @return [TTFunk::Table::Glyf::Simple, TTFunk::Table::Glyf::Compound]
307
+ # if it's a TrueType font
155
308
  def find_glyph(glyph_id)
156
309
  if cff.exists?
157
310
  cff.top_index[0].charstrings_index[glyph_id].glyph
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,9 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ttfunk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0
4
+ version: 1.8.0
5
5
  platform: ruby
6
6
  authors:
7
+ - Alexander Mankuta
7
8
  - Gregory Brown
8
9
  - Brad Ediger
9
10
  - Daniel Nelson
@@ -15,43 +16,58 @@ bindir: bin
15
16
  cert_chain:
16
17
  - |
17
18
  -----BEGIN CERTIFICATE-----
18
- MIIDODCCAiCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhhbGV4
19
- L0RDPXBvaW50bGVzcy9EQz1vbmUwHhcNMjAwODAxMTQxMjE1WhcNMjEwODAxMTQx
20
- MjE1WjAjMSEwHwYDVQQDDBhhbGV4L0RDPXBvaW50bGVzcy9EQz1vbmUwggEiMA0G
21
- CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPOVLPGEK+eaP6zJfifrpWvPTg4qo3
22
- XNJJPom80SwqX2hVCVsRDK4RYgKUQqKRQzHhlx14wZHwWLETBVbNDGX3uqyCnTWU
23
- JUKh3ydiZShXpNHoV/NW7hhEYvNsDcBAjYTmbvXOhuYCo0Tz/0N2Oiun/0wIICtP
24
- vytY9TY0/lklWjAbsqJjNOu3o8IYkJBAN/rU96E/6WhFwjnxLcTnV9RfFRXdjG5j
25
- CughoB2xSwKX8gwbQ8fsnaZRmdyDGYNpz6sGF0zycfiLkTttbLA2nYATCALy98CH
26
- nsyZNsTjb4WINCuY2yEDjwesw9f/ROkNC68EgQ5M+aMjp+D0WcYGfzojAgMBAAGj
27
- dzB1MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBRPgIwSVbeonua/
28
- Ny/8576oxdUbrjAdBgNVHREEFjAUgRJhbGV4QHBvaW50bGVzcy5vbmUwHQYDVR0S
29
- BBYwFIESYWxleEBwb2ludGxlc3Mub25lMA0GCSqGSIb3DQEBCwUAA4IBAQAzhGxF
30
- M0bXJ9GWD9vdVHOyzBQBJcJAvnsz2yV3+r4eJBsQynFIscsea8lHFL/d1eHYP0mN
31
- k0fhK+WDcPlrj0Sn/Ezhk2qogTIekwDOK6pZkGRQzD45leJqQMnYd+/TXK3ri485
32
- Gi4oJ6NitnnUT59SQnjD5JcENfc0EcRzclmVRFE8W4O+ORgo4Dypq1rwYUzxeyUk
33
- mP5jNBWtH+hGUph28GQb0Hph6YnQb8zEFB88Xq80PK1SzkIPHpbTBk9mwPf6ypeX
34
- Un1TJEahAlgENVml6CyDXSwk0H8N1V3gm1mb9Fe1T2Z/kAzvjo0qTDEtMVLU7Bxh
35
- uqMUrdETjTnRYCVq
19
+ MIIDMjCCAhqgAwIBAgIBAzANBgkqhkiG9w0BAQsFADA/MQ0wCwYDVQQDDARhbGV4
20
+ MRkwFwYKCZImiZPyLGQBGRYJcG9pbnRsZXNzMRMwEQYKCZImiZPyLGQBGRYDb25l
21
+ MB4XDTI0MDMwNDIwMTIyOFoXDTI1MDMwNDIwMTIyOFowPzENMAsGA1UEAwwEYWxl
22
+ eDEZMBcGCgmSJomT8ixkARkWCXBvaW50bGVzczETMBEGCgmSJomT8ixkARkWA29u
23
+ ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM85Us8YQr55o/rMl+J+
24
+ ula89ODiqjdc0kk+ibzRLCpfaFUJWxEMrhFiApRCopFDMeGXHXjBkfBYsRMFVs0M
25
+ Zfe6rIKdNZQlQqHfJ2JlKFek0ehX81buGERi82wNwECNhOZu9c6G5gKjRPP/Q3Y6
26
+ K6f/TAggK0+/K1j1NjT+WSVaMBuyomM067ejwhiQkEA3+tT3oT/paEXCOfEtxOdX
27
+ 1F8VFd2MbmMK6CGgHbFLApfyDBtDx+ydplGZ3IMZg2nPqwYXTPJx+IuRO21ssDad
28
+ gBMIAvL3wIeezJk2xONvhYg0K5jbIQOPB6zD1/9E6Q0LrwSBDkz5oyOn4PRZxgZ/
29
+ OiMCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFE+A
30
+ jBJVt6ie5r83L/znvqjF1RuuMA0GCSqGSIb3DQEBCwUAA4IBAQAam5ZgizC0Pknb
31
+ nm7O8fY6+0rdvIP9Zhzbigvfjy664xyZYJ2hJLnvN64wKewcYeYIrC/OEOVbkjWl
32
+ YUDqUfy59JAYvJNQJDi2ZbJPji17WlQaz/x/0QlwWnsYIjOBw0Jyi5Hv41pkMAcO
33
+ +YgdSby0qLIu8sNoTP4YXxRyBuHNBgAUexf3x+dvMyHuM+Q/lKiKmJLwzUlcYr0F
34
+ luk6Jow2lBzuzfjss07L5THk162mtlWVIdtbLsAvcxwTwVZ7W0bKQkyJnTj8gnye
35
+ +ucJ3nnxbYV+GcYHgWdTMu39wjP8z+w+PYLBxpaVjThblqhDQpmIjT4zJvAQALi9
36
+ auxR4ast
36
37
  -----END CERTIFICATE-----
37
- date: 2020-12-29 00:00:00.000000000 Z
38
+ date: 2024-03-04 00:00:00.000000000 Z
38
39
  dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: bigdecimal
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '3.1'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '3.1'
39
54
  - !ruby/object:Gem::Dependency
40
55
  name: prawn-dev
41
56
  requirement: !ruby/object:Gem::Requirement
42
57
  requirements:
43
58
  - - "~>"
44
59
  - !ruby/object:Gem::Version
45
- version: 0.1.0
60
+ version: 0.4.0
46
61
  type: :development
47
62
  prerelease: false
48
63
  version_requirements: !ruby/object:Gem::Requirement
49
64
  requirements:
50
65
  - - "~>"
51
66
  - !ruby/object:Gem::Version
52
- version: 0.1.0
67
+ version: 0.4.0
53
68
  description: Font Metrics Parser for the Prawn PDF generator
54
69
  email:
70
+ - alex@pointless.one
55
71
  - gregory.t.brown@gmail.com
56
72
  - brad@bradediger.com
57
73
  - dnelson@bluejade.com
@@ -149,12 +165,18 @@ files:
149
165
  - lib/ttfunk/table/simple.rb
150
166
  - lib/ttfunk/table/vorg.rb
151
167
  - lib/ttfunk/ttf_encoder.rb
152
- homepage: https://prawnpdf.org
168
+ homepage: http://prawnpdf.org/
153
169
  licenses:
154
170
  - Nonstandard
155
- - GPL-2.0
156
- - GPL-3.0
157
- metadata: {}
171
+ - GPL-2.0-only
172
+ - GPL-3.0-only
173
+ metadata:
174
+ rubygems_mfa_required: 'true'
175
+ homepage_uri: http://prawnpdf.org/
176
+ changelog_uri: https://github.com/prawnpdf/ttfunk/blob/1.8.0/CHANGELOG.md
177
+ source_code_uri: https://github.com/prawnpdf/ttfunk
178
+ documentation_uri: https://prwnpdf.org/docs/ttfunk/1.8.0/
179
+ bug_tracker_uri: https://github.com/prawnpdf/ttfunk/issues
158
180
  post_install_message:
159
181
  rdoc_options: []
160
182
  require_paths:
@@ -163,14 +185,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
163
185
  requirements:
164
186
  - - ">="
165
187
  - !ruby/object:Gem::Version
166
- version: '2.5'
188
+ version: '2.7'
167
189
  required_rubygems_version: !ruby/object:Gem::Requirement
168
190
  requirements:
169
191
  - - ">="
170
192
  - !ruby/object:Gem::Version
171
193
  version: '0'
172
194
  requirements: []
173
- rubygems_version: 3.2.3
195
+ rubygems_version: 3.5.3
174
196
  signing_key:
175
197
  specification_version: 4
176
198
  summary: TrueType Font Metrics Parser
metadata.gz.sig CHANGED
Binary file