Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
# maxErr = 1.0, approximation error, measured in units per em (UPM).
# postFormat = 2.0, default `post` table format.
# reverseDirection = True, assuming the input contours' direction is correctly set (counter-clockwise), we just flip it to clockwise.
if self.font.sfntVersion != "OTTO" or not self.font.has_key("CFF ") or not self.font.has_key("post"):
print("WARNING: Invalid CFF-based font. --otf2ttf is now ignored.", file = sys.stderr)
self.jobs.convert_otf2ttf = False
return
# Convert cubic to quadratic
quadGlyphs = {}
glyphOrder = self.font.getGlyphOrder()
glyphSet = self.font.getGlyphSet()
for glyphName in glyphSet.keys():
glyph = glyphSet[glyphName]
ttPen = TTGlyphPen(glyphSet)
cu2quPen = Cu2QuPen(ttPen, maxErr, reverseDirection)
glyph.draw(cu2quPen)
quadGlyphs[glyphName] = ttPen.glyph()
# Create quadratic `glyf` table
glyf = newTable("glyf")
glyf.glyphOrder = glyphOrder
glyf.glyphs = quadGlyphs
self.font["glyf"] = glyf
# Create global instruction table `prep` with basic rendering settings
hintProg = Program()
hintProg.fromBytecode([184, 1, 255, 133, 184, 0, 4, 141])
prep = newTable("prep")
prep.program = hintProg
self.font["prep"] = prep
def setupTable_glyf(self):
"""Make the glyf table."""
allGlyphs = self.allGlyphs
if self.convertCubics:
from cu2qu.pens import Cu2QuPen
allGlyphs = {}
for name, glyph in self.allGlyphs.items():
if isinstance(glyph, StubGlyph):
allGlyphs[name] = glyph
continue
newGlyph = glyph.__class__()
glyph.draw(Cu2QuPen(
newGlyph.getPen(), self.cubicConversionError,
reverse_direction=True))
# the width is needed for autoUseMyMetrics method below
newGlyph.width = glyph.width
allGlyphs[name] = newGlyph
self.otf["loca"] = newTable("loca")
self.otf["glyf"] = glyf = newTable("glyf")
glyf.glyphs = {}
glyf.glyphOrder = self.glyphOrder
for name in self.glyphOrder:
glyph = allGlyphs[name]
pen = TTGlyphPen(allGlyphs)
glyph.draw(pen)
ttGlyph = pen.glyph()
def setupTable_glyf(self):
"""Make the glyf table."""
allGlyphs = self.allGlyphs
if self.convertCubics:
from cu2qu.pens import Cu2QuPen
allGlyphs = {}
for name, glyph in self.allGlyphs.items():
if isinstance(glyph, StubGlyph):
allGlyphs[name] = glyph
continue
newGlyph = glyph.__class__()
glyph.draw(Cu2QuPen(
newGlyph.getPen(), self.cubicConversionError,
reverse_direction=True))
allGlyphs[name] = newGlyph
self.otf["loca"] = newTable("loca")
self.otf["glyf"] = glyf = newTable("glyf")
glyf.glyphs = {}
glyf.glyphOrder = self.glyphOrder
for name in self.glyphOrder:
pen = TTGlyphPen(allGlyphs)
allGlyphs[name].draw(pen)
glyf[name] = pen.glyph()
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 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 setupTable_glyf(self):
"""Make the glyf table."""
allGlyphs = self.allGlyphs
if self.convertCubics:
from cu2qu.pens import Cu2QuPen
allGlyphs = {}
for name, glyph in self.allGlyphs.items():
if isinstance(glyph, StubGlyph):
allGlyphs[name] = glyph
continue
newGlyph = glyph.__class__()
glyph.draw(Cu2QuPen(
newGlyph.getPen(), self.cubicConversionError,
reverse_direction=True))
allGlyphs[name] = newGlyph
self.otf["loca"] = newTable("loca")
self.otf["glyf"] = glyf = newTable("glyf")
glyf.glyphs = {}
glyf.glyphOrder = self.glyphOrder
for name in self.glyphOrder:
glyph = allGlyphs[name]
pen = TTGlyphPen(allGlyphs)
glyph.draw(pen)
ttGlyph = pen.glyph()
if ttGlyph.isComposite() and self.autoUseMyMetrics:
self.autoUseMyMetrics(ttGlyph, glyph.width, allGlyphs)
def generateTTFs(self):
"""Build TTF for each font generated since last call to generateTTFs."""
fonts = [OpenFont(ufo) for ufo in self.generatedFonts]
self.generatedFonts = []
log(">> Converting curves to quadratic")
# using a slightly higher max error (e.g. 0.0025 em), dots will have
# fewer control points and look noticeably different
max_err = 0.002
if self.compatible:
fonts_to_quadratic(fonts, max_err_em=max_err, dump_stats=True, reverse_direction=True)
else:
for font in fonts:
fonts_to_quadratic([font], max_err_em=max_err, dump_stats=True, reverse_direction=True)
log(">> Generating TTF files")
for font in fonts:
ttfName = self.generateOutputPath(font, "ttf")
log(os.path.basename(ttfName))
saveOTF(
font, ttfName,
self.thinGlyphOrder if "Thin" in ttfName else self.glyphOrder,
truetype=True)
def generateTTFs(self):
"""Build TTF for each font generated since last call to generateTTFs."""
fonts = [OpenFont(ufo) for ufo in self.generatedFonts]
self.generatedFonts = []
log(">> Converting curves to quadratic")
# using a slightly higher max error (e.g. 0.0025 em), dots will have
# fewer control points and look noticeably different
max_err = 0.002
if self.compatible:
fonts_to_quadratic(fonts, max_err_em=max_err, dump_stats=True, reverse_direction=True)
else:
for font in fonts:
fonts_to_quadratic([font], max_err_em=max_err, dump_stats=True, reverse_direction=True)
log(">> Generating TTF files")
for font in fonts:
ttfName = self.generateOutputPath(font, "ttf")
log(os.path.basename(ttfName))
saveOTF(
font, ttfName,
self.thinGlyphOrder if "Thin" in ttfName else self.glyphOrder,
truetype=True)
def process(self):
from cu2qu.ufo import fonts_to_quadratic
# first apply all custom pre-filters
for funcs, ufo, glyphSet in zip(self.preFilters, self.ufos, self.glyphSets):
for func in funcs:
func(ufo, glyphSet)
fonts_to_quadratic(
self.glyphSets,
max_err=self._conversionErrors,
reverse_direction=self._reverseDirection,
dump_stats=True,
remember_curve_type=self._rememberCurveType and self.inplace,
)
decompose = DecomposeComponentsFilter(include=lambda g: len(g))
for ufo, glyphSet in zip(self.ufos, self.glyphSets):
decompose(ufo, glyphSet)
# finally apply all custom post-filters
for funcs, ufo, glyphSet in zip(self.postFilters, self.ufos, self.glyphSets):
for func in funcs:
func(ufo, glyphSet)
elif curve_type == "cubic":
pass # keep converting
else:
raise NotImplementedError(curve_type)
modified = super(CubicToQuadraticFilter, self).__call__(font, glyphSet)
if modified:
stats = self.context.stats
logger.info(
"New spline lengths: %s"
% (", ".join("%s: %d" % (l, stats[l]) for l in sorted(stats.keys())))
)
if self.options.rememberCurveType:
# 'lib' here is the layer's lib, as defined in for loop variable
curve_type = lib.get(CURVE_TYPE_LIB_KEY, "cubic")
if curve_type != "quadratic":
lib[CURVE_TYPE_LIB_KEY] = "quadratic"
return modified