lilypond-1.5.7
[lilypond.git] / buildscripts / ps-to-pfa.py
bloba1d80c18c981e2136609c58f7691ec0ca0098888
1 #!@PYTHON@
3 # ps-to-pfa.py -- make PostScript Type 3 font from separate ps char files
4 #
5 # source file of the GNU LilyPond music typesetter
6 #
7 # (c) 1998 Jan Nieuwenhuizen <janneke@gnu.org>
9 #TODO. This could be more efficient.
11 name = 'ps-to-pfa'
12 version = '0.4'
14 datadir = ''
16 import os
17 import sys
18 import getopt
19 from string import *
20 import re
21 import time
23 logfile = sys.stdout
25 def program_id ():
26 return name + ' version ' + version;
28 def identify ():
29 sys.stdout.write (program_id () + '\n')
31 def help ():
32 sys.stdout.write ("Usage: %s [options] [files]\n"
33 "ps-to-pfa.py -- make PostScript Type 3 font from separate ps char files\n\n"
34 + "Options:\n"
35 + " -d, --datadir=DIR use DIR for ps header/footer\n"
36 + " -h, --help print this help\n"
37 + " -o, --output=FILE set output file to FILE.\n"
38 % (program_name)
40 sys.exit (0)
42 output_name = ''
44 identify ()
45 (options, files) = getopt.getopt (
46 sys.argv[1:], 'o:d:', ['help', 'package', 'output='])
47 for opt in options:
48 o = opt[0]
49 a = opt[1]
50 if o== '--help' or o == '-h':
51 help ()
52 elif o == '-d' or o == '--datadir':
53 datadir = a
54 elif o == '-o' or o =='--output':
55 output_name = a
56 else:
57 print o
58 raise getopt.error
61 def gulp_file (f):
62 logfile.write ('[%s' % f)
63 try:
64 i = open (f)
65 i.seek (0, 2)
66 n = i.tell ()
67 i.seek (0,0)
68 except:
69 logfile.write ('can\'t open file %s\n ' % f)
70 return ''
71 s = i.read (n)
72 logfile.write (']')
73 if len (s) <= 0:
74 logfile.write ('gulped empty file: %s\n'% f)
75 return s
77 mf = files[0]
79 input_name = mf
80 font_name = os.path.basename (os.path.splitext (mf)[0])
81 if not output_name:
82 output_name = font_name + '.pfa'
85 logfile.write ('Font: %s\n'% font_name)
87 def header (f):
88 f.write ('%!PS-AdobeFont-3.0: ' + font_name + '\n')
89 f.write ('%%%%Creator: %s-%s\n' % (name, version))
90 f.write ('\n')
91 f.write (r"""
92 8 dict begin
93 /FontType 3 def %% Required elements of font
94 /FontName /%s def""" % font_name)
95 f.write (r"""
96 /FontMatrix [.083 0 0 .083 0 0] def %% 12 is default height: 1/12 = 0.083
97 /FontBBox [-1000 -1000 1000 1000] def %% does not seem to matter.
98 /Encoding 256 array def %% Trivial encoding vector
99 0 1 255 {Encoding exch /.notdef put} for
100 """)
101 def footer (f):
102 f.write (r"""
103 /BuildGlyph { % Stack contains: font charname
104 1000 0 % Width
105 -1000 -1000 1000 1000 % Bounding Box
106 setcachedevice
107 exch /CharProcs get exch % Get CharProcs dictionary
108 2 copy known not {pop /.notdef} if % See if charname is known
109 get exec % Execute character procedure
110 } bind def
112 /BuildChar { % Level 1 compatibility
113 1 index /Encoding get exch get
114 1 index /BuildGlyph get exec
115 } bind def
117 currentdict
118 end % of font dictionary
122 f.write ('/%s\n' % font_name)
123 f.write (''
124 'exch definefont pop % Define the font\n')
126 suspect_re = re.compile ('closepath ((gsave )*fill( grestore stroke)*) 1 setgray newpath (.*?) closepath fill')
128 def characters (f):
129 logfile.write ('[')
131 files = []
132 import glob
133 suffixes = [".[0-9]", ".[0-9][0-9]", ".[0-9][0-9][0-9]"]
134 for suf in suffixes:
135 files = files + glob.glob(font_name + suf)
138 # concat all files into charprocs.
139 charprocs = ' /.notdef {} def\n'
140 encoding = ''
141 for i in files:
142 s = gulp_file (i)
143 s = re.sub ('%[^\n]*\n', '', s)
145 # if you want readable stuff, look at MP output.
146 s = re.sub ('[\n\t ]+', ' ', s)
147 s = re.sub ('showpage', '', s)
149 # MP's implementation of unfill confuses GS.
150 # Look for "Metapost & setgray" on deja.com
151 # we do some twiddling to use eofill i.s.o. fill
152 if re.search ('setgray',s ):
153 m = suspect_re.search (s)
154 while m:
155 fill = m.group (1)
156 path = m.group (4)
158 # be complicated, in case of gsave/grestore.
159 # vill as quick hack to avoid duple substitutions.
160 fill = re.sub ('fill', 'eovill', fill, count = 1)
161 s = re.sub (m.group (0), ' %s %s ' % (path, fill), s)
162 m = suspect_re.search (s)
164 s = re.sub ('eovill' , 'eofill', s)
165 s = re.sub ('0 setgray' ,'', s)
168 m = re.match ('.*\.([0-9]+)',i)
169 n = atoi (m.group (1))
171 s = '\n /%s-%d{\n%s} bind def\n' % (font_name, n, s)
172 encoding = encoding + 'Encoding %d /%s-%d put\n' % (n, font_name, n)
173 charprocs = charprocs + s
175 f.write ('\n'
176 '/CharProcs 3 dict def % Subsidiary dictiorary for\n'
177 'CharProcs begin % individual character definitions\n')
178 f.write (charprocs)
179 f.write ('\n')
180 f.write ('end % of CharProcs\n')
181 f.write (encoding)
182 f.write ('\n')
183 logfile.write (']')
186 ps_file = open (output_name, 'w')
187 header (ps_file)
188 characters (ps_file)
189 footer (ps_file)
190 logfile.write ('\n')
191 ps_file.close ()
192 logfile.write ('Wrote PostScript font: %s\n' % output_name)