diff options
Diffstat (limited to 'Lib/fontTools/designspaceLib/types.py')
-rw-r--r-- | Lib/fontTools/designspaceLib/types.py | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/Lib/fontTools/designspaceLib/types.py b/Lib/fontTools/designspaceLib/types.py index 8afea96c..80ba9d6d 100644 --- a/Lib/fontTools/designspaceLib/types.py +++ b/Lib/fontTools/designspaceLib/types.py @@ -1,12 +1,15 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Dict, List, Optional, Union +from typing import Dict, List, Optional, Union, cast from fontTools.designspaceLib import ( + AxisDescriptor, DesignSpaceDocument, + DesignSpaceDocumentError, RangeAxisSubsetDescriptor, SimpleLocationDict, + ValueAxisSubsetDescriptor, VariableFontDescriptor, ) @@ -89,6 +92,10 @@ def userRegionToDesignRegion(doc: DesignSpaceDocument, userRegion: Region) -> Re designRegion = {} for name, value in userRegion.items(): axis = doc.getAxis(name) + if axis is None: + raise DesignSpaceDocumentError( + f"Cannot find axis named '{name}' for region." + ) if isinstance(value, (float, int)): designRegion[name] = axis.map_forward(value) else: @@ -107,16 +114,34 @@ def getVFUserRegion(doc: DesignSpaceDocument, vf: VariableFontDescriptor) -> Reg # - it's a single location = use it to know which rules should apply in the VF for axisSubset in vf.axisSubsets: axis = doc.getAxis(axisSubset.name) - if isinstance(axisSubset, RangeAxisSubsetDescriptor): + if axis is None: + raise DesignSpaceDocumentError( + f"Cannot find axis named '{axisSubset.name}' for variable font '{vf.name}'." + ) + if hasattr(axisSubset, "userMinimum"): + # Mypy doesn't support narrowing union types via hasattr() + # TODO(Python 3.10): use TypeGuard + # https://mypy.readthedocs.io/en/stable/type_narrowing.html + axisSubset = cast(RangeAxisSubsetDescriptor, axisSubset) + if not hasattr(axis, "minimum"): + raise DesignSpaceDocumentError( + f"Cannot select a range over '{axis.name}' for variable font '{vf.name}' " + "because it's a discrete axis, use only 'userValue' instead." + ) + axis = cast(AxisDescriptor, axis) vfUserRegion[axis.name] = Range( max(axisSubset.userMinimum, axis.minimum), min(axisSubset.userMaximum, axis.maximum), axisSubset.userDefault or axis.default, ) else: + axisSubset = cast(ValueAxisSubsetDescriptor, axisSubset) vfUserRegion[axis.name] = axisSubset.userValue # Any axis not mentioned explicitly has a single location = default value for axis in doc.axes: if axis.name not in vfUserRegion: + assert isinstance( + axis.default, (int, float) + ), f"Axis '{axis.name}' has no valid default value." vfUserRegion[axis.name] = axis.default return vfUserRegion |