#! /usr/bin/env python ################################################# # Convert each lilyglyphs symbol to a PDF file. # # # # In fact, this script creates only a Ninja # # build file to perform the conversion. # # # # Author: Scott Pakin # ################################################# import glob import os import re import subprocess import sys def kpsewhich(fname): 'Find a filename in the TeX tree.' proc = subprocess.run(['kpsewhich', fname], capture_output=True, check=True, encoding='utf-8') return proc.stdout.strip() def header_string(): 'Return a "generated file" header string.' full_name = os.path.abspath(sys.argv[0]) gen_line = 'This is a generated file. DO NOT EDIT.' edit_line = f'Edit {full_name} instead.' max_chars = max(len(gen_line), len(edit_line)) hash_line = '#' * (max_chars + 4) return '\n'.join([ hash_line, '# %-*.*s #' % (max_chars, max_chars, gen_line), '# %-*.*s #' % (max_chars, max_chars, edit_line), hash_line, '', ]) def symbol_names(fname): 'Extract all symbol names from a given font file.' proc = subprocess.run(['otfinfo', '--glyphs', fname], capture_output=True, check=True, encoding='utf-8') return [sym for sym in proc.stdout.split() if sym != '.notdef'] def find_logo_file(): 'Return the absolute path to lilyglyphs_logo.pdf.' proc = subprocess.run([ 'texdoc', '--list', '--nointeract', 'lilyglyphs_logo.pdf', ], capture_output=True, check=True, encoding='utf-8') return proc.stdout.split()[1] # If we don't have emmentaler-16.otf, generate a do-nothing Ninja file # and exit. font_path = kpsewhich('emmentaler-16.otf') if font_path == '': with open('lilyglyphs.ninja', 'w') as w: w.write(header_string()) sys.exit(0) # Generate a Ninja file that builds a PDF file for each lilyglyphs character. with open('lilyglyphs.ninja', 'w') as w: w.write(header_string()) w.write(''' rule write-file command = /bin/echo -e '$body' > $out description = Creating $out # Generate a FontForge script that extracts all symbols from a font # into named, (rather than numbered) EPS files. build extract-by-name.pe : write-file body = $ Open($$1)\\n$ Select(0x0000, 0xFFFF)\\n$ Export("%n.eps") rule extract-lilyglyphs-symbols command = cd lilyglyphs ; fontforge -script ../$in $font description = Generating an EPS file for each Lilyglyphs character ''') # Extract all EPS files at once. sym_list = symbol_names(font_path) w.write('# Extract all symbols as EPS files at once.\n') w.write('build %s : extract-lilyglyphs-symbols extract-by-name.pe\n' % ' '.join(['lilyglyphs/%s.eps' % sym[:40] for sym in sym_list])) w.write(f' font = {font_path}\n') # Convert each EPS file to a PDF file. w.write(''' rule eps-to-pdf command = epstopdf $in $out description = Converting $in to $out ''') w.write('# Convert each EPS file to a PDF file.\n') for sym in sym_list: if sym == 'space': continue sym_trunc = sym[:40] # FontForge truncates names to 40 characters. w.write(f'build lilyglyphs/{sym}.pdf : eps-to-pdf lilyglyphs/{sym_trunc}.eps\n') # Copy the lilyglyphs logo file locally and crop it. logo_path = find_logo_file() w.write(''' rule copy-and-crop command = $ cp $in $UNCROP ; $ pdfcrop $UNCROP $out description = Copying $in to $out and cropping it # Copy lilyglyphs_logo.pdf to the lilyglyphs directory and crop it. build lilyglyphs/lilyglyphs_logo.pdf : copy-and-crop %s UNCROP = lilyglyphs/lilyglyphs_logo_uncrop.pdf ''' % logo_path) # Create a phony rule that depends on all generated PDF files. w.write('# Make LILYGLYPHS depend on all generated files.\n') w.write('build LILYGLYPHS : phony') for sym in sym_list + ['lilyglyphs_logo']: if sym != 'space': w.write(f' $\n lilyglyphs/{sym}.pdf') w.write('\n')