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