bzr revid: pinky-223ff6e649c55e0032638fd654c6a1f5d1fdcf01
This commit is contained in:
pinky 2007-01-07 23:35:53 +00:00
parent 9d87f573e3
commit 1e479b40d6
51 changed files with 12226 additions and 0 deletions

View File

@ -0,0 +1,10 @@
This directory is the home of various ReportLab tools.
They are packaged such that they can be used more easily.
Tool candidates are:
- PythonPoint
- docpy.py
- graphdocpy.py
- ...

View File

@ -0,0 +1,3 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/__init__.py

View File

@ -0,0 +1,8 @@
This directory contains a number of tools to do with documentation and
documentation building.
Some of these are our own internal tools which we use for building the
ReportLab documentation. Some tools are obsolete and will be removed
in due course.
In the mean time, use at your own risk.

View File

@ -0,0 +1,3 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/docco/__init__.py

View File

@ -0,0 +1,228 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/docco/codegrab.py
#codegrab.py
"""
This grabs various Python class, method and function
headers and their doc strings to include in documents
"""
import imp
import types
import string
import os
import sys
class Struct:
pass
def getObjectsDefinedIn(modulename, directory=None):
"""Returns two tuple of (functions, classes) defined
in the given module. 'directory' must be the directory
containing the script; modulename should not include
the .py suffix"""
if directory:
searchpath = [directory]
else:
searchpath = sys.path # searches usual Python path
#might be a package. If so, check the top level
#package is there, then recalculate the path needed
words = string.split(modulename, '.')
if len(words) > 1:
packagename = words[0]
packagefound = imp.find_module(packagename, searchpath)
assert packagefound, "Package %s not found" % packagename
(file, packagepath, description) = packagefound
#now the full path should be known, if it is in the
#package
directory = apply(os.path.join, tuple([packagepath] + words[1:-1]))
modulename = words[-1]
searchpath = [directory]
#find and import the module.
found = imp.find_module(modulename, searchpath)
assert found, "Module %s not found" % modulename
(file, pathname, description) = found
mod = imp.load_module(modulename, file, pathname, description)
#grab the code too, minus trailing newlines
lines = open(pathname, 'r').readlines()
lines = map(string.rstrip, lines)
result = Struct()
result.functions = []
result.classes = []
result.doc = mod.__doc__
for name in dir(mod):
value = getattr(mod, name)
if type(value) is types.FunctionType:
path, file = os.path.split(value.func_code.co_filename)
root, ext = os.path.splitext(file)
#we're possibly interested in it
if root == modulename:
#it was defined here
funcObj = value
fn = Struct()
fn.name = name
fn.proto = getFunctionPrototype(funcObj, lines)
if funcObj.__doc__:
fn.doc = dedent(funcObj.__doc__)
else:
fn.doc = '(no documentation string)'
#is it official?
if name[0:1] == '_':
fn.status = 'private'
elif name[-1] in '0123456789':
fn.status = 'experimental'
else:
fn.status = 'official'
result.functions.append(fn)
elif type(value) == types.ClassType:
if value.__module__ == modulename:
cl = Struct()
cl.name = name
if value.__doc__:
cl.doc = dedent(value.__doc__)
else:
cl.doc = "(no documentation string)"
cl.bases = []
for base in value.__bases__:
cl.bases.append(base.__name__)
if name[0:1] == '_':
cl.status = 'private'
elif name[-1] in '0123456789':
cl.status = 'experimental'
else:
cl.status = 'official'
cl.methods = []
#loop over dict finding methods defined here
# Q - should we show all methods?
# loop over dict finding methods defined here
items = value.__dict__.items()
items.sort()
for (key2, value2) in items:
if type(value2) <> types.FunctionType:
continue # not a method
elif os.path.splitext(value2.func_code.co_filename)[0] == modulename:
continue # defined in base class
else:
#we want it
meth = Struct()
meth.name = key2
name2 = value2.func_code.co_name
meth.proto = getFunctionPrototype(value2, lines)
if name2!=key2:
meth.doc = 'pointer to '+name2
meth.proto = string.replace(meth.proto,name2,key2)
else:
if value2.__doc__:
meth.doc = dedent(value2.__doc__)
else:
meth.doc = "(no documentation string)"
#is it official?
if key2[0:1] == '_':
meth.status = 'private'
elif key2[-1] in '0123456789':
meth.status = 'experimental'
else:
meth.status = 'official'
cl.methods.append(meth)
result.classes.append(cl)
return result
def getFunctionPrototype(f, lines):
"""Pass in the function object and list of lines;
it extracts the header as a multiline text block."""
firstLineNo = f.func_code.co_firstlineno - 1
lineNo = firstLineNo
brackets = 0
while 1:
line = lines[lineNo]
for char in line:
if char == '(':
brackets = brackets + 1
elif char == ')':
brackets = brackets - 1
if brackets == 0:
break
else:
lineNo = lineNo + 1
usefulLines = lines[firstLineNo:lineNo+1]
return string.join(usefulLines, '\n')
def dedent(comment):
"""Attempts to dedent the lines to the edge. Looks at no.
of leading spaces in line 2, and removes up to that number
of blanks from other lines."""
commentLines = string.split(comment, '\n')
if len(commentLines) < 2:
cleaned = map(string.lstrip, commentLines)
else:
spc = 0
for char in commentLines[1]:
if char in string.whitespace:
spc = spc + 1
else:
break
#now check other lines
cleaned = []
for line in commentLines:
for i in range(min(len(line),spc)):
if line[0] in string.whitespace:
line = line[1:]
cleaned.append(line)
return string.join(cleaned, '\n')
def dumpDoc(modulename, directory=None):
"""Test support. Just prints docco on the module
to standard output."""
docco = getObjectsDefinedIn(modulename, directory)
print 'codegrab.py - ReportLab Documentation Utility'
print 'documenting', modulename + '.py'
print '-------------------------------------------------------'
print
if docco.functions == []:
print 'No functions found'
else:
print 'Functions:'
for f in docco.functions:
print f.proto
print ' ' + f.doc
if docco.classes == []:
print 'No classes found'
else:
print 'Classes:'
for c in docco.classes:
print c.name
print ' ' + c.doc
for m in c.methods:
print m.proto # it is already indented in the file!
print ' ' + m.doc
print
def test(m='reportlab.platypus.paragraph'):
dumpDoc(m)
if __name__=='__main__':
import sys
print 'Path to search:'
for line in sys.path:
print ' ',line
M = sys.argv[1:]
if M==[]:
M.append('reportlab.platypus.paragraph')
for m in M:
test(m)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,851 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/docco/examples.py
import string
testannotations="""
def annotations(canvas):
from reportlab.lib.units import inch
canvas.drawString(inch, 2.5*inch,
"setAuthor, setTitle, setSubject have no visible effect")
canvas.drawString(inch, inch, "But if you are viewing this document dynamically")
canvas.drawString(inch, 0.5*inch, "please look at File/Document Info")
canvas.setAuthor("the ReportLab Team")
canvas.setTitle("ReportLab PDF Generation User Guide")
canvas.setSubject("How to Generate PDF files using the ReportLab modules")
"""
# magic function making module
test1 = """
def f(a,b):
print "it worked", a, b
return a+b
"""
test2 = """
def g(n):
if n==0: return 1
else: return n*g(n-1)
"""
testhello = """
def hello(c):
from reportlab.lib.units import inch
# move the origin up and to the left
c.translate(inch,inch)
# define a large font
c.setFont("Helvetica", 14)
# choose some colors
c.setStrokeColorRGB(0.2,0.5,0.3)
c.setFillColorRGB(1,0,1)
# draw some lines
c.line(0,0,0,1.7*inch)
c.line(0,0,1*inch,0)
# draw a rectangle
c.rect(0.2*inch,0.2*inch,1*inch,1.5*inch, fill=1)
# make text go straight up
c.rotate(90)
# change color
c.setFillColorRGB(0,0,0.77)
# say hello (note after rotate the y coord needs to be negative!)
c.drawString(0.3*inch, -inch, "Hello World")
"""
testcoords = """
def coords(canvas):
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, black, red, blue, green
c = canvas
c.setStrokeColor(pink)
c.grid([inch, 2*inch, 3*inch, 4*inch], [0.5*inch, inch, 1.5*inch, 2*inch, 2.5*inch])
c.setStrokeColor(black)
c.setFont("Times-Roman", 20)
c.drawString(0,0, "(0,0) the Origin")
c.drawString(2.5*inch, inch, "(2.5,1) in inches")
c.drawString(4*inch, 2.5*inch, "(4, 2.5)")
c.setFillColor(red)
c.rect(0,2*inch,0.2*inch,0.3*inch, fill=1)
c.setFillColor(green)
c.circle(4.5*inch, 0.4*inch, 0.2*inch, fill=1)
"""
testtranslate = """
def translate(canvas):
from reportlab.lib.units import cm
canvas.translate(2.3*cm, 0.3*cm)
coords(canvas)
"""
testscale = """
def scale(canvas):
canvas.scale(0.75, 0.5)
coords(canvas)
"""
testscaletranslate = """
def scaletranslate(canvas):
from reportlab.lib.units import inch
canvas.setFont("Courier-BoldOblique", 12)
# save the state
canvas.saveState()
# scale then translate
canvas.scale(0.3, 0.5)
canvas.translate(2.4*inch, 1.5*inch)
canvas.drawString(0, 2.7*inch, "Scale then translate")
coords(canvas)
# forget the scale and translate...
canvas.restoreState()
# translate then scale
canvas.translate(2.4*inch, 1.5*inch)
canvas.scale(0.3, 0.5)
canvas.drawString(0, 2.7*inch, "Translate then scale")
coords(canvas)
"""
testmirror = """
def mirror(canvas):
from reportlab.lib.units import inch
canvas.translate(5.5*inch, 0)
canvas.scale(-1.0, 1.0)
coords(canvas)
"""
testcolors = """
def colors(canvas):
from reportlab.lib import colors
from reportlab.lib.units import inch
black = colors.black
y = x = 0; dy=inch*3/4.0; dx=inch*5.5/5; w=h=dy/2; rdx=(dx-w)/2
rdy=h/5.0; texty=h+2*rdy
canvas.setFont("Helvetica",10)
for [namedcolor, name] in (
[colors.lavenderblush, "lavenderblush"],
[colors.lawngreen, "lawngreen"],
[colors.lemonchiffon, "lemonchiffon"],
[colors.lightblue, "lightblue"],
[colors.lightcoral, "lightcoral"]):
canvas.setFillColor(namedcolor)
canvas.rect(x+rdx, y+rdy, w, h, fill=1)
canvas.setFillColor(black)
canvas.drawCentredString(x+dx/2, y+texty, name)
x = x+dx
y = y + dy; x = 0
for rgb in [(1,0,0), (0,1,0), (0,0,1), (0.5,0.3,0.1), (0.4,0.5,0.3)]:
r,g,b = rgb
canvas.setFillColorRGB(r,g,b)
canvas.rect(x+rdx, y+rdy, w, h, fill=1)
canvas.setFillColor(black)
canvas.drawCentredString(x+dx/2, y+texty, "r%s g%s b%s"%rgb)
x = x+dx
y = y + dy; x = 0
for cmyk in [(1,0,0,0), (0,1,0,0), (0,0,1,0), (0,0,0,1), (0,0,0,0)]:
c,m,y1,k = cmyk
canvas.setFillColorCMYK(c,m,y1,k)
canvas.rect(x+rdx, y+rdy, w, h, fill=1)
canvas.setFillColor(black)
canvas.drawCentredString(x+dx/2, y+texty, "c%s m%s y%s k%s"%cmyk)
x = x+dx
y = y + dy; x = 0
for gray in (0.0, 0.25, 0.50, 0.75, 1.0):
canvas.setFillGray(gray)
canvas.rect(x+rdx, y+rdy, w, h, fill=1)
canvas.setFillColor(black)
canvas.drawCentredString(x+dx/2, y+texty, "gray: %s"%gray)
x = x+dx
"""
testspumoni = """
def spumoni(canvas):
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, green, brown, white
x = 0; dx = 0.4*inch
for i in range(4):
for color in (pink, green, brown):
canvas.setFillColor(color)
canvas.rect(x,0,dx,3*inch,stroke=0,fill=1)
x = x+dx
canvas.setFillColor(white)
canvas.setStrokeColor(white)
canvas.setFont("Helvetica-Bold", 85)
canvas.drawCentredString(2.75*inch, 1.3*inch, "SPUMONI")
"""
testspumoni2 = """
def spumoni2(canvas):
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, green, brown, white, black
# draw the previous drawing
spumoni(canvas)
# now put an ice cream cone on top of it:
# first draw a triangle (ice cream cone)
p = canvas.beginPath()
xcenter = 2.75*inch
radius = 0.45*inch
p.moveTo(xcenter-radius, 1.5*inch)
p.lineTo(xcenter+radius, 1.5*inch)
p.lineTo(xcenter, 0)
canvas.setFillColor(brown)
canvas.setStrokeColor(black)
canvas.drawPath(p, fill=1)
# draw some circles (scoops)
y = 1.5*inch
for color in (pink, green, brown):
canvas.setFillColor(color)
canvas.circle(xcenter, y, radius, fill=1)
y = y+radius
"""
testbezier = """
def bezier(canvas):
from reportlab.lib.colors import yellow, green, red, black
from reportlab.lib.units import inch
i = inch
d = i/4
# define the bezier curve control points
x1,y1, x2,y2, x3,y3, x4,y4 = d,1.5*i, 1.5*i,d, 3*i,d, 5.5*i-d,3*i-d
# draw a figure enclosing the control points
canvas.setFillColor(yellow)
p = canvas.beginPath()
p.moveTo(x1,y1)
for (x,y) in [(x2,y2), (x3,y3), (x4,y4)]:
p.lineTo(x,y)
canvas.drawPath(p, fill=1, stroke=0)
# draw the tangent lines
canvas.setLineWidth(inch*0.1)
canvas.setStrokeColor(green)
canvas.line(x1,y1,x2,y2)
canvas.setStrokeColor(red)
canvas.line(x3,y3,x4,y4)
# finally draw the curve
canvas.setStrokeColor(black)
canvas.bezier(x1,y1, x2,y2, x3,y3, x4,y4)
"""
testbezier2 = """
def bezier2(canvas):
from reportlab.lib.colors import yellow, green, red, black
from reportlab.lib.units import inch
# make a sequence of control points
xd,yd = 5.5*inch/2, 3*inch/2
xc,yc = xd,yd
dxdy = [(0,0.33), (0.33,0.33), (0.75,1), (0.875,0.875),
(0.875,0.875), (1,0.75), (0.33,0.33), (0.33,0)]
pointlist = []
for xoffset in (1,-1):
yoffset = xoffset
for (dx,dy) in dxdy:
px = xc + xd*xoffset*dx
py = yc + yd*yoffset*dy
pointlist.append((px,py))
yoffset = -xoffset
for (dy,dx) in dxdy:
px = xc + xd*xoffset*dx
py = yc + yd*yoffset*dy
pointlist.append((px,py))
# draw tangent lines and curves
canvas.setLineWidth(inch*0.1)
while pointlist:
[(x1,y1),(x2,y2),(x3,y3),(x4,y4)] = pointlist[:4]
del pointlist[:4]
canvas.setLineWidth(inch*0.1)
canvas.setStrokeColor(green)
canvas.line(x1,y1,x2,y2)
canvas.setStrokeColor(red)
canvas.line(x3,y3,x4,y4)
# finally draw the curve
canvas.setStrokeColor(black)
canvas.bezier(x1,y1, x2,y2, x3,y3, x4,y4)
"""
testpencil = """
def pencil(canvas, text="No.2"):
from reportlab.lib.colors import yellow, red, black,white
from reportlab.lib.units import inch
u = inch/10.0
canvas.setStrokeColor(black)
canvas.setLineWidth(4)
# draw erasor
canvas.setFillColor(red)
canvas.circle(30*u, 5*u, 5*u, stroke=1, fill=1)
# draw all else but the tip (mainly rectangles with different fills)
canvas.setFillColor(yellow)
canvas.rect(10*u,0,20*u,10*u, stroke=1, fill=1)
canvas.setFillColor(black)
canvas.rect(23*u,0,8*u,10*u,fill=1)
canvas.roundRect(14*u, 3.5*u, 8*u, 3*u, 1.5*u, stroke=1, fill=1)
canvas.setFillColor(white)
canvas.rect(25*u,u,1.2*u,8*u, fill=1,stroke=0)
canvas.rect(27.5*u,u,1.2*u,8*u, fill=1, stroke=0)
canvas.setFont("Times-Roman", 3*u)
canvas.drawCentredString(18*u, 4*u, text)
# now draw the tip
penciltip(canvas,debug=0)
# draw broken lines across the body.
canvas.setDash([10,5,16,10],0)
canvas.line(11*u,2.5*u,22*u,2.5*u)
canvas.line(22*u,7.5*u,12*u,7.5*u)
"""
testpenciltip = """
def penciltip(canvas, debug=1):
from reportlab.lib.colors import tan, black, green
from reportlab.lib.units import inch
u = inch/10.0
canvas.setLineWidth(4)
if debug:
canvas.scale(2.8,2.8) # make it big
canvas.setLineWidth(1) # small lines
canvas.setStrokeColor(black)
canvas.setFillColor(tan)
p = canvas.beginPath()
p.moveTo(10*u,0)
p.lineTo(0,5*u)
p.lineTo(10*u,10*u)
p.curveTo(11.5*u,10*u, 11.5*u,7.5*u, 10*u,7.5*u)
p.curveTo(12*u,7.5*u, 11*u,2.5*u, 9.7*u,2.5*u)
p.curveTo(10.5*u,2.5*u, 11*u,0, 10*u,0)
canvas.drawPath(p, stroke=1, fill=1)
canvas.setFillColor(black)
p = canvas.beginPath()
p.moveTo(0,5*u)
p.lineTo(4*u,3*u)
p.lineTo(5*u,4.5*u)
p.lineTo(3*u,6.5*u)
canvas.drawPath(p, stroke=1, fill=1)
if debug:
canvas.setStrokeColor(green) # put in a frame of reference
canvas.grid([0,5*u,10*u,15*u], [0,5*u,10*u])
"""
testnoteannotation = """
from reportlab.platypus.flowables import Flowable
class NoteAnnotation(Flowable):
'''put a pencil in the margin.'''
def wrap(self, *args):
return (1,10) # I take up very little space! (?)
def draw(self):
canvas = self.canv
canvas.translate(-10,-10)
canvas.rotate(180)
canvas.scale(0.2,0.2)
pencil(canvas, text="NOTE")
"""
testhandannotation = """
from reportlab.platypus.flowables import Flowable
from reportlab.lib.colors import tan, green
class HandAnnotation(Flowable):
'''A hand flowable.'''
def __init__(self, xoffset=0, size=None, fillcolor=tan, strokecolor=green):
from reportlab.lib.units import inch
if size is None: size=4*inch
self.fillcolor, self.strokecolor = fillcolor, strokecolor
self.xoffset = xoffset
self.size = size
# normal size is 4 inches
self.scale = size/(4.0*inch)
def wrap(self, *args):
return (self.xoffset, self.size)
def draw(self):
canvas = self.canv
canvas.setLineWidth(6)
canvas.setFillColor(self.fillcolor)
canvas.setStrokeColor(self.strokecolor)
canvas.translate(self.xoffset+self.size,0)
canvas.rotate(90)
canvas.scale(self.scale, self.scale)
hand(canvas, debug=0, fill=1)
"""
lyrics = '''\
well she hit Net Solutions
and she registered her own .com site now
and filled it up with yahoo profile pics
she snarfed in one night now
and she made 50 million when Hugh Hefner
bought up the rights now
and she'll have fun fun fun
til her Daddy takes the keyboard away'''
lyrics = string.split(lyrics, "\n")
testtextsize = """
def textsize(canvas):
from reportlab.lib.units import inch
from reportlab.lib.colors import magenta, red
canvas.setFont("Times-Roman", 20)
canvas.setFillColor(red)
canvas.drawCentredString(2.75*inch, 2.5*inch, "Font size examples")
canvas.setFillColor(magenta)
size = 7
y = 2.3*inch
x = 1.3*inch
for line in lyrics:
canvas.setFont("Helvetica", size)
canvas.drawRightString(x,y,"%s points: " % size)
canvas.drawString(x,y, line)
y = y-size*1.2
size = size+1.5
"""
teststar = """
def star(canvas, title="Title Here", aka="Comment here.",
xcenter=None, ycenter=None, nvertices=5):
from math import pi
from reportlab.lib.units import inch
radius=inch/3.0
if xcenter is None: xcenter=2.75*inch
if ycenter is None: ycenter=1.5*inch
canvas.drawCentredString(xcenter, ycenter+1.3*radius, title)
canvas.drawCentredString(xcenter, ycenter-1.4*radius, aka)
p = canvas.beginPath()
p.moveTo(xcenter,ycenter+radius)
from math import pi, cos, sin
angle = (2*pi)*2/5.0
startangle = pi/2.0
for vertex in range(nvertices-1):
nextangle = angle*(vertex+1)+startangle
x = xcenter + radius*cos(nextangle)
y = ycenter + radius*sin(nextangle)
p.lineTo(x,y)
if nvertices==5:
p.close()
canvas.drawPath(p)
"""
testjoins = """
def joins(canvas):
from reportlab.lib.units import inch
# make lines big
canvas.setLineWidth(5)
star(canvas, "Default: mitered join", "0: pointed", xcenter = 1*inch)
canvas.setLineJoin(1)
star(canvas, "Round join", "1: rounded")
canvas.setLineJoin(2)
star(canvas, "Bevelled join", "2: square", xcenter=4.5*inch)
"""
testcaps = """
def caps(canvas):
from reportlab.lib.units import inch
# make lines big
canvas.setLineWidth(5)
star(canvas, "Default", "no projection",xcenter = 1*inch,
nvertices=4)
canvas.setLineCap(1)
star(canvas, "Round cap", "1: ends in half circle", nvertices=4)
canvas.setLineCap(2)
star(canvas, "Square cap", "2: projects out half a width", xcenter=4.5*inch,
nvertices=4)
"""
testdashes = """
def dashes(canvas):
from reportlab.lib.units import inch
# make lines big
canvas.setDash(6,3)
star(canvas, "Simple dashes", "6 points on, 3 off", xcenter = 1*inch)
canvas.setDash(1,2)
star(canvas, "Dots", "One on, two off")
canvas.setDash([1,1,3,3,1,4,4,1], 0)
star(canvas, "Complex Pattern", "[1,1,3,3,1,4,4,1]", xcenter=4.5*inch)
"""
testcustomfont1 = """
def customfont1(canvas):
# we know some glyphs are missing, suppress warnings
import reportlab.rl_config
reportlab.rl_config.warnOnMissingFontGlyphs = 0
import rl_doc_utils
from reportlab.pdfbase import pdfmetrics
afmFile, pfbFile = rl_doc_utils.getJustFontPaths()
justFace = pdfmetrics.EmbeddedType1Face(afmFile, pfbFile)
faceName = 'LettErrorRobot-Chrome' # pulled from AFM file
pdfmetrics.registerTypeFace(justFace)
justFont = pdfmetrics.Font('LettErrorRobot-Chrome',
faceName,
'WinAnsiEncoding')
pdfmetrics.registerFont(justFont)
canvas.setFont('LettErrorRobot-Chrome', 32)
canvas.drawString(10, 150, 'This should be in')
canvas.drawString(10, 100, 'LettErrorRobot-Chrome')
"""
testttffont1 = """
def ttffont1(canvas):
# we know some glyphs are missing, suppress warnings
import reportlab.rl_config
reportlab.rl_config.warnOnMissingFontGlyphs = 0
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
pdfmetrics.registerFont(TTFont('Rina', 'rina.ttf'))
from reportlab.pdfgen.canvas import Canvas
canvas.setFont('Rina', 32)
canvas.drawString(10, 150, "Some UTF-8 text encoded")
canvas.drawString(10, 100, "in the Rina TT Font!")
"""
testcursormoves1 = """
def cursormoves1(canvas):
from reportlab.lib.units import inch
textobject = canvas.beginText()
textobject.setTextOrigin(inch, 2.5*inch)
textobject.setFont("Helvetica-Oblique", 14)
for line in lyrics:
textobject.textLine(line)
textobject.setFillGray(0.4)
textobject.textLines('''
With many apologies to the Beach Boys
and anyone else who finds this objectionable
''')
canvas.drawText(textobject)
"""
testcursormoves2 = """
def cursormoves2(canvas):
from reportlab.lib.units import inch
textobject = canvas.beginText()
textobject.setTextOrigin(2, 2.5*inch)
textobject.setFont("Helvetica-Oblique", 14)
for line in lyrics:
textobject.textOut(line)
textobject.moveCursor(14,14) # POSITIVE Y moves down!!!
textobject.setFillColorRGB(0.4,0,1)
textobject.textLines('''
With many apologies to the Beach Boys
and anyone else who finds this objectionable
''')
canvas.drawText(textobject)
"""
testcharspace = """
def charspace(canvas):
from reportlab.lib.units import inch
textobject = canvas.beginText()
textobject.setTextOrigin(3, 2.5*inch)
textobject.setFont("Helvetica-Oblique", 10)
charspace = 0
for line in lyrics:
textobject.setCharSpace(charspace)
textobject.textLine("%s: %s" %(charspace,line))
charspace = charspace+0.5
textobject.setFillGray(0.4)
textobject.textLines('''
With many apologies to the Beach Boys
and anyone else who finds this objectionable
''')
canvas.drawText(textobject)
"""
testwordspace = """
def wordspace(canvas):
from reportlab.lib.units import inch
textobject = canvas.beginText()
textobject.setTextOrigin(3, 2.5*inch)
textobject.setFont("Helvetica-Oblique", 12)
wordspace = 0
for line in lyrics:
textobject.setWordSpace(wordspace)
textobject.textLine("%s: %s" %(wordspace,line))
wordspace = wordspace+2.5
textobject.setFillColorCMYK(0.4,0,0.4,0.2)
textobject.textLines('''
With many apologies to the Beach Boys
and anyone else who finds this objectionable
''')
canvas.drawText(textobject)
"""
testhorizontalscale = """
def horizontalscale(canvas):
from reportlab.lib.units import inch
textobject = canvas.beginText()
textobject.setTextOrigin(3, 2.5*inch)
textobject.setFont("Helvetica-Oblique", 12)
horizontalscale = 80 # 100 is default
for line in lyrics:
textobject.setHorizScale(horizontalscale)
textobject.textLine("%s: %s" %(horizontalscale,line))
horizontalscale = horizontalscale+10
textobject.setFillColorCMYK(0.0,0.4,0.4,0.2)
textobject.textLines('''
With many apologies to the Beach Boys
and anyone else who finds this objectionable
''')
canvas.drawText(textobject)
"""
testleading = """
def leading(canvas):
from reportlab.lib.units import inch
textobject = canvas.beginText()
textobject.setTextOrigin(3, 2.5*inch)
textobject.setFont("Helvetica-Oblique", 14)
leading = 8
for line in lyrics:
textobject.setLeading(leading)
textobject.textLine("%s: %s" %(leading,line))
leading = leading+2.5
textobject.setFillColorCMYK(0.8,0,0,0.3)
textobject.textLines('''
With many apologies to the Beach Boys
and anyone else who finds this objectionable
''')
canvas.drawText(textobject)
"""
testhand = """
def hand(canvas, debug=1, fill=0):
(startx, starty) = (0,0)
curves = [
( 0, 2), ( 0, 4), ( 0, 8), # back of hand
( 5, 8), ( 7,10), ( 7,14),
(10,14), (10,13), ( 7.5, 8), # thumb
(13, 8), (14, 8), (17, 8),
(19, 8), (19, 6), (17, 6),
(15, 6), (13, 6), (11, 6), # index, pointing
(12, 6), (13, 6), (14, 6),
(16, 6), (16, 4), (14, 4),
(13, 4), (12, 4), (11, 4), # middle
(11.5, 4), (12, 4), (13, 4),
(15, 4), (15, 2), (13, 2),
(12.5, 2), (11.5, 2), (11, 2), # ring
(11.5, 2), (12, 2), (12.5, 2),
(14, 2), (14, 0), (12.5, 0),
(10, 0), (8, 0), (6, 0), # pinky, then close
]
from reportlab.lib.units import inch
if debug: canvas.setLineWidth(6)
u = inch*0.2
p = canvas.beginPath()
p.moveTo(startx, starty)
ccopy = list(curves)
while ccopy:
[(x1,y1), (x2,y2), (x3,y3)] = ccopy[:3]
del ccopy[:3]
p.curveTo(x1*u,y1*u,x2*u,y2*u,x3*u,y3*u)
p.close()
canvas.drawPath(p, fill=fill)
if debug:
from reportlab.lib.colors import red, green
(lastx, lasty) = (startx, starty)
ccopy = list(curves)
while ccopy:
[(x1,y1), (x2,y2), (x3,y3)] = ccopy[:3]
del ccopy[:3]
canvas.setStrokeColor(red)
canvas.line(lastx*u,lasty*u, x1*u,y1*u)
canvas.setStrokeColor(green)
canvas.line(x2*u,y2*u, x3*u,y3*u)
(lastx,lasty) = (x3,y3)
"""
testhand2 = """
def hand2(canvas):
canvas.translate(20,10)
canvas.setLineWidth(3)
canvas.setFillColorRGB(0.1, 0.3, 0.9)
canvas.setStrokeGray(0.5)
hand(canvas, debug=0, fill=1)
"""
testfonts = """
def fonts(canvas):
from reportlab.lib.units import inch
text = "Now is the time for all good men to..."
x = 1.8*inch
y = 2.7*inch
for font in canvas.getAvailableFonts():
canvas.setFont(font, 10)
canvas.drawString(x,y,text)
canvas.setFont("Helvetica", 10)
canvas.drawRightString(x-10,y, font+":")
y = y-13
"""
testarcs = """
def arcs(canvas):
from reportlab.lib.units import inch
canvas.setLineWidth(4)
canvas.setStrokeColorRGB(0.8, 1, 0.6)
# draw rectangles enclosing the arcs
canvas.rect(inch, inch, 1.5*inch, inch)
canvas.rect(3*inch, inch, inch, 1.5*inch)
canvas.setStrokeColorRGB(0, 0.2, 0.4)
canvas.setFillColorRGB(1, 0.6, 0.8)
p = canvas.beginPath()
p.moveTo(0.2*inch, 0.2*inch)
p.arcTo(inch, inch, 2.5*inch,2*inch, startAng=-30, extent=135)
p.arc(3*inch, inch, 4*inch, 2.5*inch, startAng=-45, extent=270)
canvas.drawPath(p, fill=1, stroke=1)
"""
testvariousshapes = """
def variousshapes(canvas):
from reportlab.lib.units import inch
inch = int(inch)
canvas.setStrokeGray(0.5)
canvas.grid(range(0,11*inch/2,inch/2), range(0,7*inch/2,inch/2))
canvas.setLineWidth(4)
canvas.setStrokeColorRGB(0, 0.2, 0.7)
canvas.setFillColorRGB(1, 0.6, 0.8)
p = canvas.beginPath()
p.rect(0.5*inch, 0.5*inch, 0.5*inch, 2*inch)
p.circle(2.75*inch, 1.5*inch, 0.3*inch)
p.ellipse(3.5*inch, 0.5*inch, 1.2*inch, 2*inch)
canvas.drawPath(p, fill=1, stroke=1)
"""
testclosingfigures = """
def closingfigures(canvas):
from reportlab.lib.units import inch
h = inch/3.0; k = inch/2.0
canvas.setStrokeColorRGB(0.2,0.3,0.5)
canvas.setFillColorRGB(0.8,0.6,0.2)
canvas.setLineWidth(4)
p = canvas.beginPath()
for i in (1,2,3,4):
for j in (1,2):
xc,yc = inch*i, inch*j
p.moveTo(xc,yc)
p.arcTo(xc-h, yc-k, xc+h, yc+k, startAng=0, extent=60*i)
# close only the first one, not the second one
if j==1:
p.close()
canvas.drawPath(p, fill=1, stroke=1)
"""
testforms = """
def forms(canvas):
#first create a form...
canvas.beginForm("SpumoniForm")
#re-use some drawing functions from earlier
spumoni(canvas)
canvas.endForm()
#then draw it
canvas.doForm("SpumoniForm")
"""
def doctemplateillustration(canvas):
from reportlab.lib.units import inch
canvas.setFont("Helvetica", 10)
canvas.drawString(inch/4.0, 2.75*inch, "DocTemplate")
W = 4/3.0*inch
H = 2*inch
Wd = x = inch/4.0
Hd =y = inch/2.0
for name in ("two column", "chapter page", "title page"):
canvas.setFillColorRGB(0.5,1.0,1.0)
canvas.rect(x,y,W,H, fill=1)
canvas.setFillColorRGB(0,0,0)
canvas.drawString(x+inch/8, y+H-Wd, "PageTemplate")
canvas.drawCentredString(x+W/2.0, y-Wd, name)
x = x+W+Wd
canvas.saveState()
d = inch/16
dW = (W-3*d)/2.0
hD = H -2*d-Wd
canvas.translate(Wd+d, Hd+d)
for name in ("left Frame", "right Frame"):
canvas.setFillColorRGB(1.0,0.5,1.0)
canvas.rect(0,0, dW,hD, fill=1)
canvas.setFillGray(0.7)
dd= d/2.0
ddH = (hD-6*dd)/5.0
ddW = dW-2*dd
yy = dd
xx = dd
for i in range(5):
canvas.rect(xx,yy,ddW,ddH, fill=1, stroke=0)
yy = yy+ddH+dd
canvas.setFillColorRGB(0,0,0)
canvas.saveState()
canvas.rotate(90)
canvas.drawString(d,-dW/2, name)
canvas.restoreState()
canvas.translate(dW+d,0)
canvas.restoreState()
canvas.setFillColorRGB(1.0, 0.5, 1.0)
mx = Wd+W+Wd+d
my = Hd+d
mW = W-2*d
mH = H-d-Hd
canvas.rect(mx, my, mW, mH, fill=1)
canvas.rect(Wd+2*(W+Wd)+d, Hd+3*d, W-2*d, H/2.0, fill=1)
canvas.setFillGray(0.7)
canvas.rect(Wd+2*(W+Wd)+d+dd, Hd+5*d, W-2*d-2*dd, H/2.0-2*d-dd, fill=1)
xx = mx+dd
yy = my+mH/5.0
ddH = (mH-6*dd-mH/5.0)/3.0
ddW = mW - 2*dd
for i in range(3):
canvas.setFillGray(0.7)
canvas.rect(xx,yy,ddW,ddH, fill=1, stroke=1)
canvas.setFillGray(0)
canvas.drawString(xx+dd/2.0,yy+dd/2.0, "flowable %s" %(157-i))
yy = yy+ddH+dd
canvas.drawCentredString(3*Wd+2*W+W/2, Hd+H/2.0, "First Flowable")
canvas.setFont("Times-BoldItalic", 8)
canvas.setFillGray(0)
canvas.drawCentredString(mx+mW/2.0, my+mH+3*dd, "Chapter 6: Lubricants")
canvas.setFont("Times-BoldItalic", 10)
canvas.drawCentredString(3*Wd+2*W+W/2, Hd+H-H/4, "College Life")
# D = dir()
g = globals()
Dprime = {}
from types import StringType
from string import strip
for (a,b) in g.items():
if a[:4]=="test" and type(b) is StringType:
#print 'for', a
#print b
b = strip(b)
exec(b+'\n')
platypussetup = """
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.rl_config import defaultPageSize
from reportlab.lib.units import inch
PAGE_HEIGHT=defaultPageSize[1]; PAGE_WIDTH=defaultPageSize[0]
styles = getSampleStyleSheet()
"""
platypusfirstpage = """
Title = "Hello world"
pageinfo = "platypus example"
def myFirstPage(canvas, doc):
canvas.saveState()
canvas.setFont('Times-Bold',16)
canvas.drawCentredString(PAGE_WIDTH/2.0, PAGE_HEIGHT-108, Title)
canvas.setFont('Times-Roman',9)
canvas.drawString(inch, 0.75 * inch, "First Page / %s" % pageinfo)
canvas.restoreState()
"""
platypusnextpage = """
def myLaterPages(canvas, doc):
canvas.saveState()
canvas.setFont('Times-Roman',9)
canvas.drawString(inch, 0.75 * inch, "Page %d %s" % (doc.page, pageinfo))
canvas.restoreState()
"""
platypusgo = """
def go():
doc = SimpleDocTemplate("phello.pdf")
Story = [Spacer(1,2*inch)]
style = styles["Normal"]
for i in range(100):
bogustext = ("This is Paragraph number %s. " % i) *20
p = Paragraph(bogustext, style)
Story.append(p)
Story.append(Spacer(1,0.2*inch))
doc.build(Story, onFirstPage=myFirstPage, onLaterPages=myLaterPages)
"""
if __name__=="__main__":
# then do the platypus hello world
for b in platypussetup, platypusfirstpage, platypusnextpage, platypusgo:
b = strip(b)
exec(b+'\n')
go()

View File

@ -0,0 +1,980 @@
#!/usr/bin/env python
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/docco/graphdocpy.py
"""Generate documentation for reportlab.graphics classes.
Type the following for usage info:
python graphdocpy.py -h
"""
__version__ = '0.8'
import sys
sys.path.insert(0, '.')
import os, re, types, string, getopt, pickle, copy, time, pprint, traceback
from string import find, join, split, replace, expandtabs, rstrip
import reportlab
from reportlab import rl_config
from docpy import PackageSkeleton0, ModuleSkeleton0
from docpy import DocBuilder0, PdfDocBuilder0, HtmlDocBuilder0
from docpy import htmlescape, htmlrepr, defaultformat, \
getdoc, reduceDocStringLength
from docpy import makeHtmlSection, makeHtmlSubSection, \
makeHtmlInlineImage
from reportlab.lib.units import inch, cm
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.lib.utils import getStringIO
#from StringIO import StringIO
#getStringIO=StringIO
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.pdfgen import canvas
from reportlab.platypus.flowables import Flowable, Spacer
from reportlab.platypus.paragraph import Paragraph
from reportlab.platypus.tableofcontents import TableOfContents
from reportlab.platypus.flowables \
import Flowable, Preformatted,Spacer, Image, KeepTogether, PageBreak
from reportlab.platypus.xpreformatted import XPreformatted
from reportlab.platypus.frames import Frame
from reportlab.platypus.doctemplate \
import PageTemplate, BaseDocTemplate
from reportlab.platypus.tables import TableStyle, Table
from reportlab.graphics.shapes import NotImplementedError
import inspect
# Needed to draw Widget/Drawing demos.
from reportlab.graphics.widgetbase import Widget
from reportlab.graphics.shapes import Drawing
from reportlab.graphics import shapes
from reportlab.graphics import renderPDF
VERBOSE = rl_config.verbose
VERIFY = 1
_abstractclasserr_re = re.compile(r'^\s*abstract\s*class\s*(\w+)\s*instantiated',re.I)
####################################################################
#
# Stuff needed for building PDF docs.
#
####################################################################
def mainPageFrame(canvas, doc):
"The page frame used for all PDF documents."
canvas.saveState()
pageNumber = canvas.getPageNumber()
canvas.line(2*cm, A4[1]-2*cm, A4[0]-2*cm, A4[1]-2*cm)
canvas.line(2*cm, 2*cm, A4[0]-2*cm, 2*cm)
if pageNumber > 1:
canvas.setFont('Times-Roman', 12)
canvas.drawString(4 * inch, cm, "%d" % pageNumber)
if hasattr(canvas, 'headerLine'): # hackish
headerline = string.join(canvas.headerLine, ' \xc2\x8d ')
canvas.drawString(2*cm, A4[1]-1.75*cm, headerline)
canvas.setFont('Times-Roman', 8)
msg = "Generated with docpy. See http://www.reportlab.com!"
canvas.drawString(2*cm, 1.65*cm, msg)
canvas.restoreState()
class MyTemplate(BaseDocTemplate):
"The document template used for all PDF documents."
_invalidInitArgs = ('pageTemplates',)
def __init__(self, filename, **kw):
frame1 = Frame(2.5*cm, 2.5*cm, 15*cm, 25*cm, id='F1')
self.allowSplitting = 0
apply(BaseDocTemplate.__init__, (self, filename), kw)
self.addPageTemplates(PageTemplate('normal', [frame1], mainPageFrame))
def afterFlowable(self, flowable):
"Takes care of header line, TOC and outline entries."
if flowable.__class__.__name__ == 'Paragraph':
f = flowable
# Build a list of heading parts.
# So far, this is the *last* item on the *previous* page...
if f.style.name[:8] == 'Heading0':
self.canv.headerLine = [f.text] # hackish
elif f.style.name[:8] == 'Heading1':
if len(self.canv.headerLine) == 2:
del self.canv.headerLine[-1]
elif len(self.canv.headerLine) == 3:
del self.canv.headerLine[-1]
del self.canv.headerLine[-1]
self.canv.headerLine.append(f.text)
elif f.style.name[:8] == 'Heading2':
if len(self.canv.headerLine) == 3:
del self.canv.headerLine[-1]
self.canv.headerLine.append(f.text)
if f.style.name[:7] == 'Heading':
# Register TOC entries.
headLevel = int(f.style.name[7:])
self.notify('TOCEntry', (headLevel, flowable.getPlainText(), self.page))
# Add PDF outline entries.
c = self.canv
title = f.text
key = str(hash(f))
lev = int(f.style.name[7:])
try:
if lev == 0:
isClosed = 0
else:
isClosed = 1
c.bookmarkPage(key)
c.addOutlineEntry(title, key, level=lev, closed=isClosed)
c.showOutline()
except:
if VERBOSE:
# AR hacking in exception handlers
print 'caught exception in MyTemplate.afterFlowable with heading text %s' % f.text
traceback.print_exc()
else:
pass
####################################################################
#
# Utility functions
#
####################################################################
def indentLevel(line, spacesPerTab=4):
"""Counts the indent levels on the front.
It is assumed that one tab equals 4 spaces.
"""
x = 0
nextTab = 4
for ch in line:
if ch == ' ':
x = x + 1
elif ch == '\t':
x = nextTab
nextTab = x + spacesPerTab
else:
return x
assert indentLevel('hello') == 0, 'error in indentLevel'
assert indentLevel(' hello') == 1, 'error in indentLevel'
assert indentLevel(' hello') == 2, 'error in indentLevel'
assert indentLevel(' hello') == 3, 'error in indentLevel'
assert indentLevel('\thello') == 4, 'error in indentLevel'
assert indentLevel(' \thello') == 4, 'error in indentLevel'
assert indentLevel('\t hello') == 5, 'error in indentLevel'
####################################################################
#
# Special-purpose document builders
#
####################################################################
class GraphPdfDocBuilder0(PdfDocBuilder0):
"""A PDF document builder displaying widgets and drawings.
This generates a PDF file where only methods named 'demo' are
listed for any class C. If C happens to be a subclass of Widget
and has a 'demo' method, this method is assumed to generate and
return a sample widget instance, that is then appended graphi-
cally to the Platypus story.
Something similar happens for functions. If their names start
with 'sample' they are supposed to generate and return a sample
drawing. This is then taken and appended graphically to the
Platypus story, as well.
"""
fileSuffix = '.pdf'
def begin(self, name='', typ=''):
styleSheet = getSampleStyleSheet()
self.code = styleSheet['Code']
self.bt = styleSheet['BodyText']
self.story = []
# Cover page
t = time.gmtime(time.time())
timeString = time.strftime("%Y-%m-%d %H:%M", t)
self.story.append(Paragraph('<font size=18>Documentation for %s "%s"</font>' % (typ, name), self.bt))
self.story.append(Paragraph('<font size=18>Generated by: graphdocpy.py version %s</font>' % __version__, self.bt))
self.story.append(Paragraph('<font size=18>Date generated: %s</font>' % timeString, self.bt))
self.story.append(Paragraph('<font size=18>Format: PDF</font>', self.bt))
self.story.append(PageBreak())
# Table of contents
toc = TableOfContents()
self.story.append(toc)
self.story.append(PageBreak())
def end(self, fileName=None):
if fileName: # overrides output path
self.outPath = fileName
elif self.packageName:
self.outPath = self.packageName + self.fileSuffix
elif self.skeleton:
self.outPath = self.skeleton.getModuleName() + self.fileSuffix
else:
self.outPath = ''
if self.outPath:
doc = MyTemplate(self.outPath)
doc.multiBuild(self.story)
def beginModule(self, name, doc, imported):
story = self.story
bt = self.bt
# Defer displaying the module header info to later...
self.shouldDisplayModule = (name, doc, imported)
self.hasDisplayedModule = 0
def endModule(self, name, doc, imported):
if self.hasDisplayedModule:
DocBuilder0.endModule(self, name, doc, imported)
def beginClasses(self, names):
# Defer displaying the module header info to later...
if self.shouldDisplayModule:
self.shouldDisplayClasses = names
# Skip all methods.
def beginMethod(self, name, doc, sig):
pass
def endMethod(self, name, doc, sig):
pass
def beginClass(self, name, doc, bases):
"Append a graphic demo of a Widget or Drawing at the end of a class."
if VERBOSE:
print 'GraphPdfDocBuilder.beginClass(%s...)' % name
aClass = eval('self.skeleton.moduleSpace.' + name)
if issubclass(aClass, Widget):
if self.shouldDisplayModule:
modName, modDoc, imported = self.shouldDisplayModule
self.story.append(Paragraph(modName, self.makeHeadingStyle(self.indentLevel-2, 'module')))
self.story.append(XPreformatted(modDoc, self.bt))
self.shouldDisplayModule = 0
self.hasDisplayedModule = 1
if self.shouldDisplayClasses:
self.story.append(Paragraph('Classes', self.makeHeadingStyle(self.indentLevel-1)))
self.shouldDisplayClasses = 0
PdfDocBuilder0.beginClass(self, name, doc, bases)
self.beginAttributes(aClass)
elif issubclass(aClass, Drawing):
if self.shouldDisplayModule:
modName, modDoc, imported = self.shouldDisplayModule
self.story.append(Paragraph(modName, self.makeHeadingStyle(self.indentLevel-2, 'module')))
self.story.append(XPreformatted(modDoc, self.bt))
self.shouldDisplayModule = 0
self.hasDisplayedModule = 1
if self.shouldDisplayClasses:
self.story.append(Paragraph('Classes', self.makeHeadingStyle(self.indentLevel-1)))
self.shouldDisplayClasses = 0
PdfDocBuilder0.beginClass(self, name, doc, bases)
def beginAttributes(self, aClass):
"Append a list of annotated attributes of a class."
self.story.append(Paragraph(
'Public Attributes',
self.makeHeadingStyle(self.indentLevel+1)))
map = aClass._attrMap
if map:
map = map.items()
map.sort()
else:
map = []
for name, typ in map:
if typ != None:
if hasattr(typ, 'desc'):
desc = typ.desc
else:
desc = '<i>%s</i>' % typ.__class__.__name__
else:
desc = '<i>None</i>'
self.story.append(Paragraph(
"<b>%s</b> %s" % (name, desc), self.bt))
self.story.append(Paragraph("", self.bt))
def endClass(self, name, doc, bases):
"Append a graphic demo of a Widget or Drawing at the end of a class."
PdfDocBuilder0.endClass(self, name, doc, bases)
aClass = eval('self.skeleton.moduleSpace.' + name)
if hasattr(aClass, '_nodoc'):
pass
elif issubclass(aClass, Widget):
try:
widget = aClass()
except AssertionError, err:
if _abstractclasserr_re.match(str(err)): return
raise
self.story.append(Spacer(0*cm, 0.5*cm))
self._showWidgetDemoCode(widget)
self.story.append(Spacer(0*cm, 0.5*cm))
self._showWidgetDemo(widget)
self.story.append(Spacer(0*cm, 0.5*cm))
self._showWidgetProperties(widget)
self.story.append(PageBreak())
elif issubclass(aClass, Drawing):
drawing = aClass()
self.story.append(Spacer(0*cm, 0.5*cm))
self._showDrawingCode(drawing)
self.story.append(Spacer(0*cm, 0.5*cm))
self._showDrawingDemo(drawing)
self.story.append(Spacer(0*cm, 0.5*cm))
def beginFunctions(self, names):
srch = string.join(names, ' ')
if string.find(string.join(names, ' '), ' sample') > -1:
PdfDocBuilder0.beginFunctions(self, names)
# Skip non-sample functions.
def beginFunction(self, name, doc, sig):
"Skip function for 'uninteresting' names."
if name[:6] == 'sample':
PdfDocBuilder0.beginFunction(self, name, doc, sig)
def endFunction(self, name, doc, sig):
"Append a drawing to the story for special function names."
if name[:6] != 'sample':
return
if VERBOSE:
print 'GraphPdfDocBuilder.endFunction(%s...)' % name
PdfDocBuilder0.endFunction(self, name, doc, sig)
aFunc = eval('self.skeleton.moduleSpace.' + name)
drawing = aFunc()
self.story.append(Spacer(0*cm, 0.5*cm))
self._showFunctionDemoCode(aFunc)
self.story.append(Spacer(0*cm, 0.5*cm))
self._showDrawingDemo(drawing)
self.story.append(PageBreak())
def _showFunctionDemoCode(self, function):
"""Show a demo code of the function generating the drawing."""
# Heading
self.story.append(Paragraph("<i>Example</i>", self.bt))
self.story.append(Paragraph("", self.bt))
# Sample code
codeSample = inspect.getsource(function)
self.story.append(Preformatted(codeSample, self.code))
def _showDrawingCode(self, drawing):
"""Show code of the drawing class."""
# Heading
#className = drawing.__class__.__name__
self.story.append(Paragraph("<i>Example</i>", self.bt))
# Sample code
codeSample = inspect.getsource(drawing.__class__.__init__)
self.story.append(Preformatted(codeSample, self.code))
def _showDrawingDemo(self, drawing):
"""Show a graphical demo of the drawing."""
# Add the given drawing to the story.
# Ignored if no GD rendering available
# or the demo method does not return a drawing.
try:
flo = renderPDF.GraphicsFlowable(drawing)
self.story.append(Spacer(6,6))
self.story.append(flo)
self.story.append(Spacer(6,6))
except:
if VERBOSE:
print 'caught exception in _showDrawingDemo'
traceback.print_exc()
else:
pass
def _showWidgetDemo(self, widget):
"""Show a graphical demo of the widget."""
# Get a demo drawing from the widget and add it to the story.
# Ignored if no GD rendering available
# or the demo method does not return a drawing.
try:
if VERIFY:
widget.verify()
drawing = widget.demo()
flo = renderPDF.GraphicsFlowable(drawing)
self.story.append(Spacer(6,6))
self.story.append(flo)
self.story.append(Spacer(6,6))
except:
if VERBOSE:
print 'caught exception in _showWidgetDemo'
traceback.print_exc()
else:
pass
def _showWidgetDemoCode(self, widget):
"""Show a demo code of the widget."""
# Heading
#className = widget.__class__.__name__
self.story.append(Paragraph("<i>Example</i>", self.bt))
# Sample code
codeSample = inspect.getsource(widget.__class__.demo)
self.story.append(Preformatted(codeSample, self.code))
def _showWidgetProperties(self, widget):
"""Dump all properties of a widget."""
props = widget.getProperties()
keys = props.keys()
keys.sort()
lines = []
for key in keys:
value = props[key]
f = getStringIO()
pprint.pprint(value, f)
value = f.getvalue()[:-1]
valueLines = string.split(value, '\n')
for i in range(1, len(valueLines)):
valueLines[i] = ' '*(len(key)+3) + valueLines[i]
value = string.join(valueLines, '\n')
lines.append('%s = %s' % (key, value))
text = join(lines, '\n')
self.story.append(Paragraph("<i>Properties of Example Widget</i>", self.bt))
self.story.append(Paragraph("", self.bt))
self.story.append(Preformatted(text, self.code))
class GraphHtmlDocBuilder0(HtmlDocBuilder0):
"A class to write the skeleton of a Python source."
fileSuffix = '.html'
def beginModule(self, name, doc, imported):
# Defer displaying the module header info to later...
self.shouldDisplayModule = (name, doc, imported)
self.hasDisplayedModule = 0
def endModule(self, name, doc, imported):
if self.hasDisplayedModule:
HtmlDocBuilder0.endModule(self, name, doc, imported)
def beginClasses(self, names):
# Defer displaying the module header info to later...
if self.shouldDisplayModule:
self.shouldDisplayClasses = names
# Skip all methods.
def beginMethod(self, name, doc, sig):
pass
def endMethod(self, name, doc, sig):
pass
def beginClass(self, name, doc, bases):
"Append a graphic demo of a widget at the end of a class."
aClass = eval('self.skeleton.moduleSpace.' + name)
if issubclass(aClass, Widget):
if self.shouldDisplayModule:
modName, modDoc, imported = self.shouldDisplayModule
self.outLines.append('<H2>%s</H2>' % modName)
self.outLines.append('<PRE>%s</PRE>' % modDoc)
self.shouldDisplayModule = 0
self.hasDisplayedModule = 1
if self.shouldDisplayClasses:
self.outLines.append('<H2>Classes</H2>')
self.shouldDisplayClasses = 0
HtmlDocBuilder0.beginClass(self, name, doc, bases)
def endClass(self, name, doc, bases):
"Append a graphic demo of a widget at the end of a class."
HtmlDocBuilder0.endClass(self, name, doc, bases)
aClass = eval('self.skeleton.moduleSpace.' + name)
if issubclass(aClass, Widget):
widget = aClass()
self._showWidgetDemoCode(widget)
self._showWidgetDemo(widget)
self._showWidgetProperties(widget)
def beginFunctions(self, names):
if string.find(string.join(names, ' '), ' sample') > -1:
HtmlDocBuilder0.beginFunctions(self, names)
# Skip non-sample functions.
def beginFunction(self, name, doc, sig):
"Skip function for 'uninteresting' names."
if name[:6] == 'sample':
HtmlDocBuilder0.beginFunction(self, name, doc, sig)
def endFunction(self, name, doc, sig):
"Append a drawing to the story for special function names."
if name[:6] != 'sample':
return
HtmlDocBuilder0.endFunction(self, name, doc, sig)
aFunc = eval('self.skeleton.moduleSpace.' + name)
drawing = aFunc()
self._showFunctionDemoCode(aFunc)
self._showDrawingDemo(drawing, aFunc.__name__)
def _showFunctionDemoCode(self, function):
"""Show a demo code of the function generating the drawing."""
# Heading
self.outLines.append('<H3>Example</H3>')
# Sample code
codeSample = inspect.getsource(function)
self.outLines.append('<PRE>%s</PRE>' % codeSample)
def _showDrawingDemo(self, drawing, name):
"""Show a graphical demo of the drawing."""
# Add the given drawing to the story.
# Ignored if no GD rendering available
# or the demo method does not return a drawing.
try:
from reportlab.graphics import renderPM
modName = self.skeleton.getModuleName()
path = '%s-%s.jpg' % (modName, name)
renderPM.drawToFile(drawing, path, fmt='JPG')
self.outLines.append('<H3>Demo</H3>')
self.outLines.append(makeHtmlInlineImage(path))
except:
if VERBOSE:
print 'caught exception in GraphHTMLDocBuilder._showDrawingDemo'
traceback.print_exc()
else:
pass
def _showWidgetDemo(self, widget):
"""Show a graphical demo of the widget."""
# Get a demo drawing from the widget and add it to the story.
# Ignored if no GD rendering available
# or the demo method does not return a drawing.
try:
from reportlab.graphics import renderPM
drawing = widget.demo()
if VERIFY:
widget.verify()
modName = self.skeleton.getModuleName()
path = '%s-%s.jpg' % (modName, widget.__class__.__name__)
renderPM.drawToFile(drawing, path, fmt='JPG')
self.outLines.append('<H3>Demo</H3>')
self.outLines.append(makeHtmlInlineImage(path))
except:
if VERBOSE:
print 'caught exception in GraphHTMLDocBuilder._showWidgetDemo'
traceback.print_exc()
else:
pass
def _showWidgetDemoCode(self, widget):
"""Show a demo code of the widget."""
# Heading
#className = widget.__class__.__name__
self.outLines.append('<H3>Example Code</H3>')
# Sample code
codeSample = inspect.getsource(widget.__class__.demo)
self.outLines.append('<PRE>%s</PRE>' % codeSample)
self.outLines.append('')
def _showWidgetProperties(self, widget):
"""Dump all properties of a widget."""
props = widget.getProperties()
keys = props.keys()
keys.sort()
lines = []
for key in keys:
value = props[key]
# Method 3
f = getStringIO()
pprint.pprint(value, f)
value = f.getvalue()[:-1]
valueLines = string.split(value, '\n')
for i in range(1, len(valueLines)):
valueLines[i] = ' '*(len(key)+3) + valueLines[i]
value = string.join(valueLines, '\n')
lines.append('%s = %s' % (key, value))
text = join(lines, '\n')
self.outLines.append('<H3>Properties of Example Widget</H3>')
self.outLines.append('<PRE>%s</PRE>' % text)
self.outLines.append('')
# Highly experimental!
class PlatypusDocBuilder0(DocBuilder0):
"Document the skeleton of a Python module as a Platypus story."
fileSuffix = '.pps' # A pickled Platypus story.
def begin(self, name='', typ=''):
styleSheet = getSampleStyleSheet()
self.code = styleSheet['Code']
self.bt = styleSheet['BodyText']
self.story = []
def end(self):
if self.packageName:
self.outPath = self.packageName + self.fileSuffix
elif self.skeleton:
self.outPath = self.skeleton.getModuleName() + self.fileSuffix
else:
self.outPath = ''
if self.outPath:
f = open(self.outPath, 'w')
pickle.dump(self.story, f)
def beginPackage(self, name):
DocBuilder0.beginPackage(self, name)
self.story.append(Paragraph(name, self.bt))
def beginModule(self, name, doc, imported):
story = self.story
bt = self.bt
story.append(Paragraph(name, bt))
story.append(XPreformatted(doc, bt))
def beginClasses(self, names):
self.story.append(Paragraph('Classes', self.bt))
def beginClass(self, name, doc, bases):
bt = self.bt
story = self.story
if bases:
bases = map(lambda b:b.__name__, bases) # hack
story.append(Paragraph('%s(%s)' % (name, join(bases, ', ')), bt))
else:
story.append(Paragraph(name, bt))
story.append(XPreformatted(doc, bt))
def beginMethod(self, name, doc, sig):
bt = self.bt
story = self.story
story.append(Paragraph(name+sig, bt))
story.append(XPreformatted(doc, bt))
def beginFunctions(self, names):
if names:
self.story.append(Paragraph('Functions', self.bt))
def beginFunction(self, name, doc, sig):
bt = self.bt
story = self.story
story.append(Paragraph(name+sig, bt))
story.append(XPreformatted(doc, bt))
####################################################################
#
# Main
#
####################################################################
def printUsage():
"""graphdocpy.py - Automated documentation for the RL Graphics library.
Usage: python graphdocpy.py [options]
[options]
-h Print this help message.
-f name Use the document builder indicated by 'name',
e.g. Html, Pdf.
-m module Generate document for module named 'module'.
'module' may follow any of these forms:
- docpy.py
- docpy
- c:\\test\\docpy
and can be any of these:
- standard Python modules
- modules in the Python search path
- modules in the current directory
-p package Generate document for package named 'package'
(default is 'reportlab.graphics').
'package' may follow any of these forms:
- reportlab
- reportlab.graphics.charts
- c:\\test\\reportlab
and can be any of these:
- standard Python packages (?)
- packages in the Python search path
- packages in the current directory
-s Silent mode (default is unset).
Examples:
python graphdocpy.py reportlab.graphics
python graphdocpy.py -m signsandsymbols.py -f Pdf
python graphdocpy.py -m flags.py -f Html
python graphdocpy.py -m barchart1.py
"""
# The following functions, including main(), are actually
# the same as in docpy.py (except for some defaults).
def documentModule0(pathOrName, builder, opts={}):
"""Generate documentation for one Python file in some format.
This handles Python standard modules like string, custom modules
on the Python search path like e.g. docpy as well as modules
specified with their full path like C:/tmp/junk.py.
The doc file will always be saved in the current directory with
a basename equal to that of the module, e.g. docpy.
"""
cwd = os.getcwd()
# Append directory to Python search path if we get one.
dirName = os.path.dirname(pathOrName)
if dirName:
sys.path.append(dirName)
# Remove .py extension from module name.
if pathOrName[-3:] == '.py':
modname = pathOrName[:-3]
else:
modname = pathOrName
# Remove directory paths from module name.
if dirName:
modname = os.path.basename(modname)
# Load the module.
try:
module = __import__(modname)
except:
print 'Failed to import %s.' % modname
os.chdir(cwd)
return
# Do the real documentation work.
s = ModuleSkeleton0()
s.inspect(module)
builder.write(s)
# Remove appended directory from Python search path if we got one.
if dirName:
del sys.path[-1]
os.chdir(cwd)
def _packageWalkCallback((builder, opts), dirPath, files):
"A callback function used when waking over a package tree."
#must CD into a directory to document the module correctly
cwd = os.getcwd()
os.chdir(dirPath)
# Skip __init__ files.
files = filter(lambda f:f != '__init__.py', files)
files = filter(lambda f:f[-3:] == '.py', files)
for f in files:
path = os.path.join(dirPath, f)
## if not opts.get('isSilent', 0):
## print path
builder.indentLevel = builder.indentLevel + 1
#documentModule0(path, builder)
documentModule0(f, builder)
builder.indentLevel = builder.indentLevel - 1
#CD back out
os.chdir(cwd)
def documentPackage0(pathOrName, builder, opts={}):
"""Generate documentation for one Python package in some format.
'pathOrName' can be either a filesystem path leading to a Python
package or package name whose path will be resolved by importing
the top-level module.
The doc file will always be saved in the current directory with
a basename equal to that of the package, e.g. reportlab.lib.
"""
# Did we get a package path with OS-dependant seperators...?
if os.sep in pathOrName:
path = pathOrName
name = os.path.splitext(os.path.basename(path))[0]
# ... or rather a package name?
else:
name = pathOrName
package = __import__(name)
# Some special care needed for dotted names.
if '.' in name:
subname = 'package' + name[find(name, '.'):]
package = eval(subname)
path = os.path.dirname(package.__file__)
cwd = os.getcwd()
os.chdir(path)
builder.beginPackage(name)
os.path.walk(path, _packageWalkCallback, (builder, opts))
builder.endPackage(name)
os.chdir(cwd)
def makeGraphicsReference(outfilename):
"Make graphics_reference.pdf"
builder = GraphPdfDocBuilder0()
builder.begin(name='reportlab.graphics', typ='package')
documentPackage0('reportlab.graphics', builder, {'isSilent': 0})
builder.end(outfilename)
print 'made graphics reference in %s' % outfilename
def main():
"Handle command-line options and trigger corresponding action."
opts, args = getopt.getopt(sys.argv[1:], 'hsf:m:p:')
# Make an options dictionary that is easier to use.
optsDict = {}
for k, v in opts:
optsDict[k] = v
hasOpt = optsDict.has_key
# On -h print usage and exit immediately.
if hasOpt('-h'):
print printUsage.__doc__
sys.exit(0)
# On -s set silent mode.
isSilent = hasOpt('-s')
# On -f set the appropriate DocBuilder to use or a default one.
builder = { 'Pdf': GraphPdfDocBuilder0,
'Html': GraphHtmlDocBuilder0,
}[optsDict.get('-f', 'Pdf')]()
# Set default module or package to document.
if not hasOpt('-p') and not hasOpt('-m'):
optsDict['-p'] = 'reportlab.graphics'
# Save a few options for further use.
options = {'isSilent':isSilent}
# Now call the real documentation functions.
if hasOpt('-m'):
nameOrPath = optsDict['-m']
if not isSilent:
print "Generating documentation for module %s..." % nameOrPath
builder.begin(name=nameOrPath, typ='module')
documentModule0(nameOrPath, builder, options)
elif hasOpt('-p'):
nameOrPath = optsDict['-p']
if not isSilent:
print "Generating documentation for package %s..." % nameOrPath
builder.begin(name=nameOrPath, typ='package')
documentPackage0(nameOrPath, builder, options)
builder.end()
if not isSilent:
print "Saved %s." % builder.outPath
#if doing the usual, put a copy in docs
if builder.outPath == 'reportlab.graphics.pdf':
import shutil, reportlab
dst = os.path.join(os.path.dirname(reportlab.__file__),'docs','graphics_reference.pdf')
shutil.copyfile('reportlab.graphics.pdf', dst)
if not isSilent:
print 'copied to '+dst
def makeSuite():
"standard test harness support - run self as separate process"
from reportlab.test.utils import ScriptThatMakesFileTest
return ScriptThatMakesFileTest('tools/docco',
'graphdocpy.py',
'reportlab.graphics.pdf')
if __name__ == '__main__':
main()

View File

@ -0,0 +1,411 @@
#!/bin/env python
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/docco/rl_doc_utils.py
__version__=''' $Id: rl_doc_utils.py 2830 2006-04-05 15:18:32Z rgbecker $ '''
__doc__ = """
This module contains utilities for generating guides
"""
import os, sys, glob
import string
from rltemplate import RLDocTemplate
from stylesheet import getStyleSheet
styleSheet = getStyleSheet()
#from reportlab.platypus.doctemplate import SimpleDocTemplate
from reportlab.lib.units import inch
from reportlab.lib.pagesizes import letter, A4, A5, A3 # latter two for testing
from reportlab.rl_config import defaultPageSize
from reportlab.platypus import figures
from reportlab.platypus import Paragraph, Spacer, Preformatted,\
PageBreak, CondPageBreak, Flowable, Table, TableStyle, \
NextPageTemplate, KeepTogether, Image, XPreformatted
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib import colors
from reportlab.lib.sequencer import getSequencer
import examples
appmode=0
from t_parse import Template
QFcodetemplate = Template("X$X$", "X")
QFreptemplate = Template("X^X^", "X")
codesubst = "%s<font name=Courier>%s</font>"
QFsubst = "%s<font name=Courier><i>%s</i></font>"
def quickfix(text):
"""inside text find any subsequence of form $subsequence$.
Format the subsequence as code. If similarly if text contains ^arg^
format the arg as replaceable. The escape sequence for literal
$ is $\\$ (^ is ^\\^.
"""
from string import join
for (template,subst) in [(QFcodetemplate, codesubst), (QFreptemplate, QFsubst)]:
fragment = text
parts = []
try:
while fragment:
try:
(matches, index) = template.PARSE(fragment)
except: raise ValueError
else:
[prefix, code] = matches
if code == "\\":
part = fragment[:index]
else:
part = subst % (prefix, code)
parts.append(part)
fragment = fragment[index:]
except ValueError:
parts.append(fragment)
text = join(parts, "")
return text
#print quickfix("$testing$ testing $one$ ^two^ $three(^four^)$")
H1 = styleSheet['Heading1']
H2 = styleSheet['Heading2']
H3 = styleSheet['Heading3']
H4 = styleSheet['Heading4']
B = styleSheet['BodyText']
BU = styleSheet['Bullet']
Comment = styleSheet['Comment']
Centred = styleSheet['Centred']
Caption = styleSheet['Caption']
#set up numbering
seq = getSequencer()
seq.setFormat('Chapter','1')
seq.setFormat('Section','1')
seq.setFormat('Appendix','A')
seq.setFormat('Figure', '1')
seq.chain('Chapter','Section')
seq.chain('Chapter','Figure')
lessonnamestyle = H2
discussiontextstyle = B
exampletextstyle = styleSheet['Code']
# size for every example
examplefunctionxinches = 5.5
examplefunctionyinches = 3
examplefunctiondisplaysizes = (examplefunctionxinches*inch, examplefunctionyinches*inch)
def getJustFontPaths():
'''return afm and pfb for Just's files'''
import reportlab
folder = os.path.dirname(reportlab.__file__) + os.sep + 'fonts'
return os.path.join(folder, 'LeERC___.AFM'), os.path.join(folder, 'LeERC___.PFB')
# for testing
def NOP(*x,**y):
return None
def CPage(inches):
getStory().append(CondPageBreak(inches*inch))
def newPage():
getStory().append(PageBreak())
def nextTemplate(templName):
f = NextPageTemplate(templName)
getStory().append(f)
def disc(text, klass=Paragraph, style=discussiontextstyle):
text = quickfix(text)
P = klass(text, style)
getStory().append(P)
def restartList():
getSequencer().reset('list1')
def list(text, doBullet=1):
text=quickfix(text)
if doBullet:
text='<bullet><seq id="list1"/>.</bullet>'+text
P = Paragraph(text, BU)
getStory().append(P)
def bullet(text):
text='<bullet><font name="Symbol">\xe2\x80\xa2</font></bullet>' + quickfix(text)
P = Paragraph(text, BU)
getStory().append(P)
def eg(text,before=0.1,after=0):
space(before)
disc(text, klass=Preformatted, style=exampletextstyle)
space(after)
def space(inches=1./6):
if inches: getStory().append(Spacer(0,inches*inch))
def EmbeddedCode(code,name='t'):
eg(code)
disc("produces")
exec code+("\ngetStory().append(%s)\n"%name)
def startKeep():
return len(getStory())
def endKeep(s):
S = getStory()
k = KeepTogether(S[s:])
S[s:] = [k]
def title(text):
"""Use this for the document title only"""
disc(text,style=styleSheet['Title'])
#AR 3/7/2000 - defining three new levels of headings; code
#should be swapped over to using them.
def heading1(text):
"""Use this for chapters. Lessons within a big chapter
should now use heading2 instead. Chapters get numbered."""
getStory().append(PageBreak())
p = Paragraph('Chapter <seq id="Chapter"/> ' + quickfix(text), H1)
getStory().append(p)
def Appendix1(text,):
global appmode
getStory().append(PageBreak())
if not appmode:
seq.setFormat('Chapter','A')
seq.reset('Chapter')
appmode = 1
p = Paragraph('Appendix <seq id="Chapter"/> ' + quickfix(text), H1)
getStory().append(p)
def heading2(text):
"""Used to be 'lesson'"""
getStory().append(CondPageBreak(inch))
p = Paragraph('<seq template="%(Chapter)s.%(Section+)s "/>' + quickfix(text), H2)
getStory().append(p)
def heading3(text):
"""Used to be most of the plain old 'head' sections"""
getStory().append(CondPageBreak(inch))
p = Paragraph(quickfix(text), H3)
getStory().append(p)
def image(path, width=None, height=None ):
s = startKeep()
space(.2)
import reportlab
rlDocImageDir = os.path.join(os.path.dirname(reportlab.__file__), 'docs','images')
getStory().append(Image(os.path.join(rlDocImageDir,path),width,height))
space(.2)
endKeep(s)
def heading4(text):
"""Used to be most of the plain old 'head' sections"""
getStory().append(CondPageBreak(inch))
p = Paragraph(quickfix(text), H4)
getStory().append(p)
def todo(text):
"""Used for notes to ourselves"""
getStory().append(Paragraph(quickfix(text), Comment))
def centred(text):
getStory().append(Paragraph(quickfix(text), Centred))
def caption(text):
getStory().append(Paragraph(quickfix(text), Caption))
class Illustration(figures.Figure):
"""The examples are all presented as functions which do
something to a canvas, with a constant height and width
used. This puts them inside a figure box with a caption."""
def __init__(self, operation, caption, width=None, height=None):
stdwidth, stdheight = examplefunctiondisplaysizes
if not width:
width = stdwidth
if not height:
height = stdheight
#figures.Figure.__init__(self, stdwidth * 0.75, stdheight * 0.75)
figures.Figure.__init__(self, width, height,
'Figure <seq template="%(Chapter)s-%(Figure+)s"/>: ' + quickfix(caption))
self.operation = operation
def drawFigure(self):
#shrink it a little...
#self.canv.scale(0.75, 0.75)
self.operation(self.canv)
def illust(operation, caption, width=None, height=None):
i = Illustration(operation, caption, width=width, height=height)
getStory().append(i)
class GraphicsDrawing(Illustration):
"""Lets you include reportlab/graphics drawings seamlessly,
with the right numbering."""
def __init__(self, drawing, caption):
figures.Figure.__init__(self,
drawing.width,
drawing.height,
'Figure <seq template="%(Chapter)s-%(Figure+)s"/>: ' + quickfix(caption)
)
self.drawing = drawing
def drawFigure(self):
d = self.drawing
d.wrap(d.width, d.height)
d.drawOn(self.canv, 0, 0)
def draw(drawing, caption):
d = GraphicsDrawing(drawing, caption)
getStory().append(d)
class ParaBox(figures.Figure):
"""Illustrates paragraph examples, with style attributes on the left"""
descrStyle = ParagraphStyle('description',
fontName='Courier',
fontSize=8,
leading=9.6)
def __init__(self, text, style, caption):
figures.Figure.__init__(self, 0, 0, caption)
self.text = text
self.style = style
self.para = Paragraph(text, style)
styleText = self.getStyleText(style)
self.pre = Preformatted(styleText, self.descrStyle)
def wrap(self, availWidth, availHeight):
"""Left 30% is for attributes, right 50% for sample,
10% gutter each side."""
self.x0 = availWidth * 0.05 #left of box
self.x1 = availWidth * 0.1 #left of descriptive text
self.x2 = availWidth * 0.5 #left of para itself
self.x3 = availWidth * 0.9 #right of para itself
self.x4 = availWidth * 0.95 #right of box
self.width = self.x4 - self.x0
self.dx = 0.5 * (availWidth - self.width)
paw, self.pah = self.para.wrap(self.x3 - self.x2, availHeight)
self.pah = self.pah + self.style.spaceBefore + self.style.spaceAfter
prw, self.prh = self.pre.wrap(self.x2 - self.x1, availHeight)
self.figureHeight = max(self.prh, self.pah) * 10.0/9.0
return figures.Figure.wrap(self, availWidth, availHeight)
def getStyleText(self, style):
"""Converts style to preformatted block of text"""
lines = []
for (key, value) in style.__dict__.items():
lines.append('%s = %s' % (key, value))
lines.sort()
return string.join(lines, '\n')
def drawFigure(self):
#now we fill in the bounding box and before/after boxes
self.canv.saveState()
self.canv.setFillGray(0.95)
self.canv.setDash(1,3)
self.canv.rect(self.x2 - self.x0,
self.figureHeight * 0.95 - self.pah,
self.x3-self.x2, self.para.height,
fill=1,stroke=1)
self.canv.setFillGray(0.90)
self.canv.rect(self.x2 - self.x0, #spaceBefore
self.figureHeight * 0.95 - self.pah + self.para.height,
self.x3-self.x2, self.style.spaceBefore,
fill=1,stroke=1)
self.canv.rect(self.x2 - self.x0, #spaceBefore
self.figureHeight * 0.95 - self.pah - self.style.spaceAfter,
self.x3-self.x2, self.style.spaceAfter,
fill=1,stroke=1)
self.canv.restoreState()
#self.canv.setFillColor(colors.yellow)
self.para.drawOn(self.canv, self.x2 - self.x0,
self.figureHeight * 0.95 - self.pah)
self.pre.drawOn(self.canv, self.x1 - self.x0,
self.figureHeight * 0.95 - self.prh)
def getStyleText(self, style):
"""Converts style to preformatted block of text"""
lines = []
for (key, value) in style.__dict__.items():
if key not in ('name','parent'):
lines.append('%s = %s' % (key, value))
return string.join(lines, '\n')
class ParaBox2(figures.Figure):
"""Illustrates a paragraph side-by-side with the raw
text, to show how the XML works."""
def __init__(self, text, caption):
figures.Figure.__init__(self, 0, 0, caption)
descrStyle = ParagraphStyle('description',
fontName='Courier',
fontSize=8,
leading=9.6)
textStyle = B
self.text = text
self.left = Paragraph('<![CDATA[' + text + ']]>', descrStyle)
self.right = Paragraph(text, B)
def wrap(self, availWidth, availHeight):
self.width = availWidth * 0.9
colWidth = 0.4 * self.width
lw, self.lh = self.left.wrap(colWidth, availHeight)
rw, self.rh = self.right.wrap(colWidth, availHeight)
self.figureHeight = max(self.lh, self.rh) * 10.0/9.0
return figures.Figure.wrap(self, availWidth, availHeight)
def drawFigure(self):
self.left.drawOn(self.canv,
self.width * 0.05,
self.figureHeight * 0.95 - self.lh
)
self.right.drawOn(self.canv,
self.width * 0.55,
self.figureHeight * 0.95 - self.rh
)
def parabox(text, style, caption):
p = ParaBox(text, style,
'Figure <seq template="%(Chapter)s-%(Figure+)s"/>: ' + quickfix(caption)
)
getStory().append(p)
def parabox2(text, caption):
p = ParaBox2(text,
'Figure <seq template="%(Chapter)s-%(Figure+)s"/>: ' + quickfix(caption)
)
getStory().append(p)
def pencilnote():
getStory().append(examples.NoteAnnotation())
from reportlab.lib.colors import tan, green
def handnote(xoffset=0, size=None, fillcolor=tan, strokecolor=green):
getStory().append(examples.HandAnnotation(xoffset,size,fillcolor,strokecolor))
#make a singleton, created when requested rather
#than each time a chapter imports it.
_story = []
def setStory(story=[]):
global _story
_story = story
def getStory():
return _story

View File

@ -0,0 +1,135 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/docco/rltemplate.py
# doc template for RL manuals. Currently YAML is hard-coded
#to use this, which is wrong.
from reportlab.platypus import PageTemplate, \
BaseDocTemplate, Frame, Paragraph
from reportlab.lib.units import inch, cm
from reportlab.rl_config import defaultPageSize
class FrontCoverTemplate(PageTemplate):
def __init__(self, id, pageSize=defaultPageSize):
self.pageWidth = pageSize[0]
self.pageHeight = pageSize[1]
frame1 = Frame(inch,
3*inch,
self.pageWidth - 2*inch,
self.pageHeight - 518, id='cover')
PageTemplate.__init__(self, id, [frame1]) # note lack of onPage
def afterDrawPage(self, canvas, doc):
canvas.saveState()
canvas.drawImage('../images/replogo.gif',2*inch, 8*inch)
canvas.setFont('Times-Roman', 10)
canvas.line(inch, 120, self.pageWidth - inch, 120)
canvas.drawString(inch, 100, '165 The Broadway')
canvas.drawString(inch, 88, 'Wimbledon')
canvas.drawString(inch, 76, 'London SW19 1NE')
canvas.drawString(inch, 64, 'United Kingdom')
canvas.restoreState()
class OneColumnTemplate(PageTemplate):
def __init__(self, id, pageSize=defaultPageSize):
self.pageWidth = pageSize[0]
self.pageHeight = pageSize[1]
frame1 = Frame(inch,
inch,
self.pageWidth - 2*inch,
self.pageHeight - 2*inch,
id='normal')
PageTemplate.__init__(self, id, [frame1]) # note lack of onPage
def afterDrawPage(self, canvas, doc):
y = self.pageHeight - 50
canvas.saveState()
canvas.setFont('Times-Roman', 10)
canvas.drawString(inch, y+8, doc.title)
canvas.drawRightString(self.pageWidth - inch, y+8, doc.chapter)
canvas.line(inch, y, self.pageWidth - inch, y)
canvas.drawCentredString(doc.pagesize[0] / 2, 0.75*inch, 'Page %d' % canvas.getPageNumber())
canvas.restoreState()
class TwoColumnTemplate(PageTemplate):
def __init__(self, id, pageSize=defaultPageSize):
self.pageWidth = pageSize[0]
self.pageHeight = pageSize[1]
colWidth = 0.5 * (self.pageWidth - 2.25*inch)
frame1 = Frame(inch,
inch,
colWidth,
self.pageHeight - 2*inch,
id='leftCol')
frame2 = Frame(0.5 * self.pageWidth + 0.125,
inch,
colWidth,
self.pageHeight - 2*inch,
id='rightCol')
PageTemplate.__init__(self, id, [frame1, frame2]) # note lack of onPage
def afterDrawPage(self, canvas, doc):
y = self.pageHeight - 50
canvas.saveState()
canvas.setFont('Times-Roman', 10)
canvas.drawString(inch, y+8, doc.title)
canvas.drawRightString(self.pageWidth - inch, y+8, doc.chapter)
canvas.line(inch, y, self.pageWidth - inch, y*inch)
canvas.drawCentredString(doc.pagesize[0] / 2, 0.75*inch, 'Page %d' % canvas.getPageNumber())
canvas.restoreState()
class RLDocTemplate(BaseDocTemplate):
def afterInit(self):
self.addPageTemplates(FrontCoverTemplate('Cover', self.pagesize))
self.addPageTemplates(OneColumnTemplate('Normal', self.pagesize))
self.addPageTemplates(TwoColumnTemplate('TwoColumn', self.pagesize))
#just playing
self.title = "(Document Title Goes Here)"
self.chapter = "(No chapter yet)"
self.chapterNo = 1 #unique keys
self.sectionNo = 1 # unique keys
## # AR hack
## self.counter = 1
def beforeDocument(self):
self.canv.showOutline()
def afterFlowable(self, flowable):
"""Detect Level 1 and 2 headings, build outline,
and track chapter title."""
if isinstance(flowable, Paragraph):
style = flowable.style.name
## #AR debug text
## try:
## print '%d: %s...' % (self.counter, flowable.getPlainText()[0:40])
## except AttributeError:
## print '%d: (something with ABag)' % self.counter
## self.counter = self.counter + 1
if style == 'Title':
self.title = flowable.getPlainText()
elif style == 'Heading1':
self.chapter = flowable.getPlainText()
key = 'ch%d' % self.chapterNo
self.canv.bookmarkPage(key)
self.canv.addOutlineEntry(flowable.getPlainText(),
key, 0, 0)
self.chapterNo = self.chapterNo + 1
self.sectionNo = 1
elif style == 'Heading2':
self.section = flowable.text
key = 'ch%ds%d' % (self.chapterNo, self.sectionNo)
self.canv.bookmarkPage(key)
self.canv.addOutlineEntry(flowable.getPlainText(),
key, 1, 0)
self.sectionNo = self.sectionNo + 1

View File

@ -0,0 +1,165 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/docco/stylesheet.py
#standard stylesheet for our manuals
from reportlab.lib.styles import StyleSheet1, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT, TA_JUSTIFY
from reportlab.lib import colors
def getStyleSheet():
"""Returns a stylesheet object"""
stylesheet = StyleSheet1()
stylesheet.add(ParagraphStyle(name='Normal',
fontName='Times-Roman',
fontSize=10,
leading=12,
spaceBefore=6)
)
stylesheet.add(ParagraphStyle(name='Comment',
fontName='Times-Italic')
)
stylesheet.add(ParagraphStyle(name='Indent0',
leftIndent=18,)
)
stylesheet.add(ParagraphStyle(name='Indent1',
leftIndent=36,
firstLineIndent=0,
spaceBefore=1,
spaceAfter=7)
)
stylesheet.add(ParagraphStyle(name='Indent2',
leftIndent=50,
firstLineIndent=0,
spaceAfter=100)
)
stylesheet.add(ParagraphStyle(name='BodyText',
parent=stylesheet['Normal'],
spaceBefore=6)
)
stylesheet.add(ParagraphStyle(name='Italic',
parent=stylesheet['BodyText'],
fontName = 'Times-Italic')
)
stylesheet.add(ParagraphStyle(name='Heading1',
parent=stylesheet['Normal'],
fontName = 'Times-Bold',
alignment=TA_CENTER,
fontSize=18,
leading=22,
spaceAfter=6),
alias='h1')
stylesheet.add(ParagraphStyle(name='Heading2',
parent=stylesheet['Normal'],
fontName = 'Times-Bold',
fontSize=14,
leading=17,
spaceBefore=12,
spaceAfter=6),
alias='h2')
stylesheet.add(ParagraphStyle(name='Heading3',
parent=stylesheet['Normal'],
fontName = 'Times-BoldItalic',
fontSize=12,
leading=14,
spaceBefore=12,
spaceAfter=6),
alias='h3')
stylesheet.add(ParagraphStyle(name='Heading4',
parent=stylesheet['Normal'],
fontName = 'Times-BoldItalic',
spaceBefore=10,
spaceAfter=4),
alias='h4')
stylesheet.add(ParagraphStyle(name='Title',
parent=stylesheet['Normal'],
fontName = 'Times-Bold',
fontSize=32,
leading=40,
spaceAfter=36,
alignment=TA_CENTER
),
alias='t')
stylesheet.add(ParagraphStyle(name='Bullet',
parent=stylesheet['Normal'],
firstLineIndent=0,
leftIndent=54,
bulletIndent=18,
spaceBefore=0,
bulletFontName='Symbol'),
alias='bu')
stylesheet.add(ParagraphStyle(name='Definition',
parent=stylesheet['Normal'],
firstLineIndent=0,
leftIndent=36,
bulletIndent=0,
spaceBefore=6,
bulletFontName='Times-BoldItalic'),
alias='df')
stylesheet.add(ParagraphStyle(name='Code',
parent=stylesheet['Normal'],
fontName='Courier',
textColor=colors.navy,
fontSize=8,
leading=8.8,
leftIndent=36,
firstLineIndent=0))
stylesheet.add(ParagraphStyle(name='Link',
parent=stylesheet['Code'],
spaceAfter=7,
spaceBefore=0,
leftIndent=55))
stylesheet.add(ParagraphStyle(name='FunctionHeader',
parent=stylesheet['Normal'],
fontName='Courier-Bold',
fontSize=8,
leading=8.8))
stylesheet.add(ParagraphStyle(name='DocString',
parent=stylesheet['Normal'],
fontName='Courier',
fontSize=8,
leftIndent=18,
leading=8.8))
stylesheet.add(ParagraphStyle(name='DocStringIndent',
parent=stylesheet['Normal'],
fontName='Courier',
fontSize=8,
leftIndent=36,
leading=8.8))
stylesheet.add(ParagraphStyle(name='URL',
parent=stylesheet['Normal'],
fontName='Courier',
textColor=colors.navy,
alignment=TA_CENTER),
alias='u')
stylesheet.add(ParagraphStyle(name='Centred',
parent=stylesheet['Normal'],
alignment=TA_CENTER
))
stylesheet.add(ParagraphStyle(name='Caption',
parent=stylesheet['Centred'],
fontName='Times-Italic'
))
return stylesheet

View File

@ -0,0 +1,247 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/docco/t_parse.py
"""
Template parsing module inspired by REXX (with thanks to Donn Cave for discussion).
Template initialization has the form:
T = Template(template_string, wild_card_marker, single_char_marker,
x = regex_x, y = regex_y, ...)
Parsing has the form
([match1, match2, ..., matchn], lastindex) = T.PARSE(string)
Only the first argument is mandatory.
The resultant object efficiently parses strings that match the template_string,
giving a list of substrings that correspond to each "directive" of the template.
Template directives:
Wildcard:
The template may be initialized with a wildcard that matches any string
up to the string matching the next directive (which may not be a wild
card or single character marker) or the next literal sequence of characters
of the template. The character that represents a wildcard is specified
by the wild_card_marker parameter, which has no default.
For example, using X as the wildcard:
>>> T = Template("prefixXinteriorX", "X")
>>> T.PARSE("prefix this is before interior and this is after")
([' this is before ', ' and this is after'], 47)
>>> T = Template("<X>X<X>", "X")
>>> T.PARSE('<A HREF="index.html">go to index</A>')
(['A HREF="index.html"', 'go to index', '/A'], 36)
Obviously the character used to represent the wildcard must be distinct
from the characters used to represent literals or other directives.
Fixed length character sequences:
The template may have a marker character which indicates a fixed
length field. All adjacent instances of this marker will be matched
by a substring of the same length in the parsed string. For example:
>>> T = Template("NNN-NN-NNNN", single_char_marker="N")
>>> T.PARSE("1-2-34-5-12")
(['1-2', '34', '5-12'], 11)
>>> T.PARSE("111-22-3333")
(['111', '22', '3333'], 11)
>>> T.PARSE("1111-22-3333")
ValueError: literal not found at (3, '-')
A template may have multiple fixed length markers, which allows fixed
length fields to be adjacent, but recognized separately. For example:
>>> T = Template("MMDDYYX", "X", "MDY")
>>> T.PARSE("112489 Somebody's birthday!")
(['11', '24', '89', " Somebody's birthday!"], 27)
Regular expression markers:
The template may have markers associated with regular expressions.
the regular expressions may be either string represenations of compiled.
For example:
>>> T = Template("v: s i", v=id, s=str, i=int)
>>> T.PARSE("this_is_an_identifier: 'a string' 12344")
(['this_is_an_identifier', "'a string'", '12344'], 39)
>>>
Here id, str, and int are regular expression conveniences provided by
this module.
Directive markers may be mixed and matched, except that wildcards cannot precede
wildcards or single character markers.
Example:
>>> T = Template("ssnum: NNN-NN-NNNN, fn=X, ln=X, age=I, quote=Q", "X", "N", I=int, Q=str)
>>> T.PARSE("ssnum: 123-45-6789, fn=Aaron, ln=Watters, age=13, quote='do be do be do'")
(['123', '45', '6789', 'Aaron', 'Watters', '13', "'do be do be do'"], 72)
>>>
"""
import re, string
from types import StringType
from string import find
#
# template parsing
#
# EG: T = Template("(NNN)NNN-NNNN X X", "X", "N")
# ([area, exch, ext, fn, ln], index) = T.PARSE("(908)949-2726 Aaron Watters")
#
class Template:
def __init__(self,
template,
wild_card_marker=None,
single_char_marker=None,
**marker_to_regex_dict):
self.template = template
self.wild_card = wild_card_marker
self.char = single_char_marker
# determine the set of markers for this template
markers = marker_to_regex_dict.keys()
if wild_card_marker:
markers.append(wild_card_marker)
if single_char_marker:
for ch in single_char_marker: # allow multiple scm's
markers.append(ch)
self.char = single_char_primary = single_char_marker[0]
self.markers = markers
for mark in markers:
if len(mark)>1:
raise ValueError, "Marks must be single characters: "+`mark`
# compile the regular expressions if needed
self.marker_dict = marker_dict = {}
for (mark, rgex) in marker_to_regex_dict.items():
if type(rgex) == StringType:
rgex = re.compile(rgex)
marker_dict[mark] = rgex
# determine the parse sequence
parse_seq = []
# dummy last char
lastchar = None
index = 0
last = len(template)
# count the number of directives encountered
ndirectives = 0
while index<last:
start = index
thischar = template[index]
# is it a wildcard?
if thischar == wild_card_marker:
if lastchar == wild_card_marker:
raise ValueError, "two wild cards in sequence is not allowed"
parse_seq.append( (wild_card_marker, None) )
index = index+1
ndirectives = ndirectives+1
# is it a sequence of single character markers?
elif single_char_marker and thischar in single_char_marker:
if lastchar == wild_card_marker:
raise ValueError, "wild card cannot precede single char marker"
while index<last and template[index] == thischar:
index = index+1
parse_seq.append( (single_char_primary, index-start) )
ndirectives = ndirectives+1
# is it a literal sequence?
elif not thischar in markers:
while index<last and not template[index] in markers:
index = index+1
parse_seq.append( (None, template[start:index]) )
# otherwise it must be a re marker
else:
rgex = marker_dict[thischar]
parse_seq.append( (thischar, rgex) )
ndirectives = ndirectives+1
index = index+1
lastchar = template[index-1]
self.parse_seq = parse_seq
self.ndirectives = ndirectives
def PARSE(self, str, start=0):
ndirectives = self.ndirectives
wild_card = self.wild_card
single_char = self.char
parse_seq = self.parse_seq
lparse_seq = len(parse_seq) - 1
# make a list long enough for substitutions for directives
result = [None] * ndirectives
current_directive_index = 0
currentindex = start
# scan through the parse sequence, recognizing
for parse_index in xrange(lparse_seq + 1):
(indicator, data) = parse_seq[parse_index]
# is it a literal indicator?
if indicator is None:
if find(str, data, currentindex) != currentindex:
raise ValueError, "literal not found at "+`(currentindex,data)`
currentindex = currentindex + len(data)
else:
# anything else is a directive
# is it a wildcard?
if indicator == wild_card:
# if it is the last directive then it matches the rest of the string
if parse_index == lparse_seq:
last = len(str)
# otherwise must look at next directive to find end of wildcard
else:
# next directive must be re or literal
(nextindicator, nextdata) = parse_seq[parse_index+1]
if nextindicator is None:
# search for literal
last = find(str, nextdata, currentindex)
if last<currentindex:
raise ValueError, \
"couldn't terminate wild with lit "+`currentindex`
else:
# data is a re, search for it
last = nextdata.search(str, currentindex)
if last<currentindex:
raise ValueError, \
"couldn't terminate wild with re "+`currentindex`
elif indicator == single_char:
# data is length to eat
last = currentindex + data
else:
# other directives are always regular expressions
last = data.match(str, currentindex) + currentindex
if last<currentindex:
raise ValueError, "couldn't match re at "+`currentindex`
#print "accepting", str[currentindex:last]
result[current_directive_index] = str[currentindex:last]
current_directive_index = current_directive_index+1
currentindex = last
# sanity check
if current_directive_index != ndirectives:
raise SystemError, "not enough directives found?"
return (result, currentindex)
# some useful regular expressions
USERNAMEREGEX = \
"["+string.letters+"]["+string.letters+string.digits+"_]*"
STRINGLITREGEX = "'[^\n']*'"
SIMPLEINTREGEX = "["+string.digits+"]+"
id = re.compile(USERNAMEREGEX)
str = re.compile(STRINGLITREGEX)
int = re.compile(SIMPLEINTREGEX)
def test():
global T, T1, T2, T3
T = Template("(NNN)NNN-NNNN X X", "X", "N")
print T.PARSE("(908)949-2726 Aaron Watters")
T1 = Template("s --> s blah", s=str)
s = "' <-- a string --> ' --> 'blah blah another string blah' blah"
print T1.PARSE(s)
T2 = Template("s --> NNNiX", "X", "N", s=str, i=int)
print T2.PARSE("'A STRING' --> 15964653alpha beta gamma")
T3 = Template("XsXi", "X", "N", s=str, i=int)
print T3.PARSE("prefix'string'interior1234junk not parsed")
T4 = Template("MMDDYYX", "X", "MDY")
print T4.PARSE("122961 Somebody's birthday!")
if __name__=="__main__": test()

View File

@ -0,0 +1,201 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/docco/yaml.py
# parses "Yet Another Markup Language" into a list of tuples.
# Each tuple says what the data is e.g.
# ('Paragraph', 'Heading1', 'Why Reportlab Rules')
# and the pattern depends on type.
"""
Parser for "Aaron's Markup Language" - a markup language
which is easier to type in than XML, yet gives us a
reasonable selection of formats.
The general rule is that if a line begins with a '.',
it requires special processing. Otherwise lines
are concatenated to paragraphs, and blank lines
separate paragraphs.
If the line ".foo bar bletch" is encountered,
it immediately ends and writes out any current
paragraph.
It then looks for a parser method called 'foo';
if found, it is called with arguments (bar, bletch).
If this is not found, it assumes that 'foo' is a
paragraph style, and the text for the first line
of the paragraph is 'bar bletch'. It would be
up to the formatter to decide whether on not 'foo'
was a valid paragraph.
Special commands understood at present are:
.image filename
- adds the image to the document
.beginPre Code
- begins a Preformatted object in style 'Code'
.endPre
- ends a preformatted object.
"""
import sys
import string
import imp
import codegrab
#modes:
PLAIN = 1
PREFORMATTED = 2
BULLETCHAR = '\267' # assumes font Symbol, but works on all platforms
class Parser:
def __init__(self):
self.reset()
def reset(self):
self._lineNo = 0
self._style = 'Normal' # the default
self._results = []
self._buf = []
self._mode = PLAIN
def parseFile(self, filename):
#returns list of objects
data = open(filename, 'r').readlines()
for line in data:
#strip trailing newlines
self.readLine(line[:-1])
self.endPara()
return self._results
def readLine(self, line):
#this is the inner loop
self._lineNo = self._lineNo + 1
stripped = string.lstrip(line)
if len(stripped) == 0:
if self._mode == PLAIN:
self.endPara()
else: #preformatted, append it
self._buf.append(line)
elif line[0]=='.':
# we have a command of some kind
self.endPara()
words = string.split(stripped[1:])
cmd, args = words[0], words[1:]
#is it a parser method?
if hasattr(self.__class__, cmd):
method = eval('self.'+cmd)
#this was very bad; any type error in the method was hidden
#we have to hack the traceback
try:
apply(method, tuple(args))
except TypeError, err:
sys.stderr.write("Parser method: apply(%s,%s) %s at line %d\n" % (cmd, tuple(args), err, self._lineNo))
raise
else:
# assume it is a paragraph style -
# becomes the formatter's problem
self.endPara() #end the last one
words = string.split(stripped, ' ', 1)
assert len(words)==2, "Style %s but no data at line %d" % (words[0], self._lineNo)
(styletag, data) = words
self._style = styletag[1:]
self._buf.append(data)
else:
#we have data, add to para
self._buf.append(line)
def endPara(self):
#ends the current paragraph, or preformatted block
text = string.join(self._buf, ' ')
if text:
if self._mode == PREFORMATTED:
#item 3 is list of lines
self._results.append(('Preformatted', self._style,
string.join(self._buf,'\n')))
else:
self._results.append(('Paragraph', self._style, text))
self._buf = []
self._style = 'Normal'
def beginPre(self, stylename):
self._mode = PREFORMATTED
self._style = stylename
def endPre(self):
self.endPara()
self._mode = PLAIN
def image(self, filename):
self.endPara()
self._results.append(('Image', filename))
def vSpace(self, points):
"""Inserts a vertical spacer"""
self._results.append(('VSpace', points))
def pageBreak(self):
"""Inserts a frame break"""
self._results.append(('PageBreak','blah')) # must be a tuple
def custom(self, moduleName, funcName):
"""Goes and gets the Python object and adds it to the story"""
self.endPara()
self._results.append(('Custom',moduleName, funcName))
def getModuleDoc(self, modulename, pathname=None):
"""Documents the entire module at this point by making
paragraphs and preformatted objects"""
docco = codegrab.getObjectsDefinedIn(modulename, pathname)
if docco.doc <> None:
self._results.append(('Paragraph', 'DocString', docco.doc))
if len(docco.functions) > 0:
for fn in docco.functions:
if fn.status == 'official':
self._results.append(('Preformatted','FunctionHeader', fn.proto))
self._results.append(('Preformatted','DocString', fn.doc))
if len(docco.classes) > 0:
for cls in docco.classes:
if cls.status == 'official':
self._results.append(('Preformatted','FunctionHeader', 'Class %s:' % cls.name))
self._results.append(('Preformatted','DocString', cls.doc))
for mth in cls.methods:
if mth.status == 'official':
self._results.append(('Preformatted','FunctionHeader', mth.proto))
self._results.append(('Preformatted','DocStringIndent', mth.doc))
def getClassDoc(self, modulename, classname, pathname=None):
"""Documents the class and its public methods"""
docco = codegrab.getObjectsDefinedIn(modulename, pathname)
found = 0
for cls in docco.classes:
if cls.name == classname:
found = 1
self._results.append(('Preformatted','FunctionHeader', 'Class %s:' % cls.name))
self._results.append(('Preformatted','DocString', cls.doc))
for mth in cls.methods:
if mth.status == 'official':
self._results.append(('Preformatted','FunctionHeader', mth.proto))
self._results.append(('Preformatted','DocStringIndent', mth.doc))
break
assert found, 'No Classes Defined in ' + modulename
def nextPageTemplate(self, templateName):
self._results.append(('NextPageTemplate',templateName))
if __name__=='__main__': #NORUNTESTS
if len(sys.argv) <> 2:
print 'usage: yaml.py source.txt'
else:
p = Parser()
results = p.parseFile(sys.argv[1])
import pprint
pprint.pprint(results)

View File

@ -0,0 +1,104 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/docco/yaml2pdf.py
# yaml2pdf - turns stuff in Yet Another Markup Language
# into PDF documents. Very crude - it assumes a
# doc template and stylesheet (hard coded for now)
# and basically cranks out paragraphs in each style
"""yaml2pdf.py - converts Yet Another Markup Language
to reasonable PDF documents. This is ReportLab's
basic documentation tool.
Usage:
. "yaml2pdf.py filename.ext" will create "filename.pdf"
"""
import sys
import os
import imp
import yaml
from rltemplate import RLDocTemplate
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import *
from reportlab.lib.pagesizes import A4
from reportlab.platypus import *
from reportlab.lib import colors
from reportlab.lib.units import inch
from stylesheet import getStyleSheet
def run(infilename, outfilename):
p = yaml.Parser()
results = p.parseFile(infilename)
ss = getStyleSheet()
#now make flowables from the results
story = []
for thingy in results:
typ = thingy[0]
if typ == 'Paragraph':
(typ2, stylename, text) = thingy
if stylename == 'bu':
bulletText='\267'
else:
bulletText=None
try:
style = ss[stylename]
except KeyError:
print 'Paragraph style "%s" not found in stylesheet, using Normal instead' % stylename
style = ss['Normal']
story.append(Paragraph(text, style, bulletText=bulletText))
elif typ == 'Preformatted':
(typ2, stylename, text) = thingy
try:
style = ss[stylename]
except KeyError:
print 'Preformatted style "%s" not found in stylesheet, using Normal instead' % stylename
style = ss['Normal']
story.append(Preformatted(text, style, bulletText=bulletText))
elif typ == 'Image':
filename = thingy[1]
img = Image(filename)
story.append(img)
elif typ == 'PageBreak':
story.append(PageBreak())
elif typ == 'VSpace':
height = thingy[1]
story.append(Spacer(0, height))
elif typ == 'NextPageTemplate':
story.append(NextPageTemplate(thingy[1]))
elif typ == 'Custom':
# go find it
searchPath = [os.getcwd()+'\\']
(typ2, moduleName, funcName) = thingy
found = imp.find_module(moduleName, searchPath)
assert found, "Custom object module %s not found" % moduleName
(file, pathname, description) = found
mod = imp.load_module(moduleName, file, pathname, description)
#now get the function
func = getattr(mod, funcName)
story.append(func())
else:
print 'skipping',typ, 'for now'
#print it
doc = RLDocTemplate(outfilename, pagesize=A4)
doc.build(story)
if __name__ == '__main__': #NORUNTESTS
if len(sys.argv) == 2:
infilename = sys.argv[1]
outfilename = os.path.splitext(infilename)[0] + '.pdf'
if os.path.isfile(infilename):
run(infilename, outfilename)
else:
print 'File not found %s' % infilename
else:
print __doc__

View File

@ -0,0 +1,8 @@
py2pdf - converts Python source code to PDF
with a LOT of options.
See the header of py2pdf.py for full details.
execute demo.py to see some output.
Contributed by Dinu Gherman and copyrighted by him.
Uses Just van Rossum's PyFontify.

View File

@ -0,0 +1,3 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/py2pdf/__init__.py

View File

@ -0,0 +1,11 @@
--bgCol=(1,.9,.9)
--lineNum
#--fontSize=12
#--paperFormat=B5
#--fontName=Helvetica
#--landscape
#--restCol=(0,1,0)
#--mode=mono
--kwCol=(1,0,1)
#--kwCol=#dd00ff
#--kwCol=(.5,.5,.5)

View File

@ -0,0 +1,198 @@
#!/usr/bin/env python
"""demo.py - Demo script for py2pdf 0.5.
The main idea is: take one Python file and make a whole
bunch of PDFs out of it for test purposes.
Dinu Gherman
"""
import string, re, os, os.path, sys, shutil
from py2pdf import *
### Custom layouter class used with test3().
class ImgPDFLayouter (PythonPDFLayouter):
"A custom layouter displaying an image on each page."
def setMainFrame(self, frame=None):
"Make a frame in the right half of the page."
width, height = self.options.realPaperFormat.size
self.frame = height - 2*cm, 2*cm, 250, width-1*cm
self.makeForm()
def makeForm(self):
"Use the experimental ReportLab form support."
width, height = self.options.realPaperFormat.size
tm, bm, lm, rm = self.frame
c = self.canvas
# Define a PDF form containing an image frame
# that will be included on every page, but
# stored only once in the resulting file.
c.beginForm("imageFrame")
c.saveState()
x, y = 219.0, 655.0 # Known size of the picture.
c.scale((lm - 1*cm)/x, height/y)
path = 'vertpython.jpg'
c.drawImage(path, 0, 0)
c.restoreState()
c.endForm()
def putPageDecoration(self):
"Draw the left border image and page number."
width, height = self.options.realPaperFormat.size
tm, bm, lm, rm = self.frame
c = self.canvas
# Footer.
x, y = lm + 0.5 * (rm - lm), 0.5 * bm
c.setFillColor(Color(0, 0, 0))
c.setFont('Times-Italic', 12)
label = "Page %d" % self.pageNum
c.drawCentredString(x, y, label)
# Call the previously stored form.
c.doForm("imageFrame")
### Helpers.
def modifyPath(path, new, ext='.py'):
"Modifying the base name of a file."
rest, ext = os.path.splitext(path)
path, base = os.path.split(rest)
format = "%s-%s%s" % (base, new, ext)
return os.path.join(path, format)
def getAllTestFunctions():
"Return a list of all test functions available."
globs = globals().keys()
tests = filter(lambda g: re.match('test[\d]+', g), globs)
tests.sort()
return map(lambda t: globals()[t], tests)
### Test functions.
###
### In order to be automatically found and applied to
### a Python file all test functions must follow the
### following naming pattern: 'test[0-9]+' and contain
### a doc string.
def test0(path):
"Creating a PDF assuming an ASCII file."
p = PDFPrinter()
p.process(path)
def test1(path):
"Creating a PDF using only default options."
p = PythonPDFPrinter()
p.process(path)
def test2(path):
"Creating a PDF with some modified options."
p = PythonPDFPrinter()
p.options.updateOption('landscape', 1)
p.options.updateOption('fontName', 'Helvetica')
p.options.updateOption('fontSize', '14')
p.options.display()
p.process(path)
def test3(path):
"Creating several PDFs as 'magazine listings'."
p = PythonPDFPrinter()
p.Layouter = EmptyPythonPDFLayouter
p.options.updateOption('paperSize', '(250,400)')
p.options.updateOption('multiPage', 1)
p.options.updateOption('lineNum', 1)
p.process(path)
def test4(path):
"Creating a PDF in monochrome mode."
p = PythonPDFPrinter()
p.options.updateOption('mode', 'mono')
p.process(path)
def test5(path):
"Creating a PDF with options from a config file."
p = PythonPDFPrinter()
i = string.find(path, 'test5')
newPath = modifyPath(path[:i-1], 'config') + '.txt'
try:
p.options.updateWithContentsOfFile(newPath)
p.options.display()
p.process(path)
except IOError:
print "Skipping test5() due to IOError."
def test6(path):
"Creating a PDF with modified layout."
p = PythonPDFPrinter()
p.Layouter = ImgPDFLayouter
p.options.updateOption('fontName', 'Helvetica')
p.options.updateOption('fontSize', '12')
p.options.display()
p.process(path)
### Main.
def main(inPath, *tests):
"Apply various tests to one Python source file."
for t in tests:
newPath = modifyPath(inPath, t.__name__)
shutil.copyfile(inPath, newPath)
try:
print t.__doc__
t(newPath)
finally:
os.remove(newPath)
print
if __name__=='__main__':
# Usage: "python demo.py <file> <test1> [<test2> ...]"
try:
try:
tests = map(lambda a: globals()[a], sys.argv[2:])
except IndexError:
tests = getAllTestFunctions()
fileName = sys.argv[1]
apply(main, [fileName]+tests)
# Usage: "python demo.py" (implicitly does this:
# "python demo.py demo.py" <allTestsAvailable>)
except IndexError:
print "Performing self-test..."
fileName = sys.argv[0]
tests = getAllTestFunctions()
apply(main, [fileName]+tests)

View File

@ -0,0 +1,56 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/py2pdf/idle_print.py
# idle_print [py2pdf_options] filename
__version__=''' $Id: idle_print.py 2385 2004-06-17 15:26:05Z rgbecker $ '''
# you should adjust the globals below to configure for your system
import sys, os, py2pdf, string, time
#whether we remove input/output files; if you get trouble on windows try setting _out to 0
auto_rm_in = 1
auto_rm_out = 1
viewOnly = 0
#how to call up your acrobat reader
if sys.platform=='win32':
acrord = 'C:\\Program Files\\Adobe\\Acrobat 4.0\\Reader\\AcroRd32.exe'
def printpdf(pdfname):
args = [acrord, pdfname]
os.spawnv(os.P_WAIT, args[0], args)
else:
acrord = 'acroread'
def printpdf(pdfname):
if viewOnly:
cmd = "%s %s" % (acrord,pdfname)
else:
cmd = "%s -toPostScript < %s | lpr" % (acrord,pdfname)
os.system(cmd)
args = ['--input=python']
files = []
for f in sys.argv[1:]:
if f[:2]=='--':
opt = f[2:]
if opt =='no_auto_rm_in':
auto_rm_in = 0
elif opt =='auto_rm_in':
auto_rm_in = 1
elif opt =='no_auto_rm_out':
auto_rm_out = 0
elif opt =='auto_rm_out':
auto_rm_out = 1
elif opt =='viewonly':
viewOnly = 1
elif opt[:9] =='acroread=':
acrord = opt[9:]
else:
args.append(f)
else: files.append(f)
for f in files:
py2pdf.main(args+[f])
if auto_rm_in: os.remove(f)
pdfname = os.path.splitext(f)[0]+'.pdf'
printpdf(pdfname)
if auto_rm_out: os.remove(pdfname)

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1,29 @@
PythonPoint is a utility for generating PDF slides from
a simple XML format - "PythonPoint Markup Language".
This is early days. It lets you produce quite sophisticated
output, but the DTD will undoubtedly evolve and change.
However, I want people to be able to use it this summer so am
releasing now.
It is part of the ReportLab distribution; if you have managed
to run the ReportLab tests, and have installed the Python
Imaging Library, usage should be straightforward. PIL is not
required to make slides, but the demo will have a few blanks if
you omit it.
To use, cd to the pythonpoint directory and execute:
pythonpoint.py pythonpoint.xml
This will create pythonpoint.pdf, which is your manual.
You can also try 'monterey.xml', which is a talk I gave
at the O'Reilly Open Source conference in Monterey
in summer 1999.
We have issues to resolve over module load paths;
the easiest solution for now is to put the PythonPoint
directory on your path; work in a new directory;
and explicitly include the paths to any custom shapes,
and style sheets you use.
- Andy Robinson, 6 April 2000

View File

@ -0,0 +1,3 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/pythonpoint/__init__.py

View File

@ -0,0 +1,298 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/pythonpoint/customshapes.py
__version__=''' $Id: customshapes.py 2385 2004-06-17 15:26:05Z rgbecker $ '''
# xml parser stuff for PythonPoint
# PythonPoint Markup Language!
__doc__="""
This demonstrates a custom shape for use with the <customshape> tag.
The shape must fulfil a very simple interface, which may change in
future.
The XML tag currently has this form:
<customshape
module="customshapes.py"
class = "MyShape"
initargs="(100,200,3)"
/>
PythonPoint will look in the given module for the given class,
evaluate the arguments string and pass it to the constructor.
Then, it will call
object.drawOn(canvas)
Thus your object must be fully defined by the constructor.
For this one, we pass three argumenyts: x, y and scale.
This does a five-tile jigsaw over which words can be overlaid;
based on work done for a customer's presentation.
"""
import reportlab.pdfgen.canvas
from reportlab.lib import colors
from reportlab.lib.corp import RL_CorpLogo
from reportlab.graphics.shapes import Drawing
## custom shape for use with PythonPoint.
class Jigsaw:
"""This draws a jigsaw patterm. By default it is centred on 0,0
and has dimensions of 200 x 140; use the x/y/scale attributes
to move it around."""
#Using my usual bulldozer coding style - I am sure a mathematician could
#derive an elegant way to draw this, but I just took a ruler, guessed at
#the control points, and reflected a few lists at the interactive prompt.
def __init__(self, x, y, scale=1):
self.width = 200
self.height = 140
self.x = x
self.y = y
self.scale = scale
def drawOn(self, canvas):
canvas.saveState()
canvas.setFont('Helvetica-Bold',24)
canvas.drawString(600, 100, 'A Custom Shape')
canvas.translate(self.x, self.y)
canvas.scale(self.scale, self.scale)
self.drawBounds(canvas)
self.drawCentre(canvas)
self.drawTopLeft(canvas)
self.drawBottomLeft(canvas)
self.drawBottomRight(canvas)
self.drawTopRight(canvas)
canvas.restoreState()
def curveThrough(self, path, pointlist):
"""Helper to curve through set of control points."""
assert len(pointlist) % 3 == 1, "No. of points must be 3n+1 for integer n"
(x,y) = pointlist[0]
path.moveTo(x, y)
idx = 1
while idx < len(pointlist)-2:
p1, p2, p3 = pointlist[idx:idx+3]
path.curveTo(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1])
idx = idx + 3
def drawShape(self, canvas, controls, color):
"""Utlity to draw a closed shape through a list of control points;
extends the previous proc"""
canvas.setFillColor(color)
p = canvas.beginPath()
self.curveThrough(p, controls)
p.close()
canvas.drawPath(p, stroke=1, fill=1)
def drawBounds(self, canvas):
"""Guidelines to help me draw - not needed in production"""
canvas.setStrokeColor(colors.red)
canvas.rect(-100,-70,200,140)
canvas.line(-100,0,100,0)
canvas.line(0,70,0,-70)
canvas.setStrokeColor(colors.black)
def drawCentre(self, canvas):
controls = [ (0,50), #top
#top right edge - duplicated for that corner piece
(5,50),(10,45),(10,40),
(10,35),(15,30),(20,30),
(25,30),(30,25),(30,20),
(30,15),(35,10),(40,10),
(45,10),(50,5),(50,0),
#bottom right edge
(50, -5), (45,-10), (40,-10),
(35,-10), (30,-15), (30, -20),
(30,-25), (25,-30), (20,-30),
(15,-30), (10,-35), (10,-40),
(10,-45),(5,-50),(0,-50),
#bottom left
(-5,-50),(-10,-45),(-10,-40),
(-10,-35),(-15,-30),(-20,-30),
(-25,-30),(-30,-25),(-30,-20),
(-30,-15),(-35,-10),(-40,-10),
(-45,-10),(-50,-5),(-50,0),
#top left
(-50,5),(-45,10),(-40,10),
(-35,10),(-30,15),(-30,20),
(-30,25),(-25,30),(-20,30),
(-15,30),(-10,35),(-10,40),
(-10,45),(-5,50),(0,50)
]
self.drawShape(canvas, controls, colors.yellow)
def drawTopLeft(self, canvas):
controls = [(-100,70),
(-100,69),(-100,1),(-100,0),
(-99,0),(-91,0),(-90,0),
#jigsaw interlock - 4 sections
(-90,5),(-92,5),(-92,10),
(-92,15), (-85,15), (-80,15),
(-75,15),(-68,15),(-68,10),
(-68,5),(-70,5),(-70,0),
(-69,0),(-51,0),(-50,0),
#five distinct curves
(-50,5),(-45,10),(-40,10),
(-35,10),(-30,15),(-30,20),
(-30,25),(-25,30),(-20,30),
(-15,30),(-10,35),(-10,40),
(-10,45),(-5,50),(0,50),
(0,51),(0,69),(0,70),
(-1,70),(-99,70),(-100,70)
]
self.drawShape(canvas, controls, colors.teal)
def drawBottomLeft(self, canvas):
controls = [(-100,-70),
(-99,-70),(-1,-70),(0,-70),
(0,-69),(0,-51),(0,-50),
#wavyline
(-5,-50),(-10,-45),(-10,-40),
(-10,-35),(-15,-30),(-20,-30),
(-25,-30),(-30,-25),(-30,-20),
(-30,-15),(-35,-10),(-40,-10),
(-45,-10),(-50,-5),(-50,0),
#jigsaw interlock - 4 sections
(-51, 0), (-69, 0), (-70, 0),
(-70, 5), (-68, 5), (-68, 10),
(-68, 15), (-75, 15), (-80, 15),
(-85, 15), (-92, 15), (-92, 10),
(-92, 5), (-90, 5), (-90, 0),
(-91,0),(-99,0),(-100,0)
]
self.drawShape(canvas, controls, colors.green)
def drawBottomRight(self, canvas):
controls = [ (100,-70),
(100,-69),(100,-1),(100,0),
(99,0),(91,0),(90,0),
#jigsaw interlock - 4 sections
(90, -5), (92, -5), (92, -10),
(92, -15), (85, -15), (80, -15),
(75, -15), (68, -15), (68, -10),
(68, -5), (70, -5), (70, 0),
(69, 0), (51, 0), (50, 0),
#wavyline
(50, -5), (45,-10), (40,-10),
(35,-10), (30,-15), (30, -20),
(30,-25), (25,-30), (20,-30),
(15,-30), (10,-35), (10,-40),
(10,-45),(5,-50),(0,-50),
(0,-51), (0,-69), (0,-70),
(1,-70),(99,-70),(100,-70)
]
self.drawShape(canvas, controls, colors.navy)
def drawBottomLeft(self, canvas):
controls = [(-100,-70),
(-99,-70),(-1,-70),(0,-70),
(0,-69),(0,-51),(0,-50),
#wavyline
(-5,-50),(-10,-45),(-10,-40),
(-10,-35),(-15,-30),(-20,-30),
(-25,-30),(-30,-25),(-30,-20),
(-30,-15),(-35,-10),(-40,-10),
(-45,-10),(-50,-5),(-50,0),
#jigsaw interlock - 4 sections
(-51, 0), (-69, 0), (-70, 0),
(-70, 5), (-68, 5), (-68, 10),
(-68, 15), (-75, 15), (-80, 15),
(-85, 15), (-92, 15), (-92, 10),
(-92, 5), (-90, 5), (-90, 0),
(-91,0),(-99,0),(-100,0)
]
self.drawShape(canvas, controls, colors.green)
def drawTopRight(self, canvas):
controls = [(100, 70),
(99, 70), (1, 70), (0, 70),
(0, 69), (0, 51), (0, 50),
(5, 50), (10, 45), (10, 40),
(10, 35), (15, 30), (20, 30),
(25, 30), (30, 25), (30, 20),
(30, 15), (35, 10), (40, 10),
(45, 10), (50, 5), (50, 0),
(51, 0), (69, 0), (70, 0),
(70, -5), (68, -5), (68, -10),
(68, -15), (75, -15), (80, -15),
(85, -15), (92, -15), (92, -10),
(92, -5), (90, -5), (90, 0),
(91, 0), (99, 0), (100, 0)
]
self.drawShape(canvas, controls, colors.magenta)
class Logo:
"""This draws a ReportLab Logo."""
def __init__(self, x, y, width, height):
logo = RL_CorpLogo()
logo.x = x
logo.y = y
logo.width = width
logo.height = height
self.logo = logo
def drawOn(self, canvas):
logo = self.logo
x, y = logo.x, logo.y
w, h = logo.width, logo.height
D = Drawing(w, h)
D.add(logo)
D.drawOn(canvas, 0, 0)
def run():
c = reportlab.pdfgen.canvas.Canvas('customshape.pdf')
J = Jigsaw(300, 540, 2)
J.drawOn(c)
c.save()
if __name__ == '__main__':
run()

View File

@ -0,0 +1,93 @@
StartFontMetrics 2.0
Comment Generated by RoboFog 08-06-2001 4:26:40 PM
FontName LettErrorRobot-Chrome
FullName LettErrorRobot-Chrome
FamilyName LettErrorRobot
Weight Medium
Notice (C) 1998-2001 LettError, Just van Rossum, Erik van Blokland, http://www.letterror.com/
ItalicAngle 0
IsFixedPitch false
UnderlinePosition -133
UnderlineThickness 20
Version 001.000
EncodingScheme AdobeStandardEncoding
FontBBox -53 -252 1047 752
CapHeight 647
XHeight 548
Descender -252
Ascender 747
StartCharMetrics 68
C 32 ; WX 300 ; N space ; B 0 0 0 0 ;
C 33 ; WX 300 ; N exclam ; B 48 -52 253 652 ;
C 38 ; WX 700 ; N ampersand ; B 48 -47 653 647 ;
C 42 ; WX 700 ; N asterisk ; B 48 148 653 752 ;
C 48 ; WX 700 ; N zero ; B 53 -47 648 548 ;
C 49 ; WX 500 ; N one ; B 48 -47 453 553 ;
C 50 ; WX 600 ; N two ; B 48 -47 553 548 ;
C 51 ; WX 600 ; N three ; B 48 -147 553 548 ;
C 52 ; WX 700 ; N four ; B 48 -152 653 553 ;
C 53 ; WX 600 ; N five ; B 48 -147 553 548 ;
C 54 ; WX 600 ; N six ; B 53 -47 553 647 ;
C 55 ; WX 600 ; N seven ; B 48 -152 548 548 ;
C 56 ; WX 600 ; N eight ; B 48 -47 553 647 ;
C 57 ; WX 600 ; N nine ; B 48 -147 548 548 ;
C 63 ; WX 500 ; N question ; B 48 -52 448 647 ;
C 64 ; WX 800 ; N at ; B 53 -47 748 647 ;
C 65 ; WX 700 ; N A ; B 53 -52 648 652 ;
C 66 ; WX 600 ; N B ; B 53 -47 553 647 ;
C 67 ; WX 600 ; N C ; B 53 -47 553 647 ;
C 68 ; WX 700 ; N D ; B 53 -47 648 647 ;
C 69 ; WX 600 ; N E ; B 53 -47 553 647 ;
C 70 ; WX 600 ; N F ; B 53 -52 553 647 ;
C 71 ; WX 700 ; N G ; B 53 -47 653 647 ;
C 72 ; WX 700 ; N H ; B 53 -52 648 652 ;
C 73 ; WX 300 ; N I ; B 53 -52 248 652 ;
C 74 ; WX 300 ; N J ; B -53 -252 248 652 ;
C 75 ; WX 700 ; N K ; B 53 -52 653 652 ;
C 76 ; WX 600 ; N L ; B 53 -47 553 652 ;
C 77 ; WX 900 ; N M ; B 53 -52 848 652 ;
C 78 ; WX 700 ; N N ; B 53 -52 648 652 ;
C 79 ; WX 700 ; N O ; B 53 -47 648 647 ;
C 80 ; WX 600 ; N P ; B 53 -52 548 647 ;
C 81 ; WX 700 ; N Q ; B 53 -252 653 647 ;
C 82 ; WX 600 ; N R ; B 53 -52 653 647 ;
C 83 ; WX 600 ; N S ; B 48 -47 553 647 ;
C 84 ; WX 700 ; N T ; B 48 -52 653 647 ;
C 85 ; WX 700 ; N U ; B 53 -47 648 652 ;
C 86 ; WX 700 ; N V ; B 53 -52 648 652 ;
C 87 ; WX 1100 ; N W ; B 53 -52 1047 652 ;
C 88 ; WX 700 ; N X ; B 48 -52 653 652 ;
C 89 ; WX 700 ; N Y ; B 53 -52 648 652 ;
C 90 ; WX 700 ; N Z ; B 48 -47 653 647 ;
C 97 ; WX 600 ; N a ; B 48 -47 548 548 ;
C 98 ; WX 600 ; N b ; B 53 -47 548 752 ;
C 99 ; WX 600 ; N c ; B 53 -47 553 548 ;
C 100 ; WX 600 ; N d ; B 53 -47 548 752 ;
C 101 ; WX 600 ; N e ; B 53 -47 553 548 ;
C 102 ; WX 400 ; N f ; B -53 -52 453 747 ;
C 103 ; WX 600 ; N g ; B 48 -247 548 548 ;
C 104 ; WX 600 ; N h ; B 53 -52 548 752 ;
C 105 ; WX 300 ; N i ; B 48 -52 253 752 ;
C 106 ; WX 300 ; N j ; B -53 -252 253 752 ;
C 107 ; WX 600 ; N k ; B 53 -52 553 752 ;
C 108 ; WX 300 ; N l ; B 53 -52 248 752 ;
C 109 ; WX 900 ; N m ; B 53 -52 848 548 ;
C 110 ; WX 600 ; N n ; B 53 -52 548 548 ;
C 111 ; WX 600 ; N o ; B 53 -47 548 548 ;
C 112 ; WX 600 ; N p ; B 53 -252 548 548 ;
C 113 ; WX 600 ; N q ; B 53 -252 548 548 ;
C 114 ; WX 400 ; N r ; B 53 -52 453 553 ;
C 115 ; WX 600 ; N s ; B 48 -47 553 548 ;
C 116 ; WX 400 ; N t ; B -53 -47 453 652 ;
C 117 ; WX 600 ; N u ; B 53 -47 548 553 ;
C 118 ; WX 600 ; N v ; B 53 -52 548 553 ;
C 119 ; WX 900 ; N w ; B 53 -52 848 553 ;
C 120 ; WX 700 ; N x ; B 48 -52 653 553 ;
C 121 ; WX 600 ; N y ; B 48 -252 548 553 ;
C 122 ; WX 500 ; N z ; B -53 -47 553 548 ;
EndCharMetrics
StartKernData
StartKernPairs 0
EndKernPairs
EndKernData
EndFontMetrics

Binary file not shown.

View File

@ -0,0 +1,841 @@
import string
testannotations="""
def annotations(canvas):
from reportlab.lib.units import inch
canvas.drawString(inch, 2.5*inch,
"setAuthor, setTitle, setSubject have no visible effect")
canvas.drawString(inch, inch, "But if you are viewing this document dynamically")
canvas.drawString(inch, 0.5*inch, "please look at File/Document Info")
canvas.setAuthor("the ReportLab Team")
canvas.setTitle("ReportLab PDF Generation User Guide")
canvas.setSubject("How to Generate PDF files using the ReportLab modules")
"""
# magic function making module
test1 = """
def f(a,b):
print "it worked", a, b
return a+b
"""
test2 = """
def g(n):
if n==0: return 1
else: return n*g(n-1)
"""
testhello = """
def hello(c):
from reportlab.lib.units import inch
# move the origin up and to the left
c.translate(inch,inch)
# define a large font
c.setFont("Helvetica", 14)
# choose some colors
c.setStrokeColorRGB(0.2,0.5,0.3)
c.setFillColorRGB(1,0,1)
# draw some lines
c.line(0,0,0,1.7*inch)
c.line(0,0,1*inch,0)
# draw a rectangle
c.rect(0.2*inch,0.2*inch,1*inch,1.5*inch, fill=1)
# make text go straight up
c.rotate(90)
# change color
c.setFillColorRGB(0,0,0.77)
# say hello (note after rotate the y coord needs to be negative!)
c.drawString(0.3*inch, -inch, "Hello World")
"""
testcoords = """
def coords(canvas):
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, black, red, blue, green
c = canvas
c.setStrokeColor(pink)
c.grid([inch, 2*inch, 3*inch, 4*inch], [0.5*inch, inch, 1.5*inch, 2*inch, 2.5*inch])
c.setStrokeColor(black)
c.setFont("Times-Roman", 20)
c.drawString(0,0, "(0,0) the Origin")
c.drawString(2.5*inch, inch, "(2.5,1) in inches")
c.drawString(4*inch, 2.5*inch, "(4, 2.5)")
c.setFillColor(red)
c.rect(0,2*inch,0.2*inch,0.3*inch, fill=1)
c.setFillColor(green)
c.circle(4.5*inch, 0.4*inch, 0.2*inch, fill=1)
"""
testtranslate = """
def translate(canvas):
from reportlab.lib.units import cm
canvas.translate(2.3*cm, 0.3*cm)
coords(canvas)
"""
testscale = """
def scale(canvas):
canvas.scale(0.75, 0.5)
coords(canvas)
"""
testscaletranslate = """
def scaletranslate(canvas):
from reportlab.lib.units import inch
canvas.setFont("Courier-BoldOblique", 12)
# save the state
canvas.saveState()
# scale then translate
canvas.scale(0.3, 0.5)
canvas.translate(2.4*inch, 1.5*inch)
canvas.drawString(0, 2.7*inch, "Scale then translate")
coords(canvas)
# forget the scale and translate...
canvas.restoreState()
# translate then scale
canvas.translate(2.4*inch, 1.5*inch)
canvas.scale(0.3, 0.5)
canvas.drawString(0, 2.7*inch, "Translate then scale")
coords(canvas)
"""
testmirror = """
def mirror(canvas):
from reportlab.lib.units import inch
canvas.translate(5.5*inch, 0)
canvas.scale(-1.0, 1.0)
coords(canvas)
"""
testcolors = """
def colors(canvas):
from reportlab.lib import colors
from reportlab.lib.units import inch
black = colors.black
y = x = 0; dy=inch*3/4.0; dx=inch*5.5/5; w=h=dy/2; rdx=(dx-w)/2
rdy=h/5.0; texty=h+2*rdy
canvas.setFont("Helvetica",10)
for [namedcolor, name] in (
[colors.lavenderblush, "lavenderblush"],
[colors.lawngreen, "lawngreen"],
[colors.lemonchiffon, "lemonchiffon"],
[colors.lightblue, "lightblue"],
[colors.lightcoral, "lightcoral"]):
canvas.setFillColor(namedcolor)
canvas.rect(x+rdx, y+rdy, w, h, fill=1)
canvas.setFillColor(black)
canvas.drawCentredString(x+dx/2, y+texty, name)
x = x+dx
y = y + dy; x = 0
for rgb in [(1,0,0), (0,1,0), (0,0,1), (0.5,0.3,0.1), (0.4,0.5,0.3)]:
r,g,b = rgb
canvas.setFillColorRGB(r,g,b)
canvas.rect(x+rdx, y+rdy, w, h, fill=1)
canvas.setFillColor(black)
canvas.drawCentredString(x+dx/2, y+texty, "r%s g%s b%s"%rgb)
x = x+dx
y = y + dy; x = 0
for cmyk in [(1,0,0,0), (0,1,0,0), (0,0,1,0), (0,0,0,1), (0,0,0,0)]:
c,m,y1,k = cmyk
canvas.setFillColorCMYK(c,m,y1,k)
canvas.rect(x+rdx, y+rdy, w, h, fill=1)
canvas.setFillColor(black)
canvas.drawCentredString(x+dx/2, y+texty, "c%s m%s y%s k%s"%cmyk)
x = x+dx
y = y + dy; x = 0
for gray in (0.0, 0.25, 0.50, 0.75, 1.0):
canvas.setFillGray(gray)
canvas.rect(x+rdx, y+rdy, w, h, fill=1)
canvas.setFillColor(black)
canvas.drawCentredString(x+dx/2, y+texty, "gray: %s"%gray)
x = x+dx
"""
testspumoni = """
def spumoni(canvas):
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, green, brown, white
x = 0; dx = 0.4*inch
for i in range(4):
for color in (pink, green, brown):
canvas.setFillColor(color)
canvas.rect(x,0,dx,3*inch,stroke=0,fill=1)
x = x+dx
canvas.setFillColor(white)
canvas.setStrokeColor(white)
canvas.setFont("Helvetica-Bold", 85)
canvas.drawCentredString(2.75*inch, 1.3*inch, "SPUMONI")
"""
testspumoni2 = """
def spumoni2(canvas):
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, green, brown, white, black
# draw the previous drawing
spumoni(canvas)
# now put an ice cream cone on top of it:
# first draw a triangle (ice cream cone)
p = canvas.beginPath()
xcenter = 2.75*inch
radius = 0.45*inch
p.moveTo(xcenter-radius, 1.5*inch)
p.lineTo(xcenter+radius, 1.5*inch)
p.lineTo(xcenter, 0)
canvas.setFillColor(brown)
canvas.setStrokeColor(black)
canvas.drawPath(p, fill=1)
# draw some circles (scoops)
y = 1.5*inch
for color in (pink, green, brown):
canvas.setFillColor(color)
canvas.circle(xcenter, y, radius, fill=1)
y = y+radius
"""
testbezier = """
def bezier(canvas):
from reportlab.lib.colors import yellow, green, red, black
from reportlab.lib.units import inch
i = inch
d = i/4
# define the bezier curve control points
x1,y1, x2,y2, x3,y3, x4,y4 = d,1.5*i, 1.5*i,d, 3*i,d, 5.5*i-d,3*i-d
# draw a figure enclosing the control points
canvas.setFillColor(yellow)
p = canvas.beginPath()
p.moveTo(x1,y1)
for (x,y) in [(x2,y2), (x3,y3), (x4,y4)]:
p.lineTo(x,y)
canvas.drawPath(p, fill=1, stroke=0)
# draw the tangent lines
canvas.setLineWidth(inch*0.1)
canvas.setStrokeColor(green)
canvas.line(x1,y1,x2,y2)
canvas.setStrokeColor(red)
canvas.line(x3,y3,x4,y4)
# finally draw the curve
canvas.setStrokeColor(black)
canvas.bezier(x1,y1, x2,y2, x3,y3, x4,y4)
"""
testbezier2 = """
def bezier2(canvas):
from reportlab.lib.colors import yellow, green, red, black
from reportlab.lib.units import inch
# make a sequence of control points
xd,yd = 5.5*inch/2, 3*inch/2
xc,yc = xd,yd
dxdy = [(0,0.33), (0.33,0.33), (0.75,1), (0.875,0.875),
(0.875,0.875), (1,0.75), (0.33,0.33), (0.33,0)]
pointlist = []
for xoffset in (1,-1):
yoffset = xoffset
for (dx,dy) in dxdy:
px = xc + xd*xoffset*dx
py = yc + yd*yoffset*dy
pointlist.append((px,py))
yoffset = -xoffset
for (dy,dx) in dxdy:
px = xc + xd*xoffset*dx
py = yc + yd*yoffset*dy
pointlist.append((px,py))
# draw tangent lines and curves
canvas.setLineWidth(inch*0.1)
while pointlist:
[(x1,y1),(x2,y2),(x3,y3),(x4,y4)] = pointlist[:4]
del pointlist[:4]
canvas.setLineWidth(inch*0.1)
canvas.setStrokeColor(green)
canvas.line(x1,y1,x2,y2)
canvas.setStrokeColor(red)
canvas.line(x3,y3,x4,y4)
# finally draw the curve
canvas.setStrokeColor(black)
canvas.bezier(x1,y1, x2,y2, x3,y3, x4,y4)
"""
testpencil = """
def pencil(canvas, text="No.2"):
from reportlab.lib.colors import yellow, red, black,white
from reportlab.lib.units import inch
u = inch/10.0
canvas.setStrokeColor(black)
canvas.setLineWidth(4)
# draw erasor
canvas.setFillColor(red)
canvas.circle(30*u, 5*u, 5*u, stroke=1, fill=1)
# draw all else but the tip (mainly rectangles with different fills)
canvas.setFillColor(yellow)
canvas.rect(10*u,0,20*u,10*u, stroke=1, fill=1)
canvas.setFillColor(black)
canvas.rect(23*u,0,8*u,10*u,fill=1)
canvas.roundRect(14*u, 3.5*u, 8*u, 3*u, 1.5*u, stroke=1, fill=1)
canvas.setFillColor(white)
canvas.rect(25*u,u,1.2*u,8*u, fill=1,stroke=0)
canvas.rect(27.5*u,u,1.2*u,8*u, fill=1, stroke=0)
canvas.setFont("Times-Roman", 3*u)
canvas.drawCentredString(18*u, 4*u, text)
# now draw the tip
penciltip(canvas,debug=0)
# draw broken lines across the body.
canvas.setDash([10,5,16,10],0)
canvas.line(11*u,2.5*u,22*u,2.5*u)
canvas.line(22*u,7.5*u,12*u,7.5*u)
"""
testpenciltip = """
def penciltip(canvas, debug=1):
from reportlab.lib.colors import tan, black, green
from reportlab.lib.units import inch
u = inch/10.0
canvas.setLineWidth(4)
if debug:
canvas.scale(2.8,2.8) # make it big
canvas.setLineWidth(1) # small lines
canvas.setStrokeColor(black)
canvas.setFillColor(tan)
p = canvas.beginPath()
p.moveTo(10*u,0)
p.lineTo(0,5*u)
p.lineTo(10*u,10*u)
p.curveTo(11.5*u,10*u, 11.5*u,7.5*u, 10*u,7.5*u)
p.curveTo(12*u,7.5*u, 11*u,2.5*u, 9.7*u,2.5*u)
p.curveTo(10.5*u,2.5*u, 11*u,0, 10*u,0)
canvas.drawPath(p, stroke=1, fill=1)
canvas.setFillColor(black)
p = canvas.beginPath()
p.moveTo(0,5*u)
p.lineTo(4*u,3*u)
p.lineTo(5*u,4.5*u)
p.lineTo(3*u,6.5*u)
canvas.drawPath(p, stroke=1, fill=1)
if debug:
canvas.setStrokeColor(green) # put in a frame of reference
canvas.grid([0,5*u,10*u,15*u], [0,5*u,10*u])
"""
testnoteannotation = """
from reportlab.platypus.flowables import Flowable
class NoteAnnotation(Flowable):
'''put a pencil in the margin.'''
def wrap(self, *args):
return (1,10) # I take up very little space! (?)
def draw(self):
canvas = self.canv
canvas.translate(-10,-10)
canvas.rotate(180)
canvas.scale(0.2,0.2)
pencil(canvas, text="NOTE")
"""
testhandannotation = """
from reportlab.platypus.flowables import Flowable
from reportlab.lib.colors import tan, green
class HandAnnotation(Flowable):
'''A hand flowable.'''
def __init__(self, xoffset=0, size=None, fillcolor=tan, strokecolor=green):
from reportlab.lib.units import inch
if size is None: size=4*inch
self.fillcolor, self.strokecolor = fillcolor, strokecolor
self.xoffset = xoffset
self.size = size
# normal size is 4 inches
self.scale = size/(4.0*inch)
def wrap(self, *args):
return (self.xoffset, self.size)
def draw(self):
canvas = self.canv
canvas.setLineWidth(6)
canvas.setFillColor(self.fillcolor)
canvas.setStrokeColor(self.strokecolor)
canvas.translate(self.xoffset+self.size,0)
canvas.rotate(90)
canvas.scale(self.scale, self.scale)
hand(canvas, debug=0, fill=1)
"""
lyrics = '''\
well she hit Net Solutions
and she registered her own .com site now
and filled it up with yahoo profile pics
she snarfed in one night now
and she made 50 million when Hugh Hefner
bought up the rights now
and she'll have fun fun fun
til her Daddy takes the keyboard away'''
lyrics = string.split(lyrics, "\n")
testtextsize = """
def textsize(canvas):
from reportlab.lib.units import inch
from reportlab.lib.colors import magenta, red
canvas.setFont("Times-Roman", 20)
canvas.setFillColor(red)
canvas.drawCentredString(2.75*inch, 2.5*inch, "Font size examples")
canvas.setFillColor(magenta)
size = 7
y = 2.3*inch
x = 1.3*inch
for line in lyrics:
canvas.setFont("Helvetica", size)
canvas.drawRightString(x,y,"%s points: " % size)
canvas.drawString(x,y, line)
y = y-size*1.2
size = size+1.5
"""
teststar = """
def star(canvas, title="Title Here", aka="Comment here.",
xcenter=None, ycenter=None, nvertices=5):
from math import pi
from reportlab.lib.units import inch
radius=inch/3.0
if xcenter is None: xcenter=2.75*inch
if ycenter is None: ycenter=1.5*inch
canvas.drawCentredString(xcenter, ycenter+1.3*radius, title)
canvas.drawCentredString(xcenter, ycenter-1.4*radius, aka)
p = canvas.beginPath()
p.moveTo(xcenter,ycenter+radius)
from math import pi, cos, sin
angle = (2*pi)*2/5.0
startangle = pi/2.0
for vertex in range(nvertices-1):
nextangle = angle*(vertex+1)+startangle
x = xcenter + radius*cos(nextangle)
y = ycenter + radius*sin(nextangle)
p.lineTo(x,y)
if nvertices==5:
p.close()
canvas.drawPath(p)
"""
testjoins = """
def joins(canvas):
from reportlab.lib.units import inch
# make lines big
canvas.setLineWidth(5)
star(canvas, "Default: mitered join", "0: pointed", xcenter = 1*inch)
canvas.setLineJoin(1)
star(canvas, "Round join", "1: rounded")
canvas.setLineJoin(2)
star(canvas, "Bevelled join", "2: square", xcenter=4.5*inch)
"""
testcaps = """
def caps(canvas):
from reportlab.lib.units import inch
# make lines big
canvas.setLineWidth(5)
star(canvas, "Default", "no projection",xcenter = 1*inch,
nvertices=4)
canvas.setLineCap(1)
star(canvas, "Round cap", "1: ends in half circle", nvertices=4)
canvas.setLineCap(2)
star(canvas, "Square cap", "2: projects out half a width", xcenter=4.5*inch,
nvertices=4)
"""
testdashes = """
def dashes(canvas):
from reportlab.lib.units import inch
# make lines big
canvas.setDash(6,3)
star(canvas, "Simple dashes", "6 points on, 3 off", xcenter = 1*inch)
canvas.setDash(1,2)
star(canvas, "Dots", "One on, two off")
canvas.setDash([1,1,3,3,1,4,4,1], 0)
star(canvas, "Complex Pattern", "[1,1,3,3,1,4,4,1]", xcenter=4.5*inch)
"""
testcursormoves1 = """
def cursormoves1(canvas):
from reportlab.lib.units import inch
textobject = canvas.beginText()
textobject.setTextOrigin(inch, 2.5*inch)
textobject.setFont("Helvetica-Oblique", 14)
for line in lyrics:
textobject.textLine(line)
textobject.setFillGray(0.4)
textobject.textLines('''
With many apologies to the Beach Boys
and anyone else who finds this objectionable
''')
canvas.drawText(textobject)
"""
testcursormoves2 = """
def cursormoves2(canvas):
from reportlab.lib.units import inch
textobject = canvas.beginText()
textobject.setTextOrigin(2, 2.5*inch)
textobject.setFont("Helvetica-Oblique", 14)
for line in lyrics:
textobject.textOut(line)
textobject.moveCursor(14,14) # POSITIVE Y moves down!!!
textobject.setFillColorRGB(0.4,0,1)
textobject.textLines('''
With many apologies to the Beach Boys
and anyone else who finds this objectionable
''')
canvas.drawText(textobject)
"""
testcharspace = """
def charspace(canvas):
from reportlab.lib.units import inch
textobject = canvas.beginText()
textobject.setTextOrigin(3, 2.5*inch)
textobject.setFont("Helvetica-Oblique", 10)
charspace = 0
for line in lyrics:
textobject.setCharSpace(charspace)
textobject.textLine("%s: %s" %(charspace,line))
charspace = charspace+0.5
textobject.setFillGray(0.4)
textobject.textLines('''
With many apologies to the Beach Boys
and anyone else who finds this objectionable
''')
canvas.drawText(textobject)
"""
testwordspace = """
def wordspace(canvas):
from reportlab.lib.units import inch
textobject = canvas.beginText()
textobject.setTextOrigin(3, 2.5*inch)
textobject.setFont("Helvetica-Oblique", 12)
wordspace = 0
for line in lyrics:
textobject.setWordSpace(wordspace)
textobject.textLine("%s: %s" %(wordspace,line))
wordspace = wordspace+2.5
textobject.setFillColorCMYK(0.4,0,0.4,0.2)
textobject.textLines('''
With many apologies to the Beach Boys
and anyone else who finds this objectionable
''')
canvas.drawText(textobject)
"""
testhorizontalscale = """
def horizontalscale(canvas):
from reportlab.lib.units import inch
textobject = canvas.beginText()
textobject.setTextOrigin(3, 2.5*inch)
textobject.setFont("Helvetica-Oblique", 12)
horizontalscale = 80 # 100 is default
for line in lyrics:
textobject.setHorizScale(horizontalscale)
textobject.textLine("%s: %s" %(horizontalscale,line))
horizontalscale = horizontalscale+10
textobject.setFillColorCMYK(0.0,0.4,0.4,0.2)
textobject.textLines('''
With many apologies to the Beach Boys
and anyone else who finds this objectionable
''')
canvas.drawText(textobject)
"""
testleading = """
def leading(canvas):
from reportlab.lib.units import inch
textobject = canvas.beginText()
textobject.setTextOrigin(3, 2.5*inch)
textobject.setFont("Helvetica-Oblique", 14)
leading = 8
for line in lyrics:
textobject.setLeading(leading)
textobject.textLine("%s: %s" %(leading,line))
leading = leading+2.5
textobject.setFillColorCMYK(0.8,0,0,0.3)
textobject.textLines('''
With many apologies to the Beach Boys
and anyone else who finds this objectionable
''')
canvas.drawText(textobject)
"""
testhand = """
def hand(canvas, debug=1, fill=0):
(startx, starty) = (0,0)
curves = [
( 0, 2), ( 0, 4), ( 0, 8), # back of hand
( 5, 8), ( 7,10), ( 7,14),
(10,14), (10,13), ( 7.5, 8), # thumb
(13, 8), (14, 8), (17, 8),
(19, 8), (19, 6), (17, 6),
(15, 6), (13, 6), (11, 6), # index, pointing
(12, 6), (13, 6), (14, 6),
(16, 6), (16, 4), (14, 4),
(13, 4), (12, 4), (11, 4), # middle
(11.5, 4), (12, 4), (13, 4),
(15, 4), (15, 2), (13, 2),
(12.5, 2), (11.5, 2), (11, 2), # ring
(11.5, 2), (12, 2), (12.5, 2),
(14, 2), (14, 0), (12.5, 0),
(10, 0), (8, 0), (6, 0), # pinky, then close
]
from reportlab.lib.units import inch
if debug: canvas.setLineWidth(6)
u = inch*0.2
p = canvas.beginPath()
p.moveTo(startx, starty)
ccopy = list(curves)
while ccopy:
[(x1,y1), (x2,y2), (x3,y3)] = ccopy[:3]
del ccopy[:3]
p.curveTo(x1*u,y1*u,x2*u,y2*u,x3*u,y3*u)
p.close()
canvas.drawPath(p, fill=fill)
if debug:
from reportlab.lib.colors import red, green
(lastx, lasty) = (startx, starty)
ccopy = list(curves)
while ccopy:
[(x1,y1), (x2,y2), (x3,y3)] = ccopy[:3]
del ccopy[:3]
canvas.setStrokeColor(red)
canvas.line(lastx*u,lasty*u, x1*u,y1*u)
canvas.setStrokeColor(green)
canvas.line(x2*u,y2*u, x3*u,y3*u)
(lastx,lasty) = (x3,y3)
"""
testhand2 = """
def hand2(canvas):
canvas.translate(20,10)
canvas.setLineWidth(3)
canvas.setFillColorRGB(0.1, 0.3, 0.9)
canvas.setStrokeGray(0.5)
hand(canvas, debug=0, fill=1)
"""
testfonts = """
def fonts(canvas):
from reportlab.lib.units import inch
text = "Now is the time for all good men to..."
x = 1.8*inch
y = 2.7*inch
for font in canvas.getAvailableFonts():
canvas.setFont(font, 10)
canvas.drawString(x,y,text)
canvas.setFont("Helvetica", 10)
canvas.drawRightString(x-10,y, font+":")
y = y-13
"""
testarcs = """
def arcs(canvas):
from reportlab.lib.units import inch
canvas.setLineWidth(4)
canvas.setStrokeColorRGB(0.8, 1, 0.6)
# draw rectangles enclosing the arcs
canvas.rect(inch, inch, 1.5*inch, inch)
canvas.rect(3*inch, inch, inch, 1.5*inch)
canvas.setStrokeColorRGB(0, 0.2, 0.4)
canvas.setFillColorRGB(1, 0.6, 0.8)
p = canvas.beginPath()
p.moveTo(0.2*inch, 0.2*inch)
p.arcTo(inch, inch, 2.5*inch,2*inch, startAng=-30, extent=135)
p.arc(3*inch, inch, 4*inch, 2.5*inch, startAng=-45, extent=270)
canvas.drawPath(p, fill=1, stroke=1)
"""
testvariousshapes = """
def variousshapes(canvas):
from reportlab.lib.units import inch
inch = int(inch)
canvas.setStrokeGray(0.5)
canvas.grid(range(0,11*inch/2,inch/2), range(0,7*inch/2,inch/2))
canvas.setLineWidth(4)
canvas.setStrokeColorRGB(0, 0.2, 0.7)
canvas.setFillColorRGB(1, 0.6, 0.8)
p = canvas.beginPath()
p.rect(0.5*inch, 0.5*inch, 0.5*inch, 2*inch)
p.circle(2.75*inch, 1.5*inch, 0.3*inch)
p.ellipse(3.5*inch, 0.5*inch, 1.2*inch, 2*inch)
canvas.drawPath(p, fill=1, stroke=1)
"""
testclosingfigures = """
def closingfigures(canvas):
from reportlab.lib.units import inch
h = inch/3.0; k = inch/2.0
canvas.setStrokeColorRGB(0.2,0.3,0.5)
canvas.setFillColorRGB(0.8,0.6,0.2)
canvas.setLineWidth(4)
p = canvas.beginPath()
for i in (1,2,3,4):
for j in (1,2):
xc,yc = inch*i, inch*j
p.moveTo(xc,yc)
p.arcTo(xc-h, yc-k, xc+h, yc+k, startAng=0, extent=60*i)
# close only the first one, not the second one
if j==1:
p.close()
canvas.drawPath(p, fill=1, stroke=1)
"""
testforms = """
def forms(canvas):
#first create a form...
canvas.beginForm("SpumoniForm")
#re-use some drawing functions from earlier
spumoni(canvas)
canvas.endForm()
#then draw it
canvas.doForm("SpumoniForm")
"""
def doctemplateillustration(canvas):
from reportlab.lib.units import inch
canvas.setFont("Helvetica", 10)
canvas.drawString(inch/4.0, 2.75*inch, "DocTemplate")
W = 4/3.0*inch
H = 2*inch
Wd = x = inch/4.0
Hd =y = inch/2.0
for name in ("two column", "chapter page", "title page"):
canvas.setFillColorRGB(0.5,1.0,1.0)
canvas.rect(x,y,W,H, fill=1)
canvas.setFillColorRGB(0,0,0)
canvas.drawString(x+inch/8, y+H-Wd, "PageTemplate")
canvas.drawCentredString(x+W/2.0, y-Wd, name)
x = x+W+Wd
canvas.saveState()
d = inch/16
dW = (W-3*d)/2.0
hD = H -2*d-Wd
canvas.translate(Wd+d, Hd+d)
for name in ("left Frame", "right Frame"):
canvas.setFillColorRGB(1.0,0.5,1.0)
canvas.rect(0,0, dW,hD, fill=1)
canvas.setFillGray(0.7)
dd= d/2.0
ddH = (hD-6*dd)/5.0
ddW = dW-2*dd
yy = dd
xx = dd
for i in range(5):
canvas.rect(xx,yy,ddW,ddH, fill=1, stroke=0)
yy = yy+ddH+dd
canvas.setFillColorRGB(0,0,0)
canvas.saveState()
canvas.rotate(90)
canvas.drawString(d,-dW/2, name)
canvas.restoreState()
canvas.translate(dW+d,0)
canvas.restoreState()
canvas.setFillColorRGB(1.0, 0.5, 1.0)
mx = Wd+W+Wd+d
my = Hd+d
mW = W-2*d
mH = H-d-Hd
canvas.rect(mx, my, mW, mH, fill=1)
canvas.rect(Wd+2*(W+Wd)+d, Hd+3*d, W-2*d, H/2.0, fill=1)
canvas.setFillGray(0.7)
canvas.rect(Wd+2*(W+Wd)+d+dd, Hd+5*d, W-2*d-2*dd, H/2.0-2*d-dd, fill=1)
xx = mx+dd
yy = my+mH/5.0
ddH = (mH-6*dd-mH/5.0)/3.0
ddW = mW - 2*dd
for i in range(3):
canvas.setFillGray(0.7)
canvas.rect(xx,yy,ddW,ddH, fill=1, stroke=1)
canvas.setFillGray(0)
canvas.drawString(xx+dd/2.0,yy+dd/2.0, "flowable %s" %(157-i))
yy = yy+ddH+dd
canvas.drawCentredString(3*Wd+2*W+W/2, Hd+H/2.0, "First Flowable")
canvas.setFont("Times-BoldItalic", 8)
canvas.setFillGray(0)
canvas.drawCentredString(mx+mW/2.0, my+mH+3*dd, "Chapter 6: Lubricants")
canvas.setFont("Times-BoldItalic", 10)
canvas.drawCentredString(3*Wd+2*W+W/2, Hd+H-H/4, "College Life")
class PlatIllust:
#wrap the above for PP#
def __init__(self, x, y, scale=1):
self.x = x
self.y = y
self.scale = scale
def drawOn(self, canvas):
canvas.saveState()
canvas.translate(self.x, self.y)
canvas.scale(self.scale, self.scale)
doctemplateillustration(canvas)
canvas.restoreState()
class PingoIllust:
#wrap the above for PP#
def __init__(self, x, y, scale=1):
## print 'Pingo illustration %f, %f, %f' % (x,y,scale)
self.x = x
self.y = y
self.scale = scale
def drawOn(self, canvas):
canvas.rect(self.x, self.y, 100,100, stroke=1, fill=1)
## from pingo import testdrawings
## from pingo import pingopdf
## drawing = testdrawings.getDrawing3()
## canvas.saveState()
## canvas.scale(self.scale, self.scale)
## pingopdf.draw(drawing, canvas, self.x, self.y)
## canvas.restoreState()
# D = dir()
g = globals()
Dprime = {}
from types import StringType
from string import strip
for (a,b) in g.items():
if a[:4]=="test" and type(b) is StringType:
#print 'for', a
#print b
b = strip(b)
exec(b+'\n')
platypussetup = """
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.pagesizes import DEFAULT_PAGE_SIZE
from reportlab.lib.units import inch
PAGE_HEIGHT=DEFAULT_PAGE_SIZE[1]; PAGE_WIDTH=DEFAULT_PAGE_SIZE[0]
styles = getSampleStyleSheet()
"""
platypusfirstpage = """
Title = "Hello world"
pageinfo = "platypus example"
def myFirstPage(canvas, doc):
canvas.saveState()
canvas.setFont('Times-Bold',16)
canvas.drawCentredString(PAGE_WIDTH/2.0, PAGE_HEIGHT-108, Title)
canvas.setFont('Times-Roman',9)
canvas.drawString(inch, 0.75 * inch, "First Page / %s" % pageinfo)
canvas.restoreState()
"""
platypusnextpage = """
def myLaterPages(canvas, doc):
canvas.saveState()
canvas.setFont('Times-Roman',9)
canvas.drawString(inch, 0.75 * inch, "Page %d %s" % (doc.page, pageinfo))
canvas.restoreState()
"""
platypusgo = """
def go():
doc = SimpleDocTemplate("phello.pdf")
Story = [Spacer(1,2*inch)]
style = styles["Normal"]
for i in range(100):
bogustext = ("This is Paragraph number %s. " % i) *20
p = Paragraph(bogustext, style)
Story.append(p)
Story.append(Spacer(1,0.2*inch))
doc.build(Story, onFirstPage=myFirstPage, onLaterPages=myLaterPages)
"""
if __name__=="__main__":
# then do the platypus hello world
for b in platypussetup, platypusfirstpage, platypusnextpage, platypusgo:
b = strip(b)
exec(b+'\n')
go()

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- edited with XMLSPY v2004 rel. 3 U (http://www.xmlspy.com) by Andy Robinson (ReportLab Europe Ltd.) -->
<!DOCTYPE presentation SYSTEM "../pythonpoint.dtd">
<presentation filename="figures.xml" pageDuration="10">
<stylesheet module="standard" function="getParagraphStyles"/>
<title>New Feature Tests</title>
<author>
Andy Robinson
</author>
<subject>
Reportlab Sample Applications
</subject>
<section name="Main">
<!-- any graphics in the section go on all its pages as a backdrop -->
<rectangle height="555" fill="ReportLabBlue" x="20" width="96" y="20"/>
<!--fixedimage height="64" filename="leftlogo.gif" x="20" width="96" y="510"/-->
<customshape module="customshapes" class="Logo" initargs="(20,510,96,64)"/>
<!--infostring size="14" align="right" x="800" y="36">
&#187;%(title)s, page %(page)s&#171;
</infostring-->
<!-- Now for the slides -->
<slide title="Introduction" id="Slide001" effectname="Box" effectduration="2">
<frame height="468" x="120" y="72" rightmargin="36" width="700" leftmargin="36">
<para style="Heading1">
New Feature Test Cases - Figures, Drawings and Included Pages
</para>
<para style="BodyText">
especially images and pagecatcher stuff...
</para>
<para style="BodyText">
<i>
PythonPoint
</i>
lets you create attractive and consistent presentation slides
on any platform. It is a demo app built on top of the PDFgen PDF library
and the PLATYPUS Page Layout library. Essentially, it converts slides
in an XML format to PDF.
</para>
<para style="BodyText">
It can be used right now to create slide shows, but will
undoubtedly change and evolve. Read on for a tutorial...
</para>
</frame>
</slide>
<slide title="Test Drawing Tag" id="Slide002" effectname="Dissolve" effectduration="2">
<frame height="468" x="120" y="72" rightmargin="36" width="700" leftmargin="36" border="true">
<para style="Heading1">
Drawing Tag In Action within story context
</para>
<para style="BodyText">
especially images and pagecatcher stuff...
</para>
<para style="BodyText">Hope that came out right-aligned with a box around it...</para>
<drawing module="slidebox" constructor="SlideBoxDrawing" showBoundary="1" hAlign="CENTER"/>
</frame>
</slide>
<slide title="Test PageFigure Tag" id="Slide002" effectname="Glitter" effectduration="2">
<frame height="468" x="120" y="72" rightmargin="36" width="300" leftmargin="36" border="true">
<para style="Heading1">PageFigure</para>
<para style="BodyText">This imports a page and displays it. Since this will typically be used to show
A4/Letter pages, it does a 'shrink to fit' based on frame width. The scaleFactor attribute can override this,
as I did below...
</para>
<pageCatcherFigure filename="../../../../rlextra/pageCatcher/test/ir684.pdf" pageNo="0" caption="IR684 - Authorizing your Agent" scaleFactor="0.1"/>
</frame>
<frame height="468" x="450" y="72" width="325" border="true">
<pageCatcherFigure filename="../../../rlextra/pageCatcher/test/ir684.pdf" pageNo="0" caption="IR684 - Authorizing your Agent"/>
</frame>
</slide>
</section>
</presentation>

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE presentation SYSTEM "../pythonpoint.dtd">
<presentation filename="htu.pdf">
<stylesheet module="htu" function="getParagraphStyles"/>
<section name="Main">
<rectangle x="20" width="96" y="20" height="555" fill="ReportLabBlue"/>
<infostring size="14" align="right" x="800" y="36">
&#169; 2002, H. Turgut UYAR
</infostring>
<slide title="New Features" id="Slide000">
<frame x="120" y="72" width="700" height="418" leftmargin="36" rightmargin="36">
<image filename="pplogo.gif" width="200" height="150"/>
<spacer height="30"/>
<para style="Title">New features in PythonPoint</para>
<para style="Author">H. Turgut Uyar</para>
<para style="EMail">uyar@cs.itu.edu.tr</para>
</frame>
</slide>
<slide title="TrueType Support" id="Slide002">
<frame x="120" y="515" width="700" height="60" leftmargin="36" rightmargin="36">
<para style="Heading1">TrueType Support</para>
</frame>
<frame x="120" y="72" width="700" height="418" leftmargin="36" rightmargin="36">
<para>PythonPoint can read UTF-8 encoded input files and produce
correct output (provided your font has all necessary
characters). That enables you, for example, to have native (in my
case, Turkish) characters in your document:</para>
<para style="Indent">
<!-- if you have any trouble with these, execute the lines below
to find out what we really intended
>>> turkishChars = u"\u011e \u011f \u0130 \u0131 \u015e \u015f"
>>> print turkishChars
>>> print turkishChars.encode("utf-8")
þ ø İ ı ľ ĸ
>>>
-->
<font name="Serif" size="32"> 0 ^  1 _</font>
</para>
</frame>
</slide>
<slide title="Effects" id="Slide003">
<frame x="120" y="515" width="700" height="60" leftmargin="36" rightmargin="36">
<para style="Heading1">Effects</para>
</frame>
<frame x="120" y="72" width="700" height="418" leftmargin="36" rightmargin="36">
<para>Paragraphs, images, tables and geometric shapes can now have
effectname, effectdirection, effectdimension, effectmotion and
effectduration attributes:</para>
<para style="Indent" effectname="Dissolve">A paragraph</para>
<image filename="pplogo.gif" width="80" height="60" effectname="Box"/>
<table style="table1" effectname="Split">
Col1,Col2,Col3
Row1Col1,Row1Col2,Row1Col3
Row2Col1,Row2Col2,Row2Col3
</table>
</frame>
<roundrect x="180" y="150" width="110" height="50" radius="15" fill="(0,1,0)" effectname="Glitter"/>
<string font="Helvetica" size="32" x="200" y="165" align="left" color="(1,0,0)" effectname="Blinds">String</string>
<line x1="248" y1="84" x2="520" y2="84" stroke="(1,0,1)" effectname="Wipe"/>
</slide>
<slide title="Printing" id="Slide004" outlinelevel="1">
<frame x="120" y="515" width="700" height="60" leftmargin="36" rightmargin="36">
<para style="Heading1">Printing</para>
</frame>
<frame x="120" y="72" width="700" height="418" leftmargin="36" rightmargin="36">
<para>Be careful when using effects: A new slide is created for
each effect, so DON'T print the resulting PDF file.</para>
<para effectname="Box">new command-line option: --printout</para>
<para style="Indent">produces printable PDF</para>
</frame>
</slide>
<slide title="New Paragraph Styles" id="Slide005">
<frame x="120" y="515" width="700" height="60" leftmargin="36" rightmargin="36">
<para style="Heading1">New Paragraph Styles</para>
</frame>
<frame x="120" y="72" width="700" height="418" leftmargin="36" rightmargin="36">
<para style="Bullet">Bullet2 - Second level bullets</para>
<para style="Bullet2">Here's an example</para>
<para style="Bullet2">Or an example with a longer text to see
how it wraps at the end of each line</para>
<para style="Bullet">Author and EMail</para>
<para style="Bullet2">See the cover page for examples</para>
<para style="Bullet">They have to be in the style file, so either use
the htu style file or edit your style file</para>
</frame>
</slide>
<slide title="ToDo" id="Slide006">
<frame x="120" y="515" width="700" height="60" leftmargin="36" rightmargin="36">
<para style="Heading1">ToDo</para>
</frame>
<frame x="120" y="72" width="700" height="418" leftmargin="36" rightmargin="36">
<para style="Bullet">Unicode chars in the outline</para>
</frame>
</slide>
</section>
</presentation>

View File

@ -0,0 +1,53 @@
BI
/W 103 /H 68 /BPC 8 /CS /RGB /F [/A85 /Fl]
ID
Gb"/*cYjIe']/l*^;)UQj:Ec+nd!,-,*G/5;0"E.+@qg.\92h2HbiE)jC5*M
$a,@:RoXB@WPjMu=[F;88l[?@OO=6qV,HNNiL#(cac+!&rF)2^DHJ?_:WQkn
1[fb`hOBr--B>FoSDXMt35Gnj6n\3XT8sf/Y%-NPLqg'pmQ+*EiV6D:,$akf
!i2MA/A-"n[R.R)S!ePi$u('8mrCG8[3:WLlB[amBYAS4hR2*f7tR;&\%]Ld
ZX5^f6Qj@\h7^FuQ(">[ml32FW<uUbK'hr2?[K]^D"^NBW@O0*-#'S9X\g_F
SYE1G3(8PLW#-KN>hJG;Z)t2oADV4[H6GbW.mH`MDlesQZO5+Q5)]O<r(Z![
VmGDC"b6h]?JZB+V33e(TZD-HKE7<2d\OKT7macAe_OQDp+mO))_2[22<Jb%
\k]o7Be+6"nn[fbQR6Dm77(ij1n4FYflokM/!o_(c;V/"XKVZ![CCJOTo*G.
`L+#cL'lYP!_1B2q!p=#[76oJ;FF]do.OhJK1R!%SC-8k#a*AX1,`02mU%7f
4ap-1K!c.O!DQb:1k61fiAer=f)fd@jQ]"MQAu[\kB-D?g2*"JR/O2_H!SD2
_UR(81;)KaB24OhoM!X%1D9gR5[b2,[#9dJ@_(:B_l^(Z.ae[g,)m+0jml?6
1`=Z#U4jpgmeoc&B&Bh*B5]<?;J'XU$Cj3P@rO\[Dpm@6'?OID%os>Wf2G9[
U9W99*2'#PD+cIXnp"J"(BrY^=(rg;ITf("c#0"S<;fjK,APV+p9p+05LO&X
jQNf`8c26f]J54N'k#I9=Bt4]e&6gN'#S[nK3*VhQ!`PpXcJ0i<sYK4+orF(
-qFEU#H1b4O<Lc=k3J0Qc(!7M1PjL=,1VdG4FR'urjd<)3iWt^plJ*3A8+L'
[RqBu+MoI1>:J_2rC@=<l=3,MSD5$[mUNC$200Kld\2C9?P]=X&kbd;iMr:d
o'[-mD9bK"`5ki%Rn/GH-sj\3d>>X\5dUbEcCZ?\6O)+F/35ZJD6R$H^-Z!R
5;8=l//9SUkC;LhQ*?di<'6e&/BNIqm(%(S<Q9IJ\ug@o;(c@0gW3p.>DYXJ
p%%Z+J.IshkX$tLPOD'"jSV#/6iY?QI>8P-%o0k3`e#X33RJS`f'D!D2rTJ-
(4Znb03&koo>X[bKs.qpBOkU,K<BP+F35$P(IIZK&F^U8SNceK*`.Lp3\Yth
DiF4Hr/;0#,ub"@Q:)]U%,YT(ckW`\_GIkW$"ms@es$i8@I16iOCr.d$$Y.g
lt!Gp#$'#T\$t,Q\[.aW7+H@h2YX0iR)rr%kf!@*YlEtPBAVgU?LDQKOonm1
B')C@,\ZZ]hm%8:#FPcb@"6UVZ;n1r]SVJ@31k_=Ze=g?f.0oD@hah4[KNj@
Y?=oK%;PJ-r]m9E!9l7$=njO\OC'mrIFY!$\9b]:i58?larmF9MMaHLqiJg#
IB0KR59(W[_5%Vd#snt]Q_.Xfi4?Di=(.*eYNQ=`K+75LcsK4LY:J+1W2<%\
WMqcR6r^&[74V%[O)#1M;LC>CCO3S$2.Gr@<NBm*k!PRPNjsj2TdGq%F$)'#
BB8Yk"/]I+#fCt.!D^Rm3_Or$I#HSsYqbZn*2g3lO-N1eSNoo+g"G+^J1U7'
nar#WZZk-_KTbZXJDIN#>e8E=$On&hUiAB2[.;G@FQf7_<g_,@/;qjYEf-l"
#p0YU5nQ`u=mBQ:q.h>K1&D6RJ.Ih@-56Ss<i&p->&B1q:\)MgJ8P4Sa-(Fm
J"d8Z]Mf`Q$G^\tK@pQWQs3iRB[KP=+H&@+<eJVa9[CPgFV$Fi[oV1K)4R#'
c<\Qi:XK&nEqpb'1e<d^hQhLY)Tul_%_ng0bnt*d%h<7*Qs?U)'_dL=Cd,sO
0&V5g\%1)CmnbV\;N*DE54\tJOeXg4rPH2DR5(:!'u#RAS?,"T/H%+"M[]cm
`\R90YD#$o6A*TZ?>iH@XGFQ'#n!DJ$)Mc?"U#od!oYl3En7nT"7UC,,Q&Hr
9.SPlHak6s)J0;k;hQC:k82'=COeskp&dB-#@RrY1B=H^'L=,;9uJssq%XGf
h/fXmq>1G\?k6ZH*GSk&M)?&TJ?rYW.9f!gdM2&:Kr51A3^MX?GV'T@$h)Da
-RIIcpl8fhiQr=`\k[7;3`X"d!or<JS3FXO\QVoW+fhW8&9W*[dZTpJJq9`f
6/.R;@NP%LrsQia^)8D2Q/J^E"YFmbQNj[eIj8-teIq#\bkMZYNP]`Q,`+Fc
^kG%9V@ulcF&5&o0][1B%)LoGUI()Z`kMbB+q&dLTdLnu?sC!U[nC@bMJ8S(
UJsA@G[Jh[0ebiL<eAkS@8(tI.Xj"IO4#17pl<F>(jb1YM>"Ppi`,67@]M"d
+mXd;WRE"IKX@n&dNNV/55(]`==+_r?K5bp?$^4Pn/[2ncL(/l#CfSYAg:iN
@3j5R$qtm;AIF7k%^ak'%4Z1354d"1VT\g]cm[^hI.Yf>DcLS\rq+As2F?LI
'gq+/_o9&kK,4@]qbdfA8FauP;!N'$5J@1P/\Th=9i^\b$/-6-kL#$E&39t%
/O[1Fm`/F?!q;%bB')DM`KY&D!,6)lG5TQ88ejHiTWKt;3_8:@M!NnP'D2s$
2Q25"dX)7pQ%VUq+r1%.iMQiLR#&.@\:Pe96FEbkgLu`Fb;!#d,DPC-H/d?u
^']=P86?6qr/@_/T-T0?,+>brI`?=13["Y(3DYSMX7UAUk0'!l!aPN<dOAp/
2\gYH7?Iq;ln?q8(%Ag:SW86?Kti9[-7,Lh5fc*A\=4l^Pg&oj%apAq0i?"b
jdfr6IBIK$,+s'>4$e\f&(i2TTrbVuOYhc05Rko:?UP0</LE?hksnprYNQW[
MB4QH,ADP93Y%HB:l-XOR0[N<?s68?2);KK4cL5m>9gLc(-/ni'Q6T.B&8]k
#a_e\0FTMV`IT;W7M>_'NT_f=~>
EI

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,306 @@
<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
<!-- edited with XMLSPY v2004 rel. 3 U (http://www.xmlspy.com) by Andy Robinson (ReportLab Europe Ltd.) -->
<!DOCTYPE presentation SYSTEM "../pythonpoint.dtd">
<presentation filename="monterey.pdf">
<stylesheet module="modern" function="getParagraphStyles"/>
<!--
sections define a colection of stuff to be drawn on all pages they contain.
They must begin with a graphics list
-->
<section name="Main">
<fixedimage filename="vertpython.gif" height="595" width="144" x="0" y="0"/>
<slide title="Cover" id="Slide001" effectname="Wipe">
<!--
put stuff here to be drawn on the page directly
-->
<frame height="432" x="160" y="72" rightmargin="0" width="600" leftmargin="36">
<para/>
<para/>
<para/>
<para style="Title">
Printing with Python
</para>
<image filename="lj8100.jpg"/>
<para style="BigCentered">
Andy Robinson, Robinson Analytics Ltd.
</para>
<para style="BigCentered">
O'Reilly Python Conference, Monterey, 24th August 1999
</para>
</frame>
</slide>
<slide title="Background" id="Slide002" effectname="Wipe">
<frame height="432" x="160" y="72" rightmargin="0" width="600" leftmargin="36">
<para style="Heading2">
Background to the project:
</para>
<para style="Bullet">
London-based consultant and corporate developer
</para>
<para style="Bullet">
want to do neat Python stuff in the daytime
</para>
<para style="Bullet">
working for many years on financial modelling
</para>
<para style="Bullet">
this is one of 6 modules in that system
</para>
<para style="Bullet">
quickest to deliver, offers very wide benefits
</para>
<para style="Bullet">
25% of architecture done, but already very useful
</para>
<para style="Bullet">
Release early, release often!
</para>
</frame>
</slide>
<slide title="Goal" id="Slide003" effectname="Wipe">
<fixedimage filename="vertpython.gif" height="595" width="144" x="0" y="0"/>
<frame height="432" x="160" y="72" rightmargin="0" width="600" leftmargin="36">
<para style="Heading2">
Goal:
</para>
<para style="BodyText">
A Reporting Package on the Next Curve...
</para>
<para style="Bullet">
Report on objects, not databases
</para>
<para style="Bullet">
Scalable to million page runs
</para>
<para style="Bullet">
Light enough to embed in any application
</para>
<para style="Bullet">
Allow reuse of graphical objects across reports
</para>
<para style="Bullet">
Open and extensible on several levels
</para>
<para style="Bullet">
Publication quality
</para>
<para style="Bullet">
Support all the world's languages - one day
</para>
</frame>
</slide>
<slide title="Portable Document Format" id="Slide004" effectname="Wipe">
<frame height="432" x="160" y="72" rightmargin="0" width="600" leftmargin="36">
<para style="Heading2">
Portable Document Format
</para>
<para style="Italic">
The New PostScript
</para>
<para style="Bullet">
Free readers on all platforms
</para>
<para style="Bullet">
Better than paper - view it, email it, print it
</para>
<para style="Bullet">
'Final Form' for documents
</para>
<para style="Bullet">
High end solution - no limits to quality
</para>
<para style="Italic">
...but you can't learn it in Notepad!
</para>
</frame>
</slide>
<slide title="PDFgen and PIDDLE" id="Slide005" effectname="Wipe">
<frame height="432" x="160" y="72" rightmargin="0" width="600" leftmargin="36">
<para/>
<para/>
<para style="Title">
PDFgen and PIDDLE
</para>
</frame>
</slide>
<slide title="PDFgen layer" id="Slide006" effectname="Wipe">
<frame height="432" x="160" y="72" rightmargin="0" width="600" leftmargin="36">
<para style="Heading2">
Layer One - PDFgen
</para>
<para style="Bullet">
makes PDF documents from pure Python
</para>
<para style="Bullet">
wraps up PDF document structure
</para>
<para style="Bullet">
exposes nice effects - page transitions, outline trees (RSN!)
</para>
<para style="Bullet">
low level graphics promitives (postscript imaging model)
</para>
<para style="Bullet">
Fine control of text placement
</para>
<para style="Bullet">
Supports Asian text
</para>
<para style="Bullet">
Supports coordinate transformations and clipping
</para>
<para style="Italic">
...a foundation for other apps to build on
</para>
</frame>
</slide>
<slide title="PDF Image Suport" id="Slide007" effectname="Wipe">
<frame height="432" x="160" y="72" rightmargin="0" width="600" leftmargin="36">
<para style="Heading2">
PDFgen Image Support
</para>
<para>
Python Imaging Library and zlib do all the work - many formats.
Images cached (like .pyc files) - very fast builds possible.
</para>
<image filename="python.gif" width="588" height="200"/>
</frame>
</slide>
<slide title="Layer Two: PIDDLE" id="Slide008" effectname="Wipe">
<frame height="432" x="160" y="72" rightmargin="0" width="600" leftmargin="36">
<para style="Heading2">
Layer Two: PIDDLE
</para>
<para style="Italic">
Plug In Drawing, Does Little Else
</para>
<para style="Bullet">
Easy Graphics Library
</para>
<para style="Bullet">
Abstract Canvas Interface
</para>
<para style="Bullet">
Pluggable Back Ends
</para>
<para style="Bullet">
Same code can do viewing and printing
</para>
<para style="Bullet">
Standard set of test patterns
</para>
<para style="Bullet">
Uses Python Imaging Library
</para>
<para style="BodyText">
Back ends includeTkinter, wxPython, Mac, Pythonwin, PDF, PostScript,
OpenGL, Adobe Illustrator and PIL. Really easy to add a new one!
</para>
</frame>
</slide>
<slide title="Layer Three: PLATYPUS" id="Slide009" effectname="Wipe">
<frame height="432" x="160" y="72" rightmargin="0" width="600" leftmargin="36">
<para style="Heading2">
Layer Three: PLATYPUS
</para>
<para style="Italic">
"Page Layout And Typography Using Scripts"
</para>
<para style="BodyText">
Trying to work out the API now. Key Concepts:
</para>
<para style="Bullet">
Drawable objects - can 'wrap to fit'
</para>
<para style="Bullet">
Frames on page
</para>
<para style="Bullet">
Frame consumes from a list of drawables until full
</para>
<para style="Bullet">
Document Models e.g. SimpleFlowDocument
</para>
<para style="BodyText">
XSL Flow Object model may be a good target
</para>
</frame>
</slide>
<slide title="Drawable Objects" id="Slide010" effectname="Wipe">
<frame height="432" x="160" y="72" rightmargin="0" width="600" leftmargin="36">
<para style="Heading2">
Drawable Objects
</para>
<para style="BodyText">
Next layer of PIDDLE extensibility.
Each draws in its own coodinate system
</para>
<para style="Bullet">
paragraph, image, table
</para>
<para style="Bullet">
chart libraries
</para>
<para style="Bullet">
diagrams
</para>
<para style="BodyText">
Open Source - let people contribute new ones.
Anything you could have in a view can be a new
drawable type.
</para>
</frame>
</slide>
<slide title="Style Sheets" id="Slide011" effectname="Wipe">
<frame height="432" x="160" y="72" rightmargin="0" width="600" leftmargin="36">
<para style="Heading2">
Style Sheet Driven
</para>
<para style="BodyText">
Styles use instance inheritance
</para>
<para style="Bullet">
Paragraph Styles - Style Sheet Compulsory!
</para>
<para style="Bullet">
Text Styles within a paragraph
</para>
<para style="Bullet">
Table and Table Cell Styles
</para>
</frame>
</slide>
<slide title="Vision" id="Slide012" effectname="Wipe">
<frame height="432" x="160" y="72" rightmargin="0" width="600" leftmargin="36">
<para style="Heading2">
Vision
</para>
<para style="Bullet">
XML to PDF in one step
</para>
<para style="Bullet">
Publish to web and print from same source
</para>
<para style="Bullet">
Financial and Scientific reporting tool
</para>
<para style="Bullet">
Embedded reporting engine
</para>
<para style="Bullet">
Volume reporting tool for business
</para>
</frame>
</slide>
<slide title="PythonPoint" id="Slide013" effectname="Wipe">
<frame height="432" x="160" y="72" rightmargin="0" width="600" leftmargin="36">
<para style="Heading2">
PythonPoint
</para>
<para style="Italic">
How I made this presentation...
</para>
</frame>
</slide>
</section>
</presentation>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
#Autogenerated by ReportLab guiedit do not edit
from reportlab.graphics.shapes import _DrawingEditorMixin
from reportlab.graphics.charts.slidebox import SlideBox
from rlextra.graphics.guiedit.datacharts import ODBCDataSource, CSVDataSource, DataAssociation, DataAwareDrawing
class SlideBoxDrawing(_DrawingEditorMixin,DataAwareDrawing):
def __init__(self,width=400,height=200,*args,**kw):
apply(DataAwareDrawing.__init__,(self,width,height)+args,kw)
self._add(self,SlideBox(),name='SlideBox',validate=None,desc='The main chart')
self.height = 40
self.width = 168
#self.dataSource = ODBCDataSource()
self.dataSource = CSVDataSource()
self.dataSource.filename = 'slidebox.csv'
self.dataSource.integerColumns = ['chartId','value','numberOfBoxes']
self.dataSource.sql = 'SELECT chartId,numberOfBoxes,label,value FROM generic_slidebox'
self.dataSource.associations.size = 4
self.dataSource.associations.element00 = DataAssociation(column=0, target='chartId', assocType='scalar')
self.dataSource.associations.element01 = DataAssociation(column=1, target='SlideBox.numberOfBoxes', assocType='scalar')
self.dataSource.associations.element02 = DataAssociation(column=2, target='SlideBox.sourceLabelText', assocType='scalar')
self.dataSource.associations.element03 = DataAssociation(column=3, target='SlideBox.trianglePosition', assocType='scalar')
self.verbose = 1
self.formats = ['eps', 'pdf']
self.outDir = './output/'
self.fileNamePattern = 'slidebox%03d'
if __name__=="__main__": #NORUNTESTS
SlideBoxDrawing().go()

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1,275 @@
<!--
pythonpoint.dtd
PythonPoint XML DTD, version 0.1k
Copyright 2001-2002 ReportLab, Inc.
This is a draft of the DTD for PythonPoint, a program for creating
presentation slides based on XML.
See http://www.reportlab.com for further information.
Common declaration:
<?xml version='1.0'?>
<!DOCTYPE presentation
PUBLIC "-//ReportLab//DTD PythonPoint XML v0.1k//EN"
"pythonpoint.dtd">
Please send bug reports, suggestions, etc. to: info@reportlab.com.
-->
<!-- Entities -->
<!ENTITY % bool "true|false">
<!ENTITY % align.values "left|center|right">
<!ENTITY % effectdimension.values "H|V">
<!ENTITY % effectdirection.values "0|90|180|270">
<!ENTITY % effectmotion.values "I|O">
<!ENTITY % effectname.values "Blinds|Box|Dissolve|Glitter|Split|Wipe">
<!-- Top-Level Element -->
<!ELEMENT presentation (subject?, title?, author?, section?, stylesheet?, registerFont?, slide*)+>
<!ATTLIST presentation
filename CDATA #REQUIRED
pageDuration CDATA #IMPLIED
pageWidth CDATA #IMPLIED
pageHeight CDATA #IMPLIED
>
<!-- First-Level Elements -->
<!ELEMENT author (#PCDATA)>
<!-- PDF Document Info -->
<!ELEMENT section (fixedimage*, rectangle*, roundrect*, ellipse*, polygon*, line*, string*, infostring*, customshape*, slide*)+>
<!ATTLIST section
name CDATA #REQUIRED
>
<!ELEMENT slide (fixedimage*, rectangle*, roundrect*, ellipse*, polygon*, line*, string*, infostring*, customshape*, frame*, notes*)+>
<!ATTLIST slide
id CDATA #REQUIRED
title CDATA #REQUIRED
outlineentry CDATA #IMPLIED
outlinelevel NMTOKEN #IMPLIED
showIDName (%bool;) "true"
effectname (%effectname.values;) #IMPLIED
effectdirection (%effectdirection.values;) "0"
effectdimension (%effectdimension.values;) "H"
effectmotion (%effectmotion.values;) "I"
effectduration NMTOKEN "1"
>
<!ELEMENT stylesheet EMPTY>
<!ATTLIST stylesheet
path CDATA #IMPLIED
module CDATA #REQUIRED
function CDATA #REQUIRED
>
<!ELEMENT registerFont EMPTY>
<!ATTLIST registerFont
name CDATA #REQUIRED
path CDATA #REQUIRED
>
<!ELEMENT subject (#PCDATA)>
<!-- PDF Document Info -->
<!ELEMENT title (#PCDATA)>
<!-- PDF Document Info -->
<!-- Other elements -->
<!ELEMENT b (#PCDATA)>
<!ELEMENT customshape EMPTY>
<!ATTLIST customshape
path CDATA #IMPLIED
module CDATA #IMPLIED
class CDATA #IMPLIED
initargs CDATA #IMPLIED
align (%align.values;) #IMPLIED
>
<!ELEMENT ellipse EMPTY>
<!ATTLIST ellipse
x1 NMTOKEN #REQUIRED
y1 NMTOKEN #REQUIRED
x2 NMTOKEN #REQUIRED
y2 NMTOKEN #REQUIRED
fill CDATA #IMPLIED
stroke CDATA "(0,0,0)"
linewidth NMTOKEN "0"
effectname (%effectname.values;) #IMPLIED
effectdirection (%effectdirection.values;) "0"
effectdimension (%effectdimension.values;) "H"
effectmotion (%effectmotion.values;) "I"
effectduration NMTOKEN "1"
>
<!ELEMENT fixedimage EMPTY>
<!ATTLIST fixedimage
filename CDATA #REQUIRED
x NMTOKEN #REQUIRED
y NMTOKEN #REQUIRED
width NMTOKEN #IMPLIED
height NMTOKEN #IMPLIED
>
<!ELEMENT font (#PCDATA)>
<!ATTLIST font
name CDATA #IMPLIED
color CDATA #IMPLIED
size NMTOKEN #IMPLIED
>
<!ELEMENT frame (para*, prefmt*, pycode*, image*, table*, fixedimage*, rectangle*, roundrect*, ellipse*, polygon*, line*, string*, customshape*, spacer*, drawing*, pageCatcherFigure*)+>
<!ATTLIST frame
x NMTOKEN #REQUIRED
y NMTOKEN #REQUIRED
width NMTOKEN #REQUIRED
height NMTOKEN #REQUIRED
leftmargin NMTOKEN "0"
rightmargin NMTOKEN "0"
topmargin NMTOKEN "0"
bottommargin NMTOKEN "0"
border (%bool;) "false"
>
<!ELEMENT greek (#PCDATA)>
<!ELEMENT i (#PCDATA)>
<!ELEMENT image EMPTY>
<!ATTLIST image
filename CDATA #REQUIRED
width NMTOKEN #IMPLIED
height NMTOKEN #IMPLIED
effectname (%effectname.values;) #IMPLIED
effectdirection (%effectdirection.values;) "0"
effectdimension (%effectdimension.values;) "H"
effectmotion (%effectmotion.values;) "I"
effectduration NMTOKEN "1"
>
<!ELEMENT infostring (#PCDATA)>
<!ATTLIST infostring
x NMTOKEN #REQUIRED
y NMTOKEN #REQUIRED
color CDATA "(0,0,0)"
font CDATA "Times-Roman"
size NMTOKEN "12"
align (%align.values;) "left"
>
<!ELEMENT line EMPTY>
<!ATTLIST line
x1 NMTOKEN #REQUIRED
y1 NMTOKEN #REQUIRED
x2 NMTOKEN #REQUIRED
y2 NMTOKEN #REQUIRED
stroke CDATA "(0,0,0)"
width NMTOKEN "0"
effectname (%effectname.values;) #IMPLIED
effectdirection (%effectdirection.values;) "0"
effectdimension (%effectdimension.values;) "H"
effectmotion (%effectmotion.values;) "I"
effectduration NMTOKEN "1"
>
<!ELEMENT notes (para+)>
<!ELEMENT para (#PCDATA | i | b | u | super | sub | font | greek)*>
<!ATTLIST para
style CDATA "Normal"
bullettext CDATA #IMPLIED
effectname (%effectname.values;) #IMPLIED
effectdirection (%effectdirection.values;) "0"
effectdimension (%effectdimension.values;) "H"
effectmotion (%effectmotion.values;) "I"
effectduration NMTOKEN "1"
>
<!ELEMENT polygon EMPTY>
<!ATTLIST polygon
points CDATA #REQUIRED
fill CDATA #REQUIRED
stroke CDATA "(0,0,0)"
linewidth NMTOKEN "0"
effectname (%effectname.values;) #IMPLIED
effectdirection (%effectdirection.values;) "0"
effectdimension (%effectdimension.values;) "H"
effectmotion (%effectmotion.values;) "I"
effectduration NMTOKEN "1"
>
<!ELEMENT prefmt (#PCDATA)>
<!ATTLIST prefmt
xml:space (default | preserve) #FIXED "preserve"
style CDATA #IMPLIED
>
<!ELEMENT pycode (#PCDATA)>
<!ATTLIST pycode
xml:space (default | preserve) #FIXED "preserve"
style CDATA #IMPLIED
>
<!ELEMENT rectangle EMPTY>
<!ATTLIST rectangle
x NMTOKEN #REQUIRED
y NMTOKEN #REQUIRED
width NMTOKEN #REQUIRED
height NMTOKEN #REQUIRED
fill CDATA #IMPLIED
stroke CDATA "(0,0,0)"
linewidth NMTOKEN "0"
effectname (%effectname.values;) #IMPLIED
effectdirection (%effectdirection.values;) "0"
effectdimension (%effectdimension.values;) "H"
effectmotion (%effectmotion.values;) "I"
effectduration NMTOKEN "1"
>
<!ELEMENT roundrect EMPTY>
<!ATTLIST roundrect
x NMTOKEN #REQUIRED
y NMTOKEN #REQUIRED
width NMTOKEN #REQUIRED
height NMTOKEN #REQUIRED
fill CDATA #IMPLIED
stroke CDATA "(0,0,0)"
linewidth NMTOKEN "0"
radius NMTOKEN "6"
effectname (%effectname.values;) #IMPLIED
effectdirection (%effectdirection.values;) "0"
effectdimension (%effectdimension.values;) "H"
effectmotion (%effectmotion.values;) "I"
effectduration NMTOKEN "1"
>
<!ELEMENT spacer EMPTY>
<!ATTLIST spacer
height NMTOKEN #REQUIRED
>
<!ELEMENT string (#PCDATA)>
<!ATTLIST string
x NMTOKEN #REQUIRED
y NMTOKEN #REQUIRED
color CDATA "(0,0,0)"
font CDATA "Times-Roman"
size NMTOKEN "12"
align (%align.values;) "left"
effectname (%effectname.values;) #IMPLIED
effectdirection (%effectdirection.values;) "0"
effectdimension (%effectdimension.values;) "H"
effectmotion (%effectmotion.values;) "I"
effectduration NMTOKEN "1"
>
<!ELEMENT sub (#PCDATA)>
<!ELEMENT super (#PCDATA)>
<!ELEMENT table (#PCDATA)>
<!ATTLIST table
xml:space (default | preserve) #FIXED "preserve"
widths CDATA #IMPLIED
heights CDATA #IMPLIED
style CDATA #IMPLIED
colDelim CDATA #IMPLIED
rowDelim CDATA #IMPLIED
effectname (%effectname.values;) #IMPLIED
effectdirection (%effectdirection.values;) "0"
effectdimension (%effectdimension.values;) "H"
effectmotion (%effectmotion.values;) "I"
effectduration NMTOKEN "1"
>
<!ELEMENT u (#PCDATA)>
<!ELEMENT drawing EMPTY>
<!ATTLIST drawing
module CDATA #REQUIRED
constructor CDATA #REQUIRED
baseDir CDATA #IMPLIED
hAlign CDATA #IMPLIED
showBoundary CDATA #IMPLIED
>
<!ELEMENT pageCatcherFigure (#PCDATA)>
<!ATTLIST pageCatcherFigure
filename CDATA #REQUIRED
pageNo CDATA #REQUIRED
caption CDATA #IMPLIED
width CDATA #IMPLIED
height CDATA #IMPLIED
background CDATA #IMPLIED
border CDATA #IMPLIED
scaleFactor CDATA #IMPLIED
>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,813 @@
"""
Parser for PythonPoint using the xmllib.py in the standard Python
distribution. Slow, but always present. We intend to add new parsers
as Python 2.x and the XML package spread in popularity and stabilise.
The parser has a getPresentation method; it is called from
pythonpoint.py.
"""
import string, imp, sys, os, copy
from reportlab.lib.utils import SeqTypes
from reportlab.lib import xmllib
from reportlab.lib import colors
from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
from reportlab.lib.utils import recursiveImport
from reportlab.tools.pythonpoint import pythonpoint
from reportlab.platypus import figures
def getModule(modulename,fromPath='reportlab.tools.pythonpoint.styles'):
"""Get a module containing style declarations.
Search order is:
reportlab/tools/pythonpoint/
reportlab/tools/pythonpoint/styles/
./
"""
try:
exec 'from reportlab.tools.pythonpoint import '+modulename
return eval(modulename)
except ImportError:
try:
exec 'from reportlab.tools.pythonpoint.styles import '+modulename
return eval(modulename)
except ImportError:
exec 'import '+modulename
return eval(modulename)
class PPMLParser(xmllib.XMLParser):
attributes = {
#this defines the available attributes for all objects,
#and their default values. Although these don't have to
#be strings, the ones parsed from the XML do, so
#everything is a quoted string and the parser has to
#convert these to numbers where appropriate.
'stylesheet': {
'path':'None',
'module':'None',
'function':'getParagraphStyles'
},
'frame': {
'x':'0',
'y':'0',
'width':'0',
'height':'0',
'border':'false',
'leftmargin':'0', #this is ignored
'topmargin':'0', #this is ignored
'rightmargin':'0', #this is ignored
'bottommargin':'0', #this is ignored
},
'slide': {
'id':'None',
'title':'None',
'effectname':'None', # Split, Blinds, Box, Wipe, Dissolve, Glitter
'effectdirection':'0', # 0,90,180,270
'effectdimension':'H', # H or V - horizontal or vertical
'effectmotion':'I', # Inwards or Outwards
'effectduration':'1', #seconds,
'outlineentry':'None',
'outlinelevel':'0' # 1 is a child, 2 is a grandchild etc.
},
'para': {
'style':'Normal',
'bullettext':'',
'effectname':'None',
'effectdirection':'0',
'effectdimension':'H',
'effectmotion':'I',
'effectduration':'1'
},
'image': {
'filename':'',
'width':'None',
'height':'None',
'effectname':'None',
'effectdirection':'0',
'effectdimension':'H',
'effectmotion':'I',
'effectduration':'1'
},
'table': {
'widths':'None',
'heights':'None',
'fieldDelim':',',
'rowDelim':'\n',
'style':'None',
'effectname':'None',
'effectdirection':'0',
'effectdimension':'H',
'effectmotion':'I',
'effectduration':'1'
},
'rectangle': {
'x':'0',
'y':'0',
'width':'100',
'height':'100',
'fill':'None',
'stroke':'(0,0,0)',
'linewidth':'0',
'effectname':'None',
'effectdirection':'0',
'effectdimension':'H',
'effectmotion':'I',
'effectduration':'1'
},
'roundrect': {
'x':'0',
'y':'0',
'width':'100',
'height':'100',
'radius':'6',
'fill':'None',
'stroke':'(0,0,0)',
'linewidth':'0',
'effectname':'None',
'effectdirection':'0',
'effectdimension':'H',
'effectmotion':'I',
'effectduration':'1'
},
'line': {
'x1':'0',
'y1':'0',
'x2':'100',
'y2':'100',
'stroke':'(0,0,0)',
'width':'0',
'effectname':'None',
'effectdirection':'0',
'effectdimension':'H',
'effectmotion':'I',
'effectduration':'1'
},
'ellipse': {
'x1':'0',
'y1':'0',
'x2':'100',
'y2':'100',
'stroke':'(0,0,0)',
'fill':'None',
'linewidth':'0',
'effectname':'None',
'effectdirection':'0',
'effectdimension':'H',
'effectmotion':'I',
'effectduration':'1'
},
'polygon': {
'points':'(0,0),(50,0),(25,25)',
'stroke':'(0,0,0)',
'linewidth':'0',
'stroke':'(0,0,0)',
'fill':'None',
'effectname':'None',
'effectdirection':'0',
'effectdimension':'H',
'effectmotion':'I',
'effectduration':'1'
},
'string':{
'x':'0',
'y':'0',
'color':'(0,0,0)',
'font':'Times-Roman',
'size':'12',
'align':'left',
'effectname':'None',
'effectdirection':'0',
'effectdimension':'H',
'effectmotion':'I',
'effectduration':'1'
},
'customshape':{
'path':'None',
'module':'None',
'class':'None',
'initargs':'None'
}
}
def __init__(self):
self.presentations = []
#yes, I know a generic stack would be easier...
#still, testing if we are 'in' something gives
#a degree of validation.
self._curPres = None
self._curSection = None
self._curSlide = None
self._curFrame = None
self._curPara = None #the only places we are interested in
self._curPrefmt = None
self._curPyCode = None
self._curString = None
self._curTable = None
self._curTitle = None
self._curAuthor = None
self._curSubject = None
self.fx = 1
xmllib.XMLParser.__init__(self)
def _arg(self,tag,args,name):
"What's this for???"
if args.has_key(name):
v = args[name]
else:
if self.attributes.has_key(tag):
v = self.attributes[tag][name]
else:
v = None
return v
def ceval(self,tag,args,name):
if args.has_key(name):
v = args[name]
else:
if self.attributes.has_key(tag):
v = self.attributes[tag][name]
else:
return None
# handle named colors (names from reportlab.lib.colors)
if name in ('color', 'stroke', 'fill'):
v = str(pythonpoint.checkColor(v))
return eval(v)
def getPresentation(self):
return self._curPres
def handle_data(self, data):
#the only data should be paragraph text, preformatted para
#text, 'string text' for a fixed string on the page,
#or table data
if self._curPara:
self._curPara.rawtext = self._curPara.rawtext + data
elif self._curPrefmt:
self._curPrefmt.rawtext = self._curPrefmt.rawtext + data
elif self._curPyCode:
self._curPyCode.rawtext = self._curPyCode.rawtext + data
elif self._curString:
self._curString.text = self._curString.text + data
elif self._curTable:
self._curTable.rawBlocks.append(data)
elif self._curTitle <> None: # need to allow empty strings,
# hence explicitly testing for None
self._curTitle = self._curTitle + data
elif self._curAuthor <> None:
self._curAuthor = self._curAuthor + data
elif self._curSubject <> None:
self._curSubject = self._curSubject + data
def handle_cdata(self, data):
#just append to current paragraph text, so we can quote XML
if self._curPara:
self._curPara.rawtext = self._curPara.rawtext + data
elif self._curPrefmt:
self._curPrefmt.rawtext = self._curPrefmt.rawtext + data
elif self._curPyCode:
self._curPyCode.rawtext = self._curPyCode.rawtext + data
elif self._curString:
self._curString.text = self._curString.text + data
elif self._curTable:
self._curTable.rawBlocks.append(data)
elif self._curAuthor <> None:
self._curAuthor = self._curAuthor + data
elif self._curSubject <> None:
self._curSubject = self._curSubject + data
def start_presentation(self, args):
self._curPres = pythonpoint.PPPresentation()
self._curPres.filename = self._arg('presentation',args,'filename')
self._curPres.effectName = self._arg('presentation',args,'effect')
self._curPres.pageDuration = self._arg('presentation',args,'pageDuration')
h = self._arg('presentation',args,'pageHeight')
if h:
self._curPres.pageHeight = h
w = self._arg('presentation',args,'pageWidth')
if w:
self._curPres.pageWidth = w
#print 'page size =', self._curPres.pageSize
def end_presentation(self):
pass
## print 'Fully parsed presentation',self._curPres.filename
def start_title(self, args):
self._curTitle = ''
def end_title(self):
self._curPres.title = self._curTitle
self._curTitle = None
def start_author(self, args):
self._curAuthor = ''
def end_author(self):
self._curPres.author = self._curAuthor
self._curAuthor = None
def start_subject(self, args):
self._curSubject = ''
def end_subject(self):
self._curPres.subject = self._curSubject
self._curSubject = None
def start_stylesheet(self, args):
#makes it the current style sheet.
path = self._arg('stylesheet',args,'path')
if path=='None': path = []
if type(path) not in SeqTypes: path = [path]
path.append('styles')
path.append(os.getcwd())
modulename = self._arg('stylesheet', args, 'module')
funcname = self._arg('stylesheet', args, 'function')
try:
found = imp.find_module(modulename, path)
(file, pathname, description) = found
mod = imp.load_module(modulename, file, pathname, description)
except ImportError:
#last gasp
mod = getModule(modulename)
#now get the function
func = getattr(mod, funcname)
pythonpoint.setStyles(func())
## print 'set global stylesheet to %s.%s()' % (modulename, funcname)
def end_stylesheet(self):
pass
def start_section(self, args):
name = self._arg('section',args,'name')
self._curSection = pythonpoint.PPSection(name)
def end_section(self):
self._curSection = None
def start_slide(self, args):
s = pythonpoint.PPSlide()
s.id = self._arg('slide',args,'id')
s.title = self._arg('slide',args,'title')
a = self._arg('slide',args,'effectname')
if a <> 'None':
s.effectName = a
s.effectDirection = self.ceval('slide',args,'effectdirection')
s.effectDimension = self._arg('slide',args,'effectdimension')
s.effectDuration = self.ceval('slide',args,'effectduration')
s.effectMotion = self._arg('slide',args,'effectmotion')
#HACK - may not belong here in the long run...
#by default, use the slide title for the outline entry,
#unless it is specified as an arg.
a = self._arg('slide',args,'outlineentry')
if a == "Hide":
s.outlineEntry = None
elif a <> 'None':
s.outlineEntry = a
else:
s.outlineEntry = s.title
s.outlineLevel = self.ceval('slide',args,'outlinelevel')
#let it know its section, which may be none
s.section = self._curSection
self._curSlide = s
def end_slide(self):
self._curPres.slides.append(self._curSlide)
self._curSlide = None
def start_frame(self, args):
self._curFrame = pythonpoint.PPFrame(
self.ceval('frame',args,'x'),
self.ceval('frame',args,'y'),
self.ceval('frame',args,'width'),
self.ceval('frame',args,'height')
)
if self._arg('frame',args,'border')=='true':
self._curFrame.showBoundary = 1
def end_frame(self):
self._curSlide.frames.append(self._curFrame)
self._curFrame = None
def start_notes(self, args):
name = self._arg('notes',args,'name')
self._curNotes = pythonpoint.PPNotes()
def end_notes(self):
self._curSlide.notes.append(self._curNotes)
self._curNotes = None
def start_registerFont(self, args):
name = self._arg('font',args,'name')
path = self._arg('font',args,'path')
pythonpoint.registerFont0(self.sourceFilename, name, path)
def end_registerFont(self):
pass
def pack_slide(self, element, args):
if self.fx:
effectName = self._arg(element,args,'effectname')
if effectName <> 'None':
curSlide = copy.deepcopy(self._curSlide)
if self._curFrame:
curFrame = copy.deepcopy(self._curFrame)
curSlide.frames.append(curFrame)
self._curPres.slides.append(curSlide)
self._curSlide.effectName = effectName
self._curSlide.effectDirection = self.ceval(element,args,'effectdirection')
self._curSlide.effectDimension = self._arg(element,args,'effectdimension')
self._curSlide.effectDuration = self.ceval(element,args,'effectduration')
self._curSlide.effectMotion = self._arg(element,args,'effectmotion')
self._curSlide.outlineEntry = None
def start_para(self, args):
self.pack_slide('para', args)
self._curPara = pythonpoint.PPPara()
self._curPara.style = self._arg('para',args,'style')
# hack - bullet character if bullet style
bt = self._arg('para',args,'bullettext')
if bt == '':
if self._curPara.style == 'Bullet':
bt = '\xc2\xb7' # Symbol Font bullet character, reasonable default
elif self._curPara.style == 'Bullet2':
bt = '\xc2\xb7' # second-level bullet
else:
bt = None
self._curPara.bulletText = bt
def end_para(self):
if self._curFrame:
self._curFrame.content.append(self._curPara)
self._curPara = None
elif self._curNotes:
self._curNotes.content.append(self._curPara)
self._curPara = None
def start_prefmt(self, args):
self._curPrefmt = pythonpoint.PPPreformattedText()
self._curPrefmt.style = self._arg('prefmt',args,'style')
def end_prefmt(self):
self._curFrame.content.append(self._curPrefmt)
self._curPrefmt = None
def start_pycode(self, args):
self._curPyCode = pythonpoint.PPPythonCode()
self._curPyCode.style = self._arg('pycode',args,'style')
def end_pycode(self):
self._curFrame.content.append(self._curPyCode)
self._curPyCode = None
def start_image(self, args):
self.pack_slide('image',args)
sourceFilename = self.sourceFilename # XXX
filename = self._arg('image',args,'filename')
filename = os.path.join(os.path.dirname(sourceFilename), filename)
self._curImage = pythonpoint.PPImage()
self._curImage.filename = filename
self._curImage.width = self.ceval('image',args,'width')
self._curImage.height = self.ceval('image',args,'height')
def end_image(self):
self._curFrame.content.append(self._curImage)
self._curImage = None
def start_table(self, args):
self.pack_slide('table',args)
self._curTable = pythonpoint.PPTable()
self._curTable.widths = self.ceval('table',args,'widths')
self._curTable.heights = self.ceval('table',args,'heights')
#these may contain escapes like tabs - handle with
#a bit more care.
if args.has_key('fieldDelim'):
self._curTable.fieldDelim = eval('"' + args['fieldDelim'] + '"')
if args.has_key('rowDelim'):
self._curTable.rowDelim = eval('"' + args['rowDelim'] + '"')
if args.has_key('style'):
self._curTable.style = args['style']
def end_table(self):
self._curFrame.content.append(self._curTable)
self._curTable = None
def start_spacer(self, args):
"""No contents so deal with it here."""
sp = pythonpoint.PPSpacer()
sp.height = eval(args['height'])
self._curFrame.content.append(sp)
def end_spacer(self):
pass
## the graphics objects - go into either the current section
## or the current slide.
def start_fixedimage(self, args):
sourceFilename = self.sourceFilename
filename = self._arg('image',args,'filename')
filename = os.path.join(os.path.dirname(sourceFilename), filename)
img = pythonpoint.PPFixedImage()
img.filename = filename
img.x = self.ceval('fixedimage',args,'x')
img.y = self.ceval('fixedimage',args,'y')
img.width = self.ceval('fixedimage',args,'width')
img.height = self.ceval('fixedimage',args,'height')
self._curFixedImage = img
def end_fixedimage(self):
if self._curSlide:
self._curSlide.graphics.append(self._curFixedImage)
elif self._curSection:
self._curSection.graphics.append(self._curFixedImage)
self._curFixedImage = None
def start_rectangle(self, args):
self.pack_slide('rectangle', args)
rect = pythonpoint.PPRectangle(
self.ceval('rectangle',args,'x'),
self.ceval('rectangle',args,'y'),
self.ceval('rectangle',args,'width'),
self.ceval('rectangle',args,'height')
)
rect.fillColor = self.ceval('rectangle',args,'fill')
rect.strokeColor = self.ceval('rectangle',args,'stroke')
self._curRectangle = rect
def end_rectangle(self):
if self._curSlide:
self._curSlide.graphics.append(self._curRectangle)
elif self._curSection:
self._curSection.graphics.append(self._curRectangle)
self._curRectangle = None
def start_roundrect(self, args):
self.pack_slide('roundrect', args)
rrect = pythonpoint.PPRoundRect(
self.ceval('roundrect',args,'x'),
self.ceval('roundrect',args,'y'),
self.ceval('roundrect',args,'width'),
self.ceval('roundrect',args,'height'),
self.ceval('roundrect',args,'radius')
)
rrect.fillColor = self.ceval('roundrect',args,'fill')
rrect.strokeColor = self.ceval('roundrect',args,'stroke')
self._curRoundRect = rrect
def end_roundrect(self):
if self._curSlide:
self._curSlide.graphics.append(self._curRoundRect)
elif self._curSection:
self._curSection.graphics.append(self._curRoundRect)
self._curRoundRect = None
def start_line(self, args):
self.pack_slide('line', args)
self._curLine = pythonpoint.PPLine(
self.ceval('line',args,'x1'),
self.ceval('line',args,'y1'),
self.ceval('line',args,'x2'),
self.ceval('line',args,'y2')
)
self._curLine.strokeColor = self.ceval('line',args,'stroke')
def end_line(self):
if self._curSlide:
self._curSlide.graphics.append(self._curLine)
elif self._curSection:
self._curSection.graphics.append(self._curLine)
self._curLine = None
def start_ellipse(self, args):
self.pack_slide('ellipse', args)
self._curEllipse = pythonpoint.PPEllipse(
self.ceval('ellipse',args,'x1'),
self.ceval('ellipse',args,'y1'),
self.ceval('ellipse',args,'x2'),
self.ceval('ellipse',args,'y2')
)
self._curEllipse.strokeColor = self.ceval('ellipse',args,'stroke')
self._curEllipse.fillColor = self.ceval('ellipse',args,'fill')
def end_ellipse(self):
if self._curSlide:
self._curSlide.graphics.append(self._curEllipse)
elif self._curSection:
self._curSection.graphics.append(self._curEllipse)
self._curEllipse = None
def start_polygon(self, args):
self.pack_slide('polygon', args)
self._curPolygon = pythonpoint.PPPolygon(self.ceval('polygon',args,'points'))
self._curPolygon.strokeColor = self.ceval('polygon',args,'stroke')
self._curPolygon.fillColor = self.ceval('polygon',args,'fill')
def end_polygon(self):
if self._curSlide:
self._curSlide.graphics.append(self._curPolygon)
elif self._curSection:
self._curSection.graphics.append(self._curPolygon)
self._curEllipse = None
def start_string(self, args):
self.pack_slide('string', args)
self._curString = pythonpoint.PPString(
self.ceval('string',args,'x'),
self.ceval('string',args,'y')
)
self._curString.color = self.ceval('string',args,'color')
self._curString.font = self._arg('string',args,'font')
self._curString.size = self.ceval('string',args,'size')
if args['align'] == 'left':
self._curString.align = TA_LEFT
elif args['align'] == 'center':
self._curString.align = TA_CENTER
elif args['align'] == 'right':
self._curString.align = TA_RIGHT
elif args['align'] == 'justify':
self._curString.align = TA_JUSTIFY
#text comes later within the tag
def end_string(self):
#controller should have set the text
if self._curSlide:
self._curSlide.graphics.append(self._curString)
elif self._curSection:
self._curSection.graphics.append(self._curString)
self._curString = None
def start_infostring(self, args):
# like a string, but lets them embed page no, author etc.
self.start_string(args)
self._curString.hasInfo = 1
def end_infostring(self):
self.end_string()
def start_customshape(self, args):
#loads one
path = self._arg('customshape',args,'path')
if path=='None':
path = []
else:
path=[path]
# add package root folder and input file's folder to path
path.append(os.path.dirname(self.sourceFilename))
path.append(os.path.dirname(pythonpoint.__file__))
modulename = self._arg('customshape',args,'module')
funcname = self._arg('customshape',args,'class')
try:
found = imp.find_module(modulename, path)
(file, pathname, description) = found
mod = imp.load_module(modulename, file, pathname, description)
except ImportError:
mod = getModule(modulename)
#now get the function
func = getattr(mod, funcname)
initargs = self.ceval('customshape',args,'initargs')
self._curCustomShape = apply(func, initargs)
def end_customshape(self):
if self._curSlide:
self._curSlide.graphics.append(self._curCustomShape)
elif self._curSection:
self._curSection.graphics.append(self._curCustomShape)
self._curCustomShape = None
def start_drawing(self, args):
#loads one
moduleName = args["module"]
funcName = args["constructor"]
showBoundary = int(args.get("showBoundary", "0"))
hAlign = args.get("hAlign", "CENTER")
# the path for the imports should include:
# 1. document directory
# 2. python path if baseDir not given, or
# 3. baseDir if given
try:
dirName = sdict["baseDir"]
except:
dirName = None
importPath = [os.getcwd()]
if dirName is None:
importPath.extend(sys.path)
else:
importPath.insert(0, dirName)
modul = recursiveImport(moduleName, baseDir=importPath)
func = getattr(modul, funcName)
drawing = func()
drawing.hAlign = hAlign
if showBoundary:
drawing._showBoundary = 1
self._curDrawing = pythonpoint.PPDrawing()
self._curDrawing.drawing = drawing
def end_drawing(self):
self._curFrame.content.append(self._curDrawing)
self._curDrawing = None
def start_pageCatcherFigure(self, args):
filename = args["filename"]
pageNo = int(args["pageNo"])
width = float(args.get("width", "595"))
height = float(args.get("height", "842"))
fig = figures.PageCatcherFigureNonA4(filename, pageNo, args.get("caption", ""), width, height)
sf = args.get('scaleFactor', None)
if sf: sf = float(sf)
border = not (args.get('border', None) in ['0','no'])
fig.scaleFactor = sf
fig.border = border
#self.ceval('pageCatcherFigure',args,'scaleFactor'),
#initargs = self.ceval('customshape',args,'initargs')
self._curFigure = pythonpoint.PPFigure()
self._curFigure.figure = fig
def end_pageCatcherFigure(self):
self._curFrame.content.append(self._curFigure)
self._curFigure = None
## intra-paragraph XML should be allowed through into PLATYPUS
def unknown_starttag(self, tag, attrs):
if self._curPara:
echo = '<%s' % tag
for (key, value) in attrs.items():
echo = echo + ' %s="%s"' % (key, value)
echo = echo + '>'
self._curPara.rawtext = self._curPara.rawtext + echo
else:
print 'Unknown start tag %s' % tag
def unknown_endtag(self, tag):
if self._curPara:
self._curPara.rawtext = self._curPara.rawtext + '</%s>'% tag
else:
print 'Unknown end tag %s' % tag
def handle_charref(self, name):
try:
if name[0]=='x':
n = int(name[1:],16)
else:
n = int(name)
except ValueError:
self.unknown_charref(name)
return
self.handle_data(unichr(n).encode('utf8'))

View File

@ -0,0 +1,3 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/pythonpoint/styles/__init__.py

View File

@ -0,0 +1,101 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/pythonpoint/styles/horrible.py
__version__=''' $Id: horrible.py 2385 2004-06-17 15:26:05Z rgbecker $ '''
# style_modern.py
__doc__="""This is an example style sheet. You can create your own, and
have them loaded by the presentation. A style sheet is just a
dictionary, where they keys are style names and the values are
ParagraphStyle objects.
You must provide a function called "getParagraphStyles()" to
return it. In future, we can put things like LineStyles,
TableCellStyles etc. in the same modules.
You might wish to have two parallel style sheets, one for colour
and one for black and white, so you can switch your presentations
easily.
A style sheet MUST define a style called 'Normal'.
"""
from reportlab.lib import styles, enums
def getParagraphStyles():
"""Returns a dictionary of styles based on Helvetica"""
stylesheet = {}
para = styles.ParagraphStyle('Normal', None) #the ancestor of all
para.fontName = 'Courier'
para.fontSize = 24
para.leading = 28
stylesheet['Normal'] = para
para = ParagraphStyle('BodyText', stylesheet['Normal'])
para.spaceBefore = 12
stylesheet['BodyText'] = para
para = ParagraphStyle('BigCentered', stylesheet['Normal'])
para.spaceBefore = 12
para.alignment = enums.TA_CENTER
stylesheet['BigCentered'] = para
para = ParagraphStyle('Italic', stylesheet['BodyText'])
para.fontName = 'Courier-Oblique'
stylesheet['Italic'] = para
para = ParagraphStyle('Title', stylesheet['Normal'])
para.fontName = 'Courier'
para.fontSize = 48
para.Leading = 58
para.spaceAfter = 36
para.alignment = enums.TA_CENTER
stylesheet['Title'] = para
para = ParagraphStyle('Heading1', stylesheet['Normal'])
para.fontName = 'Courier-Bold'
para.fontSize = 36
para.leading = 44
para.spaceAfter = 36
para.alignment = enums.TA_CENTER
stylesheet['Heading1'] = para
para = ParagraphStyle('Heading2', stylesheet['Normal'])
para.fontName = 'Courier-Bold'
para.fontSize = 28
para.leading = 34
para.spaceBefore = 24
para.spaceAfter = 12
stylesheet['Heading2'] = para
para = ParagraphStyle('Heading3', stylesheet['Normal'])
para.fontName = 'Courier-BoldOblique'
para.spaceBefore = 24
para.spaceAfter = 12
stylesheet['Heading3'] = para
para = ParagraphStyle('Bullet', stylesheet['Normal'])
para.firstLineIndent = -18
para.leftIndent = 72
para.spaceBefore = 6
#para.bulletFontName = 'Symbol'
para.bulletFontSize = 24
para.bulletIndent = 36
stylesheet['Bullet'] = para
para = ParagraphStyle('Definition', stylesheet['Normal'])
#use this for definition lists
para.firstLineIndent = 0
para.leftIndent = 72
para.bulletIndent = 0
para.spaceBefore = 12
para.bulletFontName = 'Couruer-BoldOblique'
stylesheet['Definition'] = para
para = ParagraphStyle('Code', stylesheet['Normal'])
para.fontName = 'Courier'
para.fontSize = 16
para.leading = 18
para.leftIndent = 36
stylesheet['Code'] = para
return stylesheet

View File

@ -0,0 +1,158 @@
from reportlab.lib import styles
from reportlab.lib import colors
from reportlab.lib.units import cm
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT, TA_JUSTIFY
from reportlab.platypus import Preformatted, Paragraph, Frame, \
Image, Table, TableStyle, Spacer
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
def getParagraphStyles():
"""Returns a dictionary of styles to get you started.
We will provide a way to specify a module of these. Note that
this just includes TableStyles as well as ParagraphStyles for any
tables you wish to use.
"""
pdfmetrics.registerFont(TTFont('Verdana','verdana.ttf'))
pdfmetrics.registerFont(TTFont('Verdana-Bold','verdanab.ttf'))
pdfmetrics.registerFont(TTFont('Verdana-Italic','verdanai.ttf'))
pdfmetrics.registerFont(TTFont('Verdana-BoldItalic','verdanaz.ttf'))
pdfmetrics.registerFont(TTFont('Arial Narrow','arialn.ttf'))
pdfmetrics.registerFont(TTFont('Arial Narrow-Bold','arialnb.ttf'))
pdfmetrics.registerFont(TTFont('Arial Narrow-Italic','arialni.ttf'))
pdfmetrics.registerFont(TTFont('Arial Narrow-BoldItalic','arialnbi.ttf'))
stylesheet = {}
ParagraphStyle = styles.ParagraphStyle
para = ParagraphStyle('Normal', None) #the ancestor of all
para.fontName = 'Verdana'
para.fontSize = 28
para.leading = 32
para.spaceAfter = 6
stylesheet['Normal'] = para
#This one is spaced out a bit...
para = ParagraphStyle('BodyText', stylesheet['Normal'])
para.spaceBefore = 12
stylesheet['BodyText'] = para
#Indented, for lists
para = ParagraphStyle('Indent', stylesheet['Normal'])
para.leftIndent = 60
para.firstLineIndent = 0
stylesheet['Indent'] = para
para = ParagraphStyle('Centered', stylesheet['Normal'])
para.alignment = TA_CENTER
stylesheet['Centered'] = para
para = ParagraphStyle('BigCentered', stylesheet['Normal'])
para.fontSize = 32
para.alignment = TA_CENTER
para.spaceBefore = 12
para.spaceAfter = 12
stylesheet['BigCentered'] = para
para = ParagraphStyle('Italic', stylesheet['BodyText'])
para.fontName = 'Verdana-Italic'
stylesheet['Italic'] = para
para = ParagraphStyle('Title', stylesheet['Normal'])
para.fontName = 'Arial Narrow-Bold'
para.fontSize = 48
para.leading = 58
para.alignment = TA_CENTER
stylesheet['Title'] = para
para = ParagraphStyle('Heading1', stylesheet['Normal'])
para.fontName = 'Arial Narrow-Bold'
para.fontSize = 40
para.leading = 44
para.alignment = TA_CENTER
stylesheet['Heading1'] = para
para = ParagraphStyle('Heading2', stylesheet['Normal'])
para.fontName = 'Verdana'
para.fontSize = 32
para.leading = 36
para.spaceBefore = 32
para.spaceAfter = 12
stylesheet['Heading2'] = para
para = ParagraphStyle('Heading3', stylesheet['Normal'])
para.fontName = 'Verdana'
para.spaceBefore = 20
para.spaceAfter = 6
stylesheet['Heading3'] = para
para = ParagraphStyle('Heading4', stylesheet['Normal'])
para.fontName = 'Verdana-BoldItalic'
para.spaceBefore = 6
stylesheet['Heading4'] = para
para = ParagraphStyle('Bullet', stylesheet['Normal'])
para.firstLineIndent = 0
para.leftIndent = 56
para.spaceBefore = 6
para.bulletFontName = 'Symbol'
para.bulletFontSize = 24
para.bulletIndent = 20
stylesheet['Bullet'] = para
para = ParagraphStyle('Bullet2', stylesheet['Normal'])
para.firstLineIndent = 0
para.leftIndent = 80
para.spaceBefore = 6
para.fontSize = 24
para.bulletFontName = 'Symbol'
para.bulletFontSize = 20
para.bulletIndent = 60
stylesheet['Bullet2'] = para
para = ParagraphStyle('Definition', stylesheet['Normal'])
#use this for definition lists
para.firstLineIndent = 0
para.leftIndent = 60
para.bulletIndent = 0
para.bulletFontName = 'Verdana-BoldItalic'
para.bulletFontSize = 24
stylesheet['Definition'] = para
para = ParagraphStyle('Code', stylesheet['Normal'])
para.fontName = 'Courier'
para.fontSize = 16
para.leading = 18
para.leftIndent = 36
stylesheet['Code'] = para
para = ParagraphStyle('PythonCode', stylesheet['Normal'])
para.fontName = 'Courier'
para.fontSize = 16
para.leading = 18
para.leftIndent = 36
stylesheet['Code'] = para
para = ParagraphStyle('Small', stylesheet['Normal'])
para.fontSize = 12
para.leading = 14
stylesheet['Small'] = para
#now for a table
ts = TableStyle([
('FONT', (0,0), (-1,-1), 'Arial Narrow', 22),
('LINEABOVE', (0,1), (-1,1), 2, colors.green),
('LINEABOVE', (0,2), (-1,-1), 0.25, colors.black),
('LINEBELOW', (0,-1), (-1,-1), 2, colors.green),
('LINEBEFORE', (0,1), (-1,-1), 2, colors.black),
('LINEAFTER', (0,1), (-1,-1), 2, colors.black),
('ALIGN', (4,1), (-1,-1), 'RIGHT'), #all numeric cells right aligned
('TEXTCOLOR', (0,2), (0,-1), colors.black),
('BACKGROUND', (0,1), (-1,1), colors.Color(0,0.7,0.7))
])
stylesheet['table1'] = ts
return stylesheet

View File

@ -0,0 +1,120 @@
#Copyright ReportLab Europe Ltd. 2000-2004
#see license.txt for license details
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/pythonpoint/styles/modern.py
__version__=''' $Id: modern.py 2385 2004-06-17 15:26:05Z rgbecker $ '''
# style_modern.py
__doc__="""This is an example style sheet. You can create your own, and
have them loaded by the presentation. A style sheet is just a
dictionary, where they keys are style names and the values are
ParagraphStyle objects.
You must provide a function called "getParagraphStyles()" to
return it. In future, we can put things like LineStyles,
TableCellStyles etc. in the same modules.
You might wish to have two parallel style sheets, one for colour
and one for black and white, so you can switch your presentations
easily.
A style sheet MUST define a style called 'Normal'.
"""
from reportlab.lib import styles
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT, TA_JUSTIFY
def getParagraphStyles():
"""Returns a dictionary of styles based on Helvetica"""
stylesheet = {}
ParagraphStyle = styles.ParagraphStyle
para = ParagraphStyle('Normal', None) #the ancestor of all
para.fontName = 'Helvetica'
para.fontSize = 24
para.leading = 28
stylesheet['Normal'] = para
para = ParagraphStyle('BodyText', stylesheet['Normal'])
para.spaceBefore = 12
stylesheet['BodyText'] = para
para = ParagraphStyle('Indent', stylesheet['Normal'])
para.leftIndent = 36
para.firstLineIndent = 0
stylesheet['Indent'] = para
para = ParagraphStyle('Centered', stylesheet['Normal'])
para.alignment = TA_CENTER
stylesheet['Centered'] = para
para = ParagraphStyle('BigCentered', stylesheet['Normal'])
para.spaceBefore = 12
para.alignment = TA_CENTER
stylesheet['BigCentered'] = para
para = ParagraphStyle('Italic', stylesheet['BodyText'])
para.fontName = 'Helvetica-Oblique'
stylesheet['Italic'] = para
para = ParagraphStyle('Title', stylesheet['Normal'])
para.fontName = 'Helvetica'
para.fontSize = 48
para.Leading = 58
para.spaceAfter = 36
para.alignment = TA_CENTER
stylesheet['Title'] = para
para = ParagraphStyle('Heading1', stylesheet['Normal'])
para.fontName = 'Helvetica-Bold'
para.fontSize = 36
para.leading = 44
para.spaceAfter = 36
para.alignment = TA_CENTER
stylesheet['Heading1'] = para
para = ParagraphStyle('Heading2', stylesheet['Normal'])
para.fontName = 'Helvetica-Bold'
para.fontSize = 28
para.leading = 34
para.spaceBefore = 24
para.spaceAfter = 12
stylesheet['Heading2'] = para
para = ParagraphStyle('Heading3', stylesheet['Normal'])
para.fontName = 'Helvetica-BoldOblique'
para.spaceBefore = 24
para.spaceAfter = 12
stylesheet['Heading3'] = para
para = ParagraphStyle('Bullet', stylesheet['Normal'])
para.firstLineIndent = -18
para.leftIndent = 72
para.spaceBefore = 6
para.bulletFontName = 'Symbol'
para.bulletFontSize = 24
para.bulletIndent = 36
stylesheet['Bullet'] = para
para = ParagraphStyle('Bullet2', stylesheet['Bullet'])
para.firstLineIndent = 0
para.bulletIndent = 72
para.leftIndent = 108
stylesheet['Bullet2'] = para
para = ParagraphStyle('Definition', stylesheet['Normal'])
#use this for definition lists
para.firstLineIndent = 0
para.leftIndent = 72
para.bulletIndent = 0
para.spaceBefore = 12
para.bulletFontName = 'Helvetica-BoldOblique'
stylesheet['Definition'] = para
para = ParagraphStyle('Code', stylesheet['Normal'])
para.fontName = 'Courier'
para.fontSize = 16
para.leading = 18
para.leftIndent = 36
stylesheet['Code'] = para
return stylesheet

View File

@ -0,0 +1,106 @@
"""This is an example style sheet. You can create your own, and
have them loaded by the presentation. A style sheet is just a
dictionary, where they keys are style names and the values are
ParagraphStyle objects.
You must provide a function called "getParagraphStyles()" to
return it. In future, we can put things like LineStyles,
TableCellStyles etc. in the same modules.
You might wish to have two parallel style sheets, one for colour
and one for black and white, so you can switch your presentations
easily.
A style sheet MUST define a style called 'Normal'.
"""
from reportlab.lib import styles
from reportlab.lib.colors import *
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT, TA_JUSTIFY
def getParagraphStyles():
"""Returns a dictionary of styles based on Helvetica"""
stylesheet = {}
ParagraphStyle = styles.ParagraphStyle
para = ParagraphStyle('Normal', None) #the ancestor of all
para.fontName = 'Helvetica-Bold'
para.fontSize = 24
para.leading = 28
para.textColor = white
stylesheet['Normal'] = para
para = ParagraphStyle('BodyText', stylesheet['Normal'])
para.spaceBefore = 12
stylesheet['BodyText'] = para
para = ParagraphStyle('BigCentered', stylesheet['Normal'])
para.spaceBefore = 12
para.alignment = TA_CENTER
stylesheet['BigCentered'] = para
para = ParagraphStyle('Italic', stylesheet['BodyText'])
para.fontName = 'Helvetica-Oblique'
para.textColor = white
stylesheet['Italic'] = para
para = ParagraphStyle('Title', stylesheet['Normal'])
para.fontName = 'Helvetica'
para.fontSize = 48
para.Leading = 58
para.spaceAfter = 36
para.alignment = TA_CENTER
stylesheet['Title'] = para
para = ParagraphStyle('Heading1', stylesheet['Normal'])
para.fontName = 'Helvetica-Bold'
para.fontSize = 48# 36
para.leading = 44
para.spaceAfter = 36
para.textColor = green
para.alignment = TA_LEFT
stylesheet['Heading1'] = para
para = ParagraphStyle('Heading2', stylesheet['Normal'])
para.fontName = 'Helvetica-Bold'
para.fontSize = 28
para.leading = 34
para.spaceBefore = 24
para.spaceAfter = 12
stylesheet['Heading2'] = para
para = ParagraphStyle('Heading3', stylesheet['Normal'])
para.fontName = 'Helvetica-BoldOblique'
para.spaceBefore = 24
para.spaceAfter = 12
stylesheet['Heading3'] = para
para = ParagraphStyle('Bullet', stylesheet['Normal'])
para.firstLineIndent = -18
para.leftIndent = 72
para.spaceBefore = 6
para.bulletFontName = 'Symbol'
para.bulletFontSize = 24
para.bulletIndent = 36
stylesheet['Bullet'] = para
para = ParagraphStyle('Definition', stylesheet['Normal'])
#use this for definition lists
para.firstLineIndent = 0
para.leftIndent = 72
para.bulletIndent = 0
para.spaceBefore = 12
para.bulletFontName = 'Helvetica-BoldOblique'
stylesheet['Definition'] = para
para = ParagraphStyle('Code', stylesheet['Normal'])
para.fontName = 'Courier-Bold'
para.fontSize = 16
para.leading = 18
para.leftIndent = 36
para.textColor = chartreuse
stylesheet['Code'] = para
return stylesheet

View File

@ -0,0 +1,132 @@
from reportlab.lib import styles
from reportlab.lib import colors
from reportlab.lib.units import cm
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT, TA_JUSTIFY
from reportlab.platypus import Preformatted, Paragraph, Frame, \
Image, Table, TableStyle, Spacer
def getParagraphStyles():
"""Returns a dictionary of styles to get you started.
We will provide a way to specify a module of these. Note that
this just includes TableStyles as well as ParagraphStyles for any
tables you wish to use.
"""
stylesheet = {}
ParagraphStyle = styles.ParagraphStyle
para = ParagraphStyle('Normal', None) #the ancestor of all
para.fontName = 'Times-Roman'
para.fontSize = 24
para.leading = 28
stylesheet['Normal'] = para
#This one is spaced out a bit...
para = ParagraphStyle('BodyText', stylesheet['Normal'])
para.spaceBefore = 12
stylesheet['BodyText'] = para
#Indented, for lists
para = ParagraphStyle('Indent', stylesheet['Normal'])
para.leftIndent = 36
para.firstLineIndent = 0
stylesheet['Indent'] = para
para = ParagraphStyle('Centered', stylesheet['Normal'])
para.alignment = TA_CENTER
stylesheet['Centered'] = para
para = ParagraphStyle('BigCentered', stylesheet['Normal'])
para.spaceBefore = 12
para.alignment = TA_CENTER
stylesheet['BigCentered'] = para
para = ParagraphStyle('Italic', stylesheet['BodyText'])
para.fontName = 'Times-Italic'
stylesheet['Italic'] = para
para = ParagraphStyle('Title', stylesheet['Normal'])
para.fontName = 'Times-Roman'
para.fontSize = 48
para.leading = 58
para.alignment = TA_CENTER
stylesheet['Title'] = para
para = ParagraphStyle('Heading1', stylesheet['Normal'])
para.fontName = 'Times-Bold'
para.fontSize = 36
para.leading = 44
para.alignment = TA_CENTER
stylesheet['Heading1'] = para
para = ParagraphStyle('Heading2', stylesheet['Normal'])
para.fontName = 'Times-Bold'
para.fontSize = 28
para.leading = 34
para.spaceBefore = 24
stylesheet['Heading2'] = para
para = ParagraphStyle('Heading3', stylesheet['Normal'])
para.fontName = 'Times-BoldItalic'
para.spaceBefore = 24
stylesheet['Heading3'] = para
para = ParagraphStyle('Heading4', stylesheet['Normal'])
para.fontName = 'Times-BoldItalic'
para.spaceBefore = 6
stylesheet['Heading4'] = para
para = ParagraphStyle('Bullet', stylesheet['Normal'])
para.firstLineIndent = 0
para.leftIndent = 56
para.spaceBefore = 6
para.bulletFontName = 'Symbol'
para.bulletFontSize = 24
para.bulletIndent = 20
stylesheet['Bullet'] = para
para = ParagraphStyle('Definition', stylesheet['Normal'])
#use this for definition lists
para.firstLineIndent = 0
para.leftIndent = 72
para.bulletIndent = 0
para.spaceBefore = 12
para.bulletFontName = 'Helvetica-BoldOblique'
para.bulletFontSize = 24
stylesheet['Definition'] = para
para = ParagraphStyle('Code', stylesheet['Normal'])
para.fontName = 'Courier'
para.fontSize = 16
para.leading = 18
para.leftIndent = 36
stylesheet['Code'] = para
para = ParagraphStyle('PythonCode', stylesheet['Normal'])
para.fontName = 'Courier'
para.fontSize = 16
para.leading = 18
para.leftIndent = 36
stylesheet['PythonCode'] = para
para = ParagraphStyle('Small', stylesheet['Normal'])
para.fontSize = 12
para.leading = 14
stylesheet['Small'] = para
#now for a table
ts = TableStyle([
('FONT', (0,0), (-1,-1), 'Times-Roman', 24),
('LINEABOVE', (0,0), (-1,0), 2, colors.green),
('LINEABOVE', (0,1), (-1,-1), 0.25, colors.black),
('LINEBELOW', (0,-1), (-1,-1), 2, colors.green),
('LINEBEFORE', (-1,0), (-1,-1), 2, colors.black),
('ALIGN', (1,1), (-1,-1), 'RIGHT'), #all numeric cells right aligned
('TEXTCOLOR', (0,1), (0,-1), colors.red),
('BACKGROUND', (0,0), (-1,0), colors.Color(0,0.7,0.7))
])
stylesheet['table1'] = ts
return stylesheet

View File

@ -0,0 +1,28 @@
#How to add bleed to a page in this case 6mm to a landscape A4
from reportlab.lib import units, pagesizes
from reportlab.pdfgen.canvas import Canvas
import sys, os, glob, time
bleedX = 6*units.mm
bleedY = 6*units.mm
pageWidth, pageHeight = pagesizes.landscape(pagesizes.A4)
def process_pdf(c,infn,prefix='PageForms'):
from rlextra.pageCatcher import pageCatcher
names, data = pageCatcher.storeFormsInMemory(open(infn,'rb').read(),prefix=prefix,all=1)
names = pageCatcher.restoreFormsInMemory(data,c)
del data
for i in xrange(len(names)):
thisname = names[i]
c.saveState()
c.translate(bleedX,bleedY)
c.doForm(thisname)
c.restoreState()
c.showPage()
def main():
for infn in sys.argv[1:]:
outfn = 'bleeding_'+os.path.basename(infn)
c = Canvas(outfn,pagesize=(pageWidth+2*bleedX,pageHeight+2*bleedY))
process_pdf(c,infn)
c.save()
if __name__=='__main__':
main()

View File

@ -0,0 +1,60 @@
__all__=('dumpttf',)
def dumpttf(fn,fontName=None, verbose=0):
'''dump out known glyphs from a ttf file'''
import os
if not os.path.isfile(fn):
raise IOError('No such file "%s"' % fn)
from reportlab.pdfbase.pdfmetrics import registerFont, stringWidth
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen.canvas import Canvas
if fontName is None:
fontName = os.path.splitext(os.path.basename(fn))[0]
dmpfn = '%s-ttf-dump.pdf' % fontName
ttf = TTFont(fontName, fn)
K = ttf.face.charToGlyph.keys()
registerFont(ttf)
c = Canvas(dmpfn)
W,H = c._pagesize
titleFontSize = 30 # title font size
titleFontName = 'Helvetica'
labelFontName = 'Courier'
fontSize = 10
border = 36
dx0 = stringWidth('12345: ', fontName, fontSize)
dx = dx0+20
dy = 20
K.sort()
y = 0
page = 0
for i, k in enumerate(K):
if y<border:
if page: c.showPage()
page += 1
y = H - border - titleFontSize
c.setFont(titleFontName, titleFontSize)
c.drawCentredString(W/2.0,y, 'TrueType Font %s Page %d' %(fontName,page))
y -= 0.2*titleFontSize + dy
x = border
c.setFont(labelFontName, 10)
c.drawString(x,y,'%5.5x:' % k )
c.setFont(fontName, 10)
c.drawString(x+dx0,y,unichr(k).encode('utf8'))
x += dx
if x+dx>W-border:
x = border
y -= dy
c.showPage()
c.save()
if verbose:
print 'Font %s("%s") has %d glyphs\ndumped to "%s"' % (fontName,fn,len(K),dmpfn)
if __name__=='__main__':
import sys, glob
if '--verbose' in sys.argv:
sys.argv.remove('--verbose')
verbose = 1
else:
verbose = 0
for a in sys.argv[1:]:
for fn in glob.glob(a):
dumpttf(fn, verbose=verbose)