diff --git a/Lib/gftools/builder/__init__.py b/Lib/gftools/builder/__init__.py index afdb9f20..36ead286 100644 --- a/Lib/gftools/builder/__init__.py +++ b/Lib/gftools/builder/__init__.py @@ -17,7 +17,7 @@ from ninja.ninja_syntax import Writer, escape_path from gftools.builder.file import File -from gftools.builder.operations import OperationBase, known_operations +from gftools.builder.operations import OperationBase, OperationRegistry from gftools.builder.operations.copy import Copy from gftools.builder.recipeproviders import get_provider from gftools.builder.schema import BASE_SCHEMA @@ -36,7 +36,7 @@ class GFBuilder: config: dict recipe: Recipe - def __init__(self, config: Union[dict, str]): + def __init__(self, config: Union[dict, str], use_fontc = False): if isinstance(config, str): parentpath = Path(config).resolve().parent with open(config, "r") as file: @@ -55,6 +55,7 @@ def __init__(self, config: Union[dict, str]): self._orig_config = yaml.dump(config) self.config = config + self.known_operations = OperationRegistry(use_fontc=use_fontc) self.writer = Writer(open("build.ninja", "w")) self.named_files = {} self.used_operations = set([]) @@ -156,9 +157,10 @@ def glyphs_to_ufo(self, source): def operation_step_to_object(self, step): operation = step.get("operation") or step.get("postprocess") - if operation not in known_operations: + cls = self.known_operations.get(operation) + if cls is None: raise ValueError(f"Unknown operation {operation}") - cls = known_operations[operation] + if operation not in self.used_operations: self.used_operations.add(operation) cls.write_rules(self.writer) @@ -381,6 +383,12 @@ def main(args=None): help="Just generate and output recipe from recipe builder", action="store_true", ) + parser.add_argument( + "--experimental-fontc", + help="Use fontc instead of fontmake", + action="store_true", + ) + parser.add_argument("config", help="Path to config file or source file", nargs="+") args = parser.parse_args(args) yaml_files = [] @@ -404,7 +412,7 @@ def main(args=None): raise ValueError("Only one config file can be given for now") config = args.config[0] - pd = GFBuilder(config) + pd = GFBuilder(config, use_fontc = args.experimental_fontc) if args.generate: config = pd.config config["recipe"] = pd.recipe diff --git a/Lib/gftools/builder/operations/__init__.py b/Lib/gftools/builder/operations/__init__.py index 0b033073..8d543b64 100644 --- a/Lib/gftools/builder/operations/__init__.py +++ b/Lib/gftools/builder/operations/__init__.py @@ -8,7 +8,9 @@ import sys from os.path import dirname from tempfile import NamedTemporaryFile +from typing import Dict +# from gftools.builder.operations.fontc import FontcBuildTTF, FontcBuildVariable from gftools.builder.file import File from gftools.utils import shell_quote @@ -149,18 +151,42 @@ def variables(self): return vars - -known_operations = {} - -for mod in pkgutil.iter_modules([dirname(__file__)]): - imp = importlib.import_module("gftools.builder.operations." + mod.name) - classes = [ - (name, cls) - for name, cls in inspect.getmembers(sys.modules[imp.__name__], inspect.isclass) - if "OperationBase" not in name and issubclass(cls, OperationBase) - ] - if len(classes) > 1: - raise ValueError( - f"Too many classes in module gftools.builder.operations.{mod.name}" - ) - known_operations[mod.name] = classes[0][1] +# just pretend these live elsewhere, here now for illustration +class FontcBuildVariable(OperationBase): + description = "Build a variable font from a source file (with fontc)" + rule = "fontc -o $out $in" + +class FontcBuildTTF(OperationBase): + description = "Build a TTF from a source file (with fontc)" + rule = "fontc -o $out $in" + +class OperationRegistry: + def __init__(self, use_fontc: bool): + self.known_operations = get_known_operations() + if use_fontc: + self.known_operations["buildVariable"] = FontcBuildVariable + self.known_operations["buildTTF"] = FontcBuildTTF + print(self.known_operations, file=sys.stderr) + + def get(self, operation_name: str): + return self.known_operations.get(operation_name) + + +def get_known_operations() -> Dict[str, OperationBase]: + known_operations = {} + + for mod in pkgutil.iter_modules([dirname(__file__)]): + if "fontc" in mod.name: + continue + imp = importlib.import_module("gftools.builder.operations." + mod.name) + classes = [ + (name, cls) + for name, cls in inspect.getmembers(sys.modules[imp.__name__], inspect.isclass) + if "OperationBase" not in name and issubclass(cls, OperationBase) + ] + if len(classes) > 1: + raise ValueError( + f"Too many classes in module gftools.builder.operations.{mod.name}" + ) + known_operations[mod.name] = classes[0][1] + return known_operations