fonttools 4.59.0__cp311-cp311-musllinux_1_2_aarch64.whl → 4.59.2__cp311-cp311-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.

Potentially problematic release.


This version of fonttools might be problematic. Click here for more details.

Files changed (38) hide show
  1. fontTools/__init__.py +1 -1
  2. fontTools/cffLib/CFF2ToCFF.py +40 -10
  3. fontTools/cffLib/transforms.py +11 -6
  4. fontTools/cu2qu/cu2qu.c +751 -643
  5. fontTools/cu2qu/cu2qu.cpython-311-aarch64-linux-musl.so +0 -0
  6. fontTools/cu2qu/cu2qu.py +17 -2
  7. fontTools/feaLib/builder.py +15 -4
  8. fontTools/feaLib/lexer.c +21 -6
  9. fontTools/feaLib/lexer.cpython-311-aarch64-linux-musl.so +0 -0
  10. fontTools/feaLib/parser.py +11 -1
  11. fontTools/feaLib/variableScalar.py +6 -1
  12. fontTools/misc/bezierTools.c +24 -9
  13. fontTools/misc/bezierTools.cpython-311-aarch64-linux-musl.so +0 -0
  14. fontTools/misc/psCharStrings.py +17 -2
  15. fontTools/misc/textTools.py +4 -2
  16. fontTools/pens/momentsPen.c +11 -4
  17. fontTools/pens/momentsPen.cpython-311-aarch64-linux-musl.so +0 -0
  18. fontTools/qu2cu/qu2cu.c +23 -8
  19. fontTools/qu2cu/qu2cu.cpython-311-aarch64-linux-musl.so +0 -0
  20. fontTools/subset/__init__.py +1 -0
  21. fontTools/ttLib/tables/_a_v_a_r.py +4 -2
  22. fontTools/ttLib/tables/_g_v_a_r.py +6 -3
  23. fontTools/ttLib/tables/_h_m_t_x.py +7 -3
  24. fontTools/ttLib/tables/_n_a_m_e.py +11 -6
  25. fontTools/varLib/__init__.py +80 -1
  26. fontTools/varLib/featureVars.py +8 -0
  27. fontTools/varLib/instancer/__init__.py +120 -22
  28. fontTools/varLib/iup.c +23 -8
  29. fontTools/varLib/iup.cpython-311-aarch64-linux-musl.so +0 -0
  30. fontTools/varLib/mutator.py +11 -0
  31. {fonttools-4.59.0.dist-info → fonttools-4.59.2.dist-info}/METADATA +38 -10
  32. {fonttools-4.59.0.dist-info → fonttools-4.59.2.dist-info}/RECORD +38 -38
  33. {fonttools-4.59.0.data → fonttools-4.59.2.data}/data/share/man/man1/ttx.1 +0 -0
  34. {fonttools-4.59.0.dist-info → fonttools-4.59.2.dist-info}/WHEEL +0 -0
  35. {fonttools-4.59.0.dist-info → fonttools-4.59.2.dist-info}/entry_points.txt +0 -0
  36. {fonttools-4.59.0.dist-info → fonttools-4.59.2.dist-info}/licenses/LICENSE +0 -0
  37. {fonttools-4.59.0.dist-info → fonttools-4.59.2.dist-info}/licenses/LICENSE.external +0 -0
  38. {fonttools-4.59.0.dist-info → fonttools-4.59.2.dist-info}/top_level.txt +0 -0
fontTools/__init__.py CHANGED
@@ -3,6 +3,6 @@ from fontTools.misc.loggingTools import configLogger
3
3
 
4
4
  log = logging.getLogger(__name__)
5
5
 
6
- version = __version__ = "4.59.0"
6
+ version = __version__ = "4.59.2"
7
7
 
8
8
  __all__ = ["version", "log", "configLogger"]
@@ -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 CFF table. (i.e. that the object has been
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
- # I'm not sure why the following is *not* necessary. And it breaks
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 CFF OTF font to CFF2 OTF font"""
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.CFFToCFF2",
144
- description="Upgrade a CFF font to CFF2.",
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."
@@ -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.decompile()
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: