diff options
Diffstat (limited to 'Lib/fontTools/merge/base.py')
-rw-r--r-- | Lib/fontTools/merge/base.py | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/Lib/fontTools/merge/base.py b/Lib/fontTools/merge/base.py new file mode 100644 index 00000000..868b51a4 --- /dev/null +++ b/Lib/fontTools/merge/base.py @@ -0,0 +1,76 @@ +# Copyright 2013 Google, Inc. All Rights Reserved. +# +# Google Author(s): Behdad Esfahbod, Roozbeh Pournader + +from fontTools.ttLib.tables.DefaultTable import DefaultTable +import logging + + +log = logging.getLogger("fontTools.merge") + + +def add_method(*clazzes, **kwargs): + """Returns a decorator function that adds a new method to one or + more classes.""" + allowDefault = kwargs.get('allowDefaultTable', False) + def wrapper(method): + done = [] + for clazz in clazzes: + if clazz in done: continue # Support multiple names of a clazz + done.append(clazz) + assert allowDefault or clazz != DefaultTable, 'Oops, table class not found.' + assert method.__name__ not in clazz.__dict__, \ + "Oops, class '%s' has method '%s'." % (clazz.__name__, method.__name__) + setattr(clazz, method.__name__, method) + return None + return wrapper + +def mergeObjects(lst): + lst = [item for item in lst if item is not NotImplemented] + if not lst: + return NotImplemented + lst = [item for item in lst if item is not None] + if not lst: + return None + + clazz = lst[0].__class__ + assert all(type(item) == clazz for item in lst), lst + + logic = clazz.mergeMap + returnTable = clazz() + returnDict = {} + + allKeys = set.union(set(), *(vars(table).keys() for table in lst)) + for key in allKeys: + try: + mergeLogic = logic[key] + except KeyError: + try: + mergeLogic = logic['*'] + except KeyError: + raise Exception("Don't know how to merge key %s of class %s" % + (key, clazz.__name__)) + if mergeLogic is NotImplemented: + continue + value = mergeLogic(getattr(table, key, NotImplemented) for table in lst) + if value is not NotImplemented: + returnDict[key] = value + + returnTable.__dict__ = returnDict + + return returnTable + +@add_method(DefaultTable, allowDefaultTable=True) +def merge(self, m, tables): + if not hasattr(self, 'mergeMap'): + log.info("Don't know how to merge '%s'.", self.tableTag) + return NotImplemented + + logic = self.mergeMap + + if isinstance(logic, dict): + return m.mergeObjects(self, self.mergeMap, tables) + else: + return logic(tables) + + |