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
data/lib/ttfunk/table/vorg.rb
CHANGED
@@ -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
|
-
|
11
|
-
|
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(
|
58
|
+
self.class.name.split('::').last.downcase
|
40
59
|
end
|
41
60
|
|
42
61
|
private
|
data/lib/ttfunk/ttf_encoder.rb
CHANGED
@@ -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
|
-
|
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)
|
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
|
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.
|
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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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:
|
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.
|
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.
|
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:
|
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.
|
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.
|
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
|