lilypond-1.3.11
[lilypond.git] / buildscripts / ps-to-pfa.py
blobbab745820d330d367b83a040974b8da639da38f0
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')
126 suspect_re = re.compile ('closepath (.*?) 1 setgray newpath (.*?) closepath fill')
128 def characters (f):
129 sys.stderr.write ('[')
131 files = []
132 import find # q
133 suffixes = [".[0-9]", ".[0-9][0-9]", ".[0-9][0-9][0-9]"]
134 for suf in suffixes:
135 files = files + find.find (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 (2)
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 sys.stderr.write (']')
186 ps_file = open (output_name, 'w')
187 header (ps_file)
188 characters (ps_file)
189 footer (ps_file)
190 sys.stderr.write ('\n')
191 ps_file.close ()
192 sys.stderr.write ('Wrote PostScript font: %s\n' % output_name)