-
Notifications
You must be signed in to change notification settings - Fork 1
/
emoji.rb
90 lines (76 loc) · 2.43 KB
/
emoji.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
require 'fileutils'
require 'json'
require_relative 'ttf/ttf'
require_relative 'ttf/ttc'
# Reads, writes, and processes any data not related to the font format
# itself; namely, the font file and image data
module Emoji
class << self
def read
f = File.open('Apple Color Emoji.ttc', 'rb')
f.read
end
def run
file = read()
data = parse_data()
puts "Parsed data: #{data.length} emoji"
# Process TTC container
ttc = TTF::TTC.new(file)
font = ttc.fonts[0]
numGlyphs = font.tables['maxp'].numGlyphs
reverse = font.tables['cmap'].reverse(numGlyphs)
data.each do |input|
cps = input.split('-').map { |hex| hex.to_i(16) }
glyphs = cps.map { |uni| reverse[uni] }
if glyphs.length > 1
lig = font.tables['morx'].chains[0].subtables
.map { |s|
next if s == nil
s.resolve(glyphs)
}
.find { |lig| lig }
else
lig = glyphs[0]
end
begin
# I hate special cases, but for some reason the font doesn't have
# single fully-qualified codepoints made up of the non-fully-qualified
# one followed by FE0F (variation selector), so if we detect this
# is the case, just use the non-fully-qualified code point.
#
# TODO: figure out if the font actually handles this and how?
if !lig && cps.length == 2 && cps[1] == 0xFE0F
lig = glyphs[0]
end
font.tables['sbix'].strikes.each do |strike|
size = strike.ppem
glyph = strike.glyphs[lig]
raise StandardError, 'Glyph data empty' if glyph.data.length == 0
FileUtils.mkdir_p("img/#{size}")
File.open("img/#{size}/#{input}.png", 'wb') do |f|
f.write(glyph.data)
end
end
rescue
puts "Can't find image for combination #{input} with error #{$!}"
end
end
end
def parse_data
spec = File.open('data/emoji-test.txt', 'r').read
additional = File.open('data/additional.txt', 'r').read
combined = [spec, additional].join("\n")
return combined.lines
.map do |row|
match = row.match(/^[0-9a-f]+(\s[0-9a-f]+)*/i)
if match
match[0].gsub(/\s+/, '-')
else
nil
end
end
.select { |row| row }
end
end
end
Emoji.run()