introduce ascii mode in config.open
[PyX.git] / dvi / dvifile.py
blobd0318e4293609fd9c95c4789a53e98879f3be173
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 io, math, re, struct, sys, warnings
25 from pyx import bbox, canvas, color, epsfile, config, path, reader, trafo, unit
26 from . 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
81 class DVIfile:
83 def __init__(self, filename, debug=0, debugfile=sys.stdout):
84 """ opens the dvi file and reads the preamble """
85 self.filename = filename
86 self.debug = debug
87 self.debugfile = debugfile
88 self.debugstack = []
90 self.fonts = {}
91 self.activefont = None
93 # stack of fonts and fontscale currently used (used for VFs)
94 self.fontstack = []
95 self.stack = []
97 # pointer to currently active page
98 self.actpage = None
100 # stack for self.file, self.fonts and self.stack, needed for VF inclusion
101 self.statestack = []
103 self.file = reader.reader(self.filename)
105 # currently read byte in file (for debugging output)
106 self.filepos = None
108 self._read_pre()
110 # helper routines
112 def beginsubpage(self, attrs):
113 c = canvas.canvas(attrs)
114 c.parent = self.actpage
115 c.markers = {}
116 self.actpage.insert(c)
117 self.actpage = c
119 def endsubpage(self):
120 for key, value in list(self.actpage.markers.items()):
121 self.actpage.parent.markers[key] = self.actpage.trafo.apply(*value)
122 self.actpage = self.actpage.parent
124 def flushtext(self, fontmap):
125 """ finish currently active text object """
126 if self.activetext:
127 x, y, charcodes = self.activetext
128 x_pt, y_pt = x * self.pyxconv, -y*self.pyxconv
129 self.actpage.insert(self.activefont.text_pt(x_pt, y_pt, charcodes, fontmap=fontmap))
130 if self.debug:
131 self.debugfile.write("[%s]\n" % "".join([chr(char) for char in self.activetext[2]]))
132 self.activetext = None
134 def putrule(self, height, width, advancepos, fontmap):
135 self.flushtext(fontmap)
136 x1 = self.pos[_POS_H] * self.pyxconv
137 y1 = -self.pos[_POS_V] * self.pyxconv
138 w = width * self.pyxconv
139 h = height * self.pyxconv
141 if height > 0 and width > 0:
142 if self.debug:
143 self.debugfile.write("%d: %srule height %d, width %d (???x??? pixels)\n" %
144 (self.filepos, advancepos and "set" or "put", height, width))
145 self.actpage.fill(path.rect_pt(x1, y1, w, h))
146 else:
147 if self.debug:
148 self.debugfile.write("%d: %srule height %d, width %d (invisible)\n" %
149 (self.filepos, advancepos and "set" or "put", height, width))
151 if advancepos:
152 if self.debug:
153 self.debugfile.write(" h:=%d+%d=%d, hh:=???\n" %
154 (self.pos[_POS_H], width, self.pos[_POS_H]+width))
155 self.pos[_POS_H] += width * self.scale
157 def putchar(self, char, advancepos, id1234, fontmap):
158 dx = advancepos and self.activefont.getwidth_dvi(char) or 0
160 if self.debug:
161 self.debugfile.write("%d: %s%s%d h:=%d+%d=%d, hh:=???\n" %
162 (self.filepos,
163 advancepos and "set" or "put",
164 id1234 and "%i " % id1234 or "char",
165 char,
166 self.pos[_POS_H], dx, self.pos[_POS_H]+dx))
168 if isinstance(self.activefont, texfont.virtualfont):
169 # virtual font handling
170 afterpos = list(self.pos)
171 afterpos[_POS_H] += dx
172 self._push_dvistring(self.activefont.getchar(char), self.activefont.getfonts(), afterpos,
173 self.activefont.getsize_pt(), fontmap)
174 else:
175 if self.activetext is None:
176 self.activetext = (self.pos[_POS_H], self.pos[_POS_V], [])
177 self.activetext[2].append(char)
178 self.pos[_POS_H] += dx
180 if (not advancepos) or self.singlecharmode:
181 self.flushtext(fontmap)
183 def usefont(self, fontnum, id1234, fontmap):
184 self.flushtext(fontmap)
185 self.activefont = self.fonts[fontnum]
186 if self.debug:
187 self.debugfile.write("%d: fnt%s%i current font is %s\n" %
188 (self.filepos,
189 id1234 and "%i " % id1234 or "num",
190 fontnum,
191 self.fonts[fontnum].name))
194 def definefont(self, cmdnr, num, c, q, d, fontname):
195 # cmdnr: type of fontdef command (only used for debugging output)
196 # c: checksum
197 # q: scaling factor (fix_word)
198 # Note that q is actually s in large parts of the documentation.
199 # d: design size (fix_word)
201 # check whether it's a virtual font by trying to open it. if this fails, it is an ordinary TeX font
202 try:
203 fontfile = config.open(fontname, [config.format.vf])
204 except IOError:
205 afont = texfont.TeXfont(fontname, c, q/self.tfmconv, d/self.tfmconv, self.tfmconv, self.pyxconv, self.debug>1)
206 else:
207 afont = texfont.virtualfont(fontname, fontfile, c, q/self.tfmconv, d/self.tfmconv, self.tfmconv, self.pyxconv, self.debug>1)
209 self.fonts[num] = afont
211 if self.debug:
212 self.debugfile.write("%d: fntdef%d %i: %s\n" % (self.filepos, cmdnr, num, fontname))
214 # scale = round((1000.0*self.conv*q)/(self.trueconv*d))
215 # m = 1.0*q/d
216 # scalestring = scale!=1000 and " scaled %d" % scale or ""
217 # print ("Font %i: %s%s---loaded at size %d DVI units" %
218 # (num, fontname, scalestring, q))
219 # if scale!=1000:
220 # print " (this font is magnified %d%%)" % round(scale/10)
222 def special(self, s, fontmap):
223 x = self.pos[_POS_H] * self.pyxconv
224 y = -self.pos[_POS_V] * self.pyxconv
225 if self.debug:
226 self.debugfile.write("%d: xxx '%s'\n" % (self.filepos, s))
227 if not s.startswith("PyX:"):
228 warnings.warn("ignoring special '%s'" % s)
229 return
231 # it is in general not safe to continue using the currently active font because
232 # the specials may involve some gsave/grestore operations
233 self.flushtext(fontmap)
235 command, args = s[4:].split()[0], s[4:].split()[1:]
236 if command == "color_begin":
237 if args[0] == "cmyk":
238 c = color.cmyk(float(args[1]), float(args[2]), float(args[3]), float(args[4]))
239 elif args[0] == "gray":
240 c = color.gray(float(args[1]))
241 elif args[0] == "hsb":
242 c = color.hsb(float(args[1]), float(args[2]), float(args[3]))
243 elif args[0] == "rgb":
244 c = color.rgb(float(args[1]), float(args[2]), float(args[3]))
245 elif args[0] == "RGB":
246 c = color.rgb(int(args[1])/255.0, int(args[2])/255.0, int(args[3])/255.0)
247 elif args[0] == "texnamed":
248 try:
249 c = getattr(color.cmyk, args[1])
250 except AttributeError:
251 raise RuntimeError("unknown TeX color '%s', aborting" % args[1])
252 elif args[0] == "pyxcolor":
253 # pyx.color.cmyk.PineGreen or
254 # pyx.color.cmyk(0,0,0,0.0)
255 pat = re.compile(r"(pyx\.)?(color\.)?(?P<model>(cmyk)|(rgb)|(grey)|(gray)|(hsb))[\.]?(?P<arg>.*)")
256 sd = pat.match(" ".join(args[1:]))
257 if sd:
258 sd = sd.groupdict()
259 if sd["arg"][0] == "(":
260 numpat = re.compile(r"[+-]?((\d+\.\d*)|(\d*\.\d+)|(\d+))([eE][+-]\d+)?")
261 arg = tuple([float(x[0]) for x in numpat.findall(sd["arg"])])
262 try:
263 c = getattr(color, sd["model"])(*arg)
264 except TypeError or AttributeError:
265 raise RuntimeError("cannot access PyX color '%s' in TeX, aborting" % " ".join(args[1:]))
266 else:
267 try:
268 c = getattr(getattr(color, sd["model"]), sd["arg"])
269 except AttributeError:
270 raise RuntimeError("cannot access PyX color '%s' in TeX, aborting" % " ".join(args[1:]))
271 else:
272 raise RuntimeError("cannot access PyX color '%s' in TeX, aborting" % " ".join(args[1:]))
273 else:
274 raise RuntimeError("color model '%s' cannot be handled by PyX, aborting" % args[0])
276 self.beginsubpage([c])
277 elif command == "color_end":
278 self.endsubpage()
279 elif command == "rotate_begin":
280 self.beginsubpage([trafo.rotate_pt(float(args[0]), x, y)])
281 elif command == "rotate_end":
282 self.endsubpage()
283 elif command == "scale_begin":
284 self.beginsubpage([trafo.scale_pt(float(args[0]), float(args[1]), x, y)])
285 elif command == "scale_end":
286 self.endsubpage()
287 elif command == "epsinclude":
288 # parse arguments
289 argdict = {}
290 for arg in args:
291 name, value = arg.split("=")
292 argdict[name] = value
294 # construct kwargs for epsfile constructor
295 epskwargs = {}
296 epskwargs["filename"] = argdict["file"]
297 epskwargs["bbox"] = bbox.bbox_pt(float(argdict["llx"]), float(argdict["lly"]),
298 float(argdict["urx"]), float(argdict["ury"]))
299 if "width" in argdict:
300 epskwargs["width"] = float(argdict["width"]) * unit.t_pt
301 if "height" in argdict:
302 epskwargs["height"] = float(argdict["height"]) * unit.t_pt
303 if "clip" in argdict:
304 epskwargs["clip"] = int(argdict["clip"])
305 self.actpage.insert(epsfile.epsfile(x * unit.t_pt, y * unit.t_pt, **epskwargs))
306 elif command == "marker":
307 if len(args) != 1:
308 raise RuntimeError("marker contains spaces")
309 for c in args[0]:
310 if c not in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@":
311 raise RuntimeError("marker contains invalid characters")
312 if args[0] in self.actpage.markers:
313 raise RuntimeError("marker name occurred several times")
314 self.actpage.markers[args[0]] = x * unit.t_pt, y * unit.t_pt
315 else:
316 raise RuntimeError("unknown PyX special '%s', aborting" % command)
318 # routines for pushing and popping different dvi chunks on the reader
320 def _push_dvistring(self, dvi, fonts, afterpos, fontsize, fontmap):
321 """ push dvi string with defined fonts on top of reader
322 stack. Every positions gets scaled relatively by the factor
323 scale. After interpretating the dvi chunk, continue with self.pos=afterpos.
324 The designsize of the virtual font is passed as a fix_word
328 #if self.debug:
329 # self.debugfile.write("executing new dvi chunk\n")
330 self.debugstack.append(self.debug)
331 self.debug = 0
333 self.statestack.append((self.file, self.fonts, self.activefont, afterpos, self.stack, self.scale))
335 # units in vf files are relative to the size of the font and given as fix_words
336 # which can be converted to floats by diving by 2**20.
337 # This yields the following scale factor for the height and width of rects:
338 self.scale = fontsize/2**20/self.pyxconv
340 self.file = reader.bytesreader(dvi)
341 self.fonts = fonts
342 self.stack = []
343 self.filepos = 0
345 self.usefont(0, 0, fontmap)
347 def _pop_dvistring(self, fontmap):
348 self.flushtext(fontmap)
349 #if self.debug:
350 # self.debugfile.write("finished executing dvi chunk\n")
351 self.debug = self.debugstack.pop()
353 self.file.close()
354 self.file, self.fonts, self.activefont, self.pos, self.stack, self.scale = self.statestack.pop()
356 # routines corresponding to the different reader states of the dvi maschine
358 def _read_pre(self):
359 afile = self.file
360 while True:
361 self.filepos = afile.tell()
362 cmd = afile.readuchar()
363 if cmd == _DVI_NOP:
364 pass
365 elif cmd == _DVI_PRE:
366 if afile.readuchar() != _DVI_VERSION: raise DVIError
367 num = afile.readuint32()
368 den = afile.readuint32()
369 self.mag = afile.readuint32()
371 # For the interpretation of the lengths in dvi and tfm files,
372 # three conversion factors are relevant:
373 # - self.tfmconv: tfm units -> dvi units
374 # - self.pyxconv: dvi units -> (PostScript) points
375 # - self.conv: dvi units -> pixels
376 self.tfmconv = (25400000.0/num)*(den/473628672.0)/16.0
378 # calculate conv as described in the DVIType docu using
379 # a given resolution in dpi
380 self.resolution = 300.0
381 self.conv = (num/254000.0)*(self.resolution/den)
383 # self.pyxconv is the conversion factor from the dvi units
384 # to (PostScript) points. It consists of
385 # - self.mag/1000.0: magstep scaling
386 # - self.conv: conversion from dvi units to pixels
387 # - 1/self.resolution: conversion from pixels to inch
388 # - 72 : conversion from inch to points
389 self.pyxconv = self.mag/1000.0*self.conv/self.resolution*72
391 # scaling used for rules when VF chunks are interpreted
392 self.scale = 1
394 comment = afile.read(afile.readuchar())
395 return
396 else:
397 raise DVIError
399 def readpage(self, pageid=None, fontmap=None, singlecharmode=False):
400 """ reads a page from the dvi file
402 This routine reads a page from the dvi file which is
403 returned as a canvas. When there is no page left in the
404 dvifile, None is returned and the file is closed properly."""
406 self.singlecharmode = singlecharmode
408 while True:
409 self.filepos = self.file.tell()
410 cmd = self.file.readuchar()
411 if cmd == _DVI_NOP:
412 pass
413 elif cmd == _DVI_BOP:
414 ispageid = [self.file.readuint32() for i in range(10)]
415 if pageid is not None and ispageid != pageid:
416 raise DVIError("invalid pageid")
417 if self.debug:
418 self.debugfile.write("%d: beginning of page %i\n" % (self.filepos, ispageid[0]))
419 self.file.readuint32()
420 break
421 elif cmd == _DVI_POST:
422 self.file.close()
423 return None # nothing left
424 else:
425 raise DVIError
427 self.actpage = canvas.canvas()
428 self.actpage.markers = {}
429 self.pos = [0, 0, 0, 0, 0, 0]
431 # tuple (hpos, vpos, codepoints) to be output, or None if no output is pending
432 self.activetext = None
434 while True:
435 afile = self.file
436 self.filepos = afile.tell()
437 try:
438 cmd = afile.readuchar()
439 except struct.error:
440 # we most probably (if the dvi file is not corrupt) hit the end of a dvi chunk,
441 # so we have to continue with the rest of the dvi file
442 self._pop_dvistring(fontmap)
443 continue
444 if cmd == _DVI_NOP:
445 pass
446 if cmd >= _DVI_CHARMIN and cmd <= _DVI_CHARMAX:
447 self.putchar(cmd, True, 0, fontmap)
448 elif cmd >= _DVI_SET1234 and cmd < _DVI_SET1234 + 4:
449 self.putchar(afile.readint(cmd - _DVI_SET1234 + 1), True, cmd-_DVI_SET1234+1, fontmap)
450 elif cmd == _DVI_SETRULE:
451 self.putrule(afile.readint32()*self.scale, afile.readint32()*self.scale, True, fontmap)
452 elif cmd >= _DVI_PUT1234 and cmd < _DVI_PUT1234 + 4:
453 self.putchar(afile.readint(cmd - _DVI_PUT1234 + 1), False, cmd-_DVI_SET1234+1, fontmap)
454 elif cmd == _DVI_PUTRULE:
455 self.putrule(afile.readint32()*self.scale, afile.readint32()*self.scale, False, fontmap)
456 elif cmd == _DVI_EOP:
457 self.flushtext(fontmap)
458 if self.debug:
459 self.debugfile.write("%d: eop\n \n" % self.filepos)
460 return self.actpage
461 elif cmd == _DVI_PUSH:
462 self.stack.append(list(self.pos))
463 if self.debug:
464 self.debugfile.write("%s: push\n"
465 "level %d:(h=%d,v=%d,w=%d,x=%d,y=%d,z=%d,hh=???,vv=???)\n" %
466 ((self.filepos, len(self.stack)-1) + tuple(self.pos)))
467 elif cmd == _DVI_POP:
468 self.flushtext(fontmap)
469 self.pos = self.stack.pop()
470 if self.debug:
471 self.debugfile.write("%s: pop\n"
472 "level %d:(h=%d,v=%d,w=%d,x=%d,y=%d,z=%d,hh=???,vv=???)\n" %
473 ((self.filepos, len(self.stack)) + tuple(self.pos)))
474 elif cmd >= _DVI_RIGHT1234 and cmd < _DVI_RIGHT1234 + 4:
475 self.flushtext(fontmap)
476 dh = afile.readint(cmd - _DVI_RIGHT1234 + 1, 1) * self.scale
477 if self.debug:
478 self.debugfile.write("%d: right%d %d h:=%d%+d=%d, hh:=???\n" %
479 (self.filepos,
480 cmd - _DVI_RIGHT1234 + 1,
482 self.pos[_POS_H],
484 self.pos[_POS_H]+dh))
485 self.pos[_POS_H] += dh
486 elif cmd == _DVI_W0:
487 self.flushtext(fontmap)
488 if self.debug:
489 self.debugfile.write("%d: w0 %d h:=%d%+d=%d, hh:=???\n" %
490 (self.filepos,
491 self.pos[_POS_W],
492 self.pos[_POS_H],
493 self.pos[_POS_W],
494 self.pos[_POS_H]+self.pos[_POS_W]))
495 self.pos[_POS_H] += self.pos[_POS_W]
496 elif cmd >= _DVI_W1234 and cmd < _DVI_W1234 + 4:
497 self.flushtext(fontmap)
498 self.pos[_POS_W] = afile.readint(cmd - _DVI_W1234 + 1, 1) * self.scale
499 if self.debug:
500 self.debugfile.write("%d: w%d %d h:=%d%+d=%d, hh:=???\n" %
501 (self.filepos,
502 cmd - _DVI_W1234 + 1,
503 self.pos[_POS_W],
504 self.pos[_POS_H],
505 self.pos[_POS_W],
506 self.pos[_POS_H]+self.pos[_POS_W]))
507 self.pos[_POS_H] += self.pos[_POS_W]
508 elif cmd == _DVI_X0:
509 self.flushtext(fontmap)
510 if self.debug:
511 self.debugfile.write("%d: x0 %d h:=%d%+d=%d, hh:=???\n" %
512 (self.filepos,
513 self.pos[_POS_X],
514 self.pos[_POS_H],
515 self.pos[_POS_X],
516 self.pos[_POS_H]+self.pos[_POS_X]))
517 self.pos[_POS_H] += self.pos[_POS_X]
518 elif cmd >= _DVI_X1234 and cmd < _DVI_X1234 + 4:
519 self.flushtext(fontmap)
520 self.pos[_POS_X] = afile.readint(cmd - _DVI_X1234 + 1, 1) * self.scale
521 if self.debug:
522 self.debugfile.write("%d: x%d %d h:=%d%+d=%d, hh:=???\n" %
523 (self.filepos,
524 cmd - _DVI_X1234 + 1,
525 self.pos[_POS_X],
526 self.pos[_POS_H],
527 self.pos[_POS_X],
528 self.pos[_POS_H]+self.pos[_POS_X]))
529 self.pos[_POS_H] += self.pos[_POS_X]
530 elif cmd >= _DVI_DOWN1234 and cmd < _DVI_DOWN1234 + 4:
531 self.flushtext(fontmap)
532 dv = afile.readint(cmd - _DVI_DOWN1234 + 1, 1) * self.scale
533 if self.debug:
534 self.debugfile.write("%d: down%d %d v:=%d%+d=%d, vv:=???\n" %
535 (self.filepos,
536 cmd - _DVI_DOWN1234 + 1,
538 self.pos[_POS_V],
540 self.pos[_POS_V]+dv))
541 self.pos[_POS_V] += dv
542 elif cmd == _DVI_Y0:
543 self.flushtext(fontmap)
544 if self.debug:
545 self.debugfile.write("%d: y0 %d v:=%d%+d=%d, vv:=???\n" %
546 (self.filepos,
547 self.pos[_POS_Y],
548 self.pos[_POS_V],
549 self.pos[_POS_Y],
550 self.pos[_POS_V]+self.pos[_POS_Y]))
551 self.pos[_POS_V] += self.pos[_POS_Y]
552 elif cmd >= _DVI_Y1234 and cmd < _DVI_Y1234 + 4:
553 self.flushtext(fontmap)
554 self.pos[_POS_Y] = afile.readint(cmd - _DVI_Y1234 + 1, 1) * self.scale
555 if self.debug:
556 self.debugfile.write("%d: y%d %d v:=%d%+d=%d, vv:=???\n" %
557 (self.filepos,
558 cmd - _DVI_Y1234 + 1,
559 self.pos[_POS_Y],
560 self.pos[_POS_V],
561 self.pos[_POS_Y],
562 self.pos[_POS_V]+self.pos[_POS_Y]))
563 self.pos[_POS_V] += self.pos[_POS_Y]
564 elif cmd == _DVI_Z0:
565 self.flushtext(fontmap)
566 if self.debug:
567 self.debugfile.write("%d: z0 %d v:=%d%+d=%d, vv:=???\n" %
568 (self.filepos,
569 self.pos[_POS_Z],
570 self.pos[_POS_V],
571 self.pos[_POS_Z],
572 self.pos[_POS_V]+self.pos[_POS_Z]))
573 self.pos[_POS_V] += self.pos[_POS_Z]
574 elif cmd >= _DVI_Z1234 and cmd < _DVI_Z1234 + 4:
575 self.flushtext(fontmap)
576 self.pos[_POS_Z] = afile.readint(cmd - _DVI_Z1234 + 1, 1) * self.scale
577 if self.debug:
578 self.debugfile.write("%d: z%d %d v:=%d%+d=%d, vv:=???\n" %
579 (self.filepos,
580 cmd - _DVI_Z1234 + 1,
581 self.pos[_POS_Z],
582 self.pos[_POS_V],
583 self.pos[_POS_Z],
584 self.pos[_POS_V]+self.pos[_POS_Z]))
585 self.pos[_POS_V] += self.pos[_POS_Z]
586 elif cmd >= _DVI_FNTNUMMIN and cmd <= _DVI_FNTNUMMAX:
587 self.usefont(cmd - _DVI_FNTNUMMIN, 0, fontmap)
588 elif cmd >= _DVI_FNT1234 and cmd < _DVI_FNT1234 + 4:
589 # note that according to the DVI docs, for four byte font numbers,
590 # the font number is signed. Don't ask why!
591 fntnum = afile.readint(cmd - _DVI_FNT1234 + 1, cmd == _DVI_FNT1234 + 3)
592 self.usefont(fntnum, cmd-_DVI_FNT1234+1, fontmap)
593 elif cmd >= _DVI_SPECIAL1234 and cmd < _DVI_SPECIAL1234 + 4:
594 self.special(afile.read(afile.readint(cmd - _DVI_SPECIAL1234 + 1)).decode("ascii"), fontmap)
595 elif cmd >= _DVI_FNTDEF1234 and cmd < _DVI_FNTDEF1234 + 4:
596 if cmd == _DVI_FNTDEF1234:
597 num = afile.readuchar()
598 elif cmd == _DVI_FNTDEF1234+1:
599 num = afile.readuint16()
600 elif cmd == _DVI_FNTDEF1234+2:
601 num = afile.readuint24()
602 elif cmd == _DVI_FNTDEF1234+3:
603 # Cool, here we have according to docu a signed int. Why?
604 num = afile.readint32()
605 self.definefont(cmd-_DVI_FNTDEF1234+1,
606 num,
607 afile.readint32(),
608 afile.readint32(),
609 afile.readint32(),
610 afile.read(afile.readuchar()+afile.readuchar()).decode("ascii"))
611 else:
612 raise DVIError