wip instancer: support format 4 axisvalues
This commit is contained in:
parent
b95607513c
commit
b502471a08
@ -1298,49 +1298,74 @@ def instantiateVariableFont(
|
||||
return varfont
|
||||
|
||||
|
||||
def updateNameTable(varfont, axisLimits):
|
||||
nametable = varfont["name"]
|
||||
if "STAT" not in varfont:
|
||||
raise ValueError("Cannot update name table since there is no STAT table.")
|
||||
stat = varfont['STAT']
|
||||
def axisValuesFromAxisLimits(stat, axisLimits):
|
||||
|
||||
axisRecords = stat.table.DesignAxisRecord.Axis
|
||||
axisValues = stat.table.AxisValueArray.AxisValue
|
||||
|
||||
axisOrder = {a.AxisOrdering: a.AxisTag for a in axisRecords}
|
||||
keptAxisValues = []
|
||||
for axisValue in axisValues:
|
||||
# TODO Format 4
|
||||
if axisValue.Format == 4:
|
||||
continue
|
||||
format4 = [a for a in axisValues if a.Format == 4]
|
||||
nonformat4 = [a for a in axisValues if a not in format4]
|
||||
axisValues = format4 + nonformat4
|
||||
|
||||
axisTag = axisOrder[axisValue.AxisIndex]
|
||||
if axisTag in axisLimits:
|
||||
pinnedAxis = isinstance(axisLimits[axisTag], (float, int))
|
||||
else:
|
||||
pinnedAxis = False
|
||||
axisOrder = {a.AxisOrdering: a.AxisTag for a in axisRecords}
|
||||
pinnedAxes = set(k for k, v in axisLimits.items() if isinstance(v, (float, int)))
|
||||
|
||||
results, seen_axes = [], set()
|
||||
for axisValue in axisValues:
|
||||
|
||||
# Ignore axisValue if it has ELIDABLE_AXIS_VALUE_NAME flag enabled.
|
||||
# Enabling this flag will hide the axisValue in application font menus.
|
||||
# TODO this is too greedy! we need to retain wght axisValues
|
||||
if axisValue.Flags == 2:
|
||||
continue
|
||||
|
||||
if axisValue.Format in (1, 3):
|
||||
if axisValue.Format == 4:
|
||||
axisIndexes = set(r.AxisIndex for r in axisValue.AxisValueRecord)
|
||||
if seen_axes - axisIndexes != seen_axes:
|
||||
continue
|
||||
# TODO fix dup appends
|
||||
for rec in axisValue.AxisValueRecord:
|
||||
axisTag = axisOrder[rec.AxisIndex]
|
||||
if axisTag not in pinnedAxes:
|
||||
continue
|
||||
if rec.Value == axisLimits[axisTag]:
|
||||
seen_axes.add(rec.AxisIndex)
|
||||
results.append((rec.AxisIndex, axisValue))
|
||||
|
||||
elif axisValue.Format in (1, 3):
|
||||
axisTag = axisOrder[axisValue.AxisIndex]
|
||||
# Add axisValue if it's used to link to another variable font
|
||||
if axisTag not in axisLimits and axisValue.Value == 1.0:
|
||||
keptAxisValues.append(axisValue)
|
||||
seen_axes.add(rec.AxisIndex)
|
||||
results.append((axisValue.AxisIndex, axisValue))
|
||||
|
||||
if axisTag not in pinnedAxes:
|
||||
continue
|
||||
# Add axisValue if its value is in the axisLimits and the user has
|
||||
# pinned the axis
|
||||
elif pinnedAxis and axisValue.Value == axisLimits[axisTag]:
|
||||
keptAxisValues.append(axisValue)
|
||||
elif axisValue.Value == axisLimits[axisTag]:
|
||||
seen_axes.add(rec.AxisIndex)
|
||||
results.append((axisValue.AxisIndex,axisValue))
|
||||
|
||||
if axisValue.Format == 2:
|
||||
if pinnedAxis and axisLimits[axisTag] >= axisValue.RangeMinValue \
|
||||
elif axisValue.Format == 2:
|
||||
axisTag = axisOrder[axisValue.AxisIndex]
|
||||
if axisTag not in pinnedAxes:
|
||||
continue
|
||||
if axisLimits[axisTag] >= axisValue.RangeMinValue \
|
||||
and axisLimits[axisTag] <= axisValue.RangeMaxValue:
|
||||
keptAxisValues.append(axisValue)
|
||||
seen_axes.add(axisValue.AxisIndex)
|
||||
results.append((axisValue.AxisIndex, axisValue))
|
||||
return [v for k, v in sorted(results)]
|
||||
|
||||
_updateNameRecords(varfont, nametable, keptAxisValues)
|
||||
|
||||
def updateNameTable(varfont, axisLimits):
|
||||
if "STAT" not in varfont:
|
||||
raise ValueError("Cannot update name table since there is no STAT table.")
|
||||
stat = varfont['STAT']
|
||||
nametable = varfont["name"]
|
||||
|
||||
selectedAxisValues = axisValuesFromAxisLimits(stat, axisLimits)
|
||||
_updateNameRecords(varfont, nametable, selectedAxisValues)
|
||||
|
||||
|
||||
def _updateNameRecords(varfont, nametable, axisValues):
|
||||
@ -1383,12 +1408,14 @@ def _updateStyleRecords(
|
||||
# wwsAxes = frozenset(["wght", "wdth", "ital"])
|
||||
currentFamilyName = nametable.getName(NameID.TYPOGRAPHIC_FAMILY_NAME, *lang) or \
|
||||
nametable.getName(NameID.FAMILY_NAME, *lang)
|
||||
if not currentFamilyName:
|
||||
return
|
||||
currentFamilyName = currentFamilyName.toUnicode()
|
||||
|
||||
currentStyleName = nametable.getName(NameID.TYPOGRAPHIC_SUBFAMILY_NAME, *lang) or \
|
||||
nametable.getName(NameID.SUBFAMILY_NAME, *lang)
|
||||
# TODO cleanup
|
||||
if not currentFamilyName or not currentStyleName:
|
||||
print(f"Cannot update {lang} since it's missing a familyName nameID 1 or subFamilyName nameID 2 entry")
|
||||
return
|
||||
currentFamilyName = currentFamilyName.toUnicode()
|
||||
currentStyleName = currentStyleName.toUnicode()
|
||||
|
||||
ribbiName = " ".join([nametable.getName(a.ValueNameID, *lang).toUnicode() for a in ribbiAxisValues])
|
||||
@ -1396,7 +1423,7 @@ def _updateStyleRecords(
|
||||
|
||||
nameIDs = {
|
||||
NameID.FAMILY_NAME: currentFamilyName,
|
||||
NameID.SUBFAMILY_NAME: ribbiName or "Regular"
|
||||
NameID.SUBFAMILY_NAME: ribbiName or nametable.getName(NameID.SUBFAMILY_NAME, *lang).toUnicode()
|
||||
}
|
||||
if nonRibbiAxisValues:
|
||||
nameIDs[NameID.FAMILY_NAME] = f"{currentFamilyName} {nonRibbiName}"
|
||||
|
@ -1924,7 +1924,8 @@ def _get_name_records(varfont):
|
||||
}
|
||||
|
||||
|
||||
def test_updateNameTable(varfont):
|
||||
def test_updateNameTable_with_registered_axes(varfont):
|
||||
# Regular
|
||||
instancer.updateNameTable(varfont, {"wght": 400, "wdth": 100})
|
||||
names = _get_name_records(varfont)
|
||||
assert names[(1, 3, 1, 0x409)] == "Test Variable Font"
|
||||
@ -1933,6 +1934,7 @@ def test_updateNameTable(varfont):
|
||||
assert (16, 3, 1, 0x409) not in names
|
||||
assert (17, 3, 1, 0x409) not in names
|
||||
|
||||
# Black
|
||||
instancer.updateNameTable(varfont, {"wght": 900, "wdth": 100})
|
||||
names = _get_name_records(varfont)
|
||||
assert names[(1, 3, 1, 0x409)] == "Test Variable Font Black"
|
||||
@ -1941,6 +1943,7 @@ def test_updateNameTable(varfont):
|
||||
assert names[(16, 3, 1, 0x409)] == "Test Variable Font"
|
||||
assert names[(17, 3, 1, 0x409)] == "Black"
|
||||
|
||||
# Thin
|
||||
instancer.updateNameTable(varfont, {"wght": 100, "wdth": 100})
|
||||
names = _get_name_records(varfont)
|
||||
assert names[(1, 3, 1, 0x409)] == "Test Variable Font Thin"
|
||||
@ -1949,8 +1952,47 @@ def test_updateNameTable(varfont):
|
||||
assert names[(16, 3, 1, 0x409)] == "Test Variable Font"
|
||||
assert names[(17, 3, 1, 0x409)] == "Thin"
|
||||
|
||||
# TODO (Marc F) this doesn't work because our test font is using Format 4 for wdth axis
|
||||
instancer.updateNameTable(varfont, {"wdth": 79, "wdth": 400})
|
||||
# Thin Condensed
|
||||
instancer.updateNameTable(varfont, {"wdth": 79, "wght": 100})
|
||||
names = _get_name_records(varfont)
|
||||
assert names[(1, 3, 1, 0x409)] == "Test Variable Font Thin Condensed"
|
||||
assert names[(2, 3, 1, 0x409)] == "Regular"
|
||||
assert names[(6, 3, 1, 0x409)] == "TestVariableFont-ThinCondensed"
|
||||
assert names[(16, 3, 1, 0x409)] == "Test Variable Font"
|
||||
assert names[(17, 3, 1, 0x409)] == "Thin Condensed"
|
||||
|
||||
|
||||
def test_updateNameTable_with_multilingual_names(varfont):
|
||||
name = varfont["name"]
|
||||
name.setName("Test Variable Font", 1, 3, 1, 0x405)
|
||||
name.setName("Normal", 2, 3, 1, 0x405)
|
||||
name.setName("Normal", 261, 3, 1, 0x405) # nameID 261=Regular STAT entry
|
||||
name.setName("Negreta",266, 3, 1, 0x405) # nameID 266=Black STAT entry
|
||||
name.setName("Zhuštěné", 279, 3, 1, 0x405) # nameID 279=Condensed STAT entry
|
||||
|
||||
# Regular | Normal
|
||||
instancer.updateNameTable(varfont, {"wdth": 100, "wght": 400})
|
||||
names = _get_name_records(varfont)
|
||||
assert names[(1, 3, 1, 0x405)] == "Test Variable Font"
|
||||
assert names[(2, 3, 1, 0x405)] == "Normal"
|
||||
assert (16, 3, 1, 0x405) not in names
|
||||
assert (17, 3, 1, 0x405) not in names
|
||||
|
||||
# Black | Negreta
|
||||
instancer.updateNameTable(varfont, {"wdth": 100, "wght": 900})
|
||||
names = _get_name_records(varfont)
|
||||
assert names[(1, 3, 1, 0x405)] == "Test Variable Font Negreta"
|
||||
assert names[(2, 3, 1, 0x405)] == "Normal"
|
||||
assert names[(16, 3, 1, 0x405)] == "Test Variable Font"
|
||||
assert names[(17, 3, 1, 0x405)] == "Negreta"
|
||||
|
||||
# Black Condensed | Negreta Zhuštěné
|
||||
instancer.updateNameTable(varfont, {"wdth": 79, "wght": 900})
|
||||
names = _get_name_records(varfont)
|
||||
assert names[(1, 3, 1, 0x405)] == "Test Variable Font Negreta Zhuštěné"
|
||||
assert names[(2, 3, 1, 0x405)] == "Normal"
|
||||
assert names[(16, 3, 1, 0x405)] == "Test Variable Font"
|
||||
assert names[(17, 3, 1, 0x405)] == "Negreta Zhuštěné"
|
||||
|
||||
|
||||
def test_sanityCheckVariableTables(varfont):
|
||||
|
Loading…
x
Reference in New Issue
Block a user