def test_designspace_generation_bracket_composite_glyph(datadir):
    with open(str(datadir.join("BracketTestFont2.glyphs"))) as f:
        font = glyphsLib.load(f)

    g = font.glyphs["B"]
    for layer in g.layers:
        assert layer.components[0].name == "A"

    designspace = to_designspace(font)

    for source in designspace.sources:
        ufo = source.font
        assert "B.BRACKET.600" in ufo
        assert ufo["B"].components[0].baseGlyph == "A"
        assert ufo["B.BRACKET.600"].components[0].baseGlyph == "A.BRACKET.600"

    font_rt = to_glyphs(designspace)

    assert "B" in font_rt.glyphs

    g2 = font_rt.glyphs["B"]
    for layer in g2.layers:
        assert layer.components[0].name == "A"

    assert "B.BRACKET.600" not in font_rt.glyphs
def find_mm_compatible_glyphs_files(path):
    """Find .glyphs file which can be generated into variable fonts.

    The criterea is a file which contains 2 masters with more than 3
    instances"""
    families = []
    for root, dirs, files in os.walk(path, topdown=False):
        for f in files:
            if '.glyphs' in f and basename(root) in SOURCE_FOLDERS:
                glyphs_path = os.path.join(root, f)
                try:
                    with open(glyphs_path, 'rb') as glyphs_file:
                        glyphs_source = glyphsLib.load(glyphs_file)

                        master_count = len(glyphs_source['fontMaster'])
                        instance_count = len(glyphs_source['instances'])
                        # Get fonts which successfully use MM
                        if master_count >= 2 and instance_count >= 3 and \
                            master_count != instance_count:
                            print 'Adding: %s' % root
                            families.append(glyphs_path)
                except:  # TODO error log and catch these exceptions betters
                    print 'Cannot add %s' % f
                    all
    return families
def test_designspace_generation_brace_layers(datadir):
    with open(str(datadir.join("BraceTestFont.glyphs"))) as f:
        font = glyphsLib.load(f)
    designspace = to_designspace(font)

    axes_order = [(a.name, a.minimum, a.default, a.maximum, a.map)
                  for a in designspace.axes]
    assert axes_order == [
        ("Width", 75, 100, 100, [(75, 50.0), (100, 100.0)]),
        ("Weight", 100, 100, 700, [(100, 100.0), (700, 1000.0)]),
    ]

    source_order = [(s.filename, s.layerName, s.name)
                    for s in designspace.sources]
    assert source_order == [
        ("NewFont-Light.ufo", None, "New Font Light"),
        ("NewFont-Light.ufo", "{75}", "New Font Light {75}"),
        ("NewFont-Bold.ufo", None, "New Font Bold"),
        ("NewFont-Bold.ufo", "{75}", "New Font Bold {75}"),
        ("NewFont-Bold.ufo", "Test2 {90, 500}",
         "New Font Bold Test2 {90, 500}"),
        ("NewFont-Bold.ufo", "Test1 {90, 600}",
         "New Font Bold Test1 {90, 600}"),
        ("NewFont-CondensedLight.ufo", None, "New Font Condensed Light"),
        ("NewFont-CondensedBold.ufo", None, "New Font Condensed Bold"),
    ]

    # Check that all sources have a font object attached and sources with the same
    # filename have the same font object attached.
    masters = {}
    for source in designspace.sources:
        assert source.font
        if source.filename in masters:
            assert masters[source.filename] is source.font
        masters[source.filename] = source.font
def test_designspace_generation_bracket_roundtrip_psnames(datadir, ufo_module):
    with open(str(datadir.join("PSNames.glyphs"))) as f:
        font = glyphsLib.load(f)
    designspace: DesignSpaceDocument = to_designspace(font, ufo_module=ufo_module)

    assert designspace.findDefault().font.lib["public.postscriptNames"] == {
        "a-cy": "uni0430",
        "a-cy.BRACKET.18": "uni0430.BRACKET.18",
        "a-cy.alt": "uni0430.alt",
    }

    font_rt = to_glyphs(designspace)
    designspace_rt = to_designspace(font_rt, ufo_module=ufo_module)

    assert designspace_rt.findDefault().font.lib["public.postscriptNames"] == {
        "a-cy": "uni0430",
        "a-cy.BRACKET.18": "uni0430.BRACKET.18",
        "a-cy.alt": "uni0430.alt",
    }

    font_rt2 = to_glyphs(designspace_rt)
    designspace_rt2 = to_designspace(font_rt2, ufo_module=ufo_module)

    assert designspace_rt2.findDefault().font.lib["public.postscriptNames"] == {
        "a-cy": "uni0430",
        "a-cy.BRACKET.18": "uni0430.BRACKET.18",
        "a-cy.alt": "uni0430.alt",
    }
def test_designspace_generation_bracket_no_export_glyph(datadir):
    with open(str(datadir.join("BracketTestFont2.glyphs"))) as f:
        font = glyphsLib.load(f)

    font.glyphs["E"].export = False

    designspace = to_designspace(font, write_skipexportglyphs=True)

    assert "E" in designspace.lib.get("public.skipExportGlyphs")

    for source in designspace.sources:
        assert "E.REV_BRACKET.570" not in source.font
        assert "E.BRACKET.630" not in source.font

    for rule in designspace.rules:
        assert "E" not in {g for g in itertools.chain(*rule.subs)}

    font_rt = to_glyphs(designspace)

    assert "E" in font_rt.glyphs
    assert {l.name
            for l in font_rt.glyphs["E"].layers} == {
                "Regular",
                "Regular [630]",
                "Bold",
                "Bold ]570]",
            }
 def test_GlyphsUnitTestSans(self):
     filename = os.path.join(
         os.path.dirname(__file__), "../data/GlyphsUnitTestSans.glyphs"
     )
     with open(filename) as f:
         font = glyphsLib.load(f)
     self.assertUFORoundtrip(font)
 def test_BraceTestFont(self):
     filename = os.path.join(
         os.path.dirname(__file__), "../data/BraceTestFont.glyphs"
     )
     with open(filename) as f:
         font = glyphsLib.load(f)
     self.assertUFORoundtrip(font)
def gen_beta_vf_project(glyphs_path, ofl_path):
    """Generate .glyph file into VF font project, based on
    https://github.com/google/fonts/pull/724"""
    glyphs_source = glyphsLib.load(open(glyphs_path, 'rb'))
    family_name = glyphs_source['familyName']
    designer = glyphs_source['designer']
    copyright = glyphs_source['copyright']

    # Generate variable font with 'VF Beta appended to font name'
    beta_family_name = family_name + ' VF Beta'
    set_family_name(glyphs_path, family_name, beta_family_name)
    # Generate variable font via cmdline fontmake
    # TODO (Marc Foley) just use fontmake properly
    subprocess.call(['fontmake', '-g', glyphs_path, '-o', 'variable'])

    # Folder cleanup
    ofl_family_dir = family_name.lower().replace(' ', '')
    vf_family_dir = ofl_family_dir + 'vfbeta'
    rename_fonts('variable_ttf')
    cleanup_folders(vf_family_dir)

    # Copy over OFL.txt license files
    ofl_txt = os.path.join(ofl_path, ofl_family_dir, 'OFL.txt')
    vf_ofl_txt = os.path.join(vf_family_dir, 'OFL.txt')
    cp_file(ofl_txt, vf_ofl_txt)

    # Create early access file and description
    meta_path = os.path.join(ofl_path, ofl_family_dir, 'METADATA.pb')
    category = _get_metadata_category(meta_path)
    create_early_access_file(vf_family_dir, category)
    create_description_file(vf_family_dir, category, designer, copyright)
Exemple #9
0
 def test_GlyphsUnitTestSans(self):
     self.skipTest("TODO")
     filename = os.path.join(os.path.dirname(__file__),
                             'data/GlyphsUnitTestSans.glyphs')
     with open(filename) as f:
         font = glyphsLib.load(f)
     self.assertUFORoundtrip(font)
def test_designspace_generation_reverse_bracket_roundtrip(datadir):
    with open(str(datadir.join("BracketTestFont2.glyphs"))) as f:
        font = glyphsLib.load(f)

    g = font.glyphs["D"]

    assert {"Regular ]600]",
            "Bold ]600]"}.intersection(l.name for l in g.layers)

    designspace = to_designspace(font)

    assert designspace.rules[1].name == "BRACKET.400.600"
    assert designspace.rules[1].conditionSets == [[
        dict(name="Weight", minimum=400, maximum=600)
    ]]
    assert designspace.rules[1].subs == [("D", "D.REV_BRACKET.600")]

    for source in designspace.sources:
        ufo = source.font
        assert "D.REV_BRACKET.600" in ufo

    font_rt = to_glyphs(designspace)

    assert "D" in font_rt.glyphs

    g2 = font_rt.glyphs["D"]
    assert {"Regular ]600]",
            "Bold ]600]"}.intersection(l.name for l in g2.layers)

    assert "D.REV_BRACKET.600" not in font_rt.glyphs
def test_designspace_generation_bracket_roundtrip(datadir):
    with open(str(datadir.join("BracketTestFont.glyphs"))) as f:
        font = glyphsLib.load(f)
    designspace = to_designspace(font)

    assert designspace.rules[0].name == "BRACKET.300.600"
    assert designspace.rules[0].conditionSets == [[
        dict(name="Weight", minimum=300, maximum=600)
    ]]
    assert designspace.rules[0].subs == [("x", "x.BRACKET.300")]

    assert designspace.rules[1].name == "BRACKET.300.1000"
    assert designspace.rules[1].conditionSets == [[
        dict(name="Weight", minimum=300, maximum=1000)
    ]]
    assert designspace.rules[1].subs == [("a", "a.BRACKET.300")]

    assert designspace.rules[2].name == "BRACKET.600.1000"
    assert designspace.rules[2].conditionSets == [[
        dict(name="Weight", minimum=600, maximum=1000)
    ]]
    assert designspace.rules[2].subs == [("x", "x.BRACKET.600")]

    for source in designspace.sources:
        assert "[300]" not in source.font.layers
        assert "Something [300]" not in source.font.layers
        assert "[600]" not in source.font.layers
        assert "Other [600]" not in source.font.layers
        g1 = source.font["x.BRACKET.300"]
        assert not g1.unicodes
        g2 = source.font["x.BRACKET.600"]
        assert not g2.unicodes

    font_rt = to_glyphs(designspace)
    assert "x" in font_rt.glyphs
    g1 = font_rt.glyphs["x"]
    assert len(g1.layers) == 12 and {l.name
                                     for l in g1.layers} == {
                                         "[300]",
                                         "[600]",
                                         "Bold",
                                         "Condensed Bold",
                                         "Condensed Light",
                                         "Light",
                                         "Other [600]",
                                         "Something [300]",
                                     }
    g2 = font_rt.glyphs["a"]
    assert len(g2.layers) == 8 and {l.name
                                    for l in g2.layers} == {
                                        "[300]",
                                        "Bold",
                                        "Condensed Bold",
                                        "Condensed Light",
                                        "Light",
                                    }
    assert "a.BRACKET.300" not in font_rt.glyphs
    assert "x.BRACKET.300" not in font_rt.glyphs
    assert "x.BRACKET.600" not in font_rt.glyphs
def main():
    args = parser.parse_args()

    for font in args.font:
        with open(font, "rb") as glyphs_file:
            data = glyphsLib.load(glyphs_file)
            print('Copyright: "{}"'.format(data["copyright"]))
            print('VendorID: "{}"'.format(customparam(data, "vendorID")))
            print("fsType: {}".format(customparam(data, "fsType")[0]))
            print('license: "{}"'.format(customparam(data, "license")))
            print('licenseURL: "{}"'.format(customparam(data, "licenseURL")))
Exemple #13
0
def main():
    args = parser.parse_args()

    for font in args.font:
        with open(font, 'rb') as glyphs_file:
            data = glyphsLib.load(glyphs_file)
            print('Copyright: "{}"'.format(data["copyright"]))
            print('VendorID: "{}"'.format(customparam(data, "vendorID")))
            print('fsType: {}'.format(customparam(data, "fsType")[0]))
            print('license: "{}"'.format(customparam(data, "license")))
            print('licenseURL: "{}"'.format(customparam(data, "licenseURL")))
Exemple #14
0
def test_designspace_generation_bracket_unbalanced_brackets(datadir):
    with open(str(datadir.join("BracketTestFont.glyphs"))) as f:
        font = glyphsLib.load(f)

    # Delete the "Other [600]" layer to unbalance bracket layers.
    del font.glyphs["x"].layers["C5C3CA59-C2D0-46F6-B5D3-86541DE36ACB"]
    with pytest.raises(ValueError) as excinfo:
        to_designspace(font)
    assert "bracket layer(s) missing" in str(excinfo)

    # Delete the other [600] layers to rebalance.
    del font.glyphs["x"].layers["E729A72D-C6FF-4DDD-ADA1-BB5B6FD7E3DD"]
    del font.glyphs["x"].layers["F5778F4C-2B04-4030-9D7D-09E3C951C089"]
    del font.glyphs["x"].layers["24328DA8-2CE1-4D0A-9C91-214ED36F6393"]
    assert to_designspace(font)
    def test_BraceTestFont_no_editor_state(self):
        filename = os.path.join(os.path.dirname(__file__),
                                "../data/BraceTestFont.glyphs")
        with open(filename) as f:
            font = glyphsLib.load(f)

        designspace = glyphsLib.to_designspace(font)
        for source in designspace.sources:
            assert source.font.lib[
                glyphsLib.builder.constants.FONT_CUSTOM_PARAM_PREFIX +
                "DisplayStrings"] == ["a", "b"]

        designspace = glyphsLib.to_designspace(font, store_editor_state=False)
        for source in designspace.sources:
            assert (glyphsLib.builder.constants.FONT_CUSTOM_PARAM_PREFIX +
                    "DisplayStrings" not in source.font.lib)
Exemple #16
0
 def assertParseWriteRoundtrip(self, filename):
     with open(filename) as f:
         expected = f.read().splitlines()
         f.seek(0, 0)
         font = glyphsLib.load(f)
     actual = write_to_lines(font)
     # Roundtrip again to check idempotence
     font = glyphsLib.loads("\n".join(actual))
     actual_idempotent = write_to_lines(font)
     # Assert idempotence first, because if that fails it's a big issue
     self.assertLinesEqual(
         actual, actual_idempotent,
         "The parser/writer should be idempotent. BIG PROBLEM!")
     self.assertLinesEqual(
         expected, actual,
         "The writer should output exactly what the parser read")
def test_designspace_generation_instances(datadir, ufo_module):
    with open(str(datadir.join("BraceTestFont.glyphs"))) as f:
        font = glyphsLib.load(f)
    designspace = to_designspace(font, ufo_module=ufo_module)

    instances_order = [
        (i.name, i.styleMapStyleName, i.location) for i in designspace.instances
    ]
    assert instances_order == [
        ("New Font Thin", "regular", {"Width": 100.0, "Weight": 100.0}),
        ("New Font Regular", "regular", {"Width": 100.0, "Weight": 500.0}),
        ("New Font Bold", "bold", {"Width": 100.0, "Weight": 1000.0}),
        ("New Font Semi Consensed", "regular", {"Width": 75.0, "Weight": 500.0}),
        ("New Font Thin Condensed", "regular", {"Width": 50.0, "Weight": 100.0}),
        ("New Font Condensed", "regular", {"Width": 50.0, "Weight": 500.0}),
        ("New Font Bold Condensed", "bold", {"Width": 50.0, "Weight": 1000.0}),
    ]
def test_designspace_generation_bracket_GDEF(datadir, ufo_module):
    with open(str(datadir.join("BracketTestFont.glyphs"))) as f:
        font = glyphsLib.load(f)

    # add some attaching anchors to the "x" glyph and its (bracket) layers to
    # trigger the generation of GDEF table
    for layer in font.glyphs["x"].layers:
        anchor = glyphsLib.classes.GSAnchor()
        anchor.name = "top"
        anchor.position = (0, 0)
        layer.anchors.append(anchor)

    designspace = to_designspace(font, ufo_module=ufo_module, generate_GDEF=True)

    for source in designspace.sources:
        ufo = source.font
        features = fontTools.feaLib.parser.Parser(
            io.StringIO(ufo.features.text), glyphNames=ufo.keys()
        ).parse()
        for stmt in features.statements:
            if (
                isinstance(stmt, fontTools.feaLib.ast.TableBlock)
                and stmt.name == "GDEF"
            ):
                gdef = stmt
                for stmt in gdef.statements:
                    if isinstance(stmt, fontTools.feaLib.ast.GlyphClassDefStatement):
                        glyph_class_defs = stmt
                        break
                else:
                    pytest.fail(
                        f"No GDEF.GlyphClassDef statement found in {ufo!r} features:\n"
                        f"{ufo.features.text}"
                    )
                break
        else:
            pytest.fail(
                f"No GDEF table definition found in {ufo!r} features:\n"
                f"{ufo.features.text}"
            )

        assert set(glyph_class_defs.baseGlyphs.glyphSet()) == {
            "x",
            "x.BRACKET.300",
            "x.BRACKET.600",
        }
def test_designspace_generation_bracket_unbalanced_brackets(datadir):
    with open(str(datadir.join("BracketTestFont2.glyphs"))) as f:
        font = glyphsLib.load(f)

    layer_names = {l.name for l in font.glyphs["C"].layers}
    assert layer_names == {"Regular", "Bold", "Bold [600]"}

    designspace = to_designspace(font)

    for source in designspace.sources:
        assert "C.BRACKET.600" in source.font

    font_rt = to_glyphs(designspace)

    assert "C" in font_rt.glyphs

    assert {l.name for l in font_rt.glyphs["C"].layers} == layer_names
    assert "C.BRACKET.600" not in font_rt.glyphs
Exemple #20
0
    def test_IntFloatCoordinates(self):
        filename = os.path.join(os.path.dirname(__file__),
                                "data/IntegerFloat.glyphs")
        with open(filename) as f:
            font = glyphsLib.load(f)

        int_points_expected = [
            (True, True),
            (False, True),
            (False, False),
            (True, True),
            (True, True),
            (True, True),
        ]

        assert isinstance(font.glyphs["a"].layers[0].width, int)
        assert [(isinstance(n.position.x, int), isinstance(n.position.y, int))
                for n in font.glyphs["a"].layers[0].paths[0].nodes
                ] == int_points_expected
def test_designspace_generation_bracket_roundtrip_no_layername(datadir):
    with open(str(datadir.join("BracketTestFont.glyphs"))) as f:
        font = glyphsLib.load(f)

    # Remove brace layers for clean slate.
    master_ids = {m.id for m in font.masters}
    for g in font.glyphs:
        dl = [l for l in g.layers if l.layerId not in master_ids]
        for l in dl:
            g.layers.remove(l)

    designspace = to_designspace(font)
    for source in designspace.sources:
        source.font.newGlyph("b.BRACKET.100")

    font_rt = to_glyphs(designspace)
    for layer in font_rt.glyphs["b"].layers:
        if layer.layerId not in master_ids:
            assert layer.name == "[100]"
        commands += add_paths(comp_layer, t, c.transform)

    svg_path = etree.fromstring(f'<path d="{commands}" />')
    svg.append(svg_path)

    et.write("%s/%s.svg" % (dir, glyph), pretty_print=True)


parser = argparse.ArgumentParser(description="Convert Glyphs file to SVG files")
parser.add_argument("--output-dir", metavar="DIRECTORY")
parser.add_argument("--master", help="Master name for .glyphs fonts", metavar="MASTER")
parser.add_argument("file", metavar="SOURCE")
parser.add_argument("glyph", metavar="GLYPH", nargs="*")

args = parser.parse_args()
gsfont = load(open(args.file))

output_dir = args.output_dir
if not output_dir:
    output_dir, _ = os.path.splitext(args.file)

print("Writing SVG files to %s" % output_dir)

if not os.path.exists(output_dir):
    os.mkdir(output_dir)

master_id = 0
if args.master:
    for master in gsfont.masters:
        if master.name == args.master:
            master_id = master.id
def get_glyphs_key(glyphs_path, key):
    with open(glyphs_path, 'rb') as glyphs_data:
        glyphs_source = glyphsLib.load(glyphs_data)
        return glyphs_source[key]
Exemple #24
0
                                same = False
                    if not same:
                        continue
                    print(
                        "Our anchor '%s' was duplicate of original source '%s'"
                        % (ours, theirs))
                    drop_anchors.add(ours)
                    break

        for to_drop in drop_anchors:
            for glyph in glyphs_with_anchor[to_drop]:
                for l in self.gsfont.glyphs[glyph].layers:
                    del l.anchors[to_drop]


gsfont = glyphsLib.load(open(args.source))

font = TTFont(args.firstmaster)

ff = unparse(font, do_gdef=True, doLookups=True, config=config)

Layout2Glyphs(gsfont, ff, args).process()

for ix, master in enumerate(args.othermasters):
    print("%s -> %i" % (master, ix + 1))
    font = TTFont(master)
    ff = unparse(font, do_gdef=True, doLookups=True, config=config)
    Layout2Glyphs(gsfont, ff, args, master=ix + 1).process_gpos()

if not args.output:
    args.output = args.source
Exemple #25
0
 def test_method(self, filename=filename):
     with open(filename) as f:
         font = glyphsLib.load(f)
     self.assertUFORoundtrip(font)
Exemple #26
0
# See the License for the specific language governing permissions and
# limitations under the License.
#
import glyphsLib
import os

parent_dir = '~/Documents/googlefonts/manual_font_cleaning/'
possible_var_fonts = []
almost_possible_var_fonts = []

for root, dirs, files in os.walk(parent_dir, topdown=False):
    for f in files:
        if '.glyphs' in f:
            try:
                with open(os.path.join(root, f)) as glyphs_file:
                    glyphs_source = glyphsLib.load(glyphs_file)

                    master_count = len(glyphs_source['fontMaster'])
                    instance_count = len(glyphs_source['instances'])

                    if master_count >= 2 and instance_count >= 3:
                        possible_var_fonts.append(
                            (glyphs_source['familyName'],
                             len(glyphs_source['fontMaster']),
                             len(glyphs_source['instances'])))
                    elif master_count >= 2 and instance_count == master_count:
                        almost_possible_var_fonts.append(
                            (glyphs_source['familyName'],
                             len(glyphs_source['fontMaster']),
                             len(glyphs_source['instances'])))
            except: