Spaces:
Paused
Paused
| # 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)] | |