lilypond-1.3.65
[lilypond.git] / buildscripts / ps-to-pfa.py
blob796c5d8b3770426b7dec2792e60d636da579fedf
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 find
17 import os
18 import sys
19 import getopt
20 from string import *
21 import re
22 import time
24 def program_id ():
25 return name + ' version ' + version;
27 def identify ():
28 sys.stdout.write (program_id () + '\n')
30 def help ():
31 sys.stdout.write ("Usage: %s [options] [files]\n"
32 "ps-to-pfa.py -- make PostScript Type 3 font from separate ps char files\n\n"
33 + "Options:\n"
34 + " -d, --datadir=DIR use DIR for ps header/footer\n"
35 + " -h, --help print this help\n"
36 + " -o, --output=FILE set output file to FILE.\n"
37 % (program_name)
39 sys.exit (0)
41 output_name = ''
43 identify ()
44 (options, files) = getopt.getopt (
45 sys.argv[1:], 'o:d:', ['help', 'package', 'output='])
46 for opt in options:
47 o = opt[0]
48 a = opt[1]
49 if o== '--help' or o == '-h':
50 help ()
51 elif o == '-d' or o == '--datadir':
52 datadir = a
53 elif o == '-o' or o =='--output':
54 output_name = a
55 else:
56 print o
57 raise getopt.error
60 def gulp_file (f):
61 sys.stderr.write ('[%s' % f)
62 try:
63 i = open (f)
64 i.seek (0, 2)
65 n = i.tell ()
66 i.seek (0,0)
67 except:
68 sys.stderr.write ('can\'t open file %s\n ' % f)
69 return ''
70 s = i.read (n)
71 sys.stderr.write (']')
72 if len (s) <= 0:
73 sys.stderr.write ('gulped empty file: %s\n'% f)
74 return s
76 mf = files[0]
78 input_name = mf
79 font_name = os.path.basename (os.path.splitext (mf)[0])
80 if not output_name:
81 output_name = font_name + '.pfa'
84 sys.stderr.write ('Font: %s\n'% font_name)
86 def header (f):
87 f.write ('%!PS-AdobeFont-3.0: ' + font_name + '\n')
88 f.write ('%%%%Creator: %s-%s\n' % (name, version))
89 f.write ('\n')
90 f.write (r"""
91 8 dict begin
92 /FontType 3 def %% Required elements of font
93 /FontName /%s def""" % font_name)
94 f.write (r"""
95 /FontMatrix [.083 0 0 .083 0 0] def %% why .83?
96 /FontBBox [-1000 -1000 1000 1000] def %% does not seem to matter.
97 /Encoding 256 array def %% Trivial encoding vector
98 0 1 255 {Encoding exch /.notdef put} for
99 """)
100 def footer (f):
101 f.write (r"""
102 /BuildGlyph { % Stack contains: font charname
103 1000 0 % Width
104 -1000 -1000 1000 1000 % Bounding Box
105 setcachedevice
106 exch /CharProcs get exch % Get CharProcs dictionary
107 2 copy known not {pop /.notdef} if % See if charname is known
108 get exec % Execute character procedure
109 } bind def
111 /BuildChar { % Level 1 compatibility
112 1 index /Encoding get exch get
113 1 index /BuildGlyph get exec
114 } bind def
116 currentdict
117 end % of font dictionary
121 f.write ('/%s\n' % font_name)
122 f.write (''
123 'exch definefont pop % Define the font\n')
125 suspect_re = re.compile ('closepath ((gsave )*fill( grestore stroke)*) 1 setgray newpath (.*?) closepath fill')
127 def characters (f):
128 sys.stderr.write ('[')
130 files = []
131 import find # q
132 suffixes = [".[0-9]", ".[0-9][0-9]", ".[0-9][0-9][0-9]"]
133 for suf in suffixes:
134 files = files + find.find (font_name + suf)
137 # concat all files into charprocs.
138 charprocs = ' /.notdef {} def\n'
139 encoding = ''
140 for i in files:
141 s = gulp_file (i)
142 s = re.sub ('%[^\n]*\n', '', s)
144 # if you want readable stuff, look at MP output.
145 s = re.sub ('[\n\t ]+', ' ', s)
146 s = re.sub ('showpage', '', s)
148 # MP's implementation of unfill confuses GS.
149 # Look for "Metapost & setgray" on deja.com
150 # we do some twiddling to use eofill i.s.o. fill
151 if re.search ('setgray',s ):
152 m = suspect_re.search (s)
153 while m:
154 fill = m.group (1)
155 path = m.group (4)
157 # be complicated, in case of gsave/grestore.
158 # vill as quick hack to avoid duple substitutions.
159 fill = re.sub ('fill', 'eovill', fill, count = 1)
160 s = re.sub (m.group (0), ' %s %s ' % (path, fill), s)
161 m = suspect_re.search (s)
163 s = re.sub ('eovill' , 'eofill', s)
164 s = re.sub ('0 setgray' ,'', s)
167 m = re.match ('.*\.([0-9]+)',i)
168 n = atoi (m.group (1))
170 s = '\n /%s-%d{\n%s} bind def\n' % (font_name, n, s)
171 encoding = encoding + 'Encoding %d /%s-%d put\n' % (n, font_name, n)
172 charprocs = charprocs + s
174 f.write ('\n'
175 '/CharProcs 3 dict def % Subsidiary dictiorary for\n'
176 'CharProcs begin % individual character definitions\n')
177 f.write (charprocs)
178 f.write ('\n')
179 f.write ('end % of CharProcs\n')
180 f.write (encoding)
181 f.write ('\n')
182 sys.stderr.write (']')
185 ps_file = open (output_name, 'w')
186 header (ps_file)
187 characters (ps_file)
188 footer (ps_file)
189 sys.stderr.write ('\n')
190 ps_file.close ()
191 sys.stderr.write ('Wrote PostScript font: %s\n' % output_name)