diff options
Diffstat (limited to 'examples/ffcopyglyphs.py')
-rw-r--r-- | examples/ffcopyglyphs.py | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/examples/ffcopyglyphs.py b/examples/ffcopyglyphs.py new file mode 100644 index 0000000..3fcfe76 --- /dev/null +++ b/examples/ffcopyglyphs.py @@ -0,0 +1,161 @@ +#!/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() |