fonttools 4.56.0__cp38-cp38-win_amd64.whl → 4.57.0__cp38-cp38-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 (34) hide show
  1. fontTools/__init__.py +1 -1
  2. fontTools/config/__init__.py +15 -0
  3. fontTools/cu2qu/cu2qu.cp38-win_amd64.pyd +0 -0
  4. fontTools/feaLib/ast.py +8 -3
  5. fontTools/feaLib/builder.py +32 -9
  6. fontTools/feaLib/lexer.cp38-win_amd64.pyd +0 -0
  7. fontTools/feaLib/parser.py +58 -0
  8. fontTools/misc/bezierTools.cp38-win_amd64.pyd +0 -0
  9. fontTools/misc/testTools.py +2 -1
  10. fontTools/otlLib/optimize/gpos.py +7 -1
  11. fontTools/pens/momentsPen.cp38-win_amd64.pyd +0 -0
  12. fontTools/qu2cu/qu2cu.cp38-win_amd64.pyd +0 -0
  13. fontTools/ttLib/__init__.py +4 -0
  14. fontTools/ttLib/__main__.py +47 -8
  15. fontTools/ttLib/tables/D__e_b_g.py +20 -2
  16. fontTools/ttLib/tables/_c_m_a_p.py +19 -6
  17. fontTools/ttLib/tables/_g_l_y_f.py +9 -4
  18. fontTools/ttLib/tables/_g_v_a_r.py +4 -2
  19. fontTools/ttLib/tables/otConverters.py +5 -2
  20. fontTools/ttLib/tables/otTables.py +5 -1
  21. fontTools/ttLib/ttFont.py +3 -5
  22. fontTools/ttLib/ttGlyphSet.py +0 -10
  23. fontTools/ttx.py +13 -1
  24. fontTools/varLib/__init__.py +92 -89
  25. fontTools/varLib/hvar.py +113 -0
  26. fontTools/varLib/iup.cp38-win_amd64.pyd +0 -0
  27. fontTools/varLib/varStore.py +1 -1
  28. {fonttools-4.56.0.dist-info → fonttools-4.57.0.dist-info}/METADATA +14 -1
  29. {fonttools-4.56.0.dist-info → fonttools-4.57.0.dist-info}/RECORD +34 -33
  30. {fonttools-4.56.0.dist-info → fonttools-4.57.0.dist-info}/WHEEL +1 -1
  31. {fonttools-4.56.0.data → fonttools-4.57.0.data}/data/share/man/man1/ttx.1 +0 -0
  32. {fonttools-4.56.0.dist-info → fonttools-4.57.0.dist-info}/LICENSE +0 -0
  33. {fonttools-4.56.0.dist-info → fonttools-4.57.0.dist-info}/entry_points.txt +0 -0
  34. {fonttools-4.56.0.dist-info → fonttools-4.57.0.dist-info}/top_level.txt +0 -0
fontTools/ttx.py CHANGED
@@ -101,9 +101,15 @@ Compile options
101
101
  --with-zopfli
102
102
  Use Zopfli instead of Zlib to compress WOFF. The Python
103
103
  extension is available at https://pypi.python.org/pypi/zopfli
104
+ --optimize-font-speed
105
+ Enable optimizations that prioritize speed over file size.
106
+ This mainly affects how glyf t able and gvar / VARC tables are
107
+ compiled. The produced fonts will be larger, but rendering
108
+ performance will be improved with HarfBuzz and other text
109
+ layout engines.
104
110
  """
105
111
 
106
- from fontTools.ttLib import TTFont, TTLibError
112
+ from fontTools.ttLib import OPTIMIZE_FONT_SPEED, TTFont, TTLibError
107
113
  from fontTools.misc.macCreatorType import getMacCreatorAndType
108
114
  from fontTools.unicode import setUnicodeData
109
115
  from fontTools.misc.textTools import Tag, tostr
@@ -141,6 +147,7 @@ class Options(object):
141
147
  recalcTimestamp = None
142
148
  flavor = None
143
149
  useZopfli = False
150
+ optimizeFontSpeed = False
144
151
 
145
152
  def __init__(self, rawOptions, numFiles):
146
153
  self.onlyTables = []
@@ -229,6 +236,8 @@ class Options(object):
229
236
  self.flavor = value
230
237
  elif option == "--with-zopfli":
231
238
  self.useZopfli = True
239
+ elif option == "--optimize-font-speed":
240
+ self.optimizeFontSpeed = True
232
241
  if self.verbose and self.quiet:
233
242
  raise getopt.GetoptError("-q and -v options are mutually exclusive")
234
243
  if self.verbose:
@@ -324,6 +333,8 @@ def ttCompile(input, output, options):
324
333
  recalcBBoxes=options.recalcBBoxes,
325
334
  recalcTimestamp=options.recalcTimestamp,
326
335
  )
336
+ if options.optimizeFontSpeed:
337
+ ttf.cfg[OPTIMIZE_FONT_SPEED] = options.optimizeFontSpeed
327
338
  ttf.importXML(input)
328
339
 
329
340
  if options.recalcTimestamp is None and "head" in ttf and input is not sys.stdin:
@@ -386,6 +397,7 @@ def parseOptions(args):
386
397
  "version",
387
398
  "with-zopfli",
388
399
  "newline=",
400
+ "optimize-font-speed",
389
401
  ],
390
402
  )
391
403
 
@@ -12,13 +12,13 @@ a Glyphs source, eg., using noto-source as an example:
12
12
 
13
13
  .. code-block:: sh
14
14
 
15
- $ fontmake -o ttf-interpolatable -g NotoSansArabic-MM.glyphs
15
+ $ fontmake -o ttf-interpolatable -g NotoSansArabic-MM.glyphs
16
16
 
17
17
  Then you can make a variable-font this way:
18
18
 
19
19
  .. code-block:: sh
20
20
 
21
- $ fonttools varLib master_ufo/NotoSansArabic.designspace
21
+ $ fonttools varLib master_ufo/NotoSansArabic.designspace
22
22
 
23
23
  API *will* change in near future.
24
24
  """
@@ -479,7 +479,15 @@ def _merge_TTHinting(font, masterModel, master_ttfs):
479
479
 
480
480
  _MetricsFields = namedtuple(
481
481
  "_MetricsFields",
482
- ["tableTag", "metricsTag", "sb1", "sb2", "advMapping", "vOrigMapping"],
482
+ [
483
+ "tableTag",
484
+ "metricsTag",
485
+ "sb1",
486
+ "sb2",
487
+ "advMapping",
488
+ "vOrigMapping",
489
+ "phantomIndex",
490
+ ],
483
491
  )
484
492
 
485
493
  HVAR_FIELDS = _MetricsFields(
@@ -489,6 +497,7 @@ HVAR_FIELDS = _MetricsFields(
489
497
  sb2="RsbMap",
490
498
  advMapping="AdvWidthMap",
491
499
  vOrigMapping=None,
500
+ phantomIndex=0,
492
501
  )
493
502
 
494
503
  VVAR_FIELDS = _MetricsFields(
@@ -498,109 +507,43 @@ VVAR_FIELDS = _MetricsFields(
498
507
  sb2="BsbMap",
499
508
  advMapping="AdvHeightMap",
500
509
  vOrigMapping="VOrgMap",
510
+ phantomIndex=1,
501
511
  )
502
512
 
503
513
 
504
514
  def _add_HVAR(font, masterModel, master_ttfs, axisTags):
505
- _add_VHVAR(font, masterModel, master_ttfs, axisTags, HVAR_FIELDS)
515
+ getAdvanceMetrics = partial(
516
+ _get_advance_metrics, font, masterModel, master_ttfs, axisTags, HVAR_FIELDS
517
+ )
518
+ _add_VHVAR(font, axisTags, HVAR_FIELDS, getAdvanceMetrics)
506
519
 
507
520
 
508
521
  def _add_VVAR(font, masterModel, master_ttfs, axisTags):
509
- _add_VHVAR(font, masterModel, master_ttfs, axisTags, VVAR_FIELDS)
522
+ getAdvanceMetrics = partial(
523
+ _get_advance_metrics, font, masterModel, master_ttfs, axisTags, VVAR_FIELDS
524
+ )
525
+ _add_VHVAR(font, axisTags, VVAR_FIELDS, getAdvanceMetrics)
510
526
 
511
527
 
512
- def _add_VHVAR(font, masterModel, master_ttfs, axisTags, tableFields):
528
+ def _add_VHVAR(font, axisTags, tableFields, getAdvanceMetrics):
513
529
  tableTag = tableFields.tableTag
514
530
  assert tableTag not in font
531
+ glyphOrder = font.getGlyphOrder()
515
532
  log.info("Generating " + tableTag)
516
533
  VHVAR = newTable(tableTag)
517
534
  tableClass = getattr(ot, tableTag)
518
535
  vhvar = VHVAR.table = tableClass()
519
536
  vhvar.Version = 0x00010000
520
537
 
521
- glyphOrder = font.getGlyphOrder()
522
-
523
- # Build list of source font advance widths for each glyph
524
- metricsTag = tableFields.metricsTag
525
- advMetricses = [m[metricsTag].metrics for m in master_ttfs]
526
-
527
- # Build list of source font vertical origin coords for each glyph
528
- if tableTag == "VVAR" and "VORG" in master_ttfs[0]:
529
- vOrigMetricses = [m["VORG"].VOriginRecords for m in master_ttfs]
530
- defaultYOrigs = [m["VORG"].defaultVertOriginY for m in master_ttfs]
531
- vOrigMetricses = list(zip(vOrigMetricses, defaultYOrigs))
532
- else:
533
- vOrigMetricses = None
534
-
535
- metricsStore, advanceMapping, vOrigMapping = _get_advance_metrics(
536
- font,
537
- masterModel,
538
- master_ttfs,
539
- axisTags,
540
- glyphOrder,
541
- advMetricses,
542
- vOrigMetricses,
543
- )
538
+ vhAdvanceDeltasAndSupports, vOrigDeltasAndSupports = getAdvanceMetrics()
544
539
 
545
- vhvar.VarStore = metricsStore
546
- if advanceMapping is None:
547
- setattr(vhvar, tableFields.advMapping, None)
540
+ if vOrigDeltasAndSupports:
541
+ singleModel = False
548
542
  else:
549
- setattr(vhvar, tableFields.advMapping, advanceMapping)
550
- if vOrigMapping is not None:
551
- setattr(vhvar, tableFields.vOrigMapping, vOrigMapping)
552
- setattr(vhvar, tableFields.sb1, None)
553
- setattr(vhvar, tableFields.sb2, None)
554
-
555
- font[tableTag] = VHVAR
556
- return
557
-
558
-
559
- def _get_advance_metrics(
560
- font,
561
- masterModel,
562
- master_ttfs,
563
- axisTags,
564
- glyphOrder,
565
- advMetricses,
566
- vOrigMetricses=None,
567
- ):
568
- vhAdvanceDeltasAndSupports = {}
569
- vOrigDeltasAndSupports = {}
570
- # HACK: we treat width 65535 as a sentinel value to signal that a glyph
571
- # from a non-default master should not participate in computing {H,V}VAR,
572
- # as if it were missing. Allows to variate other glyph-related data independently
573
- # from glyph metrics
574
- sparse_advance = 0xFFFF
575
- for glyph in glyphOrder:
576
- vhAdvances = [
577
- (
578
- metrics[glyph][0]
579
- if glyph in metrics and metrics[glyph][0] != sparse_advance
580
- else None
581
- )
582
- for metrics in advMetricses
583
- ]
584
- vhAdvanceDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports(
585
- vhAdvances, round=round
543
+ singleModel = models.allEqual(
544
+ id(v[1]) for v in vhAdvanceDeltasAndSupports.values()
586
545
  )
587
546
 
588
- singleModel = models.allEqual(id(v[1]) for v in vhAdvanceDeltasAndSupports.values())
589
-
590
- if vOrigMetricses:
591
- singleModel = False
592
- for glyph in glyphOrder:
593
- # We need to supply a vOrigs tuple with non-None default values
594
- # for each glyph. vOrigMetricses contains values only for those
595
- # glyphs which have a non-default vOrig.
596
- vOrigs = [
597
- metrics[glyph] if glyph in metrics else defaultVOrig
598
- for metrics, defaultVOrig in vOrigMetricses
599
- ]
600
- vOrigDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports(
601
- vOrigs, round=round
602
- )
603
-
604
547
  directStore = None
605
548
  if singleModel:
606
549
  # Build direct mapping
@@ -621,7 +564,7 @@ def _get_advance_metrics(
621
564
  storeBuilder.setSupports(supports)
622
565
  advMapping[glyphName] = storeBuilder.storeDeltas(deltas, round=noRound)
623
566
 
624
- if vOrigMetricses:
567
+ if vOrigDeltasAndSupports:
625
568
  vOrigMap = {}
626
569
  for glyphName in glyphOrder:
627
570
  deltas, supports = vOrigDeltasAndSupports[glyphName]
@@ -633,7 +576,7 @@ def _get_advance_metrics(
633
576
  advMapping = [mapping2[advMapping[g]] for g in glyphOrder]
634
577
  advanceMapping = builder.buildVarIdxMap(advMapping, glyphOrder)
635
578
 
636
- if vOrigMetricses:
579
+ if vOrigDeltasAndSupports:
637
580
  vOrigMap = [mapping2[vOrigMap[g]] for g in glyphOrder]
638
581
 
639
582
  useDirect = False
@@ -657,10 +600,70 @@ def _get_advance_metrics(
657
600
  advanceMapping = None
658
601
  else:
659
602
  metricsStore = indirectStore
660
- if vOrigMetricses:
603
+ if vOrigDeltasAndSupports:
661
604
  vOrigMapping = builder.buildVarIdxMap(vOrigMap, glyphOrder)
662
605
 
663
- return metricsStore, advanceMapping, vOrigMapping
606
+ vhvar.VarStore = metricsStore
607
+ setattr(vhvar, tableFields.advMapping, advanceMapping)
608
+ if vOrigMapping is not None:
609
+ setattr(vhvar, tableFields.vOrigMapping, vOrigMapping)
610
+ setattr(vhvar, tableFields.sb1, None)
611
+ setattr(vhvar, tableFields.sb2, None)
612
+
613
+ font[tableTag] = VHVAR
614
+ return
615
+
616
+
617
+ def _get_advance_metrics(font, masterModel, master_ttfs, axisTags, tableFields):
618
+ tableTag = tableFields.tableTag
619
+ glyphOrder = font.getGlyphOrder()
620
+
621
+ # Build list of source font advance widths for each glyph
622
+ metricsTag = tableFields.metricsTag
623
+ advMetricses = [m[metricsTag].metrics for m in master_ttfs]
624
+
625
+ # Build list of source font vertical origin coords for each glyph
626
+ if tableTag == "VVAR" and "VORG" in master_ttfs[0]:
627
+ vOrigMetricses = [m["VORG"].VOriginRecords for m in master_ttfs]
628
+ defaultYOrigs = [m["VORG"].defaultVertOriginY for m in master_ttfs]
629
+ vOrigMetricses = list(zip(vOrigMetricses, defaultYOrigs))
630
+ else:
631
+ vOrigMetricses = None
632
+
633
+ vhAdvanceDeltasAndSupports = {}
634
+ vOrigDeltasAndSupports = {}
635
+ # HACK: we treat width 65535 as a sentinel value to signal that a glyph
636
+ # from a non-default master should not participate in computing {H,V}VAR,
637
+ # as if it were missing. Allows to variate other glyph-related data independently
638
+ # from glyph metrics
639
+ sparse_advance = 0xFFFF
640
+ for glyph in glyphOrder:
641
+ vhAdvances = [
642
+ (
643
+ metrics[glyph][0]
644
+ if glyph in metrics and metrics[glyph][0] != sparse_advance
645
+ else None
646
+ )
647
+ for metrics in advMetricses
648
+ ]
649
+ vhAdvanceDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports(
650
+ vhAdvances, round=round
651
+ )
652
+
653
+ if vOrigMetricses:
654
+ for glyph in glyphOrder:
655
+ # We need to supply a vOrigs tuple with non-None default values
656
+ # for each glyph. vOrigMetricses contains values only for those
657
+ # glyphs which have a non-default vOrig.
658
+ vOrigs = [
659
+ metrics[glyph] if glyph in metrics else defaultVOrig
660
+ for metrics, defaultVOrig in vOrigMetricses
661
+ ]
662
+ vOrigDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports(
663
+ vOrigs, round=round
664
+ )
665
+
666
+ return vhAdvanceDeltasAndSupports, vOrigDeltasAndSupports
664
667
 
665
668
 
666
669
  def _add_MVAR(font, masterModel, master_ttfs, axisTags):
@@ -0,0 +1,113 @@
1
+ from fontTools.misc.roundTools import noRound
2
+ from fontTools.ttLib import TTFont, newTable
3
+ from fontTools.ttLib.tables import otTables as ot
4
+ from fontTools.ttLib.tables.otBase import OTTableWriter
5
+ from fontTools.varLib import HVAR_FIELDS, VVAR_FIELDS, _add_VHVAR
6
+ from fontTools.varLib import builder, models, varStore
7
+ from fontTools.misc.fixedTools import fixedToFloat as fi2fl
8
+ from fontTools.misc.cliTools import makeOutputFileName
9
+ from functools import partial
10
+ import logging
11
+
12
+ log = logging.getLogger("fontTools.varLib.avar")
13
+
14
+
15
+ def _get_advance_metrics(font, axisTags, tableFields):
16
+ # There's two ways we can go from here:
17
+ # 1. For each glyph, at each master peak, compute the value of the
18
+ # advance width at that peak. Then pass these all to a VariationModel
19
+ # builder to compute back the deltas.
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.
22
+ # We'll go with the second option, as it's simpler, faster, and more direct.
23
+ gvar = font["gvar"]
24
+ vhAdvanceDeltasAndSupports = {}
25
+ glyphOrder = font.getGlyphOrder()
26
+ phantomIndex = tableFields.phantomIndex
27
+ for glyphName in glyphOrder:
28
+ supports = []
29
+ deltas = []
30
+ variations = gvar.variations.get(glyphName, [])
31
+
32
+ for tv in variations:
33
+ supports.append(tv.axes)
34
+ phantoms = tv.coordinates[-4:]
35
+ phantoms = phantoms[phantomIndex * 2 : phantomIndex * 2 + 2]
36
+ assert len(phantoms) == 2
37
+ phantoms[0] = phantoms[0][phantomIndex] if phantoms[0] is not None else 0
38
+ phantoms[1] = phantoms[1][phantomIndex] if phantoms[1] is not None else 0
39
+ deltas.append(phantoms[1] - phantoms[0])
40
+
41
+ vhAdvanceDeltasAndSupports[glyphName] = (deltas, supports)
42
+
43
+ vOrigDeltasAndSupports = None # TODO
44
+
45
+ return vhAdvanceDeltasAndSupports, vOrigDeltasAndSupports
46
+
47
+
48
+ def add_HVAR(font):
49
+ if "HVAR" in font:
50
+ del font["HVAR"]
51
+ axisTags = [axis.axisTag for axis in font["fvar"].axes]
52
+ getAdvanceMetrics = partial(_get_advance_metrics, font, axisTags, HVAR_FIELDS)
53
+ _add_VHVAR(font, axisTags, HVAR_FIELDS, getAdvanceMetrics)
54
+
55
+
56
+ def add_VVAR(font):
57
+ if "VVAR" in font:
58
+ del font["VVAR"]
59
+ getAdvanceMetrics = partial(_get_advance_metrics, font, axisTags, HVAR_FIELDS)
60
+ axisTags = [axis.axisTag for axis in font["fvar"].axes]
61
+ _add_VHVAR(font, axisTags, VVAR_FIELDS, getAdvanceMetrics)
62
+
63
+
64
+ def main(args=None):
65
+ """Add `HVAR` table to variable font."""
66
+
67
+ if args is None:
68
+ import sys
69
+
70
+ args = sys.argv[1:]
71
+
72
+ from fontTools import configLogger
73
+ from fontTools.designspaceLib import DesignSpaceDocument
74
+ import argparse
75
+
76
+ parser = argparse.ArgumentParser(
77
+ "fonttools varLib.hvar",
78
+ description="Add `HVAR` table from to variable font.",
79
+ )
80
+ parser.add_argument("font", metavar="varfont.ttf", help="Variable-font file.")
81
+ parser.add_argument(
82
+ "-o",
83
+ "--output-file",
84
+ type=str,
85
+ help="Output font file name.",
86
+ )
87
+
88
+ options = parser.parse_args(args)
89
+
90
+ configLogger(level="WARNING")
91
+
92
+ font = TTFont(options.font)
93
+ if not "fvar" in font:
94
+ log.error("Not a variable font.")
95
+ return 1
96
+
97
+ add_HVAR(font)
98
+ if "vmtx" in font:
99
+ add_VVAR(font)
100
+
101
+ if options.output_file is None:
102
+ outfile = makeOutputFileName(options.font, overWrite=True, suffix=".hvar")
103
+ else:
104
+ outfile = options.output_file
105
+ if outfile:
106
+ log.info("Saving %s", outfile)
107
+ font.save(outfile)
108
+
109
+
110
+ if __name__ == "__main__":
111
+ import sys
112
+
113
+ sys.exit(main())
Binary file
@@ -41,7 +41,7 @@ class OnlineVarStoreBuilder(object):
41
41
  def setSupports(self, supports):
42
42
  self._model = None
43
43
  self._supports = list(supports)
44
- if not self._supports[0]:
44
+ if self._supports and not self._supports[0]:
45
45
  del self._supports[0] # Drop base master support
46
46
  self._cache = None
47
47
  self._data = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fonttools
3
- Version: 4.56.0
3
+ Version: 4.57.0
4
4
  Summary: Tools to manipulate font files
5
5
  Home-page: http://github.com/fonttools/fonttools
6
6
  Author: Just van Rossum
@@ -378,6 +378,19 @@ Have fun!
378
378
  Changelog
379
379
  ~~~~~~~~~
380
380
 
381
+ 4.57.0 (released 2025-04-03)
382
+ ----------------------------
383
+
384
+ - [ttLib.__main__] Add `--no-recalc-timestamp` flag (#3771)
385
+ - [ttLib.__main__] Add `-b` (recalcBBoxes=False) flag (#3772)
386
+ - [cmap] Speed up glyphOrder loading from cmap (#3774)
387
+ - [ttLib.__main__] Improvements around the `-t` flag (#3776)
388
+ - [Debg] Fix parsing from XML; add roundtrip tests (#3781)
389
+ - [fealib] Support \*Base.MinMax tables (#3783, #3786)
390
+ - [config] Add OPTIMIZE_FONT_SPEED (#3784)
391
+ - [varLib.hvar] New module to add HVAR table to the font (#3780)
392
+ - [otlLib.optimize] Fix crash when the provided TTF does not contain a `GPOS` (#3794)
393
+
381
394
  4.56.0 (released 2025-02-07)
382
395
  ----------------------------
383
396