Merge pull request #1652 from anthrotype/varlib-set-default-OS2-classes
varLib: add set_default_weight_width_slant
This commit is contained in:
commit
06fe38dd6b
@ -857,6 +857,45 @@ def load_designspace(designspace):
|
||||
)
|
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/typography/opentype/spec/os2#uswidthclass
|
||||
WDTH_VALUE_TO_OS2_WIDTH_CLASS = {
|
||||
50: 1,
|
||||
62.5: 2,
|
||||
75: 3,
|
||||
87.5: 4,
|
||||
100: 5,
|
||||
112.5: 6,
|
||||
125: 7,
|
||||
150: 8,
|
||||
200: 9,
|
||||
}
|
||||
|
||||
|
||||
def set_default_weight_width_slant(font, location):
|
||||
if "OS/2" in font:
|
||||
if "wght" in location:
|
||||
weight_class = otRound(max(1, min(location["wght"], 1000)))
|
||||
if font["OS/2"].usWeightClass != weight_class:
|
||||
log.info("Setting OS/2.usWidthClass = %s", weight_class)
|
||||
font["OS/2"].usWeightClass = weight_class
|
||||
|
||||
if "wdth" in location:
|
||||
# map 'wdth' axis (50..200) to OS/2.usWidthClass (1..9), rounding to closest
|
||||
widthValue = min(max(location["wdth"], 50), 200)
|
||||
widthClass = otRound(
|
||||
models.piecewiseLinearMap(widthValue, WDTH_VALUE_TO_OS2_WIDTH_CLASS)
|
||||
)
|
||||
if font["OS/2"].usWidthClass != widthClass:
|
||||
log.info("Setting OS/2.usWidthClass = %s", widthClass)
|
||||
font["OS/2"].usWidthClass = widthClass
|
||||
|
||||
if "slnt" in location and "post" in font:
|
||||
italicAngle = max(-90, min(location["slnt"], 90))
|
||||
if font["post"].italicAngle != italicAngle:
|
||||
log.info("Setting post.italicAngle = %s", italicAngle)
|
||||
font["post"].italicAngle = italicAngle
|
||||
|
||||
|
||||
def build(designspace, master_finder=lambda s:s, exclude=[], optimize=True):
|
||||
"""
|
||||
Build variation font from a designspace file.
|
||||
@ -930,6 +969,10 @@ def build(designspace, master_finder=lambda s:s, exclude=[], optimize=True):
|
||||
post.extraNames = []
|
||||
post.mapping = {}
|
||||
|
||||
set_default_weight_width_slant(
|
||||
vf, location={axis.axisTag: axis.defaultValue for axis in vf["fvar"].axes}
|
||||
)
|
||||
|
||||
for tag in exclude:
|
||||
if tag in vf:
|
||||
del vf[tag]
|
||||
|
@ -55,7 +55,7 @@
|
||||
will be recalculated by the compiler -->
|
||||
<version value="4"/>
|
||||
<xAvgCharWidth value="506"/>
|
||||
<usWeightClass value="400"/>
|
||||
<usWeightClass value="368"/>
|
||||
<usWidthClass value="5"/>
|
||||
<fsType value="00000000 00000100"/>
|
||||
<ySubscriptXSize value="650"/>
|
||||
|
@ -55,7 +55,7 @@
|
||||
will be recalculated by the compiler -->
|
||||
<version value="4"/>
|
||||
<xAvgCharWidth value="580"/>
|
||||
<usWeightClass value="400"/>
|
||||
<usWeightClass value="350"/>
|
||||
<usWidthClass value="5"/>
|
||||
<fsType value="00000000 00000100"/>
|
||||
<ySubscriptXSize value="650"/>
|
||||
|
@ -4,6 +4,7 @@ from fontTools.ttLib import TTFont, newTable
|
||||
from fontTools.varLib import build
|
||||
from fontTools.varLib.mutator import instantiateVariableFont
|
||||
from fontTools.varLib import main as varLib_main, load_masters
|
||||
from fontTools.varLib import set_default_weight_width_slant
|
||||
from fontTools.designspaceLib import (
|
||||
DesignSpaceDocumentError, DesignSpaceDocument, SourceDescriptor,
|
||||
)
|
||||
@ -661,5 +662,81 @@ def _extract_flat_kerning(font, pairpos_table):
|
||||
return extracted_kerning
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def ttFont():
|
||||
f = TTFont()
|
||||
f["OS/2"] = newTable("OS/2")
|
||||
f["OS/2"].usWeightClass = 400
|
||||
f["OS/2"].usWidthClass = 100
|
||||
f["post"] = newTable("post")
|
||||
f["post"].italicAngle = 0
|
||||
return f
|
||||
|
||||
|
||||
class SetDefaultWeightWidthSlantTest(object):
|
||||
@pytest.mark.parametrize(
|
||||
"location, expected",
|
||||
[
|
||||
({"wght": 0}, 1),
|
||||
({"wght": 1}, 1),
|
||||
({"wght": 100}, 100),
|
||||
({"wght": 1000}, 1000),
|
||||
({"wght": 1001}, 1000),
|
||||
],
|
||||
)
|
||||
def test_wght(self, ttFont, location, expected):
|
||||
set_default_weight_width_slant(ttFont, location)
|
||||
|
||||
assert ttFont["OS/2"].usWeightClass == expected
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"location, expected",
|
||||
[
|
||||
({"wdth": 0}, 1),
|
||||
({"wdth": 56}, 1),
|
||||
({"wdth": 57}, 2),
|
||||
({"wdth": 62.5}, 2),
|
||||
({"wdth": 75}, 3),
|
||||
({"wdth": 87.5}, 4),
|
||||
({"wdth": 100}, 5),
|
||||
({"wdth": 112.5}, 6),
|
||||
({"wdth": 125}, 7),
|
||||
({"wdth": 150}, 8),
|
||||
({"wdth": 200}, 9),
|
||||
({"wdth": 201}, 9),
|
||||
({"wdth": 1000}, 9),
|
||||
],
|
||||
)
|
||||
def test_wdth(self, ttFont, location, expected):
|
||||
set_default_weight_width_slant(ttFont, location)
|
||||
|
||||
assert ttFont["OS/2"].usWidthClass == expected
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"location, expected",
|
||||
[
|
||||
({"slnt": -91}, -90),
|
||||
({"slnt": -90}, -90),
|
||||
({"slnt": 0}, 0),
|
||||
({"slnt": 11.5}, 11.5),
|
||||
({"slnt": 90}, 90),
|
||||
({"slnt": 91}, 90),
|
||||
],
|
||||
)
|
||||
def test_slnt(self, ttFont, location, expected):
|
||||
set_default_weight_width_slant(ttFont, location)
|
||||
|
||||
assert ttFont["post"].italicAngle == expected
|
||||
|
||||
def test_all(self, ttFont):
|
||||
set_default_weight_width_slant(
|
||||
ttFont, {"wght": 500, "wdth": 150, "slnt": -12.0}
|
||||
)
|
||||
|
||||
assert ttFont["OS/2"].usWeightClass == 500
|
||||
assert ttFont["OS/2"].usWidthClass == 8
|
||||
assert ttFont["post"].italicAngle == -12.0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(unittest.main())
|
||||
|
Loading…
x
Reference in New Issue
Block a user