cli.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import os
  2. import argparse
  3. import logging
  4. from fontTools.misc.cliTools import makeOutputFileName
  5. from fontTools.ttLib import TTFont
  6. from fontTools.pens.qu2cuPen import Qu2CuPen
  7. from fontTools.pens.ttGlyphPen import TTGlyphPen
  8. import fontTools
  9. logger = logging.getLogger("fontTools.qu2cu")
  10. def _font_to_cubic(input_path, output_path=None, **kwargs):
  11. font = TTFont(input_path)
  12. logger.info("Converting curves for %s", input_path)
  13. stats = {} if kwargs["dump_stats"] else None
  14. qu2cu_kwargs = {
  15. "stats": stats,
  16. "max_err": kwargs["max_err_em"] * font["head"].unitsPerEm,
  17. "all_cubic": kwargs["all_cubic"],
  18. }
  19. if "gvar" in font:
  20. raise ValueError("Cannot convert variable font")
  21. glyphSet = font.getGlyphSet()
  22. glyphOrder = font.getGlyphOrder()
  23. glyf = font["glyf"]
  24. for glyphName in glyphOrder:
  25. glyph = glyphSet[glyphName]
  26. ttpen = TTGlyphPen(glyphSet)
  27. pen = Qu2CuPen(ttpen, **qu2cu_kwargs)
  28. glyph.draw(pen)
  29. glyf[glyphName] = ttpen.glyph(dropImpliedOnCurves=True)
  30. font["head"].glyphDataFormat = 1
  31. if kwargs["dump_stats"]:
  32. logger.info("Stats: %s", stats)
  33. logger.info("Saving %s", output_path)
  34. font.save(output_path)
  35. def _main(args=None):
  36. """Convert an OpenType font from quadratic to cubic curves"""
  37. parser = argparse.ArgumentParser(prog="qu2cu")
  38. parser.add_argument("--version", action="version", version=fontTools.__version__)
  39. parser.add_argument(
  40. "infiles",
  41. nargs="+",
  42. metavar="INPUT",
  43. help="one or more input TTF source file(s).",
  44. )
  45. parser.add_argument("-v", "--verbose", action="count", default=0)
  46. parser.add_argument(
  47. "-e",
  48. "--conversion-error",
  49. type=float,
  50. metavar="ERROR",
  51. default=0.001,
  52. help="maxiumum approximation error measured in EM (default: 0.001)",
  53. )
  54. parser.add_argument(
  55. "-c",
  56. "--all-cubic",
  57. default=False,
  58. action="store_true",
  59. help="whether to only use cubic curves",
  60. )
  61. output_parser = parser.add_mutually_exclusive_group()
  62. output_parser.add_argument(
  63. "-o",
  64. "--output-file",
  65. default=None,
  66. metavar="OUTPUT",
  67. help=("output filename for the converted TTF."),
  68. )
  69. output_parser.add_argument(
  70. "-d",
  71. "--output-dir",
  72. default=None,
  73. metavar="DIRECTORY",
  74. help="output directory where to save converted TTFs",
  75. )
  76. options = parser.parse_args(args)
  77. if options.conversion_error <= 0:
  78. parser.error("--conversion-error must be greater than zero")
  79. if not options.verbose:
  80. level = "WARNING"
  81. elif options.verbose == 1:
  82. level = "INFO"
  83. else:
  84. level = "DEBUG"
  85. logging.basicConfig(level=level)
  86. if len(options.infiles) > 1 and options.output_file:
  87. parser.error("-o/--output-file can't be used with multile inputs")
  88. if options.output_dir:
  89. output_dir = options.output_dir
  90. if not os.path.exists(output_dir):
  91. os.mkdir(output_dir)
  92. elif not os.path.isdir(output_dir):
  93. parser.error("'%s' is not a directory" % output_dir)
  94. output_paths = [
  95. os.path.join(output_dir, os.path.basename(p)) for p in options.infiles
  96. ]
  97. elif options.output_file:
  98. output_paths = [options.output_file]
  99. else:
  100. output_paths = [
  101. makeOutputFileName(p, overWrite=True, suffix=".cubic")
  102. for p in options.infiles
  103. ]
  104. kwargs = dict(
  105. dump_stats=options.verbose > 0,
  106. max_err_em=options.conversion_error,
  107. all_cubic=options.all_cubic,
  108. )
  109. for input_path, output_path in zip(options.infiles, output_paths):
  110. _font_to_cubic(input_path, output_path, **kwargs)