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