aboutsummaryrefslogtreecommitdiff
path: root/print.py
diff options
context:
space:
mode:
Diffstat (limited to 'print.py')
-rwxr-xr-xprint.py601
1 files changed, 0 insertions, 601 deletions
diff --git a/print.py b/print.py
deleted file mode 100755
index 13b4263..0000000
--- a/print.py
+++ /dev/null
@@ -1,601 +0,0 @@
-#!/usr/bin/env python
-
-# This program accepts a series of newline-separated game IDs on
-# stdin and formats them into PostScript to be printed out. You
-# specify using command-line options which game the IDs are for,
-# and how many you want per page.
-
-# Supported games are those which are sensibly solvable using
-# pencil and paper: Rectangles, Pattern, Solo, Net.
-
-# Command-line syntax is
-#
-# print.py <game-name> <format>
-#
-# <game-name> is one of `rect', `rectangles', `pattern', `solo',
-# `net', `dominosa'. <format> is two numbers separated by an x:
-# `2x3', for example, means two columns by three rows.
-#
-# The program will then read game IDs from stdin until it sees EOF,
-# and generate as many PostScript pages on stdout as it needs.
-#
-# The resulting PostScript will automatically adapt itself to the
-# size of the clip rectangle, so that the puzzles are sensibly
-# distributed across whatever paper size you decide to use.
-
-import sys
-import string
-import re
-
-class Holder:
- pass
-
-def psvprint(h, a):
- for i in xrange(len(a)):
- h.s = h.s + str(a[i])
- if i < len(a)-1:
- h.s = h.s + " "
- else:
- h.s = h.s + "\n"
-
-def psprint(h, *a):
- psvprint(h, a)
-
-def rect_format(s):
- # Parse the game ID.
- ret = Holder()
- ret.s = ""
- params, seed = string.split(s, ":")
- w, h = map(string.atoi, string.split(params, "x"))
- grid = []
- while len(seed) > 0:
- if seed[0] in '_'+string.lowercase:
- if seed[0] in string.lowercase:
- grid.extend([-1] * (ord(seed[0]) - ord('a') + 1))
- seed = seed[1:]
- elif seed[0] in string.digits:
- ns = ""
- while len(seed) > 0 and seed[0] in string.digits:
- ns = ns + seed[0]
- seed = seed[1:]
- grid.append(string.atoi(ns))
- assert w * h == len(grid)
- # I'm going to arbitrarily choose to use 7pt text for the
- # numbers, and a 14pt grid pitch.
- textht = 7
- gridpitch = 14
- # Set up coordinate system.
- pw = gridpitch * w
- ph = gridpitch * h
- ret.coords = (pw/2, pw/2, ph/2, ph/2)
- psprint(ret, "%g %g translate" % (-ret.coords[0], -ret.coords[2]))
- # Draw the internal grid lines, _very_ thin (the player will
- # need to draw over them visibly).
- psprint(ret, "newpath 0.01 setlinewidth")
- for x in xrange(1,w):
- psprint(ret, "%g 0 moveto 0 %g rlineto" % (x * gridpitch, h * gridpitch))
- for y in xrange(1,h):
- psprint(ret, "0 %g moveto %g 0 rlineto" % (y * gridpitch, w * gridpitch))
- psprint(ret, "stroke")
- # Draw round the grid exterior, much thicker.
- psprint(ret, "newpath 1.5 setlinewidth")
- psprint(ret, "0 0 moveto 0 %g rlineto %g 0 rlineto 0 %g rlineto" % \
- (h * gridpitch, w * gridpitch, -h * gridpitch))
- psprint(ret, "closepath stroke")
- # And draw the numbers.
- psprint(ret, "/Helvetica findfont %g scalefont setfont" % textht)
- for y in xrange(h):
- for x in xrange(w):
- n = grid[y*w+x]
- if n > 0:
- psprint(ret, "%g %g (%d) ctshow" % \
- ((x+0.5)*gridpitch, (h-y-0.5)*gridpitch, n))
- return ret.coords, ret.s
-
-def net_format(s):
- # Parse the game ID.
- ret = Holder()
- ret.s = ""
- params, seed = string.split(s, ":")
- wrapping = 0
- if params[-1:] == "w":
- wrapping = 1
- params = params[:-1]
- w, h = map(string.atoi, string.split(params, "x"))
- grid = []
- hbarriers = []
- vbarriers = []
- while len(seed) > 0:
- n = string.atoi(seed[0], 16)
- seed = seed[1:]
- while len(seed) > 0 and seed[0] in 'hv':
- x = len(grid) % w
- y = len(grid) / w
- if seed[0] == 'h':
- hbarriers.append((x, y+1))
- else:
- vbarriers.append((x+1, y))
- seed = seed[1:]
- grid.append(n)
- assert w * h == len(grid)
- # I'm going to arbitrarily choose a 24pt grid pitch.
- gridpitch = 24
- scale = 0.25
- bigoffset = 0.25
- smalloffset = 0.17
- squaresize = 0.25
- # Set up coordinate system.
- pw = gridpitch * w
- ph = gridpitch * h
- ret.coords = (pw/2, pw/2, ph/2, ph/2)
- psprint(ret, "%g %g translate" % (-ret.coords[0], -ret.coords[2]))
- # Draw the base grid lines.
- psprint(ret, "newpath 0.02 setlinewidth")
- for x in xrange(1,w):
- psprint(ret, "%g 0 moveto 0 %g rlineto" % (x * gridpitch, h * gridpitch))
- for y in xrange(1,h):
- psprint(ret, "0 %g moveto %g 0 rlineto" % (y * gridpitch, w * gridpitch))
- psprint(ret, "stroke")
- # Draw round the grid exterior.
- psprint(ret, "newpath")
- if not wrapping:
- psprint(ret, "2 setlinewidth")
- psprint(ret, "0 0 moveto 0 %g rlineto %g 0 rlineto 0 %g rlineto" % \
- (h * gridpitch, w * gridpitch, -h * gridpitch))
- psprint(ret, "closepath stroke")
- # Draw any barriers.
- psprint(ret, "newpath 2 setlinewidth 1 setlinecap")
- for x, y in hbarriers:
- psprint(ret, "%g %g moveto %g 0 rlineto" % \
- (x * gridpitch, (h - y) * gridpitch, gridpitch))
- for x, y in vbarriers:
- psprint(ret, "%g %g moveto 0 -%g rlineto" % \
- (x * gridpitch, (h - y) * gridpitch, gridpitch))
- psprint(ret, "stroke")
- # And draw the symbol in each box.
- for i in xrange(len(grid)):
- x = i % w
- y = i / w
- v = grid[i]
- # Rotate to canonical form.
- if v in (1,2,4,8):
- v = 1
- elif v in (5,10):
- v = 5
- elif v in (3,6,9,12):
- v = 9
- elif v in (7,11,13,14):
- v = 13
- # Centre on an area in the corner of the tile.
- psprint(ret, "gsave")
- if v & 4:
- hoffset = bigoffset
- else:
- hoffset = smalloffset
- if v & 2:
- voffset = bigoffset
- else:
- voffset = smalloffset
- psprint(ret, "%g %g translate" % \
- ((x + hoffset) * gridpitch, (h - y - voffset) * gridpitch))
- psprint(ret, "%g dup scale" % (float(gridpitch) * scale / 2))
- psprint(ret, "newpath 0.07 setlinewidth")
- # Draw the radial lines.
- for dx, dy, z in ((1,0,1), (0,1,2), (-1,0,4), (0,-1,8)):
- if v & z:
- psprint(ret, "0 0 moveto %d %d lineto" % (dx, dy))
- psprint(ret, "stroke")
- # Draw additional figures if desired.
- if v == 1:
- # Endpoints have a little empty square at the centre.
- psprint(ret, "newpath %g %g moveto 0 -%g rlineto" % \
- (squaresize, squaresize, squaresize * 2))
- psprint(ret, "-%g 0 rlineto 0 %g rlineto closepath fill" % \
- (squaresize * 2, squaresize * 2))
- # Get back out of the centre section.
- psprint(ret, "grestore")
- # Draw the endpoint square in large in the middle.
- if v == 1:
- psprint(ret, "gsave")
- psprint(ret, "%g %g translate" % \
- ((x + 0.5) * gridpitch, (h - y - 0.5) * gridpitch))
- psprint(ret, "%g dup scale" % (float(gridpitch) / 2))
- psprint(ret, "newpath %g %g moveto 0 -%g rlineto" % \
- (squaresize, squaresize, squaresize * 2))
- psprint(ret, "-%g 0 rlineto 0 %g rlineto closepath fill" % \
- (squaresize * 2, squaresize * 2))
- psprint(ret, "grestore")
- return ret.coords, ret.s
-
-def pattern_format(s):
- ret = Holder()
- ret.s = ""
- # Parse the game ID.
- params, seed = string.split(s, ":")
- w, h = map(string.atoi, string.split(params, "x"))
- rowdata = map(lambda s: string.split(s, "."), string.split(seed, "/"))
- assert len(rowdata) == w+h
- # I'm going to arbitrarily choose to use 7pt text for the
- # numbers, and a 14pt grid pitch.
- textht = 7
- gridpitch = 14
- gutter = 8 # between the numbers and the grid
- # Find the maximum number of numbers in each dimension, to
- # determine the border size required.
- xborder = reduce(max, map(len, rowdata[w:]))
- yborder = reduce(max, map(len, rowdata[:w]))
- # Set up coordinate system. I'm going to put the origin at the
- # _top left_ of the grid, so that both sets of numbers get
- # drawn the same way.
- pw = (w + xborder) * gridpitch + gutter
- ph = (h + yborder) * gridpitch + gutter
- ret.coords = (xborder * gridpitch + gutter, w * gridpitch, \
- yborder * gridpitch + gutter, h * gridpitch)
- # Draw the internal grid lines. Every fifth one is thicker, as
- # a visual aid.
- psprint(ret, "newpath 0.1 setlinewidth")
- for x in xrange(1,w):
- if x % 5 != 0:
- psprint(ret, "%g 0 moveto 0 %g rlineto" % (x * gridpitch, -h * gridpitch))
- for y in xrange(1,h):
- if y % 5 != 0:
- psprint(ret, "0 %g moveto %g 0 rlineto" % (-y * gridpitch, w * gridpitch))
- psprint(ret, "stroke")
- psprint(ret, "newpath 0.75 setlinewidth")
- for x in xrange(5,w,5):
- psprint(ret, "%g 0 moveto 0 %g rlineto" % (x * gridpitch, -h * gridpitch))
- for y in xrange(5,h,5):
- psprint(ret, "0 %g moveto %g 0 rlineto" % (-y * gridpitch, w * gridpitch))
- psprint(ret, "stroke")
- # Draw round the grid exterior.
- psprint(ret, "newpath 1.5 setlinewidth")
- psprint(ret, "0 0 moveto 0 %g rlineto %g 0 rlineto 0 %g rlineto" % \
- (-h * gridpitch, w * gridpitch, h * gridpitch))
- psprint(ret, "closepath stroke")
- # And draw the numbers.
- psprint(ret, "/Helvetica findfont %g scalefont setfont" % textht)
- for i in range(w+h):
- ns = rowdata[i]
- if i < w:
- xo = (i + 0.5) * gridpitch
- yo = (gutter + 0.5 * gridpitch)
- else:
- xo = -(gutter + 0.5 * gridpitch)
- yo = ((i-w) + 0.5) * -gridpitch
- for j in range(len(ns)-1, -1, -1):
- psprint(ret, "%g %g (%s) ctshow" % (xo, yo, ns[j]))
- if i < w:
- yo = yo + gridpitch
- else:
- xo = xo - gridpitch
- return ret.coords, ret.s
-
-def solo_format(s):
- ret = Holder()
- ret.s = ""
- # Parse the game ID.
- params, seed = string.split(s, ":")
- c, r = map(string.atoi, string.split(params, "x"))
- cr = c*r
- grid = []
- while len(seed) > 0:
- if seed[0] in '_'+string.lowercase:
- if seed[0] in string.lowercase:
- grid.extend([-1] * (ord(seed[0]) - ord('a') + 1))
- seed = seed[1:]
- elif seed[0] in string.digits:
- ns = ""
- while len(seed) > 0 and seed[0] in string.digits:
- ns = ns + seed[0]
- seed = seed[1:]
- grid.append(string.atoi(ns))
- assert cr * cr == len(grid)
- # I'm going to arbitrarily choose to use 9pt text for the
- # numbers, and a 16pt grid pitch.
- textht = 9
- gridpitch = 16
- # Set up coordinate system.
- pw = ph = gridpitch * cr
- ret.coords = (pw/2, pw/2, ph/2, ph/2)
- psprint(ret, "%g %g translate" % (-ret.coords[0], -ret.coords[2]))
- # Draw the thin internal grid lines.
- psprint(ret, "newpath 0.1 setlinewidth")
- for x in xrange(1,cr):
- if x % r != 0:
- psprint(ret, "%g 0 moveto 0 %g rlineto" % (x * gridpitch, cr * gridpitch))
- for y in xrange(1,cr):
- if y % c != 0:
- psprint(ret, "0 %g moveto %g 0 rlineto" % (y * gridpitch, cr * gridpitch))
- psprint(ret, "stroke")
- # Draw the thicker internal grid lines.
- psprint(ret, "newpath 1 setlinewidth")
- for x in xrange(r,cr,r):
- psprint(ret, "%g 0 moveto 0 %g rlineto" % (x * gridpitch, cr * gridpitch))
- for y in xrange(c,cr,c):
- psprint(ret, "0 %g moveto %g 0 rlineto" % (y * gridpitch, cr * gridpitch))
- psprint(ret, "stroke")
- # Draw round the grid exterior, thicker still.
- psprint(ret, "newpath 1.5 setlinewidth")
- psprint(ret, "0 0 moveto 0 %g rlineto %g 0 rlineto 0 %g rlineto" % \
- (cr * gridpitch, cr * gridpitch, -cr * gridpitch))
- psprint(ret, "closepath stroke")
- # And draw the numbers.
- psprint(ret, "/Helvetica findfont %g scalefont setfont" % textht)
- for y in xrange(cr):
- for x in xrange(cr):
- n = grid[y*cr+x]
- if n > 0:
- if n > 9:
- s = chr(ord('a') + n - 10)
- else:
- s = chr(ord('0') + n)
- psprint(ret, "%g %g (%s) ctshow" % \
- ((x+0.5)*gridpitch, (cr-y-0.5)*gridpitch, s))
- return ret.coords, ret.s
-
-def dominosa_format(s):
- ret = Holder()
- ret.s = ""
- params, seed = string.split(s, ":")
- n = string.atoi(params)
- w = n+2
- h = n+1
- grid = []
- while len(seed) > 0:
- if seed[0] == '[': # XXX
- d, seed = string.split(seed[1:], "]")
- grid.append(string.atoi(d))
- else:
- assert seed[0] in string.digits
- grid.append(string.atoi(seed[0:1]))
- seed = seed[1:]
- assert w*h == len(grid)
- # I'm going to arbitrarily choose to use 9pt text for the
- # numbers, and a 16pt grid pitch.
- textht = 9
- gridpitch = 16
- pw = gridpitch * w
- ph = gridpitch * h
- psprint(ret, "/Helvetica findfont %g scalefont setfont" % textht)
- ret.coords = (pw/2, pw/2, ph/2, ph/2)
- psprint(ret, "%g %g translate" % (-ret.coords[0], -ret.coords[2]))
- for y in xrange(h):
- for x in xrange(w):
- psprint(ret, "%g %g (%d) ctshow" % \
- ((x+0.5)*gridpitch, (h-y-0.5)*gridpitch, grid[y*w+x]))
- return ret.coords, ret.s
-
-def slant_format(s):
- # Parse the game ID.
- ret = Holder()
- ret.s = ""
- params, seed = string.split(s, ":")
- w, h = map(string.atoi, string.split(params, "x"))
- W = w+1
- H = h+1
- grid = []
- while len(seed) > 0:
- if seed[0] in string.lowercase:
- grid.extend([-1] * (ord(seed[0]) - ord('a') + 1))
- seed = seed[1:]
- elif seed[0] in "01234":
- grid.append(string.atoi(seed[0]))
- seed = seed[1:]
- assert W * H == len(grid)
- # I'm going to arbitrarily choose to use 7pt text for the
- # numbers, and a 14pt grid pitch.
- textht = 7
- gridpitch = 14
- radius = textht * 2.0 / 3.0
- # Set up coordinate system.
- pw = gridpitch * w
- ph = gridpitch * h
- ret.coords = (pw/2, pw/2, ph/2, ph/2)
- psprint(ret, "%g %g translate" % (-ret.coords[0], -ret.coords[2]))
- # Draw round the grid exterior, thickly.
- psprint(ret, "newpath 1 setlinewidth")
- psprint(ret, "0 0 moveto 0 %g rlineto %g 0 rlineto 0 %g rlineto" % \
- (h * gridpitch, w * gridpitch, -h * gridpitch))
- psprint(ret, "closepath stroke")
- # Draw the internal grid lines, _very_ thin (the player will
- # need to draw over them visibly).
- psprint(ret, "newpath 0.01 setlinewidth")
- for x in xrange(1,w):
- psprint(ret, "%g 0 moveto 0 %g rlineto" % (x * gridpitch, h * gridpitch))
- for y in xrange(1,h):
- psprint(ret, "0 %g moveto %g 0 rlineto" % (y * gridpitch, w * gridpitch))
- psprint(ret, "stroke")
- # And draw the numbers.
- psprint(ret, "/Helvetica findfont %g scalefont setfont" % textht)
- for y in xrange(H):
- for x in xrange(W):
- n = grid[y*W+x]
- if n >= 0:
- psprint(ret, "newpath %g %g %g 0 360 arc" % \
- ((x)*gridpitch, (h-y)*gridpitch, radius),
- "gsave 1 setgray fill grestore stroke")
- psprint(ret, "%g %g (%d) ctshow" % \
- ((x)*gridpitch, (h-y)*gridpitch, n))
- return ret.coords, ret.s
-
-def lightup_format(s):
- # Parse the game ID.
- ret = Holder()
- ret.s = ""
- params, seed = string.split(s, ":")
- w, h = map(string.atoi, string.split(params, "x"))
- grid = []
- while len(seed) > 0:
- if seed[0] in string.lowercase:
- grid.extend([-2] * (ord(seed[0]) - ord('a') + 1))
- seed = seed[1:]
- elif seed[0] == "B":
- grid.append(-1)
- seed = seed[1:]
- elif seed[0] in "01234":
- grid.append(string.atoi(seed[0]))
- seed = seed[1:]
- assert w * h == len(grid)
- # I'm going to arbitrarily choose to use 9pt text for the
- # numbers, and a 14pt grid pitch.
- textht = 10
- gridpitch = 14
- # Set up coordinate system.
- pw = gridpitch * w
- ph = gridpitch * h
- ret.coords = (pw/2, pw/2, ph/2, ph/2)
- psprint(ret, "%g %g translate" % (-ret.coords[0], -ret.coords[2]))
- # Draw round the grid exterior, thickly.
- psprint(ret, "newpath 1 setlinewidth")
- psprint(ret, "0 0 moveto 0 %g rlineto %g 0 rlineto 0 %g rlineto" % \
- (h * gridpitch, w * gridpitch, -h * gridpitch))
- psprint(ret, "closepath stroke")
- # Draw the internal grid lines.
- psprint(ret, "newpath 0.02 setlinewidth")
- for x in xrange(1,w):
- psprint(ret, "%g 0 moveto 0 %g rlineto" % (x * gridpitch, h * gridpitch))
- for y in xrange(1,h):
- psprint(ret, "0 %g moveto %g 0 rlineto" % (y * gridpitch, w * gridpitch))
- psprint(ret, "stroke")
- # And draw the black squares and numbers.
- psprint(ret, "/Helvetica-Bold findfont %g scalefont setfont" % textht)
- for y in xrange(h):
- for x in xrange(w):
- n = grid[y*w+x]
- if n >= -1:
- psprint(ret, ("newpath %g %g moveto 0 %g rlineto " +
- "%g 0 rlineto 0 %g rlineto closepath fill") % \
- ((x)*gridpitch, (h-1-y)*gridpitch, gridpitch, gridpitch, \
- -gridpitch))
- if n >= 0:
- psprint(ret, "gsave 1 setgray %g %g (%d) ctshow grestore" % \
- ((x+0.5)*gridpitch, (h-y-0.5)*gridpitch, n))
- return ret.coords, ret.s
-
-formatters = {
-"net": net_format,
-"rect": rect_format,
-"rectangles": rect_format,
-"pattern": pattern_format,
-"solo": solo_format,
-"dominosa": dominosa_format,
-"slant": slant_format,
-"lightup": lightup_format
-}
-
-if len(sys.argv) < 3:
- sys.stderr.write("print.py: expected two arguments (game and format)\n")
- sys.exit(1)
-
-formatter = formatters.get(sys.argv[1], None)
-if formatter == None:
- sys.stderr.write("print.py: unrecognised game name `%s'\n" % sys.argv[1])
- sys.exit(1)
-
-try:
- format = map(string.atoi, string.split(sys.argv[2], "x"))
-except ValueError, e:
- format = []
-if len(format) != 2:
- sys.stderr.write("print.py: expected format such as `2x3' as second" \
- + " argument\n")
- sys.exit(1)
-
-xx, yy = format
-ppp = xx * yy # puzzles per page
-
-ids = []
-while 1:
- s = sys.stdin.readline()
- if s == "": break
- if s[-1:] == "\n": s = s[:-1]
- ids.append(s)
-
-pages = int((len(ids) + ppp - 1) / ppp)
-
-# Output initial DSC stuff.
-print "%!PS-Adobe-3.0"
-print "%%Creator: print.py from Simon Tatham's Puzzle Collection"
-print "%%DocumentData: Clean7Bit"
-print "%%LanguageLevel: 1"
-print "%%Pages:", pages
-print "%%DocumentNeededResources:"
-print "%%+ font Helvetica"
-print "%%DocumentSuppliedResources: procset Puzzles 0 0"
-print "%%EndComments"
-print "%%BeginProlog"
-print "%%BeginResource: procset Puzzles 0 0"
-print "/ctshow {"
-print " 3 1 roll"
-print " newpath 0 0 moveto (X) true charpath flattenpath pathbbox"
-print " 3 -1 roll add 2 div 3 1 roll pop pop sub moveto"
-print " dup stringwidth pop 0.5 mul neg 0 rmoveto show"
-print "} bind def"
-print "%%EndResource"
-print "%%EndProlog"
-print "%%BeginSetup"
-print "%%IncludeResource: font Helvetica"
-print "%%EndSetup"
-
-# Now do each page.
-puzzle_index = 0;
-
-for i in xrange(1, pages+1):
- print "%%Page:", i, i
- print "save"
-
- # Do the drawing for each puzzle, giving a set of PS fragments
- # and bounding boxes.
- fragments = [['' for i in xrange(xx)] for i in xrange(yy)]
- lrbound = [(0,0) for i in xrange(xx)]
- tbbound = [(0,0) for i in xrange(yy)]
-
- for y in xrange(yy):
- for x in xrange(xx):
- if puzzle_index >= len(ids):
- break
- coords, frag = formatter(ids[puzzle_index])
- fragments[y][x] = frag
- lb, rb = lrbound[x]
- lrbound[x] = (max(lb, coords[0]), max(rb, coords[1]))
- tb, bb = tbbound[y]
- tbbound[y] = (max(tb, coords[2]), max(bb, coords[3]))
- puzzle_index = puzzle_index + 1
-
- # Now we know the sizes of everything, do the drawing in such a
- # way that we provide equal gutter space at the page edges and
- # between puzzle rows/columns.
- for y in xrange(yy):
- for x in xrange(xx):
- if len(fragments[y][x]) > 0:
- print "gsave"
- print "clippath flattenpath pathbbox pop pop translate"
- print "clippath flattenpath pathbbox 4 2 roll pop pop"
- # Compute the total height of all puzzles, which
- # we'll use it to work out the amount of gutter
- # space below this puzzle.
- htotal = reduce(lambda a,b:a+b, map(lambda (a,b):a+b, tbbound), 0)
- # Now compute the total height of all puzzles
- # _below_ this one, plus the height-below-origin of
- # this one.
- hbelow = reduce(lambda a,b:a+b, map(lambda (a,b):a+b, tbbound[y+1:]), 0)
- hbelow = hbelow + tbbound[y][1]
- print "%g sub %d mul %d div %g add exch" % (htotal, yy-y, yy+1, hbelow)
- # Now do all the same computations for width,
- # except we need the total width of everything
- # _before_ this one since the coordinates work the
- # other way round.
- wtotal = reduce(lambda a,b:a+b, map(lambda (a,b):a+b, lrbound), 0)
- # Now compute the total height of all puzzles
- # _below_ this one, plus the height-below-origin of
- # this one.
- wleft = reduce(lambda a,b:a+b, map(lambda (a,b):a+b, lrbound[:x]), 0)
- wleft = wleft + lrbound[x][0]
- print "%g sub %d mul %d div %g add exch" % (wtotal, x+1, xx+1, wleft)
- print "translate"
- sys.stdout.write(fragments[y][x])
- print "grestore"
-
- print "restore showpage"
-
-print "%%EOF"