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)
This commit is contained in:
Cosimo Lupo 2022-06-14 18:06:15 +01:00
parent 676a66fad3
commit 82460bd368

View File

@ -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