1 # -*- coding: ISO-8859-1 -*-
4 # Copyright (C) 2005-2006 Jörg Lehmann <joergl@users.sourceforge.net>
5 # Copyright (C) 2005-2006 André Wobst <wobsta@users.sourceforge.net>
7 # This file is part of PyX (http://pyx.sourceforge.net/).
9 # PyX is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or
12 # (at your option) any later version.
14 # PyX is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with PyX; if not, write to the Free Software
21 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 import cStringIO
, copy
, time
, math
24 import bbox
, style
, version
, type1font
, unit
, trafo
29 # fallback implementation for Python 2.2 and below
31 return zip(xrange(len(list)), list)
36 # fallback implementation for Python 2.1
39 for key
, value
in list:
47 # in order to keep a consistent order of the registered resources we
48 # not only store them in a hash but also keep an ordered list (up to a
49 # possible merging of resources, in which case the first instance is
51 self
.resourceshash
= {}
52 self
.resourceslist
= []
54 def add(self
, resource
):
55 rkey
= (resource
.type, resource
.id)
56 if self
.resourceshash
.has_key(rkey
):
57 self
.resourceshash
[rkey
].merge(resource
)
59 self
.resourceshash
[rkey
] = resource
60 self
.resourceslist
.append(resource
)
62 def mergeregistry(self
, registry
):
63 for resource
in registry
.resources
:
66 def output(self
, file, writer
):
67 """ write all PostScript code of the prolog resources """
68 for resource
in self
.resourceslist
:
69 resource
.output(file, writer
, self
)
77 """ a PostScript resource """
79 def __init__(self
, type, id):
80 # Every PSresource has to have a type and a unique id.
81 # Resources with the same type and id will be merged
82 # when they are registered in the PSregistry
86 def merge(self
, other
):
87 """ merge self with other, which has to be a resource of the same type and with
91 def output(self
, file, writer
, registry
):
92 raise NotImplementedError("output not implemented for %s" % repr(self
))
95 # Different variants of prolog items
98 class PSdefinition(PSresource
):
100 """ PostScript function definition included in the prolog """
102 def __init__(self
, id, body
):
103 self
.type = "definition"
107 def output(self
, file, writer
, registry
):
108 file.write("%%%%BeginRessource: %s\n" % self
.id)
109 file.write("%(body)s /%(id)s exch def\n" % self
.__dict
__)
110 file.write("%%EndRessource\n")
115 def __init__(self
, document
, file, title
=None):
116 if len(document
.pages
) != 1:
117 raise ValueError("EPS file can be constructed out of a single page document only")
118 page
= document
.pages
[0]
121 pagefile
= cStringIO
.StringIO()
122 registry
= PSregistry()
124 pagebbox
= bbox
.empty()
126 page
.processPS(pagefile
, self
, acontext
, registry
, pagebbox
)
128 file.write("%!PS-Adobe-3.0 EPSF-3.0\n")
130 file.write("%%%%BoundingBox: %d %d %d %d\n" % pagebbox
.lowrestuple_pt())
131 file.write("%%%%HiResBoundingBox: %g %g %g %g\n" % pagebbox
.highrestuple_pt())
132 file.write("%%%%Creator: PyX %s\n" % version
.version
)
133 if title
is not None:
134 file.write("%%%%Title: %s\n" % title
)
135 file.write("%%%%CreationDate: %s\n" %
136 time
.asctime(time
.localtime(time
.time())))
137 file.write("%%EndComments\n")
139 file.write("%%BeginProlog\n")
140 registry
.output(file, self
)
141 file.write("%%EndProlog\n")
143 file.write(pagefile
.getvalue())
146 file.write("showpage\n")
147 file.write("%%Trailer\n")
148 file.write("%%EOF\n")
153 def __init__(self
, document
, file, writebbox
=0, title
=None):
154 # We first have to process the content of the pages, writing them into the stream pagesfile
155 # Doing so, we fill the registry and also calculate the page bounding boxes, which are
156 # stored in page._bbox for every page
157 pagesfile
= cStringIO
.StringIO()
158 registry
= PSregistry()
160 # calculated bounding boxes of the whole document
161 documentbbox
= bbox
.empty()
163 for nr
, page
in enumerate(document
.pages
):
164 # process contents of page
165 pagefile
= cStringIO
.StringIO()
167 pagebbox
= bbox
.empty()
168 page
.processPS(pagefile
, self
, acontext
, registry
, pagebbox
)
170 documentbbox
+= pagebbox
172 pagesfile
.write("%%%%Page: %s %d\n" % (page
.pagename
is None and str(nr
+1) or page
.pagename
, nr
+1))
174 pagesfile
.write("%%%%PageMedia: %s\n" % page
.paperformat
.name
)
175 pagesfile
.write("%%%%PageOrientation: %s\n" % (page
.rotated
and "Landscape" or "Portrait"))
176 if pagebbox
and writebbox
:
177 pagesfile
.write("%%%%PageBoundingBox: %d %d %d %d\n" % pagebbox
.lowrestuple_pt())
180 pagesfile
.write("%%BeginPageSetup\n")
181 pagesfile
.write("/pgsave save def\n")
183 pagesfile
.write("%%EndPageSetup\n")
184 pagesfile
.write(pagefile
.getvalue())
186 pagesfile
.write("pgsave restore\n")
187 pagesfile
.write("showpage\n")
188 pagesfile
.write("%%PageTrailer\n")
190 file.write("%!PS-Adobe-3.0\n")
191 if documentbbox
and writebbox
:
192 file.write("%%%%BoundingBox: %d %d %d %d\n" % documentbbox
.lowrestuple_pt())
193 file.write("%%%%HiResBoundingBox: %g %g %g %g\n" % documentbbox
.highrestuple_pt())
194 file.write("%%%%Creator: PyX %s\n" % version
.version
)
195 if title
is not None:
196 file.write("%%%%Title: %s\n" % title
)
197 file.write("%%%%CreationDate: %s\n" %
198 time
.asctime(time
.localtime(time
.time())))
200 # required paper formats
202 for page
in document
.pages
:
204 paperformats
[page
.paperformat
] = page
.paperformat
207 for paperformat
in paperformats
.values():
209 file.write("%%DocumentMedia: ")
213 file.write("%s %d %d 75 white ()\n" % (paperformat
.name
,
214 unit
.topt(paperformat
.width
),
215 unit
.topt(paperformat
.height
)))
217 # file.write(%%DocumentNeededResources: ") # register not downloaded fonts here
219 file.write("%%%%Pages: %d\n" % len(document
.pages
))
220 file.write("%%PageOrder: Ascend\n")
221 file.write("%%EndComments\n")
223 # document defaults section
224 #file.write("%%BeginDefaults\n")
225 #file.write("%%EndDefaults\n")
227 # document prolog section
228 file.write("%%BeginProlog\n")
229 registry
.output(file, self
)
230 file.write("%%EndProlog\n")
232 # document setup section
233 #file.write("%%BeginSetup\n")
234 #file.write("%%EndSetup\n")
236 file.write(pagesfile
.getvalue())
239 file.write("%%Trailer\n")
240 file.write("%%EOF\n")
245 self
.linewidth_pt
= None
246 self
.colorspace
= None
247 self
.selectedfont
= None
248 # dictionary mapping font names to dictionaries mapping encoding names to encodings
249 # encodings themselves are mappings from glyphnames to codepoints
252 def __call__(self
, **kwargs
):
253 newcontext
= copy
.copy(self
)
254 for key
, value
in kwargs
.items():
255 setattr(newcontext
, key
, value
)