def run_from_designspace(self,
                             designspace_path,
                             interpolate=False,
                             masters_as_instances=False,
                             instance_data=None,
                             interpolate_binary_layout=False,
                             **kwargs):
        """Run toolchain from a MutatorMath design space document.

        Args:
            designspace_path: Path to designspace document.
            interpolate: If True output instance fonts, otherwise just masters.
            masters_as_instances: If True, output master fonts as instances.
            instance_data: Data to be applied to instance UFOs, as returned from
                glyphsLib's parsing function (ignored unless interpolate is True).
            interpolate_binary_layout: Interpolate layout tables from compiled
                master binaries.
            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 import build as build_designspace
        from mutatorMath.ufo.document import DesignSpaceDocumentReader

        ufos = []
        if not interpolate or masters_as_instances:
            reader = DesignSpaceDocumentReader(designspace_path, ufoVersion=3)
            ufos.extend(reader.getSourcePaths())
        if interpolate:
            logger.info('Interpolating master UFOs from designspace')
            results = build_designspace(designspace_path,
                                        outputUFOFormatVersion=3)
            if instance_data is not None:
                ufos.extend(apply_instance_data(instance_data))
            else:
                for result in results:
                    ufos.extend(result.values())

        interpolate_layout_from = (designspace_path
                                   if interpolate_binary_layout else None)

        self.run_from_ufos(ufos,
                           designspace_path=designspace_path,
                           is_instance=(interpolate or masters_as_instances),
                           interpolate_layout_from=interpolate_layout_from,
                           **kwargs)
Beispiel #2
0
    def run_from_designspace(self,
                             designspace_path,
                             interpolate=False,
                             masters_as_instances=False,
                             instance_data=None,
                             interpolate_binary_layout=False,
                             **kwargs):
        """Run toolchain from a MutatorMath design space document.

        Args:
            designspace_path: Path to designspace document.
            interpolate: If True output instance fonts, otherwise just masters.
            masters_as_instances: If True, output master fonts as instances.
            instance_data: Data to be applied to instance UFOs, as returned from
                glyphsLib's parsing function.
            interpolate_binary_layout: Interpolate layout tables from compiled
                master binaries.
            kwargs: Arguments passed along to run_from_ufos.
        """

        from glyphsLib.interpolation import apply_instance_data
        from mutatorMath.ufo import build as build_designspace
        from mutatorMath.ufo.document import DesignSpaceDocumentReader

        ufos = []
        if not interpolate or masters_as_instances:
            reader = DesignSpaceDocumentReader(designspace_path, ufoVersion=3)
            ufos.extend(reader.getSourcePaths())
        if interpolate:
            logger.info('Interpolating master UFOs from designspace')
            results = build_designspace(designspace_path,
                                        outputUFOFormatVersion=3)
            if instance_data is not None:
                ufos.extend(apply_instance_data(instance_data))
            else:
                for result in results:
                    ufos.extend(result.values())

        interpolate_layout_from = (designspace_path
                                   if interpolate_binary_layout else None)

        self.run_from_ufos(ufos,
                           designspace_path=designspace_path,
                           is_instance=(interpolate or masters_as_instances),
                           interpolate_layout_from=interpolate_layout_from,
                           **kwargs)
Beispiel #3
0
    def interpolate_instance_ufos(self,
                                  designspace,
                                  include=None,
                                  round_instances=False):
        """Interpolate master UFOs with MutatorMath and return instance UFOs.

        Args:
            designspace: a DesignSpaceDocument object containing sources and
                instances.
            include (str): optional regular expression pattern to match the
                DS instance 'name' attribute and only interpolate the matching
                instances.
            round_instances (bool): round instances' coordinates to integer.
        Returns:
            list of defcon.Font objects corresponding to the UFO instances.
        Raises:
            FontmakeError: if any of the sources defines a custom 'layer', for
                this is not supported by MutatorMath.
        """
        from glyphsLib.interpolation import apply_instance_data
        from mutatorMath.ufo.document import DesignSpaceDocumentReader

        if any(source.layerName is not None for source in designspace.sources):
            raise FontmakeError(
                "MutatorMath doesn't support DesignSpace sources with 'layer' "
                "attribute")

        # TODO: replace mutatorMath with ufoProcessor?
        builder = DesignSpaceDocumentReader(designspace.path,
                                            ufoVersion=3,
                                            roundGeometry=round_instances,
                                            verbose=True)
        logger.info("Interpolating master UFOs from designspace")
        if include is not None:
            instances = self._search_instances(designspace, pattern=include)
            for instance_name in instances:
                builder.readInstance(("name", instance_name))
            filenames = set(instances.values())
        else:
            builder.readInstances()
            filenames = None  # will include all instances
        logger.info("Applying instance data from designspace")
        instance_ufos = apply_instance_data(designspace,
                                            include_filenames=filenames)
        return instance_ufos
Beispiel #4
0
    def run_from_designspace(
            self, designspace_path, interpolate=False,
            masters_as_instances=False, instance_data=None,
            interpolate_binary_layout=False, **kwargs):
        """Run toolchain from a MutatorMath design space document.

        Args:
            designspace_path: Path to designspace document.
            interpolate: If True output instance fonts, otherwise just masters.
            masters_as_instances: If True, output master fonts as instances.
            instance_data: Data to be applied to instance UFOs, as returned from
                glyphsLib's parsing function.
            interpolate_binary_layout: Interpolate layout tables from compiled
                master binaries.
            kwargs: Arguments passed along to run_from_ufos.
        """

        from glyphsLib.interpolation import apply_instance_data
        from mutatorMath.ufo import build as build_designspace
        from mutatorMath.ufo.document import DesignSpaceDocumentReader

        ufos = []
        if not interpolate or masters_as_instances:
            reader = DesignSpaceDocumentReader(designspace_path, ufoVersion=3)
            ufos.extend(reader.getSourcePaths())
        if interpolate:
            self.info('Interpolating master UFOs from designspace')
            results = build_designspace(
                designspace_path, outputUFOFormatVersion=3)
            if instance_data is not None:
                ufos.extend(apply_instance_data(instance_data))
            else:
                for result in results:
                    ufos.extend(result.values())

        interpolate_layout_from = (
            designspace_path if interpolate_binary_layout else None)

        self.run_from_ufos(
            ufos, designspace_path=designspace_path,
            is_instance=(interpolate or masters_as_instances),
            interpolate_layout_from=interpolate_layout_from, **kwargs)
Beispiel #5
0
    def run_from_designspace(
            self, designspace_path, interpolate=False,
            masters_as_instances=False, instance_data=None, **kwargs):
        """Run toolchain from a MutatorMath design space document to OpenType
        binaries.
        """
        from glyphsLib.interpolation import apply_instance_data
        from mutatorMath.ufo import build as build_designspace
        from mutatorMath.ufo.document import DesignSpaceDocumentReader

        ufos = []
        if not interpolate or masters_as_instances:
            reader = DesignSpaceDocumentReader(designspace_path, ufoVersion=3)
            ufos.extend(reader.getSourcePaths())
        if interpolate:
            print('>> Interpolating master UFOs from design space')
            results = build_designspace(
                designspace_path, outputUFOFormatVersion=3)
            for result in results:
                if instance_data is not None:
                    ufos.extend(apply_instance_data(instance_data))
        self.run_from_ufos(
            ufos, designspace_path=designspace_path,
            is_instance=(interpolate or masters_as_instances), **kwargs)
Beispiel #6
0
    def interpolate_instance_ufos_mutatormath(
        self,
        designspace,
        include=None,
        round_instances=False,
        expand_features_to_instances=False,
    ):
        """Interpolate master UFOs with MutatorMath and return instance UFOs.

        Args:
            designspace: a DesignSpaceDocument object containing sources and
                instances.
            include (str): optional regular expression pattern to match the
                DS instance 'name' attribute and only interpolate the matching
                instances.
            round_instances (bool): round instances' coordinates to integer.
            expand_features_to_instances: parses the master feature file, expands all
                include()s and writes the resulting full feature file to all instance
                UFOs. Use this if you share feature files among masters in external
                files. Otherwise, the relative include paths can break as instances
                may end up elsewhere. Only done on interpolation.
        Returns:
            list of defcon.Font objects corresponding to the UFO instances.
        Raises:
            FontmakeError: if any of the sources defines a custom 'layer', for
                this is not supported by MutatorMath.
            ValueError: "expand_features_to_instances" is True but no source in the
                designspace document is designated with '<features copy="1"/>'.
        """
        from glyphsLib.interpolation import apply_instance_data
        from mutatorMath.ufo.document import DesignSpaceDocumentReader

        if any(source.layerName is not None for source in designspace.sources):
            raise FontmakeError(
                "MutatorMath doesn't support DesignSpace sources with 'layer' "
                "attribute")

        with temporarily_disabling_axis_maps(
                designspace.path) as temp_designspace_path:
            builder = DesignSpaceDocumentReader(
                temp_designspace_path,
                ufoVersion=3,
                roundGeometry=round_instances,
                verbose=True,
            )
            logger.info("Interpolating master UFOs from designspace")
            if include is not None:
                instances = self._search_instances(designspace,
                                                   pattern=include)
                for instance_name in instances:
                    builder.readInstance(("name", instance_name))
                filenames = set(instances.values())
            else:
                builder.readInstances()
                filenames = None  # will include all instances

        logger.info("Applying instance data from designspace")
        instance_ufos = apply_instance_data(designspace,
                                            include_filenames=filenames)

        if expand_features_to_instances:
            logger.debug("Expanding features to instance UFOs")
            master_source = next(
                (s for s in designspace.sources if s.copyFeatures), None)
            if not master_source:
                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()
                for instance_ufo in instance_ufos:
                    instance_ufo.features.text = master_source_features
                    instance_ufo.save()

        return instance_ufos
Beispiel #7
0
    def run_from_designspace(self,
                             designspace_path,
                             interpolate=False,
                             masters_as_instances=False,
                             interpolate_binary_layout=False,
                             round_instances=False,
                             **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

        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_path,
                                                   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,
                           **kwargs)
Beispiel #8
0
    def run_from_designspace(self,
                             designspace_path,
                             interpolate=False,
                             masters_as_instances=False,
                             instance_data=None,
                             interpolate_binary_layout=False,
                             round_instances=False,
                             **kwargs):
        """Run toolchain from a MutatorMath design space document.

        Args:
            designspace_path: Path to designspace document.
            interpolate: If True output instance fonts, otherwise just masters.
            masters_as_instances: If True, output master fonts as instances.
            instance_data: Data to be applied to instance UFOs, as returned from
                glyphsLib's parsing function (ignored unless interpolate is True).
            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 import build as build_designspace
        from mutatorMath.ufo.document import DesignSpaceDocumentReader

        ufos = []
        if not interpolate or masters_as_instances:
            reader = DesignSpaceDocumentReader(designspace_path, ufoVersion=3)
            ufos.extend(reader.getSourcePaths())
        if interpolate:
            logger.info('Interpolating master UFOs from designspace')
            _, ilocs = self._designspace_locations(designspace_path)
            for ipath in ilocs.keys():
                # mutatorMath does not remove the existing instance UFOs
                # so we do it ourselves, or else strange things happen...
                # https://github.com/googlei18n/fontmake/issues/372
                if ipath.endswith(".ufo") and os.path.isdir(ipath):
                    logger.debug("Removing %s" % ipath)
                    shutil.rmtree(ipath)
            results = build_designspace(designspace_path,
                                        outputUFOFormatVersion=3,
                                        roundGeometry=round_instances)
            if instance_data is not None:
                ufos.extend(apply_instance_data(instance_data))
            else:
                for result in results:
                    ufos.extend(result.values())

        interpolate_layout_from = (designspace_path
                                   if interpolate_binary_layout else None)

        self.run_from_ufos(ufos,
                           designspace_path=designspace_path,
                           is_instance=(interpolate or masters_as_instances),
                           interpolate_layout_from=interpolate_layout_from,
                           **kwargs)