fonttools 4.58.5__cp312-cp312-win32.whl → 4.59.0__cp312-cp312-win32.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/cu2qu/cu2qu.cp312-win32.pyd +0 -0
- fontTools/feaLib/lexer.cp312-win32.pyd +0 -0
- fontTools/merge/__init__.py +1 -1
- fontTools/misc/bezierTools.cp312-win32.pyd +0 -0
- fontTools/misc/filesystem/__init__.py +68 -0
- fontTools/misc/filesystem/_base.py +134 -0
- fontTools/misc/filesystem/_copy.py +45 -0
- fontTools/misc/filesystem/_errors.py +54 -0
- fontTools/misc/filesystem/_info.py +75 -0
- fontTools/misc/filesystem/_osfs.py +164 -0
- fontTools/misc/filesystem/_path.py +67 -0
- fontTools/misc/filesystem/_subfs.py +92 -0
- fontTools/misc/filesystem/_tempfs.py +34 -0
- fontTools/misc/filesystem/_tools.py +34 -0
- fontTools/misc/filesystem/_walk.py +55 -0
- fontTools/misc/filesystem/_zipfs.py +204 -0
- fontTools/misc/sstruct.py +2 -6
- fontTools/misc/xmlWriter.py +28 -1
- fontTools/pens/momentsPen.cp312-win32.pyd +0 -0
- fontTools/pens/roundingPen.py +2 -2
- fontTools/qu2cu/qu2cu.cp312-win32.pyd +0 -0
- fontTools/subset/__init__.py +11 -11
- fontTools/ttLib/sfnt.py +2 -3
- fontTools/ttLib/tables/S__i_l_f.py +2 -2
- fontTools/ttLib/tables/T_S_I__1.py +2 -5
- fontTools/ttLib/tables/T_S_I__5.py +2 -2
- fontTools/ttLib/tables/_c_m_a_p.py +1 -1
- fontTools/ttLib/tables/_c_v_t.py +1 -2
- fontTools/ttLib/tables/_g_l_y_f.py +9 -10
- fontTools/ttLib/tables/_h_d_m_x.py +4 -4
- fontTools/ttLib/tables/_l_o_c_a.py +2 -2
- fontTools/ttLib/tables/_p_o_s_t.py +3 -4
- fontTools/ttLib/tables/otBase.py +2 -4
- fontTools/ttLib/tables/otTables.py +7 -12
- fontTools/ttLib/tables/sbixStrike.py +3 -3
- fontTools/ttLib/ttFont.py +7 -16
- fontTools/ttLib/woff2.py +10 -13
- fontTools/ufoLib/__init__.py +20 -25
- fontTools/ufoLib/glifLib.py +12 -17
- fontTools/ufoLib/validators.py +2 -4
- fontTools/unicodedata/__init__.py +2 -0
- fontTools/varLib/hvar.py +1 -1
- fontTools/varLib/iup.cp312-win32.pyd +0 -0
- {fonttools-4.58.5.dist-info → fonttools-4.59.0.dist-info}/METADATA +19 -3
- {fonttools-4.58.5.dist-info → fonttools-4.59.0.dist-info}/RECORD +52 -40
- {fonttools-4.58.5.dist-info → fonttools-4.59.0.dist-info}/licenses/LICENSE.external +29 -0
- {fonttools-4.58.5.data → fonttools-4.59.0.data}/data/share/man/man1/ttx.1 +0 -0
- {fonttools-4.58.5.dist-info → fonttools-4.59.0.dist-info}/WHEEL +0 -0
- {fonttools-4.58.5.dist-info → fonttools-4.59.0.dist-info}/entry_points.txt +0 -0
- {fonttools-4.58.5.dist-info → fonttools-4.59.0.dist-info}/licenses/LICENSE +0 -0
- {fonttools-4.58.5.dist-info → fonttools-4.59.0.dist-info}/top_level.txt +0 -0
|
@@ -974,11 +974,10 @@ class Glyph(object):
|
|
|
974
974
|
lastcomponent = len(self.components) - 1
|
|
975
975
|
more = 1
|
|
976
976
|
haveInstructions = 0
|
|
977
|
-
for i in
|
|
977
|
+
for i, compo in enumerate(self.components):
|
|
978
978
|
if i == lastcomponent:
|
|
979
979
|
haveInstructions = hasattr(self, "program")
|
|
980
980
|
more = 0
|
|
981
|
-
compo = self.components[i]
|
|
982
981
|
data = data + compo.compile(more, haveInstructions, glyfTable)
|
|
983
982
|
if haveInstructions:
|
|
984
983
|
instructions = self.program.getBytecode()
|
|
@@ -2037,8 +2036,8 @@ class GlyphCoordinates(object):
|
|
|
2037
2036
|
if round is noRound:
|
|
2038
2037
|
return
|
|
2039
2038
|
a = self._a
|
|
2040
|
-
for i in
|
|
2041
|
-
a[i] = round(
|
|
2039
|
+
for i, value in enumerate(a):
|
|
2040
|
+
a[i] = round(value)
|
|
2042
2041
|
|
|
2043
2042
|
def calcBounds(self):
|
|
2044
2043
|
a = self._a
|
|
@@ -2168,8 +2167,8 @@ class GlyphCoordinates(object):
|
|
|
2168
2167
|
"""
|
|
2169
2168
|
r = self.copy()
|
|
2170
2169
|
a = r._a
|
|
2171
|
-
for i in
|
|
2172
|
-
a[i] = -
|
|
2170
|
+
for i, value in enumerate(a):
|
|
2171
|
+
a[i] = -value
|
|
2173
2172
|
return r
|
|
2174
2173
|
|
|
2175
2174
|
def __round__(self, *, round=otRound):
|
|
@@ -2214,8 +2213,8 @@ class GlyphCoordinates(object):
|
|
|
2214
2213
|
other = other._a
|
|
2215
2214
|
a = self._a
|
|
2216
2215
|
assert len(a) == len(other)
|
|
2217
|
-
for i in
|
|
2218
|
-
a[i] +=
|
|
2216
|
+
for i, value in enumerate(other):
|
|
2217
|
+
a[i] += value
|
|
2219
2218
|
return self
|
|
2220
2219
|
return NotImplemented
|
|
2221
2220
|
|
|
@@ -2238,8 +2237,8 @@ class GlyphCoordinates(object):
|
|
|
2238
2237
|
other = other._a
|
|
2239
2238
|
a = self._a
|
|
2240
2239
|
assert len(a) == len(other)
|
|
2241
|
-
for i in
|
|
2242
|
-
a[i] -=
|
|
2240
|
+
for i, value in enumerate(other):
|
|
2241
|
+
a[i] -= value
|
|
2243
2242
|
return self
|
|
2244
2243
|
return NotImplemented
|
|
2245
2244
|
|
|
@@ -65,8 +65,8 @@ class table__h_d_m_x(DefaultTable.DefaultTable):
|
|
|
65
65
|
items = sorted(self.hdmx.items())
|
|
66
66
|
for ppem, widths in items:
|
|
67
67
|
data = data + bytechr(ppem) + bytechr(max(widths.values()))
|
|
68
|
-
for
|
|
69
|
-
width = widths[
|
|
68
|
+
for glyphName in glyphOrder:
|
|
69
|
+
width = widths[glyphName]
|
|
70
70
|
data = data + bytechr(width)
|
|
71
71
|
data = data + pad
|
|
72
72
|
return data
|
|
@@ -123,5 +123,5 @@ class table__h_d_m_x(DefaultTable.DefaultTable):
|
|
|
123
123
|
glyphName = safeEval('"""' + glyphName + '"""')
|
|
124
124
|
line = list(map(int, line[1:]))
|
|
125
125
|
assert len(line) == len(ppems), "illegal hdmx format"
|
|
126
|
-
for i in
|
|
127
|
-
hdmx[
|
|
126
|
+
for i, ppem in enumerate(ppems):
|
|
127
|
+
hdmx[ppem][glyphName] = line[i]
|
|
@@ -46,8 +46,8 @@ class table__l_o_c_a(DefaultTable.DefaultTable):
|
|
|
46
46
|
max_location = 0
|
|
47
47
|
if max_location < 0x20000 and all(l % 2 == 0 for l in self.locations):
|
|
48
48
|
locations = array.array("H")
|
|
49
|
-
for
|
|
50
|
-
locations.append(
|
|
49
|
+
for location in self.locations:
|
|
50
|
+
locations.append(location // 2)
|
|
51
51
|
ttFont["head"].indexToLocFormat = 0
|
|
52
52
|
else:
|
|
53
53
|
locations = array.array("I", self.locations)
|
|
@@ -174,10 +174,9 @@ class table__p_o_s_t(DefaultTable.DefaultTable):
|
|
|
174
174
|
extraNames = self.extraNames = [
|
|
175
175
|
n for n in self.extraNames if n not in standardGlyphOrder
|
|
176
176
|
]
|
|
177
|
-
for i in
|
|
178
|
-
extraDict[
|
|
179
|
-
for
|
|
180
|
-
glyphName = glyphOrder[glyphID]
|
|
177
|
+
for i, name in enumerate(extraNames):
|
|
178
|
+
extraDict[name] = i
|
|
179
|
+
for glyphName in glyphOrder:
|
|
181
180
|
if glyphName in self.mapping:
|
|
182
181
|
psName = self.mapping[glyphName]
|
|
183
182
|
else:
|
fontTools/ttLib/tables/otBase.py
CHANGED
|
@@ -500,8 +500,7 @@ class OTTableWriter(object):
|
|
|
500
500
|
internedTables = {}
|
|
501
501
|
|
|
502
502
|
items = self.items
|
|
503
|
-
for i in
|
|
504
|
-
item = items[i]
|
|
503
|
+
for i, item in enumerate(items):
|
|
505
504
|
if hasattr(item, "getCountData"):
|
|
506
505
|
items[i] = item.getCountData()
|
|
507
506
|
elif hasattr(item, "subWriter"):
|
|
@@ -1130,8 +1129,7 @@ class BaseTable(object):
|
|
|
1130
1129
|
for conv in self.getConverters():
|
|
1131
1130
|
if conv.repeat:
|
|
1132
1131
|
value = getattr(self, conv.name, [])
|
|
1133
|
-
for i in
|
|
1134
|
-
item = value[i]
|
|
1132
|
+
for i, item in enumerate(value):
|
|
1135
1133
|
conv.xmlWrite(xmlWriter, font, item, conv.name, [("index", i)])
|
|
1136
1134
|
else:
|
|
1137
1135
|
if conv.aux and not eval(conv.aux, None, vars(self)):
|
|
@@ -990,8 +990,7 @@ class Coverage(FormatSwitchingBaseTable):
|
|
|
990
990
|
if brokenOrder or len(ranges) * 3 < len(glyphs): # 3 words vs. 1 word
|
|
991
991
|
# Format 2 is more compact
|
|
992
992
|
index = 0
|
|
993
|
-
for i in
|
|
994
|
-
start, end = ranges[i]
|
|
993
|
+
for i, (start, end) in enumerate(ranges):
|
|
995
994
|
r = RangeRecord()
|
|
996
995
|
r.StartID = start
|
|
997
996
|
r.Start = font.getGlyphName(start)
|
|
@@ -1404,8 +1403,7 @@ class ClassDef(FormatSwitchingBaseTable):
|
|
|
1404
1403
|
glyphCount = endGlyph - startGlyph + 1
|
|
1405
1404
|
if len(ranges) * 3 < glyphCount + 1:
|
|
1406
1405
|
# Format 2 is more compact
|
|
1407
|
-
for i in
|
|
1408
|
-
cls, start, startName, end, endName = ranges[i]
|
|
1406
|
+
for i, (cls, start, startName, end, endName) in enumerate(ranges):
|
|
1409
1407
|
rec = ClassRangeRecord()
|
|
1410
1408
|
rec.Start = startName
|
|
1411
1409
|
rec.End = endName
|
|
@@ -1463,8 +1461,7 @@ class AlternateSubst(FormatSwitchingBaseTable):
|
|
|
1463
1461
|
if alternates is None:
|
|
1464
1462
|
alternates = self.alternates = {}
|
|
1465
1463
|
items = list(alternates.items())
|
|
1466
|
-
for i in
|
|
1467
|
-
glyphName, set = items[i]
|
|
1464
|
+
for i, (glyphName, set) in enumerate(items):
|
|
1468
1465
|
items[i] = font.getGlyphID(glyphName), glyphName, set
|
|
1469
1466
|
items.sort()
|
|
1470
1467
|
cov = Coverage()
|
|
@@ -1520,8 +1517,8 @@ class LigatureSubst(FormatSwitchingBaseTable):
|
|
|
1520
1517
|
input = _getGlyphsFromCoverageTable(rawTable["Coverage"])
|
|
1521
1518
|
ligSets = rawTable["LigatureSet"]
|
|
1522
1519
|
assert len(input) == len(ligSets)
|
|
1523
|
-
for i in
|
|
1524
|
-
ligatures[
|
|
1520
|
+
for i, inp in enumerate(input):
|
|
1521
|
+
ligatures[inp] = ligSets[i].Ligature
|
|
1525
1522
|
else:
|
|
1526
1523
|
assert 0, "unknown format: %s" % self.Format
|
|
1527
1524
|
self.ligatures = ligatures
|
|
@@ -1577,8 +1574,7 @@ class LigatureSubst(FormatSwitchingBaseTable):
|
|
|
1577
1574
|
ligatures = newLigatures
|
|
1578
1575
|
|
|
1579
1576
|
items = list(ligatures.items())
|
|
1580
|
-
for i in
|
|
1581
|
-
glyphName, set = items[i]
|
|
1577
|
+
for i, (glyphName, set) in enumerate(items):
|
|
1582
1578
|
items[i] = font.getGlyphID(glyphName), glyphName, set
|
|
1583
1579
|
items.sort()
|
|
1584
1580
|
cov = Coverage()
|
|
@@ -2279,8 +2275,7 @@ def fixLookupOverFlows(ttf, overflowRecord):
|
|
|
2279
2275
|
lookup = lookups[lookupIndex]
|
|
2280
2276
|
if lookup.LookupType != extType:
|
|
2281
2277
|
lookup.LookupType = extType
|
|
2282
|
-
for si in
|
|
2283
|
-
subTable = lookup.SubTable[si]
|
|
2278
|
+
for si, subTable in enumerate(lookup.SubTable):
|
|
2284
2279
|
extSubTableClass = lookupTypes[overflowRecord.tableType][extType]
|
|
2285
2280
|
extSubTable = extSubTableClass()
|
|
2286
2281
|
extSubTable.Format = 1
|
|
@@ -128,9 +128,9 @@ class Strike(object):
|
|
|
128
128
|
xmlWriter.simpletag("resolution", value=self.resolution)
|
|
129
129
|
xmlWriter.newline()
|
|
130
130
|
glyphOrder = ttFont.getGlyphOrder()
|
|
131
|
-
for
|
|
132
|
-
if
|
|
133
|
-
self.glyphs[
|
|
131
|
+
for glyphName in glyphOrder:
|
|
132
|
+
if glyphName in self.glyphs:
|
|
133
|
+
self.glyphs[glyphName].toXML(xmlWriter, ttFont)
|
|
134
134
|
# TODO: what if there are more glyph data records than (glyf table) glyphs?
|
|
135
135
|
xmlWriter.endtag("strike")
|
|
136
136
|
xmlWriter.newline()
|
fontTools/ttLib/ttFont.py
CHANGED
|
@@ -259,9 +259,8 @@ class TTFont(object):
|
|
|
259
259
|
"head"
|
|
260
260
|
] # make sure 'head' is loaded so the recalculation is actually done
|
|
261
261
|
|
|
262
|
-
tags =
|
|
263
|
-
|
|
264
|
-
tags.remove("GlyphOrder")
|
|
262
|
+
tags = self.keys()
|
|
263
|
+
tags.pop(0) # skip GlyphOrder tag
|
|
265
264
|
numTables = len(tags)
|
|
266
265
|
# write to a temporary stream to allow saving to unseekable streams
|
|
267
266
|
writer = SFNTWriter(
|
|
@@ -307,14 +306,9 @@ class TTFont(object):
|
|
|
307
306
|
self.disassembleInstructions = disassembleInstructions
|
|
308
307
|
self.bitmapGlyphDataFormat = bitmapGlyphDataFormat
|
|
309
308
|
if not tables:
|
|
310
|
-
tables =
|
|
311
|
-
if "GlyphOrder" not in tables:
|
|
312
|
-
tables = ["GlyphOrder"] + tables
|
|
309
|
+
tables = self.keys()
|
|
313
310
|
if skipTables:
|
|
314
|
-
for tag in skipTables
|
|
315
|
-
if tag in tables:
|
|
316
|
-
tables.remove(tag)
|
|
317
|
-
numTables = len(tables)
|
|
311
|
+
tables = [tag for tag in tables if tag not in skipTables]
|
|
318
312
|
|
|
319
313
|
if writeVersion:
|
|
320
314
|
from fontTools import version
|
|
@@ -337,8 +331,7 @@ class TTFont(object):
|
|
|
337
331
|
else:
|
|
338
332
|
path, ext = os.path.splitext(writer.filename)
|
|
339
333
|
|
|
340
|
-
for
|
|
341
|
-
tag = tables[i]
|
|
334
|
+
for tag in tables:
|
|
342
335
|
if splitTables:
|
|
343
336
|
tablePath = path + "." + tagToIdentifier(tag) + ext
|
|
344
337
|
tableWriter = xmlWriter.XMLWriter(
|
|
@@ -608,8 +601,7 @@ class TTFont(object):
|
|
|
608
601
|
else:
|
|
609
602
|
reversecmap = {}
|
|
610
603
|
useCount = {}
|
|
611
|
-
for i in
|
|
612
|
-
tempName = glyphOrder[i]
|
|
604
|
+
for i, tempName in enumerate(glyphOrder):
|
|
613
605
|
if tempName in reversecmap:
|
|
614
606
|
# If a font maps both U+0041 LATIN CAPITAL LETTER A and
|
|
615
607
|
# U+0391 GREEK CAPITAL LETTER ALPHA to the same glyph,
|
|
@@ -866,8 +858,7 @@ class GlyphOrder(object):
|
|
|
866
858
|
"The 'id' attribute is only for humans; " "it is ignored when parsed."
|
|
867
859
|
)
|
|
868
860
|
writer.newline()
|
|
869
|
-
for i in
|
|
870
|
-
glyphName = glyphOrder[i]
|
|
861
|
+
for i, glyphName in enumerate(glyphOrder):
|
|
871
862
|
writer.simpletag("GlyphID", id=i, name=glyphName)
|
|
872
863
|
writer.newline()
|
|
873
864
|
|
fontTools/ttLib/woff2.py
CHANGED
|
@@ -394,10 +394,9 @@ class WOFF2Writer(SFNTWriter):
|
|
|
394
394
|
|
|
395
395
|
def _calcMasterChecksum(self):
|
|
396
396
|
"""Calculate checkSumAdjustment."""
|
|
397
|
-
tags = list(self.tables.keys())
|
|
398
397
|
checksums = []
|
|
399
|
-
for
|
|
400
|
-
checksums.append(self.tables[
|
|
398
|
+
for tag in self.tables.keys():
|
|
399
|
+
checksums.append(self.tables[tag].checkSum)
|
|
401
400
|
|
|
402
401
|
# Create a SFNT directory for checksum calculation purposes
|
|
403
402
|
self.searchRange, self.entrySelector, self.rangeShift = getSearchRange(
|
|
@@ -642,10 +641,10 @@ woff2OverlapSimpleBitmapFlag = 0x0001
|
|
|
642
641
|
|
|
643
642
|
def getKnownTagIndex(tag):
|
|
644
643
|
"""Return index of 'tag' in woff2KnownTags list. Return 63 if not found."""
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
644
|
+
try:
|
|
645
|
+
return woff2KnownTags.index(tag)
|
|
646
|
+
except ValueError:
|
|
647
|
+
return woff2UnknownTagIndex
|
|
649
648
|
|
|
650
649
|
|
|
651
650
|
class WOFF2DirectoryEntry(DirectoryEntry):
|
|
@@ -747,8 +746,8 @@ class WOFF2LocaTable(getTableClass("loca")):
|
|
|
747
746
|
"indexFormat is 0 but local offsets not multiples of 2"
|
|
748
747
|
)
|
|
749
748
|
locations = array.array("H")
|
|
750
|
-
for
|
|
751
|
-
locations.append(
|
|
749
|
+
for location in self.locations:
|
|
750
|
+
locations.append(location // 2)
|
|
752
751
|
else:
|
|
753
752
|
locations = array.array("I", self.locations)
|
|
754
753
|
if sys.byteorder != "big":
|
|
@@ -1026,11 +1025,10 @@ class WOFF2GlyfTable(getTableClass("glyf")):
|
|
|
1026
1025
|
lastcomponent = len(glyph.components) - 1
|
|
1027
1026
|
more = 1
|
|
1028
1027
|
haveInstructions = 0
|
|
1029
|
-
for i in
|
|
1028
|
+
for i, component in enumerate(glyph.components):
|
|
1030
1029
|
if i == lastcomponent:
|
|
1031
1030
|
haveInstructions = hasattr(glyph, "program")
|
|
1032
1031
|
more = 0
|
|
1033
|
-
component = glyph.components[i]
|
|
1034
1032
|
self.compositeStream += component.compile(more, haveInstructions, self)
|
|
1035
1033
|
if haveInstructions:
|
|
1036
1034
|
self._encodeInstructions(glyph)
|
|
@@ -1078,9 +1076,8 @@ class WOFF2GlyfTable(getTableClass("glyf")):
|
|
|
1078
1076
|
|
|
1079
1077
|
flags = array.array("B")
|
|
1080
1078
|
triplets = array.array("B")
|
|
1081
|
-
for i in
|
|
1079
|
+
for i, (x, y) in enumerate(coordinates):
|
|
1082
1080
|
onCurve = glyph.flags[i] & _g_l_y_f.flagOnCurve
|
|
1083
|
-
x, y = coordinates[i]
|
|
1084
1081
|
absX = abs(x)
|
|
1085
1082
|
absY = abs(y)
|
|
1086
1083
|
onCurveBit = 0 if onCurve else 128
|
fontTools/ufoLib/__init__.py
CHANGED
|
@@ -32,30 +32,27 @@ Value conversion functions are available for converting
|
|
|
32
32
|
- :func:`.convertFontInfoValueForAttributeFromVersion3ToVersion2`
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
|
-
import
|
|
36
|
-
from copy import deepcopy
|
|
37
|
-
from os import fsdecode
|
|
35
|
+
import enum
|
|
38
36
|
import logging
|
|
37
|
+
import os
|
|
39
38
|
import zipfile
|
|
40
|
-
import enum
|
|
41
39
|
from collections import OrderedDict
|
|
42
|
-
import
|
|
43
|
-
import
|
|
44
|
-
|
|
45
|
-
import fs
|
|
46
|
-
import fs.copy
|
|
47
|
-
import fs.osfs
|
|
48
|
-
import fs.zipfs
|
|
49
|
-
import fs.tempfs
|
|
50
|
-
import fs.tools
|
|
40
|
+
from copy import deepcopy
|
|
41
|
+
from os import fsdecode
|
|
42
|
+
|
|
43
|
+
from fontTools.misc import filesystem as fs
|
|
51
44
|
from fontTools.misc import plistlib
|
|
52
|
-
from fontTools.ufoLib.validators import *
|
|
53
|
-
from fontTools.ufoLib.filenames import userNameToFileName
|
|
54
45
|
from fontTools.ufoLib.converters import convertUFO1OrUFO2KerningToUFO3Kerning
|
|
55
46
|
from fontTools.ufoLib.errors import UFOLibError
|
|
56
|
-
from fontTools.ufoLib.
|
|
47
|
+
from fontTools.ufoLib.filenames import userNameToFileName
|
|
48
|
+
from fontTools.ufoLib.utils import _VersionTupleEnumMixin, numberTypes
|
|
49
|
+
from fontTools.ufoLib.validators import *
|
|
50
|
+
|
|
51
|
+
# client code can check this to see if the upstream `fs` package is being used
|
|
52
|
+
haveFS = fs._haveFS
|
|
57
53
|
|
|
58
54
|
__all__ = [
|
|
55
|
+
"haveFS",
|
|
59
56
|
"makeUFOPath",
|
|
60
57
|
"UFOLibError",
|
|
61
58
|
"UFOReader",
|
|
@@ -184,7 +181,7 @@ class _UFOBaseIO:
|
|
|
184
181
|
return
|
|
185
182
|
self.fs.writebytes(fileName, data)
|
|
186
183
|
else:
|
|
187
|
-
with self.fs.
|
|
184
|
+
with self.fs.open(fileName, mode="wb") as fp:
|
|
188
185
|
try:
|
|
189
186
|
plistlib.dump(obj, fp)
|
|
190
187
|
except Exception as e:
|
|
@@ -412,7 +409,7 @@ class UFOReader(_UFOBaseIO):
|
|
|
412
409
|
path = fsdecode(path)
|
|
413
410
|
try:
|
|
414
411
|
if encoding is None:
|
|
415
|
-
return self.fs.
|
|
412
|
+
return self.fs.open(path, mode="rb")
|
|
416
413
|
else:
|
|
417
414
|
return self.fs.open(path, mode="r", encoding=encoding)
|
|
418
415
|
except fs.errors.ResourceNotFound:
|
|
@@ -818,7 +815,7 @@ class UFOReader(_UFOBaseIO):
|
|
|
818
815
|
# systems often have hidden directories
|
|
819
816
|
continue
|
|
820
817
|
if validate:
|
|
821
|
-
with imagesFS.
|
|
818
|
+
with imagesFS.open(path.name, "rb") as fp:
|
|
822
819
|
valid, error = pngValidator(fileObj=fp)
|
|
823
820
|
if valid:
|
|
824
821
|
result.append(path.name)
|
|
@@ -984,18 +981,16 @@ class UFOWriter(UFOReader):
|
|
|
984
981
|
% len(rootDirs)
|
|
985
982
|
)
|
|
986
983
|
else:
|
|
987
|
-
|
|
988
|
-
# when its root subdirectory is closed
|
|
989
|
-
self.fs = parentFS.opendir(
|
|
990
|
-
rootDirs[0], factory=fs.subfs.ClosingSubFS
|
|
991
|
-
)
|
|
984
|
+
rootDir = rootDirs[0]
|
|
992
985
|
else:
|
|
993
986
|
# if the output zip file didn't exist, we create the root folder;
|
|
994
987
|
# we name it the same as input 'path', but with '.ufo' extension
|
|
995
988
|
rootDir = os.path.splitext(os.path.basename(path))[0] + ".ufo"
|
|
996
989
|
parentFS = fs.zipfs.ZipFS(path, write=True, encoding="utf-8")
|
|
997
990
|
parentFS.makedir(rootDir)
|
|
998
|
-
|
|
991
|
+
# 'ClosingSubFS' ensures that the parent filesystem is closed
|
|
992
|
+
# when its root subdirectory is closed
|
|
993
|
+
self.fs = parentFS.opendir(rootDir, factory=fs.subfs.ClosingSubFS)
|
|
999
994
|
else:
|
|
1000
995
|
self.fs = fs.osfs.OSFS(path, create=True)
|
|
1001
996
|
self._fileStructure = structure
|
fontTools/ufoLib/glifLib.py
CHANGED
|
@@ -3,7 +3,7 @@ Generic module for reading and writing the .glif format.
|
|
|
3
3
|
|
|
4
4
|
More info about the .glif format (GLyphInterchangeFormat) can be found here:
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
http://unifiedfontobject.org
|
|
7
7
|
|
|
8
8
|
The main class in this module is :class:`GlyphSet`. It manages a set of .glif files
|
|
9
9
|
in a folder. It offers two ways to read glyph data, and one way to write
|
|
@@ -12,33 +12,28 @@ glyph data. See the class doc string for details.
|
|
|
12
12
|
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
|
|
15
|
-
import logging
|
|
16
15
|
import enum
|
|
17
|
-
|
|
16
|
+
import logging
|
|
18
17
|
from collections import OrderedDict
|
|
19
|
-
import
|
|
20
|
-
|
|
21
|
-
import fs
|
|
22
|
-
import
|
|
23
|
-
import fs.path
|
|
18
|
+
from warnings import warn
|
|
19
|
+
|
|
20
|
+
import fontTools.misc.filesystem as fs
|
|
21
|
+
from fontTools.misc import etree, plistlib
|
|
24
22
|
from fontTools.misc.textTools import tobytes
|
|
25
|
-
from fontTools.misc import plistlib
|
|
26
23
|
from fontTools.pens.pointPen import AbstractPointPen, PointToSegmentPen
|
|
24
|
+
from fontTools.ufoLib import UFOFormatVersion, _UFOBaseIO
|
|
27
25
|
from fontTools.ufoLib.errors import GlifLibError
|
|
28
26
|
from fontTools.ufoLib.filenames import userNameToFileName
|
|
27
|
+
from fontTools.ufoLib.utils import _VersionTupleEnumMixin, numberTypes
|
|
29
28
|
from fontTools.ufoLib.validators import (
|
|
30
|
-
|
|
29
|
+
anchorsValidator,
|
|
31
30
|
colorValidator,
|
|
31
|
+
genericTypeValidator,
|
|
32
|
+
glyphLibValidator,
|
|
32
33
|
guidelinesValidator,
|
|
33
|
-
anchorsValidator,
|
|
34
34
|
identifierValidator,
|
|
35
35
|
imageValidator,
|
|
36
|
-
glyphLibValidator,
|
|
37
36
|
)
|
|
38
|
-
from fontTools.misc import etree
|
|
39
|
-
from fontTools.ufoLib import _UFOBaseIO, UFOFormatVersion
|
|
40
|
-
from fontTools.ufoLib.utils import numberTypes, _VersionTupleEnumMixin
|
|
41
|
-
|
|
42
37
|
|
|
43
38
|
__all__ = [
|
|
44
39
|
"GlyphSet",
|
|
@@ -206,7 +201,7 @@ class GlyphSet(_UFOBaseIO):
|
|
|
206
201
|
# 'dirName' is kept for backward compatibility only, but it's DEPRECATED
|
|
207
202
|
# as it's not guaranteed that it maps to an existing OSFS directory.
|
|
208
203
|
# Client could use the FS api via the `self.fs` attribute instead.
|
|
209
|
-
self.dirName = fs.path.
|
|
204
|
+
self.dirName = fs.path.basename(path)
|
|
210
205
|
self.fs = filesystem
|
|
211
206
|
# if glyphSet contains no 'contents.plist', we consider it empty
|
|
212
207
|
self._havePreviousFile = filesystem.exists(CONTENTS_FILENAME)
|
fontTools/ufoLib/validators.py
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
"""Various low level data validators."""
|
|
2
2
|
|
|
3
3
|
import calendar
|
|
4
|
+
from collections.abc import Mapping
|
|
4
5
|
from io import open
|
|
5
|
-
import fs.base
|
|
6
|
-
import fs.osfs
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
import fontTools.misc.filesystem as fs
|
|
9
8
|
from fontTools.ufoLib.utils import numberTypes
|
|
10
9
|
|
|
11
|
-
|
|
12
10
|
# -------
|
|
13
11
|
# Generic
|
|
14
12
|
# -------
|
fontTools/varLib/hvar.py
CHANGED
|
@@ -56,7 +56,7 @@ def add_HVAR(font):
|
|
|
56
56
|
def add_VVAR(font):
|
|
57
57
|
if "VVAR" in font:
|
|
58
58
|
del font["VVAR"]
|
|
59
|
-
getAdvanceMetrics = partial(_get_advance_metrics, font, axisTags,
|
|
59
|
+
getAdvanceMetrics = partial(_get_advance_metrics, font, axisTags, VVAR_FIELDS)
|
|
60
60
|
axisTags = [axis.axisTag for axis in font["fvar"].axes]
|
|
61
61
|
_add_VHVAR(font, axisTags, VVAR_FIELDS, getAdvanceMetrics)
|
|
62
62
|
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fonttools
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.59.0
|
|
4
4
|
Summary: Tools to manipulate font files
|
|
5
5
|
Home-page: http://github.com/fonttools/fonttools
|
|
6
6
|
Author: Just van Rossum
|
|
@@ -31,7 +31,6 @@ Description-Content-Type: text/x-rst
|
|
|
31
31
|
License-File: LICENSE
|
|
32
32
|
License-File: LICENSE.external
|
|
33
33
|
Provides-Extra: ufo
|
|
34
|
-
Requires-Dist: fs<3,>=2.2.0; extra == "ufo"
|
|
35
34
|
Provides-Extra: lxml
|
|
36
35
|
Requires-Dist: lxml>=4.0; extra == "lxml"
|
|
37
36
|
Provides-Extra: woff
|
|
@@ -57,7 +56,6 @@ Requires-Dist: skia-pathops>=0.5.0; extra == "pathops"
|
|
|
57
56
|
Provides-Extra: repacker
|
|
58
57
|
Requires-Dist: uharfbuzz>=0.23.0; extra == "repacker"
|
|
59
58
|
Provides-Extra: all
|
|
60
|
-
Requires-Dist: fs<3,>=2.2.0; extra == "all"
|
|
61
59
|
Requires-Dist: lxml>=4.0; extra == "all"
|
|
62
60
|
Requires-Dist: brotli>=1.0.1; platform_python_implementation == "CPython" and extra == "all"
|
|
63
61
|
Requires-Dist: brotlicffi>=0.8.0; platform_python_implementation != "CPython" and extra == "all"
|
|
@@ -388,6 +386,24 @@ Have fun!
|
|
|
388
386
|
Changelog
|
|
389
387
|
~~~~~~~~~
|
|
390
388
|
|
|
389
|
+
4.59.0 (released 2025-07-16)
|
|
390
|
+
----------------------------
|
|
391
|
+
|
|
392
|
+
- Removed hard-dependency on pyfilesystem2 (``fs`` package) from ``fonttools[ufo]`` extra.
|
|
393
|
+
This is replaced by the `fontTools.misc.filesystem` package, a stdlib-only, drop-in
|
|
394
|
+
replacement for the subset of the pyfilesystem2's API used by ``fontTools.ufoLib``.
|
|
395
|
+
The latter should continue to work with the upstream ``fs`` (we even test with/without).
|
|
396
|
+
Clients who wish to continue using ``fs`` can do so by depending on it directly instead
|
|
397
|
+
of via the ``fonttools[ufo]`` extra (#3885, #3620).
|
|
398
|
+
- [xmlWriter] Replace illegal XML characters (e.g. control or non-characters) with "?"
|
|
399
|
+
when dumping to ttx (#3868, #71).
|
|
400
|
+
- [varLib.hvar] Fixed vertical metrics fields copy/pasta error (#3884).
|
|
401
|
+
- Micro optimizations in ttLib and sstruct modules (#3878, #3879).
|
|
402
|
+
- [unicodedata] Add Garay script to RTL_SCRIPTS (#3882).
|
|
403
|
+
- [roundingPen] Remove unreliable kwarg usage. Argument names aren’t consistent among
|
|
404
|
+
point pens’ ``.addComponent()`` implementations, in particular ``baseGlyphName``
|
|
405
|
+
vs ``glyphName`` (#3880).
|
|
406
|
+
|
|
391
407
|
4.58.5 (released 2025-07-03)
|
|
392
408
|
----------------------------
|
|
393
409
|
|