glyph_imager 0.0.14 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/VERSION +1 -1
  2. data/glyph_imager.gemspec +45 -36
  3. data/lib/glyph_imager.rb +19 -27
  4. data/test/fonts/Musica.ttf +0 -0
  5. data/test/test_glyph_imager.rb +9 -3
  6. data/vendor/ttfunk/.gitignore +1 -0
  7. data/vendor/ttfunk/data/fonts/DejaVuSans.ttf +0 -0
  8. data/vendor/ttfunk/data/fonts/comicsans.ttf +0 -0
  9. data/vendor/ttfunk/example.rb +45 -0
  10. data/vendor/ttfunk/lib/ttfunk.rb +102 -0
  11. data/vendor/ttfunk/lib/ttfunk/directory.rb +17 -0
  12. data/vendor/ttfunk/lib/ttfunk/encoding/mac_roman.rb +88 -0
  13. data/vendor/ttfunk/lib/ttfunk/encoding/windows_1252.rb +69 -0
  14. data/vendor/ttfunk/lib/ttfunk/reader.rb +44 -0
  15. data/vendor/ttfunk/lib/ttfunk/resource_file.rb +78 -0
  16. data/vendor/ttfunk/lib/ttfunk/subset.rb +18 -0
  17. data/vendor/ttfunk/lib/ttfunk/subset/base.rb +141 -0
  18. data/vendor/ttfunk/lib/ttfunk/subset/mac_roman.rb +50 -0
  19. data/vendor/ttfunk/lib/ttfunk/subset/unicode.rb +48 -0
  20. data/vendor/ttfunk/lib/ttfunk/subset/unicode_8bit.rb +63 -0
  21. data/vendor/ttfunk/lib/ttfunk/subset/windows_1252.rb +55 -0
  22. data/vendor/ttfunk/lib/ttfunk/subset_collection.rb +72 -0
  23. data/vendor/ttfunk/lib/ttfunk/table.rb +46 -0
  24. data/vendor/ttfunk/lib/ttfunk/table/cmap.rb +34 -0
  25. data/vendor/ttfunk/lib/ttfunk/table/cmap/format00.rb +54 -0
  26. data/vendor/ttfunk/lib/ttfunk/table/cmap/format04.rb +126 -0
  27. data/vendor/ttfunk/lib/ttfunk/table/cmap/format12.rb +37 -0
  28. data/vendor/ttfunk/lib/ttfunk/table/cmap/subtable.rb +82 -0
  29. data/vendor/ttfunk/lib/ttfunk/table/glyf.rb +64 -0
  30. data/vendor/ttfunk/lib/ttfunk/table/glyf/compound.rb +81 -0
  31. data/vendor/ttfunk/lib/ttfunk/table/glyf/simple.rb +37 -0
  32. data/vendor/ttfunk/lib/ttfunk/table/head.rb +44 -0
  33. data/vendor/ttfunk/lib/ttfunk/table/hhea.rb +41 -0
  34. data/vendor/ttfunk/lib/ttfunk/table/hmtx.rb +47 -0
  35. data/vendor/ttfunk/lib/ttfunk/table/kern.rb +79 -0
  36. data/vendor/ttfunk/lib/ttfunk/table/kern/format0.rb +62 -0
  37. data/vendor/ttfunk/lib/ttfunk/table/loca.rb +43 -0
  38. data/vendor/ttfunk/lib/ttfunk/table/maxp.rb +40 -0
  39. data/vendor/ttfunk/lib/ttfunk/table/name.rb +125 -0
  40. data/vendor/ttfunk/lib/ttfunk/table/os2.rb +78 -0
  41. data/vendor/ttfunk/lib/ttfunk/table/post.rb +91 -0
  42. data/vendor/ttfunk/lib/ttfunk/table/post/format10.rb +43 -0
  43. data/vendor/ttfunk/lib/ttfunk/table/post/format20.rb +35 -0
  44. data/vendor/ttfunk/lib/ttfunk/table/post/format25.rb +23 -0
  45. data/vendor/ttfunk/lib/ttfunk/table/post/format30.rb +17 -0
  46. data/vendor/ttfunk/lib/ttfunk/table/post/format40.rb +17 -0
  47. data/vendor/ttfunk/lib/ttfunk/table/simple.rb +14 -0
  48. metadata +46 -37
  49. data/vendor/ttf-ruby-0.1/AUTHORS +0 -1
  50. data/vendor/ttf-ruby-0.1/COPYING +0 -340
  51. data/vendor/ttf-ruby-0.1/README +0 -49
  52. data/vendor/ttf-ruby-0.1/TODO +0 -23
  53. data/vendor/ttf-ruby-0.1/VERSION +0 -1
  54. data/vendor/ttf-ruby-0.1/lib/ttf.rb +0 -20
  55. data/vendor/ttf-ruby-0.1/lib/ttf/datatypes.rb +0 -181
  56. data/vendor/ttf-ruby-0.1/lib/ttf/encodings.rb +0 -140
  57. data/vendor/ttf-ruby-0.1/lib/ttf/exceptions.rb +0 -28
  58. data/vendor/ttf-ruby-0.1/lib/ttf/font_loader.rb +0 -290
  59. data/vendor/ttf-ruby-0.1/lib/ttf/fontchunk.rb +0 -77
  60. data/vendor/ttf-ruby-0.1/lib/ttf/table/cmap.rb +0 -408
  61. data/vendor/ttf-ruby-0.1/lib/ttf/table/cvt.rb +0 -49
  62. data/vendor/ttf-ruby-0.1/lib/ttf/table/fpgm.rb +0 -48
  63. data/vendor/ttf-ruby-0.1/lib/ttf/table/gasp.rb +0 -88
  64. data/vendor/ttf-ruby-0.1/lib/ttf/table/glyf.rb +0 -452
  65. data/vendor/ttf-ruby-0.1/lib/ttf/table/head.rb +0 -86
  66. data/vendor/ttf-ruby-0.1/lib/ttf/table/hhea.rb +0 -96
  67. data/vendor/ttf-ruby-0.1/lib/ttf/table/hmtx.rb +0 -98
  68. data/vendor/ttf-ruby-0.1/lib/ttf/table/kern.rb +0 -186
  69. data/vendor/ttf-ruby-0.1/lib/ttf/table/loca.rb +0 -75
  70. data/vendor/ttf-ruby-0.1/lib/ttf/table/maxp.rb +0 -81
  71. data/vendor/ttf-ruby-0.1/lib/ttf/table/name.rb +0 -226
  72. data/vendor/ttf-ruby-0.1/lib/ttf/table/os2.rb +0 -172
  73. data/vendor/ttf-ruby-0.1/lib/ttf/table/post.rb +0 -120
  74. data/vendor/ttf-ruby-0.1/lib/ttf/table/prep.rb +0 -27
  75. data/vendor/ttf-ruby-0.1/lib/ttf/table/vhea.rb +0 -45
  76. data/vendor/ttf-ruby-0.1/lib/ttf/table/vmtx.rb +0 -36
  77. data/vendor/ttf-ruby-0.1/setup.rb +0 -1558
  78. data/vendor/ttf-ruby-0.1/tools/README +0 -44
  79. data/vendor/ttf-ruby-0.1/tools/ttfcairoglyphviewer +0 -229
  80. data/vendor/ttf-ruby-0.1/tools/ttfdump +0 -396
  81. data/vendor/ttf-ruby-0.1/tools/ttfglyph2svg +0 -144
  82. data/vendor/ttf-ruby-0.1/tools/ttfsubset +0 -273
@@ -0,0 +1,69 @@
1
+ module TTFunk
2
+ module Encoding
3
+ class Windows1252
4
+ TO_UNICODE = Hash[*(0..255).zip(0..255).flatten]
5
+ TO_UNICODE.update(
6
+ 0x80 => 0x20AC, 0x82 => 0x201A, 0x83 => 0x0192, 0x84 => 0x201E, 0x85 => 0x2026,
7
+ 0x86 => 0x2020, 0x87 => 0x2021, 0x88 => 0x02C6, 0x89 => 0x2030, 0x8A => 0x0160,
8
+ 0x8B => 0x2039, 0x8C => 0x0152, 0x8E => 0x017D, 0x91 => 0x2018, 0x92 => 0x2019,
9
+ 0x93 => 0x201C, 0x94 => 0x201D, 0x95 => 0x2022, 0x96 => 0x2013, 0x97 => 0x2014,
10
+ 0x98 => 0x02DC, 0x99 => 0x2122, 0x9A => 0x0161, 0x9B => 0x203A, 0x9C => 0x0152,
11
+ 0x9E => 0x017E, 0x9F => 0x0178
12
+ )
13
+
14
+ FROM_UNICODE = {}
15
+ (0..255).each { |key| FROM_UNICODE[TO_UNICODE[key]] = key }
16
+
17
+ # Maps Windows-1252 codes to their corresponding index in the Postscript glyph
18
+ # table (see TTFunk::Table::Post::Format10). If any entry in this array is a string,
19
+ # it is a postscript glyph that is not in the standard list, and which should be
20
+ # emitted specially in the TTF postscript table ('post', see format 2).
21
+ POSTSCRIPT_GLYPH_MAPPING = [
22
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
25
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
26
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
27
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
28
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
29
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 0,
30
+ "Euro", 0, 196, 166, 197, 171, 130, 194, 216, 198, 228, 190, 176, 0, 230, 0,
31
+ 0, 182, 183, 180, 181, 135, 178, 179, 217, 140, 229, 191, 177, 0, 231, 186,
32
+ 3, 163, 132, 133, 189, 150, 232, 134, 142, 139, 157, 169, 164, 16, 138, 218,
33
+ 131, 147, 242, 243, 141, 151, 136, 195, 222, 241, 158, 170, 245, 244, 246, 162,
34
+ 173, 201, 199, 174, 98, 99, 144, 100, 203, 101, 200, 202, 207, 204, 205, 206,
35
+ 233, 102, 211, 208, 209, 175, 103, 240, 145, 214, 212, 213, 104, 235, 237, 137,
36
+ 106, 105, 107, 109, 108, 110, 160, 111, 113, 112, 114, 115, 117, 116, 118, 119,
37
+ 234, 120, 122, 121, 123, 125, 124, 184, 161, 127, 126, 128, 129, 236, 238, 186
38
+ ]
39
+
40
+ def self.covers?(character)
41
+ !FROM_UNICODE[character].nil?
42
+ end
43
+
44
+ def self.to_utf8(string)
45
+ to_unicode_codepoints(string.unpack("C*")).pack("U*")
46
+ end
47
+
48
+ def self.to_unicode(string)
49
+ to_unicode_codepoints(string.unpack("C*")).pack("n*")
50
+ end
51
+
52
+ def self.from_utf8(string)
53
+ from_unicode_codepoints(string.unpack("U*")).pack("C*")
54
+ end
55
+
56
+ def self.from_unicode(string)
57
+ from_unicode_codepoints(string.unpack("n*")).pack("C*")
58
+ end
59
+
60
+ def self.to_unicode_codepoints(array)
61
+ array.map { |code| TO_UNICODE[code] }
62
+ end
63
+
64
+ def self.from_unicode_codepoints(array)
65
+ array.map { |code| FROM_UNICODE[code] || 0 }
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,44 @@
1
+ module TTFunk
2
+ module Reader
3
+ private
4
+
5
+ def io
6
+ @file.contents
7
+ end
8
+
9
+ def read(bytes, format)
10
+ io.read(bytes).unpack(format)
11
+ end
12
+
13
+ def read_signed(count)
14
+ read(count*2, "n*").map { |i| to_signed(i) }
15
+ end
16
+
17
+ def to_signed(n)
18
+ (n>=0x8000) ? -((n ^ 0xFFFF) + 1) : n
19
+ end
20
+
21
+ def parse_from(position)
22
+ saved, io.pos = io.pos, position
23
+ result = yield position
24
+ io.pos = saved
25
+ return result
26
+ end
27
+
28
+ # For debugging purposes
29
+ def hexdump(string)
30
+ bytes = string.unpack("C*")
31
+ bytes.each_with_index do |c, i|
32
+ print "%02X" % c
33
+ if (i+1) % 16 == 0
34
+ puts
35
+ elsif (i+1) % 8 == 0
36
+ print " "
37
+ else
38
+ print " "
39
+ end
40
+ end
41
+ puts unless bytes.length % 16 == 0
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,78 @@
1
+ module TTFunk
2
+ class ResourceFile
3
+ attr_reader :map
4
+
5
+ def self.open(path)
6
+ ::File.open(path, "rb") do |io|
7
+ file = new(io)
8
+ yield file
9
+ end
10
+ end
11
+
12
+ def initialize(io)
13
+ @io = io
14
+
15
+ data_offset, map_offset, data_length, map_length = @io.read(16).unpack("N*")
16
+
17
+ @map = {}
18
+ @io.pos = map_offset + 24 # skip header copy, next map handle, file reference, and attrs
19
+ type_list_offset, name_list_offset = @io.read(4).unpack("n*")
20
+
21
+ type_list_offset += map_offset
22
+ name_list_offset += map_offset
23
+
24
+ @io.pos = type_list_offset
25
+ max_index = @io.read(2).unpack("n").first
26
+ 0.upto(max_index) do
27
+ type, max_type_index, ref_list_offset = @io.read(8).unpack("A4nn")
28
+ @map[type] = { :list => [], :named => {} }
29
+
30
+ parse_from(type_list_offset + ref_list_offset) do
31
+ 0.upto(max_type_index) do
32
+ id, name_ofs, attr = @io.read(5).unpack("nnC")
33
+ data_ofs = @io.read(3)
34
+ data_ofs = data_offset + [0, data_ofs].pack("CA*").unpack("N").first
35
+ handle = @io.read(4).unpack("N").first
36
+
37
+ entry = { :id => id, :attributes => attr, :offset => data_ofs, :handle => handle }
38
+
39
+ if name_list_offset + name_ofs < map_offset + map_length
40
+ parse_from(name_ofs + name_list_offset) do
41
+ len = @io.read(1).unpack("C").first
42
+ entry[:name] = @io.read(len)
43
+ end
44
+ end
45
+
46
+ @map[type][:list] << entry
47
+ @map[type][:named][entry[:name]] = entry if entry[:name]
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ def [](type, index=0)
54
+ if @map[type]
55
+ collection = index.is_a?(Fixnum) ? :list : :named
56
+ if @map[type][collection][index]
57
+ parse_from(@map[type][collection][index][:offset]) do
58
+ length = @io.read(4).unpack("N").first
59
+ return @io.read(length)
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ def resources_for(type)
66
+ (@map[type] && @map[type][:named] || {}).keys
67
+ end
68
+
69
+ private
70
+
71
+ def parse_from(offset)
72
+ saved, @io.pos = @io.pos, offset
73
+ yield
74
+ ensure
75
+ @io.pos = saved
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,18 @@
1
+ require 'ttfunk/subset/unicode'
2
+ require 'ttfunk/subset/unicode_8bit'
3
+ require 'ttfunk/subset/mac_roman'
4
+ require 'ttfunk/subset/windows_1252'
5
+
6
+ module TTFunk
7
+ module Subset
8
+ def self.for(original, encoding)
9
+ case encoding.to_sym
10
+ when :unicode then Unicode.new(original)
11
+ when :unicode_8bit then Unicode8Bit.new(original)
12
+ when :mac_roman then MacRoman.new(original)
13
+ when :windows_1252 then Windows1252.new(original)
14
+ else raise NotImplementedError, "encoding #{encoding} is not supported"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,141 @@
1
+ require 'ttfunk/table/cmap'
2
+ require 'ttfunk/table/glyf'
3
+ require 'ttfunk/table/head'
4
+ require 'ttfunk/table/hhea'
5
+ require 'ttfunk/table/hmtx'
6
+ require 'ttfunk/table/kern'
7
+ require 'ttfunk/table/loca'
8
+ require 'ttfunk/table/maxp'
9
+ require 'ttfunk/table/name'
10
+ require 'ttfunk/table/post'
11
+ require 'ttfunk/table/simple'
12
+
13
+ module TTFunk
14
+ module Subset
15
+ class Base
16
+ attr_reader :original
17
+
18
+ def initialize(original)
19
+ @original = original
20
+ end
21
+
22
+ def unicode?
23
+ false
24
+ end
25
+
26
+ def to_unicode_map
27
+ {}
28
+ end
29
+
30
+ def encode(options={})
31
+ cmap_table = new_cmap_table(options)
32
+ glyphs = collect_glyphs(original_glyph_ids)
33
+
34
+ old2new_glyph = cmap_table[:charmap].inject({ 0 => 0 }) { |map, (code, ids)| map[ids[:old]] = ids[:new]; map }
35
+ next_glyph_id = cmap_table[:max_glyph_id]
36
+
37
+ glyphs.keys.each do |old_id|
38
+ unless old2new_glyph.key?(old_id)
39
+ old2new_glyph[old_id] = next_glyph_id
40
+ next_glyph_id += 1
41
+ end
42
+ end
43
+
44
+ new2old_glyph = old2new_glyph.invert
45
+
46
+ # "mandatory" tables. Every font should ("should") have these, including
47
+ # the cmap table (encoded above).
48
+ glyf_table = TTFunk::Table::Glyf.encode(glyphs, new2old_glyph, old2new_glyph)
49
+ loca_table = TTFunk::Table::Loca.encode(glyf_table[:offsets])
50
+ hmtx_table = TTFunk::Table::Hmtx.encode(original.horizontal_metrics, new2old_glyph)
51
+ hhea_table = TTFunk::Table::Hhea.encode(original.horizontal_header, hmtx_table)
52
+ maxp_table = TTFunk::Table::Maxp.encode(original.maximum_profile, old2new_glyph)
53
+ post_table = TTFunk::Table::Post.encode(original.postscript, new2old_glyph)
54
+ name_table = TTFunk::Table::Name.encode(original.name)
55
+ head_table = TTFunk::Table::Head.encode(original.header, loca_table)
56
+
57
+ # "optional" tables. Fonts may omit these if they do not need them. Because they
58
+ # apply globally, we can simply copy them over, without modification, if they
59
+ # exist.
60
+ os2_table = original.os2.raw
61
+ cvt_table = TTFunk::Table::Simple.new(original, "cvt ").raw
62
+ fpgm_table = TTFunk::Table::Simple.new(original, "fpgm").raw
63
+ prep_table = TTFunk::Table::Simple.new(original, "prep").raw
64
+
65
+ # for PDF's, the kerning info is all included in the PDF as the text is
66
+ # drawn. Thus, the PDF readers do not actually use the kerning info in
67
+ # embedded fonts. If the library is used for something else, the generated
68
+ # subfont may need a kerning table... in that case, you need to opt into it.
69
+ if options[:kerning]
70
+ kern_table = TTFunk::Table::Kern.encode(original.kerning, old2new_glyph)
71
+ end
72
+
73
+ tables = { 'cmap' => cmap_table[:table],
74
+ 'glyf' => glyf_table[:table],
75
+ 'loca' => loca_table[:table],
76
+ 'kern' => kern_table,
77
+ 'hmtx' => hmtx_table[:table],
78
+ 'hhea' => hhea_table,
79
+ 'maxp' => maxp_table,
80
+ 'OS/2' => os2_table,
81
+ 'post' => post_table,
82
+ 'name' => name_table,
83
+ 'head' => head_table,
84
+ 'prep' => prep_table,
85
+ 'fpgm' => fpgm_table,
86
+ 'cvt ' => cvt_table }
87
+
88
+ tables.delete_if { |tag, table| table.nil? }
89
+
90
+ search_range = (Math.log(tables.length) / Math.log(2)).to_i * 16
91
+ entry_selector = (Math.log(search_range) / Math.log(2)).to_i
92
+ range_shift = tables.length * 16 - search_range
93
+
94
+ newfont = [original.directory.scaler_type, tables.length, search_range, entry_selector, range_shift].pack("Nn*")
95
+
96
+ directory_size = tables.length * 16
97
+ offset = newfont.length + directory_size
98
+
99
+ table_data = ""
100
+ head_offset = nil
101
+ tables.each do |tag, data|
102
+ newfont << [tag, checksum(data), offset, data.length].pack("A4N*")
103
+ table_data << data
104
+ head_offset = offset if tag == 'head'
105
+ offset += data.length
106
+ while offset % 4 != 0
107
+ offset += 1
108
+ table_data << "\0"
109
+ end
110
+ end
111
+
112
+ newfont << table_data
113
+ sum = checksum(newfont)
114
+ adjustment = 0xB1B0AFBA - sum
115
+ newfont[head_offset+8,4] = [adjustment].pack("N")
116
+
117
+ return newfont
118
+ end
119
+
120
+ private
121
+
122
+ def unicode_cmap
123
+ @unicode_cmap ||= @original.cmap.unicode.first
124
+ end
125
+
126
+ def checksum(data)
127
+ data += "\0" * (4 - data.length % 4) unless data.length % 4 == 0
128
+ data.unpack("N*").inject(0) { |sum, dword| sum + dword } & 0xFFFF_FFFF
129
+ end
130
+
131
+ def collect_glyphs(glyph_ids)
132
+ glyphs = glyph_ids.inject({}) { |h, id| h[id] = original.glyph_outlines.for(id); h }
133
+ additional_ids = glyphs.values.select { |g| g && g.compound? }.map { |g| g.glyph_ids }.flatten
134
+
135
+ glyphs.update(collect_glyphs(additional_ids)) if additional_ids.any?
136
+
137
+ return glyphs
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,50 @@
1
+ require 'set'
2
+ require 'ttfunk/subset/base'
3
+ require 'ttfunk/encoding/mac_roman'
4
+
5
+ module TTFunk
6
+ module Subset
7
+ class MacRoman < Base
8
+ def initialize(original)
9
+ super
10
+ @subset = Array.new(256)
11
+ end
12
+
13
+ def to_unicode_map
14
+ Encoding::MacRoman::TO_UNICODE
15
+ end
16
+
17
+ def use(character)
18
+ @subset[Encoding::MacRoman::FROM_UNICODE[character]] = character
19
+ end
20
+
21
+ def covers?(character)
22
+ Encoding::MacRoman.covers?(character)
23
+ end
24
+
25
+ def includes?(character)
26
+ code = Encoding::MacRoman::FROM_UNICODE[character]
27
+ code && @subset[code]
28
+ end
29
+
30
+ def from_unicode(character)
31
+ Encoding::MacRoman::FROM_UNICODE[character]
32
+ end
33
+
34
+ protected
35
+
36
+ def new_cmap_table(options)
37
+ mapping = {}
38
+ @subset.each_with_index do |unicode, roman|
39
+ mapping[roman] = unicode_cmap[unicode] if roman
40
+ end
41
+
42
+ TTFunk::Table::Cmap.encode(mapping, :mac_roman)
43
+ end
44
+
45
+ def original_glyph_ids
46
+ ([0] + @subset.map { |unicode| unicode && unicode_cmap[unicode] }).compact.uniq.sort
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,48 @@
1
+ require 'set'
2
+ require 'ttfunk/subset/base'
3
+
4
+ module TTFunk
5
+ module Subset
6
+ class Unicode < Base
7
+ def initialize(original)
8
+ super
9
+ @subset = Set.new
10
+ end
11
+
12
+ def unicode?
13
+ true
14
+ end
15
+
16
+ def to_unicode_map
17
+ @subset.inject({}) { |map, code| map[code] = code; map }
18
+ end
19
+
20
+ def use(character)
21
+ @subset << character
22
+ end
23
+
24
+ def covers?(character)
25
+ true
26
+ end
27
+
28
+ def includes?(character)
29
+ @subset.includes(character)
30
+ end
31
+
32
+ def from_unicode(character)
33
+ character
34
+ end
35
+
36
+ protected
37
+
38
+ def new_cmap_table(options)
39
+ mapping = @subset.inject({}) { |map, code| map[code] = unicode_cmap[code]; map }
40
+ TTFunk::Table::Cmap.encode(mapping, :unicode)
41
+ end
42
+
43
+ def original_glyph_ids
44
+ ([0] + @subset.map { |code| unicode_cmap[code] }).uniq.sort
45
+ end
46
+ end
47
+ end
48
+ end