Merge pull request #267 from mike-fabian/python3-port

Python3 port
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a5cc017
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+__pycache__/
+*.pyc
+waveflag
+build/
diff --git a/Makefile b/Makefile
index e8d53b5..148ca66 100644
--- a/Makefile
+++ b/Makefile
@@ -19,6 +19,7 @@
 LDFLAGS = -lm `pkg-config --libs cairo`
 
 PNGQUANT = pngquant
+PYTHON = python3
 PNGQUANTFLAGS = --speed 1 --skip-if-larger --quality 85-95 --force
 BODY_DIMENSIONS = 136x128
 IMOPS := -size $(BODY_DIMENSIONS) canvas:none -compose copy -gravity center
@@ -88,7 +89,7 @@
 FLAG_FILES = $(addprefix $(FLAGS_DIR)/, $(FLAG_NAMES))
 RESIZED_FLAG_FILES = $(addprefix $(RESIZED_FLAGS_DIR)/, $(FLAG_NAMES))
 
-FLAG_GLYPH_NAMES = $(shell ./flag_glyph_name.py $(FLAGS))
+FLAG_GLYPH_NAMES = $(shell $(PYTHON) flag_glyph_name.py $(FLAGS))
 RENAMED_FLAG_NAMES = $(FLAG_GLYPH_NAMES:%=emoji_%.png)
 RENAMED_FLAG_FILES = $(addprefix $(RENAMED_FLAGS_DIR)/, $(RENAMED_FLAG_NAMES))
 
@@ -207,7 +208,7 @@
 # Run make without -j if this happens.
 
 %.ttx: %.ttx.tmpl $(ADD_GLYPHS) $(ALL_COMPRESSED_FILES)
-	@python $(ADD_GLYPHS) -f "$<" -o "$@" -d "$(COMPRESSED_DIR)" $(ADD_GLYPHS_FLAGS)
+	@$(PYTHON) $(ADD_GLYPHS) -f "$<" -o "$@" -d "$(COMPRESSED_DIR)" $(ADD_GLYPHS_FLAGS)
 
 %.ttf: %.ttx
 	@rm -f "$@"
@@ -215,8 +216,8 @@
 
 $(EMOJI).ttf: $(EMOJI).tmpl.ttf $(EMOJI_BUILDER) $(PUA_ADDER) \
 	$(ALL_COMPRESSED_FILES) | check_vs_adder
-	@python $(EMOJI_BUILDER) $(SMALL_METRICS) -V $< "$@" "$(COMPRESSED_DIR)/emoji_u"
-	@python $(PUA_ADDER) "$@" "$@-with-pua"
+	@$(PYTHON) $(EMOJI_BUILDER) $(SMALL_METRICS) -V $< "$@" "$(COMPRESSED_DIR)/emoji_u"
+	@$(PYTHON) $(PUA_ADDER) "$@" "$@-with-pua"
 	@$(VS_ADDER) -vs 2640 2642 2695 --dstdir '.' -o "$@-with-pua-varsel" "$@-with-pua"
 	@mv "$@-with-pua-varsel" "$@"
 	@rm "$@-with-pua"
diff --git a/add_aliases.py b/add_aliases.py
index 90aed7d..b943f5d 100755
--- a/add_aliases.py
+++ b/add_aliases.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright 2017 Google Inc. All rights reserved.
 #
diff --git a/add_emoji_gsub.py b/add_emoji_gsub.py
index bae73cb..9f578a3 100755
--- a/add_emoji_gsub.py
+++ b/add_emoji_gsub.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright 2014 Google Inc. All rights reserved.
 #
diff --git a/add_glyphs.py b/add_glyphs.py
index a12b440..7104f45 100644
--- a/add_glyphs.py
+++ b/add_glyphs.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 """Extend a ttx file with additional data.
 
@@ -66,7 +66,7 @@
 
 
 def remap_values(seq_to_file, map_fn):
-  return {k: map_fn(v) for k, v in seq_to_file.iteritems()}
+  return {k: map_fn(v) for k, v in seq_to_file.items()}
 
 
 def get_png_file_to_advance_mapper(lineheight):
@@ -280,7 +280,7 @@
     return
 
   rtl_seq_to_target_name = {
-      get_rtl_seq(seq): name for seq, name in seq_to_target_name.iteritems()}
+      get_rtl_seq(seq): name for seq, name in seq_to_target_name.items()}
   seq_to_target_name.update(rtl_seq_to_target_name)
   # sequences that don't have rtl variants get mapped to the empty sequence,
   # delete it.
@@ -289,7 +289,7 @@
 
   # organize by first codepoint in sequence
   keyed_ligatures = collections.defaultdict(list)
-  for t in seq_to_target_name.iteritems():
+  for t in seq_to_target_name.items():
     first_cp = t[0][0]
     keyed_ligatures[first_cp].append(t)
 
@@ -339,7 +339,7 @@
   source is a key in the dictionary, we can delete it.  This updates the
   dictionary and returns the usable aliases."""
   usable_aliases = {}
-  for k, v in aliases.iteritems():
+  for k, v in aliases.items():
     if v in seq_dict:
       usable_aliases[k] = v
       if k in seq_dict:
diff --git a/add_svg_glyphs.py b/add_svg_glyphs.py
index 0f7a6b3..6309157 100755
--- a/add_svg_glyphs.py
+++ b/add_svg_glyphs.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright 2015 Google, Inc. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/check_emoji_sequences.py b/check_emoji_sequences.py
index f29bbe9..dff1b86 100755
--- a/check_emoji_sequences.py
+++ b/check_emoji_sequences.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright 2016 Google Inc. All rights reserved.
 #
diff --git a/collect_emoji_svg.py b/collect_emoji_svg.py
index ea39cbd..9d2ba64 100755
--- a/collect_emoji_svg.py
+++ b/collect_emoji_svg.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright 2015 Google, Inc. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/flag_glyph_name.py b/flag_glyph_name.py
index 50c266b..e5ce40c 100755
--- a/flag_glyph_name.py
+++ b/flag_glyph_name.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright 2014 Google Inc. All rights reserved.
 #
diff --git a/flag_info.py b/flag_info.py
index 233243f..3dbd63f 100755
--- a/flag_info.py
+++ b/flag_info.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 #
 # Copyright 2016 Google Inc. All rights reserved.
 #
diff --git a/gen_version.py b/gen_version.py
index 749f12e..48581a8 100755
--- a/gen_version.py
+++ b/gen_version.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright 2015 Google Inc. All rights reserved.
 #
diff --git a/generate_emoji_html.py b/generate_emoji_html.py
index 8e0d56c..09fa8ed 100755
--- a/generate_emoji_html.py
+++ b/generate_emoji_html.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright 2016 Google Inc. All rights reserved.
 #
diff --git a/generate_emoji_name_data.py b/generate_emoji_name_data.py
index b228058..9a72621 100755
--- a/generate_emoji_name_data.py
+++ b/generate_emoji_name_data.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-#
 #
 # Copyright 2015 Google Inc. All rights reserved.
diff --git a/generate_emoji_thumbnails.py b/generate_emoji_thumbnails.py
index e67da53..5f70351 100755
--- a/generate_emoji_thumbnails.py
+++ b/generate_emoji_thumbnails.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright 2017 Google Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/generate_test_html.py b/generate_test_html.py
index 21ab1c6..e45108c 100755
--- a/generate_test_html.py
+++ b/generate_test_html.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright 2015 Google, Inc. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/map_pua_emoji.py b/map_pua_emoji.py
index aac031c..bd8e102 100644
--- a/map_pua_emoji.py
+++ b/map_pua_emoji.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright 2014 Google Inc. All rights reserved.
 #
@@ -19,6 +19,7 @@
 __author__ = 'roozbeh@google.com (Roozbeh Pournader)'
 
 import sys
+import itertools
 
 from fontTools import ttLib
 
@@ -53,8 +54,9 @@
     """Add PUA characters to the cmap of the first font and save as second."""
     font = ttLib.TTFont(source_file)
     cmap = font_data.get_cmap(font)
-    for pua, (ch1, ch2) in (add_emoji_gsub.EMOJI_KEYCAPS.items()
-                            + add_emoji_gsub.EMOJI_FLAGS.items()):
+    for pua, (ch1, ch2) in itertools.chain(
+        add_emoji_gsub.EMOJI_KEYCAPS.items(), add_emoji_gsub.EMOJI_FLAGS.items()
+    ):
         if pua not in cmap:
             glyph_name = get_glyph_name_from_gsub([ch1, ch2], font)
             if glyph_name is not None:
diff --git a/materialize_emoji_images.py b/materialize_emoji_images.py
index d8a8b0e..83e3fdd 100755
--- a/materialize_emoji_images.py
+++ b/materialize_emoji_images.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright 2016 Google Inc. All rights reserved.
 #
diff --git a/strip_vs_from_filenames.py b/strip_vs_from_filenames.py
index f27cb3c..f0f7422 100755
--- a/strip_vs_from_filenames.py
+++ b/strip_vs_from_filenames.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright 2017 Google Inc. All rights reserved.
 #
diff --git a/svg_cleaner.py b/svg_cleaner.py
index e968d2f..40d3827 100755
--- a/svg_cleaner.py
+++ b/svg_cleaner.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright 2015 Google, Inc. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/third_party/color_emoji/emoji_builder.py b/third_party/color_emoji/emoji_builder.py
index 4157807..61a3a39 100644
--- a/third_party/color_emoji/emoji_builder.py
+++ b/third_party/color_emoji/emoji_builder.py
@@ -19,13 +19,19 @@
 
 
 from __future__ import print_function
-import sys, struct, StringIO
+import sys, struct
 from png import PNG
 import os
 from os import path
 
 from nototools import font_data
 
+
+try:
+	unichr  # py2
+except NameError:
+	unichr = chr  # py3
+
 def get_glyph_name_from_gsub (string, font, cmap_dict):
 	ligatures = font['GSUB'].table.LookupList.Lookup[0].SubTable[0].ligatures
 	first_glyph = cmap_dict[ord (string[0])]
@@ -112,9 +118,9 @@
 		line_height = (ascent + descent) * y_ppem / float (upem)
 		line_ascent = ascent * y_ppem / float (upem)
 		y_bearing = int (round (line_ascent - .5 * (line_height - height)))
-                # fudge y_bearing if calculations are a bit off
-                if y_bearing == 128:
-                  y_bearing = 127
+		# fudge y_bearing if calculations are a bit off
+		if y_bearing == 128:
+			y_bearing = 127
 		advance = width
 
 		vert_x_bearing = - width / 2
@@ -133,22 +139,22 @@
 		# CHAR	vertBearingX
 		# CHAR	vertBearingY
 		# BYTE	vertAdvance
-                try:
-                  if big_metrics:
-                        self.write (struct.pack ("BBbbBbbB",
+		try:
+		  if big_metrics:
+		        self.write (struct.pack ("BBbbBbbB",
 					 height, width,
 					 x_bearing, y_bearing,
 					 advance,
 					 vert_x_bearing, vert_y_bearing,
 					 vert_advance))
-                  else:
-                        self.write (struct.pack ("BBbbB",
+		  else:
+		        self.write (struct.pack ("BBbbB",
 					 height, width,
 					 x_bearing, y_bearing,
 					 advance))
-                except Exception as e:
-                  raise ValueError("%s, h: %d w: %d x: %d y: %d %d a:" % (
-                      e, height, width, x_bearing, y_bearing, advance))
+		except Exception as e:
+		  raise ValueError("%s, h: %d w: %d x: %d y: %d %d a:" % (
+		      e, height, width, x_bearing, y_bearing, advance))
 
 	def write_format1 (self, png):
 
@@ -179,12 +185,12 @@
 				self.write (pixel)
 			offset += stride
 
-	png_allowed_chunks =  ["IHDR", "PLTE", "tRNS", "sRGB", "IDAT", "IEND"]
+	png_allowed_chunks =  [b"IHDR", b"PLTE", b"tRNS", b"sRGB", b"IDAT", b"IEND"]
 
 	def write_format17 (self, png):
                 self.write_format17or18(png, False)
 
-        def write_format18 (self, png):
+	def write_format18 (self, png):
                 self.write_format17or18(png, True)
 
 	def write_format17or18 (self, png, big_metrics):
@@ -202,7 +208,7 @@
 
 	def image_write_func (self, image_format):
 		if image_format == 1: return self.write_format1
-                if image_format == 17: return self.write_format17
+		if image_format == 17: return self.write_format17
 		if image_format == 18: return self.write_format18
 		return None
 
@@ -441,7 +447,7 @@
 
 	def add_font_table (font, tag, data):
 		tab = ttLib.tables.DefaultTable.DefaultTable (tag)
-		tab.data = str(data)
+		tab.data = data
 		font[tag] = tab
 
 	def drop_outline_tables (font):
@@ -478,7 +484,7 @@
 	eblc.write_header ()
 	eblc.start_strikes (len (img_prefixes))
 
-        def is_vs(cp):
+	def is_vs(cp):
                 return cp >= 0xfe00 and cp <= 0xfe0f
 
 	for img_prefix in img_prefixes:
@@ -491,13 +497,13 @@
 			codes = img_file[len (img_prefix):-4]
 			if "_" in codes:
 				pieces = codes.split ("_")
-                                cps = [int(code, 16) for code in pieces]
-				uchars = "".join ([unichr(cp) for cp in cps if not is_vs(cp)])
+				cps = [int(code, 16) for code in pieces]
+				uchars = "".join (unichr(cp) for cp in cps if not is_vs(cp))
 			else:
-                                cp = int(codes, 16)
-                                if is_vs(cp):
-                                        print("ignoring unexpected vs input %04x" % cp)
-                                        continue
+				cp = int(codes, 16)
+				if is_vs(cp):
+				        print("ignoring unexpected vs input %04x" % cp)
+				        continue
 				uchars = unichr(cp)
 			img_files[uchars] = img_file
 		if not img_files:
@@ -561,8 +567,7 @@
         # hack removal of cmap pua entry for unknown flag glyph.  If we try to
         # remove it earlier, getGlyphID dies.  Need to restructure all of this
         # code.
-        font_data.delete_from_cmap(font, [0xfe82b])
-
+	font_data.delete_from_cmap(font, [0xfe82b])
 	font.save (out_file)
 	print("Output font '%s' generated." % out_file)
 
diff --git a/third_party/color_emoji/png.py b/third_party/color_emoji/png.py
index 20f849a..6e74500 100644
--- a/third_party/color_emoji/png.py
+++ b/third_party/color_emoji/png.py
@@ -17,7 +17,15 @@
 # Google Author(s): Behdad Esfahbod
 #
 
-import struct, StringIO
+import struct
+import sys
+from io import BytesIO
+
+
+try:
+	basestring  # py2
+except NameError:
+	basestring = str  # py3
 
 
 class PNG:
@@ -55,7 +63,8 @@
 		return PNG.signature
 
 	def read_chunk (self):
-		length = struct.unpack (">I", self.f.read (4))[0]
+		buf = self.f.read (4)
+		length = struct.unpack (">I", buf)[0]
 		chunk_type = self.f.read (4)
 		chunk_data = self.f.read (length)
 		if len (chunk_data) != length:
@@ -67,7 +76,7 @@
 
 	def read_IHDR (self):
 		(chunk_type, chunk_data, crc) = self.read_chunk ()
-		if chunk_type != "IHDR":
+		if chunk_type != b"IHDR":
 			raise PNG.BadChunk
 		#  Width:              4 bytes
 		#  Height:             4 bytes
@@ -93,7 +102,7 @@
 
 	def filter_chunks (self, chunks):
 		self.seek (0);
-		out = StringIO.StringIO ()
+		out = BytesIO ()
 		out.write (self.read_signature ())
 		while True:
 			chunk_type, chunk_data, crc = self.read_chunk ()
@@ -102,6 +111,6 @@
 				out.write (chunk_type)
 				out.write (chunk_data)
 				out.write (crc)
-			if chunk_type == "IEND":
+			if chunk_type == b"IEND":
 				break
 		return PNG (out)