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
, path
, unit
, trafo
26 # PostScript-procedure definitions
27 # cf. file: 5002.EPSF_Spec_v3.0.pdf
28 # with important correction in EndEPSF:
29 # end operator is missing in the spec!
31 _BeginEPSF
= canvas
.definition("BeginEPSF", """{
32 /b4_Inc_state save def
33 /dict_count countdictstack def
34 /op_count count 1 sub def
37 0 setgray 0 setlinecap
38 1 setlinewidth 0 setlinejoin
39 10 setmiterlimit [ ] 0 setdash newpath
43 {false setstrokeadjust false setoverprint
48 _EndEPSF
= canvas
.definition("EndEPSF", """{
50 count op_count sub {pop} repeat
51 countdictstack dict_count sub {end} repeat
55 def _readbbox(filename
):
56 """returns bounding box of EPS file filename as 4-tuple (llx, lly, urx, ury)"""
59 file = open(filename
, "r")
61 raise IOError, "cannot open EPS file '%s'" % filename
63 bbpattern
= re
.compile( r
"""^%%BoundingBox:\s+([+-]?\d+)
66 \s+([+-]?\d+)\s*$""" , re
.VERBOSE
)
68 for line
in file.xreadlines():
70 if line
=="%%EndComments\n":
71 # TODO: BoundingBox-Deklaration kann auch an Ende von Datei
72 # verschoben worden sein...
73 # ...but evaluation of such a bbox directive requires
74 # a parsing of the DSC!
76 "bounding box not found in header of EPS file '%s'" % \
79 bbmatch
= bbpattern
.match(line
)
80 if bbmatch
is not None:
81 # conversion strings->int
82 (llx
, lly
, urx
, ury
) = map(int, bbmatch
.groups())
83 return bbox
.bbox(llx
, lly
, urx
, ury
)
86 "bounding box not found in EPS file '%s'" % filename
89 class epsfile(base
.PSCmd
):
91 """class for epsfiles"""
95 x
= "0 t m", y
= "0 t m",
96 width
= None, height
= None, scale
=None,
103 inserts EPS file named filename at position (x,y). If clip is
104 set, the result gets clipped to the bbox of the EPS file. If
105 translatebbox is not set, the EPS graphics is not translated to
106 the corresponding origin. With showbb set, the bbox is drawn.
110 self
.filename
= filename
111 self
.mybbox
= _readbbox(self
.filename
)
113 self
._x
= unit
.topt(x
)
114 self
._y
= unit
.topt(y
)
116 # determine scaling in x and y direction
117 self
.scalex
= self
.scaley
= scale
119 if (width
is not None or height
is not None):
120 if scale
is not None:
121 raise ValueError("cannot set both width and/or height and scale simultaneously")
122 if height
is not None:
123 self
.scalex
= unit
.topt(height
)/(self
.mybbox
.urx
-self
.mybbox
.llx
)
124 if width
is not None:
125 self
.scaley
= unit
.topt(width
)/(self
.mybbox
.ury
-self
.mybbox
.lly
)
127 if self
.scalex
is None:
128 self
.scalex
= self
.scaley
130 if self
.scaley
is None:
131 self
.scaley
= self
.scalex
133 # now, we set the actual width and height of the eps file (after a
135 self
._width
= (self
.mybbox
.urx
-self
.mybbox
.llx
)
137 self
._width
*= self
.scalex
139 self
._height
= (self
.mybbox
.ury
-self
.mybbox
.lly
)
141 self
._height
*= self
.scaley
143 # take alignment into account
145 if self
.align
[0]=="b":
147 elif self
.align
[0]=="c":
148 self
._y
-= self
._height
/2.0
149 elif self
.align
[0]=="t":
150 self
._y
-= self
._height
152 raise ValueError("vertical alignment can only be b (bottom), c (center), or t (top)")
154 if self
.align
[1]=="l":
156 elif self
.align
[1]=="c":
157 self
._x
-= self
._width
/2.0
158 elif self
.align
[1]=="r":
159 self
._x
-= self
._width
161 raise ValueError("horizontal alignment can only be l (left), c (center), or r (right)")
164 self
.translatebbox
= translatebbox
165 self
.showbbox
= showbbox
167 self
.trafo
= trafo
._translate
(self
._x
, self
._y
)
169 if self
.scalex
is not None:
170 self
.trafo
= self
.trafo
* trafo
._scale
(self
.scalex
, self
.scaley
)
173 self
.trafo
= self
.trafo
* trafo
._translate
(-self
.mybbox
.llx
, -self
.mybbox
.lly
)
176 return self
.mybbox
.transformed(self
.trafo
)
179 return [_BeginEPSF
, _EndEPSF
]
181 def write(self
, file):
183 epsfile
=open(self
.filename
,"r")
185 raise IOError, "cannot open EPS file '%s'" % self
.filename
187 file.write("BeginEPSF\n")
191 bbrect
= self
.mybbox
.rect().transformed(self
.trafo
)
194 canvas
._newpath
().write(file)
196 canvas
._stroke
().write(file)
199 canvas
._newpath
().write(file)
201 canvas
._clip
().write(file)
203 self
.trafo
.write(file)
205 file.write("%%%%BeginDocument: %s\n" % self
.filename
)
206 file.write(epsfile
.read())
207 file.write("%%EndDocument\n")
208 file.write("EndEPSF\n")