allow for empty function calls (like random())
[PyX/mjg.git] / pyx / prolog.py
blobc48c23d62bc1db3b01a9bd5f72b3d0527fa0e0be
1 #!/usr/bin/env python
2 # -*- coding: ISO-8859-1 -*-
5 # Copyright (C) 2003-2004 Jörg Lehmann <joergl@users.sourceforge.net>
6 # Copyright (C) 2003-2004 André Wobst <wobsta@users.sourceforge.net>
8 # This file is part of PyX (http://pyx.sourceforge.net/).
10 # PyX is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
15 # PyX is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License
21 # along with PyX; if not, write to the Free Software
22 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 """prolog module:
26 Snippets included in the prolog of a PostScript file, which can be
27 used as return values of canvasitem instances.
29 """
31 import pykpathsea, t1strip
34 # Abstract base class
37 class prologitem:
39 """Part of the PostScript prolog"""
41 def merge(self, other):
42 """ try to merge self with other prologitem
44 If the merge succeeds, return None. Otherwise return other.
45 Raise ValueError, if conflicts arise!"""
47 pass
49 def outputPS(self, file):
50 """ write self in file """
51 pass
54 # Different variants of prolog items
57 class definition(prologitem):
59 """ PostScript function definition included in the prolog """
61 def __init__(self, id, body):
62 self.id = id
63 self.body = body
65 def merge(self, other):
66 if not isinstance(other, definition):
67 return other
68 if self.id==other.id:
69 if self.body==other.body:
70 return None
71 raise ValueError("Conflicting function definitions!")
72 else:
73 return other
75 def outputPS(self, file):
76 file.write("%%%%BeginRessource: %s\n" % self.id)
77 file.write("%(body)s /%(id)s exch def\n" % self.__dict__)
78 file.write("%%EndRessource\n")
81 class fontdefinition(prologitem):
83 """ PostScript font definition included in the prolog """
85 def __init__(self, font, fontname, filename, encfilename, usedchars):
86 """ include type 1 font defined by the following parameters
88 - fontname: PostScript FontName of font
89 - filename: name (without path) of file containing the font definition
90 - encfilename: name (without path) of file containing used encoding of font
91 or None (if no encoding file used)
92 - usechars: list with 256 elements containing used charcodes of font
94 """
96 # Note that here we only need the encoding for selecting the used glyphs!
98 # XXX rewrite
100 self.font = font
101 self.fontname = fontname
102 self.filename = filename
103 self.encfilename = encfilename
104 self.usedchars = usedchars
106 def merge(self, other):
107 if not isinstance(other, fontdefinition):
108 return other
109 if self.fontname==other.fontname and self.encfilename==other.encfilename:
110 for i in range(len(self.usedchars)):
111 self.usedchars[i] = self.usedchars[i] or other.usedchars[i]
112 return None
113 else:
114 return other
116 def outputPS(self, file):
117 if self.filename:
118 file.write("%%%%BeginFont: %s\n" % self.fontname)
119 file.write("%Included char codes:")
120 for i in range(len(self.usedchars)):
121 if self.usedchars[i]:
122 file.write(" %d" % i)
123 file.write("\n")
124 pfbpath = pykpathsea.find_file(self.filename, pykpathsea.kpse_type1_format)
125 if not pfbpath:
126 raise RuntimeError("cannot find type 1 font %s" % self.filename)
127 if self.encfilename is not None:
128 encpath = pykpathsea.find_file(self.encfilename, pykpathsea.kpse_tex_ps_header_format)
129 if not encpath:
130 raise RuntimeError("cannot find font encoding file %s" % self.encfilename)
131 t1strip.t1strip(file, pfbpath, self.usedchars, encpath)
132 else:
133 t1strip.t1strip(file, pfbpath, self.usedchars)
134 file.write("%%EndFont\n")
137 class fontencoding(prologitem):
139 """ PostScript font encoding vector included in the prolog """
141 def __init__(self, name, filename):
142 """ include font encoding vector specified by
144 - name: name of the encoding
145 - filename: name (without path) of file containing the font encoding
149 self.name = name
150 self.filename = filename
152 def merge(self, other):
153 if not isinstance(other, fontencoding):
154 return other
155 if self.name==other.name:
156 if self.filename==other.filename:
157 return None
158 raise ValueError("Conflicting encodings!")
159 else:
160 return other
162 def outputPS(self, file):
163 file.write("%%%%BeginProcSet: %s\n" % self.name)
164 path = pykpathsea.find_file(self.filename, pykpathsea.kpse_tex_ps_header_format)
165 encfile = open(path, "r")
166 file.write(encfile.read())
167 encfile.close()
168 file.write("%%EndProcSet\n")
171 class fontreencoding(prologitem):
173 """ PostScript font re-encoding directive included in the prolog """
175 def __init__(self, fontname, basefontname, encname):
176 """ include font re-encoding directive specified by
178 - fontname: PostScript FontName of the new reencoded font
179 - basefontname: PostScript FontName of the original font
180 - encname: name of the encoding
181 - font: a reference to the font instance (temporarily added for pdf support)
183 Before being able to reencode a font, you have to include the
184 encoding via a fontencoding prolog item with name=encname
188 self.fontname = fontname
189 self.basefontname = basefontname
190 self.encname = encname
192 def merge(self, other):
193 if not isinstance(other, fontreencoding):
194 return other
195 if self.fontname==other.fontname:
196 if self.basefontname==other.basefontname and self.encname==other.encname:
197 return None
198 raise ValueError("Conflicting font reencodings!")
199 else:
200 return other
202 def outputPS(self, file):
203 file.write("%%%%BeginProcSet: %s\n" % self.fontname)
204 file.write("/%s /%s %s ReEncodeFont\n" % (self.basefontname, self.fontname, self.encname))
205 file.write("%%EndProcSet\n")