def main(): global doNotSave start = time.time() doNotSave = False filename = sys.argv[-1] font = GSFont(filename) # Store classes and features classes = parseOpenType(font.classes, [], " ") features = parseOpenType(font.features, [], "\n") # Gets number of axes and stores in a dictionary fontAxes = getAxes(font) # Set origin master to determine which layers are used in the duplicate glyph VfOrigin = getVfOrigin(font) weightDict = { "Thin": 100, "ExtraLight": 200, "UltraLight": 200, "Light": 300, "Normal": 400, "Regular": 400, "Medium": 500, "DemiBold": 600, "SemiBold": 600, "Bold": 700, "UltraBold": 800, "ExtraBold": 800, "Black": 900, "Heavy": 900, } # Checks all masters and updates fontAxes dictionary min/max values # Checks all instances and stores scaled min/def/max values # TODO add ability to check virtual master ranges parseAxesValues(font, fontAxes, VfOrigin, weightDict) needsDup = [] logged = {} noComponents = {} # Recursively goes through all glyphs and determines if they will need a duplicate glyph needsDup = getBracketGlyphs(font, needsDup, logged, noComponents) substitution = "import os\nimport sys\nimport fontTools\nfrom fontTools.ttLib import TTFont\nfrom fontTools.varLib.featureVars import addFeatureVariations\n\nfontPath = sys.argv[-1]\n\nf = TTFont(fontPath)\n\ncondSubst = [\n" substitution = setupBracketGlyphs(font, needsDup, features, classes, VfOrigin, logged, fontAxes, substitution) updateOpenType(font, font.classes, classes, " ") updateOpenType(font, font.features, features, "\n") saveFont(font, filename, start, substitution)
def main(): args = parser.parse_args() for font_path in args.font: font = GSFont(font_path) print('Copyright: "{}"'.format(font.copyright)) print('VendorID: "{}"'.format(customparam(font, "vendorID"))) print('fsType: {}'.format(customparam(font, "fsType"))) print('license: "{}"'.format(customparam(font, "license"))) print('licenseURL: "{}"'.format(customparam(font, "licenseURL")))
def main(): parser = argparse.ArgumentParser(description="Build Rana Kufi.") parser.add_argument("glyphs", help="input Glyphs source file") parser.add_argument("version", help="font version") parser.add_argument("otf", help="output OTF file") args = parser.parse_args() font = GSFont(args.glyphs) prepare(font) instance = font.instances[0] # XXX otf = build(instance, args) otf.save(args.otf)
def main(): parser = argparse.ArgumentParser(description="Build Rana Kufi.") parser.add_argument("glyphs", help="input Glyphs source file") parser.add_argument("otf", help="output OTF file") parser.add_argument("--debug", help="Save debug files", action="store_true") args = parser.parse_args() font = GSFont(args.glyphs) prepare(font) otf = buildVF(font, args) otf.save(args.otf)
def main(): parser = argparse.ArgumentParser(description="Build Rana Kufi.") parser.add_argument("glyphs", help="input Glyphs source file") parser.add_argument("version",help="font version") parser.add_argument("otf", help="output OTF file") parser.add_argument("cidinfo",help="output CID info file") parser.add_argument("cidmap", help="output CID map file") args = parser.parse_args() font = GSFont(args.glyphs) prepare(font) instance = font.instances[0] # XXX otf, cidinfo, cidmap = build(instance, args) with open(args.cidinfo, "w") as fp: fp.write(cidinfo) with open(args.cidmap, "w") as fp: fp.write(cidmap) otf.save(args.otf)
def main(): from argparse import ArgumentParser from pathlib import Path parser = ArgumentParser(description="Build Qahiri font.") parser.add_argument("input", help="input Glyphs source file", type=Path) parser.add_argument("version", help="font version", type=float) parser.add_argument("output", help="output font file", type=Path) args = parser.parse_args() isTTF = False if args.output.suffix == ".ttf": isTTF = True font = GSFont(args.input) prepare(font, isTTF) instance = font.instances[0] # XXX otf = build(instance, isTTF, args.version) otf.save(args.output)
def buildVF(opts): font = GSFont(opts.glyphs) glyphOrder = buildAltGlyphs(font) prepare(font) for instance in font.instances: print(f" MASTER {instance.name}") build(instance, opts, glyphOrder) if instance.name == "Regular": regular = instance ds = DesignSpaceDocument() for i, axisDef in enumerate(font.axes): axis = ds.newAxisDescriptor() axis.tag = axisDef.axisTag axis.name = axisDef.name axis.maximum = max(x.axes[i] for x in font.instances) axis.minimum = min(x.axes[i] for x in font.instances) axis.default = regular.axes[i] ds.addAxis(axis) for instance in font.instances: source = ds.newSourceDescriptor() source.font = instance.font source.familyName = instance.familyName source.styleName = instance.name source.name = instance.fullName source.location = { a.name: instance.axes[i] for i, a in enumerate(ds.axes) } ds.addSource(source) print(f" MERGE {font.familyName}") otf, _, _ = merge(ds) subroutinize(otf) if not opts.debug: otf["post"].formatType = 3.0 return otf
def build(args): font = GSFont(args.file) # Set metadata major, minor = args.version.split(".") font.versionMajor, font.versionMinor = int(major), int(minor) font.copyright = font.copyright.format(year=datetime.now().year) builder = UFOBuilder( font, propagate_anchors=False, write_skipexportglyphs=True, store_editor_state=False, ) for master in builder.masters: if master.info.styleName == args.master: ufo = master break anchors = {} curs = [] curs.append("lookupflag RightToLeft IgnoreMarks;") for glyph in ufo: for anchor in glyph.anchors: if anchor.name in ("entry", "exit"): anchors.setdefault(glyph.name, [None, None]) anchors[glyph.name][0 if anchor.name == "entry" else 1] = anchor for glyph, (entry, exit_) in anchors.items(): curs.append( f"pos cursive {glyph} {_dumpAnchor(entry)} {_dumpAnchor(exit_)};") curs = "\n".join(curs) + "\n" ufo.features.text = ufo.features.text.replace("# Automatic Code Cursive", curs) compileTTF(ufo, inplace=True, flattenComponents=True, useProductionNames=False).save(args.out_file)
def main(): font = GSFont(SOURCE_PATH) glyph_list = [] # parse definitions file, define ColorDefinitions object cfp = ColorFileParser(KEY_PATH) color_defs = cfp.parse() # parse source code for color settings # and create GlyphObj objects with color attributes for glyph in font.glyphs: # integer for GlyphsApp color if present # None if color is absent glyph_color = glyph.color # string glyph_name = glyph.name # list of strings glyph_unicode = glyph.unicode # date / time formatted as 2019-01-18 15:04:57 if present # None if no edits have been made to the glyph # glyph_changetime = glyph.lastChange if glyph_color is not None: color = Color(glyph_color) gco = GlyphColorObj(glyph_name, glyph_unicode, color, color_defs) else: # default state if no color detected is WHITE gco = GlyphColorObj(glyph_name, glyph_unicode, Color.WHITE, color_defs) glyph_list.append(gco) for glyphobj in glyph_list: print("[{} {}] : {} {}".format(glyphobj.name, glyphobj.unicode_hex, glyphobj.color_name, glyphobj.value))
import sys import os import re import time import copy from glyphsLib import GSFont from glyphsLib import GSGlyph from glyphsLib import GSLayer filename = sys.argv[-1] font = GSFont(filename) delMasters = [] delInstances = [] delAxes = [] i = 0 for master in font.masters: if re.match('.*Oblique.*', master.name) != None: for glyph in font.glyphs: delLayers = [] for layer in glyph.layers: if layer.layerId == master.id or layer.associatedMasterId == master.id: delLayers.append(layer.layerId) for layerId in delLayers: del glyph.layers[layerId] delMasters.append(i) i = i - 1 else: for glyph in font.glyphs: delLayers = []
# Create build glyphs file : # Turn on Export for Bracket Glyphs and disable non ttf instances # Add extra opentype code for rvrn glyphs that are substituted by another feature as well so that there is a logical path to allow resubstitution, these are manually defined. import sys from glyphsLib import GSFont from glyphsLib import GSGlyph file = sys.argv[1] font = GSFont(file) print("\tPreparing %s" % file) # List of Glyphs which should have export enabled - in the Glyphs App static fonts export these are not active but get swapped with a custom parameter, for the VFs though they needs to be exported italicBracketGlyphs = [ "cedi.rvrn", "colonsign.rvrn", "guarani.rvrn", "cent.rvrn", "dollar.rvrn", "dollar.tf.rvrn", "cent.tf.rvrn", "naira.rvrn", "peseta.rvrn", "won.rvrn", "peso.rvrn", "curvedStemParagraphSignOrnament.rvrn", "paragraph.rvrn" ] uprightBracketGlyphs = italicBracketGlyphs + [ "apple.rvrn", "Adieresis.rvrn", "Odieresis.rvrn", "Udieresis.rvrn", "Adieresis.titl.rvrn", "Odieresis.titl.rvrn", "Udieresis.titl.rvrn", ] # Extra FEA code so that the glyphs swapped by rvrn can be substituted again by another opentype feature
#!/usr/bin/env python3 import sys from glyphsLib import GSFont font = GSFont(sys.argv[1]) glyphs = [g.layers[0] for g in font.glyphs if len(g.layers[0].anchors) > 0] for g in glyphs: print("Anchors %s {" % g.parent.name) for a in g.anchors: print(" %s <%i %i>" % (a.name, *a.position)) print("};\n")
""" Set metrics in all masters of a Glyphs source to easily adjust metrics with a minimum of clicking and typing. Update values, then run once. USAGE: You must have glyphsLib installed, for instance via `pip install glyphsLib`. Then, run this via the terminal, adding the path to a Glyphs source: python3 sources/scripts/set-metrics.py sources/LibreCaslonText.glyphs """ from glyphsLib import GSFont import sys filepath = sys.argv[1] font = GSFont(filepath) for master in font.masters: master.customParameters["hheaAscender"] = 1940 master.customParameters["hheaDescender"] = -520 master.customParameters["hheaLineGap"] = 0 master.customParameters["typoAscender"] = 1940 master.customParameters["typoDescender"] = -520 master.customParameters["typoLineGap"] = 0 master.customParameters["winAscent"] = 1696 master.customParameters["winDescent"] = 531 font.save(filepath)
# -*- coding: utf-8 -*- # # This script demonstrates how to iterate through glyphs in a GlyphsApp *.glyphs source file # and parse glyph-specific metadata # # Dependencies for this script can be installed with: # # $ pip3 install --upgrade glyphsLib # from glyphsLib import GSFont SOURCE_PATH = "../glyphs_source/GenericSans-GreenHighlight.glyphs" font = GSFont(SOURCE_PATH) for glyph in font.glyphs: # integer for GlyphsApp color if present # None if color is absent glyph_color = glyph.color # string glyph_name = glyph.name # list of strings glyph_unicode = glyph.unicode # date / time formatted as 2019-01-18 15:04:57 if present # None if no edits have been made to the glyph glyph_changetime = glyph.lastChange print("{} - {} - {} - {}".format(glyph_name, glyph_unicode, glyph_color,
def main(args=None): """Test for interpolatability issues between fonts""" import argparse parser = argparse.ArgumentParser( "fonttools varLib.interpolatable", description=main.__doc__, ) parser.add_argument( "--json", action="store_true", help="Output report in JSON format", ) parser.add_argument("inputs", metavar="FILE", type=str, nargs="+", help="Input TTF/UFO files") args = parser.parse_args(args) glyphs = None # glyphs = ['uni08DB', 'uniFD76'] # glyphs = ['uni08DE', 'uni0034'] # glyphs = ['uni08DE', 'uni0034', 'uni0751', 'uni0753', 'uni0754', 'uni08A4', 'uni08A4.fina', 'uni08A5.fina'] from os.path import basename fonts = [] names = [] if len(args.inputs) == 1: if args.inputs[0].endswith('.designspace'): from fontTools.designspaceLib import DesignSpaceDocument designspace = DesignSpaceDocument.fromfile(args.inputs[0]) args.inputs = [master.path for master in designspace.sources] elif args.inputs[0].endswith('.glyphs'): from glyphsLib import GSFont, to_ufos gsfont = GSFont(args.inputs[0]) fonts.extend(to_ufos(gsfont)) names = [ '%s-%s' % (f.info.familyName, f.info.styleName) for f in fonts ] args.inputs = [] elif args.inputs[0].endswith('.ttf'): from fontTools.ttLib import TTFont font = TTFont(args.inputs[0]) if 'gvar' in font: # Is variable font gvar = font['gvar'] # Gather all "master" locations locs = set() for variations in gvar.variations.values(): for var in variations: loc = [] for tag, val in sorted(var.axes.items()): loc.append((tag, val[1])) locs.add(tuple(loc)) # Rebuild locs as dictionaries new_locs = [{}] for loc in sorted(locs, key=lambda v: (len(v), v)): names.append(str(loc)) l = {} for tag, val in loc: l[tag] = val new_locs.append(l) locs = new_locs del new_locs # locs is all master locations now for loc in locs: fonts.append( font.getGlyphSet(location=loc, normalized=True)) args.inputs = [] for filename in args.inputs: if filename.endswith(".ufo"): from fontTools.ufoLib import UFOReader fonts.append(UFOReader(filename)) else: from fontTools.ttLib import TTFont fonts.append(TTFont(filename)) names.append(basename(filename).rsplit(".", 1)[0]) if hasattr(fonts[0], 'getGlyphSet'): glyphsets = [font.getGlyphSet() for font in fonts] else: glyphsets = fonts problems = test(glyphsets, glyphs=glyphs, names=names) if args.json: import json print(json.dumps(problems)) else: for glyph, glyph_problems in problems.items(): print(f"Glyph {glyph} was not compatible: ") for p in glyph_problems: if p["type"] == "missing": print(" Glyph was missing in master %s" % p["master"]) if p["type"] == "open_path": print(" Glyph has an open path in master %s" % p["master"]) if p["type"] == "path_count": print(" Path count differs: %i in %s, %i in %s" % (p["value_1"], p["master_1"], p["value_2"], p["master_2"])) if p["type"] == "node_count": print( " Node count differs in path %i: %i in %s, %i in %s" % ( p["path"], p["value_1"], p["master_1"], p["value_2"], p["master_2"], )) if p["type"] == "node_incompatibility": print( " Node %o incompatible in path %i: %s in %s, %s in %s" % ( p["node"], p["path"], p["value_1"], p["master_1"], p["value_2"], p["master_2"], )) if p["type"] == "contour_order": print(" Contour order differs: %s in %s, %s in %s" % ( p["value_1"], p["master_1"], p["value_2"], p["master_2"], )) if p["type"] == "wrong_start_point": print(" Contour start point differs: %s, %s" % ( p["master_1"], p["master_2"], )) if problems: return problems
import sys from glyphsLib import GSFont def settransformedcomponents(f): glyphs = [] # Collect glyphs for glyph in f.glyphs: for layer in glyph.layers: for i, component in enumerate(layer.components): if component.transform[0] != 1 or component.transform[3] != 1: if [glyph, len(layer.components), i] not in glyphs: glyphs.append([glyph, len(layer.components), i]) # Adjust transform for glyph, component_count, i in glyphs: for layer in glyph.layers: if component_count == len(layer.components): if layer.components[i].transform[0] == 1: layer.components[i].transform[0] = 0.999 if layer.components[i].transform[3] == 1: layer.components[i].transform[3] = 0.999 if __name__ == "__main__": font = GSFont(sys.argv[-1]) settransformedcomponents(font) font.save(sys.argv[-1])