4 # Copyright (C) 2002 Jörg Lehmann <joergl@users.sourceforge.net>
5 # Copyright (C) 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 import base
, bbox
, canvas
, unit
, trafo
26 # PostScript-procedure definitions (cf. 5002.EPSF_Spec_v3.0.pdf)
27 # with important correction in EndEPSF:
28 # end operator is missing in the spec!
30 _BeginEPSF
= canvas
.definition("BeginEPSF", """{
31 /b4_Inc_state save def
32 /dict_count countdictstack def
33 /op_count count 1 sub def
36 0 setgray 0 setlinecap
37 1 setlinewidth 0 setlinejoin
38 10 setmiterlimit [ ] 0 setdash newpath
42 {false setstrokeadjust false setoverprint
47 _EndEPSF
= canvas
.definition("EndEPSF", """{
49 count op_count sub {pop} repeat
50 countdictstack dict_count sub {end} repeat
54 def _readbbox(filename
):
55 """returns bounding box of EPS file filename as 4-tuple (llx, lly, urx, ury)"""
58 file = open(filename
, "r")
60 raise IOError, "cannot open EPS file '%s'" % filename
62 bbpattern
= re
.compile( r
"""^%%BoundingBox:\s+([+-]?\d+)
65 \s+([+-]?\d+)\s*$""" , re
.VERBOSE
)
67 for line
in file.xreadlines():
69 if line
=="%%EndComments\n":
70 # XXX: BoundingBox-Deklaration kann auch an Ende von Datei
71 # verschoben worden sein...
72 # ...but evaluation of such a bbox directive requires
73 # a parsing of the DSC!
75 "bounding box not found in header of EPS file '%s'" % \
78 bbmatch
= bbpattern
.match(line
)
79 if bbmatch
is not None:
80 # conversion strings->int
81 (llx
, lly
, urx
, ury
) = map(int, bbmatch
.groups())
82 return bbox
._bbox
(llx
, lly
, urx
, ury
)
85 "bounding box not found in EPS file '%s'" % filename
88 class epsfile(base
.PSCmd
):
90 """class for epsfiles"""
94 width
=None, height
=None, scale
=None,
101 inserts EPS file named filename at position (x,y). If clip is
102 set, the result gets clipped to the bbox of the EPS file. If
103 translatebbox is not set, the EPS graphics is not translated to
104 the corresponding origin. With showbb set, the bbox is drawn.
108 self
._x
= unit
.topt(x
)
109 self
._y
= unit
.topt(y
)
110 self
.filename
= filename
111 self
.mybbox
= _readbbox(self
.filename
)
113 # determine scaling in x and y direction
114 self
.scalex
= self
.scaley
= scale
116 if (width
is not None or height
is not None):
117 if scale
is not None:
118 raise ValueError("cannot set both width and/or height and scale simultaneously")
119 if height
is not None:
120 self
.scalex
= unit
.topt(height
)/(self
.mybbox
.urx
-self
.mybbox
.llx
)
121 if width
is not None:
122 self
.scaley
= unit
.topt(width
)/(self
.mybbox
.ury
-self
.mybbox
.lly
)
124 if self
.scalex
is None:
125 self
.scalex
= self
.scaley
127 if self
.scaley
is None:
128 self
.scaley
= self
.scalex
130 # set the actual width and height of the eps file (after a
132 self
._width
= (self
.mybbox
.urx
-self
.mybbox
.llx
)
134 self
._width
*= self
.scalex
136 self
._height
= (self
.mybbox
.ury
-self
.mybbox
.lly
)
138 self
._height
*= self
.scaley
140 # take alignment into account
142 if self
.align
[0]=="b":
144 elif self
.align
[0]=="c":
145 self
._y
-= self
._height
/2.0
146 elif self
.align
[0]=="t":
147 self
._y
-= self
._height
149 raise ValueError("vertical alignment can only be b (bottom), c (center), or t (top)")
151 if self
.align
[1]=="l":
153 elif self
.align
[1]=="c":
154 self
._x
-= self
._width
/2.0
155 elif self
.align
[1]=="r":
156 self
._x
-= self
._width
158 raise ValueError("horizontal alignment can only be l (left), c (center), or r (right)")
161 self
.translatebbox
= translatebbox
162 self
.showbbox
= showbbox
164 self
.trafo
= trafo
._translate
(self
._x
, self
._y
)
166 if self
.scalex
is not None:
167 self
.trafo
= self
.trafo
* trafo
._scale
(self
.scalex
, self
.scaley
)
170 self
.trafo
= self
.trafo
* trafo
._translate
(-self
.mybbox
.llx
, -self
.mybbox
.lly
)
173 return self
.mybbox
.transformed(self
.trafo
)
176 return [_BeginEPSF
, _EndEPSF
]
178 def write(self
, file):
180 epsfile
=open(self
.filename
,"r")
182 raise IOError, "cannot open EPS file '%s'" % self
.filename
184 file.write("BeginEPSF\n")
186 bbrect
= self
.mybbox
.rect().transformed(self
.trafo
)
189 canvas
._newpath
().write(file)
191 canvas
._stroke
().write(file)
194 canvas
._newpath
().write(file)
196 canvas
._clip
().write(file)
198 self
.trafo
.write(file)
200 file.write("%%%%BeginDocument: %s\n" % self
.filename
)
201 file.write(epsfile
.read())
202 file.write("%%EndDocument\n")
203 file.write("EndEPSF\n")