generate-expected-outputs.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #!/usr/bin/env python3
  2. # Pre-generates the expected output subset files (via fonttools) for
  3. # specified subset test suite(s).
  4. import os
  5. import sys
  6. import shutil
  7. import io
  8. import re
  9. import tempfile
  10. from difflib import unified_diff
  11. from fontTools.ttLib import TTFont
  12. from subprocess import check_call
  13. from subset_test_suite import SubsetTestSuite
  14. def usage():
  15. print("Usage: generate-expected-outputs.py hb-subset <test suite file> ...")
  16. def strip_check_sum (ttx_string):
  17. return re.sub ('checkSumAdjustment value=["]0x([0-9a-fA-F])+["]',
  18. 'checkSumAdjustment value="0x00000000"',
  19. ttx_string, count=1)
  20. def generate_expected_output(input_file, unicodes, profile_flags, instance_flags, iup_optimize, output_directory, font_name, no_fonttools):
  21. input_path = input_file
  22. if not no_fonttools and instance_flags:
  23. instance_path = os.path.join(tempfile.mkdtemp (), font_name)
  24. args = ["fonttools", "varLib.instancer",
  25. "--no-overlap-flag",
  26. "--no-recalc-timestamp"]
  27. if not iup_optimize:
  28. args.extend(["--no-optimize",])
  29. args.extend(["--output=%s" % instance_path,
  30. input_file])
  31. args.extend(instance_flags)
  32. check_call(args)
  33. input_path = instance_path
  34. fonttools_path = os.path.join(tempfile.mkdtemp (), font_name)
  35. args = ["fonttools", "subset", input_path]
  36. if instance_flags:
  37. args.extend(["--recalc-bounds", "--recalc-average-width"])
  38. args.extend(["--drop-tables+=DSIG,BASE",
  39. "--drop-tables-=sbix",
  40. "--no-harfbuzz-repacker", # disable harfbuzz repacker so we aren't comparing to ourself.
  41. "--output-file=%s" % fonttools_path])
  42. if unicodes != "":
  43. args.extend(["--unicodes=%s" % unicodes,])
  44. # --gid-map is unsupported in fonttools so don't send it. Tests using
  45. # it are crafted to work without fonttools knowing about the flag.
  46. args.extend([f for f in profile_flags if not f.startswith("--gid-map")])
  47. # Harfbuzz doesn't support pruning codepage ranges, so disable it in fonttools.
  48. args.extend(["--no-prune-codepage-ranges"])
  49. if not no_fonttools:
  50. check_call(args)
  51. with io.StringIO () as fp:
  52. with TTFont (fonttools_path) as font:
  53. font.saveXML (fp)
  54. fonttools_ttx = strip_check_sum (fp.getvalue ())
  55. harfbuzz_path = os.path.join(tempfile.mkdtemp (), font_name)
  56. args = [
  57. hb_subset,
  58. "--font-file=" + input_file,
  59. "--output-file=" + harfbuzz_path,
  60. "--drop-tables+=DSIG,BASE",
  61. "--drop-tables-=sbix"]
  62. if unicodes != "":
  63. args.extend(["--unicodes=%s" % unicodes,])
  64. args.extend(profile_flags)
  65. if instance_flags:
  66. args.extend(["--instance=%s" % ','.join(instance_flags)])
  67. if iup_optimize:
  68. args.extend(["--optimize",])
  69. check_call(args)
  70. with io.StringIO () as fp:
  71. with TTFont (harfbuzz_path) as font:
  72. font.saveXML (fp)
  73. harfbuzz_ttx = strip_check_sum (fp.getvalue ())
  74. if not no_fonttools and harfbuzz_ttx != fonttools_ttx:
  75. for line in unified_diff (fonttools_ttx.splitlines (1), harfbuzz_ttx.splitlines (1), fonttools_path, harfbuzz_path):
  76. sys.stdout.write (line)
  77. sys.stdout.flush ()
  78. raise Exception ('ttx for fonttools and harfbuzz does not match.')
  79. output_path = os.path.join(output_directory, font_name)
  80. shutil.copy(harfbuzz_path, output_path)
  81. args = sys.argv[1:]
  82. if not args:
  83. usage()
  84. hb_subset, args = args[0], args[1:]
  85. if not args:
  86. usage()
  87. for path in args:
  88. with open(path, mode="r", encoding="utf-8") as f:
  89. test_suite = SubsetTestSuite(path, f.read())
  90. output_directory = test_suite.get_output_directory()
  91. print("Generating output files for %s" % output_directory)
  92. for test in test_suite.tests():
  93. unicodes = test.unicodes()
  94. font_name = test.get_font_name()
  95. no_fonttools = ("no_fonttools" in test.options)
  96. print("Creating subset %s/%s" % (output_directory, font_name))
  97. generate_expected_output(test.font_path, unicodes, test.get_profile_flags(),
  98. test.get_instance_flags(), test.iup_optimize, output_directory, font_name, no_fonttools=no_fonttools)