fonttools 4.57.0__cp312-cp312-win32.whl → 4.58.1__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.

Files changed (67) hide show
  1. fontTools/__init__.py +1 -1
  2. fontTools/cffLib/__init__.py +61 -26
  3. fontTools/cffLib/specializer.py +4 -1
  4. fontTools/cu2qu/cu2qu.c +15357 -14829
  5. fontTools/cu2qu/cu2qu.cp312-win32.pyd +0 -0
  6. fontTools/designspaceLib/statNames.py +14 -7
  7. fontTools/feaLib/ast.py +12 -9
  8. fontTools/feaLib/builder.py +75 -49
  9. fontTools/feaLib/lexer.c +17160 -17986
  10. fontTools/feaLib/lexer.cp312-win32.pyd +0 -0
  11. fontTools/feaLib/parser.py +1 -39
  12. fontTools/fontBuilder.py +6 -0
  13. fontTools/merge/cmap.py +33 -1
  14. fontTools/merge/tables.py +12 -1
  15. fontTools/misc/bezierTools.c +39948 -41831
  16. fontTools/misc/bezierTools.cp312-win32.pyd +0 -0
  17. fontTools/misc/etree.py +4 -27
  18. fontTools/misc/loggingTools.py +1 -1
  19. fontTools/misc/symfont.py +6 -8
  20. fontTools/mtiLib/__init__.py +1 -3
  21. fontTools/otlLib/builder.py +359 -145
  22. fontTools/otlLib/optimize/gpos.py +42 -62
  23. fontTools/pens/momentsPen.c +13283 -13448
  24. fontTools/pens/momentsPen.cp312-win32.pyd +0 -0
  25. fontTools/pens/pointPen.py +21 -12
  26. fontTools/pens/t2CharStringPen.py +31 -11
  27. fontTools/qu2cu/qu2cu.c +16550 -16269
  28. fontTools/qu2cu/qu2cu.cp312-win32.pyd +0 -0
  29. fontTools/subset/__init__.py +12 -1
  30. fontTools/ttLib/tables/G_V_A_R_.py +5 -0
  31. fontTools/ttLib/tables/T_S_I__0.py +14 -3
  32. fontTools/ttLib/tables/T_S_I__5.py +16 -5
  33. fontTools/ttLib/tables/__init__.py +1 -0
  34. fontTools/ttLib/tables/_c_v_t.py +2 -0
  35. fontTools/ttLib/tables/_f_p_g_m.py +3 -1
  36. fontTools/ttLib/tables/_g_l_y_f.py +2 -6
  37. fontTools/ttLib/tables/_g_v_a_r.py +58 -15
  38. fontTools/ttLib/tables/_p_o_s_t.py +5 -2
  39. fontTools/ttLib/tables/otBase.py +1 -0
  40. fontTools/ufoLib/__init__.py +3 -3
  41. fontTools/ufoLib/converters.py +89 -25
  42. fontTools/ufoLib/errors.py +8 -0
  43. fontTools/ufoLib/etree.py +1 -1
  44. fontTools/ufoLib/filenames.py +155 -100
  45. fontTools/ufoLib/glifLib.py +9 -2
  46. fontTools/ufoLib/kerning.py +66 -36
  47. fontTools/ufoLib/utils.py +5 -2
  48. fontTools/unicodedata/Mirrored.py +446 -0
  49. fontTools/unicodedata/__init__.py +6 -2
  50. fontTools/varLib/__init__.py +20 -6
  51. fontTools/varLib/featureVars.py +13 -7
  52. fontTools/varLib/hvar.py +1 -1
  53. fontTools/varLib/instancer/__init__.py +14 -5
  54. fontTools/varLib/iup.c +19642 -19154
  55. fontTools/varLib/iup.cp312-win32.pyd +0 -0
  56. fontTools/voltLib/__main__.py +206 -0
  57. fontTools/voltLib/ast.py +4 -0
  58. fontTools/voltLib/parser.py +16 -8
  59. fontTools/voltLib/voltToFea.py +347 -166
  60. {fonttools-4.57.0.dist-info → fonttools-4.58.1.dist-info}/METADATA +64 -11
  61. {fonttools-4.57.0.dist-info → fonttools-4.58.1.dist-info}/RECORD +67 -63
  62. {fonttools-4.57.0.dist-info → fonttools-4.58.1.dist-info}/WHEEL +1 -1
  63. fonttools-4.58.1.dist-info/licenses/LICENSE.external +359 -0
  64. {fonttools-4.57.0.data → fonttools-4.58.1.data}/data/share/man/man1/ttx.1 +0 -0
  65. {fonttools-4.57.0.dist-info → fonttools-4.58.1.dist-info}/entry_points.txt +0 -0
  66. {fonttools-4.57.0.dist-info → fonttools-4.58.1.dist-info}/licenses/LICENSE +0 -0
  67. {fonttools-4.57.0.dist-info → fonttools-4.58.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,446 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # NOTE: The mappings in this file were generated from the command line:
4
+ # cat BidiMirroring.txt | grep "^[0-9A-F]" | sed "s/;//" | awk '{print " 0x"$1": 0x"$2","}'
5
+ #
6
+ # Source: http://www.unicode.org/Public/UNIDATA/BidiMirroring.txt
7
+ # License: http://unicode.org/copyright.html#License
8
+ #
9
+ # BidiMirroring-16.0.0.txt
10
+ # Date: 2024-01-30
11
+ # © 2024 Unicode®, Inc.
12
+ # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
13
+ # For terms of use and license, see https://www.unicode.org/terms_of_use.html
14
+ #
15
+ # Unicode Character Database
16
+ # For documentation, see https://www.unicode.org/reports/tr44/
17
+ MIRRORED = {
18
+ 0x0028: 0x0029,
19
+ 0x0029: 0x0028,
20
+ 0x003C: 0x003E,
21
+ 0x003E: 0x003C,
22
+ 0x005B: 0x005D,
23
+ 0x005D: 0x005B,
24
+ 0x007B: 0x007D,
25
+ 0x007D: 0x007B,
26
+ 0x00AB: 0x00BB,
27
+ 0x00BB: 0x00AB,
28
+ 0x0F3A: 0x0F3B,
29
+ 0x0F3B: 0x0F3A,
30
+ 0x0F3C: 0x0F3D,
31
+ 0x0F3D: 0x0F3C,
32
+ 0x169B: 0x169C,
33
+ 0x169C: 0x169B,
34
+ 0x2039: 0x203A,
35
+ 0x203A: 0x2039,
36
+ 0x2045: 0x2046,
37
+ 0x2046: 0x2045,
38
+ 0x207D: 0x207E,
39
+ 0x207E: 0x207D,
40
+ 0x208D: 0x208E,
41
+ 0x208E: 0x208D,
42
+ 0x2208: 0x220B,
43
+ 0x2209: 0x220C,
44
+ 0x220A: 0x220D,
45
+ 0x220B: 0x2208,
46
+ 0x220C: 0x2209,
47
+ 0x220D: 0x220A,
48
+ 0x2215: 0x29F5,
49
+ 0x221F: 0x2BFE,
50
+ 0x2220: 0x29A3,
51
+ 0x2221: 0x299B,
52
+ 0x2222: 0x29A0,
53
+ 0x2224: 0x2AEE,
54
+ 0x223C: 0x223D,
55
+ 0x223D: 0x223C,
56
+ 0x2243: 0x22CD,
57
+ 0x2245: 0x224C,
58
+ 0x224C: 0x2245,
59
+ 0x2252: 0x2253,
60
+ 0x2253: 0x2252,
61
+ 0x2254: 0x2255,
62
+ 0x2255: 0x2254,
63
+ 0x2264: 0x2265,
64
+ 0x2265: 0x2264,
65
+ 0x2266: 0x2267,
66
+ 0x2267: 0x2266,
67
+ 0x2268: 0x2269,
68
+ 0x2269: 0x2268,
69
+ 0x226A: 0x226B,
70
+ 0x226B: 0x226A,
71
+ 0x226E: 0x226F,
72
+ 0x226F: 0x226E,
73
+ 0x2270: 0x2271,
74
+ 0x2271: 0x2270,
75
+ 0x2272: 0x2273,
76
+ 0x2273: 0x2272,
77
+ 0x2274: 0x2275,
78
+ 0x2275: 0x2274,
79
+ 0x2276: 0x2277,
80
+ 0x2277: 0x2276,
81
+ 0x2278: 0x2279,
82
+ 0x2279: 0x2278,
83
+ 0x227A: 0x227B,
84
+ 0x227B: 0x227A,
85
+ 0x227C: 0x227D,
86
+ 0x227D: 0x227C,
87
+ 0x227E: 0x227F,
88
+ 0x227F: 0x227E,
89
+ 0x2280: 0x2281,
90
+ 0x2281: 0x2280,
91
+ 0x2282: 0x2283,
92
+ 0x2283: 0x2282,
93
+ 0x2284: 0x2285,
94
+ 0x2285: 0x2284,
95
+ 0x2286: 0x2287,
96
+ 0x2287: 0x2286,
97
+ 0x2288: 0x2289,
98
+ 0x2289: 0x2288,
99
+ 0x228A: 0x228B,
100
+ 0x228B: 0x228A,
101
+ 0x228F: 0x2290,
102
+ 0x2290: 0x228F,
103
+ 0x2291: 0x2292,
104
+ 0x2292: 0x2291,
105
+ 0x2298: 0x29B8,
106
+ 0x22A2: 0x22A3,
107
+ 0x22A3: 0x22A2,
108
+ 0x22A6: 0x2ADE,
109
+ 0x22A8: 0x2AE4,
110
+ 0x22A9: 0x2AE3,
111
+ 0x22AB: 0x2AE5,
112
+ 0x22B0: 0x22B1,
113
+ 0x22B1: 0x22B0,
114
+ 0x22B2: 0x22B3,
115
+ 0x22B3: 0x22B2,
116
+ 0x22B4: 0x22B5,
117
+ 0x22B5: 0x22B4,
118
+ 0x22B6: 0x22B7,
119
+ 0x22B7: 0x22B6,
120
+ 0x22B8: 0x27DC,
121
+ 0x22C9: 0x22CA,
122
+ 0x22CA: 0x22C9,
123
+ 0x22CB: 0x22CC,
124
+ 0x22CC: 0x22CB,
125
+ 0x22CD: 0x2243,
126
+ 0x22D0: 0x22D1,
127
+ 0x22D1: 0x22D0,
128
+ 0x22D6: 0x22D7,
129
+ 0x22D7: 0x22D6,
130
+ 0x22D8: 0x22D9,
131
+ 0x22D9: 0x22D8,
132
+ 0x22DA: 0x22DB,
133
+ 0x22DB: 0x22DA,
134
+ 0x22DC: 0x22DD,
135
+ 0x22DD: 0x22DC,
136
+ 0x22DE: 0x22DF,
137
+ 0x22DF: 0x22DE,
138
+ 0x22E0: 0x22E1,
139
+ 0x22E1: 0x22E0,
140
+ 0x22E2: 0x22E3,
141
+ 0x22E3: 0x22E2,
142
+ 0x22E4: 0x22E5,
143
+ 0x22E5: 0x22E4,
144
+ 0x22E6: 0x22E7,
145
+ 0x22E7: 0x22E6,
146
+ 0x22E8: 0x22E9,
147
+ 0x22E9: 0x22E8,
148
+ 0x22EA: 0x22EB,
149
+ 0x22EB: 0x22EA,
150
+ 0x22EC: 0x22ED,
151
+ 0x22ED: 0x22EC,
152
+ 0x22F0: 0x22F1,
153
+ 0x22F1: 0x22F0,
154
+ 0x22F2: 0x22FA,
155
+ 0x22F3: 0x22FB,
156
+ 0x22F4: 0x22FC,
157
+ 0x22F6: 0x22FD,
158
+ 0x22F7: 0x22FE,
159
+ 0x22FA: 0x22F2,
160
+ 0x22FB: 0x22F3,
161
+ 0x22FC: 0x22F4,
162
+ 0x22FD: 0x22F6,
163
+ 0x22FE: 0x22F7,
164
+ 0x2308: 0x2309,
165
+ 0x2309: 0x2308,
166
+ 0x230A: 0x230B,
167
+ 0x230B: 0x230A,
168
+ 0x2329: 0x232A,
169
+ 0x232A: 0x2329,
170
+ 0x2768: 0x2769,
171
+ 0x2769: 0x2768,
172
+ 0x276A: 0x276B,
173
+ 0x276B: 0x276A,
174
+ 0x276C: 0x276D,
175
+ 0x276D: 0x276C,
176
+ 0x276E: 0x276F,
177
+ 0x276F: 0x276E,
178
+ 0x2770: 0x2771,
179
+ 0x2771: 0x2770,
180
+ 0x2772: 0x2773,
181
+ 0x2773: 0x2772,
182
+ 0x2774: 0x2775,
183
+ 0x2775: 0x2774,
184
+ 0x27C3: 0x27C4,
185
+ 0x27C4: 0x27C3,
186
+ 0x27C5: 0x27C6,
187
+ 0x27C6: 0x27C5,
188
+ 0x27C8: 0x27C9,
189
+ 0x27C9: 0x27C8,
190
+ 0x27CB: 0x27CD,
191
+ 0x27CD: 0x27CB,
192
+ 0x27D5: 0x27D6,
193
+ 0x27D6: 0x27D5,
194
+ 0x27DC: 0x22B8,
195
+ 0x27DD: 0x27DE,
196
+ 0x27DE: 0x27DD,
197
+ 0x27E2: 0x27E3,
198
+ 0x27E3: 0x27E2,
199
+ 0x27E4: 0x27E5,
200
+ 0x27E5: 0x27E4,
201
+ 0x27E6: 0x27E7,
202
+ 0x27E7: 0x27E6,
203
+ 0x27E8: 0x27E9,
204
+ 0x27E9: 0x27E8,
205
+ 0x27EA: 0x27EB,
206
+ 0x27EB: 0x27EA,
207
+ 0x27EC: 0x27ED,
208
+ 0x27ED: 0x27EC,
209
+ 0x27EE: 0x27EF,
210
+ 0x27EF: 0x27EE,
211
+ 0x2983: 0x2984,
212
+ 0x2984: 0x2983,
213
+ 0x2985: 0x2986,
214
+ 0x2986: 0x2985,
215
+ 0x2987: 0x2988,
216
+ 0x2988: 0x2987,
217
+ 0x2989: 0x298A,
218
+ 0x298A: 0x2989,
219
+ 0x298B: 0x298C,
220
+ 0x298C: 0x298B,
221
+ 0x298D: 0x2990,
222
+ 0x298E: 0x298F,
223
+ 0x298F: 0x298E,
224
+ 0x2990: 0x298D,
225
+ 0x2991: 0x2992,
226
+ 0x2992: 0x2991,
227
+ 0x2993: 0x2994,
228
+ 0x2994: 0x2993,
229
+ 0x2995: 0x2996,
230
+ 0x2996: 0x2995,
231
+ 0x2997: 0x2998,
232
+ 0x2998: 0x2997,
233
+ 0x299B: 0x2221,
234
+ 0x29A0: 0x2222,
235
+ 0x29A3: 0x2220,
236
+ 0x29A4: 0x29A5,
237
+ 0x29A5: 0x29A4,
238
+ 0x29A8: 0x29A9,
239
+ 0x29A9: 0x29A8,
240
+ 0x29AA: 0x29AB,
241
+ 0x29AB: 0x29AA,
242
+ 0x29AC: 0x29AD,
243
+ 0x29AD: 0x29AC,
244
+ 0x29AE: 0x29AF,
245
+ 0x29AF: 0x29AE,
246
+ 0x29B8: 0x2298,
247
+ 0x29C0: 0x29C1,
248
+ 0x29C1: 0x29C0,
249
+ 0x29C4: 0x29C5,
250
+ 0x29C5: 0x29C4,
251
+ 0x29CF: 0x29D0,
252
+ 0x29D0: 0x29CF,
253
+ 0x29D1: 0x29D2,
254
+ 0x29D2: 0x29D1,
255
+ 0x29D4: 0x29D5,
256
+ 0x29D5: 0x29D4,
257
+ 0x29D8: 0x29D9,
258
+ 0x29D9: 0x29D8,
259
+ 0x29DA: 0x29DB,
260
+ 0x29DB: 0x29DA,
261
+ 0x29E8: 0x29E9,
262
+ 0x29E9: 0x29E8,
263
+ 0x29F5: 0x2215,
264
+ 0x29F8: 0x29F9,
265
+ 0x29F9: 0x29F8,
266
+ 0x29FC: 0x29FD,
267
+ 0x29FD: 0x29FC,
268
+ 0x2A2B: 0x2A2C,
269
+ 0x2A2C: 0x2A2B,
270
+ 0x2A2D: 0x2A2E,
271
+ 0x2A2E: 0x2A2D,
272
+ 0x2A34: 0x2A35,
273
+ 0x2A35: 0x2A34,
274
+ 0x2A3C: 0x2A3D,
275
+ 0x2A3D: 0x2A3C,
276
+ 0x2A64: 0x2A65,
277
+ 0x2A65: 0x2A64,
278
+ 0x2A79: 0x2A7A,
279
+ 0x2A7A: 0x2A79,
280
+ 0x2A7B: 0x2A7C,
281
+ 0x2A7C: 0x2A7B,
282
+ 0x2A7D: 0x2A7E,
283
+ 0x2A7E: 0x2A7D,
284
+ 0x2A7F: 0x2A80,
285
+ 0x2A80: 0x2A7F,
286
+ 0x2A81: 0x2A82,
287
+ 0x2A82: 0x2A81,
288
+ 0x2A83: 0x2A84,
289
+ 0x2A84: 0x2A83,
290
+ 0x2A85: 0x2A86,
291
+ 0x2A86: 0x2A85,
292
+ 0x2A87: 0x2A88,
293
+ 0x2A88: 0x2A87,
294
+ 0x2A89: 0x2A8A,
295
+ 0x2A8A: 0x2A89,
296
+ 0x2A8B: 0x2A8C,
297
+ 0x2A8C: 0x2A8B,
298
+ 0x2A8D: 0x2A8E,
299
+ 0x2A8E: 0x2A8D,
300
+ 0x2A8F: 0x2A90,
301
+ 0x2A90: 0x2A8F,
302
+ 0x2A91: 0x2A92,
303
+ 0x2A92: 0x2A91,
304
+ 0x2A93: 0x2A94,
305
+ 0x2A94: 0x2A93,
306
+ 0x2A95: 0x2A96,
307
+ 0x2A96: 0x2A95,
308
+ 0x2A97: 0x2A98,
309
+ 0x2A98: 0x2A97,
310
+ 0x2A99: 0x2A9A,
311
+ 0x2A9A: 0x2A99,
312
+ 0x2A9B: 0x2A9C,
313
+ 0x2A9C: 0x2A9B,
314
+ 0x2A9D: 0x2A9E,
315
+ 0x2A9E: 0x2A9D,
316
+ 0x2A9F: 0x2AA0,
317
+ 0x2AA0: 0x2A9F,
318
+ 0x2AA1: 0x2AA2,
319
+ 0x2AA2: 0x2AA1,
320
+ 0x2AA6: 0x2AA7,
321
+ 0x2AA7: 0x2AA6,
322
+ 0x2AA8: 0x2AA9,
323
+ 0x2AA9: 0x2AA8,
324
+ 0x2AAA: 0x2AAB,
325
+ 0x2AAB: 0x2AAA,
326
+ 0x2AAC: 0x2AAD,
327
+ 0x2AAD: 0x2AAC,
328
+ 0x2AAF: 0x2AB0,
329
+ 0x2AB0: 0x2AAF,
330
+ 0x2AB1: 0x2AB2,
331
+ 0x2AB2: 0x2AB1,
332
+ 0x2AB3: 0x2AB4,
333
+ 0x2AB4: 0x2AB3,
334
+ 0x2AB5: 0x2AB6,
335
+ 0x2AB6: 0x2AB5,
336
+ 0x2AB7: 0x2AB8,
337
+ 0x2AB8: 0x2AB7,
338
+ 0x2AB9: 0x2ABA,
339
+ 0x2ABA: 0x2AB9,
340
+ 0x2ABB: 0x2ABC,
341
+ 0x2ABC: 0x2ABB,
342
+ 0x2ABD: 0x2ABE,
343
+ 0x2ABE: 0x2ABD,
344
+ 0x2ABF: 0x2AC0,
345
+ 0x2AC0: 0x2ABF,
346
+ 0x2AC1: 0x2AC2,
347
+ 0x2AC2: 0x2AC1,
348
+ 0x2AC3: 0x2AC4,
349
+ 0x2AC4: 0x2AC3,
350
+ 0x2AC5: 0x2AC6,
351
+ 0x2AC6: 0x2AC5,
352
+ 0x2AC7: 0x2AC8,
353
+ 0x2AC8: 0x2AC7,
354
+ 0x2AC9: 0x2ACA,
355
+ 0x2ACA: 0x2AC9,
356
+ 0x2ACB: 0x2ACC,
357
+ 0x2ACC: 0x2ACB,
358
+ 0x2ACD: 0x2ACE,
359
+ 0x2ACE: 0x2ACD,
360
+ 0x2ACF: 0x2AD0,
361
+ 0x2AD0: 0x2ACF,
362
+ 0x2AD1: 0x2AD2,
363
+ 0x2AD2: 0x2AD1,
364
+ 0x2AD3: 0x2AD4,
365
+ 0x2AD4: 0x2AD3,
366
+ 0x2AD5: 0x2AD6,
367
+ 0x2AD6: 0x2AD5,
368
+ 0x2ADE: 0x22A6,
369
+ 0x2AE3: 0x22A9,
370
+ 0x2AE4: 0x22A8,
371
+ 0x2AE5: 0x22AB,
372
+ 0x2AEC: 0x2AED,
373
+ 0x2AED: 0x2AEC,
374
+ 0x2AEE: 0x2224,
375
+ 0x2AF7: 0x2AF8,
376
+ 0x2AF8: 0x2AF7,
377
+ 0x2AF9: 0x2AFA,
378
+ 0x2AFA: 0x2AF9,
379
+ 0x2BFE: 0x221F,
380
+ 0x2E02: 0x2E03,
381
+ 0x2E03: 0x2E02,
382
+ 0x2E04: 0x2E05,
383
+ 0x2E05: 0x2E04,
384
+ 0x2E09: 0x2E0A,
385
+ 0x2E0A: 0x2E09,
386
+ 0x2E0C: 0x2E0D,
387
+ 0x2E0D: 0x2E0C,
388
+ 0x2E1C: 0x2E1D,
389
+ 0x2E1D: 0x2E1C,
390
+ 0x2E20: 0x2E21,
391
+ 0x2E21: 0x2E20,
392
+ 0x2E22: 0x2E23,
393
+ 0x2E23: 0x2E22,
394
+ 0x2E24: 0x2E25,
395
+ 0x2E25: 0x2E24,
396
+ 0x2E26: 0x2E27,
397
+ 0x2E27: 0x2E26,
398
+ 0x2E28: 0x2E29,
399
+ 0x2E29: 0x2E28,
400
+ 0x2E55: 0x2E56,
401
+ 0x2E56: 0x2E55,
402
+ 0x2E57: 0x2E58,
403
+ 0x2E58: 0x2E57,
404
+ 0x2E59: 0x2E5A,
405
+ 0x2E5A: 0x2E59,
406
+ 0x2E5B: 0x2E5C,
407
+ 0x2E5C: 0x2E5B,
408
+ 0x3008: 0x3009,
409
+ 0x3009: 0x3008,
410
+ 0x300A: 0x300B,
411
+ 0x300B: 0x300A,
412
+ 0x300C: 0x300D,
413
+ 0x300D: 0x300C,
414
+ 0x300E: 0x300F,
415
+ 0x300F: 0x300E,
416
+ 0x3010: 0x3011,
417
+ 0x3011: 0x3010,
418
+ 0x3014: 0x3015,
419
+ 0x3015: 0x3014,
420
+ 0x3016: 0x3017,
421
+ 0x3017: 0x3016,
422
+ 0x3018: 0x3019,
423
+ 0x3019: 0x3018,
424
+ 0x301A: 0x301B,
425
+ 0x301B: 0x301A,
426
+ 0xFE59: 0xFE5A,
427
+ 0xFE5A: 0xFE59,
428
+ 0xFE5B: 0xFE5C,
429
+ 0xFE5C: 0xFE5B,
430
+ 0xFE5D: 0xFE5E,
431
+ 0xFE5E: 0xFE5D,
432
+ 0xFE64: 0xFE65,
433
+ 0xFE65: 0xFE64,
434
+ 0xFF08: 0xFF09,
435
+ 0xFF09: 0xFF08,
436
+ 0xFF1C: 0xFF1E,
437
+ 0xFF1E: 0xFF1C,
438
+ 0xFF3B: 0xFF3D,
439
+ 0xFF3D: 0xFF3B,
440
+ 0xFF5B: 0xFF5D,
441
+ 0xFF5D: 0xFF5B,
442
+ 0xFF5F: 0xFF60,
443
+ 0xFF60: 0xFF5F,
444
+ 0xFF62: 0xFF63,
445
+ 0xFF63: 0xFF62,
446
+ }
@@ -15,8 +15,7 @@ except ImportError: # pragma: no cover
15
15
  # fall back to built-in unicodedata (possibly outdated)
16
16
  from unicodedata import *
17
17
 
18
- from . import Blocks, Scripts, ScriptExtensions, OTTags
19
-
18
+ from . import Blocks, Mirrored, Scripts, ScriptExtensions, OTTags
20
19
 
21
20
  __all__ = [
22
21
  # names from built-in unicodedata module
@@ -46,6 +45,11 @@ __all__ = [
46
45
  ]
47
46
 
48
47
 
48
+ def mirrored(code):
49
+ """If code (unicode codepoint) has a mirrored version returns it, otherwise None."""
50
+ return Mirrored.MIRRORED.get(code)
51
+
52
+
49
53
  def script(char):
50
54
  """Return the four-letter script code assigned to the Unicode character
51
55
  'char' as string.
@@ -109,6 +109,8 @@ def _add_fvar(font, axes, instances: List[InstanceDescriptor]):
109
109
  axis.flags = int(a.hidden)
110
110
  fvar.axes.append(axis)
111
111
 
112
+ default_coordinates = {axis.axisTag: axis.defaultValue for axis in fvar.axes}
113
+
112
114
  for instance in instances:
113
115
  # Filter out discrete axis locations
114
116
  coordinates = {
@@ -130,16 +132,26 @@ def _add_fvar(font, axes, instances: List[InstanceDescriptor]):
130
132
  psname = instance.postScriptFontName
131
133
 
132
134
  inst = NamedInstance()
133
- inst.subfamilyNameID = nameTable.addMultilingualName(
134
- localisedStyleName, mac=macNames
135
+ inst.coordinates = {
136
+ axes[k].tag: axes[k].map_backward(v) for k, v in coordinates.items()
137
+ }
138
+
139
+ subfamilyNameID = nameTable.findMultilingualName(
140
+ localisedStyleName, windows=True, mac=macNames
135
141
  )
142
+ if subfamilyNameID in {2, 17} and inst.coordinates == default_coordinates:
143
+ # Instances can only reuse an existing name ID 2 or 17 if they are at the
144
+ # default location across all axes, see:
145
+ # https://github.com/fonttools/fonttools/issues/3825.
146
+ inst.subfamilyNameID = subfamilyNameID
147
+ else:
148
+ inst.subfamilyNameID = nameTable.addMultilingualName(
149
+ localisedStyleName, windows=True, mac=macNames, minNameID=256
150
+ )
151
+
136
152
  if psname is not None:
137
153
  psname = tostr(psname)
138
154
  inst.postscriptNameID = nameTable.addName(psname, platforms=platforms)
139
- inst.coordinates = {
140
- axes[k].tag: axes[k].map_backward(v) for k, v in coordinates.items()
141
- }
142
- # inst.coordinates = {axes[k].tag:v for k,v in coordinates.items()}
143
155
  fvar.instances.append(inst)
144
156
 
145
157
  assert "fvar" not in font
@@ -555,6 +567,8 @@ def _add_VHVAR(font, axisTags, tableFields, getAdvanceMetrics):
555
567
  varData.addItem(vhAdvanceDeltasAndSupports[glyphName][0], round=noRound)
556
568
  varData.optimize()
557
569
  directStore = builder.buildVarStore(varTupleList, [varData])
570
+ # remove unused regions from VarRegionList
571
+ directStore.prune_regions()
558
572
 
559
573
  # Build optimized indirect mapping
560
574
  storeBuilder = varStore.OnlineVarStoreBuilder(axisTags)
@@ -392,10 +392,13 @@ def addFeatureVariationsRaw(font, table, conditionalSubstitutions, featureTag="r
392
392
 
393
393
  for scriptRecord in table.ScriptList.ScriptRecord:
394
394
  if scriptRecord.Script.DefaultLangSys is None:
395
- raise VarLibError(
396
- "Feature variations require that the script "
397
- f"'{scriptRecord.ScriptTag}' defines a default language system."
398
- )
395
+ # We need to have a default LangSys to attach variations to.
396
+ langSys = ot.LangSys()
397
+ langSys.LookupOrder = None
398
+ langSys.ReqFeatureIndex = 0xFFFF
399
+ langSys.FeatureIndex = []
400
+ langSys.FeatureCount = 0
401
+ scriptRecord.Script.DefaultLangSys = langSys
399
402
  langSystems = [lsr.LangSys for lsr in scriptRecord.Script.LangSysRecord]
400
403
  for langSys in [scriptRecord.Script.DefaultLangSys] + langSystems:
401
404
  langSys.FeatureIndex.append(varFeatureIndex)
@@ -597,9 +600,12 @@ def buildFeatureRecord(featureTag, lookupListIndices):
597
600
  def buildFeatureVariationRecord(conditionTable, substitutionRecords):
598
601
  """Build a FeatureVariationRecord."""
599
602
  fvr = ot.FeatureVariationRecord()
600
- fvr.ConditionSet = ot.ConditionSet()
601
- fvr.ConditionSet.ConditionTable = conditionTable
602
- fvr.ConditionSet.ConditionCount = len(conditionTable)
603
+ if len(conditionTable) != 0:
604
+ fvr.ConditionSet = ot.ConditionSet()
605
+ fvr.ConditionSet.ConditionTable = conditionTable
606
+ fvr.ConditionSet.ConditionCount = len(conditionTable)
607
+ else:
608
+ fvr.ConditionSet = None
603
609
  fvr.FeatureTableSubstitution = ot.FeatureTableSubstitution()
604
610
  fvr.FeatureTableSubstitution.Version = 0x00010000
605
611
  fvr.FeatureTableSubstitution.SubstitutionRecord = substitutionRecords
fontTools/varLib/hvar.py CHANGED
@@ -18,7 +18,7 @@ def _get_advance_metrics(font, axisTags, tableFields):
18
18
  # advance width at that peak. Then pass these all to a VariationModel
19
19
  # builder to compute back the deltas.
20
20
  # 2. For each master peak, pull out the deltas of the advance width directly,
21
- # and feed these to the VarStoreBuilder, forgoing the remoding step.
21
+ # and feed these to the VarStoreBuilder, forgoing the remodeling step.
22
22
  # We'll go with the second option, as it's simpler, faster, and more direct.
23
23
  gvar = font["gvar"]
24
24
  vhAdvanceDeltasAndSupports = {}
@@ -675,6 +675,7 @@ def instantiateCFF2(
675
675
  privateDicts.append(fd.Private)
676
676
 
677
677
  allCommands = []
678
+ allCommandPrivates = []
678
679
  for cs in charStrings:
679
680
  assert cs.private.vstore.otVarStore is varStore # Or in many places!!
680
681
  commands = programToCommands(cs.program, getNumRegions=getNumRegions)
@@ -683,6 +684,7 @@ def instantiateCFF2(
683
684
  if specialize:
684
685
  commands = specializeCommands(commands, generalizeFirst=not generalize)
685
686
  allCommands.append(commands)
687
+ allCommandPrivates.append(cs.private)
686
688
 
687
689
  def storeBlendsToVarStore(arg):
688
690
  if not isinstance(arg, list):
@@ -742,8 +744,8 @@ def instantiateCFF2(
742
744
  assert varData.ItemCount == 0
743
745
 
744
746
  # Add charstring blend lists to VarStore so we can instantiate them
745
- for commands in allCommands:
746
- vsindex = 0
747
+ for commands, private in zip(allCommands, allCommandPrivates):
748
+ vsindex = getattr(private, "vsindex", 0)
747
749
  for command in commands:
748
750
  if command[0] == "vsindex":
749
751
  vsindex = command[1][0]
@@ -752,7 +754,6 @@ def instantiateCFF2(
752
754
  storeBlendsToVarStore(arg)
753
755
 
754
756
  # Add private blend lists to VarStore so we can instantiate values
755
- vsindex = 0
756
757
  for opcode, name, arg_type, default, converter in privateDictOperators2:
757
758
  if arg_type not in ("number", "delta", "array"):
758
759
  continue
@@ -763,6 +764,7 @@ def instantiateCFF2(
763
764
  continue
764
765
  values = getattr(private, name)
765
766
 
767
+ # This is safe here since "vsindex" is the first in the privateDictOperators2
766
768
  if name == "vsindex":
767
769
  vsindex = values[0]
768
770
  continue
@@ -783,8 +785,8 @@ def instantiateCFF2(
783
785
 
784
786
  # Read back new charstring blends from the instantiated VarStore
785
787
  varDataCursor = [0] * len(varStore.VarData)
786
- for commands in allCommands:
787
- vsindex = 0
788
+ for commands, private in zip(allCommands, allCommandPrivates):
789
+ vsindex = getattr(private, "vsindex", 0)
788
790
  for command in commands:
789
791
  if command[0] == "vsindex":
790
792
  vsindex = command[1][0]
@@ -799,9 +801,16 @@ def instantiateCFF2(
799
801
  if arg_type not in ("number", "delta", "array"):
800
802
  continue
801
803
 
804
+ vsindex = 0
802
805
  for private in privateDicts:
803
806
  if not hasattr(private, name):
804
807
  continue
808
+
809
+ # This is safe here since "vsindex" is the first in the privateDictOperators2
810
+ if name == "vsindex":
811
+ vsindex = values[0]
812
+ continue
813
+
805
814
  values = getattr(private, name)
806
815
  if arg_type == "number":
807
816
  values = [values]