[fontBuilder] Enable making CFF2 fonts with 'post' table format 2

Before this change all OTFs wound up with 'post' table format 3
This commit is contained in:
Miguel Sousa 2019-04-01 14:14:45 -07:00
parent 30885c50f4
commit b0710b829b
3 changed files with 93 additions and 42 deletions

View File

@ -690,8 +690,9 @@ class FontBuilder(object):
"""Create a new `post` table and initialize it with default values, """Create a new `post` table and initialize it with default values,
which can be overridden by keyword arguments. which can be overridden by keyword arguments.
""" """
isCFF2 = 'CFF2' in self.font
postTable = self._initTableWithValues("post", _postDefaults, values) postTable = self._initTableWithValues("post", _postDefaults, values)
if self.isTTF and keepGlyphNames: if (self.isTTF or isCFF2) and keepGlyphNames:
postTable.formatType = 2.0 postTable.formatType = 2.0
postTable.extraNames = [] postTable.extraNames = []
postTable.mapping = {} postTable.mapping = {}

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="OTTO" ttLibVersion="3.33"> <ttFont sfntVersion="OTTO" ttLibVersion="3.38">
<GlyphOrder> <GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. --> <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/> <GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="glyph00001"/> <GlyphID id="1" name=".null"/>
<GlyphID id="2" name="A"/> <GlyphID id="2" name="A"/>
<GlyphID id="3" name="a"/> <GlyphID id="3" name="a"/>
</GlyphOrder> </GlyphOrder>
@ -13,12 +13,12 @@
<!-- Most of this table will be recalculated by the compiler --> <!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/> <tableVersion value="1.0"/>
<fontRevision value="1.0"/> <fontRevision value="1.0"/>
<checkSumAdjustment value="0xed07360f"/> <checkSumAdjustment value="0x79eab779"/>
<magicNumber value="0x5f0f3cf5"/> <magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/> <flags value="00000000 00000011"/>
<unitsPerEm value="1000"/> <unitsPerEm value="1000"/>
<created value="Wed Dec 5 11:55:26 2018"/> <created value="Wed Mar 27 00:23:21 2019"/>
<modified value="Wed Dec 5 11:55:26 2018"/> <modified value="Wed Mar 27 00:23:21 2019"/>
<xMin value="0"/> <xMin value="0"/>
<yMin value="0"/> <yMin value="0"/>
<xMax value="0"/> <xMax value="0"/>
@ -110,9 +110,9 @@
<hmtx> <hmtx>
<mtx name=".notdef" width="600" lsb="0"/> <mtx name=".notdef" width="600" lsb="0"/>
<mtx name=".null" width="600" lsb="0"/>
<mtx name="A" width="600" lsb="0"/> <mtx name="A" width="600" lsb="0"/>
<mtx name="a" width="600" lsb="0"/> <mtx name="a" width="600" lsb="0"/>
<mtx name="glyph00001" width="600" lsb="0"/>
</hmtx> </hmtx>
<cmap> <cmap>
@ -179,7 +179,7 @@
</name> </name>
<post> <post>
<formatType value="3.0"/> <formatType value="2.0"/>
<italicAngle value="0.0"/> <italicAngle value="0.0"/>
<underlinePosition value="0"/> <underlinePosition value="0"/>
<underlineThickness value="0"/> <underlineThickness value="0"/>
@ -188,6 +188,18 @@
<maxMemType42 value="0"/> <maxMemType42 value="0"/>
<minMemType1 value="0"/> <minMemType1 value="0"/>
<maxMemType1 value="0"/> <maxMemType1 value="0"/>
<psNames>
<!-- This file uses unique glyph names based on the information
found in the 'post' table. Since these names might not be unique,
we have to invent artificial names in case of clashes. In order to
be able to retain the original information, we need a name to
ps name mapping for those cases where they differ. That's what
you see below.
-->
</psNames>
<extraNames>
<!-- following are the name that are not taken from the standard Mac glyph order -->
</extraNames>
</post> </post>
<CFF2> <CFF2>
@ -212,6 +224,13 @@
67 66 33 67 67 hvcurveto 67 66 33 67 67 hvcurveto
-900 vlineto -900 vlineto
</CharString> </CharString>
<CharString name=".null">
100 100 rmoveto
900 vlineto
-67 67 66 -33 67 hhcurveto
67 66 33 67 67 hvcurveto
-900 vlineto
</CharString>
<CharString name="A"> <CharString name="A">
100 100 rmoveto 100 100 rmoveto
900 vlineto 900 vlineto
@ -229,13 +248,6 @@
-400 -400 1 blend -400 -400 1 blend
hlineto hlineto
</CharString> </CharString>
<CharString name="glyph00001">
100 100 rmoveto
900 vlineto
-67 67 66 -33 67 hhcurveto
67 66 33 67 67 hvcurveto
-900 vlineto
</CharString>
</CharStrings> </CharStrings>
<VarStore Format="1"> <VarStore Format="1">
<Format value="1"/> <Format value="1"/>

View File

@ -2,14 +2,13 @@ from __future__ import print_function, division, absolute_import
from __future__ import unicode_literals from __future__ import unicode_literals
import os import os
import shutil import pytest
import re import re
from fontTools.ttLib import TTFont from fontTools.ttLib import TTFont
from fontTools.pens.ttGlyphPen import TTGlyphPen from fontTools.pens.ttGlyphPen import TTGlyphPen
from fontTools.pens.t2CharStringPen import T2CharStringPen from fontTools.pens.t2CharStringPen import T2CharStringPen
from fontTools.fontBuilder import FontBuilder from fontTools.fontBuilder import FontBuilder
from fontTools.ttLib.tables.TupleVariation import TupleVariation from fontTools.ttLib.tables.TupleVariation import TupleVariation
from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates
from fontTools.misc.psCharStrings import T2CharString from fontTools.misc.psCharStrings import T2CharString
@ -53,6 +52,43 @@ def _setupFontBuilder(isTTF, unitsPerEm=1024):
return fb, advanceWidths, nameStrings return fb, advanceWidths, nameStrings
def _setupFontBuilderFvar(fb):
assert 'name' in fb.font, 'Must run setupNameTable() first.'
axes = [
('TEST', 0, 0, 100, "Test Axis"),
]
instances = [
dict(location=dict(TEST=0), stylename="TotallyNormal"),
dict(location=dict(TEST=100), stylename="TotallyTested"),
]
fb.setupFvar(axes, instances)
return fb
def _setupFontBuilderCFF2(fb):
assert 'fvar' in fb.font, 'Must run _setupFontBuilderFvar() first.'
pen = T2CharStringPen(None, None, CFF2=True)
drawTestGlyph(pen)
charString = pen.getCharString()
program = [
200, 200, -200, -200, 2, "blend", "rmoveto",
400, 400, 1, "blend", "hlineto",
400, 400, 1, "blend", "vlineto",
-400, -400, 1, "blend", "hlineto"
]
charStringVariable = T2CharString(program=program)
charStrings = {".notdef": charString, "A": charString,
"a": charStringVariable, ".null": charString}
fb.setupCFF2(charStrings, regions=[{"TEST": (0, 1, 1)}])
return fb
def _verifyOutput(outPath, tables=None): def _verifyOutput(outPath, tables=None):
f = TTFont(outPath) f = TTFont(outPath)
f.saveXML(outPath + ".ttx", tables=tables) f.saveXML(outPath + ".ttx", tables=tables)
@ -191,32 +227,9 @@ def test_build_cff2(tmpdir):
outPath = os.path.join(str(tmpdir), "test_var.otf") outPath = os.path.join(str(tmpdir), "test_var.otf")
fb, advanceWidths, nameStrings = _setupFontBuilder(False, 1000) fb, advanceWidths, nameStrings = _setupFontBuilder(False, 1000)
fb.setupNameTable(nameStrings) fb.setupNameTable(nameStrings)
fb = _setupFontBuilderFvar(fb)
axes = [ fb = _setupFontBuilderCFF2(fb)
('TEST', 0, 0, 100, "Test Axis"),
]
instances = [
dict(location=dict(TEST=0), stylename="TotallyNormal"),
dict(location=dict(TEST=100), stylename="TotallyTested"),
]
fb.setupFvar(axes, instances)
pen = T2CharStringPen(None, None, CFF2=True)
drawTestGlyph(pen)
charString = pen.getCharString()
program = [
200, 200, -200, -200, 2, "blend", "rmoveto",
400, 400, 1, "blend", "hlineto",
400, 400, 1, "blend", "vlineto",
-400, -400, 1, "blend", "hlineto"
]
charStringVariable = T2CharString(program=program)
charStrings = {".notdef": charString, "A": charString, "a": charStringVariable, ".null": charString}
fb.setupCFF2(charStrings, regions=[{"TEST": (0, 1, 1)}])
metrics = {gn: (advanceWidth, 0) for gn, advanceWidth in advanceWidths.items()} metrics = {gn: (advanceWidth, 0) for gn, advanceWidth in advanceWidths.items()}
fb.setupHorizontalMetrics(metrics) fb.setupHorizontalMetrics(metrics)
@ -246,6 +259,31 @@ def test_setupNameTable_no_windows():
assert not any(n for n in fb.font["name"].names if n.platformID == 3) assert not any(n for n in fb.font["name"].names if n.platformID == 3)
@pytest.mark.parametrize('is_ttf, keep_glyph_names, make_cff2, post_format', [
(True, True, False, 2), # TTF with post table format 2.0
(True, False, False, 3), # TTF with post table format 3.0
(False, True, False, 3), # CFF with post table format 3.0
(False, False, False, 3), # CFF with post table format 3.0
(False, True, True, 2), # CFF2 with post table format 2.0
(False, False, True, 3), # CFF2 with post table format 3.0
])
def test_setupPost(is_ttf, keep_glyph_names, make_cff2, post_format):
fb, _, nameStrings = _setupFontBuilder(is_ttf)
if make_cff2:
fb.setupNameTable(nameStrings)
fb = _setupFontBuilderCFF2(_setupFontBuilderFvar(fb))
if keep_glyph_names:
fb.setupPost()
else:
fb.setupPost(keepGlyphNames=keep_glyph_names)
assert fb.isTTF is is_ttf
assert ('CFF2' in fb.font) is make_cff2
assert fb.font["post"].formatType == post_format
def test_unicodeVariationSequences(tmpdir): def test_unicodeVariationSequences(tmpdir):
familyName = "UVSTestFont" familyName = "UVSTestFont"
styleName = "Regular" styleName = "Regular"