fonttools 4.56.0__cp39-cp39-win_amd64.whl → 4.58.0__cp39-cp39-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of fonttools might be problematic. Click here for more details.
- fontTools/__init__.py +1 -1
- fontTools/cffLib/__init__.py +61 -26
- fontTools/config/__init__.py +15 -0
- fontTools/cu2qu/cu2qu.cp39-win_amd64.pyd +0 -0
- fontTools/designspaceLib/statNames.py +14 -7
- fontTools/feaLib/ast.py +92 -13
- fontTools/feaLib/builder.py +52 -13
- fontTools/feaLib/lexer.cp39-win_amd64.pyd +0 -0
- fontTools/feaLib/parser.py +59 -39
- fontTools/fontBuilder.py +6 -0
- fontTools/misc/bezierTools.cp39-win_amd64.pyd +0 -0
- fontTools/misc/etree.py +4 -27
- fontTools/misc/testTools.py +2 -1
- fontTools/mtiLib/__init__.py +0 -2
- fontTools/otlLib/builder.py +195 -145
- fontTools/otlLib/optimize/gpos.py +49 -63
- fontTools/pens/momentsPen.cp39-win_amd64.pyd +0 -0
- fontTools/pens/pointPen.py +21 -12
- fontTools/qu2cu/qu2cu.cp39-win_amd64.pyd +0 -0
- fontTools/subset/__init__.py +11 -0
- fontTools/ttLib/__init__.py +4 -0
- fontTools/ttLib/__main__.py +47 -8
- fontTools/ttLib/tables/D__e_b_g.py +20 -2
- fontTools/ttLib/tables/G_V_A_R_.py +5 -0
- fontTools/ttLib/tables/T_S_I__0.py +14 -3
- fontTools/ttLib/tables/T_S_I__5.py +16 -5
- fontTools/ttLib/tables/__init__.py +1 -0
- fontTools/ttLib/tables/_c_m_a_p.py +19 -6
- fontTools/ttLib/tables/_c_v_t.py +2 -0
- fontTools/ttLib/tables/_f_p_g_m.py +3 -1
- fontTools/ttLib/tables/_g_l_y_f.py +11 -10
- fontTools/ttLib/tables/_g_v_a_r.py +62 -17
- fontTools/ttLib/tables/_p_o_s_t.py +5 -2
- fontTools/ttLib/tables/otBase.py +1 -0
- fontTools/ttLib/tables/otConverters.py +5 -2
- fontTools/ttLib/tables/otTables.py +5 -1
- fontTools/ttLib/ttFont.py +3 -5
- fontTools/ttLib/ttGlyphSet.py +0 -10
- fontTools/ttx.py +13 -1
- fontTools/ufoLib/__init__.py +2 -2
- fontTools/ufoLib/converters.py +89 -25
- fontTools/ufoLib/errors.py +8 -0
- fontTools/ufoLib/etree.py +1 -1
- fontTools/ufoLib/filenames.py +155 -100
- fontTools/ufoLib/glifLib.py +9 -2
- fontTools/ufoLib/kerning.py +66 -36
- fontTools/ufoLib/utils.py +5 -2
- fontTools/unicodedata/Mirrored.py +446 -0
- fontTools/unicodedata/__init__.py +6 -2
- fontTools/varLib/__init__.py +94 -89
- fontTools/varLib/hvar.py +113 -0
- fontTools/varLib/iup.cp39-win_amd64.pyd +0 -0
- fontTools/varLib/varStore.py +1 -1
- fontTools/voltLib/__main__.py +206 -0
- fontTools/voltLib/ast.py +4 -0
- fontTools/voltLib/parser.py +16 -8
- fontTools/voltLib/voltToFea.py +347 -166
- {fonttools-4.56.0.dist-info → fonttools-4.58.0.dist-info}/METADATA +60 -12
- {fonttools-4.56.0.dist-info → fonttools-4.58.0.dist-info}/RECORD +65 -66
- {fonttools-4.56.0.dist-info → fonttools-4.58.0.dist-info}/WHEEL +1 -1
- fonttools-4.58.0.dist-info/licenses/LICENSE.external +359 -0
- fontTools/cu2qu/cu2qu.c +0 -14829
- fontTools/feaLib/lexer.c +0 -17986
- fontTools/misc/bezierTools.c +0 -41831
- fontTools/pens/momentsPen.c +0 -13448
- fontTools/qu2cu/qu2cu.c +0 -16269
- fontTools/varLib/iup.c +0 -19154
- {fonttools-4.56.0.data → fonttools-4.58.0.data}/data/share/man/man1/ttx.1 +0 -0
- {fonttools-4.56.0.dist-info → fonttools-4.58.0.dist-info}/entry_points.txt +0 -0
- {fonttools-4.56.0.dist-info → fonttools-4.58.0.dist-info/licenses}/LICENSE +0 -0
- {fonttools-4.56.0.dist-info → fonttools-4.58.0.dist-info}/top_level.txt +0 -0
|
@@ -3,6 +3,7 @@ from functools import partial
|
|
|
3
3
|
from fontTools.misc import sstruct
|
|
4
4
|
from fontTools.misc.textTools import safeEval
|
|
5
5
|
from fontTools.misc.lazyTools import LazyDict
|
|
6
|
+
from fontTools.ttLib import OPTIMIZE_FONT_SPEED
|
|
6
7
|
from fontTools.ttLib.tables.TupleVariation import TupleVariation
|
|
7
8
|
from . import DefaultTable
|
|
8
9
|
import array
|
|
@@ -23,19 +24,24 @@ log = logging.getLogger(__name__)
|
|
|
23
24
|
# FreeType2 source code for parsing 'gvar':
|
|
24
25
|
# http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/src/truetype/ttgxvar.c
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
GVAR_HEADER_FORMAT_HEAD = """
|
|
27
28
|
> # big endian
|
|
28
29
|
version: H
|
|
29
30
|
reserved: H
|
|
30
31
|
axisCount: H
|
|
31
32
|
sharedTupleCount: H
|
|
32
33
|
offsetToSharedTuples: I
|
|
33
|
-
|
|
34
|
+
"""
|
|
35
|
+
# In between the HEAD and TAIL lies the glyphCount, which is
|
|
36
|
+
# of different size: 2 bytes for gvar, and 3 bytes for GVAR.
|
|
37
|
+
GVAR_HEADER_FORMAT_TAIL = """
|
|
38
|
+
> # big endian
|
|
34
39
|
flags: H
|
|
35
40
|
offsetToGlyphVariationData: I
|
|
36
41
|
"""
|
|
37
42
|
|
|
38
|
-
|
|
43
|
+
GVAR_HEADER_SIZE_HEAD = sstruct.calcsize(GVAR_HEADER_FORMAT_HEAD)
|
|
44
|
+
GVAR_HEADER_SIZE_TAIL = sstruct.calcsize(GVAR_HEADER_FORMAT_TAIL)
|
|
39
45
|
|
|
40
46
|
|
|
41
47
|
class table__g_v_a_r(DefaultTable.DefaultTable):
|
|
@@ -50,6 +56,7 @@ class table__g_v_a_r(DefaultTable.DefaultTable):
|
|
|
50
56
|
"""
|
|
51
57
|
|
|
52
58
|
dependencies = ["fvar", "glyf"]
|
|
59
|
+
gid_size = 2
|
|
53
60
|
|
|
54
61
|
def __init__(self, tag=None):
|
|
55
62
|
DefaultTable.DefaultTable.__init__(self, tag)
|
|
@@ -57,6 +64,7 @@ class table__g_v_a_r(DefaultTable.DefaultTable):
|
|
|
57
64
|
self.variations = {}
|
|
58
65
|
|
|
59
66
|
def compile(self, ttFont):
|
|
67
|
+
|
|
60
68
|
axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
|
|
61
69
|
sharedTuples = tv.compileSharedTuples(
|
|
62
70
|
axisTags, itertools.chain(*self.variations.values())
|
|
@@ -72,28 +80,33 @@ class table__g_v_a_r(DefaultTable.DefaultTable):
|
|
|
72
80
|
offsets.append(offset)
|
|
73
81
|
compiledOffsets, tableFormat = self.compileOffsets_(offsets)
|
|
74
82
|
|
|
83
|
+
GVAR_HEADER_SIZE = GVAR_HEADER_SIZE_HEAD + self.gid_size + GVAR_HEADER_SIZE_TAIL
|
|
75
84
|
header = {}
|
|
76
85
|
header["version"] = self.version
|
|
77
86
|
header["reserved"] = self.reserved
|
|
78
87
|
header["axisCount"] = len(axisTags)
|
|
79
88
|
header["sharedTupleCount"] = len(sharedTuples)
|
|
80
89
|
header["offsetToSharedTuples"] = GVAR_HEADER_SIZE + len(compiledOffsets)
|
|
81
|
-
header["glyphCount"] = len(compiledGlyphs)
|
|
82
90
|
header["flags"] = tableFormat
|
|
83
91
|
header["offsetToGlyphVariationData"] = (
|
|
84
92
|
header["offsetToSharedTuples"] + sharedTupleSize
|
|
85
93
|
)
|
|
86
|
-
compiledHeader = sstruct.pack(GVAR_HEADER_FORMAT, header)
|
|
87
94
|
|
|
88
|
-
result = [
|
|
95
|
+
result = [
|
|
96
|
+
sstruct.pack(GVAR_HEADER_FORMAT_HEAD, header),
|
|
97
|
+
len(compiledGlyphs).to_bytes(self.gid_size, "big"),
|
|
98
|
+
sstruct.pack(GVAR_HEADER_FORMAT_TAIL, header),
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
result.append(compiledOffsets)
|
|
89
102
|
result.extend(sharedTuples)
|
|
90
103
|
result.extend(compiledGlyphs)
|
|
91
104
|
return b"".join(result)
|
|
92
105
|
|
|
93
106
|
def compileGlyphs_(self, ttFont, axisTags, sharedCoordIndices):
|
|
107
|
+
optimizeSpeed = ttFont.cfg[OPTIMIZE_FONT_SPEED]
|
|
94
108
|
result = []
|
|
95
109
|
glyf = ttFont["glyf"]
|
|
96
|
-
optimizeSize = getattr(self, "optimizeSize", True)
|
|
97
110
|
for glyphName in ttFont.getGlyphOrder():
|
|
98
111
|
variations = self.variations.get(glyphName, [])
|
|
99
112
|
if not variations:
|
|
@@ -102,11 +115,12 @@ class table__g_v_a_r(DefaultTable.DefaultTable):
|
|
|
102
115
|
pointCountUnused = 0 # pointCount is actually unused by compileGlyph
|
|
103
116
|
result.append(
|
|
104
117
|
compileGlyph_(
|
|
118
|
+
self.gid_size,
|
|
105
119
|
variations,
|
|
106
120
|
pointCountUnused,
|
|
107
121
|
axisTags,
|
|
108
122
|
sharedCoordIndices,
|
|
109
|
-
optimizeSize=
|
|
123
|
+
optimizeSize=not optimizeSpeed,
|
|
110
124
|
)
|
|
111
125
|
)
|
|
112
126
|
return result
|
|
@@ -114,7 +128,19 @@ class table__g_v_a_r(DefaultTable.DefaultTable):
|
|
|
114
128
|
def decompile(self, data, ttFont):
|
|
115
129
|
axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
|
|
116
130
|
glyphs = ttFont.getGlyphOrder()
|
|
117
|
-
|
|
131
|
+
|
|
132
|
+
# Parse the header
|
|
133
|
+
GVAR_HEADER_SIZE = GVAR_HEADER_SIZE_HEAD + self.gid_size + GVAR_HEADER_SIZE_TAIL
|
|
134
|
+
sstruct.unpack(GVAR_HEADER_FORMAT_HEAD, data[:GVAR_HEADER_SIZE_HEAD], self)
|
|
135
|
+
self.glyphCount = int.from_bytes(
|
|
136
|
+
data[GVAR_HEADER_SIZE_HEAD : GVAR_HEADER_SIZE_HEAD + self.gid_size], "big"
|
|
137
|
+
)
|
|
138
|
+
sstruct.unpack(
|
|
139
|
+
GVAR_HEADER_FORMAT_TAIL,
|
|
140
|
+
data[GVAR_HEADER_SIZE_HEAD + self.gid_size : GVAR_HEADER_SIZE],
|
|
141
|
+
self,
|
|
142
|
+
)
|
|
143
|
+
|
|
118
144
|
assert len(glyphs) == self.glyphCount
|
|
119
145
|
assert len(axisTags) == self.axisCount
|
|
120
146
|
sharedCoords = tv.decompileSharedTuples(
|
|
@@ -144,7 +170,7 @@ class table__g_v_a_r(DefaultTable.DefaultTable):
|
|
|
144
170
|
glyph = glyf[glyphName]
|
|
145
171
|
numPointsInGlyph = self.getNumPoints_(glyph)
|
|
146
172
|
return decompileGlyph_(
|
|
147
|
-
numPointsInGlyph, sharedCoords, axisTags, gvarData
|
|
173
|
+
self.gid_size, numPointsInGlyph, sharedCoords, axisTags, gvarData
|
|
148
174
|
)
|
|
149
175
|
|
|
150
176
|
return read_item
|
|
@@ -262,23 +288,42 @@ class table__g_v_a_r(DefaultTable.DefaultTable):
|
|
|
262
288
|
|
|
263
289
|
|
|
264
290
|
def compileGlyph_(
|
|
265
|
-
|
|
291
|
+
dataOffsetSize,
|
|
292
|
+
variations,
|
|
293
|
+
pointCount,
|
|
294
|
+
axisTags,
|
|
295
|
+
sharedCoordIndices,
|
|
296
|
+
*,
|
|
297
|
+
optimizeSize=True,
|
|
266
298
|
):
|
|
299
|
+
assert dataOffsetSize in (2, 3)
|
|
267
300
|
tupleVariationCount, tuples, data = tv.compileTupleVariationStore(
|
|
268
301
|
variations, pointCount, axisTags, sharedCoordIndices, optimizeSize=optimizeSize
|
|
269
302
|
)
|
|
270
303
|
if tupleVariationCount == 0:
|
|
271
304
|
return b""
|
|
272
|
-
|
|
273
|
-
|
|
305
|
+
|
|
306
|
+
offsetToData = 2 + dataOffsetSize + len(tuples)
|
|
307
|
+
|
|
308
|
+
result = [
|
|
309
|
+
tupleVariationCount.to_bytes(2, "big"),
|
|
310
|
+
offsetToData.to_bytes(dataOffsetSize, "big"),
|
|
311
|
+
tuples,
|
|
312
|
+
data,
|
|
313
|
+
]
|
|
314
|
+
if (offsetToData + len(data)) % 2 != 0:
|
|
274
315
|
result.append(b"\0") # padding
|
|
275
316
|
return b"".join(result)
|
|
276
317
|
|
|
277
318
|
|
|
278
|
-
def decompileGlyph_(pointCount, sharedTuples, axisTags, data):
|
|
279
|
-
|
|
319
|
+
def decompileGlyph_(dataOffsetSize, pointCount, sharedTuples, axisTags, data):
|
|
320
|
+
assert dataOffsetSize in (2, 3)
|
|
321
|
+
if len(data) < 2 + dataOffsetSize:
|
|
280
322
|
return []
|
|
281
|
-
|
|
323
|
+
|
|
324
|
+
tupleVariationCount = int.from_bytes(data[:2], "big")
|
|
325
|
+
offsetToData = int.from_bytes(data[2 : 2 + dataOffsetSize], "big")
|
|
326
|
+
|
|
282
327
|
dataPos = offsetToData
|
|
283
328
|
return tv.decompileTupleVariationStore(
|
|
284
329
|
"gvar",
|
|
@@ -287,6 +332,6 @@ def decompileGlyph_(pointCount, sharedTuples, axisTags, data):
|
|
|
287
332
|
pointCount,
|
|
288
333
|
sharedTuples,
|
|
289
334
|
data,
|
|
290
|
-
|
|
335
|
+
2 + dataOffsetSize,
|
|
291
336
|
offsetToData,
|
|
292
337
|
)
|
|
@@ -122,13 +122,16 @@ class table__p_o_s_t(DefaultTable.DefaultTable):
|
|
|
122
122
|
glyphName = psName = self.glyphOrder[i]
|
|
123
123
|
if glyphName == "":
|
|
124
124
|
glyphName = "glyph%.5d" % i
|
|
125
|
+
|
|
125
126
|
if glyphName in allNames:
|
|
126
127
|
# make up a new glyphName that's unique
|
|
127
128
|
n = allNames[glyphName]
|
|
128
|
-
|
|
129
|
+
# check if the exists in any of the seen names or later ones
|
|
130
|
+
names = set(allNames.keys()) | set(self.glyphOrder)
|
|
131
|
+
while (glyphName + "." + str(n)) in names:
|
|
129
132
|
n += 1
|
|
130
133
|
allNames[glyphName] = n + 1
|
|
131
|
-
glyphName = glyphName + "
|
|
134
|
+
glyphName = glyphName + "." + str(n)
|
|
132
135
|
|
|
133
136
|
self.glyphOrder[i] = glyphName
|
|
134
137
|
allNames[glyphName] = 1
|
fontTools/ttLib/tables/otBase.py
CHANGED
|
@@ -10,7 +10,7 @@ from fontTools.ttLib.tables.TupleVariation import TupleVariation
|
|
|
10
10
|
from fontTools.misc.roundTools import nearestMultipleShortestRepr, otRound
|
|
11
11
|
from fontTools.misc.textTools import bytesjoin, tobytes, tostr, pad, safeEval
|
|
12
12
|
from fontTools.misc.lazyTools import LazyList
|
|
13
|
-
from fontTools.ttLib import getSearchRange
|
|
13
|
+
from fontTools.ttLib import OPTIMIZE_FONT_SPEED, getSearchRange
|
|
14
14
|
from .otBase import (
|
|
15
15
|
CountReference,
|
|
16
16
|
FormatSwitchingBaseTable,
|
|
@@ -1810,7 +1810,10 @@ class TupleValues:
|
|
|
1810
1810
|
return TupleVariation.decompileDeltas_(None, data)[0]
|
|
1811
1811
|
|
|
1812
1812
|
def write(self, writer, font, tableDict, values, repeatIndex=None):
|
|
1813
|
-
|
|
1813
|
+
optimizeSpeed = font.cfg[OPTIMIZE_FONT_SPEED]
|
|
1814
|
+
return bytes(
|
|
1815
|
+
TupleVariation.compileDeltaValues_(values, optimizeSize=not optimizeSpeed)
|
|
1816
|
+
)
|
|
1814
1817
|
|
|
1815
1818
|
def xmlRead(self, attrs, content, font):
|
|
1816
1819
|
return safeEval(attrs["value"])
|
|
@@ -11,6 +11,7 @@ from functools import reduce
|
|
|
11
11
|
from math import radians
|
|
12
12
|
import itertools
|
|
13
13
|
from collections import defaultdict, namedtuple
|
|
14
|
+
from fontTools.ttLib import OPTIMIZE_FONT_SPEED
|
|
14
15
|
from fontTools.ttLib.tables.TupleVariation import TupleVariation
|
|
15
16
|
from fontTools.ttLib.tables.otTraverse import dfs_base_table
|
|
16
17
|
from fontTools.misc.arrayTools import quantizeRect
|
|
@@ -236,6 +237,8 @@ class VarComponent:
|
|
|
236
237
|
return data[i:]
|
|
237
238
|
|
|
238
239
|
def compile(self, font):
|
|
240
|
+
optimizeSpeed = font.cfg[OPTIMIZE_FONT_SPEED]
|
|
241
|
+
|
|
239
242
|
data = []
|
|
240
243
|
|
|
241
244
|
flags = self.flags
|
|
@@ -259,7 +262,8 @@ class VarComponent:
|
|
|
259
262
|
data.append(_write_uint32var(self.axisIndicesIndex))
|
|
260
263
|
data.append(
|
|
261
264
|
TupleVariation.compileDeltaValues_(
|
|
262
|
-
[fl2fi(v, 14) for v in self.axisValues]
|
|
265
|
+
[fl2fi(v, 14) for v in self.axisValues],
|
|
266
|
+
optimizeSize=not optimizeSpeed,
|
|
263
267
|
)
|
|
264
268
|
)
|
|
265
269
|
else:
|
fontTools/ttLib/ttFont.py
CHANGED
|
@@ -593,10 +593,8 @@ class TTFont(object):
|
|
|
593
593
|
# temporary cmap and by the real cmap in case we don't find a unicode
|
|
594
594
|
# cmap.
|
|
595
595
|
numGlyphs = int(self["maxp"].numGlyphs)
|
|
596
|
-
glyphOrder = [
|
|
596
|
+
glyphOrder = ["glyph%.5d" % i for i in range(numGlyphs)]
|
|
597
597
|
glyphOrder[0] = ".notdef"
|
|
598
|
-
for i in range(1, numGlyphs):
|
|
599
|
-
glyphOrder[i] = "glyph%.5d" % i
|
|
600
598
|
# Set the glyph order, so the cmap parser has something
|
|
601
599
|
# to work with (so we don't get called recursively).
|
|
602
600
|
self.glyphOrder = glyphOrder
|
|
@@ -606,7 +604,7 @@ class TTFont(object):
|
|
|
606
604
|
# this naming table will usually not cover all glyphs in the font.
|
|
607
605
|
# If the font has no Unicode cmap table, reversecmap will be empty.
|
|
608
606
|
if "cmap" in self:
|
|
609
|
-
reversecmap = self["cmap"].
|
|
607
|
+
reversecmap = self["cmap"].buildReversedMin()
|
|
610
608
|
else:
|
|
611
609
|
reversecmap = {}
|
|
612
610
|
useCount = {}
|
|
@@ -616,7 +614,7 @@ class TTFont(object):
|
|
|
616
614
|
# If a font maps both U+0041 LATIN CAPITAL LETTER A and
|
|
617
615
|
# U+0391 GREEK CAPITAL LETTER ALPHA to the same glyph,
|
|
618
616
|
# we prefer naming the glyph as "A".
|
|
619
|
-
glyphName = self._makeGlyphName(
|
|
617
|
+
glyphName = self._makeGlyphName(reversecmap[tempName])
|
|
620
618
|
numUses = useCount[glyphName] = useCount.get(glyphName, 0) + 1
|
|
621
619
|
if numUses > 1:
|
|
622
620
|
glyphName = "%s.alt%d" % (glyphName, numUses - 1)
|
fontTools/ttLib/ttGlyphSet.py
CHANGED
|
@@ -104,16 +104,6 @@ class _TTGlyphSetGlyf(_TTGlyphSet):
|
|
|
104
104
|
return _TTGlyphGlyf(self, glyphName, recalcBounds=self.recalcBounds)
|
|
105
105
|
|
|
106
106
|
|
|
107
|
-
class _TTGlyphSetGlyf(_TTGlyphSet):
|
|
108
|
-
def __init__(self, font, location, recalcBounds=True):
|
|
109
|
-
self.glyfTable = font["glyf"]
|
|
110
|
-
super().__init__(font, location, self.glyfTable, recalcBounds=recalcBounds)
|
|
111
|
-
self.gvarTable = font.get("gvar")
|
|
112
|
-
|
|
113
|
-
def __getitem__(self, glyphName):
|
|
114
|
-
return _TTGlyphGlyf(self, glyphName, recalcBounds=self.recalcBounds)
|
|
115
|
-
|
|
116
|
-
|
|
117
107
|
class _TTGlyphSetCFF(_TTGlyphSet):
|
|
118
108
|
def __init__(self, font, location):
|
|
119
109
|
tableTag = "CFF2" if "CFF2" in font else "CFF "
|
fontTools/ttx.py
CHANGED
|
@@ -101,9 +101,15 @@ Compile options
|
|
|
101
101
|
--with-zopfli
|
|
102
102
|
Use Zopfli instead of Zlib to compress WOFF. The Python
|
|
103
103
|
extension is available at https://pypi.python.org/pypi/zopfli
|
|
104
|
+
--optimize-font-speed
|
|
105
|
+
Enable optimizations that prioritize speed over file size.
|
|
106
|
+
This mainly affects how glyf t able and gvar / VARC tables are
|
|
107
|
+
compiled. The produced fonts will be larger, but rendering
|
|
108
|
+
performance will be improved with HarfBuzz and other text
|
|
109
|
+
layout engines.
|
|
104
110
|
"""
|
|
105
111
|
|
|
106
|
-
from fontTools.ttLib import TTFont, TTLibError
|
|
112
|
+
from fontTools.ttLib import OPTIMIZE_FONT_SPEED, TTFont, TTLibError
|
|
107
113
|
from fontTools.misc.macCreatorType import getMacCreatorAndType
|
|
108
114
|
from fontTools.unicode import setUnicodeData
|
|
109
115
|
from fontTools.misc.textTools import Tag, tostr
|
|
@@ -141,6 +147,7 @@ class Options(object):
|
|
|
141
147
|
recalcTimestamp = None
|
|
142
148
|
flavor = None
|
|
143
149
|
useZopfli = False
|
|
150
|
+
optimizeFontSpeed = False
|
|
144
151
|
|
|
145
152
|
def __init__(self, rawOptions, numFiles):
|
|
146
153
|
self.onlyTables = []
|
|
@@ -229,6 +236,8 @@ class Options(object):
|
|
|
229
236
|
self.flavor = value
|
|
230
237
|
elif option == "--with-zopfli":
|
|
231
238
|
self.useZopfli = True
|
|
239
|
+
elif option == "--optimize-font-speed":
|
|
240
|
+
self.optimizeFontSpeed = True
|
|
232
241
|
if self.verbose and self.quiet:
|
|
233
242
|
raise getopt.GetoptError("-q and -v options are mutually exclusive")
|
|
234
243
|
if self.verbose:
|
|
@@ -324,6 +333,8 @@ def ttCompile(input, output, options):
|
|
|
324
333
|
recalcBBoxes=options.recalcBBoxes,
|
|
325
334
|
recalcTimestamp=options.recalcTimestamp,
|
|
326
335
|
)
|
|
336
|
+
if options.optimizeFontSpeed:
|
|
337
|
+
ttf.cfg[OPTIMIZE_FONT_SPEED] = options.optimizeFontSpeed
|
|
327
338
|
ttf.importXML(input)
|
|
328
339
|
|
|
329
340
|
if options.recalcTimestamp is None and "head" in ttf and input is not sys.stdin:
|
|
@@ -386,6 +397,7 @@ def parseOptions(args):
|
|
|
386
397
|
"version",
|
|
387
398
|
"with-zopfli",
|
|
388
399
|
"newline=",
|
|
400
|
+
"optimize-font-speed",
|
|
389
401
|
],
|
|
390
402
|
)
|
|
391
403
|
|
fontTools/ufoLib/__init__.py
CHANGED
|
@@ -204,7 +204,7 @@ class UFOReader(_UFOBaseIO):
|
|
|
204
204
|
"""Read the various components of a .ufo.
|
|
205
205
|
|
|
206
206
|
Attributes:
|
|
207
|
-
path: An
|
|
207
|
+
path: An :class:`os.PathLike` object pointing to the .ufo.
|
|
208
208
|
validate: A boolean indicating if the data read should be
|
|
209
209
|
validated. Defaults to `True`.
|
|
210
210
|
|
|
@@ -891,7 +891,7 @@ class UFOWriter(UFOReader):
|
|
|
891
891
|
"""Write the various components of a .ufo.
|
|
892
892
|
|
|
893
893
|
Attributes:
|
|
894
|
-
path: An
|
|
894
|
+
path: An :class:`os.PathLike` object pointing to the .ufo.
|
|
895
895
|
formatVersion: the UFO format version as a tuple of integers (major, minor),
|
|
896
896
|
or as a single integer for the major digit only (minor is implied to be 0).
|
|
897
897
|
By default, the latest formatVersion will be used; currently it is 3.0,
|
fontTools/ufoLib/converters.py
CHANGED
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Functions for converting UFO1 or UFO2 files into UFO3 format.
|
|
3
|
+
|
|
4
|
+
Currently provides functionality for converting kerning rules
|
|
5
|
+
and kerning groups. Conversion is only supported _from_ UFO1
|
|
6
|
+
or UFO2, and _to_ UFO3.
|
|
3
7
|
"""
|
|
4
8
|
|
|
5
9
|
# adapted from the UFO spec
|
|
6
10
|
|
|
7
11
|
|
|
8
12
|
def convertUFO1OrUFO2KerningToUFO3Kerning(kerning, groups, glyphSet=()):
|
|
13
|
+
"""Convert kerning data in UFO1 or UFO2 syntax into UFO3 syntax.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
kerning:
|
|
17
|
+
A dictionary containing the kerning rules defined in
|
|
18
|
+
the UFO font, as used in :class:`.UFOReader` objects.
|
|
19
|
+
groups:
|
|
20
|
+
A dictionary containing the groups defined in the UFO
|
|
21
|
+
font, as used in :class:`.UFOReader` objects.
|
|
22
|
+
glyphSet:
|
|
23
|
+
Optional; a set of glyph objects to skip (default: None).
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
1. A dictionary representing the converted kerning data.
|
|
27
|
+
2. A copy of the groups dictionary, with all groups renamed to UFO3 syntax.
|
|
28
|
+
3. A dictionary containing the mapping of old group names to new group names.
|
|
29
|
+
|
|
30
|
+
"""
|
|
9
31
|
# gather known kerning groups based on the prefixes
|
|
10
32
|
firstReferencedGroups, secondReferencedGroups = findKnownKerningGroups(groups)
|
|
11
33
|
# Make lists of groups referenced in kerning pairs.
|
|
@@ -63,35 +85,54 @@ def convertUFO1OrUFO2KerningToUFO3Kerning(kerning, groups, glyphSet=()):
|
|
|
63
85
|
|
|
64
86
|
|
|
65
87
|
def findKnownKerningGroups(groups):
|
|
66
|
-
"""
|
|
67
|
-
|
|
68
|
-
In some cases not all kerning groups will be referenced
|
|
69
|
-
by the kerning pairs. The algorithm for locating
|
|
70
|
-
in convertUFO1OrUFO2KerningToUFO3Kerning will
|
|
71
|
-
unreferenced groups. By scanning for known prefixes
|
|
88
|
+
"""Find all kerning groups in a UFO1 or UFO2 font that use known prefixes.
|
|
89
|
+
|
|
90
|
+
In some cases, not all kerning groups will be referenced
|
|
91
|
+
by the kerning pairs in a UFO. The algorithm for locating
|
|
92
|
+
groups in :func:`convertUFO1OrUFO2KerningToUFO3Kerning` will
|
|
93
|
+
miss these unreferenced groups. By scanning for known prefixes,
|
|
72
94
|
this function will catch all of the prefixed groups.
|
|
73
95
|
|
|
74
|
-
|
|
96
|
+
The prefixes and sides by this function are:
|
|
97
|
+
|
|
75
98
|
@MMK_L_ - side 1
|
|
76
99
|
@MMK_R_ - side 2
|
|
77
100
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
101
|
+
as defined in the UFO1 specification.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
groups:
|
|
105
|
+
A dictionary containing the groups defined in the UFO
|
|
106
|
+
font, as read by :class:`.UFOReader`.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Two sets; the first containing the names of all
|
|
110
|
+
first-side kerning groups identified in the ``groups``
|
|
111
|
+
dictionary, and the second containing the names of all
|
|
112
|
+
second-side kerning groups identified.
|
|
113
|
+
|
|
114
|
+
"First-side" and "second-side" are with respect to the
|
|
115
|
+
writing direction of the script.
|
|
116
|
+
|
|
117
|
+
Example::
|
|
118
|
+
|
|
119
|
+
>>> testGroups = {
|
|
120
|
+
... "@MMK_L_1" : None,
|
|
121
|
+
... "@MMK_L_2" : None,
|
|
122
|
+
... "@MMK_L_3" : None,
|
|
123
|
+
... "@MMK_R_1" : None,
|
|
124
|
+
... "@MMK_R_2" : None,
|
|
125
|
+
... "@MMK_R_3" : None,
|
|
126
|
+
... "@MMK_l_1" : None,
|
|
127
|
+
... "@MMK_r_1" : None,
|
|
128
|
+
... "@MMK_X_1" : None,
|
|
129
|
+
... "foo" : None,
|
|
130
|
+
... }
|
|
131
|
+
>>> first, second = findKnownKerningGroups(testGroups)
|
|
132
|
+
>>> sorted(first) == ['@MMK_L_1', '@MMK_L_2', '@MMK_L_3']
|
|
133
|
+
True
|
|
134
|
+
>>> sorted(second) == ['@MMK_R_1', '@MMK_R_2', '@MMK_R_3']
|
|
135
|
+
True
|
|
95
136
|
"""
|
|
96
137
|
knownFirstGroupPrefixes = ["@MMK_L_"]
|
|
97
138
|
knownSecondGroupPrefixes = ["@MMK_R_"]
|
|
@@ -110,6 +151,27 @@ def findKnownKerningGroups(groups):
|
|
|
110
151
|
|
|
111
152
|
|
|
112
153
|
def makeUniqueGroupName(name, groupNames, counter=0):
|
|
154
|
+
"""Make a kerning group name that will be unique within the set of group names.
|
|
155
|
+
|
|
156
|
+
If the requested kerning group name already exists within the set, this
|
|
157
|
+
will return a new name by adding an incremented counter to the end
|
|
158
|
+
of the requested name.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
name:
|
|
162
|
+
The requested kerning group name.
|
|
163
|
+
groupNames:
|
|
164
|
+
A list of the existing kerning group names.
|
|
165
|
+
counter:
|
|
166
|
+
Optional; a counter of group names already seen (default: 0). If
|
|
167
|
+
:attr:`.counter` is not provided, the function will recurse,
|
|
168
|
+
incrementing the value of :attr:`.counter` until it finds the
|
|
169
|
+
first unused ``name+counter`` combination, and return that result.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
A unique kerning group name composed of the requested name suffixed
|
|
173
|
+
by the smallest available integer counter.
|
|
174
|
+
"""
|
|
113
175
|
# Add a number to the name if the counter is higher than zero.
|
|
114
176
|
newName = name
|
|
115
177
|
if counter > 0:
|
|
@@ -123,6 +185,8 @@ def makeUniqueGroupName(name, groupNames, counter=0):
|
|
|
123
185
|
|
|
124
186
|
def test():
|
|
125
187
|
"""
|
|
188
|
+
Tests for :func:`.convertUFO1OrUFO2KerningToUFO3Kerning`.
|
|
189
|
+
|
|
126
190
|
No known prefixes.
|
|
127
191
|
|
|
128
192
|
>>> testKerning = {
|
fontTools/ufoLib/errors.py
CHANGED
|
@@ -10,6 +10,14 @@ class UnsupportedUFOFormat(UFOLibError):
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class GlifLibError(UFOLibError):
|
|
13
|
+
"""An error raised by glifLib.
|
|
14
|
+
|
|
15
|
+
This class is a loose backport of PEP 678, adding a :attr:`.note`
|
|
16
|
+
attribute that can hold additional context for errors encountered.
|
|
17
|
+
|
|
18
|
+
It will be maintained until only Python 3.11-and-later are supported.
|
|
19
|
+
"""
|
|
20
|
+
|
|
13
21
|
def _add_note(self, note: str) -> None:
|
|
14
22
|
# Loose backport of PEP 678 until we only support Python 3.11+, used for
|
|
15
23
|
# adding additional context to errors.
|
fontTools/ufoLib/etree.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""DEPRECATED - This module is kept here only as a backward compatibility shim
|
|
2
|
-
for the old ufoLib.etree module, which was moved to fontTools.misc.etree
|
|
2
|
+
for the old ufoLib.etree module, which was moved to :mod:`fontTools.misc.etree`.
|
|
3
3
|
Please use the latter instead.
|
|
4
4
|
"""
|
|
5
5
|
|