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