3 # ps-to-pfa.py -- make PostScript Type 3 font from separate ps char files
5 # source file of the GNU LilyPond music typesetter
7 # (c) 1998 Jan Nieuwenhuizen <janneke@gnu.org>
9 #TODO. This could be more efficient.
24 # todo, port: see http://starship.skyport.net/crew/amk/regex/regex-to-re.html
29 return name + ' version ' + version;
32 sys.stdout.write (program_id () + '\n')
35 sys.stdout.write ("Usage: %s [options] [files]\n"
36 "ps-to-pfa.py -- make PostScript Type 3 font from separate ps char files\n\n"
38 + " -d, --datadir=DIR use DIR for ps header/footer\n"
39 + " -h, --help print this help\n"
40 + " -o, --output=FILE set output file to FILE.\n"
48 (options, files) = getopt.getopt (
49 sys.argv[1:], 'o:d:', ['help', 'package', 'output='])
53 if o== '--help' or o == '-h':
55 elif o == '-d' or o == '--datadir':
57 elif o == '-o' or o =='--output':
65 sys.stderr.write ('[%s' % f)
72 sys.stderr.write ('can\'t open file %s\n ' % f)
75 sys.stderr.write (']')
77 sys.stderr.write ('gulped empty file: %s\n'% f)
83 font_name = os.path.basename (os.path.splitext (mf)[0])
85 output_name = font_name + '.pfa'
88 sys.stderr.write ('Font: %s\n'% font_name)
91 f.write ('%!PS-AdobeFont-3.0: ' + font_name + '\n')
92 f.write ('%%%%Creator: %s-%s\n' % (name, version))
96 /FontType 3 def %% Required elements of font
97 /FontName /%s def""" % font_name)
99 /FontMatrix [.083 0 0 .083 0 0] def %% why .83?
100 /FontBBox [-1000 -1000 1000 1000] def %% does not seem to matter.
101 /Encoding 256 array def %% Trivial encoding vector
102 0 1 255 {Encoding exch /.notdef put} for
106 /BuildGlyph { % Stack contains: font charname
108 -1000 -1000 1000 1000 % Bounding Box
110 exch /CharProcs get exch % Get CharProcs dictionary
111 2 copy known not {pop /.notdef} if % See if charname is known
112 get exec % Execute character procedure
115 /BuildChar { % Level 1 compatibility
116 1 index /Encoding get exch get
117 1 index /BuildGlyph get exec
121 end % of font dictionary
125 f.write ('/%s\n' % font_name)
127 'exch definefont pop % Define the font\n')
130 suspect_re = re.compile ('closepath (.*?) 1 setgray newpath (.*?) closepath fill')
133 sys.stderr.write ('[')
137 suffixes = [".[0-9]", ".[0-9][0-9]", ".[0-9][0-9][0-9]"]
139 files = files + find.find (font_name + suf)
142 # concat all files into charprocs.
143 charprocs = ' /.notdef {} def\n'
147 s = re.sub ('%[^\n]*\n', '', s)
149 # if you want readable stuff, look at MP output.
150 s = re.sub ('[\n\t ]+', ' ', s)
151 s = re.sub ('showpage', '', s)
153 # MP's implementation of unfill confuses GS.
154 # Look for "Metapost & setgray" on deja.com
155 # we do some twiddling to use eofill i.s.o. fill
156 if re.search ('setgray',s ):
157 m = suspect_re.search (s)
162 # be complicated, in case of gsave/grestore.
163 # vill as quick hack to avoid duple substitutions.
164 fill = re.sub ('fill', 'eovill', fill, count = 1)
165 s = re.sub (m.group (0), ' %s %s ' % (path, fill), s)
166 m = suspect_re.search (s)
168 s = re.sub ('eovill' , 'eofill', s)
169 s = re.sub ('0 setgray' ,'', s)
172 m = re.match ('.*\.([0-9]+)',i)
173 n = atoi (m.group (1))
175 s = '\n /%s-%d{\n%s} bind def\n' % (font_name, n, s)
176 encoding = encoding + 'Encoding %d /%s-%d put\n' % (n, font_name, n)
177 charprocs = charprocs + s
180 '/CharProcs 3 dict def % Subsidiary dictiorary for\n'
181 'CharProcs begin % individual character definitions\n')
184 f.write ('end % of CharProcs\n')
187 sys.stderr.write (']')
190 ps_file = open (output_name, 'w')
194 sys.stderr.write ('\n')
196 sys.stderr.write ('Wrote PostScript font: %s\n' % output_name)