def test_apply_instance_data(tmpdir, instance_names):
    font = glyphsLib.GSFont(TESTFILE_PATH)
    instance_dir = "instances"
    designspace = glyphsLib.to_designspace(font, instance_dir=instance_dir)
    path = str(tmpdir / (font.familyName + '.designspace'))
    write_designspace_and_UFOs(designspace, path)
    builder = DesignSpaceDocumentReader(designspace.path, ufoVersion=3)
    if instance_names is None:
        # generate all instances
        builder.process()
        include_filenames = None
    else:
        # generate only selected instances
        for name in instance_names:
            builder.readInstance(("stylename", name))
        # make relative filenames from paths returned by MutatorMath
        include_filenames = {os.path.relpath(instance_path, str(tmpdir))
                             for instance_path in builder.results.values()}

    ufos = apply_instance_data(designspace.path,
                               include_filenames=include_filenames)

    for filename in include_filenames or ():
        assert os.path.isdir(str(tmpdir / filename))
    assert len(ufos) == len(builder.results)
    assert isinstance(ufos[0], defcon.Font)
Exemplo n.º 2
0
def _save_gsfont(font):
    f = glyphsLib.GSFont()
    f.familyName = font.info.familyName
    if "com.schriftgestaltung.appVersion" in font.lib:
        f.appVersion = font.lib["com.schriftgestaltung.appVersion"]
    if "com.schriftgestaltung.DisplayStrings" in font.lib:
        f.DisplayStrings = font.lib["com.schriftgestaltung.DisplayStrings"]
    if font.info.openTypeHeadCreated:
        f.date = _ufo_date_to_glyphs(font.info.openTypeHeadCreated)
    f.upm = font.info.unitsPerEm
    fontmaster = glyphsLib.GSFontMaster()
    if "com.schriftgestaltung.fontMasterID" in font.lib:
        fontmaster.id = font.lib["com.schriftgestaltung.fontMasterID"]

    f.masters = [fontmaster]
    # f.instances = [glyphsLib.GSInstance()]
    # f.instances[0].instanceInterpolations = {}
    fontmaster.ascender = font.info.ascender
    fontmaster.xHeight = font.info.xHeight
    fontmaster.capHeight = font.info.capHeight
    fontmaster.descender = font.info.descender
    for glyph in font.defaultLayer:
        _save_glyph(glyph, f, bbf=font)
    for g in font.groups:
        if "public.kern" in g:
            continue
        f.classes.append(glyphsLib.GSClass(g, " ".join(font.groups[g])))
    _save_kerning(font.kerning, f, fontmaster.id)
    return f
 def notExportedGlyphs(self):
     notExportedGlyphsList = []
     GSft = glyphsLib.GSFont(self.sourcePath)
     for g in GSft.glyphs:
         if g.export is False:
             notExportedGlyphsList.append(g.name)
     return notExportedGlyphsList
Exemplo n.º 4
0
def test_background_component_decompose(datadir):
    font = glyphsLib.GSFont(str(datadir.join("Recursion.glyphs")))
    ds = to_designspace(font)

    for source in ds.sources:
        for layer in source.font.layers:
            for glyph in layer:
                if layer.name == "Apr 27 20, 17:59" and glyph.name == "B":
                    continue
                assert not glyph.components

    ufo_rg = ds.sources[0].font
    assert ufo_rg.layers["public.background"]["A"].contours == ufo_rg[
        "B"].contours
    assert (ufo_rg.layers["Apr 27 20, 17:57.background"]["A"].contours ==
            ufo_rg["B"].contours)
    assert ufo_rg.layers["public.background"]["B"].contours == ufo_rg[
        "A"].contours
    assert len(ufo_rg.layers["Apr 27 20, 17:59.background"]["B"].contours) == 2

    assert ufo_rg.layers["Apr 27 20, 17:59"]["B"].components

    ufo_bd = ds.sources[1].font
    assert ufo_bd.layers["public.background"]["A"].contours == ufo_bd[
        "B"].contours
    assert (ufo_bd.layers["Apr 27 20, 17:57.background"]["A"].contours ==
            ufo_bd["B"].contours)
    assert ufo_bd.layers["public.background"]["B"].contours == ufo_bd[
        "A"].contours
    assert (ufo_bd.layers["Apr 27 20, 17:59.background"]["B"].contours ==
            ufo_bd["A"].contours)
Exemplo n.º 5
0
def main():
    parser = argparse.ArgumentParser(
        "Translate all .glyphs files into UFO+designspace in the specified directories."
    )
    parser.add_argument(
        "-o", "--out", metavar="OUTPUT_DIR", default="ufos", help="Output directory"
    )
    parser.add_argument("directories", nargs="*")
    args = parser.parse_args()

    for directory in args.directories:
        files = glyphs_files(directory)
        for filename in files:
            try:
                # Code for glyphsLib with roundtrip
                from glyphsLib.builder import to_designspace

                font = glyphsLib.GSFont(filename)
                designspace = to_designspace(font)
                dsname = font.familyName.replace(" ", "") + ".designspace"
                designspace.write(os.path.join(args.out, dsname))
            except ImportError:
                # This is the version that works with glyphsLib 2.1.0
                glyphsLib.build_masters(
                    filename, master_dir=args.out, designspace_instance_dir=args.out
                )
Exemplo n.º 6
0
    def build_master_ufos(
        self,
        glyphs_path,
        designspace_path=None,
        master_dir=None,
        instance_dir=None,
        family_name=None,
        mti_source=None,
        write_skipexportglyphs=True,
    ):
        """Build UFOs and MutatorMath designspace from Glyphs source."""
        import glyphsLib

        if master_dir is None:
            master_dir = self._output_dir("ufo")
        if not os.path.isdir(master_dir):
            os.mkdir(master_dir)
        if instance_dir is None:
            instance_dir = self._output_dir("ufo", is_instance=True)
        if not os.path.isdir(instance_dir):
            os.mkdir(instance_dir)

        font = glyphsLib.GSFont(glyphs_path)

        if designspace_path is not None:
            designspace_dir = os.path.dirname(designspace_path)
        else:
            designspace_dir = master_dir
        # glyphsLib.to_designspace expects instance_dir to be relative
        instance_dir = os.path.relpath(instance_dir, designspace_dir)

        designspace = glyphsLib.to_designspace(
            font,
            family_name=family_name,
            instance_dir=instance_dir,
            write_skipexportglyphs=write_skipexportglyphs,
        )

        masters = {}
        # multiple sources can have the same font/filename (but different layer),
        # we want to save a font only once
        for source in designspace.sources:
            if source.filename in masters:
                assert source.font is masters[source.filename]
                continue
            ufo_path = os.path.join(master_dir, source.filename)
            # no need to also set the relative 'filename' attribute as that
            # will be auto-updated on writing the designspace document
            source.path = ufo_path
            source.font.save(ufo_path)
            masters[source.filename] = source.font

        if designspace_path is None:
            designspace_path = os.path.join(master_dir, designspace.filename)
        designspace.write(designspace_path)
        if mti_source:
            self.add_mti_features_to_master_ufos(mti_source, masters.values())
        return designspace_path
Exemplo n.º 7
0
def test_background_component_decompose_missing(datadir):
    font = glyphsLib.GSFont(str(datadir.join("Recursion.glyphs")))

    layer = font.glyphs["B"].layers[
        "DB4D7D04-C02D-48DE-811E-03AA03052DD2"].background
    layer.components.append(GSComponent("xxx"))

    with pytest.raises(MissingComponentError):
        to_designspace(font)
Exemplo n.º 8
0
def test_ufo_filename_custom_param_plus_legacy():
    """Test that new-style UFO_FILENAME_CUSTOM_PARAM overrides legacy
    (UFO_FILENAME_KEY|FULL_FILENAME_KEY)."""
    font = glyphsLib.GSFont(os.path.join(DATA, "UFOFilenameTest.glyphs"))
    font.masters[0].customParameters[UFO_FILENAME_CUSTOM_PARAM] = "aaa.ufo"
    font.instances[0].customParameters[UFO_FILENAME_CUSTOM_PARAM] = "bbb.ufo"

    ds = glyphsLib.to_designspace(font, minimize_glyphs_diffs=True)
    assert ds.sources[0].filename == "aaa.ufo"
    assert ds.instances[0].filename == "bbb.ufo"
Exemplo n.º 9
0
def test_ufo_filename_custom_param_instance_empty():
    font = glyphsLib.GSFont(os.path.join(DATA, "UFOFilenameTest.glyphs"))
    font.masters[0].customParameters[UFO_FILENAME_CUSTOM_PARAM] = "aaa.ufo"
    del font.instances[0].customParameters[UFO_FILENAME_CUSTOM_PARAM]
    del font.instances[0].customParameters[FULL_FILENAME_KEY]

    ds = glyphsLib.to_designspace(font, minimize_glyphs_diffs=True)
    assert ds.sources[0].filename == "aaa.ufo"
    # Instance filename should be whatever the default is.
    assert ds.instances[0].filename == "instance_ufos/NewFont-Regular.ufo"
Exemplo n.º 10
0
def load(filename, **kwargs):
    gsfont = glyphsLib.GSFont(filename)
    gsmaster = None
    if "master" not in kwargs or not kwargs["master"]:
        gsmaster = gsfont.masters[0]
    else:
        wanted = kwargs["master"]
        for m in gsfont.masters:
            if m.name == wanted:
                gsmaster = m
                break
        if not gsmaster:
            raise ValueError(f"Master {wanted} not found in {filename}")
    return _load_gsfont(gsmaster)
Exemplo n.º 11
0
 def load_masters(self):
     if self.masters:
         return
     for src in self.config["sources"]:
         if src.endswith("glyphs"):
             gsfont = glyphsLib.GSFont(src)
             self.masters[src] = []
             for master in gsfont.masters:
                 self.masters[src].append(
                     Babelfont.open(src, master=master.name))
         elif src.endswith("designspace"):
             continue
         else:
             self.masters[src] = [Babelfont.open(src)]
Exemplo n.º 12
0
    def build_master_ufos(self,
                          glyphs_path,
                          designspace_path=None,
                          master_dir=None,
                          instance_dir=None,
                          family_name=None,
                          mti_source=None):
        """Build UFOs and MutatorMath designspace from Glyphs source."""
        import glyphsLib

        if master_dir is None:
            master_dir = self._output_dir('ufo')
        if not os.path.isdir(master_dir):
            os.mkdir(master_dir)
        if instance_dir is None:
            instance_dir = self._output_dir('ufo', is_instance=True)
        if not os.path.isdir(instance_dir):
            os.mkdir(instance_dir)

        font = glyphsLib.GSFont(glyphs_path)

        if designspace_path is not None:
            designspace_dir = os.path.dirname(designspace_path)
        else:
            designspace_dir = master_dir
        # glyphsLib.to_designspace expects instance_dir to be relative
        instance_dir = os.path.relpath(instance_dir, designspace_dir)

        designspace = glyphsLib.to_designspace(font,
                                               family_name=family_name,
                                               instance_dir=instance_dir)

        masters = []
        for source in designspace.sources:
            masters.append(source.font)
            ufo_path = os.path.join(master_dir, source.filename)
            # no need to also set the relative 'filename' attribute as that
            # will be auto-updated on writing the designspace document
            source.path = ufo_path
            source.font.save(ufo_path)

        if designspace_path is None:
            designspace_path = os.path.join(master_dir, designspace.filename)
        designspace.write(designspace_path)
        if mti_source:
            self.add_mti_features_to_master_ufos(mti_source, masters)
        return designspace_path
Exemplo n.º 13
0
def test_apply_instance_data(tmpdir, instance_names, ufo_module):
    font = glyphsLib.GSFont(os.path.join(DATA, "GlyphsUnitTestSans.glyphs"))
    instance_dir = "instances"
    designspace = glyphsLib.to_designspace(font, instance_dir=instance_dir)
    path = str(tmpdir / (font.familyName + ".designspace"))
    write_designspace_and_UFOs(designspace, path)

    test_designspace = DesignSpaceDocument()
    test_designspace.read(designspace.path)
    if instance_names is None:
        # Collect all instances.
        test_instances = [instance.filename for instance in test_designspace.instances]
    else:
        # Collect only selected instances.
        test_instances = [
            instance.filename
            for instance in test_designspace.instances
            if instance.styleName in instance_names
        ]

    # Generate dummy UFOs for collected instances so we don't actually need to
    # interpolate.
    tmpdir.mkdir(instance_dir)
    for instance in test_instances:
        ufo = ufo_module.Font()
        ufo.save(str(tmpdir / instance))

    ufos = apply_instance_data(designspace.path, include_filenames=test_instances)

    for filename in test_instances:
        assert os.path.isdir(str(tmpdir / filename))
    assert len(ufos) == len(test_instances)

    for ufo in ufos:
        assert ufo.info.openTypeOS2WeightClass in {
            100,
            200,
            300,
            400,
            500,
            700,
            900,
            357,
        }
        assert ufo.info.openTypeOS2WidthClass is None  # GlyphsUnitTestSans is wght only
Exemplo n.º 14
0
def test_glyphs_font_without_propagated_anchors(datadir):

    font = glyphsLib.GSFont(str(datadir.join("AnchorPropagation.glyphs")))

    # These two layers are supposed to be devoid of anchors in the .glyphs source
    # with Glyphs.app expecting to propagate them automatically upon font generation
    assert len(font.glyphs["lam_alefHamzaabove-ar"].layers[0].anchors) == 0
    assert len(font.glyphs["shadda_fatha-ar"].layers[0].anchors) == 0

    # check for `top_1` anchor of lam_alef-ar.short to be in its original location
    layer = font.glyphs["lam_alef-ar.short"].layers[0]
    assert "top_1" in [x.name for x in layer.anchors]
    assert layer.anchors["top_1"].position.x == 498
    assert layer.anchors["top_1"].position.y == 760

    # check for `top_2` anchor of lam_alef-ar.short to be in its original location
    layer = font.glyphs["lam_alef-ar.short"].layers[0]
    assert "top_2" in [x.name for x in layer.anchors]
    assert layer.anchors["top_2"].position.x == 130
    assert layer.anchors["top_2"].position.y == 628
Exemplo n.º 15
0
def test_gslayer_load():
    testfile = glyphsLib.GSFont("tests/data/Test1.glyphs")
    a = testfile.glyphs[0].layers[0]
    a_layer = glyphs._load_gslayer(a, None)
    assert isinstance(a_layer, Glyph)
    assert len(a_layer.contours) == 2
    assert len(a_layer.contours[0].points) == 8
    assert len(a_layer.contours[1].points) == 4
    assert a_layer.contours[0].points[0].x == 345
    assert a_layer.contours[0].points[0].y == 700
    assert a_layer.leftMargin == 25
    assert a_layer.rightMargin == 25
    assert a_layer.bounds == (25, 0, 505, 700)
    assert a_layer.width == 530

    b = testfile.glyphs[1].layers[0]
    b_layer = glyphs._load_gslayer(b, None)
    assert isinstance(b_layer, Glyph)
    assert len(b_layer.contours) == 3
    assert b_layer.leftMargin == 65
    assert b_layer.rightMargin == 35
Exemplo n.º 16
0
    def get_family_name(self):
        """Ensure that all source files have the same family name"""
        names = set()
        for fp in self.config["sources"]:
            if fp.endswith("glyphs"):
                src = glyphsLib.GSFont(fp)
                names.add(src.familyName)
            elif fp.endswith("ufo"):
                src = Font(fp)
                names.add(src.info.familyName)
            elif fp.endswith("designspace"):
                ds = designspaceLib.DesignSpaceDocument.fromfile(
                    self.config["sources"][0])
                names.add(ds.sources[0].familyName)
            else:
                raise ValueError(f"{fp} not a supported source file!")

        if len(names) > 1:
            raise ValueError(
                f"Inconsistent family names in sources {names}. Set familyName in config instead"
            )
        return list(names)[0]
Exemplo n.º 17
0
def test_ufo_filename_custom_param():
    """Test that new-style UFO_FILENAME_CUSTOM_PARAM is written instead of
    (UFO_FILENAME_KEY|FULL_FILENAME_KEY)."""
    font = glyphsLib.GSFont(os.path.join(DATA, "UFOFilenameTest.glyphs"))
    ds = glyphsLib.to_designspace(font, minimize_glyphs_diffs=True)
    assert ds.sources[0].filename == "MyFontMaster.ufo"
    assert ds.instances[0].filename == "../build/instance_ufos/MyFont.ufo"
    assert "com.schriftgestaltung.customParameters" not in ds.instances[0].lib

    font_rt = glyphsLib.to_glyphs(ds, minimize_ufo_diffs=True)
    assert (
        font_rt.masters[0].customParameters[UFO_FILENAME_CUSTOM_PARAM]
        == "MyFontMaster.ufo"
    )
    assert UFO_FILENAME_KEY not in font_rt.masters[0].userData
    assert (
        font_rt.instances[0].customParameters[UFO_FILENAME_CUSTOM_PARAM]
        == "../build/instance_ufos/MyFont.ufo"
    )
    assert FULL_FILENAME_KEY not in font_rt.instances[0].customParameters

    ds_rt = glyphsLib.to_designspace(font_rt, minimize_glyphs_diffs=True)
    assert ds_rt.sources[0].filename == "MyFontMaster.ufo"
    assert ds_rt.instances[0].filename == "../build/instance_ufos/MyFont.ufo"
Exemplo n.º 18
0
import glyphsLib
import sys

font = glyphsLib.GSFont(sys.argv[-2])
for instance in font.instances:
    for parameter in instance.customParameters:
        if parameter.name == "Export COLR Table":
            parameter.value = 1

font.familyName += " Play"

font.save(sys.argv[-1])
Exemplo n.º 19
0
import glyphsLib
import importlib
import argparse
import sys
from glob import glob

parser = argparse.ArgumentParser(description='Filter a font file')
parser.add_argument('input', metavar='GLYPHS', help='the Glyphs file')
parser.add_argument('filter', metavar='FILTER', help='the filter to use')
args = parser.parse_args()

base_path = "NaNGlyphFilters"
sys.path.append(base_path)
glyphsLib.Glyphs.font = glyphsLib.GSFont(args.input)
filter_script = args.filter

sys.modules['GlyphsApp'] = glyphsLib

try:
    i = importlib.import_module(filter_script)
except ModuleNotFoundError as e:
    modules = [
        x[len(base_path) + 1:-3] for x in sorted(glob(base_path + "/*.py"))
        if "/NaN" not in x
    ]
    print("Couldn't find filter '%s'.\nTry one of: %s" %
          (filter_script, ", ".join(modules)))
    sys.exit(1)

save_file = args.input.replace(".glyphs", "-" + filter_script + ".glyphs")
glyphsLib.Glyphs.font.save(save_file)
Exemplo n.º 20
0
    def build_master_ufos(
        self,
        glyphs_path,
        designspace_path=None,
        master_dir=None,
        instance_dir=None,
        family_name=None,
        mti_source=None,
        write_skipexportglyphs=True,
        generate_GDEF=True,
    ):
        """Build UFOs and MutatorMath designspace from Glyphs source."""
        import glyphsLib

        if master_dir is None:
            master_dir = self._output_dir("ufo")
        if not os.path.isdir(master_dir):
            os.mkdir(master_dir)
        if instance_dir is None:
            instance_dir = self._output_dir("ufo", is_instance=True)

        if designspace_path is not None:
            designspace_dir = os.path.dirname(designspace_path)
        else:
            designspace_dir = master_dir
        # glyphsLib.to_designspace expects instance_dir to be relative to the
        # designspace's own directory
        try:
            instance_dir = os.path.relpath(instance_dir, designspace_dir)
        except ValueError as e:
            raise FontmakeError(
                "Can't make instance_dir path relative to designspace. "
                "If on Windows, please make sure that --instance-dir, "
                "--master-dir and --designspace-path are on the same mount drive "
                "(e.g. C: or D:)",
                glyphs_path,
            ) from e

        try:
            font = glyphsLib.GSFont(glyphs_path)
        except Exception as e:
            raise FontmakeError("Loading Glyphs file failed", glyphs_path) from e

        designspace = glyphsLib.to_designspace(
            font,
            family_name=family_name,
            instance_dir=instance_dir,
            write_skipexportglyphs=write_skipexportglyphs,
            ufo_module=ufoLib2,
            generate_GDEF=generate_GDEF,
            store_editor_state=False,
            minimal=True,
        )

        masters = {}
        # multiple sources can have the same font/filename (but different layer),
        # we want to save a font only once
        for source in designspace.sources:
            if source.path in masters:
                assert source.font is masters[source.path]
                continue
            ufo_path = os.path.join(master_dir, source.filename)
            # no need to also set the relative 'filename' attribute as that
            # will be auto-updated on writing the designspace document
            source.path = ufo_path
            masters[ufo_path] = source.font

        if designspace_path is None:
            designspace_path = os.path.join(master_dir, designspace.filename)
        designspace.write(designspace_path)
        if mti_source:
            self.add_mti_features_to_master_ufos(mti_source, masters)

        for ufo_path, ufo in masters.items():
            self.save_ufo_as(ufo, ufo_path)

        return designspace_path