fonttools 4.55.4__cp313-cp313-musllinux_1_2_aarch64.whl → 4.61.1__cp313-cp313-musllinux_1_2_aarch64.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.
- fontTools/__init__.py +1 -1
- fontTools/annotations.py +30 -0
- fontTools/cffLib/CFF2ToCFF.py +65 -10
- fontTools/cffLib/__init__.py +61 -26
- fontTools/cffLib/specializer.py +4 -1
- fontTools/cffLib/transforms.py +11 -6
- fontTools/config/__init__.py +15 -0
- fontTools/cu2qu/cu2qu.c +6567 -5579
- fontTools/cu2qu/cu2qu.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/cu2qu/cu2qu.py +36 -4
- fontTools/cu2qu/ufo.py +14 -0
- fontTools/designspaceLib/__init__.py +8 -3
- fontTools/designspaceLib/statNames.py +14 -7
- fontTools/feaLib/ast.py +24 -15
- fontTools/feaLib/builder.py +139 -66
- fontTools/feaLib/error.py +1 -1
- fontTools/feaLib/lexer.c +7038 -7995
- fontTools/feaLib/lexer.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/feaLib/parser.py +75 -40
- fontTools/feaLib/variableScalar.py +6 -1
- fontTools/fontBuilder.py +50 -44
- fontTools/merge/__init__.py +1 -1
- fontTools/merge/cmap.py +33 -1
- fontTools/merge/tables.py +12 -1
- fontTools/misc/bezierTools.c +14913 -17013
- fontTools/misc/bezierTools.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/misc/bezierTools.py +4 -1
- fontTools/misc/configTools.py +3 -1
- fontTools/misc/enumTools.py +23 -0
- fontTools/misc/etree.py +4 -27
- 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/fixedTools.py +1 -1
- fontTools/misc/loggingTools.py +1 -1
- fontTools/misc/psCharStrings.py +17 -2
- fontTools/misc/sstruct.py +2 -6
- fontTools/misc/symfont.py +6 -8
- fontTools/misc/testTools.py +5 -1
- fontTools/misc/textTools.py +4 -2
- fontTools/misc/visitor.py +32 -16
- fontTools/misc/xmlWriter.py +44 -8
- fontTools/mtiLib/__init__.py +1 -3
- fontTools/otlLib/builder.py +402 -155
- fontTools/otlLib/optimize/gpos.py +49 -63
- fontTools/pens/filterPen.py +218 -26
- fontTools/pens/momentsPen.c +5514 -5584
- fontTools/pens/momentsPen.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/pens/pointPen.py +61 -18
- fontTools/pens/roundingPen.py +2 -2
- fontTools/pens/t2CharStringPen.py +31 -11
- fontTools/qu2cu/qu2cu.c +6581 -6168
- fontTools/qu2cu/qu2cu.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/subset/__init__.py +283 -25
- fontTools/subset/svg.py +2 -3
- fontTools/ttLib/__init__.py +4 -0
- fontTools/ttLib/__main__.py +47 -8
- fontTools/ttLib/removeOverlaps.py +7 -5
- fontTools/ttLib/reorderGlyphs.py +8 -7
- fontTools/ttLib/sfnt.py +11 -9
- fontTools/ttLib/tables/D__e_b_g.py +20 -2
- fontTools/ttLib/tables/G_V_A_R_.py +5 -0
- fontTools/ttLib/tables/S__i_l_f.py +2 -2
- fontTools/ttLib/tables/T_S_I__0.py +14 -3
- fontTools/ttLib/tables/T_S_I__1.py +2 -5
- fontTools/ttLib/tables/T_S_I__5.py +18 -7
- fontTools/ttLib/tables/__init__.py +1 -0
- fontTools/ttLib/tables/_a_v_a_r.py +12 -3
- fontTools/ttLib/tables/_c_m_a_p.py +20 -7
- fontTools/ttLib/tables/_c_v_t.py +3 -2
- fontTools/ttLib/tables/_f_p_g_m.py +3 -1
- fontTools/ttLib/tables/_g_l_y_f.py +45 -21
- fontTools/ttLib/tables/_g_v_a_r.py +67 -19
- fontTools/ttLib/tables/_h_d_m_x.py +4 -4
- fontTools/ttLib/tables/_h_m_t_x.py +7 -3
- fontTools/ttLib/tables/_l_o_c_a.py +2 -2
- fontTools/ttLib/tables/_n_a_m_e.py +11 -6
- fontTools/ttLib/tables/_p_o_s_t.py +9 -7
- fontTools/ttLib/tables/otBase.py +5 -12
- fontTools/ttLib/tables/otConverters.py +5 -2
- fontTools/ttLib/tables/otData.py +1 -1
- fontTools/ttLib/tables/otTables.py +33 -30
- fontTools/ttLib/tables/otTraverse.py +2 -1
- fontTools/ttLib/tables/sbixStrike.py +3 -3
- fontTools/ttLib/ttFont.py +666 -120
- fontTools/ttLib/ttGlyphSet.py +0 -10
- fontTools/ttLib/woff2.py +10 -13
- fontTools/ttx.py +13 -1
- fontTools/ufoLib/__init__.py +300 -202
- fontTools/ufoLib/converters.py +103 -30
- fontTools/ufoLib/errors.py +8 -0
- fontTools/ufoLib/etree.py +1 -1
- fontTools/ufoLib/filenames.py +171 -106
- fontTools/ufoLib/glifLib.py +303 -205
- fontTools/ufoLib/kerning.py +98 -48
- fontTools/ufoLib/utils.py +46 -15
- fontTools/ufoLib/validators.py +121 -99
- fontTools/unicodedata/Blocks.py +35 -20
- fontTools/unicodedata/Mirrored.py +446 -0
- fontTools/unicodedata/ScriptExtensions.py +63 -37
- fontTools/unicodedata/Scripts.py +173 -152
- fontTools/unicodedata/__init__.py +10 -2
- fontTools/varLib/__init__.py +198 -109
- fontTools/varLib/avar/__init__.py +0 -0
- fontTools/varLib/avar/__main__.py +72 -0
- fontTools/varLib/avar/build.py +79 -0
- fontTools/varLib/avar/map.py +108 -0
- fontTools/varLib/avar/plan.py +1004 -0
- fontTools/varLib/{avar.py → avar/unbuild.py} +70 -59
- fontTools/varLib/avarPlanner.py +3 -999
- fontTools/varLib/featureVars.py +21 -7
- fontTools/varLib/hvar.py +113 -0
- fontTools/varLib/instancer/__init__.py +180 -65
- fontTools/varLib/interpolatableHelpers.py +3 -0
- fontTools/varLib/iup.c +7564 -6903
- fontTools/varLib/iup.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/varLib/models.py +17 -2
- fontTools/varLib/mutator.py +11 -0
- fontTools/varLib/varStore.py +10 -38
- 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.55.4.dist-info → fonttools-4.61.1.dist-info}/METADATA +269 -1410
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/RECORD +318 -294
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/WHEEL +1 -1
- fonttools-4.61.1.dist-info/licenses/LICENSE.external +388 -0
- {fonttools-4.55.4.data → fonttools-4.61.1.data}/data/share/man/man1/ttx.1 +0 -0
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/entry_points.txt +0 -0
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info/licenses}/LICENSE +0 -0
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/top_level.txt +0 -0
fontTools/__init__.py
CHANGED
fontTools/annotations.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import TYPE_CHECKING, Iterable, Optional, TypeVar, Union
|
|
3
|
+
from collections.abc import Callable, Sequence
|
|
4
|
+
from fontTools.misc.filesystem._base import FS
|
|
5
|
+
from os import PathLike
|
|
6
|
+
from xml.etree.ElementTree import Element as ElementTreeElement
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from fontTools.ufoLib import UFOFormatVersion
|
|
10
|
+
from fontTools.ufoLib.glifLib import GLIFFormatVersion
|
|
11
|
+
from lxml.etree import _Element as LxmlElement
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
T = TypeVar("T") # Generic type
|
|
15
|
+
K = TypeVar("K") # Generic dict key type
|
|
16
|
+
V = TypeVar("V") # Generic dict value type
|
|
17
|
+
|
|
18
|
+
GlyphNameToFileNameFunc = Optional[Callable[[str, set[str]], str]]
|
|
19
|
+
ElementType = Union[ElementTreeElement, "LxmlElement"]
|
|
20
|
+
FormatVersion = Union[int, tuple[int, int]]
|
|
21
|
+
FormatVersions = Optional[Iterable[FormatVersion]]
|
|
22
|
+
GLIFFormatVersionInput = Optional[Union[int, tuple[int, int], "GLIFFormatVersion"]]
|
|
23
|
+
UFOFormatVersionInput = Optional[Union[int, tuple[int, int], "UFOFormatVersion"]]
|
|
24
|
+
IntFloat = Union[int, float]
|
|
25
|
+
KerningPair = tuple[str, str]
|
|
26
|
+
KerningDict = dict[KerningPair, IntFloat]
|
|
27
|
+
KerningGroups = dict[str, Sequence[str]]
|
|
28
|
+
KerningNested = dict[str, dict[str, IntFloat]]
|
|
29
|
+
PathStr = Union[str, PathLike[str]]
|
|
30
|
+
PathOrFS = Union[PathStr, FS]
|
fontTools/cffLib/CFF2ToCFF.py
CHANGED
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
from fontTools.ttLib import TTFont, newTable
|
|
4
4
|
from fontTools.misc.cliTools import makeOutputFileName
|
|
5
|
+
from fontTools.misc.psCharStrings import T2StackUseExtractor
|
|
5
6
|
from fontTools.cffLib import (
|
|
6
7
|
TopDictIndex,
|
|
7
8
|
buildOrder,
|
|
8
9
|
buildDefaults,
|
|
9
10
|
topDictOperators,
|
|
10
11
|
privateDictOperators,
|
|
12
|
+
FDSelect,
|
|
11
13
|
)
|
|
14
|
+
from .transforms import desubroutinizeCharString
|
|
15
|
+
from .specializer import specializeProgram
|
|
12
16
|
from .width import optimizeWidths
|
|
13
17
|
from collections import defaultdict
|
|
14
18
|
import logging
|
|
@@ -27,7 +31,7 @@ def _convertCFF2ToCFF(cff, otFont):
|
|
|
27
31
|
The CFF2 font cannot be variable. (TODO Accept those and convert to the
|
|
28
32
|
default instance?)
|
|
29
33
|
|
|
30
|
-
This assumes a decompiled
|
|
34
|
+
This assumes a decompiled CFF2 table. (i.e. that the object has been
|
|
31
35
|
filled via :meth:`decompile` and e.g. not loaded from XML.)"""
|
|
32
36
|
|
|
33
37
|
cff.major = 1
|
|
@@ -51,9 +55,14 @@ def _convertCFF2ToCFF(cff, otFont):
|
|
|
51
55
|
if hasattr(topDict, key):
|
|
52
56
|
delattr(topDict, key)
|
|
53
57
|
|
|
54
|
-
fdArray = topDict.FDArray
|
|
55
58
|
charStrings = topDict.CharStrings
|
|
56
59
|
|
|
60
|
+
fdArray = topDict.FDArray
|
|
61
|
+
if not hasattr(topDict, "FDSelect"):
|
|
62
|
+
# FDSelect is optional in CFF2, but required in CFF.
|
|
63
|
+
fdSelect = topDict.FDSelect = FDSelect()
|
|
64
|
+
fdSelect.gidArray = [0] * len(charStrings.charStrings)
|
|
65
|
+
|
|
57
66
|
defaults = buildDefaults(privateDictOperators)
|
|
58
67
|
order = buildOrder(privateDictOperators)
|
|
59
68
|
for fd in fdArray:
|
|
@@ -69,6 +78,7 @@ def _convertCFF2ToCFF(cff, otFont):
|
|
|
69
78
|
if hasattr(privateDict, key):
|
|
70
79
|
delattr(privateDict, key)
|
|
71
80
|
|
|
81
|
+
# Add ending operators
|
|
72
82
|
for cs in charStrings.values():
|
|
73
83
|
cs.decompile()
|
|
74
84
|
cs.program.append("endchar")
|
|
@@ -100,23 +110,43 @@ def _convertCFF2ToCFF(cff, otFont):
|
|
|
100
110
|
if width != private.defaultWidthX:
|
|
101
111
|
cs.program.insert(0, width - private.nominalWidthX)
|
|
102
112
|
|
|
113
|
+
# Handle stack use since stack-depth is lower in CFF than in CFF2.
|
|
114
|
+
for glyphName in charStrings.keys():
|
|
115
|
+
cs, fdIndex = charStrings.getItemAndSelector(glyphName)
|
|
116
|
+
if fdIndex is None:
|
|
117
|
+
fdIndex = 0
|
|
118
|
+
private = fdArray[fdIndex].Private
|
|
119
|
+
extractor = T2StackUseExtractor(
|
|
120
|
+
getattr(private, "Subrs", []), cff.GlobalSubrs, private=private
|
|
121
|
+
)
|
|
122
|
+
stackUse = extractor.execute(cs)
|
|
123
|
+
if stackUse > 48: # CFF stack depth is 48
|
|
124
|
+
desubroutinizeCharString(cs)
|
|
125
|
+
cs.program = specializeProgram(cs.program)
|
|
126
|
+
|
|
127
|
+
# Unused subroutines are still in CFF2 (ie. lacking 'return' operator)
|
|
128
|
+
# because they were not decompiled when we added the 'return'.
|
|
129
|
+
# Moreover, some used subroutines may have become unused after the
|
|
130
|
+
# stack-use fixup. So we remove all unused subroutines now.
|
|
131
|
+
cff.remove_unused_subroutines()
|
|
132
|
+
|
|
103
133
|
mapping = {
|
|
104
|
-
name: ("cid" + str(n) if n else ".notdef")
|
|
134
|
+
name: ("cid" + str(n).zfill(5) if n else ".notdef")
|
|
105
135
|
for n, name in enumerate(topDict.charset)
|
|
106
136
|
}
|
|
107
137
|
topDict.charset = [
|
|
108
|
-
"cid" + str(n) if n else ".notdef" for n in range(len(topDict.charset))
|
|
138
|
+
"cid" + str(n).zfill(5) if n else ".notdef" for n in range(len(topDict.charset))
|
|
109
139
|
]
|
|
110
140
|
charStrings.charStrings = {
|
|
111
141
|
mapping[name]: v for name, v in charStrings.charStrings.items()
|
|
112
142
|
}
|
|
113
143
|
|
|
114
|
-
|
|
115
|
-
# the output if I add it.
|
|
116
|
-
# topDict.ROS = ("Adobe", "Identity", 0)
|
|
144
|
+
topDict.ROS = ("Adobe", "Identity", 0)
|
|
117
145
|
|
|
118
146
|
|
|
119
147
|
def convertCFF2ToCFF(font, *, updatePostTable=True):
|
|
148
|
+
if "CFF2" not in font:
|
|
149
|
+
raise ValueError("Input font does not contain a CFF2 table.")
|
|
120
150
|
cff = font["CFF2"].cff
|
|
121
151
|
_convertCFF2ToCFF(cff, font)
|
|
122
152
|
del font["CFF2"]
|
|
@@ -131,7 +161,7 @@ def convertCFF2ToCFF(font, *, updatePostTable=True):
|
|
|
131
161
|
|
|
132
162
|
|
|
133
163
|
def main(args=None):
|
|
134
|
-
"""Convert
|
|
164
|
+
"""Convert CFF2 OTF font to CFF OTF font"""
|
|
135
165
|
if args is None:
|
|
136
166
|
import sys
|
|
137
167
|
|
|
@@ -140,8 +170,8 @@ def main(args=None):
|
|
|
140
170
|
import argparse
|
|
141
171
|
|
|
142
172
|
parser = argparse.ArgumentParser(
|
|
143
|
-
"fonttools cffLib.
|
|
144
|
-
description="
|
|
173
|
+
"fonttools cffLib.CFF2ToCFF",
|
|
174
|
+
description="Convert a non-variable CFF2 font to CFF.",
|
|
145
175
|
)
|
|
146
176
|
parser.add_argument(
|
|
147
177
|
"input", metavar="INPUT.ttf", help="Input OTF file with CFF table."
|
|
@@ -159,6 +189,16 @@ def main(args=None):
|
|
|
159
189
|
action="store_false",
|
|
160
190
|
help="Don't set the output font's timestamp to the current time.",
|
|
161
191
|
)
|
|
192
|
+
parser.add_argument(
|
|
193
|
+
"--remove-overlaps",
|
|
194
|
+
action="store_true",
|
|
195
|
+
help="Merge overlapping contours and components. Requires skia-pathops",
|
|
196
|
+
)
|
|
197
|
+
parser.add_argument(
|
|
198
|
+
"--ignore-overlap-errors",
|
|
199
|
+
action="store_true",
|
|
200
|
+
help="Don't crash if the remove-overlaps operation fails for some glyphs.",
|
|
201
|
+
)
|
|
162
202
|
loggingGroup = parser.add_mutually_exclusive_group(required=False)
|
|
163
203
|
loggingGroup.add_argument(
|
|
164
204
|
"-v", "--verbose", action="store_true", help="Run more verbosely."
|
|
@@ -190,6 +230,21 @@ def main(args=None):
|
|
|
190
230
|
|
|
191
231
|
convertCFF2ToCFF(font)
|
|
192
232
|
|
|
233
|
+
if options.remove_overlaps:
|
|
234
|
+
from fontTools.ttLib.removeOverlaps import removeOverlaps
|
|
235
|
+
from io import BytesIO
|
|
236
|
+
|
|
237
|
+
log.debug("Removing overlaps")
|
|
238
|
+
|
|
239
|
+
stream = BytesIO()
|
|
240
|
+
font.save(stream)
|
|
241
|
+
stream.seek(0)
|
|
242
|
+
font = TTFont(stream, recalcTimestamp=False, recalcBBoxes=False)
|
|
243
|
+
removeOverlaps(
|
|
244
|
+
font,
|
|
245
|
+
ignoreErrors=options.ignore_overlap_errors,
|
|
246
|
+
)
|
|
247
|
+
|
|
193
248
|
log.info(
|
|
194
249
|
"Saving %s",
|
|
195
250
|
outfile,
|
fontTools/cffLib/__init__.py
CHANGED
|
@@ -1464,10 +1464,11 @@ class CharsetConverter(SimpleConverter):
|
|
|
1464
1464
|
if glyphName in allNames:
|
|
1465
1465
|
# make up a new glyphName that's unique
|
|
1466
1466
|
n = allNames[glyphName]
|
|
1467
|
-
|
|
1467
|
+
names = set(allNames) | set(charset)
|
|
1468
|
+
while (glyphName + "." + str(n)) in names:
|
|
1468
1469
|
n += 1
|
|
1469
1470
|
allNames[glyphName] = n + 1
|
|
1470
|
-
glyphName = glyphName + "
|
|
1471
|
+
glyphName = glyphName + "." + str(n)
|
|
1471
1472
|
allNames[glyphName] = 1
|
|
1472
1473
|
newCharset.append(glyphName)
|
|
1473
1474
|
charset = newCharset
|
|
@@ -1663,25 +1664,26 @@ class EncodingConverter(SimpleConverter):
|
|
|
1663
1664
|
return "StandardEncoding"
|
|
1664
1665
|
elif value == 1:
|
|
1665
1666
|
return "ExpertEncoding"
|
|
1667
|
+
# custom encoding at offset `value`
|
|
1668
|
+
assert value > 1
|
|
1669
|
+
file = parent.file
|
|
1670
|
+
file.seek(value)
|
|
1671
|
+
log.log(DEBUG, "loading Encoding at %s", value)
|
|
1672
|
+
fmt = readCard8(file)
|
|
1673
|
+
haveSupplement = bool(fmt & 0x80)
|
|
1674
|
+
fmt = fmt & 0x7F
|
|
1675
|
+
|
|
1676
|
+
if fmt == 0:
|
|
1677
|
+
encoding = parseEncoding0(parent.charset, file)
|
|
1678
|
+
elif fmt == 1:
|
|
1679
|
+
encoding = parseEncoding1(parent.charset, file)
|
|
1666
1680
|
else:
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
if haveSupplement:
|
|
1674
|
-
raise NotImplementedError("Encoding supplements are not yet supported")
|
|
1675
|
-
fmt = fmt & 0x7F
|
|
1676
|
-
if fmt == 0:
|
|
1677
|
-
encoding = parseEncoding0(
|
|
1678
|
-
parent.charset, file, haveSupplement, parent.strings
|
|
1679
|
-
)
|
|
1680
|
-
elif fmt == 1:
|
|
1681
|
-
encoding = parseEncoding1(
|
|
1682
|
-
parent.charset, file, haveSupplement, parent.strings
|
|
1683
|
-
)
|
|
1684
|
-
return encoding
|
|
1681
|
+
raise ValueError(f"Unknown Encoding format: {fmt}")
|
|
1682
|
+
|
|
1683
|
+
if haveSupplement:
|
|
1684
|
+
parseEncodingSupplement(file, encoding, parent.strings)
|
|
1685
|
+
|
|
1686
|
+
return encoding
|
|
1685
1687
|
|
|
1686
1688
|
def write(self, parent, value):
|
|
1687
1689
|
if value == "StandardEncoding":
|
|
@@ -1719,27 +1721,60 @@ class EncodingConverter(SimpleConverter):
|
|
|
1719
1721
|
return encoding
|
|
1720
1722
|
|
|
1721
1723
|
|
|
1722
|
-
def
|
|
1724
|
+
def readSID(file):
|
|
1725
|
+
"""Read a String ID (SID) — 2-byte unsigned integer."""
|
|
1726
|
+
data = file.read(2)
|
|
1727
|
+
if len(data) != 2:
|
|
1728
|
+
raise EOFError("Unexpected end of file while reading SID")
|
|
1729
|
+
return struct.unpack(">H", data)[0] # big-endian uint16
|
|
1730
|
+
|
|
1731
|
+
|
|
1732
|
+
def parseEncodingSupplement(file, encoding, strings):
|
|
1733
|
+
"""
|
|
1734
|
+
Parse the CFF Encoding supplement data:
|
|
1735
|
+
- nSups: number of supplementary mappings
|
|
1736
|
+
- each mapping: (code, SID) pair
|
|
1737
|
+
and apply them to the `encoding` list in place.
|
|
1738
|
+
"""
|
|
1739
|
+
nSups = readCard8(file)
|
|
1740
|
+
for _ in range(nSups):
|
|
1741
|
+
code = readCard8(file)
|
|
1742
|
+
sid = readSID(file)
|
|
1743
|
+
name = strings[sid]
|
|
1744
|
+
encoding[code] = name
|
|
1745
|
+
|
|
1746
|
+
|
|
1747
|
+
def parseEncoding0(charset, file):
|
|
1748
|
+
"""
|
|
1749
|
+
Format 0: simple list of codes.
|
|
1750
|
+
After reading the base table, optionally parse the supplement.
|
|
1751
|
+
"""
|
|
1723
1752
|
nCodes = readCard8(file)
|
|
1724
1753
|
encoding = [".notdef"] * 256
|
|
1725
1754
|
for glyphID in range(1, nCodes + 1):
|
|
1726
1755
|
code = readCard8(file)
|
|
1727
1756
|
if code != 0:
|
|
1728
1757
|
encoding[code] = charset[glyphID]
|
|
1758
|
+
|
|
1729
1759
|
return encoding
|
|
1730
1760
|
|
|
1731
1761
|
|
|
1732
|
-
def parseEncoding1(charset, file
|
|
1762
|
+
def parseEncoding1(charset, file):
|
|
1763
|
+
"""
|
|
1764
|
+
Format 1: range-based encoding.
|
|
1765
|
+
After reading the base ranges, optionally parse the supplement.
|
|
1766
|
+
"""
|
|
1733
1767
|
nRanges = readCard8(file)
|
|
1734
1768
|
encoding = [".notdef"] * 256
|
|
1735
1769
|
glyphID = 1
|
|
1736
|
-
for
|
|
1770
|
+
for _ in range(nRanges):
|
|
1737
1771
|
code = readCard8(file)
|
|
1738
1772
|
nLeft = readCard8(file)
|
|
1739
|
-
for
|
|
1773
|
+
for _ in range(nLeft + 1):
|
|
1740
1774
|
encoding[code] = charset[glyphID]
|
|
1741
|
-
code
|
|
1742
|
-
|
|
1775
|
+
code += 1
|
|
1776
|
+
glyphID += 1
|
|
1777
|
+
|
|
1743
1778
|
return encoding
|
|
1744
1779
|
|
|
1745
1780
|
|
fontTools/cffLib/specializer.py
CHANGED
|
@@ -580,7 +580,10 @@ def specializeCommands(
|
|
|
580
580
|
for i in range(len(commands) - 1, 0, -1):
|
|
581
581
|
if "rmoveto" == commands[i][0] == commands[i - 1][0]:
|
|
582
582
|
v1, v2 = commands[i - 1][1], commands[i][1]
|
|
583
|
-
commands[i - 1] = (
|
|
583
|
+
commands[i - 1] = (
|
|
584
|
+
"rmoveto",
|
|
585
|
+
[_addArgs(v1[0], v2[0]), _addArgs(v1[1], v2[1])],
|
|
586
|
+
)
|
|
584
587
|
del commands[i]
|
|
585
588
|
|
|
586
589
|
# 2. Specialize rmoveto/rlineto/rrcurveto operators into horizontal/vertical variants.
|
fontTools/cffLib/transforms.py
CHANGED
|
@@ -94,17 +94,22 @@ class _DesubroutinizingT2Decompiler(SimpleT2Decompiler):
|
|
|
94
94
|
cs._patches.append((index, subr._desubroutinized))
|
|
95
95
|
|
|
96
96
|
|
|
97
|
+
def desubroutinizeCharString(cs):
|
|
98
|
+
"""Desubroutinize a charstring in-place."""
|
|
99
|
+
cs.decompile()
|
|
100
|
+
subrs = getattr(cs.private, "Subrs", [])
|
|
101
|
+
decompiler = _DesubroutinizingT2Decompiler(subrs, cs.globalSubrs, cs.private)
|
|
102
|
+
decompiler.execute(cs)
|
|
103
|
+
cs.program = cs._desubroutinized
|
|
104
|
+
del cs._desubroutinized
|
|
105
|
+
|
|
106
|
+
|
|
97
107
|
def desubroutinize(cff):
|
|
98
108
|
for fontName in cff.fontNames:
|
|
99
109
|
font = cff[fontName]
|
|
100
110
|
cs = font.CharStrings
|
|
101
111
|
for c in cs.values():
|
|
102
|
-
c
|
|
103
|
-
subrs = getattr(c.private, "Subrs", [])
|
|
104
|
-
decompiler = _DesubroutinizingT2Decompiler(subrs, c.globalSubrs, c.private)
|
|
105
|
-
decompiler.execute(c)
|
|
106
|
-
c.program = c._desubroutinized
|
|
107
|
-
del c._desubroutinized
|
|
112
|
+
desubroutinizeCharString(c)
|
|
108
113
|
# Delete all the local subrs
|
|
109
114
|
if hasattr(font, "FDArray"):
|
|
110
115
|
for fd in font.FDArray:
|
fontTools/config/__init__.py
CHANGED
|
@@ -73,3 +73,18 @@ Config.register_option(
|
|
|
73
73
|
parse=Option.parse_optional_bool,
|
|
74
74
|
validate=Option.validate_optional_bool,
|
|
75
75
|
)
|
|
76
|
+
|
|
77
|
+
Config.register_option(
|
|
78
|
+
name="fontTools.ttLib:OPTIMIZE_FONT_SPEED",
|
|
79
|
+
help=dedent(
|
|
80
|
+
"""\
|
|
81
|
+
Enable optimizations that prioritize speed over file size. This
|
|
82
|
+
mainly affects how glyf table and gvar / VARC tables are compiled.
|
|
83
|
+
The produced fonts will be larger, but rendering performance will
|
|
84
|
+
be improved with HarfBuzz and other text layout engines.
|
|
85
|
+
"""
|
|
86
|
+
),
|
|
87
|
+
default=False,
|
|
88
|
+
parse=Option.parse_optional_bool,
|
|
89
|
+
validate=Option.validate_optional_bool,
|
|
90
|
+
)
|