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)
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")))
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")))
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)
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
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]
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
def test_method(self, filename=filename): with open(filename) as f: font = glyphsLib.load(f) self.assertUFORoundtrip(font)
# 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: