Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add allQuadratic=False option to allow building glyf v1 with cubics #768

Merged
merged 2 commits into from
Jul 28, 2023
Merged
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
17 changes: 16 additions & 1 deletion Lib/ufo2ft/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ def compileOTF(ufo, **kwargs):
flattenComponents=False,
autoUseMyMetrics=True,
dropImpliedOnCurves=False,
allQuadratic=True,
),
}

Expand Down Expand Up @@ -252,13 +253,20 @@ def compileTTF(ufo, **kwargs):

*dropImpliedOnCurves* (bool) specifies whether on-curve points that are exactly
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.
"""
kwargs = init_kwargs(kwargs, compileTTF_args)

glyphSet = call_preprocessor(ufo, **kwargs)

logger.info("Building OpenType tables")
otf = call_outline_compiler(ufo, glyphSet, **kwargs)

otf = call_outline_compiler(
ufo, glyphSet, glyphDataFormat=(0 if kwargs["allQuadratic"] else 1), **kwargs
)

# Only the default layer is likely to have all glyphs used in feature code.
if kwargs["layerName"] is None:
Expand All @@ -280,6 +288,7 @@ def compileTTF(ufo, **kwargs):
colrAutoClipBoxes=False,
extraSubstitutions=None,
autoUseMyMetrics=True,
allQuadratic=True,
),
}

Expand Down Expand Up @@ -327,6 +336,7 @@ def compileInterpolatableTTFs(ufos, **kwargs):
ufo,
glyphSet,
**kwargs,
glyphDataFormat=(0 if kwargs["allQuadratic"] else 1),
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 Expand Up @@ -562,6 +572,7 @@ def compileFeatures(
colrAutoClipBoxes=False,
autoUseMyMetrics=True,
dropImpliedOnCurves=False,
allQuadratic=True,
),
}

Expand Down Expand Up @@ -612,6 +623,10 @@ def compileVariableTTFs(designSpaceDoc: DesignSpaceDocument, **kwargs):
to build. If not provided, all variable fonts listed in the given
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.

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

Returns a dictionary that maps each variable font filename to a new variable
Expand Down
2 changes: 2 additions & 0 deletions Lib/ufo2ft/filters/cubicToQuadratic.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class CubicToQuadraticFilter(BaseFilter):
"conversionError": None,
"reverseDirection": True,
"rememberCurveType": False,
"allQuadratic": True,
}

def set_context(self, font, glyphSet):
Expand Down Expand Up @@ -64,6 +65,7 @@ def filter(self, glyph):
self.context.absoluteError,
reverse_direction=self.options.reverseDirection,
stats=self.context.stats,
all_quadratic=self.options.allQuadratic,
)
contours = list(glyph)
glyph.clearContours()
Expand Down
4 changes: 3 additions & 1 deletion Lib/ufo2ft/outlineCompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ def setupTable_head(self):
)
head.fontDirectionHint = 2
head.indexToLocFormat = 0
head.glyphDataFormat = 0
head.glyphDataFormat = getattr(self, "glyphDataFormat", 0)

def setupTable_name(self):
"""
Expand Down Expand Up @@ -1440,6 +1440,7 @@ def __init__(
dropImpliedOnCurves=False,
autoUseMyMetrics=True,
roundCoordinates=True,
glyphDataFormat=0,
):
super().__init__(
font,
Expand All @@ -1454,6 +1455,7 @@ def __init__(
self.autoUseMyMetrics = autoUseMyMetrics
self.dropImpliedOnCurves = dropImpliedOnCurves
self.roundCoordinates = roundCoordinates
self.glyphDataFormat = glyphDataFormat

def compileGlyphs(self):
"""Compile and return the TrueType glyphs for this font."""
Expand Down
5 changes: 5 additions & 0 deletions Lib/ufo2ft/preProcessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ def initDefaultFilters(
flattenComponents=False,
convertCubics=True,
conversionError=None,
allQuadratic=True,
reverseDirection=True,
rememberCurveType=True,
):
Expand Down Expand Up @@ -227,6 +228,7 @@ def initDefaultFilters(
conversionError=conversionError,
reverseDirection=reverseDirection,
rememberCurveType=rememberCurveType and self.inplace,
allQuadratic=allQuadratic,
)
)
return filters
Expand Down Expand Up @@ -266,6 +268,7 @@ def __init__(
layerNames=None,
skipExportGlyphs=None,
filters=None,
allQuadratic=True,
):
from fontTools.cu2qu.ufo import DEFAULT_MAX_ERR

Expand Down Expand Up @@ -293,6 +296,7 @@ def __init__(
]
self._reverseDirection = reverseDirection
self._rememberCurveType = rememberCurveType
self.allQuadratic = allQuadratic

self.defaultFilters = []
for ufo in ufos:
Expand Down Expand Up @@ -336,6 +340,7 @@ def process(self):
reverse_direction=self._reverseDirection,
dump_stats=True,
remember_curve_type=self._rememberCurveType and self.inplace,
all_quadratic=self.allQuadratic,
)

# TrueType fonts cannot mix contours and components, so pick out all glyphs
Expand Down
170 changes: 170 additions & 0 deletions tests/data/TestFont-not-allQuadratic.ttx
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont>

<glyf>

<!-- The xMin, yMin, xMax and yMax values
will be recalculated by the compiler. -->

<TTGlyph name=".notdef" xMin="50" yMin="0" xMax="450" yMax="750">
<contour>
<pt x="450" y="0" on="1"/>
<pt x="50" y="0" on="1"/>
<pt x="50" y="750" on="1"/>
<pt x="450" y="750" on="1"/>
</contour>
<contour>
<pt x="400" y="50" on="1"/>
<pt x="400" y="700" on="1"/>
<pt x="100" y="700" on="1"/>
<pt x="100" y="50" on="1"/>
</contour>
<instructions/>
</TTGlyph>

<TTGlyph name="uni0020"/><!-- contains no outline data -->

<TTGlyph name="uni0061" xMin="66" yMin="0" xMax="322" yMax="510">
<contour>
<pt x="66" y="0" on="1"/>
<pt x="194" y="510" on="1"/>
<pt x="322" y="0" on="1"/>
</contour>
<instructions/>
</TTGlyph>

<TTGlyph name="uni0062" xMin="100" yMin="-5" xMax="310" yMax="505">
<contour>
<pt x="100" y="505" on="1"/>
<pt x="310" y="505" on="1"/>
<pt x="310" y="-5" on="1"/>
<pt x="100" y="-5" on="1"/>
</contour>
<instructions/>
</TTGlyph>

<TTGlyph name="uni0063" xMin="100" yMin="-10" xMax="300" yMax="500">
<contour>
<pt x="300" y="-10" on="1"/>
<pt x="150" y="-10" on="0" cubic="1"/>
<pt x="100" y="40" on="0" cubic="1"/>
<pt x="100" y="245" on="1"/>
<pt x="100" y="450" on="0" cubic="1"/>
<pt x="150" y="500" on="0" cubic="1"/>
<pt x="300" y="500" on="1"/>
</contour>
<instructions/>
</TTGlyph>

<TTGlyph name="uni0064" xMin="90" yMin="77" xMax="211" yMax="197">
<contour>
<pt x="151" y="197" on="1"/>
<pt x="184" y="197" on="0" cubic="1"/>
<pt x="211" y="170" on="0" cubic="1"/>
<pt x="211" y="137" on="1"/>
<pt x="211" y="104" on="0" cubic="1"/>
<pt x="184" y="77" on="0" cubic="1"/>
<pt x="151" y="77" on="1"/>
<pt x="117" y="77" on="0" cubic="1"/>
<pt x="90" y="104" on="0" cubic="1"/>
<pt x="90" y="137" on="1"/>
<pt x="90" y="170" on="0" cubic="1"/>
<pt x="117" y="197" on="0" cubic="1"/>
</contour>
<instructions/>
</TTGlyph>

<TTGlyph name="uni0065" xMin="-55" yMin="23" xMax="454" yMax="510">
<contour>
<pt x="66" y="510" on="1"/>
<pt x="322" y="510" on="1"/>
<pt x="194" y="75" on="1"/>
</contour>
<contour>
<pt x="-55" y="23" on="1"/>
<pt x="-55" y="173" on="0" cubic="1"/>
<pt x="-5" y="223" on="0" cubic="1"/>
<pt x="199" y="223" on="1"/>
<pt x="404" y="223" on="0" cubic="1"/>
<pt x="454" y="173" on="0" cubic="1"/>
<pt x="454" y="23" on="1"/>
</contour>
<instructions/>
</TTGlyph>

<TTGlyph name="uni0066" xMin="-55" yMin="23" xMax="454" yMax="510">
<contour>
<pt x="66" y="510" on="1"/>
<pt x="194" y="75" on="1"/>
<pt x="322" y="510" on="1"/>
</contour>
<contour>
<pt x="-55" y="23" on="1"/>
<pt x="-55" y="173" on="0" cubic="1"/>
<pt x="-5" y="223" on="0" cubic="1"/>
<pt x="199" y="223" on="1"/>
<pt x="404" y="223" on="0" cubic="1"/>
<pt x="454" y="173" on="0" cubic="1"/>
<pt x="454" y="23" on="1"/>
</contour>
<instructions/>
</TTGlyph>

<TTGlyph name="uni0067" xMin="66" yMin="0" xMax="322" yMax="510">
<component glyphName="uni0061" x="0" y="0" flags="0x204"/>
</TTGlyph>

<TTGlyph name="uni0068" xMin="100" yMin="-5" xMax="310" yMax="657">
<component glyphName="uni0064" x="60" y="460" flags="0x4"/>
<component glyphName="uni0062" x="0" y="0" flags="0x204"/>
</TTGlyph>

<TTGlyph name="uni0069" xMin="-55" yMin="-80" xMax="454" yMax="510">
<contour>
<pt x="-55" y="-80" on="1"/>
<pt x="-55" y="69" on="0" cubic="1"/>
<pt x="-5" y="119" on="0" cubic="1"/>
<pt x="199" y="119" on="1"/>
<pt x="404" y="119" on="0" cubic="1"/>
<pt x="454" y="69" on="0" cubic="1"/>
<pt x="454" y="-80" on="1"/>
</contour>
<contour>
<pt x="66" y="0" on="1"/>
<pt x="194" y="510" on="1"/>
<pt x="322" y="0" on="1"/>
</contour>
<instructions/>
</TTGlyph>

<TTGlyph name="uni006A" xMin="-55" yMin="-280" xMax="454" yMax="230">
<contour>
<pt x="-55" y="-80" on="1"/>
<pt x="-55" y="69" on="0" cubic="1"/>
<pt x="-5" y="119" on="0" cubic="1"/>
<pt x="199" y="119" on="1"/>
<pt x="404" y="119" on="0" cubic="1"/>
<pt x="454" y="69" on="0" cubic="1"/>
<pt x="454" y="-80" on="1"/>
</contour>
<contour>
<pt x="66" y="230" on="1"/>
<pt x="322" y="230" on="1"/>
<pt x="194" y="-280" on="1"/>
</contour>
<instructions/>
</TTGlyph>

<TTGlyph name="uni006B" xMin="66" yMin="0" xMax="422" yMax="510">
<component glyphName="uni0061" x="0" y="0" flags="0x4"/>
<component glyphName="uni0061" x="100" y="0" flags="0x4"/>
</TTGlyph>

<TTGlyph name="uni006C" xMin="78" yMin="0" xMax="422" yMax="510">
<component glyphName="uni0061" x="400" y="0" scalex="-1.0" scaley="1.0" flags="0x4"/>
<component glyphName="uni0061" x="100" y="0" flags="0x4"/>
</TTGlyph>

</glyf>

</ttFont>
Loading
Loading