From 6a09096800eeb53c8b99763be55cf5c9ce73ce38 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 20 Dec 2023 21:21:51 -0700 Subject: [PATCH] [VARC] Use variable-length encoding for VarIdx'es --- Lib/fontTools/ttLib/tables/otTables.py | 58 ++++++++++++++++++++----- Tests/ttLib/data/varc-6868.ttf | Bin 9864 -> 9836 bytes Tests/ttLib/data/varc-ac00-ac01.ttf | Bin 3404 -> 3384 bytes 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/Lib/fontTools/ttLib/tables/otTables.py b/Lib/fontTools/ttLib/tables/otTables.py index 3406415d0..d354f6ff6 100644 --- a/Lib/fontTools/ttLib/tables/otTables.py +++ b/Lib/fontTools/ttLib/tables/otTables.py @@ -98,7 +98,7 @@ _packer = { 3: lambda v: struct.pack(">L", v)[1:], 4: lambda v: struct.pack(">L", v), } -_unpackers = { +_unpacker = { 1: lambda v: struct.unpack(">B", v)[0], 2: lambda v: struct.unpack(">H", v)[0], 3: lambda v: struct.unpack(">L", b"\0" + v)[0], @@ -106,6 +106,46 @@ _unpackers = { } +def _read_var_length_number(data, i): + """Read a variable-length number from data starting at index i. + + Return the number and the next index. + """ + + b0 = data[i] + if b0 < 0x80: + return b0, i + 1 + elif b0 < 0xC0: + return (b0 - 0x80) << 8 | data[i + 1], i + 2 + elif b0 < 0xE0: + return (b0 - 0xC0) << 16 | data[i + 1] << 8 | data[i + 2], i + 3 + elif b0 < 0xF0: + return (b0 - 0xE0) << 24 | data[i + 1] << 16 | data[i + 2] << 8 | data[ + i + 3 + ], i + 4 + else: + return (b0 - 0xF0) << 32 | data[i + 1] << 24 | data[i + 2] << 16 | data[ + i + 3 + ] << 8 | data[i + 4], i + 5 + + +def _write_var_length_number(v): + """Write a variable-length number. + + Return the data. + """ + if v < 0x80: + return struct.pack(">B", v) + elif v < 0x4000: + return struct.pack(">H", (v | 0x8000)) + elif v < 0x200000: + return struct.pack(">L", (v | 0xC00000))[1:] + elif v < 0x10000000: + return struct.pack(">L", (v | 0xE0000000)) + else: + return struct.pack(">B", 0xF0) + struct.pack(">L", v) + + class VarComponent: def __init__(self): self.flags = 0 @@ -118,11 +158,11 @@ class VarComponent: def decompile(self, data, font, localState): i = 0 - self.flags = flags = _unpackers[2](data[i : i + 2]) + self.flags = flags = _unpacker[2](data[i : i + 2]) i += 2 gidSize = 3 if flags & VarComponentFlags.GID_IS_24BIT else 2 - glyphID = _unpackers[gidSize](data[i : i + gidSize]) + glyphID = _unpacker[gidSize](data[i : i + gidSize]) i += gidSize self.glyphName = font.glyphOrder[glyphID] @@ -131,7 +171,7 @@ class VarComponent: self.axisIndicesIndex = ( None if axisIndicesIndexSize == 0 - else _unpackers[axisIndicesIndexSize](data[i : i + axisIndicesIndexSize]) + else _unpacker[axisIndicesIndexSize](data[i : i + axisIndicesIndexSize]) ) i += axisIndicesIndexSize @@ -146,13 +186,11 @@ class VarComponent: self.axisValues = tuple(axisValues) if flags & VarComponentFlags.AXIS_VALUES_HAVE_VARIATION: - self.axisValuesVarIndex = _unpackers[4](data[i : i + 4]) - i += 4 + self.axisValuesVarIndex, i = _read_var_length_number(data, i) else: self.axisValuesVarIndex = NO_VARIATION_INDEX if flags & VarComponentFlags.TRANSFORM_HAS_VARIATION: - self.transformVarIndex = _unpackers[4](data[i : i + 4]) - i += 4 + self.transformVarIndex, i = _read_var_length_number(data, i) else: self.transformVarIndex = NO_VARIATION_INDEX @@ -219,12 +257,12 @@ class VarComponent: if self.axisValuesVarIndex != NO_VARIATION_INDEX: flags |= VarComponentFlags.AXIS_VALUES_HAVE_VARIATION - data.append(struct.pack(">L", self.axisValuesVarIndex)) + data.append(_write_var_length_number(self.axisValuesVarIndex)) else: flags &= ~VarComponentFlags.AXIS_VALUES_HAVE_VARIATION if self.transformVarIndex != NO_VARIATION_INDEX: flags |= VarComponentFlags.TRANSFORM_HAS_VARIATION - data.append(struct.pack(">L", self.transformVarIndex)) + data.append(_write_var_length_number(self.transformVarIndex)) else: flags &= ~VarComponentFlags.TRANSFORM_HAS_VARIATION diff --git a/Tests/ttLib/data/varc-6868.ttf b/Tests/ttLib/data/varc-6868.ttf index 5e02bb1466860fbcdda27df91095d397e0d0a8e0..b2c49f9789abbe8b1471ace718d17152d62543c0 100644 GIT binary patch delta 260 zcmeD1ed8m;z{tSBz{AkMz|7zf<{0F>OyX${0|S=<0|WP+i89uVJR2hgA2<)CRxS|W+r>-gA7au zC#Q;N2_9r%VPIhTKZpG#13Qz00>h!nOGV^a4lytuntVz`706&dH2JHDI?G`OhQpJU zMD>6Sro)rNL=}Mymcx^4MKxHCFfbgMyjoPp>j(qW5e8<)Crr*?I+?1O*Res(Ji@@j wc!9}^!GnT8z)Qi5eBv+4D5^-7&sU_m}YI(5K9mM0DYZCC;$Ke delta 288 zcmaFk)8Q+_z{tSBz{AkMz|7zf<{0EW;emS}0|S=<0|WQ>i89uV8XF@dI9WJU*Z$pH z!a1Ldy^-NHV=)u&WGN99b+BGWAbE`874s}+W450ROpFaKEdQ8f88euf?4^NHObm>Z z6GgPdfJ_#kO$-c7|L3s3WMF4Pl1E~Qr_lu~4n9M-t3lViTAcKK{d9tvm z9*7APpX@5C2x77TnOUM5Y+&K}$OAr76gS0Zp diff --git a/Tests/ttLib/data/varc-ac00-ac01.ttf b/Tests/ttLib/data/varc-ac00-ac01.ttf index 4597c2e612e4e8310daeae44f0bf718213a44d87..8c10394f71625250ba21b8e3c8416ec4cf7379c7 100644 GIT binary patch delta 124 zcmX>jwL?mVfsuiMfrp`iftkS}%rVH>@9^#n1_ssu1_nmci89uV9UCJ|SXflc>-KJ* zz|zOaqU#WtJXwiN+w%V}hK~%Kj81n8nfmYDX=G*k|Bb-_D8$9!crNUvZUY-LL)Jed akQxT3_qEK%_wKMT0+mQGY@Wroi46dKz$XC! delta 144 zcmdlXbw)~tfsuiMfrp`iftkS}%rVH>LO=>A!WzK9!00tm#+q@?#t0J@mY{nFlQvIa z>0@Lu@Jy(fti-163)J@i7sE#ePDZD@g-reT?lb~LSb>=7|2GB$pad6#