2016-04-07 15:03:22 +02:00
|
|
|
#!/usr/bin/env python
|
2015-11-01 17:11:06 +01:00
|
|
|
from __future__ import print_function
|
2014-02-20 08:51:58 +01:00
|
|
|
import os
|
2016-06-03 08:38:09 +02:00
|
|
|
import glob
|
2014-02-20 08:51:58 +01:00
|
|
|
import shutil
|
|
|
|
import subprocess
|
|
|
|
import json
|
2015-10-15 01:35:07 +02:00
|
|
|
import sys
|
2016-06-03 21:03:39 +02:00
|
|
|
import xml.etree.ElementTree as ET
|
2016-05-25 15:55:13 +02:00
|
|
|
from six import unichr
|
2014-02-20 08:51:58 +01:00
|
|
|
|
|
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
|
|
|
2016-07-31 11:03:58 +02:00
|
|
|
ZULIP_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../../')
|
|
|
|
|
|
|
|
EMOJI_DUMP_DIR_PATH = os.path.join(ZULIP_PATH, 'var', 'emoji_dump')
|
2016-06-03 21:03:39 +02:00
|
|
|
|
2014-02-20 08:51:58 +01:00
|
|
|
class MissingGlyphError(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2016-06-03 21:03:39 +02:00
|
|
|
def color_font(code_point, code_point_to_fname_map):
|
2016-07-31 11:03:58 +02:00
|
|
|
in_name = os.path.join(EMOJI_DUMP_DIR_PATH, 'bitmaps/strike0/{}.png'.format(
|
2016-06-03 21:04:09 +02:00
|
|
|
code_point_to_fname_map[int(code_point, 16)]
|
2016-07-31 11:03:58 +02:00
|
|
|
))
|
2014-02-20 08:51:58 +01:00
|
|
|
out_name = 'out/unicode/{}.png'.format(code_point)
|
|
|
|
try:
|
|
|
|
shutil.copyfile(in_name, out_name)
|
|
|
|
except IOError:
|
2016-06-03 21:03:39 +02:00
|
|
|
raise MissingGlyphError('code_point: %r' % (code_point))
|
2014-02-20 08:51:58 +01:00
|
|
|
|
|
|
|
|
|
|
|
def bw_font(name, code_point):
|
|
|
|
char = unichr(int(code_point, 16))
|
|
|
|
|
|
|
|
AA_SCALE = 8
|
|
|
|
SIZE = (68, 68)
|
|
|
|
BIG_SIZE = tuple([x * AA_SCALE for x in SIZE])
|
|
|
|
|
|
|
|
# AndroidEmoji.ttf is from
|
|
|
|
# https://android.googlesource.com/platform/frameworks/base.git/+/master/data/fonts/AndroidEmoji.ttf
|
|
|
|
# commit 07912f876c8639f811b06831465c14c4a3b17663
|
|
|
|
font = ImageFont.truetype('AndroidEmoji.ttf', 65 * AA_SCALE)
|
|
|
|
image = Image.new('RGBA', BIG_SIZE)
|
|
|
|
draw = ImageDraw.Draw(image)
|
|
|
|
draw.text((0, 0), char, font=font, fill='black')
|
2016-06-03 21:04:09 +02:00
|
|
|
image.resize(SIZE, Image.ANTIALIAS).save(
|
|
|
|
'out/unicode/{}.png'.format(code_point), 'PNG'
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2016-06-03 21:03:39 +02:00
|
|
|
def code_point_to_file_name_map(ttx):
|
|
|
|
"""Given the NotoColorEmoji.ttx file, parse it to generate a map from
|
|
|
|
codepoint to filename (a la glyph0****.png)
|
|
|
|
"""
|
|
|
|
result = {}
|
|
|
|
xml = ET.parse(ttx)
|
|
|
|
for elem in xml.find("*cmap_format_12"): # type: ignore # https://github.com/python/typeshed/pull/254
|
|
|
|
code_point = int(elem.attrib["code"], 16)
|
|
|
|
fname = elem.attrib["name"]
|
|
|
|
result[code_point] = fname
|
|
|
|
return result
|
2014-02-20 08:51:58 +01:00
|
|
|
|
|
|
|
|
2016-06-03 03:33:52 +02:00
|
|
|
def main():
|
|
|
|
# ttx is in the fonttools pacakge, the -z option is only on master
|
|
|
|
# https://github.com/behdad/fonttools/
|
2014-02-20 08:51:58 +01:00
|
|
|
|
2016-06-03 03:33:52 +02:00
|
|
|
# NotoColorEmoji.tff is from
|
|
|
|
# https://android.googlesource.com/platform/external/noto-fonts/+/marshmallow-release/other/NotoColorEmoji.ttf
|
|
|
|
# note that you have to run it though base64 -D before being able
|
|
|
|
# to use it, since it downloads from that page base64 encoded
|
2016-06-03 08:38:09 +02:00
|
|
|
|
|
|
|
# this is so we don't accidently leave ttx files from previous
|
|
|
|
# runs of this script lying around
|
2016-07-31 11:03:58 +02:00
|
|
|
for fname in glob.glob(os.path.join(EMOJI_DUMP_DIR_PATH, "*ttx*")):
|
2016-06-03 08:38:09 +02:00
|
|
|
os.remove(fname)
|
|
|
|
|
2016-07-31 11:03:58 +02:00
|
|
|
# check if directory `var/emoji_dump` exists
|
|
|
|
subprocess.check_call(['mkdir', '-p', EMOJI_DUMP_DIR_PATH])
|
|
|
|
|
|
|
|
subprocess.call('ttx -v -z extfile -d {} NotoColorEmoji.ttf'.format(EMOJI_DUMP_DIR_PATH), shell=True)
|
2014-02-20 08:51:58 +01:00
|
|
|
|
2016-06-03 03:33:52 +02:00
|
|
|
try:
|
|
|
|
shutil.rmtree('out')
|
|
|
|
except OSError:
|
|
|
|
pass
|
2015-09-25 08:56:36 +02:00
|
|
|
|
2016-06-03 03:33:52 +02:00
|
|
|
os.mkdir('out')
|
|
|
|
os.mkdir('out/unicode')
|
2015-09-25 08:56:36 +02:00
|
|
|
|
2016-06-03 03:33:52 +02:00
|
|
|
emoji_map = json.load(open('emoji_map.json'))
|
|
|
|
|
|
|
|
# Fix data problem with red/blue cars being inaccurate.
|
|
|
|
emoji_map['blue_car'] = emoji_map['red_car']
|
|
|
|
emoji_map['red_car'] = emoji_map['oncoming_automobile']
|
2015-10-15 01:35:07 +02:00
|
|
|
|
2016-06-03 03:33:52 +02:00
|
|
|
failed = False
|
2016-07-31 11:03:58 +02:00
|
|
|
code_point_to_fname_map = code_point_to_file_name_map(os.path.join(EMOJI_DUMP_DIR_PATH, "NotoColorEmoji.ttx"))
|
2016-06-03 03:33:52 +02:00
|
|
|
for name, code_point in emoji_map.items():
|
|
|
|
try:
|
|
|
|
color_font(code_point, code_point_to_fname_map)
|
|
|
|
except MissingGlyphError:
|
|
|
|
try:
|
|
|
|
bw_font(name, code_point)
|
|
|
|
except Exception as e:
|
|
|
|
print(e)
|
|
|
|
print('Missing {}, {}'.format(name, code_point))
|
|
|
|
failed = True
|
|
|
|
continue
|
|
|
|
|
|
|
|
os.symlink(
|
|
|
|
'unicode/{}.png'.format(code_point),
|
|
|
|
'out/{}.png'.format(name)
|
|
|
|
)
|
|
|
|
|
|
|
|
if failed:
|
|
|
|
print("Errors dumping emoji!")
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|