remove unused Variable{Float,Int} namedtuples from otTables/otConverters
This commit is contained in:
parent
0eb27e9878
commit
e8e2aa530b
@ -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,
|
||||
}
|
||||
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user