-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRakefile
249 lines (217 loc) · 7.22 KB
/
Rakefile
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# Languages to generate font texture for
LANGUAGES = {
'zh_CN' => 'wqy-zenhei.ttc', # http://wenq.org/enindex.cgi
'ja' => 'TakaoPGothic.ttf' # https://launchpad.net/takao-fonts
}
EXTRA_FML = Hash.new('').merge({
# 'ja' => "kerning=-1",
})
# Command template to generate glyph images for each font style
FONT_STYLES = {
:dialog => <<-DIALOG,
convert -background transparent -font '%{font}' -pointsize 16 \
-fill '#f5f5f5' label:%{character} png32:%{glyph}
DIALOG
:outline => <<-'OUTLINE',
convert \( -background transparent -fill '#550b0b' -font '%{font}' label:%{character} \) \
\( -background transparent -fill '#e9f9f9' -font '%{font}' label:%{character} \) \
-background transparent \
-page -1-1 -clone 0 \
-page -1+1 -clone 0 \
-page +1+1 -clone 0 \
-page +1-1 -clone 0 \
-page +0+0 -clone 1 \
-delete 0,1 -layers merge +repage png32:%{glyph}
OUTLINE
:label => <<-'LABEL'
convert \( -background transparent -fill '#000000' -font '%{font}' label:%{character} \) \
\( -background transparent -fill '#ffffff' -font '%{font}' label:%{character} \) \
-background transparent \
-page -0-1 -clone 0 \
-page +0+0 -clone 1 \
-delete 0,1 -layers merge +repage png32:%{glyph}
LABEL
}
FONT_CFG_IDS = {
:dialog => 'default',
:label => 'door_label',
:outline => 'white_outline'
}
# Naming scheme of font textures
def font_texture(style, language)
"images/gui/#{style}_font.#{language}.png"
end
# Naming scheme of locale specific fonts.cfg
def fonts_cfg(language)
"data/fonts.#{language}.cfg"
end
# Naming scheme of fonts.cfg snippets
def font_cfg_snippet(style, language)
"data/#{style}_font.#{language}.cfg"
end
# Naming scheme of character lists
def character_list(language)
"tmp/fonts/#{language}/characters.txt"
end
# Naming scheme of po files
def po_file(language)
"po/#{language}.po"
end
# Naming scheme of font generation working path
def work_path(style, language)
"tmp/fonts/#{language}/#{style}"
end
# Naming scheme of glyphs
def glyph_image(style, language, character)
File.join work_path(style, language), "#{codepoint_of(character)}.png"
end
# Naming scheme of font tasks
def font_task(style, language)
"font:#{style}:#{language}"
end
# Naming scheme of glyph tasks
def glyphs_task(style, language)
"glyphs:#{style}:#{language}"
end
# Width and height of an image
def image_size(path)
`file #{path}` =~ /(\d+)\s*x\s*(\d+)/
[$1, $2].map(&method(:Integer))
end
# Unicode codepoint of a character
def codepoint_of(character)
character.unpack('U*').first
end
# Character with given unicode codepoint
def character_with_codepoint(codepoint)
[codepoint].pack('U*')
end
# Quote a character in FML
def fml_quote(character)
case character
when '"'
%("\\"")
when "'"
%("'")
else
%("#{character}")
end
end
task :default => :fonts
desc 'Generate all font textures and fonts.cfg snippets'
task :fonts => (LANGUAGES.keys.map do |language|
desc "Generate #{language} font textures and fonts.cfg snippets"
task language => [
fonts_cfg(language),
*FONT_STYLES.keys.map do |style|
[
# glyphs_task(style, language),
font_texture(style, language), font_cfg_snippet(style, language)]
end.flatten
]
end)
# We need to generate a texture and snippet for each pair of (language, font style)
LANGUAGES.each_pair do |language, font|
character_list = character_list(language)
msgstr_text = "#{character_list}.raw"
po_file = po_file(language)
language_work_path = work_path('', language)
directory language_work_path
desc "Generate #{language} character list"
file character_list => [po_file, language_work_path] do
sh <<-SCRIPT
cat /dev/null > #{msgstr_text}
msggrep -v -N CHANGELOG -N MAC_APP_STORE_METADATA \
-N iOS_CHANGELOG -N iOS_APP_STORE_METADATA #{po_file} | \
msgfilter --keep-header -o /dev/null tee -a #{msgstr_text}
cat #{msgstr_text} | utils/strip_po_markup.sh \
| utils/uniq_chars.rb > #{character_list}
SCRIPT
end
file fonts_cfg(language) do |t|
File.open(t.name, 'w') do |file|
file.write <<-EOF
[fonts]
@include "data/number_font.cfg"
@include "data/outline_font.#{language}.cfg"
@include "data/label_font.#{language}.cfg"
@include "data/dialog_font.#{language}.cfg"
[/fonts]
EOF
end
end
FONT_STYLES.each_pair do |style, command|
work_path = work_path(style, language)
directory work_path
glyph_pattern =
Regexp.new(Regexp.escape(glyph_image(style, language, 'a')).sub(/\d+/, '.+'))
rule glyph_pattern => work_path do |t|
glyph = t.name
character = character_with_codepoint(Integer(glyph[/(\d+)/, 1]))
# escape for shell
if character == "'"
character = %q("'")
else
character = "'#{character}'"
end
sh(command % {:font => font, :character => character,
:glyph => glyph, :work_path => work_path})
end
glyphs = {}
glyphs_task = glyphs_task(style, language)
task glyphs_task => character_list do
File.read(character_list).chars.each do |character|
glyph = glyph_image(style, language, character)
glyphs[glyph] = character
Rake::Task[glyph].invoke
end
end
font_texture = font_texture(style, language)
desc "Generate #{language} #{style} font texture"
file font_texture => [work_path, glyphs_task] do
sh <<-COMMAND
montage -label '' -background transparent -gravity SouthWest \
-geometry '1x1+0+0<' #{glyphs.keys.join(' ')} png32:#{font_texture}
COMMAND
# For iOS optimization, the textures need to have even width and height
(width, height) = image_size(font_texture).map {|length| length + length % 2}
sh "convert #{font_texture} -gravity NorthWest -background transparent -extent #{width}x#{height} png32:#{font_texture}"
end
font_cfg_snippet = font_cfg_snippet(style, language)
desc "Generate #{language} #{style} font data"
file font_cfg_snippet => [work_path, font_texture, glyphs_task] do
(texture_width, texture_height) = image_size(font_texture)
widths = {}
heights = {}
glyphs.each_pair do |glyph, character|
(widths[character], heights[character]) = image_size(glyph)
end
(grid_width, grid_height) = [widths, heights].map {|h| h.values.max}
columns = texture_width / grid_width
File.open(font_cfg_snippet, 'w') do |cfg|
cfg.write <<-HEAD
[font]
id="#{FONT_CFG_IDS[style]}"
texture=#{font_texture.sub %r'^images/', ''}
pad=0
#{EXTRA_FML[language]}
HEAD
glyphs.values.each_slice(columns).each_with_index do |characters, row|
characters.each_with_index do |character, column|
left = column * grid_width
top = row * grid_height
right = left + widths[character] - 1
bottom = top + grid_width - 1
cfg.write <<-CHARS
[chars]
chars=#{fml_quote(character)}
rect=#{left},#{top},#{right},#{bottom}
[/chars]
CHARS
end
end
cfg.write '[/font]'
end
end
end
end