def test_ttcompile_ttf_to_woff2(tmpdir): inttx = os.path.join("Tests", "ttx", "data", "TestTTF.ttx") outwoff2 = tmpdir.join("TestTTF.woff2") options = ttx.Options([], 1) options.flavor = "woff2" ttx.ttCompile(inttx, str(outwoff2), options) # confirm that font was built assert outwoff2.check(file=True) # confirm that it is valid TTF file, can instantiate a TTFont, has expected OpenType tables ttf = TTFont(str(outwoff2)) # DSIG should not be included from original ttx as per woff2 spec (https://dev.w3.org/webfonts/WOFF2/spec/) assert "DSIG" not in ttf expected_tables = ( "head", "hhea", "maxp", "OS/2", "name", "cmap", "hmtx", "fpgm", "prep", "cvt ", "loca", "glyf", "post", "gasp", ) for table in expected_tables: assert table in ttf
def test_ttcompile_timestamp_calcs(inpath, outpath1, outpath2, tmpdir): inttx = os.path.join("Tests", "ttx", "data", inpath) outttf1 = tmpdir.join(outpath1) outttf2 = tmpdir.join(outpath2) options = ttx.Options([], 1) # build with default options = do not recalculate timestamp ttx.ttCompile(inttx, str(outttf1), options) # confirm that font was built assert outttf1.check(file=True) # confirm that timestamp is same as modified time on ttx file mtime = os.path.getmtime(inttx) epochtime = timestampSinceEpoch(mtime) ttf = TTFont(str(outttf1)) assert ttf["head"].modified == epochtime # reset options to recalculate the timestamp and compile new font options.recalcTimestamp = True ttx.ttCompile(inttx, str(outttf2), options) # confirm that font was built assert outttf2.check(file=True) # confirm that timestamp is more recent than modified time on ttx file mtime = os.path.getmtime(inttx) epochtime = timestampSinceEpoch(mtime) ttf = TTFont(str(outttf2)) assert ttf["head"].modified > epochtime
def test_ttcompile_ttf_to_woff_with_zopfli(tmpdir): inttx = os.path.join("Tests", "ttx", "data", "TestTTF.ttx") outwoff = tmpdir.join("TestTTF.woff") options = ttx.Options([], 1) options.flavor = "woff" options.useZopfli = True ttx.ttCompile(inttx, str(outwoff), options) # confirm that font was built assert outwoff.check(file=True) # confirm that it is valid TTF file, can instantiate a TTFont, has expected OpenType tables ttf = TTFont(str(outwoff)) expected_tables = ( "head", "hhea", "maxp", "OS/2", "name", "cmap", "hmtx", "fpgm", "prep", "cvt ", "loca", "glyf", "post", "gasp", "DSIG", ) for table in expected_tables: assert table in ttf
def roundTrip(ttFile1, options, report): fn = os.path.basename(ttFile1) xmlFile1 = tempfile.mktemp(".%s.ttx1" % fn) ttFile2 = tempfile.mktemp(".%s" % fn) xmlFile2 = tempfile.mktemp(".%s.ttx2" % fn) try: ttx.ttDump(ttFile1, xmlFile1, options) if options.onlyTables or options.skipTables: options.mergeFile = ttFile1 ttx.ttCompile(xmlFile1, ttFile2, options) options.mergeFile = None ttx.ttDump(ttFile2, xmlFile2, options) diffcmd = 'diff -U2 -I ".*modified value\|checkSumAdjustment.*" "%s" "%s"' % (xmlFile1, xmlFile2) output = os.popen(diffcmd, "r", 1) lines = [] while True: line = output.readline() if not line: break sys.stdout.write(line) lines.append(line) if lines: report.write("=============================================================\n") report.write(" \"%s\" differs after round tripping\n" % ttFile1) report.write("-------------------------------------------------------------\n") report.writelines(lines) else: print("(TTX files are the same)") finally: for tmpFile in (xmlFile1, ttFile2, xmlFile2): if os.path.exists(tmpFile): os.remove(tmpFile)
def obfuscate(s): global tree, names if tree is None: tree = ET.parse('DejaVuSansMono_cmap.ttx') for c in tree.getroot().find('cmap/cmap_format_12').findall('map'): code = int(c.attrib['code'], 16) if 0x21 <= code <= 0x7e: names.append((code, c.attrib['name'])) random.shuffle(names) for c in tree.getroot().find('cmap/cmap_format_12').findall('map'): code = int(c.attrib['code'], 16) if 0x21 <= code <= 0x7e: c.attrib['name'] = names[code - 0x21][1] with TmpFile() as scrambled_ttx, TmpFile() as scrambled_ttf: tree.write(scrambled_ttx.name, xml_declaration=True) ttx.ttCompile(scrambled_ttx.name, scrambled_ttf.name, ttx.Options([('-m', 'DejaVuSansMono.ttf')], 1)) text = html.escape(scramble(s, names)) return subprocess.check_output( ['python', 'obfuscate.py', text, scrambled_ttf.name])
def test_ttcompile_otf_compile_default(tmpdir): inttx = os.path.join("Tests", "ttx", "data", "TestOTF.ttx") # outotf = os.path.join(str(tmpdir), "TestOTF.otf") outotf = tmpdir.join("TestOTF.ttx") default_options = ttx.Options([], 1) ttx.ttCompile(inttx, str(outotf), default_options) # confirm that font was built assert outotf.check(file=True) # confirm that it is valid OTF file, can instantiate a TTFont, has expected OpenType tables ttf = TTFont(str(outotf)) expected_tables = ( "head", "hhea", "maxp", "OS/2", "name", "cmap", "post", "CFF ", "hmtx", "DSIG", ) for table in expected_tables: assert table in ttf
# Generates ttf, woff, and woff2 fonts from ttx source. import sys from fontTools import subset from fontTools import ttx from fontTools.ttLib import sfnt # Arguments TTX = sys.argv[1] # Files TTF = TTX.replace(".ttx", ".ttf") WOFF = TTX.replace(".ttx", ".woff") WOFF2 = TTX.replace(".ttx", ".woff2") # Make ttf ttx.ttCompile(TTX, TTF, ttx.Options([], 1)) # Make woff sfnt.ZOPFLI_LEVELS[sfnt.ZLIB_COMPRESSION_LEVEL] = 1000 for w in (WOFF, WOFF2): subset.main([ TTF, "--glyphs=*", "--notdef-glyph", "--notdef-outline", "--no-name-legacy", "--no-glyph-names", "--no-legacy-cmap", "--no-symbol-cmap", "--no-recalc-bounds", "--no-recalc-timestamp", "--canonical-order", "--prune-unicode-ranges", "--no-recalc-average-width", "--with-zopfli", "--flavor=" + w.split(".")[-1], "--output-file=" + w ])