Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions Lib/ufo2ft/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ def compileTTF(ufo, **kwargs):
in between two off-curves can be dropped when building glyphs (default: False).

*allQuadratic* (bool) specifies whether to convert all curves to quadratic - True
by default, builds traditional glyf v0 table. If False, quadratic curves or cubic
curves are generated depending on which has fewer points; a glyf v1 is generated.
by default, builds traditional glyf v0 table. If False, quadratic or cubic curves
are generated depending on which has fewer points, and any cubic outlines are
placed in the uppercase GLYF table.
"""
return TTFCompiler(**kwargs).compile(ufo)

Expand Down Expand Up @@ -158,8 +159,9 @@ def compileVariableTTFs(designSpaceDoc, **kwargs):
designspace will by built.

*allQuadratic* (bool) specifies whether to convert all curves to quadratic - True
by default, builds traditional glyf v0 table. If False, quadratic curves or cubic
curves are generated depending on which has fewer points; a glyf v1 is generated.
by default, builds traditional glyf v0 table. If False, quadratic or cubic curves
are generated depending on which has fewer points, and any cubic outlines are
placed in the uppercase GLYF table.

The rest of the arguments works the same as in the other compile functions.

Expand Down Expand Up @@ -281,8 +283,9 @@ def compileVariableCFF2s(designSpaceDoc, **kwargs):
designspace will by built.

*allQuadratic* (bool) specifies whether to convert all curves to quadratic - True
by default, builds traditional glyf v0 table. If False, quadratic curves or cubic
curves are generated depending on which has fewer points; a glyf v1 is generated.
by default, builds traditional glyf v0 table. If False, quadratic or cubic curves
are generated depending on which has fewer points, and any cubic outlines are
placed in the uppercase GLYF table.

The rest of the arguments works the same as in the other compile functions.

Expand Down
22 changes: 22 additions & 0 deletions Lib/ufo2ft/_compilers/baseCompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ def postprocess(self, ttf, ufo, glyphSet, info=None):
)
kwargs = prune_unknown_kwargs(self.__dict__, postProcessor.process)
ttf = postProcessor.process(**kwargs)
# Upgrade to the beyond-64k companion tables (GLYF/LOCA/MAXP/...)
# only on final outputs. While building a variable font,
# postProcessorClass is None for the interpolation masters (see
# _compileNeededSources), so they keep their lowercase glyf/loca/maxp
# tables and varLib sees a consistent table family; the merged VF is
# uppercased here when its own postprocess runs.
_maybe_uppercase_beyond64k(ttf, getattr(self, "allQuadratic", True))
return ttf

def compileFeatures(
Expand Down Expand Up @@ -481,3 +488,18 @@ def compile_variable_features(self, designSpaceDoc, ttFont, glyphSet):

# Add back feature variations, as the code above would overwrite them.
varLib.addGSUBFeatureVariations(ttFont, designSpaceDoc)


def _maybe_uppercase_beyond64k(ttFont, allQuadratic=True):
# maxp.numGlyphs is uint16: a count of 65536 overflows it even though every
# gid (0..0xFFFF) still fits. Guard on count > 0xFFFF, not gid width.
# allQuadratic=False opts into cubic curves (CUBIC flag is only valid in the
# uppercase GLYF, never lowercase glyf), so always upgrade then to make the
# compatibility breaking obvious rather than depending on whether a cubic
# was emitted, which could be a silent footgun.
if len(ttFont.getGlyphOrder()) <= 0xFFFF and allQuadratic:
return

from fontTools.ttLib.beyond64k import upper_tables

upper_tables(ttFont)
2 changes: 1 addition & 1 deletion Lib/ufo2ft/_compilers/interpolatableTTFCompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class InterpolatableTTFCompiler(BaseInterpolatableCompiler):

def compileOutlines(self, ufo, glyphSet, layerName=None):
kwargs = prune_unknown_kwargs(self.__dict__, self.outlineCompilerClass)
kwargs["glyphDataFormat"] = 0 if self.allQuadratic else 1
kwargs["allowCubic"] = not self.allQuadratic
Comment thread
behdad marked this conversation as resolved.
kwargs["tables"] = SPARSE_TTF_MASTER_TABLES if layerName else None
# we want to keep coordinates as floats in glyf masters so that fonttools
# can compute impliable on-curve points from unrounded coordinates before
Expand Down
2 changes: 1 addition & 1 deletion Lib/ufo2ft/_compilers/ttfCompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ class TTFCompiler(BaseCompiler):

def compileOutlines(self, ufo, glyphSet):
kwargs = prune_unknown_kwargs(self.__dict__, self.outlineCompilerClass)
kwargs["glyphDataFormat"] = 0 if self.allQuadratic else 1
kwargs["allowCubic"] = not self.allQuadratic
outlineCompiler = self.outlineCompilerClass(ufo, glyphSet=glyphSet, **kwargs)
return outlineCompiler.compile()
14 changes: 6 additions & 8 deletions Lib/ufo2ft/outlineCompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ def setupTable_head(self):
)
head.fontDirectionHint = 2
head.indexToLocFormat = 0
head.glyphDataFormat = getattr(self, "glyphDataFormat", 0)
head.glyphDataFormat = 0

def setupTable_name(self):
"""
Expand Down Expand Up @@ -1673,7 +1673,7 @@ def __init__(
dropImpliedOnCurves=False,
autoUseMyMetrics=True,
roundCoordinates=True,
glyphDataFormat=0,
allowCubic=False,
ftConfig=None,
*,
compilingVFDefaultSource=True,
Expand All @@ -1693,7 +1693,7 @@ def __init__(
self.autoUseMyMetrics = autoUseMyMetrics
self.dropImpliedOnCurves = dropImpliedOnCurves
self.roundCoordinates = roundCoordinates
self.glyphDataFormat = glyphDataFormat
self.allowCubic = allowCubic

def makeMissingRequiredGlyphs(self, font, glyphSet, sfntVersion, notdefGlyph=None):
"""
Expand Down Expand Up @@ -1728,7 +1728,6 @@ def compileGlyphs(self):
allGlyphs = self.allGlyphs
ttGlyphs = {}
round = otRound if self.roundCoordinates else noRound
glyphDataFormat = self.glyphDataFormat
for name in self.glyphOrder:
glyph = allGlyphs[name]
pen = TTGlyphPointPen(allGlyphs)
Expand All @@ -1743,14 +1742,13 @@ def compileGlyphs(self):
round=round,
)
if (
glyphDataFormat == 0
not self.allowCubic
and ttGlyph.numberOfContours > 0
and any(f & flagCubic for f in ttGlyph.flags)
):
raise ValueError(
f"{name!r} has cubic Bezier curves, but glyphDataFormat=0; "
"either convert to quadratic (convertCubics=True) or use "
"allQuadratic=False so that glyphDataFormat=1."
f"{name!r} has cubic Bezier curves; either convert to "
"quadratic (convertCubics=True) or use allQuadratic=False."
)
ttGlyphs[name] = ttGlyph
return ttGlyphs
Expand Down
170 changes: 0 additions & 170 deletions tests/data/TestFont-not-allQuadratic.ttx

This file was deleted.

Loading
Loading