From 98e2bf5526a49a89b498801c357422340d7bb5df Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 7 May 2021 15:41:11 -0600 Subject: [PATCH] [varLib.builder] Document bit-tweedling https://github.com/fonttools/fonttools/pull/2285#discussion_r628401241 --- Lib/fontTools/ttLib/tables/otConverters.py | 8 ++++---- Lib/fontTools/varLib/builder.py | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Lib/fontTools/ttLib/tables/otConverters.py b/Lib/fontTools/ttLib/tables/otConverters.py index d5bfc5aa5..1f1a3194b 100644 --- a/Lib/fontTools/ttLib/tables/otConverters.py +++ b/Lib/fontTools/ttLib/tables/otConverters.py @@ -1630,10 +1630,10 @@ class VarDataValue(BaseConverter): longWords = bool(wordCount & 0x8000) wordCount = wordCount & 0x7FFF - (readBigArray, readSmallArray) = { - False: (reader.readShortArray, reader.readInt8Array), - True: (reader.readLongArray, reader.readShortArray), - }[longWords] + if longWords: + readBigArray, readSmallArray = reader.readLongArray, reader.readShortArray + else: + readBigArray, readSmallArray = reader.readShortArray, reader.readInt8Array n1, n2 = min(regionCount, wordCount), max(regionCount, wordCount) values.extend(readBigArray(n1)) diff --git a/Lib/fontTools/varLib/builder.py b/Lib/fontTools/varLib/builder.py index 45a9fb3d8..c024c613d 100644 --- a/Lib/fontTools/varLib/builder.py +++ b/Lib/fontTools/varLib/builder.py @@ -34,9 +34,23 @@ def VarData_calculateNumShorts(self, optimize=False): items = self.Item bit_lengths = [0] * count for item in items: + # The "+ (i < -1)" magic is to handle two's-compliment. + # That is, we want to get back 7 for -128, whereas + # bit_length() returns 8. Similarly for -65536. + # The reason "i < -1" is used instead of "i < 0" is that + # the latter would make it return 0 for "-1" instead of 1. 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] + # The addition of 8, instead of seven, is to account for the sign bit. + # This "((b + 8) >> 3) if b else 0" when combined with the above + # "(i + (i < -1)).bit_length()" is a faster way to compute byte-lengths + # conforming to: + # + # byte_length = (0 if i == 0 else + # 1 if -128 <= i < 128 else + # 2 if -65536 <= i < 65536 else + # ...) + byte_lengths = [((b + 8) >> 3) 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)