diff --git a/Lib/fontmake/__main__.py b/Lib/fontmake/__main__.py index 766ab6db..15b3b192 100644 --- a/Lib/fontmake/__main__.py +++ b/Lib/fontmake/__main__.py @@ -354,6 +354,12 @@ def main(args=None): "interpolating. Use if you share feature files of masters in " "external files, as instances can end up elsewhere.", ) + outputGroup.add_argument( + "--fea-include-dir", + default=None, + help="Overrides the default directory where to search for included " + "feature files with relative paths." + ) outputGroup.add_argument( "--no-generate-GDEF", dest="generate_GDEF", diff --git a/Lib/fontmake/font_project.py b/Lib/fontmake/font_project.py index 13c0ad73..955f84fd 100644 --- a/Lib/fontmake/font_project.py +++ b/Lib/fontmake/font_project.py @@ -277,6 +277,7 @@ def _build_interpolatable_masters( feature_writers=None, cff_round_tolerance=None, debug_feature_file=None, + fea_include_dir=None, flatten_components=False, filters=None, **kwargs, @@ -289,6 +290,7 @@ def _build_interpolatable_masters( cubicConversionError=conversion_error, featureWriters=feature_writers, debugFeatureFile=debug_feature_file, + feaIncludeDir=fea_include_dir, filters=filters, flattenComponents=flatten_components, inplace=True, @@ -300,6 +302,7 @@ def _build_interpolatable_masters( roundTolerance=cff_round_tolerance, featureWriters=feature_writers, debugFeatureFile=debug_feature_file, + feaIncludeDir=fea_include_dir, filters=filters, inplace=True, ) @@ -331,6 +334,7 @@ def build_variable_fonts( feature_writers=None, cff_round_tolerance=None, debug_feature_file=None, + fea_include_dir=None, flatten_components=False, filters=None, **kwargs, @@ -390,6 +394,7 @@ def build_variable_fonts( optimizeGvar=optimize_gvar, flattenComponents=flatten_components, debugFeatureFile=debug_feature_file, + feaIncludeDir=fea_include_dir, filters=filters, inplace=True, variableFontNames=list(vf_name_to_output_path), @@ -401,6 +406,7 @@ def build_variable_fonts( useProductionNames=use_production_names, roundTolerance=cff_round_tolerance, debugFeatureFile=debug_feature_file, + feaIncludeDir=fea_include_dir, optimizeCFF=optimize_cff, filters=filters, inplace=True, @@ -468,6 +474,7 @@ def save_otfs( flatten_components=False, filters=None, generate_GDEF=True, + fea_include_dir=None, ): """Build OpenType binaries from UFOs. @@ -570,6 +577,7 @@ def save_otfs( cubicConversionError=conversion_error, featureWriters=feature_writers, debugFeatureFile=debug_feature_file, + feaIncludeDir=fea_include_dir, cffVersion=cff_version, subroutinizer=subroutinizer, flattenComponents=flatten_components, @@ -751,6 +759,7 @@ def run_from_glyphs( mti_source=None, write_skipexportglyphs=True, generate_GDEF=True, + fea_include_dir=None, **kwargs, ): """Run toolchain from Glyphs source. @@ -783,8 +792,15 @@ def run_from_glyphs( generate_GDEF=generate_GDEF, ufo_structure=kwargs.get("ufo_structure"), ) + if fea_include_dir is None: + # 'include' statements in features.fea should be resolved relative to + # the input .glyphs path, like Glyphs.app would do, and not relative + # to the UFOs that are generated by glyphsLib. + fea_include_dir = os.path.dirname(glyphs_path) try: - self.run_from_designspace(designspace_path, **kwargs) + self.run_from_designspace( + designspace_path, fea_include_dir=fea_include_dir, **kwargs + ) except FontmakeError as e: e.source_trail.append(glyphs_path) raise @@ -795,6 +811,7 @@ def interpolate_instance_ufos( include=None, round_instances=False, expand_features_to_instances=False, + fea_include_dir=None, ufo_structure="package", ): """Interpolate master UFOs with Instantiator and return instance UFOs. @@ -839,7 +856,9 @@ def interpolate_instance_ufos( if expand_features_to_instances: logger.debug("Expanding features to instance UFOs") - fea_txt = parseLayoutFeatures(subDoc.default.font).asFea() + fea_txt = parseLayoutFeatures( + subDoc.default.font, includeDir=fea_include_dir + ).asFea() generator = attr.evolve(generator, copy_feature_text=fea_txt) for instance in subDoc.instances: @@ -885,6 +904,7 @@ def interpolate_instance_ufos_mutatormath( include=None, round_instances=False, expand_features_to_instances=False, + fea_include_dir=None, ): """Interpolate master UFOs with MutatorMath and return instance UFOs. @@ -947,7 +967,9 @@ def interpolate_instance_ufos_mutatormath( raise ValueError("No source is designated as the master for features.") else: master_source_font = builder.sources[master_source.name][0] - master_source_features = parseLayoutFeatures(master_source_font).asFea() + master_source_features = parseLayoutFeatures( + master_source_font, includeDir=fea_include_dir + ).asFea() for instance_ufo in instance_ufos: instance_ufo.features.text = master_source_features instance_ufo.save() @@ -1091,6 +1113,7 @@ def _run_from_designspace_static( round_instances=False, feature_writers=None, expand_features_to_instances=False, + fea_include_dir=None, use_mutatormath=False, ufo_structure="package", **kwargs, @@ -1107,6 +1130,7 @@ def _run_from_designspace_static( include=pattern, round_instances=round_instances, expand_features_to_instances=expand_features_to_instances, + fea_include_dir=fea_include_dir, ) ) else: @@ -1116,6 +1140,7 @@ def _run_from_designspace_static( include=pattern, round_instances=round_instances, expand_features_to_instances=expand_features_to_instances, + fea_include_dir=fea_include_dir, ufo_structure=ufo_structure, ) ) @@ -1139,6 +1164,7 @@ def _run_from_designspace_static( interpolate_layout_from=interpolate_layout_from, interpolate_layout_dir=interpolate_layout_dir, feature_writers=feature_writers, + fea_include_dir=fea_include_dir, **kwargs, )