aboutsummaryrefslogtreecommitdiff
path: root/Lib/fontTools/merge/util.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/fontTools/merge/util.py')
-rw-r--r--Lib/fontTools/merge/util.py131
1 files changed, 131 insertions, 0 deletions
diff --git a/Lib/fontTools/merge/util.py b/Lib/fontTools/merge/util.py
new file mode 100644
index 00000000..66cea4d5
--- /dev/null
+++ b/Lib/fontTools/merge/util.py
@@ -0,0 +1,131 @@
+# 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)]