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/placeholder.rb
CHANGED
@@ -1,10 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TTFunk
|
4
|
+
# Encoded String placeholder.
|
5
|
+
#
|
6
|
+
# @api private
|
4
7
|
class Placeholder
|
8
|
+
# Placeholder position in the cintaining Encoded String
|
9
|
+
# @return [Integer]
|
5
10
|
attr_accessor :position
|
6
|
-
attr_reader :name, :length
|
7
11
|
|
12
|
+
# Planceholder name
|
13
|
+
# @return [Symbol]
|
14
|
+
attr_reader :name
|
15
|
+
|
16
|
+
# Length of the placeholder
|
17
|
+
# @return [Integer]
|
18
|
+
attr_reader :length
|
19
|
+
|
20
|
+
# @param name [Symbol]
|
21
|
+
# @param length [Integer]
|
8
22
|
def initialize(name, length: 1)
|
9
23
|
@name = name
|
10
24
|
@length = length
|
data/lib/ttfunk/reader.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TTFunk
|
4
|
+
# Helper methods to read form file content.
|
5
|
+
# @api rpivate
|
4
6
|
module Reader
|
5
7
|
private
|
6
8
|
|
@@ -23,7 +25,7 @@ module TTFunk
|
|
23
25
|
def parse_from(position)
|
24
26
|
saved = io.pos
|
25
27
|
io.pos = position
|
26
|
-
result = yield
|
28
|
+
result = yield(position)
|
27
29
|
io.pos = saved
|
28
30
|
result
|
29
31
|
end
|
@@ -36,12 +38,12 @@ module TTFunk
|
|
36
38
|
if ((i + 1) % 16).zero?
|
37
39
|
puts
|
38
40
|
elsif ((i + 1) % 8).zero?
|
39
|
-
print
|
41
|
+
print(' ')
|
40
42
|
else
|
41
|
-
print
|
43
|
+
print(' ')
|
42
44
|
end
|
43
45
|
end
|
44
|
-
puts
|
46
|
+
puts if (bytes.length % 16) != 0
|
45
47
|
end
|
46
48
|
end
|
47
49
|
end
|
data/lib/ttfunk/resource_file.rb
CHANGED
@@ -1,16 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TTFunk
|
4
|
+
# Data-fork suitcases resource file
|
4
5
|
class ResourceFile
|
6
|
+
# Resource map
|
7
|
+
#
|
8
|
+
# @return [Hash]
|
5
9
|
attr_reader :map
|
6
10
|
|
11
|
+
# Open a resource file
|
12
|
+
#
|
13
|
+
# @param path [String, Pathname]
|
14
|
+
# @yieldparam resource_file [TTFunk::ResourceFile]
|
15
|
+
# @return [any] result of the block
|
7
16
|
def self.open(path)
|
8
|
-
::File.open(path, 'rb')
|
17
|
+
::File.open(path, 'rb') { |io|
|
9
18
|
file = new(io)
|
10
|
-
yield
|
11
|
-
|
19
|
+
yield(file)
|
20
|
+
}
|
12
21
|
end
|
13
22
|
|
23
|
+
# @param io [IO]
|
14
24
|
def initialize(io)
|
15
25
|
@io = io
|
16
26
|
|
@@ -41,7 +51,7 @@ module TTFunk
|
|
41
51
|
id: id,
|
42
52
|
attributes: attr,
|
43
53
|
offset: data_ofs,
|
44
|
-
handle: handle
|
54
|
+
handle: handle,
|
45
55
|
}
|
46
56
|
|
47
57
|
if name_list_offset + name_ofs < map_offset + map_length
|
@@ -58,6 +68,16 @@ module TTFunk
|
|
58
68
|
end
|
59
69
|
end
|
60
70
|
|
71
|
+
# Get resource
|
72
|
+
#
|
73
|
+
# @overload [](type, index = 0)
|
74
|
+
# @param type [String]
|
75
|
+
# @param inxed [Integer]
|
76
|
+
# @return [String]
|
77
|
+
# @overload [](type, name)
|
78
|
+
# @param type [String]
|
79
|
+
# @param name [String]
|
80
|
+
# @return [String]
|
61
81
|
def [](type, index = 0)
|
62
82
|
if @map[type]
|
63
83
|
collection = index.is_a?(Integer) ? :list : :named
|
@@ -70,8 +90,12 @@ module TTFunk
|
|
70
90
|
end
|
71
91
|
end
|
72
92
|
|
93
|
+
# Get resource names
|
94
|
+
#
|
95
|
+
# @param type [String]
|
96
|
+
# @return [Array<String>]
|
73
97
|
def resources_for(type)
|
74
|
-
(@map[type] && @map[type][:named] || {}).keys
|
98
|
+
((@map[type] && @map[type][:named]) || {}).keys
|
75
99
|
end
|
76
100
|
|
77
101
|
private
|
data/lib/ttfunk/sci_form.rb
CHANGED
@@ -1,19 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TTFunk
|
4
|
+
# Scientific number representation
|
4
5
|
class SciForm
|
5
|
-
|
6
|
-
|
6
|
+
# Significand
|
7
|
+
# @return [Float, Integer]
|
8
|
+
attr_reader :significand
|
9
|
+
|
10
|
+
# Exponent
|
11
|
+
# @return [Float, Integer]
|
12
|
+
attr_reader :exponent
|
7
13
|
|
14
|
+
# @param significand [Float, Integer]
|
15
|
+
# @param exponent [Float, Integer]
|
8
16
|
def initialize(significand, exponent = 0)
|
9
17
|
@significand = significand
|
10
18
|
@exponent = exponent
|
11
19
|
end
|
12
20
|
|
21
|
+
# Convert to Float.
|
22
|
+
#
|
23
|
+
# @return [Float]
|
13
24
|
def to_f
|
14
|
-
significand * 10**exponent
|
25
|
+
significand * (10**exponent)
|
15
26
|
end
|
16
27
|
|
28
|
+
# Check equality to another number.
|
29
|
+
#
|
30
|
+
# @param other [Float, SciForm]
|
31
|
+
# @return [Boolean]
|
17
32
|
def ==(other)
|
18
33
|
case other
|
19
34
|
when Float
|
@@ -25,5 +40,7 @@ module TTFunk
|
|
25
40
|
false
|
26
41
|
end
|
27
42
|
end
|
43
|
+
|
44
|
+
alias eql? ==
|
28
45
|
end
|
29
46
|
end
|
data/lib/ttfunk/sub_table.rb
CHANGED
@@ -1,16 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative 'reader'
|
4
4
|
|
5
5
|
module TTFunk
|
6
|
+
# SFNT sub-table
|
6
7
|
class SubTable
|
8
|
+
# A read past sub-table end was attempted.
|
7
9
|
class EOTError < StandardError
|
8
10
|
end
|
9
11
|
|
10
12
|
include Reader
|
11
13
|
|
12
|
-
|
14
|
+
# File or IO this sub-table is in.
|
15
|
+
# @return [IO]
|
16
|
+
attr_reader :file
|
13
17
|
|
18
|
+
# This sub-table's offset from the file beginning.
|
19
|
+
# @return [Integer]
|
20
|
+
attr_reader :table_offset
|
21
|
+
|
22
|
+
# This sub-table's length in byes.
|
23
|
+
# @return [Integer, nil]
|
24
|
+
attr_reader :length
|
25
|
+
|
26
|
+
# @param file [IO]
|
27
|
+
# @param offset [Integer]
|
28
|
+
# @param length [Integer]
|
14
29
|
def initialize(file, offset, length = nil)
|
15
30
|
@file = file
|
16
31
|
@table_offset = offset
|
@@ -18,15 +33,25 @@ module TTFunk
|
|
18
33
|
parse_from(@table_offset) { parse! }
|
19
34
|
end
|
20
35
|
|
21
|
-
#
|
36
|
+
# End of sub-table?
|
37
|
+
#
|
38
|
+
# @return [Boolean]
|
22
39
|
def eot?
|
23
40
|
# if length isn't set yet there's no way to know if we're at the end of
|
24
|
-
# the table or not
|
41
|
+
# the sub-table or not
|
25
42
|
return false unless length
|
26
43
|
|
27
44
|
io.pos > table_offset + length
|
28
45
|
end
|
29
46
|
|
47
|
+
# Read a series of values.
|
48
|
+
#
|
49
|
+
# @overload read(bytes, format)
|
50
|
+
# @param bytes [Integer] number of bytes to read.
|
51
|
+
# @param format [String] format to parse the bytes.
|
52
|
+
# @return [Array]
|
53
|
+
# @raise [EOTError]
|
54
|
+
# @see # Ruby Packed data
|
30
55
|
def read(*args)
|
31
56
|
if eot?
|
32
57
|
raise EOTError, 'attempted to read past the end of the table'
|
data/lib/ttfunk/subset/base.rb
CHANGED
@@ -14,45 +14,87 @@ require_relative '../table/simple'
|
|
14
14
|
|
15
15
|
module TTFunk
|
16
16
|
module Subset
|
17
|
+
# Base subset.
|
18
|
+
#
|
19
|
+
# @api private
|
17
20
|
class Base
|
21
|
+
# Microsoft Platform ID
|
18
22
|
MICROSOFT_PLATFORM_ID = 3
|
23
|
+
|
24
|
+
# Symbol Encoding ID for Microsoft Platform
|
19
25
|
MS_SYMBOL_ENCODING_ID = 0
|
20
26
|
|
27
|
+
# Original font
|
28
|
+
#
|
29
|
+
# @return [TTFunk::File]
|
21
30
|
attr_reader :original
|
22
31
|
|
32
|
+
# @param original [TTFunk::File]
|
23
33
|
def initialize(original)
|
24
34
|
@original = original
|
25
35
|
end
|
26
36
|
|
37
|
+
# Is this Unicode-based subset?
|
38
|
+
#
|
39
|
+
# @return [Boolean]
|
27
40
|
def unicode?
|
28
41
|
false
|
29
42
|
end
|
30
43
|
|
44
|
+
# Does this subset use Microsoft Symbolic encoding?
|
45
|
+
#
|
46
|
+
# @return [Boolean]
|
31
47
|
def microsoft_symbol?
|
32
48
|
new_cmap_table[:platform_id] == MICROSOFT_PLATFORM_ID &&
|
33
49
|
new_cmap_table[:encoding_id] == MS_SYMBOL_ENCODING_ID
|
34
50
|
end
|
35
51
|
|
52
|
+
# Get a mapping from this subset to Unicode.
|
53
|
+
#
|
54
|
+
# @return [Hash{Integer => Integer}]
|
36
55
|
def to_unicode_map
|
37
56
|
{}
|
38
57
|
end
|
39
58
|
|
59
|
+
# Encode this subset into a binary font representation.
|
60
|
+
#
|
61
|
+
# @param options [Hash]
|
62
|
+
# @return [String]
|
40
63
|
def encode(options = {})
|
41
64
|
encoder_klass.new(original, self, options).encode
|
42
65
|
end
|
43
66
|
|
67
|
+
# Encoder class for this subset.
|
68
|
+
#
|
69
|
+
# @return [TTFunk::TTFEncoder, TTFunk::OTFEncoder]
|
44
70
|
def encoder_klass
|
45
71
|
original.cff.exists? ? OTFEncoder : TTFEncoder
|
46
72
|
end
|
47
73
|
|
74
|
+
# Get the first Unicode cmap from the original font.
|
75
|
+
#
|
76
|
+
# @return [TTFunk::Table::Cmap::Subtable]
|
48
77
|
def unicode_cmap
|
49
78
|
@unicode_cmap ||= @original.cmap.unicode.first
|
50
79
|
end
|
51
80
|
|
81
|
+
# Get glyphs in this subset.
|
82
|
+
#
|
83
|
+
# @return [Hash{Integer => TTFunk::Table::Glyf::Simple,
|
84
|
+
# TTFunk::Table::Glyf::Compound}] if original is a TrueType font
|
85
|
+
# @return [Hash{Integer => TTFunk::Table::Cff::Charstring] if original is
|
86
|
+
# a CFF-based OpenType font
|
52
87
|
def glyphs
|
53
88
|
@glyphs ||= collect_glyphs(original_glyph_ids)
|
54
89
|
end
|
55
90
|
|
91
|
+
# Get glyphs by their IDs in the original font.
|
92
|
+
#
|
93
|
+
# @param glyph_ids [Array<Integer>]
|
94
|
+
# @return [Hash{Integer => TTFunk::Table::Glyf::Simple,
|
95
|
+
# TTFunk::Table::Glyf::Compound>] if original is a TrueType font
|
96
|
+
# @return [Hash{Integer => TTFunk::Table::Cff::Charstring}] if original is
|
97
|
+
# a CFF-based OpenType font
|
56
98
|
def collect_glyphs(glyph_ids)
|
57
99
|
collected =
|
58
100
|
glyph_ids.each_with_object({}) do |id, h|
|
@@ -69,6 +111,9 @@ module TTFunk
|
|
69
111
|
collected
|
70
112
|
end
|
71
113
|
|
114
|
+
# Glyph ID mapping from the original font to this subset.
|
115
|
+
#
|
116
|
+
# @return [Hash{Integer => Integer}]
|
72
117
|
def old_to_new_glyph
|
73
118
|
@old_to_new_glyph ||=
|
74
119
|
begin
|
@@ -91,6 +136,9 @@ module TTFunk
|
|
91
136
|
end
|
92
137
|
end
|
93
138
|
|
139
|
+
# Glyph ID mapping from this subset to the original font.
|
140
|
+
#
|
141
|
+
# @return [Hash{Integer => Integer}]
|
94
142
|
def new_to_old_glyph
|
95
143
|
@new_to_old_glyph ||= old_to_new_glyph.invert
|
96
144
|
end
|
@@ -6,8 +6,13 @@ require_relative 'base'
|
|
6
6
|
|
7
7
|
module TTFunk
|
8
8
|
module Subset
|
9
|
+
# A subset that uses standard code page encoding.
|
9
10
|
class CodePage < Base
|
10
11
|
class << self
|
12
|
+
# Get a mapping from an encoding to Unicode
|
13
|
+
#
|
14
|
+
# @param encoding [Encoding, String, Symbol]
|
15
|
+
# @return [Hash{Integer => Integer}]
|
11
16
|
def unicode_mapping_for(encoding)
|
12
17
|
mapping_cache[encoding] ||=
|
13
18
|
(0..255).each_with_object({}) do |c, ret|
|
@@ -27,39 +32,74 @@ module TTFunk
|
|
27
32
|
end
|
28
33
|
end
|
29
34
|
|
30
|
-
|
35
|
+
# Code page used in this subset.
|
36
|
+
# This is used for proper `OS/2` table encoding.
|
37
|
+
# @return [Integer]
|
38
|
+
attr_reader :code_page
|
31
39
|
|
40
|
+
# Encoding used in this subset.
|
41
|
+
# @return [Encoding, String, Symbol]
|
42
|
+
attr_reader :encoding
|
43
|
+
|
44
|
+
# @param original [TTFunk::File]
|
45
|
+
# @param code_page [Integer]
|
46
|
+
# @param encoding [Encoding, String, Symbol]
|
32
47
|
def initialize(original, code_page, encoding)
|
33
48
|
super(original)
|
34
49
|
@code_page = code_page
|
35
50
|
@encoding = encoding
|
36
51
|
@subset = Array.new(256)
|
52
|
+
@from_unicode_cache = {}
|
37
53
|
use(space_char_code)
|
38
54
|
end
|
39
55
|
|
56
|
+
# Get a mapping from this subset to Unicode.
|
57
|
+
#
|
58
|
+
# @return [Hash]
|
40
59
|
def to_unicode_map
|
41
60
|
self.class.unicode_mapping_for(encoding)
|
61
|
+
.select { |codepoint, _unicode| @subset[codepoint] }
|
42
62
|
end
|
43
63
|
|
64
|
+
# Add a character to subset.
|
65
|
+
#
|
66
|
+
# @param character [Integer] Unicode codepoint
|
67
|
+
# @return [void]
|
44
68
|
def use(character)
|
45
69
|
@subset[from_unicode(character)] = character
|
46
70
|
end
|
47
71
|
|
72
|
+
# Can this subset include the character? This depends on the encoding used
|
73
|
+
# in this subset.
|
74
|
+
#
|
75
|
+
# @param character [Integer] Unicode codepoint
|
76
|
+
# @return [Boolean]
|
48
77
|
def covers?(character)
|
49
78
|
!from_unicode(character).nil?
|
50
79
|
end
|
51
80
|
|
81
|
+
# Does this subset actually has the character?
|
82
|
+
#
|
83
|
+
# @param character [Integer] Unicode codepoint
|
84
|
+
# @return [Boolean]
|
52
85
|
def includes?(character)
|
53
86
|
code = from_unicode(character)
|
54
87
|
code && @subset[code]
|
55
88
|
end
|
56
89
|
|
90
|
+
# Get character code for Unicode codepoint.
|
91
|
+
#
|
92
|
+
# @param character [Integer] Unicode codepoint
|
93
|
+
# @return [Integer, nil]
|
57
94
|
def from_unicode(character)
|
58
|
-
[character]
|
95
|
+
@from_unicode_cache[character] ||= (+'' << character).encode!(encoding).ord
|
59
96
|
rescue Encoding::UndefinedConversionError
|
60
97
|
nil
|
61
98
|
end
|
62
99
|
|
100
|
+
# Get `cmap` table for this subset.
|
101
|
+
#
|
102
|
+
# @return [TTFunk::Table::Cmap]
|
63
103
|
def new_cmap_table
|
64
104
|
@new_cmap_table ||=
|
65
105
|
begin
|
@@ -73,11 +113,18 @@ module TTFunk
|
|
73
113
|
end
|
74
114
|
end
|
75
115
|
|
116
|
+
# Get the list of Glyph IDs from the original font that are in this
|
117
|
+
# subset.
|
118
|
+
#
|
119
|
+
# @return [Array<Integer>]
|
76
120
|
def original_glyph_ids
|
77
121
|
([0] + @subset.map { |unicode| unicode && unicode_cmap[unicode] })
|
78
122
|
.compact.uniq.sort
|
79
123
|
end
|
80
124
|
|
125
|
+
# Get a chacter code for Space in this subset
|
126
|
+
#
|
127
|
+
# @return [Integer, nil]
|
81
128
|
def space_char_code
|
82
129
|
@space_char_code ||= from_unicode(Unicode::SPACE_CHAR)
|
83
130
|
end
|
@@ -6,7 +6,9 @@ require_relative 'code_page'
|
|
6
6
|
|
7
7
|
module TTFunk
|
8
8
|
module Subset
|
9
|
+
# Mac Roman subset. It uses code page 10,000 and Mac OS Roman encoding.
|
9
10
|
class MacRoman < CodePage
|
11
|
+
# @param original [TTFunk::File]
|
10
12
|
def initialize(original)
|
11
13
|
super(original, 10_000, Encoding::MACROMAN)
|
12
14
|
end
|
@@ -5,39 +5,67 @@ require_relative 'base'
|
|
5
5
|
|
6
6
|
module TTFunk
|
7
7
|
module Subset
|
8
|
+
# Unicode-based subset.
|
8
9
|
class Unicode < Base
|
10
|
+
# Space character code
|
9
11
|
SPACE_CHAR = 0x20
|
10
12
|
|
13
|
+
# @param original [TTFunk::File]
|
11
14
|
def initialize(original)
|
12
15
|
super
|
13
16
|
@subset = Set.new
|
14
17
|
use(SPACE_CHAR)
|
15
18
|
end
|
16
19
|
|
20
|
+
# Is this a Unicode-based subset?
|
21
|
+
#
|
22
|
+
# @return [true]
|
17
23
|
def unicode?
|
18
24
|
true
|
19
25
|
end
|
20
26
|
|
27
|
+
# Get a mapping from this subset to Unicode.
|
28
|
+
#
|
29
|
+
# @return [Hash{Integer => Integer}]
|
21
30
|
def to_unicode_map
|
22
31
|
@subset.each_with_object({}) { |code, map| map[code] = code }
|
23
32
|
end
|
24
33
|
|
34
|
+
# Add a character to subset.
|
35
|
+
#
|
36
|
+
# @param character [Integer] Unicode codepoint
|
37
|
+
# @return [void]
|
25
38
|
def use(character)
|
26
39
|
@subset << character
|
27
40
|
end
|
28
41
|
|
42
|
+
# Can this subset include the character?
|
43
|
+
#
|
44
|
+
# @param _character [Integer] Unicode codepoint
|
45
|
+
# @return [true]
|
29
46
|
def covers?(_character)
|
30
47
|
true
|
31
48
|
end
|
32
49
|
|
50
|
+
# Does this subset actually has the character?
|
51
|
+
#
|
52
|
+
# @param character [Integer] Unicode codepoint
|
53
|
+
# @return [Boolean]
|
33
54
|
def includes?(character)
|
34
55
|
@subset.include?(character)
|
35
56
|
end
|
36
57
|
|
58
|
+
# Get character code for Unicode codepoint.
|
59
|
+
#
|
60
|
+
# @param character [Integer] Unicode codepoint
|
61
|
+
# @return [Integer]
|
37
62
|
def from_unicode(character)
|
38
63
|
character
|
39
64
|
end
|
40
65
|
|
66
|
+
# Get `cmap` table for this subset.
|
67
|
+
#
|
68
|
+
# @return [TTFunk::Table::Cmap]
|
41
69
|
def new_cmap_table
|
42
70
|
@new_cmap_table ||=
|
43
71
|
begin
|
@@ -50,6 +78,10 @@ module TTFunk
|
|
50
78
|
end
|
51
79
|
end
|
52
80
|
|
81
|
+
# Get the list of Glyph IDs from the original font that are in this
|
82
|
+
# subset.
|
83
|
+
#
|
84
|
+
# @return [Array<Integer>]
|
53
85
|
def original_glyph_ids
|
54
86
|
([0] + @subset.map { |code| unicode_cmap[code] }).uniq.sort
|
55
87
|
end
|
@@ -5,7 +5,10 @@ require_relative 'base'
|
|
5
5
|
|
6
6
|
module TTFunk
|
7
7
|
module Subset
|
8
|
+
# An 8-bit Unicode-based subset. It can include any Unicode character but
|
9
|
+
# limits number of characters so that the could be encoded by a single byte.
|
8
10
|
class Unicode8Bit < Base
|
11
|
+
# @param original [TTFunk::File]
|
9
12
|
def initialize(original)
|
10
13
|
super
|
11
14
|
@subset = { 0x20 => 0x20 }
|
@@ -13,14 +16,24 @@ module TTFunk
|
|
13
16
|
@next = 0x21 # apparently, PDF's don't like to use chars between 0-31
|
14
17
|
end
|
15
18
|
|
19
|
+
# Is this a Unicode-based subset?
|
20
|
+
#
|
21
|
+
# @return [true]
|
16
22
|
def unicode?
|
17
23
|
true
|
18
24
|
end
|
19
25
|
|
26
|
+
# Get a mapping from this subset to Unicode.
|
27
|
+
#
|
28
|
+
# @return [Hash{Integer => Integer}]
|
20
29
|
def to_unicode_map
|
21
30
|
@subset.dup
|
22
31
|
end
|
23
32
|
|
33
|
+
# Add a character to subset.
|
34
|
+
#
|
35
|
+
# @param character [Integer] Unicode codepoint
|
36
|
+
# @return [void]
|
24
37
|
def use(character)
|
25
38
|
unless @unicodes.key?(character)
|
26
39
|
@subset[@next] = character
|
@@ -29,18 +42,33 @@ module TTFunk
|
|
29
42
|
end
|
30
43
|
end
|
31
44
|
|
45
|
+
# Can this subset include the character?
|
46
|
+
#
|
47
|
+
# @param character [Integer] Unicode codepoint
|
48
|
+
# @return [Boolean]
|
32
49
|
def covers?(character)
|
33
50
|
@unicodes.key?(character) || @next < 256
|
34
51
|
end
|
35
52
|
|
53
|
+
# Does this subset actually has the character?
|
54
|
+
#
|
55
|
+
# @param character [Integer] Unicode codepoint
|
56
|
+
# @return [Boolean]
|
36
57
|
def includes?(character)
|
37
58
|
@unicodes.key?(character)
|
38
59
|
end
|
39
60
|
|
61
|
+
# Get character code for Unicode codepoint.
|
62
|
+
#
|
63
|
+
# @param character [Integer] Unicode codepoint
|
64
|
+
# @return [Integer]
|
40
65
|
def from_unicode(character)
|
41
66
|
@unicodes[character]
|
42
67
|
end
|
43
68
|
|
69
|
+
# Get `cmap` table for this subset.
|
70
|
+
#
|
71
|
+
# @return [TTFunk::Table::Cmap]
|
44
72
|
def new_cmap_table
|
45
73
|
@new_cmap_table ||=
|
46
74
|
begin
|
@@ -59,6 +87,10 @@ module TTFunk
|
|
59
87
|
end
|
60
88
|
end
|
61
89
|
|
90
|
+
# Get the list of Glyph IDs from the original font that are in this
|
91
|
+
# subset.
|
92
|
+
#
|
93
|
+
# @return [Array<Integer>]
|
62
94
|
def original_glyph_ids
|
63
95
|
([0] + @unicodes.keys.map { |unicode| unicode_cmap[unicode] }).uniq.sort
|
64
96
|
end
|
@@ -6,7 +6,9 @@ require_relative 'code_page'
|
|
6
6
|
|
7
7
|
module TTFunk
|
8
8
|
module Subset
|
9
|
+
# Windows 1252 sbset. It uses code page 1252 and Windows-1252 encoding.
|
9
10
|
class Windows1252 < CodePage
|
11
|
+
# @param original [TTFunk::File]
|
10
12
|
def initialize(original)
|
11
13
|
super(original, 1252, Encoding::CP1252)
|
12
14
|
end
|
data/lib/ttfunk/subset.rb
CHANGED
@@ -6,7 +6,15 @@ require_relative 'subset/mac_roman'
|
|
6
6
|
require_relative 'subset/windows_1252'
|
7
7
|
|
8
8
|
module TTFunk
|
9
|
+
# Namespace for different types of subsets.
|
9
10
|
module Subset
|
11
|
+
# Create a subset for the font using the specified encoding.
|
12
|
+
#
|
13
|
+
# @param original [TTFunk::File]
|
14
|
+
# @param encoding [:unicode, :unicode_8bit, :mac_roman, :windows_1252]
|
15
|
+
# @raise [NotImplementedError] for unsupported encodings
|
16
|
+
# @return [TTFunk::Subset::Unicode, TTFunk::Subset::Unicode8Bit,
|
17
|
+
# TTFunk::Subset::MacRoman, TTFunk::Subset::Windows1252]
|
10
18
|
def self.for(original, encoding)
|
11
19
|
case encoding.to_sym
|
12
20
|
when :unicode then Unicode.new(original)
|