ttfunk 1.7.0 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +74 -0
- data/README.md +17 -15
- data/lib/ttfunk/aggregate.rb +5 -0
- data/lib/ttfunk/bin_utils.rb +27 -8
- data/lib/ttfunk/bit_field.rb +25 -2
- data/lib/ttfunk/collection.rb +27 -3
- data/lib/ttfunk/directory.rb +7 -1
- data/lib/ttfunk/encoded_string.rb +58 -4
- data/lib/ttfunk/max.rb +14 -0
- data/lib/ttfunk/min.rb +14 -0
- data/lib/ttfunk/one_based_array.rb +20 -0
- data/lib/ttfunk/otf_encoder.rb +5 -14
- data/lib/ttfunk/placeholder.rb +15 -1
- data/lib/ttfunk/reader.rb +6 -4
- data/lib/ttfunk/resource_file.rb +29 -5
- data/lib/ttfunk/sci_form.rb +20 -3
- data/lib/ttfunk/sub_table.rb +29 -4
- data/lib/ttfunk/subset/base.rb +48 -0
- data/lib/ttfunk/subset/code_page.rb +49 -2
- data/lib/ttfunk/subset/mac_roman.rb +2 -0
- data/lib/ttfunk/subset/unicode.rb +32 -0
- data/lib/ttfunk/subset/unicode_8bit.rb +32 -0
- data/lib/ttfunk/subset/windows_1252.rb +2 -0
- data/lib/ttfunk/subset.rb +8 -0
- data/lib/ttfunk/subset_collection.rb +39 -14
- data/lib/ttfunk/sum.rb +13 -0
- data/lib/ttfunk/table/cff/charset.rb +96 -18
- data/lib/ttfunk/table/cff/charsets/expert.rb +3 -2
- data/lib/ttfunk/table/cff/charsets/expert_subset.rb +3 -2
- data/lib/ttfunk/table/cff/charsets/iso_adobe.rb +3 -2
- data/lib/ttfunk/table/cff/charsets/standard_strings.rb +3 -2
- data/lib/ttfunk/table/cff/charsets.rb +1 -0
- data/lib/ttfunk/table/cff/charstring.rb +33 -12
- data/lib/ttfunk/table/cff/charstrings_index.rb +17 -11
- data/lib/ttfunk/table/cff/dict.rb +53 -23
- data/lib/ttfunk/table/cff/encoding.rb +82 -24
- data/lib/ttfunk/table/cff/encodings/expert.rb +3 -2
- data/lib/ttfunk/table/cff/encodings/standard.rb +3 -2
- data/lib/ttfunk/table/cff/encodings.rb +1 -0
- data/lib/ttfunk/table/cff/fd_selector.rb +61 -21
- data/lib/ttfunk/table/cff/font_dict.rb +30 -18
- data/lib/ttfunk/table/cff/font_index.rb +22 -10
- data/lib/ttfunk/table/cff/header.rb +16 -3
- data/lib/ttfunk/table/cff/index.rb +97 -65
- data/lib/ttfunk/table/cff/one_based_index.rb +11 -1
- data/lib/ttfunk/table/cff/path.rb +43 -4
- data/lib/ttfunk/table/cff/private_dict.rb +31 -11
- data/lib/ttfunk/table/cff/subr_index.rb +7 -2
- data/lib/ttfunk/table/cff/top_dict.rb +82 -59
- data/lib/ttfunk/table/cff/top_index.rb +10 -6
- data/lib/ttfunk/table/cff.rb +41 -21
- data/lib/ttfunk/table/cmap/format00.rb +27 -6
- data/lib/ttfunk/table/cmap/format04.rb +34 -14
- data/lib/ttfunk/table/cmap/format06.rb +28 -1
- data/lib/ttfunk/table/cmap/format10.rb +29 -2
- data/lib/ttfunk/table/cmap/format12.rb +29 -2
- data/lib/ttfunk/table/cmap/subtable.rb +50 -6
- data/lib/ttfunk/table/cmap.rb +21 -0
- data/lib/ttfunk/table/dsig.rb +47 -6
- data/lib/ttfunk/table/glyf/compound.rb +73 -6
- data/lib/ttfunk/table/glyf/path_based.rb +40 -3
- data/lib/ttfunk/table/glyf/simple.rb +50 -5
- data/lib/ttfunk/table/glyf.rb +15 -7
- data/lib/ttfunk/table/head.rb +84 -6
- data/lib/ttfunk/table/hhea.rb +71 -10
- data/lib/ttfunk/table/hmtx.rb +32 -5
- data/lib/ttfunk/table/kern/format0.rb +25 -7
- data/lib/ttfunk/table/kern.rb +16 -4
- data/lib/ttfunk/table/loca.rb +21 -8
- data/lib/ttfunk/table/maxp.rb +195 -10
- data/lib/ttfunk/table/name.rb +126 -9
- data/lib/ttfunk/table/os2.rb +150 -26
- data/lib/ttfunk/table/post/format10.rb +7 -0
- data/lib/ttfunk/table/post/format20.rb +9 -0
- data/lib/ttfunk/table/post/format30.rb +6 -0
- data/lib/ttfunk/table/post/format40.rb +5 -0
- data/lib/ttfunk/table/post.rb +63 -7
- data/lib/ttfunk/table/sbix.rb +50 -14
- data/lib/ttfunk/table/simple.rb +5 -0
- data/lib/ttfunk/table/vorg.rb +31 -3
- data/lib/ttfunk/table.rb +20 -1
- data/lib/ttfunk/ttf_encoder.rb +39 -41
- data/lib/ttfunk.rb +154 -1
- data.tar.gz.sig +0 -0
- metadata +50 -28
- metadata.gz.sig +0 -0
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
|