# -*- coding: utf-8 -*- import argparse import codecs import json import re import subprocess import unittest import yappi __doc__ = """ Glyph names validator. This tool uses HarfBuzz shaper to get the glyph sequence from the input text. Also predict the glyph sequence based on Unicode values of input text. """ class GlyphNameTests(unittest.TestCase): pass def _get_args(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('test_file', help='path to test file') parser.add_argument('font_file', help='Path to font file') parser.add_argument('-p', '--glyph-prefix', help='glyph prefix used in font', default='uni') return parser.parse_args() def exec_cmd(cmd, env=None): """ Executes the shell command and returns (rc, out, error) """ p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, close_fds=True) (out, err) = p.communicate() return (p.returncode, out, err) def get_glyphseq_from_unicode(txt): """ Hex Code of each char can be extacted using hex(ord( --text --output-format=json And removes all suffix in glyph name(like .abvs, .alt etc) """ cmd = ["hb-shape", font_path, "--text", txt, "--output-format=json"] rc, out, err = exec_cmd(cmd) glyphs = [] if rc == 0: data = json.loads(out) for d in data: glyphs.append(d["g"]) g_list = [] # Ignore any suffix in glyph name for g in glyphs: g = g.replace(args.glyph_prefix, "") g_list.append(re.sub("\..+", "", g)) return "_".join(g_list) def test_generator(line_num, line, font_path): """ Returns a test case lambda func """ expected = get_glyphseq_from_unicode(line.strip()) actual = get_glyphseq_from_font(line, font_path) return lambda self: self.assertEqual(expected, actual, 'LINE %s: %s != %s' % (line_num, expected, actual)) def validate_glyph_names(font_path, txt_file): """ Reads the input test file line by line and adds a test to GlyphNameTests class. each line from input text will become a testcase """ with codecs.open(txt_file, "r", "utf-8") as f: l = 1 for line in f: func = test_generator(l, line, font_path) setattr(GlyphNameTests, "test_l%s" % l, func) l += 1 runner = unittest.TextTestRunner(verbosity=2) itersuite = unittest.TestLoader().loadTestsFromTestCase(GlyphNameTests) runner.run(itersuite) if __name__ == "__main__": yappi.start() args = _get_args() validate_glyph_names(args.font_file, args.test_file) yappi.print_stats()