[designspaceLib] Fix recursion error with linkedUserValue in both directions

This commit is contained in:
Jany Belluz 2022-10-18 17:18:15 +01:00
parent bc03f09322
commit 12d13f0b26
5 changed files with 86 additions and 6 deletions

View File

@ -48,7 +48,6 @@ class StatNames:
styleMapStyleName: Optional[RibbiStyle] styleMapStyleName: Optional[RibbiStyle]
def getStatNames( def getStatNames(
doc: DesignSpaceDocument, userLocation: SimpleLocationDict doc: DesignSpaceDocument, userLocation: SimpleLocationDict
) -> StatNames: ) -> StatNames:
@ -89,7 +88,9 @@ def getStatNames(
# whenever a translation is missing. # whenever a translation is missing.
labels = _getAxisLabelsForUserLocation(doc.axes, userLocation) labels = _getAxisLabelsForUserLocation(doc.axes, userLocation)
if labels: if labels:
languages = set(language for label in labels for language in label.labelNames) languages = set(
language for label in labels for language in label.labelNames
)
languages.add("en") languages.add("en")
for language in languages: for language in languages:
styleName = " ".join( styleName = " ".join(
@ -214,16 +215,33 @@ def _getRibbiStyle(
axis = axes_by_tag.get("wght") axis = axes_by_tag.get("wght")
if axis is not None: if axis is not None:
for regular_label in axis.axisLabels: for regular_label in axis.axisLabels:
if regular_label.linkedUserValue == userLocation[axis.name]: if (
regular_label.linkedUserValue == userLocation[axis.name]
# In the "recursive" case where both the Regular has
# linkedUserValue pointing the Bold, and the Bold has
# linkedUserValue pointing to the Regular, only consider the
# first case: Regular (e.g. 400) has linkedUserValue pointing to
# Bold (e.g. 700, higher than Regular)
and regular_label.userValue < regular_label.linkedUserValue
):
regularUserLocation[axis.name] = regular_label.userValue regularUserLocation[axis.name] = regular_label.userValue
bold = True bold = True
break break
axis = axes_by_tag.get("ital") or axes_by_tag.get("slnt") axis = axes_by_tag.get("ital") or axes_by_tag.get("slnt")
if axis is not None: if axis is not None:
for urpright_label in axis.axisLabels: for upright_label in axis.axisLabels:
if urpright_label.linkedUserValue == userLocation[axis.name]: if (
regularUserLocation[axis.name] = urpright_label.userValue upright_label.linkedUserValue == userLocation[axis.name]
# In the "recursive" case where both the Upright has
# linkedUserValue pointing the Italic, and the Italic has
# linkedUserValue pointing to the Upright, only consider the
# first case: Upright (e.g. ital=0, slant=0) has linkedUserValue
# pointing to Italic (e.g ital=1, slant=-12, higher than
# Upright in absolute value)
and abs(upright_label.userValue) < abs(upright_label.linkedUserValue)
):
regularUserLocation[axis.name] = upright_label.userValue
italic = True italic = True
break break

View File

@ -21,6 +21,13 @@
<label uservalue="600" userminimum="450" usermaximum="650" name="Semi Bold"/> <label uservalue="600" userminimum="450" usermaximum="650" name="Semi Bold"/>
<label uservalue="700" userminimum="650" usermaximum="850" name="Bold"/> <label uservalue="700" userminimum="650" usermaximum="850" name="Bold"/>
<label uservalue="900" userminimum="850" usermaximum="900" name="Black"/> <label uservalue="900" userminimum="850" usermaximum="900" name="Black"/>
<!--
Add "recursive" linked user values, see:
https://github.com/fonttools/fonttools/issues/2852
https://github.com/fonttools/fonttools/discussions/2790
-->
<label uservalue="400" name="Regular" elidable="true" linkeduservalue="700"/>
<label uservalue="700" name="Bold" linkeduservalue="400"/>
</labels> </labels>
</axis> </axis>

View File

@ -78,6 +78,15 @@ def test_read_v5_document_simple(datadir):
AxisLabelDescriptor( AxisLabelDescriptor(
name="Black", userMinimum=850, userValue=900, userMaximum=900 name="Black", userMinimum=850, userValue=900, userMaximum=900
), ),
AxisLabelDescriptor(
name="Regular",
userValue=400,
linkedUserValue=700,
elidable=True,
),
AxisLabelDescriptor(
name="Bold", userValue=700, linkedUserValue=400
),
], ],
), ),
AxisDescriptor( AxisDescriptor(

View File

@ -61,6 +61,28 @@ def test_detect_ribbi_aktiv(datadir):
) )
def test_detect_ribbi_recursive(datadir):
doc = DesignSpaceDocument.fromfile(datadir / "test_v5.designspace")
assert getStatNames(doc, {"Weight": 700, "Width": 125, "Italic": 1}) == StatNames(
familyNames={
"en": "MasterFamilyName",
"fr": "Montserrat",
"ja": "モンセラート",
},
styleNames={
"en": "Wide Bold Italic",
},
postScriptFontName="MasterFamilyName-WideBoldItalic",
styleMapFamilyNames={
"en": "MasterFamilyName Wide",
"fr": "Montserrat Wide",
"ja": "モンセラート Wide",
},
styleMapStyleName="bold italic",
)
def test_getStatNames_on_ds4_doesnt_make_up_bad_names(datadir): def test_getStatNames_on_ds4_doesnt_make_up_bad_names(datadir):
"""See this issue on GitHub: https://github.com/googlefonts/ufo2ft/issues/630 """See this issue on GitHub: https://github.com/googlefonts/ufo2ft/issues/630

View File

@ -65,6 +65,18 @@ def test_getStatAxes(datadir):
"rangeMaxValue": 900.0, "rangeMaxValue": 900.0,
"rangeMinValue": 850.0, "rangeMinValue": 850.0,
}, },
{
"flags": 2,
"name": {"en": "Regular"},
"value": 400.0,
"linkedValue": 700.0,
},
{
"flags": 0,
"name": {"en": "Bold"},
"value": 700.0,
"linkedValue": 400.0,
},
], ],
"name": {"en": "Wéíght", "fa-IR": "قطر"}, "name": {"en": "Wéíght", "fa-IR": "قطر"},
"ordering": 2, "ordering": 2,
@ -120,6 +132,18 @@ def test_getStatAxes(datadir):
"rangeMaxValue": 850.0, "rangeMaxValue": 850.0,
"rangeMinValue": 650.0, "rangeMinValue": 650.0,
}, },
{
"flags": 2,
"name": {"en": "Regular"},
"value": 400.0,
"linkedValue": 700.0,
},
{
"flags": 0,
"name": {"en": "Bold"},
"value": 700.0,
"linkedValue": 400.0,
},
], ],
"name": {"en": "Wéíght", "fa-IR": "قطر"}, "name": {"en": "Wéíght", "fa-IR": "قطر"},
"ordering": 2, "ordering": 2,