144 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # Copyright 2013 Google, Inc. All Rights Reserved.
 | |
| #
 | |
| # Google Author(s): Behdad Esfahbod, Roozbeh Pournader
 | |
| 
 | |
| from fontTools.misc.timeTools import timestampNow
 | |
| from fontTools.ttLib.tables.DefaultTable import DefaultTable
 | |
| from functools import reduce
 | |
| import operator
 | |
| import logging
 | |
| 
 | |
| 
 | |
| log = logging.getLogger("fontTools.merge")
 | |
| 
 | |
| 
 | |
| # General utility functions for merging values from different fonts
 | |
| 
 | |
| 
 | |
| def equal(lst):
 | |
|     lst = list(lst)
 | |
|     t = iter(lst)
 | |
|     first = next(t)
 | |
|     assert all(item == first for item in t), "Expected all items to be equal: %s" % lst
 | |
|     return first
 | |
| 
 | |
| 
 | |
| def first(lst):
 | |
|     return next(iter(lst))
 | |
| 
 | |
| 
 | |
| def recalculate(lst):
 | |
|     return NotImplemented
 | |
| 
 | |
| 
 | |
| def current_time(lst):
 | |
|     return timestampNow()
 | |
| 
 | |
| 
 | |
| def bitwise_and(lst):
 | |
|     return reduce(operator.and_, lst)
 | |
| 
 | |
| 
 | |
| def bitwise_or(lst):
 | |
|     return reduce(operator.or_, lst)
 | |
| 
 | |
| 
 | |
| def avg_int(lst):
 | |
|     lst = list(lst)
 | |
|     return sum(lst) // len(lst)
 | |
| 
 | |
| 
 | |
| def onlyExisting(func):
 | |
|     """Returns a filter func that when called with a list,
 | |
|     only calls func on the non-NotImplemented items of the list,
 | |
|     and only so if there's at least one item remaining.
 | |
|     Otherwise returns NotImplemented."""
 | |
| 
 | |
|     def wrapper(lst):
 | |
|         items = [item for item in lst if item is not NotImplemented]
 | |
|         return func(items) if items else NotImplemented
 | |
| 
 | |
|     return wrapper
 | |
| 
 | |
| 
 | |
| def sumLists(lst):
 | |
|     l = []
 | |
|     for item in lst:
 | |
|         l.extend(item)
 | |
|     return l
 | |
| 
 | |
| 
 | |
| def sumDicts(lst):
 | |
|     d = {}
 | |
|     for item in lst:
 | |
|         d.update(item)
 | |
|     return d
 | |
| 
 | |
| 
 | |
| def mergeBits(bitmap):
 | |
|     def wrapper(lst):
 | |
|         lst = list(lst)
 | |
|         returnValue = 0
 | |
|         for bitNumber in range(bitmap["size"]):
 | |
|             try:
 | |
|                 mergeLogic = bitmap[bitNumber]
 | |
|             except KeyError:
 | |
|                 try:
 | |
|                     mergeLogic = bitmap["*"]
 | |
|                 except KeyError:
 | |
|                     raise Exception("Don't know how to merge bit %s" % bitNumber)
 | |
|             shiftedBit = 1 << bitNumber
 | |
|             mergedValue = mergeLogic(bool(item & shiftedBit) for item in lst)
 | |
|             returnValue |= mergedValue << bitNumber
 | |
|         return returnValue
 | |
| 
 | |
|     return wrapper
 | |
| 
 | |
| 
 | |
| class AttendanceRecordingIdentityDict(object):
 | |
|     """A dictionary-like object that records indices of items actually accessed
 | |
|     from a list."""
 | |
| 
 | |
|     def __init__(self, lst):
 | |
|         self.l = lst
 | |
|         self.d = {id(v): i for i, v in enumerate(lst)}
 | |
|         self.s = set()
 | |
| 
 | |
|     def __getitem__(self, v):
 | |
|         self.s.add(self.d[id(v)])
 | |
|         return v
 | |
| 
 | |
| 
 | |
| class GregariousIdentityDict(object):
 | |
|     """A dictionary-like object that welcomes guests without reservations and
 | |
|     adds them to the end of the guest list."""
 | |
| 
 | |
|     def __init__(self, lst):
 | |
|         self.l = lst
 | |
|         self.s = set(id(v) for v in lst)
 | |
| 
 | |
|     def __getitem__(self, v):
 | |
|         if id(v) not in self.s:
 | |
|             self.s.add(id(v))
 | |
|             self.l.append(v)
 | |
|         return v
 | |
| 
 | |
| 
 | |
| class NonhashableDict(object):
 | |
|     """A dictionary-like object mapping objects to values."""
 | |
| 
 | |
|     def __init__(self, keys, values=None):
 | |
|         if values is None:
 | |
|             self.d = {id(v): i for i, v in enumerate(keys)}
 | |
|         else:
 | |
|             self.d = {id(k): v for k, v in zip(keys, values)}
 | |
| 
 | |
|     def __getitem__(self, k):
 | |
|         return self.d[id(k)]
 | |
| 
 | |
|     def __setitem__(self, k, v):
 | |
|         self.d[id(k)] = v
 | |
| 
 | |
|     def __delitem__(self, k):
 | |
|         del self.d[id(k)]
 |