|
@@ -1,148 +0,0 @@
|
|
-#!/usr/bin/env python
|
|
|
|
-# -*- coding: utf-8 -*-
|
|
|
|
-
|
|
|
|
-# ------------------------------------------------------------------------------
|
|
|
|
-# font-tables.py
|
|
|
|
-# Copyright 2015 Christopher Simpkins
|
|
|
|
-# MIT license
|
|
|
|
-# ------------------------------------------------------------------------------
|
|
|
|
-
|
|
|
|
-import sys
|
|
|
|
-import os
|
|
|
|
-import os.path
|
|
|
|
-import hashlib
|
|
|
|
-from fontTools import ttLib
|
|
|
|
-
|
|
|
|
-# TODO: expand Python objects within the table values
|
|
|
|
-# TODO: modify TTFA table read to create YAML format from the strings
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-def main(fontpaths):
|
|
|
|
- """The main function creates a YAML formatted report on the OpenType tables in one
|
|
|
|
- or more fonts included in the fontpaths function parameter.
|
|
|
|
- :param fontpaths: """
|
|
|
|
-
|
|
|
|
- # create a report directory, gracefully fail if it already exists
|
|
|
|
- if not os.path.isdir("otreports"):
|
|
|
|
- os.mkdir("otreports")
|
|
|
|
-
|
|
|
|
- # iterate through fonts requested in the command
|
|
|
|
- for fontpath in fontpaths:
|
|
|
|
-
|
|
|
|
- if os.path.isfile(fontpath):
|
|
|
|
- # create a fonttools TTFont object using the fontpath
|
|
|
|
- tt = ttLib.TTFont(fontpath)
|
|
|
|
- print("Processing " + fontpath + "...")
|
|
|
|
-
|
|
|
|
- # define the outfile path
|
|
|
|
- basename = os.path.basename(fontpath)
|
|
|
|
- basefilename = basename + "-TABLES.yaml"
|
|
|
|
- outfilepath = os.path.join("otreports", basefilename)
|
|
|
|
-
|
|
|
|
- # read the font data and create a SHA1 hash digest for the report
|
|
|
|
- fontdata = read_bin(fontpath)
|
|
|
|
- hash_digest = hashlib.sha1(fontdata).hexdigest()
|
|
|
|
-
|
|
|
|
- # report strings for file name and SHA1 digest
|
|
|
|
- report_header_string = "FILE: " + fontpath + "\n"
|
|
|
|
- report_header_string += "SHA1: " + hash_digest + "\n\n"
|
|
|
|
-
|
|
|
|
- # open outfile write stream, create file, write name + SHA1 header
|
|
|
|
- with open(outfilepath, "w") as writer:
|
|
|
|
- writer.write(report_header_string)
|
|
|
|
-
|
|
|
|
- # iterate through the OpenType tables, write table fields in a newline delimited format with YAML syntax
|
|
|
|
- for table in tt.keys():
|
|
|
|
- table_dict = tt[table].__dict__
|
|
|
|
- if len(table_dict) > 0:
|
|
|
|
- table_string = yaml_formatter(table, table_dict)
|
|
|
|
- with open(outfilepath, 'a') as appender:
|
|
|
|
- appender.write(table_string)
|
|
|
|
- print("[✓] " + table)
|
|
|
|
- else:
|
|
|
|
- print("[E] " + table) # indicate missing table data in standard output, do not write to YAML file
|
|
|
|
- print(fontpath + " table report is available in " + outfilepath + "\n")
|
|
|
|
- else: # not a valid filepath
|
|
|
|
- sys.stderr.write("Error: '" + fontpath + "' was not found. Please check the filepath.\n\n")
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-def yaml_formatter(table_name, table_dict):
|
|
|
|
- """Creates a YAML formatted string for OpenType table font reports"""
|
|
|
|
- # define the list of tables that require table-specific processing
|
|
|
|
- special_table_list = ['name', 'OS/2', 'TTFA']
|
|
|
|
- if table_name in special_table_list:
|
|
|
|
- if table_name == "name":
|
|
|
|
- return name_yaml_formatter(table_dict)
|
|
|
|
- elif table_name == "OS/2":
|
|
|
|
- return os2_yaml_formatter(table_dict)
|
|
|
|
- elif table_name == "TTFA":
|
|
|
|
- return ttfa_yaml_formatter(table_dict)
|
|
|
|
- else:
|
|
|
|
- table_string = table_name.strip() + ": {\n"
|
|
|
|
- for field in table_dict.keys():
|
|
|
|
- table_string = table_string + (" " * 4) + field + ": " + str(table_dict[field]) + ',\n'
|
|
|
|
- table_string += "}\n\n"
|
|
|
|
- return table_string
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-def name_yaml_formatter(table_dict):
|
|
|
|
- """Formats the YAML table string for OpenType name tables"""
|
|
|
|
- table_string = "name: {\n"
|
|
|
|
- namerecord_list = table_dict['names']
|
|
|
|
- for record in namerecord_list:
|
|
|
|
- if record.__dict__['langID'] == 0:
|
|
|
|
- record_name = str(record.__dict__['nameID'])
|
|
|
|
- else:
|
|
|
|
- record_name = str(record.__dict__['nameID']) + "u"
|
|
|
|
- record_field = (" " * 4) + "nameID" + record_name
|
|
|
|
- table_string = table_string + record_field + ": " + str(record.__dict__) + ",\n"
|
|
|
|
- table_string = table_string + "}\n\n"
|
|
|
|
- return table_string
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-def os2_yaml_formatter(table_dict):
|
|
|
|
- """Formats the YAML table string for OpenType OS/2 tables"""
|
|
|
|
- table_string = "OS/2: {\n"
|
|
|
|
- for field in table_dict.keys():
|
|
|
|
- if field == "panose":
|
|
|
|
- table_string = table_string + (" "*4) + field + ": {\n"
|
|
|
|
- panose_string = ""
|
|
|
|
- panose_dict = table_dict['panose'].__dict__
|
|
|
|
- for panose_field in panose_dict.keys():
|
|
|
|
- panose_string = panose_string + (" " * 8) + panose_field[1:] + ": " + str(panose_dict[panose_field]) + ",\n"
|
|
|
|
- table_string = table_string + panose_string + (" " * 4) + "}\n"
|
|
|
|
- else:
|
|
|
|
- table_string = table_string + (" "*4) + field + ": " + str(table_dict[field]) + ',\n'
|
|
|
|
- table_string = table_string + "}\n\n"
|
|
|
|
- return table_string
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-def ttfa_yaml_formatter(table_dict):
|
|
|
|
- """Formats the YAML table string for the ttfautohint TTFA table"""
|
|
|
|
- data_string = table_dict['data'].strip()
|
|
|
|
- data_list = data_string.split('\n') # split on newlines in the string
|
|
|
|
- table_string = "TTFA: {\n"
|
|
|
|
- for definition_string in data_list:
|
|
|
|
- definition_list = definition_string.split("=")
|
|
|
|
- field = definition_list[0].strip()
|
|
|
|
- if len(definition_list) > 1:
|
|
|
|
- value = definition_list[1].strip()
|
|
|
|
- else:
|
|
|
|
- value = "''"
|
|
|
|
- table_string = table_string + (" " * 4) + field + ": " + value + ",\n"
|
|
|
|
- table_string = table_string + "}\n\n"
|
|
|
|
- return table_string
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-def read_bin(filepath):
|
|
|
|
- """read_bin function reads filepath parameter as binary data and returns raw binary to calling code"""
|
|
|
|
- try:
|
|
|
|
- with open(filepath, 'rb') as bin_reader:
|
|
|
|
- data = bin_reader.read()
|
|
|
|
- return data
|
|
|
|
- except Exception as e:
|
|
|
|
- sys.stderr.write("Error: Unable to read file " + filepath + ". " + str(e))
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-if __name__ == '__main__':
|
|
|
|
- main(sys.argv[1:])
|
|
|