]> git.donarmstrong.com Git - lilypond.git/blob - buildscripts/ps-to-pfa.py
patch::: 1.3.43.jcn1
[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 import getopt
20 from string import *
21 import re
22 import time
23
24 def program_id ():
25     return name + ' version ' + version;
26
27 def identify ():
28     sys.stdout.write (program_id () + '\n')
29
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)
38                       )
39     sys.exit (0)
40
41 output_name = ''
42
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
58
59
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
75
76 mf = files[0]
77
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'
82
83
84 sys.stderr.write ('Font: %s\n'% font_name)
85
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
110
111 /BuildChar {                                % Level 1 compatibility
112   1 index /Encoding get exch get
113   1 index /BuildGlyph get exec
114 } bind def
115
116 currentdict
117 end                                         % of font dictionary
118 """
119 )
120
121         f.write ('/%s\n' % font_name)
122         f.write (''
123 'exch definefont pop                         % Define the font\n')
124
125 suspect_re = re.compile ('closepath ((gsave )*fill( grestore stroke)*) 1 setgray newpath (.*?) closepath fill')
126
127 def characters (f):
128         sys.stderr.write ('[')
129         
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)
135
136
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)
143                 
144                 # if you want readable stuff, look at MP output.
145                 s = re.sub ('[\n\t ]+', ' ', s)
146                 s = re.sub ('showpage', '', s)
147
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)
156
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)
162
163                         s = re.sub ('eovill' , 'eofill', s)
164                         s = re.sub ('0 setgray' ,'', s)
165
166                         
167                 m = re.match ('.*\.([0-9]+)',i)
168                 n = atoi (m.group (1))
169
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
173
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 (']')
183
184
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)
192