Exemple #1
0
    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
Exemple #2
0
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)
Exemple #3
0
    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,
            )
Exemple #4
0
    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)