fonttools 4.59.0__cp311-cp311-win_amd64.whl → 4.59.1__cp311-cp311-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.

Files changed (30) 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 +30 -16
  5. fontTools/cu2qu/cu2qu.cp311-win_amd64.pyd +0 -0
  6. fontTools/feaLib/builder.py +6 -1
  7. fontTools/feaLib/lexer.c +30 -16
  8. fontTools/feaLib/lexer.cp311-win_amd64.pyd +0 -0
  9. fontTools/misc/bezierTools.c +33 -19
  10. fontTools/misc/bezierTools.cp311-win_amd64.pyd +0 -0
  11. fontTools/misc/psCharStrings.py +17 -2
  12. fontTools/pens/momentsPen.c +20 -14
  13. fontTools/pens/momentsPen.cp311-win_amd64.pyd +0 -0
  14. fontTools/qu2cu/qu2cu.c +32 -18
  15. fontTools/qu2cu/qu2cu.cp311-win_amd64.pyd +0 -0
  16. fontTools/ttLib/tables/_g_v_a_r.py +6 -3
  17. fontTools/ttLib/tables/_h_m_t_x.py +7 -3
  18. fontTools/varLib/featureVars.py +8 -0
  19. fontTools/varLib/instancer/__init__.py +65 -5
  20. fontTools/varLib/iup.c +32 -18
  21. fontTools/varLib/iup.cp311-win_amd64.pyd +0 -0
  22. fontTools/varLib/mutator.py +11 -0
  23. {fonttools-4.59.0.dist-info → fonttools-4.59.1.dist-info}/METADATA +24 -10
  24. {fonttools-4.59.0.dist-info → fonttools-4.59.1.dist-info}/RECORD +30 -30
  25. {fonttools-4.59.0.data → fonttools-4.59.1.data}/data/share/man/man1/ttx.1 +0 -0
  26. {fonttools-4.59.0.dist-info → fonttools-4.59.1.dist-info}/WHEEL +0 -0
  27. {fonttools-4.59.0.dist-info → fonttools-4.59.1.dist-info}/entry_points.txt +0 -0
  28. {fonttools-4.59.0.dist-info → fonttools-4.59.1.dist-info}/licenses/LICENSE +0 -0
  29. {fonttools-4.59.0.dist-info → fonttools-4.59.1.dist-info}/licenses/LICENSE.external +0 -0
  30. {fonttools-4.59.0.dist-info → fonttools-4.59.1.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- /* Generated by Cython 3.1.2 */
1
+ /* Generated by Cython 3.1.3 */
2
2
 
3
3
  /* BEGIN: Cython Metadata
4
4
  {
@@ -26,8 +26,8 @@ END: Cython Metadata */
26
26
  #elif PY_VERSION_HEX < 0x03080000
27
27
  #error Cython requires Python 3.8+.
28
28
  #else
29
- #define __PYX_ABI_VERSION "3_1_2"
30
- #define CYTHON_HEX_VERSION 0x030102F0
29
+ #define __PYX_ABI_VERSION "3_1_3"
30
+ #define CYTHON_HEX_VERSION 0x030103F0
31
31
  #define CYTHON_FUTURE_DIVISION 1
32
32
  /* CModulePreamble */
33
33
  #include <stddef.h>
@@ -390,6 +390,9 @@ END: Cython Metadata */
390
390
  enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) };
391
391
  #endif
392
392
  #endif
393
+ #ifndef CYTHON_LOCK_AND_GIL_DEADLOCK_AVOIDANCE_TIME
394
+ #define CYTHON_LOCK_AND_GIL_DEADLOCK_AVOIDANCE_TIME 100
395
+ #endif
393
396
  #ifndef __has_attribute
394
397
  #define __has_attribute(x) 0
395
398
  #endif
@@ -8294,16 +8297,15 @@ static int __Pyx_InitConstants(__pyx_mstatetype *__pyx_mstate) {
8294
8297
  return -1;
8295
8298
  }
8296
8299
  /* #### Code section: init_codeobjects ### */
8297
- \
8298
- typedef struct {
8299
- unsigned int argcount : 3;
8300
- unsigned int num_posonly_args : 1;
8301
- unsigned int num_kwonly_args : 1;
8302
- unsigned int nlocals : 8;
8303
- unsigned int flags : 10;
8304
- unsigned int first_line : 9;
8305
- unsigned int line_table_length : 17;
8306
- } __Pyx_PyCode_New_function_description;
8300
+ typedef struct {
8301
+ unsigned int argcount : 3;
8302
+ unsigned int num_posonly_args : 1;
8303
+ unsigned int num_kwonly_args : 1;
8304
+ unsigned int nlocals : 8;
8305
+ unsigned int flags : 10;
8306
+ unsigned int first_line : 9;
8307
+ unsigned int line_table_length : 17;
8308
+ } __Pyx_PyCode_New_function_description;
8307
8309
  /* NewCodeObj.proto */
8308
8310
  static PyObject* __Pyx_PyCode_New(
8309
8311
  const __Pyx_PyCode_New_function_description descr,
@@ -10172,6 +10174,7 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
10172
10174
  changed = 1;
10173
10175
  }
10174
10176
  #endif // CYTHON_METH_FASTCALL
10177
+ #if !CYTHON_COMPILING_IN_PYPY
10175
10178
  else if (strcmp(memb->name, "__module__") == 0) {
10176
10179
  PyObject *descr;
10177
10180
  assert(memb->type == T_OBJECT);
@@ -10186,11 +10189,13 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
10186
10189
  }
10187
10190
  changed = 1;
10188
10191
  }
10192
+ #endif // !CYTHON_COMPILING_IN_PYPY
10189
10193
  }
10190
10194
  memb++;
10191
10195
  }
10192
10196
  }
10193
10197
  #endif // !CYTHON_COMPILING_IN_LIMITED_API
10198
+ #if !CYTHON_COMPILING_IN_PYPY
10194
10199
  slot = spec->slots;
10195
10200
  while (slot && slot->slot && slot->slot != Py_tp_getset)
10196
10201
  slot++;
@@ -10222,6 +10227,7 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
10222
10227
  ++getset;
10223
10228
  }
10224
10229
  }
10230
+ #endif // !CYTHON_COMPILING_IN_PYPY
10225
10231
  if (changed)
10226
10232
  PyType_Modified(type);
10227
10233
  #endif // PY_VERSION_HEX > 0x030900B1
@@ -10354,7 +10360,7 @@ bad:
10354
10360
  }
10355
10361
 
10356
10362
  /* CommonTypesMetaclass */
10357
- PyObject* __pyx_CommonTypesMetaclass_get_module(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED void* context) {
10363
+ static PyObject* __pyx_CommonTypesMetaclass_get_module(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED void* context) {
10358
10364
  return PyUnicode_FromString(__PYX_ABI_MODULE_NAME);
10359
10365
  }
10360
10366
  static PyGetSetDef __pyx_CommonTypesMetaclass_getset[] = {
fontTools/qu2cu/qu2cu.c CHANGED
@@ -1,4 +1,4 @@
1
- /* Generated by Cython 3.1.2 */
1
+ /* Generated by Cython 3.1.3 */
2
2
 
3
3
  /* BEGIN: Cython Metadata
4
4
  {
@@ -32,8 +32,8 @@ END: Cython Metadata */
32
32
  #elif PY_VERSION_HEX < 0x03080000
33
33
  #error Cython requires Python 3.8+.
34
34
  #else
35
- #define __PYX_ABI_VERSION "3_1_2"
36
- #define CYTHON_HEX_VERSION 0x030102F0
35
+ #define __PYX_ABI_VERSION "3_1_3"
36
+ #define CYTHON_HEX_VERSION 0x030103F0
37
37
  #define CYTHON_FUTURE_DIVISION 1
38
38
  /* CModulePreamble */
39
39
  #include <stddef.h>
@@ -396,6 +396,9 @@ END: Cython Metadata */
396
396
  enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) };
397
397
  #endif
398
398
  #endif
399
+ #ifndef CYTHON_LOCK_AND_GIL_DEADLOCK_AVOIDANCE_TIME
400
+ #define CYTHON_LOCK_AND_GIL_DEADLOCK_AVOIDANCE_TIME 100
401
+ #endif
399
402
  #ifndef __has_attribute
400
403
  #define __has_attribute(x) 0
401
404
  #endif
@@ -1963,7 +1966,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
1963
1966
  static PyObject *__Pyx_PyLong_AbsNeg(PyObject *num);
1964
1967
  #define __Pyx_PyNumber_Absolute(x)\
1965
1968
  ((likely(PyLong_CheckExact(x))) ?\
1966
- (likely(__Pyx_PyLong_IsNonNeg(x)) ? (Py_INCREF(x), (x)) : __Pyx_PyLong_AbsNeg(x)) :\
1969
+ (likely(__Pyx_PyLong_IsNonNeg(x)) ? __Pyx_NewRef(x) : __Pyx_PyLong_AbsNeg(x)) :\
1967
1970
  PyNumber_Absolute(x))
1968
1971
  #else
1969
1972
  #define __Pyx_PyNumber_Absolute(x) PyNumber_Absolute(x)
@@ -9028,16 +9031,15 @@ static int __Pyx_InitConstants(__pyx_mstatetype *__pyx_mstate) {
9028
9031
  return -1;
9029
9032
  }
9030
9033
  /* #### Code section: init_codeobjects ### */
9031
- \
9032
- typedef struct {
9033
- unsigned int argcount : 3;
9034
- unsigned int num_posonly_args : 1;
9035
- unsigned int num_kwonly_args : 1;
9036
- unsigned int nlocals : 6;
9037
- unsigned int flags : 10;
9038
- unsigned int first_line : 9;
9039
- unsigned int line_table_length : 15;
9040
- } __Pyx_PyCode_New_function_description;
9034
+ typedef struct {
9035
+ unsigned int argcount : 3;
9036
+ unsigned int num_posonly_args : 1;
9037
+ unsigned int num_kwonly_args : 1;
9038
+ unsigned int nlocals : 6;
9039
+ unsigned int flags : 10;
9040
+ unsigned int first_line : 9;
9041
+ unsigned int line_table_length : 15;
9042
+ } __Pyx_PyCode_New_function_description;
9041
9043
  /* NewCodeObj.proto */
9042
9044
  static PyObject* __Pyx_PyCode_New(
9043
9045
  const __Pyx_PyCode_New_function_description descr,
@@ -10557,7 +10559,7 @@ static PyObject *__Pyx_PyLong_AbsNeg(PyObject *n) {
10557
10559
  PyObject *copy = _PyLong_Copy((PyLongObject*)n);
10558
10560
  if (likely(copy)) {
10559
10561
  #if PY_VERSION_HEX >= 0x030C00A7
10560
- ((PyLongObject*)copy)->long_value.lv_tag = ((PyLongObject*)copy)->long_value.lv_tag & ~_PyLong_SIGN_MASK;
10562
+ ((PyLongObject*)copy)->long_value.lv_tag ^= ((PyLongObject*)copy)->long_value.lv_tag & _PyLong_SIGN_MASK;
10561
10563
  #else
10562
10564
  __Pyx_SET_SIZE(copy, -Py_SIZE(copy));
10563
10565
  #endif
@@ -11193,6 +11195,13 @@ try_unpack:
11193
11195
 
11194
11196
  /* PyObjectCallMethod0 */
11195
11197
  static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name) {
11198
+ #if CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000))
11199
+ PyObject *args[1] = {obj};
11200
+ (void) __Pyx_PyObject_GetMethod;
11201
+ (void) __Pyx_PyObject_CallOneArg;
11202
+ (void) __Pyx_PyObject_CallNoArg;
11203
+ return PyObject_VectorcallMethod(method_name, args, 1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
11204
+ #else
11196
11205
  PyObject *method = NULL, *result = NULL;
11197
11206
  int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method);
11198
11207
  if (likely(is_method)) {
@@ -11205,6 +11214,7 @@ static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name
11205
11214
  Py_DECREF(method);
11206
11215
  bad:
11207
11216
  return result;
11217
+ #endif
11208
11218
  }
11209
11219
 
11210
11220
  /* CallUnboundCMethod0 */
@@ -11742,6 +11752,7 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
11742
11752
  changed = 1;
11743
11753
  }
11744
11754
  #endif // CYTHON_METH_FASTCALL
11755
+ #if !CYTHON_COMPILING_IN_PYPY
11745
11756
  else if (strcmp(memb->name, "__module__") == 0) {
11746
11757
  PyObject *descr;
11747
11758
  assert(memb->type == T_OBJECT);
@@ -11756,11 +11767,13 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
11756
11767
  }
11757
11768
  changed = 1;
11758
11769
  }
11770
+ #endif // !CYTHON_COMPILING_IN_PYPY
11759
11771
  }
11760
11772
  memb++;
11761
11773
  }
11762
11774
  }
11763
11775
  #endif // !CYTHON_COMPILING_IN_LIMITED_API
11776
+ #if !CYTHON_COMPILING_IN_PYPY
11764
11777
  slot = spec->slots;
11765
11778
  while (slot && slot->slot && slot->slot != Py_tp_getset)
11766
11779
  slot++;
@@ -11792,6 +11805,7 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
11792
11805
  ++getset;
11793
11806
  }
11794
11807
  }
11808
+ #endif // !CYTHON_COMPILING_IN_PYPY
11795
11809
  if (changed)
11796
11810
  PyType_Modified(type);
11797
11811
  #endif // PY_VERSION_HEX > 0x030900B1
@@ -12227,7 +12241,7 @@ bad:
12227
12241
  }
12228
12242
 
12229
12243
  /* CommonTypesMetaclass */
12230
- PyObject* __pyx_CommonTypesMetaclass_get_module(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED void* context) {
12244
+ static PyObject* __pyx_CommonTypesMetaclass_get_module(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED void* context) {
12231
12245
  return PyUnicode_FromString(__PYX_ABI_MODULE_NAME);
12232
12246
  }
12233
12247
  static PyGetSetDef __pyx_CommonTypesMetaclass_getset[] = {
@@ -14847,7 +14861,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyOb
14847
14861
  }
14848
14862
 
14849
14863
  /* PyObjectCallMethod1 */
14850
- #if !(CYTHON_VECTORCALL && __PYX_LIMITED_VERSION_HEX >= 0x030C0000)
14864
+ #if !(CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000)))
14851
14865
  static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg) {
14852
14866
  PyObject *result = __Pyx_PyObject_CallOneArg(method, arg);
14853
14867
  Py_DECREF(method);
@@ -14855,7 +14869,7 @@ static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg) {
14855
14869
  }
14856
14870
  #endif
14857
14871
  static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg) {
14858
- #if CYTHON_VECTORCALL && __PYX_LIMITED_VERSION_HEX >= 0x030C0000
14872
+ #if CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000))
14859
14873
  PyObject *args[2] = {obj, arg};
14860
14874
  (void) __Pyx_PyObject_GetMethod;
14861
14875
  (void) __Pyx_PyObject_CallOneArg;
Binary file
@@ -64,7 +64,6 @@ class table__g_v_a_r(DefaultTable.DefaultTable):
64
64
  self.variations = {}
65
65
 
66
66
  def compile(self, ttFont):
67
-
68
67
  axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
69
68
  sharedTuples = tv.compileSharedTuples(
70
69
  axisTags, itertools.chain(*self.variations.values())
@@ -141,8 +140,12 @@ class table__g_v_a_r(DefaultTable.DefaultTable):
141
140
  self,
142
141
  )
143
142
 
144
- assert len(glyphs) == self.glyphCount
145
- assert len(axisTags) == self.axisCount
143
+ assert len(glyphs) == self.glyphCount, (len(glyphs), self.glyphCount)
144
+ assert len(axisTags) == self.axisCount, (
145
+ len(axisTags),
146
+ self.axisCount,
147
+ axisTags,
148
+ )
146
149
  sharedCoords = tv.decompileSharedTuples(
147
150
  axisTags, self.sharedTupleCount, data, self.offsetToSharedTuples
148
151
  )
@@ -40,15 +40,19 @@ class table__h_m_t_x(DefaultTable.DefaultTable):
40
40
  % (self.headerTag, self.numberOfMetricsName)
41
41
  )
42
42
  numberOfMetrics = numGlyphs
43
- if len(data) < 4 * numberOfMetrics:
44
- raise ttLib.TTLibError("not enough '%s' table data" % self.tableTag)
43
+ numberOfSideBearings = numGlyphs - numberOfMetrics
44
+ tableSize = 4 * numberOfMetrics + 2 * numberOfSideBearings
45
+ if len(data) < tableSize:
46
+ raise ttLib.TTLibError(
47
+ f"not enough '{self.tableTag}' table data: "
48
+ f"expected {tableSize} bytes, got {len(data)}"
49
+ )
45
50
  # Note: advanceWidth is unsigned, but some font editors might
46
51
  # read/write as signed. We can't be sure whether it was a mistake
47
52
  # or not, so we read as unsigned but also issue a warning...
48
53
  metricsFmt = ">" + self.longMetricFormat * numberOfMetrics
49
54
  metrics = struct.unpack(metricsFmt, data[: 4 * numberOfMetrics])
50
55
  data = data[4 * numberOfMetrics :]
51
- numberOfSideBearings = numGlyphs - numberOfMetrics
52
56
  sideBearings = array.array("h", data[: 2 * numberOfSideBearings])
53
57
  data = data[2 * numberOfSideBearings :]
54
58
 
@@ -95,6 +95,14 @@ def addFeatureVariations(font, conditionalSubstitutions, featureTag="rvrn"):
95
95
 
96
96
  addFeatureVariationsRaw(font, font["GSUB"].table, conditionsAndLookups, featureTags)
97
97
 
98
+ # Update OS/2.usMaxContext in case the font didn't have features before, but
99
+ # does now, if the OS/2 table exists. The table may be required, but
100
+ # fontTools needs to be able to deal with non-standard fonts. Since feature
101
+ # variations are always 1:1 mappings, we can set the value to at least 1
102
+ # instead of recomputing it with `otlLib.maxContextCalc.maxCtxFont()`.
103
+ if (os2 := font.get("OS/2")) is not None:
104
+ os2.usMaxContext = max(1, os2.usMaxContext)
105
+
98
106
 
99
107
  def _existingVariableFeatures(table):
100
108
  existingFeatureVarsTags = set()
@@ -120,6 +120,7 @@ from fontTools.cffLib.specializer import (
120
120
  specializeCommands,
121
121
  generalizeCommands,
122
122
  )
123
+ from fontTools.cffLib.CFF2ToCFF import convertCFF2ToCFF
123
124
  from fontTools.varLib import builder
124
125
  from fontTools.varLib.mvar import MVAR_ENTRIES
125
126
  from fontTools.varLib.merger import MutatorMerger
@@ -136,6 +137,7 @@ from enum import IntEnum
136
137
  import logging
137
138
  import os
138
139
  import re
140
+ import io
139
141
  from typing import Dict, Iterable, Mapping, Optional, Sequence, Tuple, Union
140
142
  import warnings
141
143
 
@@ -643,7 +645,11 @@ def instantiateCFF2(
643
645
  # the Private dicts.
644
646
  #
645
647
  # Then prune unused things and possibly drop the VarStore if it's empty.
646
- # In which case, downgrade to CFF table if requested.
648
+ #
649
+ # If the downgrade parameter is True, no actual downgrading is done, but
650
+ # the function returns True if the VarStore was empty after instantiation,
651
+ # and hence a downgrade to CFF is possible. In all other cases it returns
652
+ # False.
647
653
 
648
654
  log.info("Instantiating CFF2 table")
649
655
 
@@ -882,9 +888,9 @@ def instantiateCFF2(
882
888
  del private.vstore
883
889
 
884
890
  if downgrade:
885
- from fontTools.cffLib.CFF2ToCFF import convertCFF2ToCFF
891
+ return True
886
892
 
887
- convertCFF2ToCFF(varfont)
893
+ return False
888
894
 
889
895
 
890
896
  def _instantiateGvarGlyph(
@@ -1377,6 +1383,52 @@ def _isValidAvarSegmentMap(axisTag, segmentMap):
1377
1383
  return True
1378
1384
 
1379
1385
 
1386
+ def downgradeCFF2ToCFF(varfont):
1387
+
1388
+ # Save these properties
1389
+ recalcTimestamp = varfont.recalcTimestamp
1390
+ recalcBBoxes = varfont.recalcBBoxes
1391
+
1392
+ # Disable them
1393
+ varfont.recalcTimestamp = False
1394
+ varfont.recalcBBoxes = False
1395
+
1396
+ # Save to memory, reload, downgrade and save again, reload.
1397
+ # We do this dance because the convertCFF2ToCFF changes glyph
1398
+ # names, so following save would fail if any other table was
1399
+ # loaded and referencing glyph names.
1400
+ #
1401
+ # The second save+load is unfortunate but also necessary.
1402
+
1403
+ stream = io.BytesIO()
1404
+ log.info("Saving CFF2 font to memory for downgrade")
1405
+ varfont.save(stream)
1406
+ stream.seek(0)
1407
+ varfont = TTFont(stream, recalcTimestamp=False, recalcBBoxes=False)
1408
+
1409
+ convertCFF2ToCFF(varfont)
1410
+
1411
+ stream = io.BytesIO()
1412
+ log.info("Saving downgraded CFF font to memory")
1413
+ varfont.save(stream)
1414
+ stream.seek(0)
1415
+ varfont = TTFont(stream, recalcTimestamp=False, recalcBBoxes=False)
1416
+
1417
+ # Uncomment, to see test all tables can be loaded. This fails without
1418
+ # the extra save+load above.
1419
+ """
1420
+ for tag in varfont.keys():
1421
+ print("Loading", tag)
1422
+ varfont[tag]
1423
+ """
1424
+
1425
+ # Restore them
1426
+ varfont.recalcTimestamp = recalcTimestamp
1427
+ varfont.recalcBBoxes = recalcBBoxes
1428
+
1429
+ return varfont
1430
+
1431
+
1380
1432
  def instantiateAvar(varfont, axisLimits):
1381
1433
  # 'axisLimits' dict must contain user-space (non-normalized) coordinates.
1382
1434
 
@@ -1665,7 +1717,9 @@ def instantiateVariableFont(
1665
1717
  instantiateVARC(varfont, normalizedLimits)
1666
1718
 
1667
1719
  if "CFF2" in varfont:
1668
- instantiateCFF2(varfont, normalizedLimits, downgrade=downgradeCFF2)
1720
+ downgradeCFF2 = instantiateCFF2(
1721
+ varfont, normalizedLimits, downgrade=downgradeCFF2
1722
+ )
1669
1723
 
1670
1724
  if "gvar" in varfont:
1671
1725
  instantiateGvar(varfont, normalizedLimits, optimize=optimize)
@@ -1720,6 +1774,12 @@ def instantiateVariableFont(
1720
1774
  # name table has been updated.
1721
1775
  setRibbiBits(varfont)
1722
1776
 
1777
+ if downgradeCFF2:
1778
+ origVarfont = varfont
1779
+ varfont = downgradeCFF2ToCFF(varfont)
1780
+ if inplace:
1781
+ origVarfont.__dict__ = varfont.__dict__.copy()
1782
+
1723
1783
  return varfont
1724
1784
 
1725
1785
 
@@ -1929,7 +1989,7 @@ def main(args=None):
1929
1989
  if limit is None or limit[0] == limit[2]
1930
1990
  }.issuperset(axis.axisTag for axis in varfont["fvar"].axes)
1931
1991
 
1932
- instantiateVariableFont(
1992
+ varfont = instantiateVariableFont(
1933
1993
  varfont,
1934
1994
  axisLimits,
1935
1995
  inplace=True,
fontTools/varLib/iup.c CHANGED
@@ -1,4 +1,4 @@
1
- /* Generated by Cython 3.1.2 */
1
+ /* Generated by Cython 3.1.3 */
2
2
 
3
3
  /* BEGIN: Cython Metadata
4
4
  {
@@ -26,8 +26,8 @@ END: Cython Metadata */
26
26
  #elif PY_VERSION_HEX < 0x03080000
27
27
  #error Cython requires Python 3.8+.
28
28
  #else
29
- #define __PYX_ABI_VERSION "3_1_2"
30
- #define CYTHON_HEX_VERSION 0x030102F0
29
+ #define __PYX_ABI_VERSION "3_1_3"
30
+ #define CYTHON_HEX_VERSION 0x030103F0
31
31
  #define CYTHON_FUTURE_DIVISION 1
32
32
  /* CModulePreamble */
33
33
  #include <stddef.h>
@@ -390,6 +390,9 @@ END: Cython Metadata */
390
390
  enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) };
391
391
  #endif
392
392
  #endif
393
+ #ifndef CYTHON_LOCK_AND_GIL_DEADLOCK_AVOIDANCE_TIME
394
+ #define CYTHON_LOCK_AND_GIL_DEADLOCK_AVOIDANCE_TIME 100
395
+ #endif
393
396
  #ifndef __has_attribute
394
397
  #define __has_attribute(x) 0
395
398
  #endif
@@ -2141,7 +2144,7 @@ static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected);
2141
2144
  static PyObject *__Pyx_PyLong_AbsNeg(PyObject *num);
2142
2145
  #define __Pyx_PyNumber_Absolute(x)\
2143
2146
  ((likely(PyLong_CheckExact(x))) ?\
2144
- (likely(__Pyx_PyLong_IsNonNeg(x)) ? (Py_INCREF(x), (x)) : __Pyx_PyLong_AbsNeg(x)) :\
2147
+ (likely(__Pyx_PyLong_IsNonNeg(x)) ? __Pyx_NewRef(x) : __Pyx_PyLong_AbsNeg(x)) :\
2145
2148
  PyNumber_Absolute(x))
2146
2149
  #else
2147
2150
  #define __Pyx_PyNumber_Absolute(x) PyNumber_Absolute(x)
@@ -12093,16 +12096,15 @@ static int __Pyx_InitConstants(__pyx_mstatetype *__pyx_mstate) {
12093
12096
  return -1;
12094
12097
  }
12095
12098
  /* #### Code section: init_codeobjects ### */
12096
- \
12097
- typedef struct {
12098
- unsigned int argcount : 3;
12099
- unsigned int num_posonly_args : 1;
12100
- unsigned int num_kwonly_args : 1;
12101
- unsigned int nlocals : 5;
12102
- unsigned int flags : 10;
12103
- unsigned int first_line : 9;
12104
- unsigned int line_table_length : 14;
12105
- } __Pyx_PyCode_New_function_description;
12099
+ typedef struct {
12100
+ unsigned int argcount : 3;
12101
+ unsigned int num_posonly_args : 1;
12102
+ unsigned int num_kwonly_args : 1;
12103
+ unsigned int nlocals : 5;
12104
+ unsigned int flags : 10;
12105
+ unsigned int first_line : 9;
12106
+ unsigned int line_table_length : 14;
12107
+ } __Pyx_PyCode_New_function_description;
12106
12108
  /* NewCodeObj.proto */
12107
12109
  static PyObject* __Pyx_PyCode_New(
12108
12110
  const __Pyx_PyCode_New_function_description descr,
@@ -14329,7 +14331,7 @@ static PyObject *__Pyx_PyLong_AbsNeg(PyObject *n) {
14329
14331
  PyObject *copy = _PyLong_Copy((PyLongObject*)n);
14330
14332
  if (likely(copy)) {
14331
14333
  #if PY_VERSION_HEX >= 0x030C00A7
14332
- ((PyLongObject*)copy)->long_value.lv_tag = ((PyLongObject*)copy)->long_value.lv_tag & ~_PyLong_SIGN_MASK;
14334
+ ((PyLongObject*)copy)->long_value.lv_tag ^= ((PyLongObject*)copy)->long_value.lv_tag & _PyLong_SIGN_MASK;
14333
14335
  #else
14334
14336
  __Pyx_SET_SIZE(copy, -Py_SIZE(copy));
14335
14337
  #endif
@@ -14942,6 +14944,7 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
14942
14944
  changed = 1;
14943
14945
  }
14944
14946
  #endif // CYTHON_METH_FASTCALL
14947
+ #if !CYTHON_COMPILING_IN_PYPY
14945
14948
  else if (strcmp(memb->name, "__module__") == 0) {
14946
14949
  PyObject *descr;
14947
14950
  assert(memb->type == T_OBJECT);
@@ -14956,11 +14959,13 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
14956
14959
  }
14957
14960
  changed = 1;
14958
14961
  }
14962
+ #endif // !CYTHON_COMPILING_IN_PYPY
14959
14963
  }
14960
14964
  memb++;
14961
14965
  }
14962
14966
  }
14963
14967
  #endif // !CYTHON_COMPILING_IN_LIMITED_API
14968
+ #if !CYTHON_COMPILING_IN_PYPY
14964
14969
  slot = spec->slots;
14965
14970
  while (slot && slot->slot && slot->slot != Py_tp_getset)
14966
14971
  slot++;
@@ -14992,6 +14997,7 @@ static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject
14992
14997
  ++getset;
14993
14998
  }
14994
14999
  }
15000
+ #endif // !CYTHON_COMPILING_IN_PYPY
14995
15001
  if (changed)
14996
15002
  PyType_Modified(type);
14997
15003
  #endif // PY_VERSION_HEX > 0x030900B1
@@ -15090,6 +15096,13 @@ try_unpack:
15090
15096
 
15091
15097
  /* PyObjectCallMethod0 */
15092
15098
  static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name) {
15099
+ #if CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000))
15100
+ PyObject *args[1] = {obj};
15101
+ (void) __Pyx_PyObject_GetMethod;
15102
+ (void) __Pyx_PyObject_CallOneArg;
15103
+ (void) __Pyx_PyObject_CallNoArg;
15104
+ return PyObject_VectorcallMethod(method_name, args, 1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
15105
+ #else
15093
15106
  PyObject *method = NULL, *result = NULL;
15094
15107
  int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method);
15095
15108
  if (likely(is_method)) {
@@ -15102,6 +15115,7 @@ static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name
15102
15115
  Py_DECREF(method);
15103
15116
  bad:
15104
15117
  return result;
15118
+ #endif
15105
15119
  }
15106
15120
 
15107
15121
  /* ValidateBasesTuple */
@@ -15489,7 +15503,7 @@ bad:
15489
15503
  }
15490
15504
 
15491
15505
  /* CommonTypesMetaclass */
15492
- PyObject* __pyx_CommonTypesMetaclass_get_module(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED void* context) {
15506
+ static PyObject* __pyx_CommonTypesMetaclass_get_module(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED void* context) {
15493
15507
  return PyUnicode_FromString(__PYX_ABI_MODULE_NAME);
15494
15508
  }
15495
15509
  static PyGetSetDef __pyx_CommonTypesMetaclass_getset[] = {
@@ -17939,7 +17953,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyOb
17939
17953
  }
17940
17954
 
17941
17955
  /* PyObjectCallMethod1 */
17942
- #if !(CYTHON_VECTORCALL && __PYX_LIMITED_VERSION_HEX >= 0x030C0000)
17956
+ #if !(CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000)))
17943
17957
  static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg) {
17944
17958
  PyObject *result = __Pyx_PyObject_CallOneArg(method, arg);
17945
17959
  Py_DECREF(method);
@@ -17947,7 +17961,7 @@ static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg) {
17947
17961
  }
17948
17962
  #endif
17949
17963
  static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg) {
17950
- #if CYTHON_VECTORCALL && __PYX_LIMITED_VERSION_HEX >= 0x030C0000
17964
+ #if CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000))
17951
17965
  PyObject *args[2] = {obj, arg};
17952
17966
  (void) __Pyx_PyObject_GetMethod;
17953
17967
  (void) __Pyx_PyObject_CallOneArg;
Binary file
@@ -4,9 +4,16 @@ Instantiate a variation font. Run, eg:
4
4
  .. code-block:: sh
5
5
 
6
6
  $ fonttools varLib.mutator ./NotoSansArabic-VF.ttf wght=140 wdth=85
7
+
8
+ .. warning::
9
+ ``fontTools.varLib.mutator`` is deprecated in favor of :mod:`fontTools.varLib.instancer`
10
+ which provides equivalent full instancing and also supports partial instancing.
11
+ Please migrate CLI usage to ``fonttools varLib.instancer`` and API usage to
12
+ :func:`fontTools.varLib.instancer.instantiateVariableFont`.
7
13
  """
8
14
 
9
15
  from fontTools.misc.fixedTools import floatToFixedToFloat, floatToFixed
16
+ from fontTools.misc.loggingTools import deprecateFunction
10
17
  from fontTools.misc.roundTools import otRound
11
18
  from fontTools.pens.boundsPen import BoundsPen
12
19
  from fontTools.ttLib import TTFont, newTable
@@ -159,6 +166,10 @@ def interpolate_cff2_metrics(varfont, topDict, glyphOrder, loc):
159
166
  hmtx[gname] = tuple(entry)
160
167
 
161
168
 
169
+ @deprecateFunction(
170
+ "use fontTools.varLib.instancer.instantiateVariableFont instead "
171
+ "for either full or partial instancing",
172
+ )
162
173
  def instantiateVariableFont(varfont, location, inplace=False, overlap=True):
163
174
  """Generate a static instance from a variable TTFont and a dictionary
164
175
  defining the desired location along the variable font's axes.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fonttools
3
- Version: 4.59.0
3
+ Version: 4.59.1
4
4
  Summary: Tools to manipulate font files
5
5
  Home-page: http://github.com/fonttools/fonttools
6
6
  Author: Just van Rossum
@@ -168,15 +168,6 @@ are required to unlock the extra features named "ufo", etc.
168
168
 
169
169
  *Extra:* ``lxml``
170
170
 
171
- - ``Lib/fontTools/ufoLib``
172
-
173
- Package for reading and writing UFO source files; it requires:
174
-
175
- * `fs <https://pypi.org/pypi/fs>`__: (aka ``pyfilesystem2``) filesystem
176
- abstraction layer.
177
-
178
- *Extra:* ``ufo``
179
-
180
171
  - ``Lib/fontTools/ttLib/woff2.py``
181
172
 
182
173
  Module to compress/decompress WOFF 2.0 web fonts; it requires:
@@ -269,6 +260,17 @@ are required to unlock the extra features named "ufo", etc.
269
260
 
270
261
  *Extra:* ``pathops``
271
262
 
263
+ - ``Lib/fontTools/ufoLib``
264
+
265
+ Package for reading and writing UFO source files; if available, it will use:
266
+
267
+ * `fs <https://pypi.org/pypi/fs>`__: (aka ``pyfilesystem2``) filesystem abstraction layer
268
+
269
+ for reading and writing UFOs to the local filesystem or zip files (.ufoz), instead of
270
+ the built-in ``fontTools.misc.filesystem`` package.
271
+ The reader and writer classes can in theory also accept any object compatible the
272
+ ``fs.base.FS`` interface, although not all have been tested.
273
+
272
274
  - ``Lib/fontTools/pens/cocoaPen.py`` and ``Lib/fontTools/pens/quartzPen.py``
273
275
 
274
276
  Pens for drawing glyphs with Cocoa ``NSBezierPath`` or ``CGPath`` require:
@@ -386,6 +388,18 @@ Have fun!
386
388
  Changelog
387
389
  ~~~~~~~~~
388
390
 
391
+ 4.59.1 (released 2025-08-14)
392
+ ----------------------------
393
+
394
+ - [featureVars] Update OS/2.usMaxContext if possible after addFeatureVariationsRaw (#3894).
395
+ - [vhmtx] raise TTLibError('not enough data...') when hmtx/vmtx are truncated (#3843, #3901).
396
+ - [feaLib] Combine duplicate features that have the same set of lookups regardless of the order in which those lookups are added to the feature (#3895).
397
+ - [varLib] Deprecate ``varLib.mutator`` in favor of ``varLib.instancer``. The latter
398
+ provides equivalent full (static font) instancing in addition to partial VF instancing.
399
+ CLI users should replace ``fonttools varLib.mutator`` with ``fonttools varLib.instancer``.
400
+ API users should migrate to ``fontTools.varLib.instancer.instantiateVariableFont`` (#2680).
401
+
402
+
389
403
  4.59.0 (released 2025-07-16)
390
404
  ----------------------------
391
405