""" Merge OpenType Layout tables (GDEF / GPOS / GSUB). """ from __future__ import print_function, division, absolute_import from fontTools.misc.py23 import * from fontTools.ttLib.tables import otTables as ot from fontTools.ttLib.tables.DefaultTable import DefaultTable class Merger(object): mergers = None def __init__(self, font=None): self.font = font @classmethod def merger(celf, clazzes, attrs=(None,)): assert celf != Merger, 'Subclass Merger instead.' if celf.mergers is None: celf.mergers = {} if type(clazzes) == type: clazzes = (clazzes,) if type(attrs) == str: attrs = (attrs,) def wrapper(method): assert method.__name__ == 'merge' done = [] for clazz in clazzes: if clazz in done: continue # Support multiple names of a clazz done.append(clazz) mergers = celf.mergers.setdefault(clazz, {}) for attr in attrs: assert attr not in mergers, \ "Oops, class '%s' has merge function for '%s' defined already." % (clazz.__name__, attr) mergers[attr] = method return None return wrapper def mergeObjects(self, out, lst, exclude=(), _default={}): keys = sorted(vars(out).keys()) assert all(keys == sorted(vars(v).keys()) for v in lst), \ (keys, [sorted(vars(v).keys()) for v in lst]) mergers = self.mergers.get(type(out), _default) defaultMerger = mergers.get('*', self.__class__.mergeThings) try: for key in keys: if key in exclude: continue value = getattr(out, key) values = [getattr(table, key) for table in lst] mergerFunc = mergers.get(key, defaultMerger) mergerFunc(self, value, values) except Exception as e: e.args = e.args + ('.'+key,) raise def mergeLists(self, out, lst): count = len(out) assert all(count == len(v) for v in lst), (count, [len(v) for v in lst]) for value,values in zip(out, zip(*lst)): self.mergeThings(value, values) def mergeThings(self, out, lst, _default={None:None}): clazz = type(out) try: assert all(type(item) == clazz for item in lst), (out, lst) mergerFunc = self.mergers.get(type(out), _default).get(None, None) if mergerFunc is not None: mergerFunc(self, out, lst) elif hasattr(out, '__dict__'): self.mergeObjects(out, lst) elif isinstance(out, list): self.mergeLists(out, lst) else: assert all(out == v for v in lst), (out, lst) except Exception as e: e.args = e.args + (clazz.__name__,) raise def merge_tables(font, merger, master_ttfs, axes, base_idx, tables): for tag in tables: if tag not in font: continue print('Merging', tag) merger.mergeThings(font[tag], [m[tag] for m in master_ttfs])