Merge pull request #1652 from anthrotype/varlib-set-default-OS2-classes

varLib: add set_default_weight_width_slant
This commit is contained in:
Cosimo Lupo 2019-06-20 15:04:34 +01:00 committed by GitHub
commit 06fe38dd6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 122 additions and 2 deletions

View File

@ -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]

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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())