82 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			82 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # 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)
 |