]> git.donarmstrong.com Git - lilypond.git/blob - buildscripts/ps-to-pfa.py
release: 1.1.63
[lilypond.git] / buildscripts / ps-to-pfa.py
1 #!@PYTHON@
2
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>
8
9 #TODO.  This could be more efficient.
10
11 name = 'ps-to-pfa'
12 version = '0.4'
13
14 datadir = ''
15
16 import find
17 import os
18 import sys
19
20 import getopt
21 from string import *
22 import regsub
23
24 # todo, port: see http://starship.skyport.net/crew/amk/regex/regex-to-re.html
25 import re
26 import time
27
28 def program_id ():
29     return name + ' version ' + version;
30
31 def identify ():
32     sys.stdout.write (program_id () + '\n')
33
34 def help ():
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"
37                       + "Options:\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"
41                       % (program_name)
42                       )
43     sys.exit (0)
44
45 output_name = ''
46
47 identify ()
48 (options, files) = getopt.getopt (
49     sys.argv[1:], 'o:d:', ['help', 'package', 'output='])
50 for opt in options:
51     o = opt[0]
52     a = opt[1]
53     if o== '--help' or o == '-h':
54         help ()
55     elif o == '-d' or o == '--datadir':
56         datadir = a
57     elif o == '-o' or o =='--output':
58         output_name = a
59     else:
60         print o
61         raise getopt.error
62
63
64 def gulp_file (f):
65         sys.stderr.write ('[%s' % f)
66         try:
67                 i = open (f)
68                 i.seek (0, 2)
69                 n = i.tell ()
70                 i.seek (0,0)
71         except:
72                 sys.stderr.write ('can\'t open file %s\n ' % f)
73                 return ''
74         s = i.read (n)
75         sys.stderr.write (']')
76         if len (s) <= 0:
77                 sys.stderr.write ('gulped empty file: %s\n'% f)
78         return s
79
80 mf = files[0]
81
82 input_name = mf
83 font_name = os.path.basename (os.path.splitext (mf)[0])
84 if not output_name:
85     output_name  = font_name + '.pfa'
86
87
88 sys.stderr.write ('Font: %s\n'% font_name)
89
90 def header (f):
91         f.write ('%!PS-AdobeFont-3.0: ' + font_name + '\n')
92         f.write ('%%%%Creator: %s-%s\n' % (name, version))
93         f.write ('\n')
94         f.write (r"""
95 8 dict begin
96 /FontType 3 def                             %% Required elements of font
97 /FontName /%s def""" % font_name)
98         f.write (r"""
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
103 """)
104 def footer (f):
105         f.write (r"""
106 /BuildGlyph {                               % Stack contains: font charname
107   1000 0                                   % Width
108   -1000 -1000 1000 1000                    % Bounding Box
109   setcachedevice
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
113 } bind def
114
115 /BuildChar {                                % Level 1 compatibility
116   1 index /Encoding get exch get
117   1 index /BuildGlyph get exec
118 } bind def
119
120 currentdict
121 end                                         % of font dictionary
122 """
123 )
124
125         f.write ('/%s\n' % font_name)
126         f.write (''
127 'exch definefont pop                         % Define the font\n')
128
129
130 suspect_re = re.compile ('closepath (.*?) 1 setgray newpath (.*?) closepath fill')
131
132 def characters (f):
133         sys.stderr.write ('[')
134         
135         files = []
136         import find                     # q
137         suffixes = [".[0-9]", ".[0-9][0-9]",  ".[0-9][0-9][0-9]"]
138         for suf in suffixes:
139                 files = files + find.find (font_name + suf)
140
141
142         # concat all files into charprocs.
143         charprocs = '  /.notdef {} def\n'
144         encoding = ''
145         for i in files: 
146                 s = gulp_file (i)
147                 s = re.sub ('%[^\n]*\n', '', s)
148                 
149                 # if you want readable stuff, look at MP output.
150                 s = re.sub ('[\n\t ]+', ' ', s)
151                 s = re.sub ('showpage', '', s)
152
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)
158                         while m:
159                                 fill = m.group (1)
160                                 path = m.group (2)
161
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)
167
168                         s = re.sub ('eovill' , 'eofill', s)
169                         s = re.sub ('0 setgray' ,'', s)
170
171                         
172                 m = re.match ('.*\.([0-9]+)',i)
173                 n = atoi (m.group (1))
174
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
178
179         f.write ('\n'
180 '/CharProcs 3 dict def                       % Subsidiary dictiorary for\n'
181 'CharProcs begin                             % individual character definitions\n')
182         f.write (charprocs)
183         f.write ('\n')
184         f.write ('end                                         % of CharProcs\n')
185         f.write (encoding)
186         f.write ('\n')
187         sys.stderr.write (']')
188
189
190 ps_file = open (output_name, 'w')
191 header (ps_file)
192 characters (ps_file)
193 footer (ps_file)
194 sys.stderr.write ('\n')
195 ps_file.close ()
196 sys.stderr.write ('Wrote PostScript font: %s\n' % output_name)
197