From 1e989abec4bb8a21c8ff22464d06876d92c1818a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 2 Feb 2024 13:11:28 -0700 Subject: [PATCH] [designspaceLib] Add "description" to and Fixes https://github.com/fonttools/fonttools/issues/3435 --- Doc/source/designspaceLib/xml.rst | 12 +++-- Lib/fontTools/designspaceLib/__init__.py | 48 ++++++++++++++++--- .../data/test_avar2.designspace | 4 +- Tests/designspaceLib/designspace_test.py | 6 +++ 4 files changed, 59 insertions(+), 11 deletions(-) diff --git a/Doc/source/designspaceLib/xml.rst b/Doc/source/designspaceLib/xml.rst index f6baa54e5..7b59dbb17 100644 --- a/Doc/source/designspaceLib/xml.rst +++ b/Doc/source/designspaceLib/xml.rst @@ -263,11 +263,14 @@ Example of all axis elements together ```` element ====================== -- Define axis mappings. +- Define an axis mappings group. - Child element of ``axes`` +.. rubric:: Attributes - .. versionadded:: 5.1 +- ``description``: optional, string. the description of this mappings group + + .. versionadded:: 5.2 ```` element @@ -276,8 +279,11 @@ Example of all axis elements together - Defines an axis mapping. - Child element of ```` +.. rubric:: Attributes - .. versionadded:: 5.1 +- ``description``: optional, string. the description of this mapping + + .. versionadded:: 5.2 ```` element diff --git a/Lib/fontTools/designspaceLib/__init__.py b/Lib/fontTools/designspaceLib/__init__.py index c5d31cdc4..d6789f5f6 100644 --- a/Lib/fontTools/designspaceLib/__init__.py +++ b/Lib/fontTools/designspaceLib/__init__.py @@ -476,7 +476,14 @@ class AxisMappingDescriptor(SimpleDescriptor): _attrs = ["inputLocation", "outputLocation"] - def __init__(self, *, inputLocation=None, outputLocation=None): + def __init__( + self, + *, + inputLocation=None, + outputLocation=None, + description=None, + groupDescription=None, + ): self.inputLocation: SimpleLocationDict = inputLocation or {} """dict. Axis values for the input of the mapping, in design space coordinates. @@ -491,6 +498,20 @@ class AxisMappingDescriptor(SimpleDescriptor): .. versionadded:: 5.1 """ + self.description = description + """string. A description of the mapping. + + varLib. + + .. versionadded:: 5.2 + """ + self.groupDescription = groupDescription + """string. A description of the group of mappings. + + varLib. + + .. versionadded:: 5.2 + """ class InstanceDescriptor(SimpleDescriptor): @@ -1421,10 +1442,19 @@ class BaseDocWriter(object): self._addAxis(axisObject) if self.documentObject.axisMappings: - mappingsElement = ET.Element("mappings") - self.root.findall(".axes")[0].append(mappingsElement) + mappingsElement = None + lastGroup = object() for mappingObject in self.documentObject.axisMappings: + if getattr(mappingObject, "groupDescription", None) != lastGroup: + if mappingsElement is not None: + self.root.findall(".axes")[0].append(mappingsElement) + lastGroup = getattr(mappingObject, "groupDescription", None) + mappingsElement = ET.Element("mappings") + if lastGroup is not None: + mappingsElement.attrib["description"] = lastGroup self._addAxisMapping(mappingsElement, mappingObject) + if mappingsElement is not None: + self.root.findall(".axes")[0].append(mappingsElement) if self.documentObject.locationLabels: labelsElement = ET.Element("labels") @@ -1586,6 +1616,8 @@ class BaseDocWriter(object): def _addAxisMapping(self, mappingsElement, mappingObject): mappingElement = ET.Element("mapping") + if getattr(mappingObject, "description", None) is not None: + mappingElement.attrib["description"] = mappingObject.description for what in ("inputLocation", "outputLocation"): whatObject = getattr(mappingObject, what, None) if whatObject is None: @@ -2081,10 +2113,11 @@ class BaseDocReader(LogMixin): self.documentObject.axes.append(axisObject) self.axisDefaults[axisObject.name] = axisObject.default - mappingsElement = self.root.find(".axes/mappings") self.documentObject.axisMappings = [] - if mappingsElement is not None: + for mappingsElement in self.root.findall(".axes/mappings"): + groupDescription = mappingsElement.attrib.get("description") for mappingElement in mappingsElement.findall("mapping"): + description = mappingElement.attrib.get("description") inputElement = mappingElement.find("input") outputElement = mappingElement.find("output") inputLoc = {} @@ -2098,7 +2131,10 @@ class BaseDocReader(LogMixin): value = float(dimElement.attrib["xvalue"]) outputLoc[name] = value axisMappingObject = self.axisMappingDescriptorClass( - inputLocation=inputLoc, outputLocation=outputLoc + inputLocation=inputLoc, + outputLocation=outputLoc, + description=description, + groupDescription=groupDescription, ) self.documentObject.axisMappings.append(axisMappingObject) diff --git a/Tests/designspaceLib/data/test_avar2.designspace b/Tests/designspaceLib/data/test_avar2.designspace index d54588a66..7c482a9bf 100644 --- a/Tests/designspaceLib/data/test_avar2.designspace +++ b/Tests/designspaceLib/data/test_avar2.designspace @@ -19,8 +19,8 @@ - - + + diff --git a/Tests/designspaceLib/designspace_test.py b/Tests/designspaceLib/designspace_test.py index ceddfd10f..52775bda2 100644 --- a/Tests/designspaceLib/designspace_test.py +++ b/Tests/designspaceLib/designspace_test.py @@ -720,6 +720,12 @@ def test_axisMappingsRoundtrip(tmpdir): assert [mapping.outputLocation for mapping in doc.axisMappings] == [ mapping.outputLocation for mapping in doc2.axisMappings ] + assert [mapping.description for mapping in doc.axisMappings] == [ + mapping.description for mapping in doc2.axisMappings + ] + assert [mapping.groupDescription for mapping in doc.axisMappings] == [ + mapping.groupDescription for mapping in doc2.axisMappings + ] def test_rulesConditions(tmpdir):