You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			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)
 |