From 82460bd368329ebaa61b3f197a368906e66e58fd Mon Sep 17 00:00:00 2001 From: Cosimo Lupo Date: Tue, 14 Jun 2022 18:06:15 +0100 Subject: [PATCH] otConverters: define a base class for all fixed-size floats with toInt/fromInt methods this will be useful when computing deltas for COLR table fields that use Fixed or F2Dot14 (ItemVariationStore internally treats fixed-value floats as 16 or 32-bit integers) --- Lib/fontTools/ttLib/tables/otConverters.py | 60 +++++++++++++--------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/Lib/fontTools/ttLib/tables/otConverters.py b/Lib/fontTools/ttLib/tables/otConverters.py index 44fcd0ab3..274cd7d05 100644 --- a/Lib/fontTools/ttLib/tables/otConverters.py +++ b/Lib/fontTools/ttLib/tables/otConverters.py @@ -402,40 +402,50 @@ class DeciPoints(FloatValue): def write(self, writer, font, tableDict, value, repeatIndex=None): writer.writeUShort(round(value * 10)) -class Fixed(FloatValue): - staticSize = 4 +class BaseFixedValue(FloatValue): + staticSize = NotImplemented + precisionBits = NotImplemented + readerMethod = NotImplemented + writerMethod = NotImplemented def read(self, reader, font, tableDict): - return fi2fl(reader.readLong(), 16) + return self.fromInt(getattr(reader, self.readerMethod)()) def write(self, writer, font, tableDict, value, repeatIndex=None): - writer.writeLong(fl2fi(value, 16)) - @staticmethod - def fromString(value): - return str2fl(value, 16) - @staticmethod - def toString(value): - return fl2str(value, 16) + getattr(writer, self.writerMethod)(self.toInt(value)) + @classmethod + def fromInt(cls, value): + return fi2fl(value, cls.precisionBits) + @classmethod + def toInt(cls, value): + return fl2fi(value, cls.precisionBits) + @classmethod + def fromString(cls, value): + return str2fl(value, cls.precisionBits) + @classmethod + def toString(cls, value): + return fl2str(value, cls.precisionBits) -class F2Dot14(FloatValue): +class Fixed(BaseFixedValue): + staticSize = 4 + precisionBits = 16 + readerMethod = "readLong" + writerMethod = "writeLong" + +class F2Dot14(BaseFixedValue): staticSize = 2 - def read(self, reader, font, tableDict): - return fi2fl(reader.readShort(), 14) - def write(self, writer, font, tableDict, value, repeatIndex=None): - writer.writeShort(fl2fi(value, 14)) - @staticmethod - def fromString(value): - return str2fl(value, 14) - @staticmethod - def toString(value): - return fl2str(value, 14) + precisionBits = 14 + readerMethod = "readShort" + writerMethod = "writeShort" class Angle(F2Dot14): # angles are specified in degrees, and encoded as F2Dot14 fractions of half # circle: e.g. 1.0 => 180, -0.5 => -90, -2.0 => -360, etc. factor = 1.0/(1<<14) * 180 # 0.010986328125 - def read(self, reader, font, tableDict): - return super().read(reader, font, tableDict) * 180 - def write(self, writer, font, tableDict, value, repeatIndex=None): - super().write(writer, font, tableDict, value / 180, repeatIndex=repeatIndex) + @classmethod + def fromInt(cls, value): + return super().fromInt(value) * 180 + @classmethod + def toInt(cls, value): + return super().toInt(value / 180) @classmethod def fromString(cls, value): # quantize to nearest multiples of minimum fixed-precision angle