- split out vffile
[PyX/mjg.git] / pyx / dvi / dvifile.py
blobd9b0f60c7c46fe866bf4d78858a4f1887cf6750f
1 # -*- coding: ISO-8859-1 -*-
4 # Copyright (C) 2002-2006 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-2006 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, exceptions, re, struct, string, sys, warnings, math
25 from pyx import unit, epsfile, bbox, canvas, color, trafo, path, pykpathsea, reader
26 import tfmfile, texfont
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
62 _POS_H = 0
63 _POS_V = 1
64 _POS_W = 2
65 _POS_X = 3
66 _POS_Y = 4
67 _POS_Z = 5
69 # reader states
70 _READ_PRE = 1
71 _READ_NOPAGE = 2
72 _READ_PAGE = 3
73 _READ_POST = 4 # XXX not used
74 _READ_POSTPOST = 5 # XXX not used
75 _READ_DONE = 6
78 class DVIError(exceptions.Exception): pass
80 # save and restore colors
82 class _savecolor(canvas.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):
87 file.write("q\n")
90 class _restorecolor(canvas.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):
95 file.write("Q\n")
97 class _savetrafo(canvas.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):
102 file.write("q\n")
105 class _restoretrafo(canvas.canvasitem):
106 def processPS(self, file, writer, context, registry, bbox):
107 file.write("setmatrix\n")
109 def processPDF(self, file, writer, context, registry, bbox):
110 file.write("Q\n")
113 class DVIfile:
115 def __init__(self, filename, debug=0, debugfile=sys.stdout):
116 """ opens the dvi file and reads the preamble """
117 self.filename = filename
118 self.debug = debug
119 self.debugfile = debugfile
120 self.debugstack = []
122 self.fonts = {}
123 self.activefont = None
125 # stack of fonts and fontscale currently used (used for VFs)
126 self.fontstack = []
127 self.stack = []
129 # pointer to currently active page
130 self.actpage = None
132 # stack for self.file, self.fonts and self.stack, needed for VF inclusion
133 self.statestack = []
135 self.file = reader.reader(self.filename)
137 # currently read byte in file (for debugging output)
138 self.filepos = None
140 self._read_pre()
142 # helper routines
144 def flushtext(self):
145 """ finish currently active text object """
146 if self.activetext:
147 x, y, charcodes = self.activetext
148 x_pt, y_pt = x * self.pyxconv, -y*self.pyxconv
149 self.actpage.insert(self.activefont.text_pt(x_pt, y_pt, charcodes))
150 if self.debug:
151 self.debugfile.write("[%s]\n" % "".join([chr(char) for char in self.activetext[2]]))
152 self.activetext = None
154 def putrule(self, height, width, advancepos=1):
155 self.flushtext()
156 x1 = self.pos[_POS_H] * self.pyxconv
157 y1 = -self.pos[_POS_V] * self.pyxconv
158 w = width * self.pyxconv
159 h = height * self.pyxconv
161 if height > 0 and width > 0:
162 if self.debug:
163 self.debugfile.write("%d: %srule height %d, width %d (???x??? pixels)\n" %
164 (self.filepos, advancepos and "set" or "put", height, width))
165 self.actpage.fill(path.rect_pt(x1, y1, w, h))
166 else:
167 if self.debug:
168 self.debugfile.write("%d: %srule height %d, width %d (invisible)\n" %
169 (self.filepos, advancepos and "set" or "put", height, width))
171 if advancepos:
172 if self.debug:
173 self.debugfile.write(" h:=%d+%d=%d, hh:=???\n" %
174 (self.pos[_POS_H], width, self.pos[_POS_H]+width))
175 self.pos[_POS_H] += width
177 def putchar(self, char, advancepos=1, id1234=0):
178 dx = advancepos and self.activefont.getwidth_dvi(char) or 0
180 if self.debug:
181 self.debugfile.write("%d: %s%s%d h:=%d+%d=%d, hh:=???\n" %
182 (self.filepos,
183 advancepos and "set" or "put",
184 id1234 and "%i " % id1234 or "char",
185 char,
186 self.pos[_POS_H], dx, self.pos[_POS_H]+dx))
188 if isinstance(self.activefont, texfont.virtualfont):
189 # virtual font handling
190 afterpos = list(self.pos)
191 afterpos[_POS_H] += dx
192 self._push_dvistring(self.activefont.getchar(char), self.activefont.getfonts(), afterpos,
193 self.activefont.getsize_pt())
194 else:
195 if self.activetext is None:
196 self.activetext = (self.pos[_POS_H], self.pos[_POS_V], [])
197 self.activetext[2].append(char)
198 self.pos[_POS_H] += dx
200 if not advancepos:
201 self.flushtext()
203 def usefont(self, fontnum, id1234=0):
204 self.flushtext()
205 self.activefont = self.fonts[fontnum]
206 if self.debug:
207 self.debugfile.write("%d: fnt%s%i current font is %s\n" %
208 (self.filepos,
209 id1234 and "%i " % id1234 or "num",
210 fontnum,
211 self.fonts[fontnum].name))
214 def definefont(self, cmdnr, num, c, q, d, fontname):
215 # cmdnr: type of fontdef command (only used for debugging output)
216 # c: checksum
217 # q: scaling factor (fix_word)
218 # Note that q is actually s in large parts of the documentation.
219 # d: design size (fix_word)
221 # check whether it's a virtual font
222 vffontpath = pykpathsea.find_file(fontname, pykpathsea.kpse_vf_format)
223 if vffontpath:
224 afont = texfont.virtualfont(fontname, vffontpath, c, q/self.tfmconv, d/self.tfmconv, self.tfmconv, self.pyxconv, self.debug > 1)
225 else:
226 afont = texfont.TeXfont(fontname, c, q/self.tfmconv, d/self.tfmconv, self.tfmconv, self.pyxconv, self.debug > 1)
228 self.fonts[num] = afont
230 if self.debug:
231 self.debugfile.write("%d: fntdef%d %i: %s\n" % (self.filepos, cmdnr, num, fontname))
233 # scale = round((1000.0*self.conv*q)/(self.trueconv*d))
234 # m = 1.0*q/d
235 # scalestring = scale!=1000 and " scaled %d" % scale or ""
236 # print ("Font %i: %s%s---loaded at size %d DVI units" %
237 # (num, fontname, scalestring, q))
238 # if scale!=1000:
239 # print " (this font is magnified %d%%)" % round(scale/10)
241 def special(self, s):
242 x = self.pos[_POS_H] * self.pyxconv
243 y = -self.pos[_POS_V] * self.pyxconv
244 if self.debug:
245 self.debugfile.write("%d: xxx '%s'\n" % (self.filepos, s))
246 if not s.startswith("PyX:"):
247 warnings.warn("ignoring special '%s'" % s)
248 return
250 # it is in general not safe to continue using the currently active font because
251 # the specials may involve some gsave/grestore operations
252 self.flushtext()
254 command, args = s[4:].split()[0], s[4:].split()[1:]
255 if command == "color_begin":
256 if args[0] == "cmyk":
257 c = color.cmyk(float(args[1]), float(args[2]), float(args[3]), float(args[4]))
258 elif args[0] == "gray":
259 c = color.gray(float(args[1]))
260 elif args[0] == "hsb":
261 c = color.hsb(float(args[1]), float(args[2]), float(args[3]))
262 elif args[0] == "rgb":
263 c = color.rgb(float(args[1]), float(args[2]), float(args[3]))
264 elif args[0] == "RGB":
265 c = color.rgb(int(args[1])/255.0, int(args[2])/255.0, int(args[3])/255.0)
266 elif args[0] == "texnamed":
267 try:
268 c = getattr(color.cmyk, args[1])
269 except AttributeError:
270 raise RuntimeError("unknown TeX color '%s', aborting" % args[1])
271 elif args[0] == "pyxcolor":
272 # pyx.color.cmyk.PineGreen or
273 # pyx.color.cmyk(0,0,0,0.0)
274 pat = re.compile(r"(pyx\.)?(color\.)?(?P<model>(cmyk)|(rgb)|(grey)|(gray)|(hsb))[\.]?(?P<arg>.*)")
275 sd = pat.match(" ".join(args[1:]))
276 if sd:
277 sd = sd.groupdict()
278 if sd["arg"][0] == "(":
279 numpat = re.compile(r"[+-]?((\d+\.\d*)|(\d*\.\d+)|(\d+))([eE][+-]\d+)?")
280 arg = tuple([float(x[0]) for x in numpat.findall(sd["arg"])])
281 try:
282 c = getattr(color, sd["model"])(*arg)
283 except TypeError or AttributeError:
284 raise RuntimeError("cannot access PyX color '%s' in TeX, aborting" % " ".join(args[1:]))
285 else:
286 try:
287 c = getattr(getattr(color, sd["model"]), sd["arg"])
288 except AttributeError:
289 raise RuntimeError("cannot access PyX color '%s' in TeX, aborting" % " ".join(args[1:]))
290 else:
291 raise RuntimeError("cannot access PyX color '%s' in TeX, aborting" % " ".join(args[1:]))
292 else:
293 raise RuntimeError("color model '%s' cannot be handled by PyX, aborting" % args[0])
294 self.actpage.insert(_savecolor())
295 self.actpage.insert(c)
296 elif command == "color_end":
297 self.actpage.insert(_restorecolor())
298 elif command == "rotate_begin":
299 self.actpage.insert(_savetrafo())
300 self.actpage.insert(trafo.rotate_pt(float(args[0]), x, y))
301 elif command == "rotate_end":
302 self.actpage.insert(_restoretrafo())
303 elif command == "scale_begin":
304 self.actpage.insert(_savetrafo())
305 self.actpage.insert(trafo.scale_pt(float(args[0]), float(args[1]), x, y))
306 elif command == "scale_end":
307 self.actpage.insert(_restoretrafo())
308 elif command == "epsinclude":
309 # parse arguments
310 argdict = {}
311 for arg in args:
312 name, value = arg.split("=")
313 argdict[name] = value
315 # construct kwargs for epsfile constructor
316 epskwargs = {}
317 epskwargs["filename"] = argdict["file"]
318 epskwargs["bbox"] = bbox.bbox_pt(float(argdict["llx"]), float(argdict["lly"]),
319 float(argdict["urx"]), float(argdict["ury"]))
320 if argdict.has_key("width"):
321 epskwargs["width"] = float(argdict["width"]) * unit.t_pt
322 if argdict.has_key("height"):
323 epskwargs["height"] = float(argdict["height"]) * unit.t_pt
324 if argdict.has_key("clip"):
325 epskwargs["clip"] = int(argdict["clip"])
326 self.actpage.insert(epsfile.epsfile(x * unit.t_pt, y * unit.t_pt, **epskwargs))
327 elif command == "marker":
328 if len(args) != 1:
329 raise RuntimeError("marker contains spaces")
330 for c in args[0]:
331 if c not in string.digits + string.letters + "@":
332 raise RuntimeError("marker contains invalid characters")
333 if self.actpage.markers.has_key(args[0]):
334 raise RuntimeError("marker name occurred several times")
335 self.actpage.markers[args[0]] = x * unit.t_pt, y * unit.t_pt
336 else:
337 raise RuntimeError("unknown PyX special '%s', aborting" % command)
339 # routines for pushing and popping different dvi chunks on the reader
341 def _push_dvistring(self, dvi, fonts, afterpos, fontsize):
342 """ push dvi string with defined fonts on top of reader
343 stack. Every positions gets scaled relatively by the factor
344 scale. After the interpreting of the dvi chunk has been finished,
345 continue with self.pos=afterpos. The designsize of the virtual
346 font is passed as a fix_word
350 #if self.debug:
351 # self.debugfile.write("executing new dvi chunk\n")
352 self.debugstack.append(self.debug)
353 self.debug = 0
355 self.statestack.append((self.file, self.fonts, self.activefont, afterpos, self.stack, self.pyxconv, self.tfmconv))
357 # units in vf files are relative to the size of the font and given as fix_words
358 # which can be converted to floats by diving by 2**20
359 oldpyxconv = self.pyxconv
360 self.pyxconv = fontsize/2**20
361 rescale = self.pyxconv/oldpyxconv
363 self.file = reader.stringreader(dvi)
364 self.fonts = fonts
365 self.stack = []
366 self.filepos = 0
368 # rescale self.pos in order to be consistent with the new scaling
369 self.pos = map(lambda x, rescale=rescale:1.0*x/rescale, self.pos)
371 # since tfmconv converts from tfm units to dvi units, rescale it as well
372 self.tfmconv /= rescale
374 self.usefont(0)
376 def _pop_dvistring(self):
377 self.flushtext()
378 #if self.debug:
379 # self.debugfile.write("finished executing dvi chunk\n")
380 self.debug = self.debugstack.pop()
382 self.file.close()
383 self.file, self.fonts, self.activefont, self.pos, self.stack, self.pyxconv, self.tfmconv = self.statestack.pop()
385 # routines corresponding to the different reader states of the dvi maschine
387 def _read_pre(self):
388 afile = self.file
389 while 1:
390 self.filepos = afile.tell()
391 cmd = afile.readuchar()
392 if cmd == _DVI_NOP:
393 pass
394 elif cmd == _DVI_PRE:
395 if afile.readuchar() != _DVI_VERSION: raise DVIError
396 num = afile.readuint32()
397 den = afile.readuint32()
398 self.mag = afile.readuint32()
400 # For the interpretation of the lengths in dvi and tfm files,
401 # three conversion factors are relevant:
402 # - self.tfmconv: tfm units -> dvi units
403 # - self.pyxconv: dvi units -> (PostScript) points
404 # - self.conv: dvi units -> pixels
405 self.tfmconv = (25400000.0/num)*(den/473628672.0)/16.0
407 # calculate conv as described in the DVIType docu using
408 # a given resolution in dpi
409 self.resolution = 300.0
410 self.conv = (num/254000.0)*(self.resolution/den)
412 # self.pyxconv is the conversion factor from the dvi units
413 # to (PostScript) points. It consists of
414 # - self.mag/1000.0: magstep scaling
415 # - self.conv: conversion from dvi units to pixels
416 # - 1/self.resolution: conversion from pixels to inch
417 # - 72 : conversion from inch to points
418 self.pyxconv = self.mag/1000.0*self.conv/self.resolution*72
420 comment = afile.read(afile.readuchar())
421 return
422 else:
423 raise DVIError
425 def readpage(self, pageid=None):
426 """ reads a page from the dvi file
428 This routine reads a page from the dvi file which is
429 returned as a canvas. When there is no page left in the
430 dvifile, None is returned and the file is closed properly."""
432 while 1:
433 self.filepos = self.file.tell()
434 cmd = self.file.readuchar()
435 if cmd == _DVI_NOP:
436 pass
437 elif cmd == _DVI_BOP:
438 ispageid = [self.file.readuint32() for i in range(10)]
439 if pageid is not None and ispageid != pageid:
440 raise DVIError("invalid pageid")
441 if self.debug:
442 self.debugfile.write("%d: beginning of page %i\n" % (self.filepos, ispageid[0]))
443 self.file.readuint32()
444 break
445 elif cmd == _DVI_POST:
446 self.file.close()
447 return None # nothing left
448 else:
449 raise DVIError
451 self.actpage = canvas.canvas()
452 self.actpage.markers = {}
453 self.pos = [0, 0, 0, 0, 0, 0]
455 # tuple (hpos, vpos, codepoints) to be output, or None if no output is pending
456 self.activetext = None
458 while 1:
459 afile = self.file
460 self.filepos = afile.tell()
461 try:
462 cmd = afile.readuchar()
463 except struct.error:
464 # we most probably (if the dvi file is not corrupt) hit the end of a dvi chunk,
465 # so we have to continue with the rest of the dvi file
466 self._pop_dvistring()
467 continue
468 if cmd == _DVI_NOP:
469 pass
470 if cmd >= _DVI_CHARMIN and cmd <= _DVI_CHARMAX:
471 self.putchar(cmd)
472 elif cmd >= _DVI_SET1234 and cmd < _DVI_SET1234 + 4:
473 self.putchar(afile.readint(cmd - _DVI_SET1234 + 1), id1234=cmd-_DVI_SET1234+1)
474 elif cmd == _DVI_SETRULE:
475 self.putrule(afile.readint32(), afile.readint32())
476 elif cmd >= _DVI_PUT1234 and cmd < _DVI_PUT1234 + 4:
477 self.putchar(afile.readint(cmd - _DVI_PUT1234 + 1), advancepos=0, id1234=cmd-_DVI_SET1234+1)
478 elif cmd == _DVI_PUTRULE:
479 self.putrule(afile.readint32(), afile.readint32(), 0)
480 elif cmd == _DVI_EOP:
481 self.flushtext()
482 if self.debug:
483 self.debugfile.write("%d: eop\n \n" % self.filepos)
484 return self.actpage
485 elif cmd == _DVI_PUSH:
486 self.stack.append(list(self.pos))
487 if self.debug:
488 self.debugfile.write("%s: push\n"
489 "level %d:(h=%d,v=%d,w=%d,x=%d,y=%d,z=%d,hh=???,vv=???)\n" %
490 ((self.filepos, len(self.stack)-1) + tuple(self.pos)))
491 elif cmd == _DVI_POP:
492 self.flushtext()
493 self.pos = self.stack.pop()
494 if self.debug:
495 self.debugfile.write("%s: pop\n"
496 "level %d:(h=%d,v=%d,w=%d,x=%d,y=%d,z=%d,hh=???,vv=???)\n" %
497 ((self.filepos, len(self.stack)) + tuple(self.pos)))
498 elif cmd >= _DVI_RIGHT1234 and cmd < _DVI_RIGHT1234 + 4:
499 self.flushtext()
500 dh = afile.readint(cmd - _DVI_RIGHT1234 + 1, 1)
501 if self.debug:
502 self.debugfile.write("%d: right%d %d h:=%d%+d=%d, hh:=???\n" %
503 (self.filepos,
504 cmd - _DVI_RIGHT1234 + 1,
506 self.pos[_POS_H],
508 self.pos[_POS_H]+dh))
509 self.pos[_POS_H] += dh
510 elif cmd == _DVI_W0:
511 self.flushtext()
512 if self.debug:
513 self.debugfile.write("%d: w0 %d h:=%d%+d=%d, hh:=???\n" %
514 (self.filepos,
515 self.pos[_POS_W],
516 self.pos[_POS_H],
517 self.pos[_POS_W],
518 self.pos[_POS_H]+self.pos[_POS_W]))
519 self.pos[_POS_H] += self.pos[_POS_W]
520 elif cmd >= _DVI_W1234 and cmd < _DVI_W1234 + 4:
521 self.flushtext()
522 self.pos[_POS_W] = afile.readint(cmd - _DVI_W1234 + 1, 1)
523 if self.debug:
524 self.debugfile.write("%d: w%d %d h:=%d%+d=%d, hh:=???\n" %
525 (self.filepos,
526 cmd - _DVI_W1234 + 1,
527 self.pos[_POS_W],
528 self.pos[_POS_H],
529 self.pos[_POS_W],
530 self.pos[_POS_H]+self.pos[_POS_W]))
531 self.pos[_POS_H] += self.pos[_POS_W]
532 elif cmd == _DVI_X0:
533 self.flushtext()
534 if self.debug:
535 self.debugfile.write("%d: x0 %d h:=%d%+d=%d, hh:=???\n" %
536 (self.filepos,
537 self.pos[_POS_X],
538 self.pos[_POS_H],
539 self.pos[_POS_X],
540 self.pos[_POS_H]+self.pos[_POS_X]))
541 self.pos[_POS_H] += self.pos[_POS_X]
542 elif cmd >= _DVI_X1234 and cmd < _DVI_X1234 + 4:
543 self.flushtext()
544 self.pos[_POS_X] = afile.readint(cmd - _DVI_X1234 + 1, 1)
545 if self.debug:
546 self.debugfile.write("%d: x%d %d h:=%d%+d=%d, hh:=???\n" %
547 (self.filepos,
548 cmd - _DVI_X1234 + 1,
549 self.pos[_POS_X],
550 self.pos[_POS_H],
551 self.pos[_POS_X],
552 self.pos[_POS_H]+self.pos[_POS_X]))
553 self.pos[_POS_H] += self.pos[_POS_X]
554 elif cmd >= _DVI_DOWN1234 and cmd < _DVI_DOWN1234 + 4:
555 self.flushtext()
556 dv = afile.readint(cmd - _DVI_DOWN1234 + 1, 1)
557 if self.debug:
558 self.debugfile.write("%d: down%d %d v:=%d%+d=%d, vv:=???\n" %
559 (self.filepos,
560 cmd - _DVI_DOWN1234 + 1,
562 self.pos[_POS_V],
564 self.pos[_POS_V]+dv))
565 self.pos[_POS_V] += dv
566 elif cmd == _DVI_Y0:
567 self.flushtext()
568 if self.debug:
569 self.debugfile.write("%d: y0 %d v:=%d%+d=%d, vv:=???\n" %
570 (self.filepos,
571 self.pos[_POS_Y],
572 self.pos[_POS_V],
573 self.pos[_POS_Y],
574 self.pos[_POS_V]+self.pos[_POS_Y]))
575 self.pos[_POS_V] += self.pos[_POS_Y]
576 elif cmd >= _DVI_Y1234 and cmd < _DVI_Y1234 + 4:
577 self.flushtext()
578 self.pos[_POS_Y] = afile.readint(cmd - _DVI_Y1234 + 1, 1)
579 if self.debug:
580 self.debugfile.write("%d: y%d %d v:=%d%+d=%d, vv:=???\n" %
581 (self.filepos,
582 cmd - _DVI_Y1234 + 1,
583 self.pos[_POS_Y],
584 self.pos[_POS_V],
585 self.pos[_POS_Y],
586 self.pos[_POS_V]+self.pos[_POS_Y]))
587 self.pos[_POS_V] += self.pos[_POS_Y]
588 elif cmd == _DVI_Z0:
589 self.flushtext()
590 if self.debug:
591 self.debugfile.write("%d: z0 %d v:=%d%+d=%d, vv:=???\n" %
592 (self.filepos,
593 self.pos[_POS_Z],
594 self.pos[_POS_V],
595 self.pos[_POS_Z],
596 self.pos[_POS_V]+self.pos[_POS_Z]))
597 self.pos[_POS_V] += self.pos[_POS_Z]
598 elif cmd >= _DVI_Z1234 and cmd < _DVI_Z1234 + 4:
599 self.flushtext()
600 self.pos[_POS_Z] = afile.readint(cmd - _DVI_Z1234 + 1, 1)
601 if self.debug:
602 self.debugfile.write("%d: z%d %d v:=%d%+d=%d, vv:=???\n" %
603 (self.filepos,
604 cmd - _DVI_Z1234 + 1,
605 self.pos[_POS_Z],
606 self.pos[_POS_V],
607 self.pos[_POS_Z],
608 self.pos[_POS_V]+self.pos[_POS_Z]))
609 self.pos[_POS_V] += self.pos[_POS_Z]
610 elif cmd >= _DVI_FNTNUMMIN and cmd <= _DVI_FNTNUMMAX:
611 self.usefont(cmd - _DVI_FNTNUMMIN, 0)
612 elif cmd >= _DVI_FNT1234 and cmd < _DVI_FNT1234 + 4:
613 # note that according to the DVI docs, for four byte font numbers,
614 # the font number is signed. Don't ask why!
615 fntnum = afile.readint(cmd - _DVI_FNT1234 + 1, cmd == _DVI_FNT1234 + 3)
616 self.usefont(fntnum, id1234=cmd-_DVI_FNT1234+1)
617 elif cmd >= _DVI_SPECIAL1234 and cmd < _DVI_SPECIAL1234 + 4:
618 self.special(afile.read(afile.readint(cmd - _DVI_SPECIAL1234 + 1)))
619 elif cmd >= _DVI_FNTDEF1234 and cmd < _DVI_FNTDEF1234 + 4:
620 if cmd == _DVI_FNTDEF1234:
621 num = afile.readuchar()
622 elif cmd == _DVI_FNTDEF1234+1:
623 num = afile.readuint16()
624 elif cmd == _DVI_FNTDEF1234+2:
625 num = afile.readuint24()
626 elif cmd == _DVI_FNTDEF1234+3:
627 # Cool, here we have according to docu a signed int. Why?
628 num = afile.readint32()
629 self.definefont(cmd-_DVI_FNTDEF1234+1,
630 num,
631 afile.readint32(),
632 afile.readint32(),
633 afile.readint32(),
634 afile.read(afile.readuchar()+afile.readuchar()))
635 else:
636 raise DVIError