[varLib.builder] Implement building 32bit VarStore

The full optimizer in varLib.varStore still needs to be updated.
But this pretty much enables building 32bit VarStores, even if they
won't be fully optimal.

Part of https://github.com/fonttools/fonttools/issues/2279
This commit is contained in:
Behdad Esfahbod 2021-05-01 14:27:11 -06:00
parent 802e3636bc
commit e454e96238

View File

@ -26,39 +26,40 @@ def buildVarRegionList(supports, axisTags):
return self return self
def _reorderItem(lst, narrows, zeroes): def _reorderItem(lst, mapping):
out = [] return [lst[i] for i in mapping]
count = len(lst)
for i in range(count):
if i not in narrows:
out.append(lst[i])
for i in range(count):
if i in narrows and i not in zeroes:
out.append(lst[i])
return out
def VarData_calculateNumShorts(self, optimize=False): def VarData_calculateNumShorts(self, optimize=False):
count = self.VarRegionCount count = self.VarRegionCount
items = self.Item items = self.Item
narrows = set(range(count)) bit_lengths = [0] * count
zeroes = set(range(count))
for item in items: for item in items:
wides = [i for i in narrows if not (-128 <= item[i] <= 127)] bl = [(i + (i < -1)).bit_length() for i in item]
narrows.difference_update(wides) bit_lengths = [max(*pair) for pair in zip(bl, bit_lengths)]
nonzeroes = [i for i in zeroes if item[i]] byte_lengths = [((b + 8) // 8) if b else 0 for b in bit_lengths]
zeroes.difference_update(nonzeroes)
if not narrows and not zeroes: # https://github.com/fonttools/fonttools/issues/2279
break longWords = any(b > 2 for b in byte_lengths)
if optimize: if optimize:
# Reorder columns such that all SHORT columns come before UINT8 # Reorder columns such that wider columns come before narrower columns
self.VarRegionIndex = _reorderItem(self.VarRegionIndex, narrows, zeroes) mapping = []
mapping.extend(i for i,b in enumerate(byte_lengths) if b > 2)
mapping.extend(i for i,b in enumerate(byte_lengths) if b == 2)
mapping.extend(i for i,b in enumerate(byte_lengths) if b == 1)
byte_lengths = _reorderItem(byte_lengths, mapping)
self.VarRegionIndex = _reorderItem(self.VarRegionIndex, mapping)
self.VarRegionCount = len(self.VarRegionIndex) self.VarRegionCount = len(self.VarRegionIndex)
for i in range(len(items)): for i in range(len(items)):
items[i] = _reorderItem(items[i], narrows, zeroes) items[i] = _reorderItem(items[i], mapping)
self.NumShorts = count - len(narrows)
if longWords:
self.NumShorts = max((i for i,b in enumerate(byte_lengths) if b > 2), default=-1) + 1
self.NumShorts |= 0x8000
else: else:
wides = set(range(count)) - narrows self.NumShorts = max((i for i,b in enumerate(byte_lengths) if b > 1), default=-1) + 1
self.NumShorts = 1+max(wides) if wides else 0
self.VarRegionCount = len(self.VarRegionIndex) self.VarRegionCount = len(self.VarRegionIndex)
return self return self