diff --git a/Lib/gftools/builder/operations/__init__.py b/Lib/gftools/builder/operations/__init__.py index 0b033073..8cb06db6 100644 --- a/Lib/gftools/builder/operations/__init__.py +++ b/Lib/gftools/builder/operations/__init__.py @@ -5,6 +5,7 @@ import pkgutil import importlib import inspect +import logging import sys from os.path import dirname from tempfile import NamedTemporaryFile @@ -12,6 +13,17 @@ from gftools.builder.file import File from gftools.utils import shell_quote +log = logging.getLogger(__name__) + + +# Grossness to allow class properties in Python +class classproperty: + def __init__(self, func): + self.fget = func + + def __get__(self, instance, owner): + return self.fget(owner) + @dataclass class OperationBase: @@ -131,9 +143,24 @@ def validate(self): class FontmakeOperationBase(OperationBase): + COMPILER_ENV_KEY = "GFTOOLS_COMPILER" + static = False + format = "ttf" + + @classproperty + def rule(self): + if self.compiler == "fontmake": + return "fontmake --output-path $out -o $format $fontmake_type $in $args" + else: + # Construct a ninja rule which correctly builds the requested font type + # (Good luck with fontmake args...) + return "fontc -o $out $in $args" + @property def variables(self): vars = defaultdict(str) + vars["compiler"] = self.compiler + vars["format"] = self.format # buildTTF -> ttf, etc. for k, v in self.original.items(): if k != "needs": vars[k] = v @@ -144,11 +171,42 @@ def variables(self): vars["fontmake_type"] = "-m" elif self.first_source.is_ufo: vars["fontmake_type"] = "-u" - if "--verbose" not in vars["fontmake_args"]: - vars["fontmake_args"] += " --verbose WARNING " + if "--verbose" not in vars["args"]: + vars["args"] += " --verbose WARNING " + + if "--filter" in vars["args"] and self.compiler == "fontc": + log.warning("Cannot use --filter with fontc, dropping arguments...") + del vars["args"] return vars + @property + def compiler(self): + return self.original.get( + "compiler", os.environ.get(self.COMPILER_ENV_KEY, "fontmake") + ) + + def validate(self): + if self.static: + if not self.first_source.exists(): + # We can't check this file (assume it was generated as part of the + # build), so user is on their own. + return + if ( + self.first_source.is_glyphs + and len(self.first_source.gsfont.masters) > 1 + ): + raise ValueError( + f"Cannot build a static font from {self.first_source.path}" + ) + if ( + self.first_source.designspace + and len(self.first_source.designspace.sources) > 1 + ): + raise ValueError( + f"Cannot build a static font from {self.first_source.path}" + ) + known_operations = {} diff --git a/Lib/gftools/builder/operations/buildOTF.py b/Lib/gftools/builder/operations/buildOTF.py index 84cb2fc5..0831b312 100644 --- a/Lib/gftools/builder/operations/buildOTF.py +++ b/Lib/gftools/builder/operations/buildOTF.py @@ -3,21 +3,5 @@ class BuildOTF(FontmakeOperationBase): description = "Build a OTF from a source file" - rule = "fontmake --output-path $out -o otf $fontmake_type $in $args" - - def validate(self): - if not self.first_source.exists(): - # We can't check this file (assume it was generated as part of the - # build), so user is on their own. - return - if self.first_source.is_glyphs and len(self.first_source.gsfont.masters) > 1: - raise ValueError( - f"Cannot build a static font from {self.first_source.path}" - ) - if ( - self.first_source.designspace - and len(self.first_source.designspace.sources) > 1 - ): - raise ValueError( - f"Cannot build a static font from {self.first_source.path}" - ) + format = "otf" + static = True diff --git a/Lib/gftools/builder/operations/buildTTF.py b/Lib/gftools/builder/operations/buildTTF.py index 8dc3d727..f86223b9 100644 --- a/Lib/gftools/builder/operations/buildTTF.py +++ b/Lib/gftools/builder/operations/buildTTF.py @@ -3,21 +3,5 @@ class BuildTTF(FontmakeOperationBase): description = "Build a TTF from a source file" - rule = "fontmake --output-path $out -o ttf $fontmake_type $in $args" - - def validate(self): - if not self.first_source.exists(): - # We can't check this file (assume it was generated as part of the - # build), so user is on their own. - return - if self.first_source.is_glyphs and len(self.first_source.gsfont.masters) > 1: - raise ValueError( - f"Cannot build a static font from {self.first_source.path}" - ) - if ( - self.first_source.designspace - and len(self.first_source.designspace.sources) > 1 - ): - raise ValueError( - f"Cannot build a static font from {self.first_source.path}" - ) + static = True + format = "ttf" diff --git a/Lib/gftools/builder/operations/buildVariable.py b/Lib/gftools/builder/operations/buildVariable.py index 63e1be7b..1629a99e 100644 --- a/Lib/gftools/builder/operations/buildVariable.py +++ b/Lib/gftools/builder/operations/buildVariable.py @@ -3,4 +3,5 @@ class BuildVariable(FontmakeOperationBase): description = "Build a variable font from a source file" - rule = "fontmake --output-path $out -o variable $fontmake_type $in $args" + format = "variable" + static = False diff --git a/Lib/gftools/builder/schema.py b/Lib/gftools/builder/schema.py index 64f2b0e1..1487f101 100644 --- a/Lib/gftools/builder/schema.py +++ b/Lib/gftools/builder/schema.py @@ -109,5 +109,6 @@ Optional("extraStaticFontmakeArgs"): Str(), Optional("buildSmallCap"): Bool(), Optional("splitItalic"): Bool(), + Optional("localMetadata"): Any(), } ) diff --git a/docs/gftools-builder/README.md b/docs/gftools-builder/README.md index ec22228d..0d924316 100644 --- a/docs/gftools-builder/README.md +++ b/docs/gftools-builder/README.md @@ -204,6 +204,9 @@ The build can be customized by adding the following keys to the YAML file: subspace them into separate roman and italic VF files to comply with Google Fonts' specification. Defaults to true. +- `localMetadata`: A field that's ignored so you can put whatever you like in it. + + ## *Really* customizing the build process If the options above aren't enough for you - let's say you want to run your