diff --git a/Lib/fontTools/fontBuilder.py b/Lib/fontTools/fontBuilder.py index 15a550e22..8f83ea800 100644 --- a/Lib/fontTools/fontBuilder.py +++ b/Lib/fontTools/fontBuilder.py @@ -132,6 +132,7 @@ fb.save("test.otf") from .ttLib import TTFont, newTable from .ttLib.tables._c_m_a_p import cmap_classes from .ttLib.tables._g_l_y_f import flagCubic +from .ttLib.tables.O_S_2f_2 import Panose from .misc.timeTools import timestampNow import struct from collections import OrderedDict @@ -263,18 +264,7 @@ _nameIDs = dict( # to insert in setupNameTable doc string: # print("\n".join(("%s (nameID %s)" % (k, v)) for k, v in sorted(_nameIDs.items(), key=lambda x: x[1]))) -_panoseDefaults = dict( - bFamilyType=0, - bSerifStyle=0, - bWeight=0, - bProportion=0, - bContrast=0, - bStrokeVariation=0, - bArmStyle=0, - bLetterForm=0, - bMidline=0, - bXHeight=0, -) +_panoseDefaults = Panose() _OS2Defaults = dict( version=3, diff --git a/Lib/fontTools/ttLib/tables/O_S_2f_2.py b/Lib/fontTools/ttLib/tables/O_S_2f_2.py index fc50b228a..7b403026a 100644 --- a/Lib/fontTools/ttLib/tables/O_S_2f_2.py +++ b/Lib/fontTools/ttLib/tables/O_S_2f_2.py @@ -25,6 +25,13 @@ panoseFormat = """ class Panose(object): + def __init__(self, **kwargs): + _, names, _ = sstruct.getformat(panoseFormat) + for name in names: + setattr(self, name, kwargs.pop(name, 0)) + for k in kwargs: + raise TypeError(f"Panose() got an unexpected keyword argument {k!r}") + def toXML(self, writer, ttFont): formatstring, names, fixes = sstruct.getformat(panoseFormat) for name in names: diff --git a/Tests/fontBuilder/fontBuilder_test.py b/Tests/fontBuilder/fontBuilder_test.py index a2e58be8a..c831d02e8 100644 --- a/Tests/fontBuilder/fontBuilder_test.py +++ b/Tests/fontBuilder/fontBuilder_test.py @@ -420,3 +420,48 @@ def test_unicodeVariationSequences(tmpdir): fb.setupCharacterMap(cmap, uvs) fb.save(outPath) _verifyOutput(outPath, tables=["cmap"]) + + +def test_setupPanose(): + from fontTools.ttLib.tables.O_S_2f_2 import Panose + + fb, advanceWidths, nameStrings = _setupFontBuilder(True) + + pen = TTGlyphPen(None) + drawTestGlyph(pen) + glyph = pen.glyph() + glyphs = {".notdef": glyph, "A": glyph, "a": glyph, ".null": glyph} + fb.setupGlyf(glyphs) + metrics = {} + glyphTable = fb.font["glyf"] + for gn, advanceWidth in advanceWidths.items(): + metrics[gn] = (advanceWidth, glyphTable[gn].xMin) + fb.setupHorizontalMetrics(metrics) + + fb.setupHorizontalHeader(ascent=824, descent=200) + fb.setupNameTable(nameStrings) + fb.setupOS2() + fb.setupPost() + + panoseValues = { # sample value of Times New Roman from https://www.w3.org/Printing/stevahn.html + "bFamilyType": 2, + "bSerifStyle": 2, + "bWeight": 6, + "bProportion": 3, + "bContrast": 5, + "bStrokeVariation": 4, + "bArmStyle": 5, + "bLetterForm": 2, + "bMidline": 3, + "bXHeight": 4, + } + panoseObj = Panose(**panoseValues) + + for name in panoseValues: + assert getattr(fb.font["OS/2"].panose, name) == 0 + + fb.setupOS2(panose=panoseObj) + fb.setupPost() + + for name, value in panoseValues.items(): + assert getattr(fb.font["OS/2"].panose, name) == value