fonttools/Snippets/otf2ttf.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

134 lines
3.8 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
2018-10-09 18:43:34 +02:00
import argparse
import logging
2018-10-10 12:42:46 -07:00
import os
import sys
from fontTools.pens.cu2quPen import Cu2QuPen
from fontTools import configLogger
from fontTools.misc.cliTools import makeOutputFileName
from fontTools.pens.ttGlyphPen import TTGlyphPen
from fontTools.ttLib import TTFont, newTable
log = logging.getLogger()
# default approximation error, measured in UPEM
MAX_ERR = 1.0
# default 'post' table format
POST_FORMAT = 2.0
# assuming the input contours' direction is correctly set (counter-clockwise),
# we just flip it to clockwise
REVERSE_DIRECTION = True
def glyphs_to_quadratic(glyphs, max_err=MAX_ERR, reverse_direction=REVERSE_DIRECTION):
quadGlyphs = {}
for gname in glyphs.keys():
glyph = glyphs[gname]
ttPen = TTGlyphPen(glyphs)
cu2quPen = Cu2QuPen(ttPen, max_err, reverse_direction=reverse_direction)
glyph.draw(cu2quPen)
quadGlyphs[gname] = ttPen.glyph()
return quadGlyphs
def update_hmtx(ttFont, glyf):
hmtx = ttFont["hmtx"]
for glyphName, glyph in glyf.glyphs.items():
if hasattr(glyph, "xMin"):
hmtx[glyphName] = (hmtx[glyphName][0], glyph.xMin)
def otf_to_ttf(ttFont, post_format=POST_FORMAT, **kwargs):
assert ttFont.sfntVersion == "OTTO"
assert "CFF " in ttFont
glyphOrder = ttFont.getGlyphOrder()
ttFont["loca"] = newTable("loca")
ttFont["glyf"] = glyf = newTable("glyf")
glyf.glyphOrder = glyphOrder
glyf.glyphs = glyphs_to_quadratic(ttFont.getGlyphSet(), **kwargs)
del ttFont["CFF "]
glyf.compile(ttFont)
update_hmtx(ttFont, glyf)
ttFont["maxp"] = maxp = newTable("maxp")
maxp.tableVersion = 0x00010000
maxp.maxZones = 1
maxp.maxTwilightPoints = 0
maxp.maxStorage = 0
maxp.maxFunctionDefs = 0
maxp.maxInstructionDefs = 0
maxp.maxStackElements = 0
maxp.maxSizeOfInstructions = 0
maxp.maxComponentElements = max(
len(g.components if hasattr(g, "components") else [])
for g in glyf.glyphs.values()
2022-12-13 11:26:36 +00:00
)
maxp.compile(ttFont)
post = ttFont["post"]
post.formatType = post_format
post.extraNames = []
post.mapping = {}
post.glyphOrder = glyphOrder
try:
post.compile(ttFont)
except OverflowError:
post.formatType = 3
log.warning("Dropping glyph names, they do not fit in 'post' table.")
ttFont.sfntVersion = "\000\001\000\000"
def main(args=None):
configLogger(logger=log)
parser = argparse.ArgumentParser()
2018-10-10 12:42:46 -07:00
parser.add_argument("input", nargs="+", metavar="INPUT")
parser.add_argument("-o", "--output")
parser.add_argument("-e", "--max-error", type=float, default=MAX_ERR)
parser.add_argument("--post-format", type=float, default=POST_FORMAT)
parser.add_argument(
"--keep-direction", dest="reverse_direction", action="store_false"
)
parser.add_argument("--face-index", type=int, default=0)
parser.add_argument("--overwrite", action="store_true")
options = parser.parse_args(args)
2018-10-10 12:42:46 -07:00
if options.output and len(options.input) > 1:
if not os.path.isdir(options.output):
parser.error(
"-o/--output option must be a directory when "
"processing multiple fonts"
)
for path in options.input:
if options.output and not os.path.isdir(options.output):
output = options.output
else:
output = makeOutputFileName(
path,
outputDir=options.output,
extension=".ttf",
overWrite=options.overwrite,
)
2018-10-10 12:42:46 -07:00
font = TTFont(path, fontNumber=options.face_index)
otf_to_ttf(
font,
post_format=options.post_format,
max_err=options.max_error,
reverse_direction=options.reverse_direction,
)
font.save(output)
if __name__ == "__main__":
sys.exit(main())