Merge remote-tracking branch 'upstream/master'

pull/134/head
Julien Humbert 2018-02-26 20:56:45 +09:00
commit a5046351fd
5602 changed files with 1068775 additions and 256835 deletions

View File

@ -20,7 +20,8 @@ LDFLAGS = -lm `pkg-config --libs cairo`
PNGQUANTDIR := third_party/pngquant PNGQUANTDIR := third_party/pngquant
PNGQUANT := $(PNGQUANTDIR)/pngquant PNGQUANT := $(PNGQUANTDIR)/pngquant
PNGQUANTFLAGS = --speed 1 --skip-if-larger --quality 85-95 --force PNGQUANTFLAGS = --speed 1 --skip-if-larger --quality 85-95 --force
IMOPS = -size 136x128 canvas:none -compose copy -gravity center BODY_DIMENSIONS = 136x128
IMOPS := -size $(BODY_DIMENSIONS) canvas:none -compose copy -gravity center
# zopflipng is better (about 5-10%) but much slower. it will be used if # zopflipng is better (about 5-10%) but much slower. it will be used if
# present. pass ZOPFLIPNG= as an arg to make to use optipng instead. # present. pass ZOPFLIPNG= as an arg to make to use optipng instead.

View File

@ -78,7 +78,7 @@
<head> <head>
<!-- Most of this table will be recalculated by the compiler --> <!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/> <tableVersion value="1.0"/>
<fontRevision value="1.39"/> <fontRevision value="2.004"/>
<checkSumAdjustment value="0x4d5a161a"/> <checkSumAdjustment value="0x4d5a161a"/>
<magicNumber value="0x5f0f3cf5"/> <magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00001011"/> <flags value="00000000 00001011"/>
@ -246,7 +246,7 @@
Noto Color Emoji Noto Color Emoji
</namerecord> </namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409"> <namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 1.39;GOOG;noto-emoji:20170518:009916646ea7 Version 2.004;GOOG;noto-emoji:20180102:8bd8a303c391
</namerecord> </namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409"> <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
NotoColorEmoji NotoColorEmoji

View File

@ -2,11 +2,10 @@
# Noto Emoji # Noto Emoji
Color and Black-and-White Noto emoji fonts, and tools for working with them. Color and Black-and-White Noto emoji fonts, and tools for working with them.
The color version must be built from source.
## Building NotoColorEmoji ## Building NotoColorEmoji
Building NotoColorEmoji requires a few files from nototools. Clone a copy from Building NotoColorEmoji currently requires a Python 2.x wide build. To build
the emoji font you will require a few files from nototools. Clone a copy from
https://github.com/googlei18n/nototools and either put it in your PYTHONPATH or https://github.com/googlei18n/nototools and either put it in your PYTHONPATH or
use 'python setup.py develop' ('install' currently won't fully install all the use 'python setup.py develop' ('install' currently won't fully install all the
data used by nototools). You will also need fontTools, get it from data used by nototools). You will also need fontTools, get it from
@ -20,12 +19,32 @@ font will be at the top level.
## Using NotoColorEmoji ## Using NotoColorEmoji
NotoColorEmoji uses the CBDT/CBLC color font format, which is supported by Android NotoColorEmoji uses the CBDT/CBLC color font format, which is supported by Android
and Chrome/Chromium OS, but not MacOS. Windows supports it starting with Windows 10 and Chrome/Chromium OS, but not macOS. Windows supports it starting with Windows 10
Anniversary Update. No Browser on MacOS supports it, but Edge (on latest Windows) Anniversary Update. No Browser on macOS supports it, but Edge (on latest Windows)
does. Chrome on Linux will support it with some fontconfig tweaking, see does. Chrome on Linux will support it with some fontconfig tweaking, see
[issue #36](https://github.com/googlei18n/noto-emoji/issues/36). Currently we do [issue #36](https://github.com/googlei18n/noto-emoji/issues/36). Currently we do
not build other color font formats. not build other color font formats.
## Color emoji assets
The assets provided in the repo are all those used to build the NotoColorEmoji
font. Note however that NotoColorEmoji often uses the same assets to represent
different character sequences-- notably, most gender-neutral characters or
sequences are represented using assets named after one of the gendered
sequences. This means that some sequences appear to be missing. Definitions of
the aliasing used appear in the emoji_aliases.txt file.
Also note that the images in the font might differ from the original assets. In
particular the flag images in the font are PNG images to which transforms have
been applied to standardize the size and generate the wave and border shadow. We
do not have SVG versions that reflect these transforms.
## B/W emoji font
The black-and-white emoji font is not under active development. Its repertoire of
emoji is now several years old, and the design does not reflect the current color
emoji design. Currently we have no plans to update this font.
## License ## License
Emoji fonts (under the fonts subdirectory) are under the Emoji fonts (under the fonts subdirectory) are under the
@ -40,5 +59,6 @@ Please read [CONTRIBUTING](CONTRIBUTING.md) if you are thinking of contributing
## News ## News
* 2017-09-13: Emoji redesign released.
* 2015-12-09: Unicode 7 and 8 emoji image data (.png format) added. * 2015-12-09: Unicode 7 and 8 emoji image data (.png format) added.
* 2015-09-29: All Noto fonts now licensed under the SIL Open Font License. * 2015-09-29: All Noto fonts now licensed under the SIL Open Font License.

View File

@ -14,6 +14,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from __future__ import print_function
import argparse import argparse
import glob import glob
import os import os
@ -21,17 +22,20 @@ from os import path
import shutil import shutil
import sys import sys
from nototools import unicode_data
"""Create aliases in target directory. """Create aliases in target directory.
The target files should not contain the emoji variation selector In addition to links/copies named with aliased sequences, this can also
codepoint in their names.""" create canonically named aliases/copies, if requested."""
DATA_ROOT = path.dirname(path.abspath(__file__)) DATA_ROOT = path.dirname(path.abspath(__file__))
def str_to_seq(seq_str): def str_to_seq(seq_str):
res = [int(s, 16) for s in seq_str.split('_')] res = [int(s, 16) for s in seq_str.split('_')]
if 0xfe0f in res: if 0xfe0f in res:
print '0xfe0f in file name: %s' % seq_str print('0xfe0f in file name: %s' % seq_str)
res = [x for x in res if x != 0xfe0f] res = [x for x in res if x != 0xfe0f]
return tuple(res) return tuple(res)
@ -66,7 +70,7 @@ def read_emoji_aliases(filename):
als_seq = tuple([int(x, 16) for x in als.split('_')]) als_seq = tuple([int(x, 16) for x in als.split('_')])
trg_seq = tuple([int(x, 16) for x in trg.split('_')]) trg_seq = tuple([int(x, 16) for x in trg.split('_')])
except: except:
print 'cannot process alias %s -> %s' % (als, trg) print('cannot process alias %s -> %s' % (als, trg))
continue continue
result[als_seq] = trg_seq result[als_seq] = trg_seq
return result return result
@ -74,15 +78,20 @@ def read_emoji_aliases(filename):
def add_aliases( def add_aliases(
srcdir, dstdir, aliasfile, prefix, ext, replace=False, copy=False, srcdir, dstdir, aliasfile, prefix, ext, replace=False, copy=False,
dry_run=False): canonical_names=False, dry_run=False):
"""Use aliasfile to create aliases of files in srcdir matching prefix/ext in """Use aliasfile to create aliases of files in srcdir matching prefix/ext in
dstdir. If dstdir is null, use srcdir as dstdir. If replace is false dstdir. If dstdir is null, use srcdir as dstdir. If replace is false
and a file already exists in dstdir, report and do nothing. If copy is false and a file already exists in dstdir, report and do nothing. If copy is false
create a symlink, else create a copy. If dry_run is true, report what would create a symlink, else create a copy.
be done. Dstdir will be created if necessary, even if dry_run is true."""
If canonical_names is true, check all source files and generate aliases/copies
using the canonical name if different from the existing name.
If dry_run is true, report what would be done. Dstdir will be created if
necessary, even if dry_run is true."""
if not path.isdir(srcdir): if not path.isdir(srcdir):
print >> sys.stderr, '%s is not a directory' % srcdir print('%s is not a directory' % srcdir, file=sys.stderr)
return return
if not dstdir: if not dstdir:
@ -102,36 +111,62 @@ def add_aliases(
aliases_to_create = {} aliases_to_create = {}
aliases_to_replace = [] aliases_to_replace = []
alias_exists = False alias_exists = False
for als, trg in sorted(aliases.items()):
if trg not in seq_to_file: def check_alias_seq(seq):
print >> sys.stderr, 'target %s for %s does not exist' % ( alias_str = seq_to_str(seq)
seq_to_str(trg), seq_to_str(als)) alias_name = '%s%s.%s' % (prefix, alias_str, ext)
continue
alias_name = '%s%s.%s' % (prefix, seq_to_str(als), ext)
alias_path = path.join(dstdir, alias_name) alias_path = path.join(dstdir, alias_name)
if path.exists(alias_path): if path.exists(alias_path):
if replace: if replace:
aliases_to_replace.append(alias_name) aliases_to_replace.append(alias_name)
else: else:
print >> sys.stderr, 'alias %s exists' % seq_to_str(als) print('alias %s exists' % alias_str, file=sys.stderr)
alias_exists = True alias_exists = True
return None
return alias_name
canonical_to_file = {}
for als, trg in sorted(aliases.items()):
if trg not in seq_to_file:
print('target %s for %s does not exist' % (
seq_to_str(trg), seq_to_str(als)), file=sys.stderr)
continue continue
alias_name = check_alias_seq(als)
if alias_name:
target_file = seq_to_file[trg] target_file = seq_to_file[trg]
aliases_to_create[alias_name] = target_file aliases_to_create[alias_name] = target_file
if canonical_names:
canonical_seq = unicode_data.get_canonical_emoji_sequence(als)
if canonical_seq and canonical_seq != als:
canonical_alias_name = check_alias_seq(canonical_seq)
if canonical_alias_name:
canonical_to_file[canonical_alias_name] = target_file
if canonical_names:
print('adding %d canonical aliases' % len(canonical_to_file))
for seq, f in seq_to_file.iteritems():
canonical_seq = unicode_data.get_canonical_emoji_sequence(seq)
if canonical_seq and canonical_seq != seq:
alias_name = check_alias_seq(canonical_seq)
if alias_name:
canonical_to_file[alias_name] = f
print('adding %d total canonical sequences' % len(canonical_to_file))
aliases_to_create.update(canonical_to_file)
if replace: if replace:
if not dry_run: if not dry_run:
for k in sorted(aliases_to_replace): for k in sorted(aliases_to_replace):
os.remove(path.join(dstdir, k)) os.remove(path.join(dstdir, k))
print 'replacing %d files' % len(aliases_to_replace) print('replacing %d files' % len(aliases_to_replace))
elif alias_exists: elif alias_exists:
print >> sys.stderr, 'aborting, aliases exist.' print('aborting, aliases exist.', file=sys.stderr)
return return
for k, v in sorted(aliases_to_create.items()): for k, v in sorted(aliases_to_create.items()):
if dry_run: if dry_run:
msg = 'replace ' if k in aliases_to_replace else '' msg = 'replace ' if k in aliases_to_replace else ''
print '%s%s -> %s' % (msg, k, v) print('%s%s -> %s' % (msg, k, v))
else: else:
try: try:
if copy: if copy:
@ -143,10 +178,10 @@ def add_aliases(
else: else:
raise Exception('can\'t create cross-directory symlinks yet') raise Exception('can\'t create cross-directory symlinks yet')
except Exception as e: except Exception as e:
print >> sys.stderr, 'failed to create %s -> %s' % (k, v) print('failed to create %s -> %s' % (k, v), file=sys.stderr)
raise Exception('oops, ' + str(e)) raise Exception('oops, ' + str(e))
print 'created %d %s' % ( print('created %d %s' % (
len(aliases_to_create), 'copies' if copy else 'symlinks') len(aliases_to_create), 'copies' if copy else 'symlinks'))
def main(): def main():
@ -165,13 +200,16 @@ def main():
metavar='pfx', default='emoji_u') metavar='pfx', default='emoji_u')
parser.add_argument( parser.add_argument(
'-e', '--ext', help='file name extension (default png)', '-e', '--ext', help='file name extension (default png)',
choices=['ai', 'png', 'sgv'], default='png') choices=['ai', 'png', 'svg'], default='png')
parser.add_argument( parser.add_argument(
'-r', '--replace', help='replace existing files/aliases', '-r', '--replace', help='replace existing files/aliases',
action='store_true') action='store_true')
parser.add_argument( parser.add_argument(
'-c', '--copy', help='create a copy of the file, not a symlink', '-c', '--copy', help='create a copy of the file, not a symlink',
action='store_true') action='store_true')
parser.add_argument(
'--canonical_names', help='include extra copies with canonical names '
'(including fe0f emoji presentation character)', action='store_true');
parser.add_argument( parser.add_argument(
'-n', '--dry_run', help='print out aliases to create only', '-n', '--dry_run', help='print out aliases to create only',
action='store_true') action='store_true')
@ -179,7 +217,7 @@ def main():
add_aliases( add_aliases(
args.srcdir, args.dstdir, args.aliasfile, args.prefix, args.ext, args.srcdir, args.dstdir, args.aliasfile, args.prefix, args.ext,
args.replace, args.copy, args.dry_run) args.replace, args.copy, args.canonical_names, args.dry_run)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -16,6 +16,7 @@
# Google Author(s): Doug Felt # Google Author(s): Doug Felt
"""Tool to update GSUB, hmtx, cmap, glyf tables with svg image glyphs.""" """Tool to update GSUB, hmtx, cmap, glyf tables with svg image glyphs."""
from __future__ import print_function
import argparse import argparse
import glob import glob
@ -171,7 +172,7 @@ class FontBuilder(object):
self.svgs.append(svg_record) self.svgs.append(svg_record)
def collect_glyphstr_file_pairs(prefix, ext, include=None, exclude=None): def collect_glyphstr_file_pairs(prefix, ext, include=None, exclude=None, verbosity=1):
"""Scan files with the given prefix and extension, and return a list of """Scan files with the given prefix and extension, and return a list of
(glyphstr, filename) where glyphstr is the character or ligature, and filename (glyphstr, filename) where glyphstr is the character or ligature, and filename
is the image file associated with it. The glyphstr is formed by decoding the is the image file associated with it. The glyphstr is formed by decoding the
@ -199,7 +200,7 @@ def collect_glyphstr_file_pairs(prefix, ext, include=None, exclude=None):
if ex and ex.search(image_file): if ex and ex.search(image_file):
if verbosity > 1: if verbosity > 1:
print "Exclude %s" % image_file print("Exclude %s" % image_file)
ex_count += 1 ex_count += 1
continue continue

View File

@ -15,6 +15,7 @@
# limitations under the License. # limitations under the License.
"""Compare emoji image file namings against unicode property data.""" """Compare emoji image file namings against unicode property data."""
from __future__ import print_function
import argparse import argparse
import collections import collections
@ -95,9 +96,9 @@ def _check_valid_emoji(sorted_seq_to_filepath):
not_emoji[cp].append(fp) not_emoji[cp].append(fp)
if len(not_emoji): if len(not_emoji):
print >> sys.stderr, '%d non-emoji found:' % len(not_emoji) print('%d non-emoji found:' % len(not_emoji), file=sys.stderr)
for cp in sorted(not_emoji): for cp in sorted(not_emoji):
print >> sys.stderr, '%04x (in %s)' % (cp, ', '.join(not_emoji[cp])) print('%04x (in %s)' % (cp, ', '.join(not_emoji[cp])), file=sys.stderr)
def _check_zwj(sorted_seq_to_filepath): def _check_zwj(sorted_seq_to_filepath):
@ -109,21 +110,21 @@ def _check_zwj(sorted_seq_to_filepath):
if ZWJ not in seq: if ZWJ not in seq:
continue continue
if seq[0] == 0x200d: if seq[0] == 0x200d:
print >> sys.stderr, 'zwj at head of sequence in %s' % fp print('zwj at head of sequence in %s' % fp, file=sys.stderr)
if len(seq) == 1: if len(seq) == 1:
continue continue
if seq[-1] == 0x200d: if seq[-1] == 0x200d:
print >> sys.stderr, 'zwj at end of sequence in %s' % fp print('zwj at end of sequence in %s' % fp, file=sys.stderr)
for i, cp in enumerate(seq): for i, cp in enumerate(seq):
if cp == ZWJ: if cp == ZWJ:
if i > 0: if i > 0:
pcp = seq[i-1] pcp = seq[i-1]
if pcp != EMOJI_PRESENTATION_VS and not unicode_data.is_emoji(pcp): if pcp != EMOJI_PRESENTATION_VS and not unicode_data.is_emoji(pcp):
print >> sys.stderr, 'non-emoji %04x preceeds ZWJ in %s' % (pcp, fp) print('non-emoji %04x preceeds ZWJ in %s' % (pcp, fp), file=sys.stderr)
if i < len(seq) - 1: if i < len(seq) - 1:
fcp = seq[i+1] fcp = seq[i+1]
if not unicode_data.is_emoji(fcp): if not unicode_data.is_emoji(fcp):
print >> sys.stderr, 'non-emoji %04x follows ZWJ in %s' % (fcp, fp) print('non-emoji %04x follows ZWJ in %s' % (fcp, fp), file=sys.stderr)
def _check_flags(sorted_seq_to_filepath): def _check_flags(sorted_seq_to_filepath):
@ -136,11 +137,11 @@ def _check_flags(sorted_seq_to_filepath):
if have_reg == None: if have_reg == None:
have_reg = is_reg have_reg = is_reg
elif have_reg != is_reg: elif have_reg != is_reg:
print >> sys.stderr, 'mix of regional and non-regional in %s' % fp print('mix of regional and non-regional in %s' % fp, file=sys.stderr)
if have_reg and len(seq) > 2: if have_reg and len(seq) > 2:
# We provide dummy glyphs for regional indicators, so there are sequences # We provide dummy glyphs for regional indicators, so there are sequences
# with single regional indicator symbols. # with single regional indicator symbols.
print >> sys.stderr, 'regional indicator sequence length != 2 in %s' % fp print('regional indicator sequence length != 2 in %s' % fp, file=sys.stderr)
def _check_skintone(sorted_seq_to_filepath): def _check_skintone(sorted_seq_to_filepath):
@ -153,13 +154,13 @@ def _check_skintone(sorted_seq_to_filepath):
if _is_skintone_modifier(cp): if _is_skintone_modifier(cp):
if i == 0: if i == 0:
if len(seq) > 1: if len(seq) > 1:
print >> sys.stderr, 'skin color selector first in sequence %s' % fp print('skin color selector first in sequence %s' % fp, file=sys.stderr)
# standalone are ok # standalone are ok
continue continue
pcp = seq[i-1] pcp = seq[i-1]
if not unicode_data.is_emoji_modifier_base(pcp): if not unicode_data.is_emoji_modifier_base(pcp):
print >> sys.stderr, ( print((
'emoji skintone modifier applied to non-base at %d: %s' % (i, fp)) 'emoji skintone modifier applied to non-base at %d: %s' % (i, fp)), file=sys.stderr)
elif unicode_data.is_emoji_modifier_base(cp): elif unicode_data.is_emoji_modifier_base(cp):
if i < len(seq) - 1 and _is_skintone_modifier(seq[i+1]): if i < len(seq) - 1 and _is_skintone_modifier(seq[i+1]):
base_to_modifiers[cp].add(seq[i+1]) base_to_modifiers[cp].add(seq[i+1])
@ -167,9 +168,9 @@ def _check_skintone(sorted_seq_to_filepath):
base_to_modifiers[cp] = set() base_to_modifiers[cp] = set()
for cp, modifiers in sorted(base_to_modifiers.iteritems()): for cp, modifiers in sorted(base_to_modifiers.iteritems()):
if len(modifiers) != 5: if len(modifiers) != 5:
print >> sys.stderr, 'emoji base %04x has %d modifiers defined (%s) in %s' % ( print('emoji base %04x has %d modifiers defined (%s) in %s' % (
cp, len(modifiers), cp, len(modifiers),
', '.join('%04x' % cp for cp in sorted(modifiers)), fp) ', '.join('%04x' % cp for cp in sorted(modifiers)), fp), file=sys.stderr)
def _check_zwj_sequences(seq_to_filepath): def _check_zwj_sequences(seq_to_filepath):
@ -189,7 +190,7 @@ def _check_zwj_sequences(seq_to_filepath):
for seq, fp in zwj_seq_to_filepath.iteritems(): for seq, fp in zwj_seq_to_filepath.iteritems():
if seq not in zwj_sequence_to_name: if seq not in zwj_sequence_to_name:
if seq not in zwj_sequence_without_vs_to_name_canonical: if seq not in zwj_sequence_without_vs_to_name_canonical:
print >> sys.stderr, 'zwj sequence not defined: %s' % fp print('zwj sequence not defined: %s' % fp, file=sys.stderr)
else: else:
_, can = zwj_sequence_without_vs_to_name_canonical[seq] _, can = zwj_sequence_without_vs_to_name_canonical[seq]
# print >> sys.stderr, 'canonical sequence %s contains vs: %s' % ( # print >> sys.stderr, 'canonical sequence %s contains vs: %s' % (
@ -211,7 +212,7 @@ def read_emoji_aliases():
try: try:
trg_seq = tuple([int(x, 16) for x in trg.split('_')]) trg_seq = tuple([int(x, 16) for x in trg.split('_')])
except: except:
print 'cannot process alias %s -> %s' % (als, trg) print('cannot process alias %s -> %s' % (als, trg))
continue continue
result[als_seq] = trg_seq result[als_seq] = trg_seq
return result return result
@ -229,11 +230,11 @@ def _check_coverage(seq_to_filepath):
aliases = read_emoji_aliases() aliases = read_emoji_aliases()
for k, v in sorted(aliases.items()): for k, v in sorted(aliases.items()):
if v not in seq_to_filepath and v not in non_vs_to_canonical: if v not in seq_to_filepath and v not in non_vs_to_canonical:
print 'alias %s missing target %s' % (_seq_string(k), _seq_string(v)) print('alias %s missing target %s' % (_seq_string(k), _seq_string(v)))
continue continue
if k in seq_to_filepath or k in non_vs_to_canonical: if k in seq_to_filepath or k in non_vs_to_canonical:
print 'alias %s already exists as %s (%s)' % ( print('alias %s already exists as %s (%s)' % (
_seq_string(k), _seq_string(v), seq_name(v)) _seq_string(k), _seq_string(v), seq_name(v)))
continue continue
filename = seq_to_filepath.get(v) or seq_to_filepath[non_vs_to_canonical[v]] filename = seq_to_filepath.get(v) or seq_to_filepath[non_vs_to_canonical[v]]
seq_to_filepath[k] = 'alias:' + filename seq_to_filepath[k] = 'alias:' + filename
@ -242,13 +243,13 @@ def _check_coverage(seq_to_filepath):
emoji = sorted(unicode_data.get_emoji(age=age)) emoji = sorted(unicode_data.get_emoji(age=age))
for cp in emoji: for cp in emoji:
if tuple([cp]) not in seq_to_filepath: if tuple([cp]) not in seq_to_filepath:
print 'missing single %04x (%s)' % (cp, unicode_data.name(cp, '<no name>')) print('missing single %04x (%s)' % (cp, unicode_data.name(cp, '<no name>')))
# special characters # special characters
# all but combining enclosing keycap are currently marked as emoji # all but combining enclosing keycap are currently marked as emoji
for cp in [ord('*'), ord('#'), ord(u'\u20e3')] + range(0x30, 0x3a): for cp in [ord('*'), ord('#'), ord(u'\u20e3')] + range(0x30, 0x3a):
if cp not in emoji and tuple([cp]) not in seq_to_filepath: if cp not in emoji and tuple([cp]) not in seq_to_filepath:
print 'missing special %04x (%s)' % (cp, unicode_data.name(cp)) print('missing special %04x (%s)' % (cp, unicode_data.name(cp)))
# combining sequences # combining sequences
comb_seq_to_name = sorted( comb_seq_to_name = sorted(
@ -258,22 +259,22 @@ def _check_coverage(seq_to_filepath):
# strip vs and try again # strip vs and try again
non_vs_seq = strip_vs(seq) non_vs_seq = strip_vs(seq)
if non_vs_seq not in seq_to_filepath: if non_vs_seq not in seq_to_filepath:
print 'missing combining sequence %s (%s)' % (_seq_string(seq), name) print('missing combining sequence %s (%s)' % (_seq_string(seq), name))
# flag sequences # flag sequences
flag_seq_to_name = sorted( flag_seq_to_name = sorted(
unicode_data.get_emoji_flag_sequences(age=age).iteritems()) unicode_data.get_emoji_flag_sequences(age=age).iteritems())
for seq, name in flag_seq_to_name: for seq, name in flag_seq_to_name:
if seq not in seq_to_filepath: if seq not in seq_to_filepath:
print 'missing flag sequence %s (%s)' % (_seq_string(seq), name) print('missing flag sequence %s (%s)' % (_seq_string(seq), name))
# skin tone modifier sequences # skin tone modifier sequences
mod_seq_to_name = sorted( mod_seq_to_name = sorted(
unicode_data.get_emoji_modifier_sequences(age=age).iteritems()) unicode_data.get_emoji_modifier_sequences(age=age).iteritems())
for seq, name in mod_seq_to_name: for seq, name in mod_seq_to_name:
if seq not in seq_to_filepath: if seq not in seq_to_filepath:
print 'missing modifier sequence %s (%s)' % ( print('missing modifier sequence %s (%s)' % (
_seq_string(seq), name) _seq_string(seq), name))
# zwj sequences # zwj sequences
# some of ours include the emoji presentation variation selector and some # some of ours include the emoji presentation variation selector and some
@ -294,14 +295,14 @@ def _check_coverage(seq_to_filepath):
else: else:
test_seq = seq test_seq = seq
if test_seq not in zwj_seq_without_vs: if test_seq not in zwj_seq_without_vs:
print 'missing (canonical) zwj sequence %s (%s)' % ( print('missing (canonical) zwj sequence %s (%s)' % (
_seq_string(seq), name) _seq_string(seq), name))
# check for 'unknown flag' # check for 'unknown flag'
# this is either emoji_ufe82b or 'unknown_flag', we filter out things that # this is either emoji_ufe82b or 'unknown_flag', we filter out things that
# don't start with our prefix so 'unknown_flag' would be excluded by default. # don't start with our prefix so 'unknown_flag' would be excluded by default.
if tuple([0xfe82b]) not in seq_to_filepath: if tuple([0xfe82b]) not in seq_to_filepath:
print 'missing unknown flag PUA fe82b' print('missing unknown flag PUA fe82b')
def check_sequence_to_filepath(seq_to_filepath): def check_sequence_to_filepath(seq_to_filepath):
@ -322,7 +323,7 @@ def create_sequence_to_filepath(name_to_dirpath, prefix, suffix):
result = {} result = {}
for name, dirname in name_to_dirpath.iteritems(): for name, dirname in name_to_dirpath.iteritems():
if not name.startswith(prefix): if not name.startswith(prefix):
print 'expected prefix "%s" for "%s"' % (prefix, name) print('expected prefix "%s" for "%s"' % (prefix, name))
continue continue
segments = name[len(prefix): -len(suffix)].split('_') segments = name[len(prefix): -len(suffix)].split('_')
@ -330,12 +331,12 @@ def create_sequence_to_filepath(name_to_dirpath, prefix, suffix):
seq = [] seq = []
for s in segments: for s in segments:
if not segment_re.match(s): if not segment_re.match(s):
print 'bad codepoint name "%s" in %s/%s' % (s, dirname, name) print('bad codepoint name "%s" in %s/%s' % (s, dirname, name))
segfail = True segfail = True
continue continue
n = int(s, 16) n = int(s, 16)
if n > 0x10ffff: if n > 0x10ffff:
print 'codepoint "%s" out of range in %s/%s' % (s, dirname, name) print('codepoint "%s" out of range in %s/%s' % (s, dirname, name))
segfail = True segfail = True
continue continue
seq.append(n) seq.append(n)
@ -356,8 +357,8 @@ def collect_name_to_dirpath(directory, prefix, suffix):
if not f.endswith(suffix): if not f.endswith(suffix):
continue continue
if f in result: if f in result:
print >> sys.stderr, 'duplicate file "%s" in %s and %s ' % ( print('duplicate file "%s" in %s and %s ' % (
f, dirname, result[f]) f, dirname, result[f]), file=sys.stderr)
continue continue
result[f] = dirname result[f] = dirname
return result return result
@ -375,15 +376,15 @@ def collect_name_to_dirpath_with_override(dirs, prefix, suffix):
def run_check(dirs, prefix, suffix): def run_check(dirs, prefix, suffix):
print 'Checking files with prefix "%s" and suffix "%s" in:\n %s' % ( print('Checking files with prefix "%s" and suffix "%s" in:\n %s' % (
prefix, suffix, '\n '.join(dirs)) prefix, suffix, '\n '.join(dirs)))
name_to_dirpath = collect_name_to_dirpath_with_override( name_to_dirpath = collect_name_to_dirpath_with_override(
dirs, prefix=prefix, suffix=suffix) dirs, prefix=prefix, suffix=suffix)
print 'checking %d names' % len(name_to_dirpath) print('checking %d names' % len(name_to_dirpath))
seq_to_filepath = create_sequence_to_filepath(name_to_dirpath, prefix, suffix) seq_to_filepath = create_sequence_to_filepath(name_to_dirpath, prefix, suffix)
print 'checking %d sequences' % len(seq_to_filepath) print('checking %d sequences' % len(seq_to_filepath))
check_sequence_to_filepath(seq_to_filepath) check_sequence_to_filepath(seq_to_filepath)
print 'done.' print('done.')
def main(): def main():

View File

@ -96,14 +96,14 @@ def copy_with_rename(src_dir, dst_dir, accept_pred=None, rename=None):
def build_svg_dir(dst_dir, clean=False, emoji_dir='', flags_dir=''): def build_svg_dir(dst_dir, clean=False, emoji_dir='', flags_dir=''):
"""Copies/renames files from emoji_dir and then flag_dir, giving them the """Copies/renames files from emoji_dir and then flags_dir, giving them the
standard format and prefix ('emoji_u' followed by codepoints expressed in hex standard format and prefix ('emoji_u' followed by codepoints expressed in hex
separated by underscore). If clean, removes the target dir before proceding. separated by underscore). If clean, removes the target dir before proceding.
If either emoji_dir or flag_dir are empty, skips them.""" If either emoji_dir or flags_dir are empty, skips them."""
dst_dir = tool_utils.ensure_dir_exists(dst_dir, clean=clean) dst_dir = tool_utils.ensure_dir_exists(dst_dir, clean=clean)
if not emoji_dir and not flag_dir: if not emoji_dir and not flags_dir:
logging.warning('Nothing to do.') logging.warning('Nothing to do.')
return return

View File

@ -15,6 +15,7 @@
# limitations under the License. # limitations under the License.
"""Generate a glyph name for flag emojis.""" """Generate a glyph name for flag emojis."""
from __future__ import print_function
__author__ = 'roozbeh@google.com (Roozbeh Pournader)' __author__ = 'roozbeh@google.com (Roozbeh Pournader)'
@ -48,8 +49,8 @@ def flag_code_to_glyph_name(flag_code):
def main(): def main():
print ' '.join([ print(' '.join([
flag_code_to_glyph_name(flag_code) for flag_code in sys.argv[1:]]) flag_code_to_glyph_name(flag_code) for flag_code in sys.argv[1:]]))
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@ -17,6 +17,7 @@
"""Quick tool to display count/ids of flag images in a directory named """Quick tool to display count/ids of flag images in a directory named
either using ASCII upper case pairs or the emoji_u+codepoint_sequence either using ASCII upper case pairs or the emoji_u+codepoint_sequence
names.""" names."""
from __future__ import print_function
import argparse import argparse
import re import re
@ -44,7 +45,7 @@ def _flag_names_from_file_names(src):
for f in glob.glob(path.join(src, '*.png')): for f in glob.glob(path.join(src, '*.png')):
m = flag_re.match(path.basename(f)) m = flag_re.match(path.basename(f))
if not m: if not m:
print 'no match' print('no match')
continue continue
flags.add(m.group(1)) flags.add(m.group(1))
return flags return flags
@ -52,14 +53,14 @@ def _flag_names_from_file_names(src):
def _dump_flag_info(names): def _dump_flag_info(names):
prev = None prev = None
print '%d flags' % len(names) print('%d flags' % len(names))
for n in sorted(names): for n in sorted(names):
if n[0] != prev: if n[0] != prev:
if prev: if prev:
print print()
prev = n[0] prev = n[0]
print n, print(n, end=' ')
print print()
def main(): def main():
@ -76,7 +77,7 @@ def main():
names = _flag_names_from_file_names(args.srcdir) names = _flag_names_from_file_names(args.srcdir)
else: else:
names = _flag_names_from_emoji_file_names(args.srcdir) names = _flag_names_from_emoji_file_names(args.srcdir)
print args.srcdir print(args.srcdir)
_dump_flag_info(names) _dump_flag_info(names)

Binary file not shown.

View File

@ -19,6 +19,7 @@
This takes a list of directories containing emoji image files, and This takes a list of directories containing emoji image files, and
builds an html page presenting the images along with their composition builds an html page presenting the images along with their composition
(for sequences) and unicode names (for individual emoji).""" (for sequences) and unicode names (for individual emoji)."""
from __future__ import print_function
import argparse import argparse
import codecs import codecs
@ -109,11 +110,11 @@ def _get_desc(key_tuple, aliases, dir_infos, basepaths):
if cp_key in aliases: if cp_key in aliases:
fp = get_key_filepath(aliases[cp_key]) fp = get_key_filepath(aliases[cp_key])
else: else:
print 'no alias for %s' % unicode_data.seq_to_string(cp_key) print('no alias for %s' % unicode_data.seq_to_string(cp_key))
if not fp: if not fp:
print 'no part for %s in %s' % ( print('no part for %s in %s' % (
unicode_data.seq_to_string(cp_key), unicode_data.seq_to_string(cp_key),
unicode_data.seq_to_string(key_tuple)) unicode_data.seq_to_string(key_tuple)))
return fp return fp
def _get_part(cp): def _get_part(cp):
@ -153,7 +154,7 @@ def _get_name(key_tuple, annotations):
elif key_tuple == (0xfe82b,): elif key_tuple == (0xfe82b,):
seq_name = '(unknown flag PUA codepoint)' seq_name = '(unknown flag PUA codepoint)'
else: else:
print 'no name for %s' % unicode_data.seq_to_string(key_tuple) print('no name for %s' % unicode_data.seq_to_string(key_tuple))
seq_name = '(oops)' seq_name = '(oops)'
return CELL_PREFIX + seq_name return CELL_PREFIX + seq_name
@ -308,8 +309,8 @@ def _get_image_data(image_dir, ext, prefix):
continue continue
result[cps] = filename result[cps] = filename
if fails: if fails:
print >> sys.stderr, 'get_image_data failed (%s, %s, %s):\n %s' % ( print('get_image_data failed (%s, %s, %s):\n %s' % (
image_dir, ext, prefix, '\n '.join(fails)) image_dir, ext, prefix, '\n '.join(fails)), file=sys.stderr)
raise ValueError('get image data failed') raise ValueError('get image data failed')
return result return result
@ -356,9 +357,9 @@ def _add_aliases(keys, aliases):
v_str = unicode_data.seq_to_string(v) v_str = unicode_data.seq_to_string(v)
if k in keys: if k in keys:
msg = '' if v in keys else ' but it\'s not present' msg = '' if v in keys else ' but it\'s not present'
print 'have alias image %s, should use %s%s' % (k_str, v_str, msg) print('have alias image %s, should use %s%s' % (k_str, v_str, msg))
elif v not in keys: elif v not in keys:
print 'can\'t use alias %s, no image matching %s' % (k_str, v_str) print('can\'t use alias %s, no image matching %s' % (k_str, v_str))
to_add = {k for k, v in aliases.iteritems() if k not in keys and v in keys} to_add = {k for k, v in aliases.iteritems() if k not in keys and v in keys}
return keys | to_add return keys | to_add
@ -449,9 +450,9 @@ def _instantiate_template(template, arg_dict):
keyset = set(arg_dict.keys()) keyset = set(arg_dict.keys())
extra_args = keyset - ids extra_args = keyset - ids
if extra_args: if extra_args:
print >> sys.stderr, ( print((
'the following %d args are unused:\n%s' % 'the following %d args are unused:\n%s' %
(len(extra_args), ', '.join(sorted(extra_args)))) (len(extra_args), ', '.join(sorted(extra_args)))), file=sys.stderr)
return string.Template(template).substitute(arg_dict) return string.Template(template).substitute(arg_dict)
@ -605,7 +606,7 @@ def main():
file_parts = path.splitext(args.outfile) file_parts = path.splitext(args.outfile)
if file_parts[1] != '.html': if file_parts[1] != '.html':
args.outfile = file_parts[0] + '.html' args.outfile = file_parts[0] + '.html'
print 'added .html extension to filename:\n%s' % args.outfile print('added .html extension to filename:\n%s' % args.outfile)
if args.annotate: if args.annotate:
annotations = _parse_annotation_file(args.annotate) annotations = _parse_annotation_file(args.annotate)

View File

@ -16,6 +16,7 @@
# limitations under the License. # limitations under the License.
"""Generate name data for emoji resources. Currently in json format.""" """Generate name data for emoji resources. Currently in json format."""
from __future__ import print_function
import argparse import argparse
import collections import collections
@ -273,20 +274,38 @@ def _name_data(seq, seq_file):
def generate_names( def generate_names(
src_dir, dst_dir, skip_limit=20, pretty_print=False, verbose=False): src_dir, dst_dir, skip_limit=20, omit_groups=None, pretty_print=False,
verbose=False):
srcdir = tool_utils.resolve_path(src_dir) srcdir = tool_utils.resolve_path(src_dir)
if not path.isdir(srcdir): if not path.isdir(srcdir):
print >> sys.stderr, '%s is not a directory' % src_dir print('%s is not a directory' % src_dir, file=sys.stderr)
return return
if omit_groups:
unknown_groups = set(omit_groups) - set(unicode_data.get_emoji_groups())
if unknown_groups:
print('did not recognize %d group%s: %s' % (
len(unknown_groups), '' if len(unknown_groups) == 1 else 's',
', '.join('"%s"' % g for g in omit_groups if g in unknown_groups)), file=sys.stderr)
print('valid groups are:\n %s' % (
'\n '.join(g for g in unicode_data.get_emoji_groups())), file=sys.stderr)
return
print('omitting %d group%s: %s' % (
len(omit_groups), '' if len(omit_groups) == 1 else 's',
', '.join('"%s"' % g for g in omit_groups)))
else:
# might be None
print('keeping all groups')
omit_groups = []
# make sure the destination exists # make sure the destination exists
dstdir = tool_utils.ensure_dir_exists( dstdir = tool_utils.ensure_dir_exists(
tool_utils.resolve_path(dst_dir)) tool_utils.resolve_path(dst_dir))
# _get_image_data returns canonical cp sequences # _get_image_data returns canonical cp sequences
print 'src dir:', srcdir print('src dir:', srcdir)
seq_to_file = generate_emoji_html._get_image_data(srcdir, 'png', 'emoji_u') seq_to_file = generate_emoji_html._get_image_data(srcdir, 'png', 'emoji_u')
print 'seq to file has %d sequences' % len(seq_to_file) print('seq to file has %d sequences' % len(seq_to_file))
# Aliases add non-gendered versions using gendered images for the most part. # Aliases add non-gendered versions using gendered images for the most part.
# But when we display the images, we don't distinguish genders in the # But when we display the images, we don't distinguish genders in the
@ -310,9 +329,9 @@ def generate_names(
if unicode_data.is_regional_indicator_seq(seq): if unicode_data.is_regional_indicator_seq(seq):
replace_seq = canonical_aliases[seq] replace_seq = canonical_aliases[seq]
if seq in seq_to_file: if seq in seq_to_file:
print 'warning, alias %s has file %s' % ( print('warning, alias %s has file %s' % (
unicode_data.regional_indicator_seq_to_string(seq), unicode_data.regional_indicator_seq_to_string(seq),
seq_to_file[seq]) seq_to_file[seq]))
continue continue
replace_file = seq_to_file.get(replace_seq) replace_file = seq_to_file.get(replace_seq)
if replace_file: if replace_file:
@ -323,6 +342,8 @@ def generate_names(
last_skipped_group = None last_skipped_group = None
skipcount = 0 skipcount = 0
for group in unicode_data.get_emoji_groups(): for group in unicode_data.get_emoji_groups():
if group in omit_groups:
continue
name_data = [] name_data = []
for seq in unicode_data.get_emoji_in_group(group): for seq in unicode_data.get_emoji_in_group(group):
if seq in excluded: if seq in excluded:
@ -332,11 +353,11 @@ def generate_names(
skipcount += 1 skipcount += 1
if verbose: if verbose:
if group != last_skipped_group: if group != last_skipped_group:
print 'group %s' % group print('group %s' % group)
last_skipped_group = group last_skipped_group = group
print ' %s (%s)' % ( print(' %s (%s)' % (
unicode_data.seq_to_string(seq), unicode_data.seq_to_string(seq),
', '.join(unicode_data.name(cp, 'x') for cp in seq)) ', '.join(unicode_data.name(cp, 'x') for cp in seq)))
if skip_limit >= 0 and skipcount > skip_limit: if skip_limit >= 0 and skipcount > skip_limit:
raise Exception('skipped too many items') raise Exception('skipped too many items')
else: else:
@ -348,7 +369,7 @@ def generate_names(
indent = 2 if pretty_print else None indent = 2 if pretty_print else None
separators = None if pretty_print else (',', ':') separators = None if pretty_print else (',', ':')
json.dump(data, f, indent=indent, separators=separators) json.dump(data, f, indent=indent, separators=separators)
print 'wrote %s' % outfile print('wrote %s' % outfile)
def main(): def main():
@ -368,12 +389,15 @@ def main():
parser.add_argument( parser.add_argument(
'-m', '--missing_limit', help='number of missing images before failure ' '-m', '--missing_limit', help='number of missing images before failure '
'(default 20), use -1 for no limit', metavar='n', default=20) '(default 20), use -1 for no limit', metavar='n', default=20)
parser.add_argument(
'--omit_groups', help='names of groups to omit (default "Misc")',
metavar='name', default=['Misc'], nargs='*')
parser.add_argument( parser.add_argument(
'-v', '--verbose', help='print progress information to stdout', '-v', '--verbose', help='print progress information to stdout',
action='store_true') action='store_true')
args = parser.parse_args() args = parser.parse_args()
generate_names( generate_names(
args.srcdir, args.dstdir, args.missing_limit, args.srcdir, args.dstdir, args.missing_limit, args.omit_groups,
pretty_print=args.pretty_print, verbose=args.verbose) pretty_print=args.pretty_print, verbose=args.verbose)

View File

@ -1,3 +1,4 @@
from __future__ import print_function
import os import os
from os import path from os import path
import subprocess import subprocess
@ -5,7 +6,7 @@ import subprocess
OUTPUT_DIR = '/tmp/placeholder_emoji' OUTPUT_DIR = '/tmp/placeholder_emoji'
def generate_image(name, text): def generate_image(name, text):
print name, text.replace('\n', '_') print(name, text.replace('\n', '_'))
subprocess.check_call( subprocess.check_call(
['convert', '-size', '100x100', 'label:%s' % text, ['convert', '-size', '100x100', 'label:%s' % text,
'%s/%s' % (OUTPUT_DIR, name)]) '%s/%s' % (OUTPUT_DIR, name)])
@ -75,13 +76,13 @@ with open('sequences.txt', 'r') as f:
elif is_flag_sequence(values): elif is_flag_sequence(values):
text = ''.join(regional_to_ascii(cp) for cp in values) text = ''.join(regional_to_ascii(cp) for cp in values)
elif has_color_patch(values): elif has_color_patch(values):
print 'skipping color patch sequence %s' % seq print('skipping color patch sequence %s' % seq)
elif is_keycap_sequence(values): elif is_keycap_sequence(values):
text = get_keycap_text(values) text = get_keycap_text(values)
else: else:
text = get_combining_text(values) text = get_combining_text(values)
if not text: if not text:
print 'missing %s' % seq print('missing %s' % seq)
if text: if text:
if len(text) > 3: if len(text) > 3:

View File

@ -36,12 +36,19 @@ from nototools import unicode_data
logger = logging.getLogger('emoji_thumbnails') logger = logging.getLogger('emoji_thumbnails')
def create_thumbnail(src_path, dst_path): def create_thumbnail(src_path, dst_path, crop):
# uses imagemagik # Uses imagemagik
# we need imagex exactly 72x72 in size, with transparent background # We need images exactly 72x72 in size, with transparent background.
subprocess.check_call([ # Remove 4-pixel LR margins from 136x128 source images if we crop.
if crop:
cmd = [
'convert', src_path, '-crop', '128x128+4+0!', '-thumbnail', '72x72',
'PNG32:' + dst_path]
else:
cmd = [
'convert', '-thumbnail', '72x72', '-gravity', 'center', '-background', 'convert', '-thumbnail', '72x72', '-gravity', 'center', '-background',
'none', '-extent', '72x72', src_path, dst_path]) 'none', '-extent', '72x72', src_path, 'PNG32:' + dst_path]
subprocess.check_call(cmd)
def get_inv_aliases(): def get_inv_aliases():
@ -77,14 +84,16 @@ def sequence_to_filename(seq, prefix, suffix):
return ''.join((prefix, unicode_data.seq_to_string(seq), suffix)) return ''.join((prefix, unicode_data.seq_to_string(seq), suffix))
def create_thumbnails_and_aliases(src_dir, dst_dir, dst_prefix): def create_thumbnails_and_aliases(src_dir, dst_dir, crop, dst_prefix):
"""Creates thumbnails in dst_dir based on sources in src.dir, using """Creates thumbnails in dst_dir based on sources in src.dir, using
dst_prefix. Assumes the source prefix is 'emoji_u' and the common suffix dst_prefix. Assumes the source prefix is 'emoji_u' and the common suffix
is '.png'.""" is '.png'."""
src_dir = tool_utils.resolve_path(src_dir)
if not path.isdir(src_dir): if not path.isdir(src_dir):
raise ValueError('"%s" is not a directory') raise ValueError('"%s" is not a directory')
dst_dir = tool_utils.ensure_dir_exists(dst_dir)
dst_dir = tool_utils.ensure_dir_exists(tool_utils.resolve_path(dst_dir))
src_prefix = 'emoji_u' src_prefix = 'emoji_u'
suffix = '.png' suffix = '.png'
@ -104,8 +113,9 @@ def create_thumbnails_and_aliases(src_dir, dst_dir, dst_prefix):
dst_file = sequence_to_filename(seq, dst_prefix, suffix) dst_file = sequence_to_filename(seq, dst_prefix, suffix)
dst_path = path.join(dst_dir, dst_file) dst_path = path.join(dst_dir, dst_file)
create_thumbnail(src_path, dst_path) create_thumbnail(src_path, dst_path, crop)
logger.info('wrote thumbnail: %s' % dst_file) logger.info('wrote thumbnail%s: %s' % (
' with crop' if crop else '', dst_file))
for alias_seq in inv_aliases.get(seq, ()): for alias_seq in inv_aliases.get(seq, ()):
alias_file = sequence_to_filename(alias_seq, dst_prefix, suffix) alias_file = sequence_to_filename(alias_seq, dst_prefix, suffix)
@ -115,15 +125,22 @@ def create_thumbnails_and_aliases(src_dir, dst_dir, dst_prefix):
def main(): def main():
SRC_DEFAULT = '[emoji]/build/compressed_pngs'
PREFIX_DEFAULT = 'android_'
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument( parser.add_argument(
'-s', '--src_dir', help='source images', metavar='dir', required=True) '-s', '--src_dir', help='source images (default \'%s\')' % SRC_DEFAULT,
default=SRC_DEFAULT, metavar='dir')
parser.add_argument( parser.add_argument(
'-d', '--dst_dir', help='destination directory', metavar='dir', '-d', '--dst_dir', help='destination directory', metavar='dir',
required=True) required=True)
parser.add_argument( parser.add_argument(
'-p', '--prefix', help='prefix for thumbnail', metavar='str', '-p', '--prefix', help='prefix for thumbnail (default \'%s\')' %
default='android_') PREFIX_DEFAULT, default=PREFIX_DEFAULT, metavar='str')
parser.add_argument(
'-c', '--crop', help='crop images (will automatically crop if '
'src dir is the default)', action='store_true')
parser.add_argument( parser.add_argument(
'-v', '--verbose', help='write log output', metavar='level', '-v', '--verbose', help='write log output', metavar='level',
choices='warning info debug'.split(), const='info', choices='warning info debug'.split(), const='info',
@ -133,8 +150,9 @@ def main():
if args.verbose is not None: if args.verbose is not None:
logging.basicConfig(level=getattr(logging, args.verbose.upper())) logging.basicConfig(level=getattr(logging, args.verbose.upper()))
crop = args.crop or (args.src_dir == SRC_DEFAULT)
create_thumbnails_and_aliases( create_thumbnails_and_aliases(
args.src_dir, args.dst_dir, args.prefix) args.src_dir, args.dst_dir, crop, args.prefix)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -15,6 +15,7 @@
# #
# Google Author(s): Doug Felt # Google Author(s): Doug Felt
from __future__ import print_function
import argparse import argparse
import os import os
import os.path import os.path
@ -120,9 +121,9 @@ View using Firefox&nbsp;26 and later.
text_parts.append(text) text_parts.append(text)
if verbosity and glyph and not found_initial_glyph: if verbosity and glyph and not found_initial_glyph:
print "Did not find glyph '%s', using initial glyph '%s'" % (glyph, initial_glyph_str) print("Did not find glyph '%s', using initial glyph '%s'" % (glyph, initial_glyph_str))
elif verbosity > 1 and not glyph: elif verbosity > 1 and not glyph:
print "Using initial glyph '%s'" % initial_glyph_str print("Using initial glyph '%s'" % initial_glyph_str)
lines = [header % font_name] lines = [header % font_name]
lines.append(body_head % {'font':font_name, 'glyph':initial_glyph_str, lines.append(body_head % {'font':font_name, 'glyph':initial_glyph_str,
@ -133,28 +134,28 @@ View using Firefox&nbsp;26 and later.
with open(html_name, 'w') as fp: with open(html_name, 'w') as fp:
fp.write(output) fp.write(output)
if verbosity: if verbosity:
print 'Wrote ' + html_name print('Wrote ' + html_name)
def do_generate_fonts(template_file, font_basename, pairs, reuse=0, verbosity=1): def do_generate_fonts(template_file, font_basename, pairs, reuse=0, verbosity=1):
out_woff = font_basename + '.woff' out_woff = font_basename + '.woff'
if reuse > 1 and os.path.isfile(out_woff) and os.access(out_woff, os.R_OK): if reuse > 1 and os.path.isfile(out_woff) and os.access(out_woff, os.R_OK):
if verbosity: if verbosity:
print 'Reusing ' + out_woff print('Reusing ' + out_woff)
return return
out_ttx = font_basename + '.ttx' out_ttx = font_basename + '.ttx'
if reuse == 0: if reuse == 0:
add_svg_glyphs.add_image_glyphs(template_file, out_ttx, pairs, verbosity=verbosity) add_svg_glyphs.add_image_glyphs(template_file, out_ttx, pairs, verbosity=verbosity)
elif verbosity: elif verbosity:
print 'Reusing ' + out_ttx print('Reusing ' + out_ttx)
quiet=verbosity < 2 quiet=verbosity < 2
font = ttx.TTFont(flavor='woff', quiet=quiet) font = ttx.TTFont(flavor='woff', quiet=quiet)
font.importXML(out_ttx, quiet=quiet) font.importXML(out_ttx, quiet=quiet)
font.save(out_woff) font.save(out_woff)
if verbosity: if verbosity:
print 'Wrote ' + out_woff print('Wrote ' + out_woff)
def main(argv): def main(argv):
@ -193,7 +194,7 @@ def main(argv):
if not out_basename: if not out_basename:
out_basename = args.template_file.split('.')[0] # exclude e.g. '.tmpl.ttx' out_basename = args.template_file.split('.')[0] # exclude e.g. '.tmpl.ttx'
if args.v: if args.v:
print "Output basename is %s." % out_basename print("Output basename is %s." % out_basename)
do_generate_fonts(args.template_file, out_basename, pairs, reuse=args.reuse_font, verbosity=args.v) do_generate_fonts(args.template_file, out_basename, pairs, reuse=args.reuse_font, verbosity=args.v)
do_generate_test_html(out_basename, pairs, glyph=args.glyph, verbosity=args.v) do_generate_test_html(out_basename, pairs, glyph=args.glyph, verbosity=args.v)

View File

@ -16,6 +16,7 @@
"""Create a copy of the emoji images that instantiates aliases, etc. as """Create a copy of the emoji images that instantiates aliases, etc. as
symlinks.""" symlinks."""
from __future__ import print_function
import argparse import argparse
import glob import glob
@ -68,10 +69,10 @@ def _alias_people(code_strings, dst):
if src[1:].lower() in code_strings: if src[1:].lower() in code_strings:
src_name = 'emoji_%s.png' % src.lower() src_name = 'emoji_%s.png' % src.lower()
ali_name = 'emoji_u%s.png' % ali.lower() ali_name = 'emoji_u%s.png' % ali.lower()
print 'creating symlink %s -> %s' % (ali_name, src_name) print('creating symlink %s -> %s' % (ali_name, src_name))
os.symlink(path.join(dst, src_name), path.join(dst, ali_name)) os.symlink(path.join(dst, src_name), path.join(dst, ali_name))
else: else:
print >> os.stderr, 'people image %s not found' % src print('people image %s not found' % src, file=os.stderr)
def _alias_flags(code_strings, dst): def _alias_flags(code_strings, dst):
@ -80,27 +81,27 @@ def _alias_flags(code_strings, dst):
if src_str in code_strings: if src_str in code_strings:
src_name = 'emoji_u%s.png' % src_str src_name = 'emoji_u%s.png' % src_str
ali_name = 'emoji_u%s.png' % _flag_str(ali) ali_name = 'emoji_u%s.png' % _flag_str(ali)
print 'creating symlink %s (%s) -> %s (%s)' % (ali_name, ali, src_name, src) print('creating symlink %s (%s) -> %s (%s)' % (ali_name, ali, src_name, src))
os.symlink(path.join(dst, src_name), path.join(dst, ali_name)) os.symlink(path.join(dst, src_name), path.join(dst, ali_name))
else: else:
print >> os.stderr, 'flag image %s (%s) not found' % (src_name, src) print('flag image %s (%s) not found' % (src_name, src), file=os.stderr)
def _alias_omitted_flags(code_strings, dst): def _alias_omitted_flags(code_strings, dst):
UNKNOWN_FLAG = 'fe82b' UNKNOWN_FLAG = 'fe82b'
if UNKNOWN_FLAG not in code_strings: if UNKNOWN_FLAG not in code_strings:
print >> os.stderr, 'unknown flag missing' print('unknown flag missing', file=os.stderr)
return return
dst_name = 'emoji_u%s.png' % UNKNOWN_FLAG dst_name = 'emoji_u%s.png' % UNKNOWN_FLAG
dst_path = path.join(dst, dst_name) dst_path = path.join(dst, dst_name)
for ali in sorted(OMITTED_FLAGS): for ali in sorted(OMITTED_FLAGS):
ali_str = _flag_str(ali) ali_str = _flag_str(ali)
if ali_str in code_strings: if ali_str in code_strings:
print >> os.stderr, 'omitted flag %s has image %s' % (ali, ali_str) print('omitted flag %s has image %s' % (ali, ali_str), file=os.stderr)
continue continue
ali_name = 'emoji_u%s.png' % ali_str ali_name = 'emoji_u%s.png' % ali_str
print 'creating symlink %s (%s) -> unknown_flag (%s)' % ( print('creating symlink %s (%s) -> unknown_flag (%s)' % (
ali_str, ali, dst_name) ali_str, ali, dst_name))
os.symlink(dst_path, path.join(dst, ali_name)) os.symlink(dst_path, path.join(dst, ali_name))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 945 B

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
png/128/emoji_u002a.png 100755 → 100644

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
png/128/emoji_u002a_20e3.png 100755 → 100644

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 B

After

Width:  |  Height:  |  Size: 943 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 815 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 895 B

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 884 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 569 B

After

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 530 B

After

Width:  |  Height:  |  Size: 479 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 554 B

After

Width:  |  Height:  |  Size: 494 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 432 B

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 999 B

After

Width:  |  Height:  |  Size: 942 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 502 B

After

Width:  |  Height:  |  Size: 458 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1013 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1008 B

After

Width:  |  Height:  |  Size: 980 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 490 B

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 859 B

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Some files were not shown because too many files have changed in this diff Show More