more PDF work: beginnings of text support
[PyX/mjg.git] / pyx / prolog.py
blobfd9c3c5c33fa90d9760a626fc146d5e98f310296
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 PSOp 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, 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 self.fontname = fontname
99 self.filename = filename
100 self.encfilename = encfilename
101 self.usedchars = usedchars
103 def merge(self, other):
104 if not isinstance(other, fontdefinition):
105 return other
106 if self.fontname==other.fontname and self.encfilename==other.encfilename:
107 for i in range(len(self.usedchars)):
108 self.usedchars[i] = self.usedchars[i] or other.usedchars[i]
109 return None
110 else:
111 return other
113 def outputPS(self, file):
114 if self.filename:
115 file.write("%%%%BeginFont: %s\n" % self.fontname)
116 file.write("%Included char codes:")
117 for i in range(len(self.usedchars)):
118 if self.usedchars[i]:
119 file.write(" %d" % i)
120 file.write("\n")
121 pfbpath = pykpathsea.find_file(self.filename, pykpathsea.kpse_type1_format)
122 if not pfbpath:
123 raise RuntimeError("cannot find type 1 font %s" % self.filename)
124 if self.encfilename is not None:
125 encpath = pykpathsea.find_file(self.encfilename, pykpathsea.kpse_tex_ps_header_format)
126 if not encpath:
127 raise RuntimeError("cannot find font encoding file %s" % self.encfilename)
128 t1strip.t1strip(file, pfbpath, self.usedchars, encpath)
129 else:
130 t1strip.t1strip(file, pfbpath, self.usedchars)
131 file.write("%%EndFont\n")
134 class fontencoding(prologitem):
136 """ PostScript font encoding vector included in the prolog """
138 def __init__(self, name, filename):
139 """ include font encoding vector specified by
141 - name: name of the encoding
142 - filename: name (without path) of file containing the font encoding
146 self.name = name
147 self.filename = filename
149 def merge(self, other):
150 if not isinstance(other, fontencoding):
151 return other
152 if self.name==other.name:
153 if self.filename==other.filename:
154 return None
155 raise ValueError("Conflicting encodings!")
156 else:
157 return other
159 def outputPS(self, file):
160 file.write("%%%%BeginProcSet: %s\n" % self.name)
161 path = pykpathsea.find_file(self.filename, pykpathsea.kpse_tex_ps_header_format)
162 encfile = open(path, "r")
163 file.write(encfile.read())
164 encfile.close()
165 file.write("%%EndProcSet\n")
168 class fontreencoding(prologitem):
170 """ PostScript font re-encoding directive included in the prolog """
172 def __init__(self, fontname, basefontname, encname):
173 """ include font re-encoding directive specified by
175 - fontname: PostScript FontName of the new reencoded font
176 - basefontname: PostScript FontName of the original font
177 - encname: name of the encoding
179 Before being able to reencode a font, you have to include the
180 encoding via a fontencoding prolog item with name=encname
184 self.fontname = fontname
185 self.basefontname = basefontname
186 self.encname = encname
188 def merge(self, other):
189 if not isinstance(other, fontreencoding):
190 return other
191 if self.fontname==other.fontname:
192 if self.basefontname==other.basefontname and self.encname==other.encname:
193 return None
194 raise ValueError("Conflicting font reencodings!")
195 else:
196 return other
198 def outputPS(self, file):
199 file.write("%%%%BeginProcSet: %s\n" % self.fontname)
200 file.write("/%s /%s %s ReEncodeFont\n" % (self.basefontname, self.fontname, self.encname))
201 file.write("%%EndProcSet\n")