Be clever in what we accept

See https://github.com/fonttools/fonttools/pull/1416#issuecomment-448674815
This commit is contained in:
Nikolaus Waxweiler 2018-12-19 18:29:34 +00:00
parent e464e450ac
commit 67d1f3598a

View File

@ -23,7 +23,7 @@ from __future__ import unicode_literals
from fontTools.misc.py23 import * from fontTools.misc.py23 import *
from fontTools.misc.fixedTools import otRound from fontTools.misc.fixedTools import otRound
from fontTools.misc.arrayTools import Vector from fontTools.misc.arrayTools import Vector
from fontTools.ttLib import TTFont, newTable from fontTools.ttLib import TTFont, newTable, TTLibError
from fontTools.ttLib.tables._n_a_m_e import NameRecord from fontTools.ttLib.tables._n_a_m_e import NameRecord
from fontTools.ttLib.tables._f_v_a_r import Axis, NamedInstance from fontTools.ttLib.tables._f_v_a_r import Axis, NamedInstance
from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates
@ -747,29 +747,52 @@ def build(designspace, master_finder=lambda s:s, exclude=[], optimize=True):
ds = load_designspace(designspace) ds = load_designspace(designspace)
log.info("Building variable font") log.info("Building variable font")
master_fonts = []
master_ttfs = []
master_source = ds.masters[ds.base_idx]
if hasattr(designspace, "sources"): # Assume a DesignspaceDocument if hasattr(designspace, "sources"): # Assume a DesignspaceDocument
for master in ds.masters: basedir = getattr(designspace, "path", None)
if master.font is None: else: # Assume a path
basedir = os.path.dirname(designspace)
for master in ds.masters:
# 1. If a SourceDescriptor has a layer name, demand that the compiled TTFont
# be supplied by the caller. This spares us from modifying MasterFinder.
if master.layerName:
if not master.font:
raise AttributeError( raise AttributeError(
"designspace source '%s' is missing required 'font' attribute" "Designspace source '%s' specified a layer name but lacks the "
"then required TTFont object in the 'font' attribute."
% getattr(master, "name", "<Unknown>") % getattr(master, "name", "<Unknown>")
) )
master_fonts = [master.font for master in ds.masters] master_fonts.append(master.font)
master_ttfs = [] master_ttfs.append(None) # No file path for in-memory object.
# Make a copy of the designated base font that we can then modify in-place. else:
buffer = io.BytesIO() # 2. If the caller already supplies a TTFont for a source, just take it.
master_fonts[ds.base_idx].save(buffer) if master.font:
buffer.seek(0) font = master.font
vf = TTFont(buffer) master_fonts.append(font)
else: # Assume a file path master_ttfs.append(None) # No file path for in-memory object.
log.info("Loading master fonts") else:
basedir = os.path.dirname(designspace) # 3. A SourceDescriptor's filename might point to a UFO or an OpenType
master_ttfs = [ # binary. Find out the hard way.
master_finder(os.path.join(basedir, m.filename)) for m in ds.masters master_path = os.path.join(basedir, master.filename)
] try:
master_fonts = [TTFont(ttf_path) for ttf_path in master_ttfs] font = TTFont(master_path)
# Reload base font as target font master_fonts.append(font)
vf = TTFont(master_ttfs[ds.base_idx]) master_ttfs.append(master_path)
except (IOError, TTLibError):
# 4. Probably no OpenType binary, fall back to the master finder.
master_path = master_finder(master_path)
font = TTFont(master_path)
master_fonts.append(font)
master_ttfs.append(master_path)
# Copy the master source TTFont object to work on it.
if master is master_source:
buffer = io.BytesIO()
font.save(buffer)
buffer.seek(0)
vf = TTFont(buffer)
# TODO append masters as named-instances as well; needs .designspace change. # TODO append masters as named-instances as well; needs .designspace change.
fvar = _add_fvar(vf, ds.axes, ds.instances) fvar = _add_fvar(vf, ds.axes, ds.instances)