remove unused Variable{Float,Int} namedtuples from otTables/otConverters

This commit is contained in:
Cosimo Lupo 2021-07-22 11:51:25 +01:00
parent 0eb27e9878
commit e8e2aa530b
4 changed files with 37 additions and 206 deletions

View File

@ -26,20 +26,10 @@ from fontTools.ttLib.tables import C_O_L_R_
from fontTools.ttLib.tables import C_P_A_L_
from fontTools.ttLib.tables import _n_a_m_e
from fontTools.ttLib.tables import otTables as ot
from fontTools.ttLib.tables.otTables import (
ExtendMode,
CompositeMode,
VariableValue,
VariableFloat,
VariableInt,
)
from fontTools.ttLib.tables.otTables import ExtendMode, CompositeMode
from .errors import ColorLibError
from .geometry import round_start_circle_stable_containment
from .table_builder import (
convertTupleClass,
BuildCallback,
TableBuilder,
)
from .table_builder import BuildCallback, TableBuilder
# TODO move type aliases to colorLib.types?
@ -52,52 +42,45 @@ _ColorGlyphsV0Dict = Dict[str, Sequence[Tuple[str, int]]]
MAX_PAINT_COLR_LAYER_COUNT = 255
_DEFAULT_ALPHA = VariableFloat(1.0)
_DEFAULT_ALPHA = 1.0
_MAX_REUSE_LEN = 32
def _beforeBuildPaintVarRadialGradient(paint, source, srcMapFn=lambda v: v):
# normalize input types (which may or may not specify a varIdx)
x0 = convertTupleClass(VariableFloat, source["x0"])
y0 = convertTupleClass(VariableFloat, source["y0"])
r0 = convertTupleClass(VariableFloat, source["r0"])
x1 = convertTupleClass(VariableFloat, source["x1"])
y1 = convertTupleClass(VariableFloat, source["y1"])
r1 = convertTupleClass(VariableFloat, source["r1"])
def _beforeBuildPaintRadialGradient(paint, source):
x0 = source["x0"]
y0 = source["y0"]
r0 = source["r0"]
x1 = source["x1"]
y1 = source["y1"]
r1 = source["r1"]
# TODO apparently no builder_test confirms this works (?)
# avoid abrupt change after rounding when c0 is near c1's perimeter
c = round_start_circle_stable_containment(
(x0.value, y0.value), r0.value, (x1.value, y1.value), r1.value
)
x0, y0 = x0._replace(value=c.centre[0]), y0._replace(value=c.centre[1])
r0 = r0._replace(value=c.radius)
c = round_start_circle_stable_containment((x0, y0), r0, (x1, y1), r1)
x0, y0 = c.centre
r0 = c.radius
# update source to ensure paint is built with corrected values
source["x0"] = srcMapFn(x0)
source["y0"] = srcMapFn(y0)
source["r0"] = srcMapFn(r0)
source["x1"] = srcMapFn(x1)
source["y1"] = srcMapFn(y1)
source["r1"] = srcMapFn(r1)
source["x0"] = x0
source["y0"] = y0
source["r0"] = r0
source["x1"] = x1
source["y1"] = y1
source["r1"] = r1
return paint, source
def _beforeBuildPaintRadialGradient(paint, source):
return _beforeBuildPaintVarRadialGradient(paint, source, lambda v: v.value)
def _defaultColorStop():
colorStop = ot.ColorStop()
colorStop.Alpha = _DEFAULT_ALPHA.value
colorStop.Alpha = _DEFAULT_ALPHA
return colorStop
def _defaultVarColorStop():
colorStop = ot.VarColorStop()
colorStop.Alpha = _DEFAULT_ALPHA.value
colorStop.Alpha = _DEFAULT_ALPHA
return colorStop
@ -115,7 +98,7 @@ def _defaultVarColorLine():
def _defaultPaintSolid():
paint = ot.Paint()
paint.Alpha = _DEFAULT_ALPHA.value
paint.Alpha = _DEFAULT_ALPHA
return paint
@ -130,14 +113,21 @@ def _buildPaintCallbacks():
BuildCallback.BEFORE_BUILD,
ot.Paint,
ot.PaintFormat.PaintVarRadialGradient,
): _beforeBuildPaintVarRadialGradient,
): _beforeBuildPaintRadialGradient,
(BuildCallback.CREATE_DEFAULT, ot.ColorStop): _defaultColorStop,
(BuildCallback.CREATE_DEFAULT, ot.VarColorStop): _defaultVarColorStop,
(BuildCallback.CREATE_DEFAULT, ot.ColorLine): _defaultColorLine,
(BuildCallback.CREATE_DEFAULT, ot.VarColorLine): _defaultVarColorLine,
(BuildCallback.CREATE_DEFAULT, ot.VarColorLine): _defaultVarColorLine,
(BuildCallback.CREATE_DEFAULT, ot.Paint, ot.PaintFormat.PaintSolid): _defaultPaintSolid,
(BuildCallback.CREATE_DEFAULT, ot.Paint, ot.PaintFormat.PaintVarSolid): _defaultPaintSolid,
(
BuildCallback.CREATE_DEFAULT,
ot.Paint,
ot.PaintFormat.PaintSolid,
): _defaultPaintSolid,
(
BuildCallback.CREATE_DEFAULT,
ot.Paint,
ot.PaintFormat.PaintVarSolid,
): _defaultPaintSolid,
}

View File

@ -17,8 +17,6 @@ from fontTools.ttLib.tables.otConverters import (
Short,
UInt8,
UShort,
VarInt16,
VarUInt16,
IntValue,
FloatValue,
)
@ -50,14 +48,6 @@ def _assignable(convertersByName):
return {k: v for k, v in convertersByName.items() if not isinstance(v, ComputedInt)}
def convertTupleClass(tupleClass, value):
if isinstance(value, tupleClass):
return value
if isinstance(value, tuple):
return tupleClass(*value)
return tupleClass(value)
def _isNonStrSequence(value):
return isinstance(value, collections.abc.Sequence) and not isinstance(value, str)
@ -97,13 +87,9 @@ class TableBuilder:
self._callbackTable = callbackTable
def _convert(self, dest, field, converter, value):
tupleClass = getattr(converter, "tupleClass", None)
enumClass = getattr(converter, "enumClass", None)
if tupleClass:
value = convertTupleClass(tupleClass, value)
elif enumClass:
if enumClass:
if isinstance(value, enumClass):
pass
elif isinstance(value, str):
@ -213,11 +199,8 @@ class TableUnbuilder:
continue
value = getattr(table, converter.name)
tupleClass = getattr(converter, "tupleClass", None)
enumClass = getattr(converter, "enumClass", None)
if tupleClass:
source[converter.name] = tuple(value)
elif enumClass:
if enumClass:
source[converter.name] = value.name.lower()
elif isinstance(converter, Struct):
if converter.repeat:

View File

@ -14,8 +14,8 @@ from .otBase import (CountReference, FormatSwitchingBaseTable,
OTTableReader, OTTableWriter, ValueRecordFactory)
from .otTables import (lookupTypes, AATStateTable, AATState, AATAction,
ContextualMorphAction, LigatureMorphAction,
InsertionMorphAction, MorxSubtable, VariableFloat,
VariableInt, ExtendMode as _ExtendMode,
InsertionMorphAction, MorxSubtable,
ExtendMode as _ExtendMode,
CompositeMode as _CompositeMode)
from itertools import zip_longest
from functools import partial
@ -1700,104 +1700,6 @@ class LookupFlag(UShort):
xmlWriter.comment(" ".join(flags))
xmlWriter.newline()
def _issubclass_namedtuple(x):
return (
issubclass(x, tuple)
and getattr(x, "_fields", None) is not None
)
class _NamedTupleConverter(BaseConverter):
# subclasses must override this
tupleClass = NotImplemented
# List[SimpleValue]
converterClasses = NotImplemented
def __init__(self, name, repeat, aux, tableClass=None):
# we expect all converters to be subclasses of SimpleValue
assert all(issubclass(klass, SimpleValue) for klass in self.converterClasses)
assert _issubclass_namedtuple(self.tupleClass), repr(self.tupleClass)
assert len(self.tupleClass._fields) == len(self.converterClasses)
assert tableClass is None # tableClass is unused by SimplValues
BaseConverter.__init__(self, name, repeat, aux)
self.converters = [
klass(name=name, repeat=None, aux=None)
for name, klass in zip(self.tupleClass._fields, self.converterClasses)
]
self.convertersByName = {conv.name: conv for conv in self.converters}
# returned by getRecordSize method
self.staticSize = sum(c.staticSize for c in self.converters)
def read(self, reader, font, tableDict):
kwargs = {
conv.name: conv.read(reader, font, tableDict)
for conv in self.converters
}
return self.tupleClass(**kwargs)
def write(self, writer, font, tableDict, value, repeatIndex=None):
for conv in self.converters:
v = getattr(value, conv.name)
# repeatIndex is unused for SimpleValues
conv.write(writer, font, tableDict, v, repeatIndex=None)
def xmlWrite(self, xmlWriter, font, value, name, attrs):
assert value is not None
defaults = value.__new__.__defaults__ or ()
assert len(self.converters) >= len(defaults)
values = {}
required = object()
for conv, default in zip_longest(
reversed(self.converters),
reversed(defaults),
fillvalue=required,
):
v = getattr(value, conv.name)
if default is required or v != default:
values[conv.name] = conv.toString(v)
if attrs is None:
attrs = []
attrs.extend(
(conv.name, values[conv.name])
for conv in self.converters
if conv.name in values
)
xmlWriter.simpletag(name, attrs)
xmlWriter.newline()
def xmlRead(self, attrs, content, font):
converters = self.convertersByName
kwargs = {
k: converters[k].fromString(v)
for k, v in attrs.items()
}
return self.tupleClass(**kwargs)
class VarFixed(_NamedTupleConverter):
tupleClass = VariableFloat
converterClasses = [Fixed, ULong]
class VarF2Dot14(_NamedTupleConverter):
tupleClass = VariableFloat
converterClasses = [F2Dot14, ULong]
class VarInt16(_NamedTupleConverter):
tupleClass = VariableInt
converterClasses = [Short, ULong]
class VarUInt16(_NamedTupleConverter):
tupleClass = VariableInt
converterClasses = [UShort, ULong]
class VarAngle(_NamedTupleConverter):
tupleClass = VariableFloat
converterClasses = [F2Dot14, ULong]
class _UInt8Enum(UInt8):
enumClass = NotImplemented
@ -1867,11 +1769,4 @@ converterMapping = {
"OffsetTo": lambda C: partial(Table, tableClass=C),
"LOffsetTo": lambda C: partial(LTable, tableClass=C),
"LOffset24To": lambda C: partial(Table24, tableClass=C),
# Variable types
"VarFixed": VarFixed,
"VarF2Dot14": VarF2Dot14,
"VarInt16": VarInt16,
"VarUInt16": VarUInt16,
"VarAngle": VarAngle,
}

View File

@ -1297,43 +1297,6 @@ class BaseGlyphList(BaseTable):
return self.__dict__.copy()
class VariableValue(namedtuple("VariableValue", ["value", "varIdx"])):
__slots__ = ()
_value_mapper = None
def __new__(cls, value, varIdx=0xFFFFFFFF):
return super().__new__(
cls,
cls._value_mapper(value) if cls._value_mapper else value,
varIdx
)
@classmethod
def _make(cls, iterable):
if cls._value_mapper:
it = iter(iterable)
try:
value = next(it)
except StopIteration:
pass
else:
value = cls._value_mapper(value)
iterable = itertools.chain((value,), it)
return super()._make(iterable)
class VariableFloat(VariableValue):
__slots__ = ()
_value_mapper = float
class VariableInt(VariableValue):
__slots__ = ()
_value_mapper = otRound
class ExtendMode(IntEnum):
PAD = 0
REPEAT = 1