fontBuilder: add glyphDataFormat=0; error with accidentally cubic outlines
Fixes #3113
This commit is contained in:
parent
65bc6105f7
commit
a421f9045a
@ -131,6 +131,7 @@ fb.save("test.otf")
|
||||
|
||||
from .ttLib import TTFont, newTable
|
||||
from .ttLib.tables._c_m_a_p import cmap_classes
|
||||
from .ttLib.tables._g_l_y_f import flagCubic
|
||||
from .misc.timeTools import timestampNow
|
||||
import struct
|
||||
from collections import OrderedDict
|
||||
@ -319,7 +320,7 @@ _OS2Defaults = dict(
|
||||
|
||||
|
||||
class FontBuilder(object):
|
||||
def __init__(self, unitsPerEm=None, font=None, isTTF=True):
|
||||
def __init__(self, unitsPerEm=None, font=None, isTTF=True, glyphDataFormat=0):
|
||||
"""Initialize a FontBuilder instance.
|
||||
|
||||
If the `font` argument is not given, a new `TTFont` will be
|
||||
@ -327,15 +328,31 @@ class FontBuilder(object):
|
||||
the font will be a glyf-based TTF; if `isTTF` is False it will be
|
||||
a CFF-based OTF.
|
||||
|
||||
The `glyphDataFormat` argument corresponds to the `head` table field
|
||||
that defines the format of the TrueType `glyf` table (default=0).
|
||||
TrueType glyphs historically can only contain quadratic splines and static
|
||||
components, but there's a proposal to add support for cubic Bezier curves as well
|
||||
as variable composites/components at
|
||||
https://github.com/harfbuzz/boring-expansion-spec/blob/main/glyf1.md
|
||||
You can experiment with the new features by setting `glyphDataFormat` to 1.
|
||||
A ValueError is raised if `glyphDataFormat` is left at 0 but glyphs are added
|
||||
that contain cubic splines or varcomposites. This is to prevent accidentally
|
||||
creating fonts that are incompatible with existing TrueType implementations.
|
||||
|
||||
If `font` is given, it must be a `TTFont` instance and `unitsPerEm`
|
||||
must _not_ be given. The `isTTF` argument will be ignored.
|
||||
must _not_ be given. The `isTTF` and `glyphDataFormat` arguments will be ignored.
|
||||
"""
|
||||
if font is None:
|
||||
self.font = TTFont(recalcTimestamp=False)
|
||||
self.isTTF = isTTF
|
||||
now = timestampNow()
|
||||
assert unitsPerEm is not None
|
||||
self.setupHead(unitsPerEm=unitsPerEm, created=now, modified=now)
|
||||
self.setupHead(
|
||||
unitsPerEm=unitsPerEm,
|
||||
create=now,
|
||||
modified=now,
|
||||
glyphDataFormat=glyphDataFormat,
|
||||
)
|
||||
self.setupMaxp()
|
||||
else:
|
||||
assert unitsPerEm is None
|
||||
@ -639,8 +656,25 @@ class FontBuilder(object):
|
||||
If `calcGlyphBounds` is True, the bounds of all glyphs will be
|
||||
calculated. Only pass False if your glyph objects already have
|
||||
their bounding box values set.
|
||||
|
||||
Raises ValueError if any of the glyphs contains cubic curves or is a variable
|
||||
composite but the `head` table has `glyphDataFormat` set to 0 (instead of 1).
|
||||
"""
|
||||
assert self.isTTF
|
||||
|
||||
glyphDataFormat = self.font["head"].glyphDataFormat
|
||||
if glyphDataFormat == 0:
|
||||
for name, g in glyphs.items():
|
||||
if g.isVarComposite():
|
||||
raise ValueError(
|
||||
f"Glyph {name!r} is a variable composite, but glyphDataFormat=0"
|
||||
)
|
||||
elif g.numberOfContours > 0 and any(f & flagCubic for f in g.flags):
|
||||
raise ValueError(
|
||||
f"Glyph {name!r} has cubic Bezier outlines, but glyphDataFormat=0; "
|
||||
"either convert to quadratics with cu2qu or set glyphDataFormat=1."
|
||||
)
|
||||
|
||||
self.font["loca"] = newTable("loca")
|
||||
self.font["glyf"] = newTable("glyf")
|
||||
self.font["glyf"].glyphs = glyphs
|
||||
|
Loading…
x
Reference in New Issue
Block a user