1 # -*- encoding: utf-8 -*-
4 # Copyright (C) 2002-2011 Jörg Lehmann <joergl@users.sourceforge.net>
5 # Copyright (C) 2003-2004,2006,2007 Michael Schindler <m-schindler@users.sourceforge.net>
6 # Copyright (C) 2002-2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 import cStringIO
, math
, re
, string
, struct
, sys
, warnings
25 from pyx
import bbox
, canvas
, canvasitem
, color
, epsfile
, filelocator
, path
, reader
, trafo
, unit
26 import texfont
, tfmfile
29 _DVI_CHARMIN
= 0 # typeset a character and move right (range min)
30 _DVI_CHARMAX
= 127 # typeset a character and move right (range max)
31 _DVI_SET1234
= 128 # typeset a character and move right
32 _DVI_SETRULE
= 132 # typeset a rule and move right
33 _DVI_PUT1234
= 133 # typeset a character
34 _DVI_PUTRULE
= 137 # typeset a rule
35 _DVI_NOP
= 138 # no operation
36 _DVI_BOP
= 139 # beginning of page
37 _DVI_EOP
= 140 # ending of page
38 _DVI_PUSH
= 141 # save the current positions (h, v, w, x, y, z)
39 _DVI_POP
= 142 # restore positions (h, v, w, x, y, z)
40 _DVI_RIGHT1234
= 143 # move right
41 _DVI_W0
= 147 # move right by w
42 _DVI_W1234
= 148 # move right and set w
43 _DVI_X0
= 152 # move right by x
44 _DVI_X1234
= 153 # move right and set x
45 _DVI_DOWN1234
= 157 # move down
46 _DVI_Y0
= 161 # move down by y
47 _DVI_Y1234
= 162 # move down and set y
48 _DVI_Z0
= 166 # move down by z
49 _DVI_Z1234
= 167 # move down and set z
50 _DVI_FNTNUMMIN
= 171 # set current font (range min)
51 _DVI_FNTNUMMAX
= 234 # set current font (range max)
52 _DVI_FNT1234
= 235 # set current font
53 _DVI_SPECIAL1234
= 239 # special (dvi extention)
54 _DVI_FNTDEF1234
= 243 # define the meaning of a font number
55 _DVI_PRE
= 247 # preamble
56 _DVI_POST
= 248 # postamble beginning
57 _DVI_POSTPOST
= 249 # postamble ending
59 _DVI_VERSION
= 2 # dvi version
61 # position variable indices
73 _READ_POST
= 4 # XXX not used
74 _READ_POSTPOST
= 5 # XXX not used
78 class DVIError(Exception): pass
80 # save and restore colors
82 class _savecolor(canvasitem
.canvasitem
):
83 def processPS(self
, file, writer
, context
, registry
, bbox
):
84 file.write("currentcolor currentcolorspace\n")
86 def processPDF(self
, file, writer
, context
, registry
, bbox
):
90 class _restorecolor(canvasitem
.canvasitem
):
91 def processPS(self
, file, writer
, context
, registry
, bbox
):
92 file.write("setcolorspace setcolor\n")
94 def processPDF(self
, file, writer
, context
, registry
, bbox
):
97 class _savetrafo(canvasitem
.canvasitem
):
98 def processPS(self
, file, writer
, context
, registry
, bbox
):
99 file.write("matrix currentmatrix\n")
101 def processPDF(self
, file, writer
, context
, registry
, bbox
):
105 class _restoretrafo(canvasitem
.canvasitem
):
106 def processPS(self
, file, writer
, context
, registry
, bbox
):
107 file.write("setmatrix\n")
109 def processPDF(self
, file, writer
, context
, registry
, bbox
):
115 def __init__(self
, filename
, debug
=0, debugfile
=sys
.stdout
, singlecharmode
=0):
116 """ opens the dvi file and reads the preamble """
117 self
.filename
= filename
119 self
.debugfile
= debugfile
121 self
.singlecharmode
= singlecharmode
124 self
.activefont
= None
126 # stack of fonts and fontscale currently used (used for VFs)
130 # pointer to currently active page
133 # stack for self.file, self.fonts and self.stack, needed for VF inclusion
136 self
.file = reader
.reader(self
.filename
)
138 # currently read byte in file (for debugging output)
145 def flushtext(self
, fontmap
):
146 """ finish currently active text object """
148 x
, y
, charcodes
= self
.activetext
149 x_pt
, y_pt
= x
* self
.pyxconv
, -y
*self
.pyxconv
150 self
.actpage
.insert(self
.activefont
.text_pt(x_pt
, y_pt
, charcodes
, fontmap
=fontmap
))
152 self
.debugfile
.write("[%s]\n" % "".join([chr(char
) for char
in self
.activetext
[2]]))
153 self
.activetext
= None
155 def putrule(self
, height
, width
, advancepos
, fontmap
):
156 self
.flushtext(fontmap
)
157 x1
= self
.pos
[_POS_H
] * self
.pyxconv
158 y1
= -self
.pos
[_POS_V
] * self
.pyxconv
159 w
= width
* self
.pyxconv
160 h
= height
* self
.pyxconv
162 if height
> 0 and width
> 0:
164 self
.debugfile
.write("%d: %srule height %d, width %d (???x??? pixels)\n" %
165 (self
.filepos
, advancepos
and "set" or "put", height
, width
))
166 self
.actpage
.fill(path
.rect_pt(x1
, y1
, w
, h
))
169 self
.debugfile
.write("%d: %srule height %d, width %d (invisible)\n" %
170 (self
.filepos
, advancepos
and "set" or "put", height
, width
))
174 self
.debugfile
.write(" h:=%d+%d=%d, hh:=???\n" %
175 (self
.pos
[_POS_H
], width
, self
.pos
[_POS_H
]+width
))
176 self
.pos
[_POS_H
] += width
* self
.scale
178 def putchar(self
, char
, advancepos
, id1234
, fontmap
):
179 dx
= advancepos
and self
.activefont
.getwidth_dvi(char
) or 0
182 self
.debugfile
.write("%d: %s%s%d h:=%d+%d=%d, hh:=???\n" %
184 advancepos
and "set" or "put",
185 id1234
and "%i " % id1234
or "char",
187 self
.pos
[_POS_H
], dx
, self
.pos
[_POS_H
]+dx
))
189 if isinstance(self
.activefont
, texfont
.virtualfont
):
190 # virtual font handling
191 afterpos
= list(self
.pos
)
192 afterpos
[_POS_H
] += dx
193 self
._push
_dvistring
(self
.activefont
.getchar(char
), self
.activefont
.getfonts(), afterpos
,
194 self
.activefont
.getsize_pt(), fontmap
)
196 if self
.activetext
is None:
197 self
.activetext
= (self
.pos
[_POS_H
], self
.pos
[_POS_V
], [])
198 self
.activetext
[2].append(char
)
199 self
.pos
[_POS_H
] += dx
201 if (not advancepos
) or self
.singlecharmode
:
202 self
.flushtext(fontmap
)
204 def usefont(self
, fontnum
, id1234
, fontmap
):
205 self
.flushtext(fontmap
)
206 self
.activefont
= self
.fonts
[fontnum
]
208 self
.debugfile
.write("%d: fnt%s%i current font is %s\n" %
210 id1234
and "%i " % id1234
or "num",
212 self
.fonts
[fontnum
].name
))
215 def definefont(self
, cmdnr
, num
, c
, q
, d
, fontname
):
216 # cmdnr: type of fontdef command (only used for debugging output)
218 # q: scaling factor (fix_word)
219 # Note that q is actually s in large parts of the documentation.
220 # d: design size (fix_word)
222 # check whether it's a virtual font by trying to open it. if this fails, it is an ordinary TeX font
224 fontfile
= filelocator
.open(fontname
, [filelocator
.format
.vf
], mode
="rb")
226 afont
= texfont
.TeXfont(fontname
, c
, q
/self
.tfmconv
, d
/self
.tfmconv
, self
.tfmconv
, self
.pyxconv
, self
.debug
>1)
228 afont
= texfont
.virtualfont(fontname
, fontfile
, c
, q
/self
.tfmconv
, d
/self
.tfmconv
, self
.tfmconv
, self
.pyxconv
, self
.debug
>1)
230 self
.fonts
[num
] = afont
233 self
.debugfile
.write("%d: fntdef%d %i: %s\n" % (self
.filepos
, cmdnr
, num
, fontname
))
235 # scale = round((1000.0*self.conv*q)/(self.trueconv*d))
237 # scalestring = scale!=1000 and " scaled %d" % scale or ""
238 # print ("Font %i: %s%s---loaded at size %d DVI units" %
239 # (num, fontname, scalestring, q))
241 # print " (this font is magnified %d%%)" % round(scale/10)
243 def special(self
, s
, fontmap
):
244 x
= self
.pos
[_POS_H
] * self
.pyxconv
245 y
= -self
.pos
[_POS_V
] * self
.pyxconv
247 self
.debugfile
.write("%d: xxx '%s'\n" % (self
.filepos
, s
))
248 if not s
.startswith("PyX:"):
249 warnings
.warn("ignoring special '%s'" % s
)
252 # it is in general not safe to continue using the currently active font because
253 # the specials may involve some gsave/grestore operations
254 self
.flushtext(fontmap
)
256 command
, args
= s
[4:].split()[0], s
[4:].split()[1:]
257 if command
== "color_begin":
258 if args
[0] == "cmyk":
259 c
= color
.cmyk(float(args
[1]), float(args
[2]), float(args
[3]), float(args
[4]))
260 elif args
[0] == "gray":
261 c
= color
.gray(float(args
[1]))
262 elif args
[0] == "hsb":
263 c
= color
.hsb(float(args
[1]), float(args
[2]), float(args
[3]))
264 elif args
[0] == "rgb":
265 c
= color
.rgb(float(args
[1]), float(args
[2]), float(args
[3]))
266 elif args
[0] == "RGB":
267 c
= color
.rgb(int(args
[1])/255.0, int(args
[2])/255.0, int(args
[3])/255.0)
268 elif args
[0] == "texnamed":
270 c
= getattr(color
.cmyk
, args
[1])
271 except AttributeError:
272 raise RuntimeError("unknown TeX color '%s', aborting" % args
[1])
273 elif args
[0] == "pyxcolor":
274 # pyx.color.cmyk.PineGreen or
275 # pyx.color.cmyk(0,0,0,0.0)
276 pat
= re
.compile(r
"(pyx\.)?(color\.)?(?P<model>(cmyk)|(rgb)|(grey)|(gray)|(hsb))[\.]?(?P<arg>.*)")
277 sd
= pat
.match(" ".join(args
[1:]))
280 if sd
["arg"][0] == "(":
281 numpat
= re
.compile(r
"[+-]?((\d+\.\d*)|(\d*\.\d+)|(\d+))([eE][+-]\d+)?")
282 arg
= tuple([float(x
[0]) for x
in numpat
.findall(sd
["arg"])])
284 c
= getattr(color
, sd
["model"])(*arg
)
285 except TypeError or AttributeError:
286 raise RuntimeError("cannot access PyX color '%s' in TeX, aborting" % " ".join(args
[1:]))
289 c
= getattr(getattr(color
, sd
["model"]), sd
["arg"])
290 except AttributeError:
291 raise RuntimeError("cannot access PyX color '%s' in TeX, aborting" % " ".join(args
[1:]))
293 raise RuntimeError("cannot access PyX color '%s' in TeX, aborting" % " ".join(args
[1:]))
295 raise RuntimeError("color model '%s' cannot be handled by PyX, aborting" % args
[0])
296 self
.actpage
.insert(_savecolor())
297 self
.actpage
.insert(c
)
298 elif command
== "color_end":
299 self
.actpage
.insert(_restorecolor())
300 elif command
== "rotate_begin":
301 self
.actpage
.insert(_savetrafo())
302 self
.actpage
.insert(trafo
.rotate_pt(float(args
[0]), x
, y
))
303 elif command
== "rotate_end":
304 self
.actpage
.insert(_restoretrafo())
305 elif command
== "scale_begin":
306 self
.actpage
.insert(_savetrafo())
307 self
.actpage
.insert(trafo
.scale_pt(float(args
[0]), float(args
[1]), x
, y
))
308 elif command
== "scale_end":
309 self
.actpage
.insert(_restoretrafo())
310 elif command
== "epsinclude":
314 name
, value
= arg
.split("=")
315 argdict
[name
] = value
317 # construct kwargs for epsfile constructor
319 epskwargs
["filename"] = argdict
["file"]
320 epskwargs
["bbox"] = bbox
.bbox_pt(float(argdict
["llx"]), float(argdict
["lly"]),
321 float(argdict
["urx"]), float(argdict
["ury"]))
322 if argdict
.has_key("width"):
323 epskwargs
["width"] = float(argdict
["width"]) * unit
.t_pt
324 if argdict
.has_key("height"):
325 epskwargs
["height"] = float(argdict
["height"]) * unit
.t_pt
326 if argdict
.has_key("clip"):
327 epskwargs
["clip"] = int(argdict
["clip"])
328 self
.actpage
.insert(epsfile
.epsfile(x
* unit
.t_pt
, y
* unit
.t_pt
, **epskwargs
))
329 elif command
== "marker":
331 raise RuntimeError("marker contains spaces")
333 if c
not in string
.digits
+ string
.letters
+ "@":
334 raise RuntimeError("marker contains invalid characters")
335 if self
.actpage
.markers
.has_key(args
[0]):
336 raise RuntimeError("marker name occurred several times")
337 self
.actpage
.markers
[args
[0]] = x
* unit
.t_pt
, y
* unit
.t_pt
339 raise RuntimeError("unknown PyX special '%s', aborting" % command
)
341 # routines for pushing and popping different dvi chunks on the reader
343 def _push_dvistring(self
, dvi
, fonts
, afterpos
, fontsize
, fontmap
):
344 """ push dvi string with defined fonts on top of reader
345 stack. Every positions gets scaled relatively by the factor
346 scale. After interpretating the dvi chunk, continue with self.pos=afterpos.
347 The designsize of the virtual font is passed as a fix_word
352 # self.debugfile.write("executing new dvi chunk\n")
353 self
.debugstack
.append(self
.debug
)
356 self
.statestack
.append((self
.file, self
.fonts
, self
.activefont
, afterpos
, self
.stack
, self
.scale
))
358 # units in vf files are relative to the size of the font and given as fix_words
359 # which can be converted to floats by diving by 2**20.
360 # This yields the following scale factor for the height and width of rects:
361 self
.scale
= fontsize
/2**20/self
.pyxconv
363 self
.file = reader
.stringreader(dvi
)
368 self
.usefont(0, 0, fontmap
)
370 def _pop_dvistring(self
, fontmap
):
371 self
.flushtext(fontmap
)
373 # self.debugfile.write("finished executing dvi chunk\n")
374 self
.debug
= self
.debugstack
.pop()
377 self
.file, self
.fonts
, self
.activefont
, self
.pos
, self
.stack
, self
.scale
= self
.statestack
.pop()
379 # routines corresponding to the different reader states of the dvi maschine
384 self
.filepos
= afile
.tell()
385 cmd
= afile
.readuchar()
388 elif cmd
== _DVI_PRE
:
389 if afile
.readuchar() != _DVI_VERSION
: raise DVIError
390 num
= afile
.readuint32()
391 den
= afile
.readuint32()
392 self
.mag
= afile
.readuint32()
394 # For the interpretation of the lengths in dvi and tfm files,
395 # three conversion factors are relevant:
396 # - self.tfmconv: tfm units -> dvi units
397 # - self.pyxconv: dvi units -> (PostScript) points
398 # - self.conv: dvi units -> pixels
399 self
.tfmconv
= (25400000.0/num
)*(den
/473628672.0)/16.0
401 # calculate conv as described in the DVIType docu using
402 # a given resolution in dpi
403 self
.resolution
= 300.0
404 self
.conv
= (num
/254000.0)*(self
.resolution
/den
)
406 # self.pyxconv is the conversion factor from the dvi units
407 # to (PostScript) points. It consists of
408 # - self.mag/1000.0: magstep scaling
409 # - self.conv: conversion from dvi units to pixels
410 # - 1/self.resolution: conversion from pixels to inch
411 # - 72 : conversion from inch to points
412 self
.pyxconv
= self
.mag
/1000.0*self
.conv
/self
.resolution
*72
414 # scaling used for rules when VF chunks are interpreted
417 comment
= afile
.read(afile
.readuchar())
422 def readpage(self
, pageid
=None, fontmap
=None):
423 """ reads a page from the dvi file
425 This routine reads a page from the dvi file which is
426 returned as a canvas. When there is no page left in the
427 dvifile, None is returned and the file is closed properly."""
430 self
.filepos
= self
.file.tell()
431 cmd
= self
.file.readuchar()
434 elif cmd
== _DVI_BOP
:
435 ispageid
= [self
.file.readuint32() for i
in range(10)]
436 if pageid
is not None and ispageid
!= pageid
:
437 raise DVIError("invalid pageid")
439 self
.debugfile
.write("%d: beginning of page %i\n" % (self
.filepos
, ispageid
[0]))
440 self
.file.readuint32()
442 elif cmd
== _DVI_POST
:
444 return None # nothing left
448 self
.actpage
= canvas
.canvas()
449 self
.actpage
.markers
= {}
450 self
.pos
= [0, 0, 0, 0, 0, 0]
452 # tuple (hpos, vpos, codepoints) to be output, or None if no output is pending
453 self
.activetext
= None
457 self
.filepos
= afile
.tell()
459 cmd
= afile
.readuchar()
461 # we most probably (if the dvi file is not corrupt) hit the end of a dvi chunk,
462 # so we have to continue with the rest of the dvi file
463 self
._pop
_dvistring
(fontmap
)
467 if cmd
>= _DVI_CHARMIN
and cmd
<= _DVI_CHARMAX
:
468 self
.putchar(cmd
, True, 0, fontmap
)
469 elif cmd
>= _DVI_SET1234
and cmd
< _DVI_SET1234
+ 4:
470 self
.putchar(afile
.readint(cmd
- _DVI_SET1234
+ 1), True, cmd
-_DVI_SET1234
+1, fontmap
)
471 elif cmd
== _DVI_SETRULE
:
472 self
.putrule(afile
.readint32()*self
.scale
, afile
.readint32()*self
.scale
, True, fontmap
)
473 elif cmd
>= _DVI_PUT1234
and cmd
< _DVI_PUT1234
+ 4:
474 self
.putchar(afile
.readint(cmd
- _DVI_PUT1234
+ 1), False, cmd
-_DVI_SET1234
+1, fontmap
)
475 elif cmd
== _DVI_PUTRULE
:
476 self
.putrule(afile
.readint32()*self
.scale
, afile
.readint32()*self
.scale
, False, fontmap
)
477 elif cmd
== _DVI_EOP
:
478 self
.flushtext(fontmap
)
480 self
.debugfile
.write("%d: eop\n \n" % self
.filepos
)
482 elif cmd
== _DVI_PUSH
:
483 self
.stack
.append(list(self
.pos
))
485 self
.debugfile
.write("%s: push\n"
486 "level %d:(h=%d,v=%d,w=%d,x=%d,y=%d,z=%d,hh=???,vv=???)\n" %
487 ((self
.filepos
, len(self
.stack
)-1) + tuple(self
.pos
)))
488 elif cmd
== _DVI_POP
:
489 self
.flushtext(fontmap
)
490 self
.pos
= self
.stack
.pop()
492 self
.debugfile
.write("%s: pop\n"
493 "level %d:(h=%d,v=%d,w=%d,x=%d,y=%d,z=%d,hh=???,vv=???)\n" %
494 ((self
.filepos
, len(self
.stack
)) + tuple(self
.pos
)))
495 elif cmd
>= _DVI_RIGHT1234
and cmd
< _DVI_RIGHT1234
+ 4:
496 self
.flushtext(fontmap
)
497 dh
= afile
.readint(cmd
- _DVI_RIGHT1234
+ 1, 1) * self
.scale
499 self
.debugfile
.write("%d: right%d %d h:=%d%+d=%d, hh:=???\n" %
501 cmd
- _DVI_RIGHT1234
+ 1,
505 self
.pos
[_POS_H
]+dh
))
506 self
.pos
[_POS_H
] += dh
508 self
.flushtext(fontmap
)
510 self
.debugfile
.write("%d: w0 %d h:=%d%+d=%d, hh:=???\n" %
515 self
.pos
[_POS_H
]+self
.pos
[_POS_W
]))
516 self
.pos
[_POS_H
] += self
.pos
[_POS_W
]
517 elif cmd
>= _DVI_W1234
and cmd
< _DVI_W1234
+ 4:
518 self
.flushtext(fontmap
)
519 self
.pos
[_POS_W
] = afile
.readint(cmd
- _DVI_W1234
+ 1, 1) * self
.scale
521 self
.debugfile
.write("%d: w%d %d h:=%d%+d=%d, hh:=???\n" %
523 cmd
- _DVI_W1234
+ 1,
527 self
.pos
[_POS_H
]+self
.pos
[_POS_W
]))
528 self
.pos
[_POS_H
] += self
.pos
[_POS_W
]
530 self
.flushtext(fontmap
)
532 self
.debugfile
.write("%d: x0 %d h:=%d%+d=%d, hh:=???\n" %
537 self
.pos
[_POS_H
]+self
.pos
[_POS_X
]))
538 self
.pos
[_POS_H
] += self
.pos
[_POS_X
]
539 elif cmd
>= _DVI_X1234
and cmd
< _DVI_X1234
+ 4:
540 self
.flushtext(fontmap
)
541 self
.pos
[_POS_X
] = afile
.readint(cmd
- _DVI_X1234
+ 1, 1) * self
.scale
543 self
.debugfile
.write("%d: x%d %d h:=%d%+d=%d, hh:=???\n" %
545 cmd
- _DVI_X1234
+ 1,
549 self
.pos
[_POS_H
]+self
.pos
[_POS_X
]))
550 self
.pos
[_POS_H
] += self
.pos
[_POS_X
]
551 elif cmd
>= _DVI_DOWN1234
and cmd
< _DVI_DOWN1234
+ 4:
552 self
.flushtext(fontmap
)
553 dv
= afile
.readint(cmd
- _DVI_DOWN1234
+ 1, 1) * self
.scale
555 self
.debugfile
.write("%d: down%d %d v:=%d%+d=%d, vv:=???\n" %
557 cmd
- _DVI_DOWN1234
+ 1,
561 self
.pos
[_POS_V
]+dv
))
562 self
.pos
[_POS_V
] += dv
564 self
.flushtext(fontmap
)
566 self
.debugfile
.write("%d: y0 %d v:=%d%+d=%d, vv:=???\n" %
571 self
.pos
[_POS_V
]+self
.pos
[_POS_Y
]))
572 self
.pos
[_POS_V
] += self
.pos
[_POS_Y
]
573 elif cmd
>= _DVI_Y1234
and cmd
< _DVI_Y1234
+ 4:
574 self
.flushtext(fontmap
)
575 self
.pos
[_POS_Y
] = afile
.readint(cmd
- _DVI_Y1234
+ 1, 1) * self
.scale
577 self
.debugfile
.write("%d: y%d %d v:=%d%+d=%d, vv:=???\n" %
579 cmd
- _DVI_Y1234
+ 1,
583 self
.pos
[_POS_V
]+self
.pos
[_POS_Y
]))
584 self
.pos
[_POS_V
] += self
.pos
[_POS_Y
]
586 self
.flushtext(fontmap
)
588 self
.debugfile
.write("%d: z0 %d v:=%d%+d=%d, vv:=???\n" %
593 self
.pos
[_POS_V
]+self
.pos
[_POS_Z
]))
594 self
.pos
[_POS_V
] += self
.pos
[_POS_Z
]
595 elif cmd
>= _DVI_Z1234
and cmd
< _DVI_Z1234
+ 4:
596 self
.flushtext(fontmap
)
597 self
.pos
[_POS_Z
] = afile
.readint(cmd
- _DVI_Z1234
+ 1, 1) * self
.scale
599 self
.debugfile
.write("%d: z%d %d v:=%d%+d=%d, vv:=???\n" %
601 cmd
- _DVI_Z1234
+ 1,
605 self
.pos
[_POS_V
]+self
.pos
[_POS_Z
]))
606 self
.pos
[_POS_V
] += self
.pos
[_POS_Z
]
607 elif cmd
>= _DVI_FNTNUMMIN
and cmd
<= _DVI_FNTNUMMAX
:
608 self
.usefont(cmd
- _DVI_FNTNUMMIN
, 0, fontmap
)
609 elif cmd
>= _DVI_FNT1234
and cmd
< _DVI_FNT1234
+ 4:
610 # note that according to the DVI docs, for four byte font numbers,
611 # the font number is signed. Don't ask why!
612 fntnum
= afile
.readint(cmd
- _DVI_FNT1234
+ 1, cmd
== _DVI_FNT1234
+ 3)
613 self
.usefont(fntnum
, cmd
-_DVI_FNT1234
+1, fontmap
)
614 elif cmd
>= _DVI_SPECIAL1234
and cmd
< _DVI_SPECIAL1234
+ 4:
615 self
.special(afile
.read(afile
.readint(cmd
- _DVI_SPECIAL1234
+ 1)), fontmap
)
616 elif cmd
>= _DVI_FNTDEF1234
and cmd
< _DVI_FNTDEF1234
+ 4:
617 if cmd
== _DVI_FNTDEF1234
:
618 num
= afile
.readuchar()
619 elif cmd
== _DVI_FNTDEF1234
+1:
620 num
= afile
.readuint16()
621 elif cmd
== _DVI_FNTDEF1234
+2:
622 num
= afile
.readuint24()
623 elif cmd
== _DVI_FNTDEF1234
+3:
624 # Cool, here we have according to docu a signed int. Why?
625 num
= afile
.readint32()
626 self
.definefont(cmd
-_DVI_FNTDEF1234
+1,
631 afile
.read(afile
.readuchar()+afile
.readuchar()))