#!/usr/bin/env python3 '''FontForge: Copy glyphs from one font to another, without using ffbuilder''' __url__ = 'https://github.com/silnrsi/pysilfont' __copyright__ = 'Copyright (c) 2015-2019 SIL International (https://www.sil.org)' __license__ = 'Released under the MIT License (https://opensource.org/licenses/MIT)' __author__ = 'Martin Hosken' from silfont.core import execute import psMat import io ''' This will need updating, since FontForge is no longer supported as a tool by execute() So: - ifont and ofont will need to be changed to have type 'filename' - ifont will then need to be opened using fontforge.open - The font will need to be saved with font.save - execute will need to be called with the tool set to None instead of "FF" ''' argspec = [ ('ifont',{'help': 'Input font file'}, {'type': 'infont'}), ('ofont',{'help': 'Output font file','nargs': '?' }, {'type': 'outfont', 'def': 'new'}), ('-i','--input',{'help': 'Font to get glyphs from', 'required' : True}, {'type': 'infont'}), ('-r','--range',{'help': 'StartUnicode..EndUnicode no spaces, e.g. 20..7E', 'action' : 'append'}, {}), ('--rangefile',{'help': 'File with USVs e.g. 20 or a range e.g. 20..7E or both', 'action' : 'append'}, {}), ('-n','--name',{'help': 'Include glyph named name', 'action' : 'append'}, {}), ('--namefile',{'help': 'File with glyph names', 'action' : 'append'}, {}), ('-a','--anchors',{'help' : 'Copy across anchor points', 'action' : 'store_true'}, {}), ('-f','--force',{'help' : 'Overwrite existing glyphs in the font', 'action' : 'store_true'}, {}), ('-s','--scale',{'type' : float, 'help' : 'Scale glyphs by this factor'}, {}) ] def copyglyph(font, infont, g, u, args) : extras = set() if args.scale is None : scale = psMat.identity() else : scale = psMat.scale(args.scale) o = font.findEncodingSlot(u) if o == -1 : glyph = font.createChar(u, g.glyphname) else : glyph = font[o] if len(g.references) == 0 : font.selection.select(glyph) pen = glyph.glyphPen() g.draw(pen) glyph.transform(scale) else : for r in g.references : t = psMat.compose(r[1], scale) newt = psMat.compose(psMat.identity(), psMat.translate(t[4], t[5])) glyph.addReference(r[0], newt) extras.add(r[0]) glyph.width = g.width * scale[0] if args.anchors : for a in g.anchorPoints : try : l = font.getSubtableOfAnchor(a[1]) except EnvironmentError : font.addAnchorClass("", a[0]*scale[0], a[1]*scale[3]) glyph.anchorPoints = g.anchorPoints return list(extras) def doit(args) : font = args.ifont infont = args.input font.encoding = "Original" infont.encoding = "Original" # compact the font so findEncodingSlot will work infont.layers["Fore"].is_quadratic = font.layers["Fore"].is_quadratic # list of glyphs to copy glist = list() # glyphs specified on the command line for n in args.name or [] : glist.append(n) # glyphs specified in a file for filename in args.namefile or [] : namefile = io.open(filename, 'r') for line in namefile : # ignore comments line = line.partition('#')[0] line = line.strip() # ignore blank lines if (line == ''): continue glist.append(line) # copy glyphs by name reportErrors = True while len(glist) : tglist = glist[:] glist = [] for n in tglist: if n in font and not args.force : if reportErrors : print("Glyph {} already present. Skipping".format(n)) continue if n not in infont : print("Can't find glyph {}".format(n)) continue g = infont[n] glist.extend(copyglyph(font, infont, g, -1, args)) reportErrors = False # list of characters to copy ulist = list() # characters specified on the command line for r in args.range or [] : (rstart, rend) = [int(x, 16) for x in r.split('..')] for u in range(rstart, rend + 1) : ulist.append(u) # characters specified in a file for filename in args.rangefile or [] : rangefile = io.open(filename, 'r') for line in rangefile : # ignore comments line = line.partition('#')[0] line = line.strip() # ignore blank lines if (line == ''): continue # obtain USVs try: (rstart, rend) = line.split('..') except ValueError: rstart = line rend = line rstart = int(rstart, 16) rend = int(rend, 16) for u in range(rstart, rend + 1): ulist.append(u) # copy the characters from the generated list for u in ulist: o = font.findEncodingSlot(u) if o != -1 and not args.force : print("Glyph for {:x} already present. Skipping".format(u)) continue e = infont.findEncodingSlot(u) if e == -1 : print("Can't find glyph for {:04x}".format(u)) continue g = infont[e] copyglyph(font, infont, g, u, args) return font def cmd() : execute("FF",doit,argspec) if __name__ == "__main__": cmd()