aboutsummaryrefslogtreecommitdiff
path: root/Lib/fontTools/colorLib/table_builder.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/fontTools/colorLib/table_builder.py')
-rw-r--r--Lib/fontTools/colorLib/table_builder.py61
1 files changed, 35 insertions, 26 deletions
diff --git a/Lib/fontTools/colorLib/table_builder.py b/Lib/fontTools/colorLib/table_builder.py
index 763115b9..6fba6b0f 100644
--- a/Lib/fontTools/colorLib/table_builder.py
+++ b/Lib/fontTools/colorLib/table_builder.py
@@ -17,9 +17,10 @@ from fontTools.ttLib.tables.otConverters import (
Short,
UInt8,
UShort,
+ VarInt16,
+ VarUInt16,
IntValue,
FloatValue,
- OptionalValue,
)
from fontTools.misc.roundTools import otRound
@@ -38,7 +39,7 @@ class BuildCallback(enum.Enum):
"""
AFTER_BUILD = enum.auto()
- """Keyed on (CREATE_DEFAULT, class[, Format if available]).
+ """Keyed on (CREATE_DEFAULT, class).
Receives no arguments.
Should return a new instance of class.
"""
@@ -49,29 +50,37 @@ 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)
-def _split_format(cls, source):
+def _set_format(dest, source):
if _isNonStrSequence(source):
- assert len(source) > 0, f"{cls} needs at least format from {source}"
- fmt, remainder = source[0], source[1:]
+ assert len(source) > 0, f"{type(dest)} needs at least format from {source}"
+ dest.Format = source[0]
+ source = source[1:]
elif isinstance(source, collections.abc.Mapping):
- assert "Format" in source, f"{cls} needs at least Format from {source}"
- remainder = source.copy()
- fmt = remainder.pop("Format")
+ assert "Format" in source, f"{type(dest)} needs at least Format from {source}"
+ dest.Format = source["Format"]
else:
- raise ValueError(f"Not sure how to populate {cls} from {source}")
+ raise ValueError(f"Not sure how to populate {type(dest)} from {source}")
assert isinstance(
- fmt, collections.abc.Hashable
- ), f"{cls} Format is not hashable: {fmt!r}"
+ dest.Format, collections.abc.Hashable
+ ), f"{type(dest)} Format is not hashable: {dest.Format}"
assert (
- fmt in cls.convertersByName
- ), f"{cls} invalid Format: {fmt!r}"
+ dest.Format in dest.convertersByName
+ ), f"{dest.Format} invalid Format of {cls}"
- return fmt, remainder
+ return source
class TableBuilder:
@@ -88,9 +97,13 @@ class TableBuilder:
self._callbackTable = callbackTable
def _convert(self, dest, field, converter, value):
+ tupleClass = getattr(converter, "tupleClass", None)
enumClass = getattr(converter, "enumClass", None)
- if enumClass:
+ if tupleClass:
+ value = convertTupleClass(tupleClass, value)
+
+ elif enumClass:
if isinstance(value, enumClass):
pass
elif isinstance(value, str):
@@ -127,11 +140,6 @@ class TableBuilder:
return source
callbackKey = (cls,)
- fmt = None
- if issubclass(cls, FormatSwitchingBaseTable):
- fmt, source = _split_format(cls, source)
- callbackKey = (cls, fmt)
-
dest = self._callbackTable.get(
(BuildCallback.CREATE_DEFAULT,) + callbackKey, lambda: cls()
)()
@@ -142,9 +150,11 @@ class TableBuilder:
# For format switchers we need to resolve converters based on format
if issubclass(cls, FormatSwitchingBaseTable):
- dest.Format = fmt
+ source = _set_format(dest, source)
+
convByName = _assignable(convByName[dest.Format])
skippedFields.add("Format")
+ callbackKey = (cls, dest.Format)
# Convert sequence => mapping so before thunk only has to handle one format
if _isNonStrSequence(source):
@@ -172,10 +182,6 @@ class TableBuilder:
# let's try as a 1-tuple
dest = self.build(cls, (source,))
- for field, conv in convByName.items():
- if not hasattr(dest, field) and isinstance(conv, OptionalValue):
- setattr(dest, field, conv.DEFAULT)
-
dest = self._callbackTable.get(
(BuildCallback.AFTER_BUILD,) + callbackKey, lambda d: d
)(dest)
@@ -204,8 +210,11 @@ class TableUnbuilder:
continue
value = getattr(table, converter.name)
+ tupleClass = getattr(converter, "tupleClass", None)
enumClass = getattr(converter, "enumClass", None)
- if enumClass:
+ if tupleClass:
+ source[converter.name] = tuple(value)
+ elif enumClass:
source[converter.name] = value.name.lower()
elif isinstance(converter, Struct):
if converter.repeat: