Applied upstream as r3028 r3025 r3024
[PyX/mjg.git] / pyx / dvi / dvifile.py
blobc92557cf7346f187a7155415ec342109258aa980
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, math, re, string, struct, sys, warnings
25 from pyx import bbox, canvas, canvasitem, color, epsfile, path, pykpathsea, 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
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(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):
87 file.write("q\n")
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):
95 file.write("Q\n")
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):
102 file.write("q\n")
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):
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, fontmap):
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, fontmap=fontmap))
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, fontmap):
155 self.flushtext(fontmap)
156 x1 = self.pos[_POS_H] * self.pyxconv
157 y1 = -self.pos[_POS_V] * self.pyxconv
158 w = width * self.pyxconv * self.scale
159 h = height * self.pyxconv * self.scale
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 * self.scale
177 def putchar(self, char, advancepos, id1234, fontmap):
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(), fontmap)
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(fontmap)
203 def usefont(self, fontnum, id1234, fontmap):
204 self.flushtext(fontmap)
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, fontmap):
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(fontmap)
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, fontmap):
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.scale))
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 # This yields the following scale factor for the height and width of rects:
360 self.scale = fontsize/2**20/self.pyxconv
362 self.file = reader.stringreader(dvi)
363 self.fonts = fonts
364 self.stack = []
365 self.filepos = 0
367 self.usefont(0, 0, fontmap)
369 def _pop_dvistring(self, fontmap):
370 self.flushtext(fontmap)
371 #if self.debug:
372 # self.debugfile.write("finished executing dvi chunk\n")
373 self.debug = self.debugstack.pop()
375 self.file.close()
376 self.file, self.fonts, self.activefont, self.pos, self.stack, self.scale = self.statestack.pop()
378 # routines corresponding to the different reader states of the dvi maschine
380 def _read_pre(self):
381 afile = self.file
382 while 1:
383 self.filepos = afile.tell()
384 cmd = afile.readuchar()
385 if cmd == _DVI_NOP:
386 pass
387 elif cmd == _DVI_PRE:
388 if afile.readuchar() != _DVI_VERSION: raise DVIError
389 num = afile.readuint32()
390 den = afile.readuint32()
391 self.mag = afile.readuint32()
393 # For the interpretation of the lengths in dvi and tfm files,
394 # three conversion factors are relevant:
395 # - self.tfmconv: tfm units -> dvi units
396 # - self.pyxconv: dvi units -> (PostScript) points
397 # - self.conv: dvi units -> pixels
398 self.tfmconv = (25400000.0/num)*(den/473628672.0)/16.0
400 # calculate conv as described in the DVIType docu using
401 # a given resolution in dpi
402 self.resolution = 300.0
403 self.conv = (num/254000.0)*(self.resolution/den)
405 # self.pyxconv is the conversion factor from the dvi units
406 # to (PostScript) points. It consists of
407 # - self.mag/1000.0: magstep scaling
408 # - self.conv: conversion from dvi units to pixels
409 # - 1/self.resolution: conversion from pixels to inch
410 # - 72 : conversion from inch to points
411 self.pyxconv = self.mag/1000.0*self.conv/self.resolution*72
413 # scaling used for rules when VF chunks are interpreted
414 self.scale = 1
416 comment = afile.read(afile.readuchar())
417 return
418 else:
419 raise DVIError
421 def readpage(self, pageid=None, fontmap=None):
422 """ reads a page from the dvi file
424 This routine reads a page from the dvi file which is
425 returned as a canvas. When there is no page left in the
426 dvifile, None is returned and the file is closed properly."""
428 while 1:
429 self.filepos = self.file.tell()
430 cmd = self.file.readuchar()
431 if cmd == _DVI_NOP:
432 pass
433 elif cmd == _DVI_BOP:
434 ispageid = [self.file.readuint32() for i in range(10)]
435 if pageid is not None and ispageid != pageid:
436 raise DVIError("invalid pageid")
437 if self.debug:
438 self.debugfile.write("%d: beginning of page %i\n" % (self.filepos, ispageid[0]))
439 self.file.readuint32()
440 break
441 elif cmd == _DVI_POST:
442 self.file.close()
443 return None # nothing left
444 else:
445 raise DVIError
447 self.actpage = canvas.canvas()
448 self.actpage.markers = {}
449 self.pos = [0, 0, 0, 0, 0, 0]
451 # tuple (hpos, vpos, codepoints) to be output, or None if no output is pending
452 self.activetext = None
454 while 1:
455 afile = self.file
456 self.filepos = afile.tell()
457 try:
458 cmd = afile.readuchar()
459 except struct.error:
460 # we most probably (if the dvi file is not corrupt) hit the end of a dvi chunk,
461 # so we have to continue with the rest of the dvi file
462 self._pop_dvistring(fontmap)
463 continue
464 if cmd == _DVI_NOP:
465 pass
466 if cmd >= _DVI_CHARMIN and cmd <= _DVI_CHARMAX:
467 self.putchar(cmd, True, 0, fontmap)
468 elif cmd >= _DVI_SET1234 and cmd < _DVI_SET1234 + 4:
469 self.putchar(afile.readint(cmd - _DVI_SET1234 + 1), True, cmd-_DVI_SET1234+1, fontmap)
470 elif cmd == _DVI_SETRULE:
471 self.putrule(afile.readint32(), afile.readint32(), True, fontmap)
472 elif cmd >= _DVI_PUT1234 and cmd < _DVI_PUT1234 + 4:
473 self.putchar(afile.readint(cmd - _DVI_PUT1234 + 1), False, cmd-_DVI_SET1234+1, fontmap)
474 elif cmd == _DVI_PUTRULE:
475 self.putrule(afile.readint32(), afile.readint32(), False, fontmap)
476 elif cmd == _DVI_EOP:
477 self.flushtext(fontmap)
478 if self.debug:
479 self.debugfile.write("%d: eop\n \n" % self.filepos)
480 return self.actpage
481 elif cmd == _DVI_PUSH:
482 self.stack.append(list(self.pos))
483 if self.debug:
484 self.debugfile.write("%s: push\n"
485 "level %d:(h=%d,v=%d,w=%d,x=%d,y=%d,z=%d,hh=???,vv=???)\n" %
486 ((self.filepos, len(self.stack)-1) + tuple(self.pos)))
487 elif cmd == _DVI_POP:
488 self.flushtext(fontmap)
489 self.pos = self.stack.pop()
490 if self.debug:
491 self.debugfile.write("%s: pop\n"
492 "level %d:(h=%d,v=%d,w=%d,x=%d,y=%d,z=%d,hh=???,vv=???)\n" %
493 ((self.filepos, len(self.stack)) + tuple(self.pos)))
494 elif cmd >= _DVI_RIGHT1234 and cmd < _DVI_RIGHT1234 + 4:
495 self.flushtext(fontmap)
496 dh = afile.readint(cmd - _DVI_RIGHT1234 + 1, 1)
497 if self.debug:
498 self.debugfile.write("%d: right%d %d h:=%d%+d=%d, hh:=???\n" %
499 (self.filepos,
500 cmd - _DVI_RIGHT1234 + 1,
502 self.pos[_POS_H],
504 self.pos[_POS_H]+dh))
505 self.pos[_POS_H] += dh
506 elif cmd == _DVI_W0:
507 self.flushtext(fontmap)
508 if self.debug:
509 self.debugfile.write("%d: w0 %d h:=%d%+d=%d, hh:=???\n" %
510 (self.filepos,
511 self.pos[_POS_W],
512 self.pos[_POS_H],
513 self.pos[_POS_W],
514 self.pos[_POS_H]+self.pos[_POS_W]))
515 self.pos[_POS_H] += self.pos[_POS_W]
516 elif cmd >= _DVI_W1234 and cmd < _DVI_W1234 + 4:
517 self.flushtext(fontmap)
518 self.pos[_POS_W] = afile.readint(cmd - _DVI_W1234 + 1, 1)
519 if self.debug:
520 self.debugfile.write("%d: w%d %d h:=%d%+d=%d, hh:=???\n" %
521 (self.filepos,
522 cmd - _DVI_W1234 + 1,
523 self.pos[_POS_W],
524 self.pos[_POS_H],
525 self.pos[_POS_W],
526 self.pos[_POS_H]+self.pos[_POS_W]))
527 self.pos[_POS_H] += self.pos[_POS_W]
528 elif cmd == _DVI_X0:
529 self.flushtext(fontmap)
530 if self.debug:
531 self.debugfile.write("%d: x0 %d h:=%d%+d=%d, hh:=???\n" %
532 (self.filepos,
533 self.pos[_POS_X],
534 self.pos[_POS_H],
535 self.pos[_POS_X],
536 self.pos[_POS_H]+self.pos[_POS_X]))
537 self.pos[_POS_H] += self.pos[_POS_X]
538 elif cmd >= _DVI_X1234 and cmd < _DVI_X1234 + 4:
539 self.flushtext(fontmap)
540 self.pos[_POS_X] = afile.readint(cmd - _DVI_X1234 + 1, 1)
541 if self.debug:
542 self.debugfile.write("%d: x%d %d h:=%d%+d=%d, hh:=???\n" %
543 (self.filepos,
544 cmd - _DVI_X1234 + 1,
545 self.pos[_POS_X],
546 self.pos[_POS_H],
547 self.pos[_POS_X],
548 self.pos[_POS_H]+self.pos[_POS_X]))
549 self.pos[_POS_H] += self.pos[_POS_X]
550 elif cmd >= _DVI_DOWN1234 and cmd < _DVI_DOWN1234 + 4:
551 self.flushtext(fontmap)
552 dv = afile.readint(cmd - _DVI_DOWN1234 + 1, 1)
553 if self.debug:
554 self.debugfile.write("%d: down%d %d v:=%d%+d=%d, vv:=???\n" %
555 (self.filepos,
556 cmd - _DVI_DOWN1234 + 1,
558 self.pos[_POS_V],
560 self.pos[_POS_V]+dv))
561 self.pos[_POS_V] += dv
562 elif cmd == _DVI_Y0:
563 self.flushtext(fontmap)
564 if self.debug:
565 self.debugfile.write("%d: y0 %d v:=%d%+d=%d, vv:=???\n" %
566 (self.filepos,
567 self.pos[_POS_Y],
568 self.pos[_POS_V],
569 self.pos[_POS_Y],
570 self.pos[_POS_V]+self.pos[_POS_Y]))
571 self.pos[_POS_V] += self.pos[_POS_Y]
572 elif cmd >= _DVI_Y1234 and cmd < _DVI_Y1234 + 4:
573 self.flushtext(fontmap)
574 self.pos[_POS_Y] = afile.readint(cmd - _DVI_Y1234 + 1, 1)
575 if self.debug:
576 self.debugfile.write("%d: y%d %d v:=%d%+d=%d, vv:=???\n" %
577 (self.filepos,
578 cmd - _DVI_Y1234 + 1,
579 self.pos[_POS_Y],
580 self.pos[_POS_V],
581 self.pos[_POS_Y],
582 self.pos[_POS_V]+self.pos[_POS_Y]))
583 self.pos[_POS_V] += self.pos[_POS_Y]
584 elif cmd == _DVI_Z0:
585 self.flushtext(fontmap)
586 if self.debug:
587 self.debugfile.write("%d: z0 %d v:=%d%+d=%d, vv:=???\n" %
588 (self.filepos,
589 self.pos[_POS_Z],
590 self.pos[_POS_V],
591 self.pos[_POS_Z],
592 self.pos[_POS_V]+self.pos[_POS_Z]))
593 self.pos[_POS_V] += self.pos[_POS_Z]
594 elif cmd >= _DVI_Z1234 and cmd < _DVI_Z1234 + 4:
595 self.flushtext(fontmap)
596 self.pos[_POS_Z] = afile.readint(cmd - _DVI_Z1234 + 1, 1)
597 if self.debug:
598 self.debugfile.write("%d: z%d %d v:=%d%+d=%d, vv:=???\n" %
599 (self.filepos,
600 cmd - _DVI_Z1234 + 1,
601 self.pos[_POS_Z],
602 self.pos[_POS_V],
603 self.pos[_POS_Z],
604 self.pos[_POS_V]+self.pos[_POS_Z]))
605 self.pos[_POS_V] += self.pos[_POS_Z]
606 elif cmd >= _DVI_FNTNUMMIN and cmd <= _DVI_FNTNUMMAX:
607 self.usefont(cmd - _DVI_FNTNUMMIN, 0, fontmap)
608 elif cmd >= _DVI_FNT1234 and cmd < _DVI_FNT1234 + 4:
609 # note that according to the DVI docs, for four byte font numbers,
610 # the font number is signed. Don't ask why!
611 fntnum = afile.readint(cmd - _DVI_FNT1234 + 1, cmd == _DVI_FNT1234 + 3)
612 self.usefont(fntnum, cmd-_DVI_FNT1234+1, fontmap)
613 elif cmd >= _DVI_SPECIAL1234 and cmd < _DVI_SPECIAL1234 + 4:
614 self.special(afile.read(afile.readint(cmd - _DVI_SPECIAL1234 + 1)), fontmap)
615 elif cmd >= _DVI_FNTDEF1234 and cmd < _DVI_FNTDEF1234 + 4:
616 if cmd == _DVI_FNTDEF1234:
617 num = afile.readuchar()
618 elif cmd == _DVI_FNTDEF1234+1:
619 num = afile.readuint16()
620 elif cmd == _DVI_FNTDEF1234+2:
621 num = afile.readuint24()
622 elif cmd == _DVI_FNTDEF1234+3:
623 # Cool, here we have according to docu a signed int. Why?
624 num = afile.readint32()
625 self.definefont(cmd-_DVI_FNTDEF1234+1,
626 num,
627 afile.readint32(),
628 afile.readint32(),
629 afile.readint32(),
630 afile.read(afile.readuchar()+afile.readuchar()))
631 else:
632 raise DVIError