def initFeatureWriters(self, featureWriters=None): """Initialize feature writer classes as specified in the UFO lib. If none are defined in the UFO, the default feature writers are used: currently, KernFeatureWriter and MarkFeatureWriter. The 'featureWriters' argument can be used to override these. The method sets the `self.featureWriters` attribute with the list of writers. Note that the writers that generate GSUB features are placed first in this list, before all others. This is because the GSUB table may be used in the subsequent feature writers to resolve substitutions from glyphs with unicodes to their alternates. """ if featureWriters is None: featureWriters = loadFeatureWriters(self.ufo) if featureWriters is None: featureWriters = self.defaultFeatureWriters gsubWriters = [] others = [] for writer in featureWriters: if isclass(writer): writer = writer() if writer.tableTag == "GSUB": gsubWriters.append(writer) else: others.append(writer) self.featureWriters = gsubWriters + others
def test_loadFeatureWriters_valid(specList, FontClass): ufo = FontClass() ufo.lib[FEATURE_WRITERS_KEY] = specList for writer in loadFeatureWriters(ufo, ignoreErrors=False): assert writer.tableTag in {"GSUB", "GPOS"} assert callable(writer.write)
def run_from_designspace( self, designspace_path, output=(), interpolate=False, masters_as_instances=False, interpolate_binary_layout=False, round_instances=False, feature_writers=None, expand_features_to_instances=False, use_mutatormath=False, **kwargs, ): """Run toolchain from a DesignSpace document to produce either static instance fonts (ttf or otf), interpolatable or variable fonts. Args: designspace_path: Path to designspace document. interpolate: If True output all instance fonts, otherwise just masters. If the value is a string, only build instance(s) that match given name. The string is compiled into a regular expression and matched against the "name" attribute of designspace instances using `re.fullmatch`. masters_as_instances: If True, output master fonts as instances. interpolate_binary_layout: Interpolate layout tables from compiled master binaries. round_instances: apply integer rounding when interpolating with MutatorMath. kwargs: Arguments passed along to run_from_ufos. Raises: TypeError: "variable" or "interpolatable" outputs are incompatible with arguments "interpolate", "masters_as_instances", and "interpolate_binary_layout". """ interp_outputs = INTERPOLATABLE_OUTPUTS.intersection(output) static_outputs = set(output).difference(interp_outputs) if interp_outputs: for argname in ( "interpolate", "masters_as_instances", "interpolate_binary_layout", ): if locals()[argname]: raise TypeError( '"%s" argument incompatible with output %r' % (argname, ", ".join(sorted(interp_outputs)))) designspace = designspaceLib.DesignSpaceDocument.fromfile( designspace_path) # if no --feature-writers option was passed, check in the designspace's # <lib> element if user supplied a custom featureWriters configuration; # if so, use that for all the UFOs built from this designspace if feature_writers is None and FEATURE_WRITERS_KEY in designspace.lib: feature_writers = loadFeatureWriters(designspace) if static_outputs: self._run_from_designspace_static( designspace, outputs=static_outputs, interpolate=interpolate, masters_as_instances=masters_as_instances, interpolate_binary_layout=interpolate_binary_layout, round_instances=round_instances, feature_writers=feature_writers, expand_features_to_instances=expand_features_to_instances, use_mutatormath=use_mutatormath, **kwargs, ) if interp_outputs: self._run_from_designspace_interpolatable( designspace, outputs=interp_outputs, feature_writers=feature_writers, **kwargs, )
def run_from_designspace(self, designspace_path, interpolate=False, masters_as_instances=False, interpolate_binary_layout=False, round_instances=False, feature_writers=None, **kwargs): """Run toolchain from a MutatorMath design space document. Args: designspace_path: Path to designspace document. interpolate: If True output all instance fonts, otherwise just masters. If the value is a string, only build instance(s) that match given name. The string is compiled into a regular expression and matched against the "name" attribute of designspace instances using `re.fullmatch`. masters_as_instances: If True, output master fonts as instances. interpolate_binary_layout: Interpolate layout tables from compiled master binaries. round_instances: apply integer rounding when interpolating with MutatorMath. kwargs: Arguments passed along to run_from_ufos. Raises: TypeError: "variable" output is incompatible with arguments "interpolate", "masters_as_instances", and "interpolate_binary_layout". """ if "variable" in kwargs.get("output", ()): for argname in ("interpolate", "masters_as_instances", "interpolate_binary_layout"): if locals()[argname]: raise TypeError( '"%s" argument incompatible with "variable" output' % argname) from glyphsLib.interpolation import apply_instance_data from mutatorMath.ufo.document import DesignSpaceDocumentReader designspace = designspaceLib.DesignSpaceDocument.fromfile( designspace_path) # if no --feature-writers option was passed, check in the designspace's # <lib> element if user supplied a custom featureWriters configuration; # if so, use that for all the UFOs built from this designspace if feature_writers is None and FEATURE_WRITERS_KEY in designspace.lib: feature_writers = loadFeatureWriters(designspace) ufos = [] reader = DesignSpaceDocumentReader(designspace_path, ufoVersion=3, roundGeometry=round_instances, verbose=True) if not interpolate or masters_as_instances: ufos.extend(reader.getSourcePaths()) if interpolate: logger.info('Interpolating master UFOs from designspace') if isinstance(interpolate, basestring): instances = self._search_instances(designspace, pattern=interpolate) for instance_name in instances: reader.readInstance(("name", instance_name)) filenames = set(instances.values()) else: reader.readInstances() filenames = None # will include all instances logger.info('Applying instance data from designspace') ufos.extend( apply_instance_data(designspace_path, include_filenames=filenames)) if interpolate_binary_layout is False: interpolate_layout_from = interpolate_layout_dir = None else: interpolate_layout_from = designspace_path if isinstance(interpolate_binary_layout, basestring): interpolate_layout_dir = interpolate_binary_layout else: interpolate_layout_dir = None self.run_from_ufos(ufos, designspace_path=designspace_path, is_instance=(interpolate or masters_as_instances), interpolate_layout_from=interpolate_layout_from, interpolate_layout_dir=interpolate_layout_dir, feature_writers=feature_writers, **kwargs)