Reportlab Userguide PDF

Download as pdf or txt
Download as pdf or txt
You are on page 1of 25
At a glance
Powered by AI
The document discusses the ReportLab PDF Library and its capabilities for generating PDF documents programmatically using Python.

The document discusses different color models including CMYK and how to enforce color space consistency.

Colors in CMYK can be represented by real values between 0 and 1 using CMYKColor or integer values between 0 and 100 using PCMYKColor.

ReportLab PDF Library User Guide

ReportLab Version 2.7 Document generated on 2013/05/07 20:18:53

Thornton House Thornton Road Wimbledon London SW19 4NG, UK

User Guide

Table of contents

Table of contents
Table of contents Chapter 1 Introduction 2 6

1.1 About this document . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.2 What is the ReportLab PDF Library? . . . . . . . . . . . . . . . . . . . 6 1.3 ReportLab's commercial software . . . . . . . . . . . . . . . . . . . . . 7 1.4 What is Python? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.5 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.6 Installation and Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1.7 Getting Involved . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1.8 Site Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1.9 Learning More About Python . . . . . . . . . . . . . . . . . . . . . . . 9 1.10 Goals for the 2.x and 3.x release series . . . . . . . . . . . . . . . . . 9 1.11 What's New in ReportLab 2.7 . . . . . . . . . . . . . . . . . . . . . . . 9

Chapter 2 Graphics and Text with pdfgen

10

2.1 Basic Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.2 More about the Canvas . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.3 Drawing Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.4 The tools: the "draw" operations . . . . . . . . . . . . . . . . . . . . . 12 2.5 The toolbox: the "state change" operations . . . . . . . . . . . . . . . 14 2.6 Other canvas methods. . . . . . . . . . . . . . . . . . . . . . . . . . . 16 2.7 Coordinates (default user space) . . . . . . . . . . . . . . . . . . . . . 16 2.8 Colors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.9 Color space checking . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.10 Color Overprinting . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.11 Standard fonts and text objects . . . . . . . . . . . . . . . . . . . . . 26 2.12 Text object methods . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.13 Paths and Lines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 2.14 Rectangles, circles, ellipses . . . . . . . . . . . . . . . . . . . . . . . 38 2.15 Bezier curves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 2.16 Path object methods . . . . . . . . . . . . . . . . . . . . . . . . . . 41 2.17 Further Reading: The ReportLab Graphics Library . . . . . . . . . . . 46

Chapter 3 Fonts and encodings

47

3.1 Unicode and UTF8 are the default input encodings . . . . . . . . . . . 47


Page 2

User Guide

Table of contents

3.2 Automatic output font substitution . . . . . . . . . . . . . . . . . . . . 47 3.3 Using non-standard Type 1 fonts . . . . . . . . . . . . . . . . . . . . . 48 3.4 Standard Single-Byte Font Encodings . . . . . . . . . . . . . . . . . . 49 3.5 TrueType Font Support . . . . . . . . . . . . . . . . . . . . . . . . . . 51 3.6 Asian Font Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 3.7 RenderPM tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

Chapter 4 Exposing PDF Special Capabilities

54

4.1 Forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 4.2 Links and Destinations . . . . . . . . . . . . . . . . . . . . . . . . . . 54 4.3 Outline Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 4.4 Page Transition Effects . . . . . . . . . . . . . . . . . . . . . . . . . . 56 4.5 Internal File Annotations . . . . . . . . . . . . . . . . . . . . . . . . . 56 4.6 Encryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

Chapter 5 PLATYPUS - Page Layout and Typography Using Scripts

59

5.1 Design Goals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 5.2 Getting started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 5.3 Flowables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 5.4 Guidelines for flowable positioning . . . . . . . . . . . . . . . . . . . . 61 5.5 Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 5.6 Documents and Templates . . . . . . . . . . . . . . . . . . . . . . . . 63

Chapter 6 Paragraphs
6.1 Using Paragraph Styles

66
. . . . . . . . . . . . . . . . . . . . . . . . . 66

6.2 Paragraph XML Markup Tags . . . . . . . . . . . . . . . . . . . . . . 70 6.3 Intra-paragraph markup . . . . . . . . . . . . . . . . . . . . . . . . . 70 6.4 Bullets and Paragraph Numbering . . . . . . . . . . . . . . . . . . . . 73

Chapter 7 Tables and TableStyles

75

7.1 Table User Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 7.2 TableStyle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 7.3 TableStyle User Methods . . . . . . . . . . . . . . . . . . . . . . . . . 76 7.4 TableStyle Commands . . . . . . . . . . . . . . . . . . . . . . . . . . 76

Chapter 8 Programming Flowables

81

8.1 DocAssign(self, var, expr, life='forever') . . . . . . . . . . . . . . . . . 81 8.2 DocExec(self, stmt, lifetime='forever') . . . . . . . . . . . . . . . . . . 81

Page 3

User Guide

Table of contents

8.3 DocPara(self, expr, format=None, style=None, klass=None, escape=True)81 8.4 DocAssert(self, cond, format=None) . . . . . . . . . . . . . . . . . . . 81 8.5 DocIf(self, cond, thenBlock, elseBlock=[]) . . . . . . . . . . . . . . . . 81 8.6 DocWhile(self, cond, whileBlock) . . . . . . . . . . . . . . . . . . . . . 81

Chapter 9 Other Useful Flowables

82

9.1 Preformatted(text, style, bulletText=None, dedent=0, maxLineLength=None, splitChars=None, newLineChars=None) . . . . 82 9.2 XPreformatted(text, style, bulletText=None, dedent=0, frags=None) . . 82 9.3 Image(filename, width=None, height=None) . . . . . . . . . . . . . . . 83 9.4 Spacer(width, height) . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 9.5 PageBreak() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 9.6 CondPageBreak(height) . . . . . . . . . . . . . . . . . . . . . . . . . 84 9.7 KeepTogether(flowables) . . . . . . . . . . . . . . . . . . . . . . . . . 84 9.8 TableOfContents() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 9.9 SimpleIndex() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 9.10 ListFlowable(),ListItem() . . . . . . . . . . . . . . . . . . . . . . . . . 86

Chapter 10 Writing your own Flowable Objects

88

10.1 A very simple Flowable . . . . . . . . . . . . . . . . . . . . . . . . . 88 10.2 Modifying a Built in Flowable . . . . . . . . . . . . . . . . . . . . . . 89

Chapter 11 Graphics

91

11.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 11.2 General Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 11.3 Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 11.4 Labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 11.5 Axes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 11.6 Bar Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 11.7 Line Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 11.8 Line Plots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 11.9 Pie Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 11.10 Legends . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 11.11 Shapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 11.12 Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

Appendix A ReportLab Demos

123

A.1 Odyssey . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 A.2 Standard Fonts and Colors . . . . . . . . . . . . . . . . . . . . . . . 123


Page 4

User Guide

Table of contents

A.3 Py2pdf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 A.4 Gadflypaper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 A.5 Pythonpoint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

Page 5

User Guide

Chapter 1 Introduction

Chapter 1 Introduction
1.1 About this document
This document is an introduction to the ReportLab PDF library. Some previous programming experience is presumed and familiarity with the Python Programming language is recommended. If you are new to Python, we tell you in the next section where to go for orientation. This manual does not cover 100% of the features, but should explain all the main concepts and help you get started, and point you at other learning resources. After working your way through this, you should be ready to begin writing programs to produce sophisticated reports. In this chapter, we will cover the groundwork: What is ReportLab all about, and why should I use it? What is Python? How do I get everything set up and running? We need your help to make sure this manual is complete and helpful. Please send any feedback to our user mailing list, which is signposted from www.reportlab.com.

1.2 What is the ReportLab PDF Library?


This is a software library that lets you directly create documents in Adobe's Portable Document Format (PDF) using the Python programming language. It also creates charts and data graphics in various bitmap and vector formats as well as PDF. PDF is the global standard for electronic documents. It supports high-quality printing yet is totally portable across platforms, thanks to the freely available Acrobat Reader. Any application which previously generated hard copy reports or driving a printer can benefit from making PDF documents instead; these can be archived, emailed, placed on the web, or printed out the old-fashioned way. However, the PDF file format is a complex indexed binary format which is impossible to type directly. The PDF format specification is more than 600 pages long and PDF files must provide precise byte offsets -- a single extra character placed anywhere in a valid PDF document can render it invalid. This makes it harder to generate than HTML. Most of the world's PDF documents have been produced by Adobe's Acrobat tools, or rivals such as JAWS PDF Creator, which act as 'print drivers'. Anyone wanting to automate PDF production would typically use a product like Quark, Word or Framemaker running in a loop with macros or plugins, connected to Acrobat. Pipelines of several languages and products can be slow and somewhat unwieldy. The ReportLab library directly creates PDF based on your graphics commands. There are no intervening steps. Your applications can generate reports extremely fast - sometimes orders of magnitude faster than traditional report-writing tools. This approach is shared by several other libraries - PDFlib for C, iText for Java, iTextSharp for .NET and others. However, The ReportLab library differs in that it can work at much higher levels, with a full featured engine for laying out documents complete with tables and charts. In addition, because you are writing a program in a powerful general purpose language, there are no restrictions at all on where you get your data from, how you transform it, and the kind of output you can create. And you can reuse code across whole families of reports. The ReportLab library is expected to be useful in at least the following contexts: Dynamic PDF generation on the web High-volume corporate reporting and database publishing An embeddable print engine for other applications, including a 'report language' so that users can customize their own reports. This is particularly relevant to cross-platform apps which cannot rely on a consistent printing or previewing API on each operating system. A 'build system' for complex documents with charts, tables and text such as management accounts, statistical reports and scientific papers Going from XML to PDF in one step

Page 6

User Guide

Chapter 1 Introduction

1.3 ReportLab's commercial software


The ReportLab library forms the foundation of our commercial solution for PDF generation, Report Markup Language (RML). This is available for evaluation on our web site with full documentation. We believe that RML is the fastest and easiest way to develop rich PDF workflows. You work in a markup language at a similar level to HTML, using your favorite templating system to populate an RML document; then call our rml2pdf API function to generate a PDF. It's what ReportLab staff use to build all of the solutions you can see on reportlab.com. Key differences: Fully documented with two manuals, a formal specification (the DTD) and extensive self-documenting tests. (By contrast, we try to make sure the open source documentation isn't wrong, but we don't always keep up with the code) Work in high-level markup rather than constructing graphs of Python objects Requires no Python expertise - your colleagues may thank you after you've left!' Support for vector graphics and inclusion of other PDF documents Many more useful features expressed with a single tag, which would need a lot of coding in the open source package Commercial support is included We ask open source developers to consider trying out RML where it is appropriate. You can register on our site and try out a copy before buying. The costs are reasonable and linked to the volume of the project, and the revenue helps us spend more time developing this software.

1.4 What is Python?


Python is an interpreted, interactive, object-oriented programming language. It is often compared to Tcl, Perl, Scheme or Java. Python combines remarkable power with very clear syntax. It has modules, classes, exceptions, very high level dynamic data types, and dynamic typing. There are interfaces to many system calls and libraries, as well as to various windowing systems (X11, Motif, Tk, Mac, MFC). New built-in modules are easily written in C or C++. Python is also usable as an extension language for applications that need a programmable interface. Python is as old as Java and has been growing steadily in popularity for years; since our library first came out it has entered the mainstream. Many ReportLab library users are already Python devotees, but if you are not, we feel that the language is an excellent choice for document-generation apps because of its expressiveness and ability to get data from anywhere. Python is copyrighted but freely usable and distributable, even for commercial use.

1.5 Acknowledgements
Many people have contributed to ReportLab. We would like to thank in particular (in alphabetical order): Albertas Agejevas, Alex Buck, Andre Reitz, Andrew Mercer, Benjamin Dumke, Benn B, Chad Miller, Chris Lee, Christian Jacobs, Dinu Gherman, Eric Johnson, Felix Labrecque, Gary Poster, Germn M. Bravo, Guillaume Francois, Hans Brand, Henning Vonbargen, Hosam Aly, Ian Stevens, James Martin-Collar, Jeff Bauer, Jerome Alet, Jerry Casiano, Jorge Godoy, Keven D Smith, Magnus Lie Hetland, Marcel Tromp, Ty Sarna Marius Gedminas, Max M, Michael Egorov, Mike Folwell, Moshe Wagner, Nate Silva, Paul McNett, Peter Johnson, PJACock, Publio da Costa Melo, Randolph Bentson, Robert Alsina, Robert Hlzl, Robert Kern, Ron Peleg, Simon King, Steve Halasz, T Blatter, Tim Roberts, Tomasz Swiderski, Volker Haas, Yoann Roman, and many more. Special thanks go to Just van Rossum for his valuable assistance with font technicalities. Moshe Wagner and Hosam Aly deserve a huge thanks for contributing to the RTL patch, which is not yet on thr trunk. Marius Gedminas deserves a big hand for contributing the work on TrueType fonts and we are glad to include these in the toolkit. Finally we thank Michal Kosmulski for the DarkGarden font for and Bitstream Inc. for the Vera fonts.

Page 7

User Guide

Chapter 1 Introduction

1.6 Installation and Setup


To avoid duplication, the installation instructions are kept in the README file in our distribution, which can be viewed online at http://bitbucket.org/rptlab/reportlab/ This release (2.7) of ReportLab requires Python versions 2.5, 2.6 or 2.7. We will be maintaining a 2.7.x branch for essential bug fixes, but after this release the focus of our development will shift to dual support for Python 2.7 and 3.3+. We advise everyone who can to move to Python 2.7.

1.7 Getting Involved


ReportLab is an Open Source project. Although we are a commercial company we provide the core PDF generation sources freely, even for commercial purposes, and we make no income directly from these modules. We also welcome help from the community as much as any other Open Source project. There are many ways in which you can help: General feedback on the core API. Does it work for you? Are there any rough edges? Does anything feel clunky and awkward? New objects to put in reports, or useful utilities for the library. We have an open standard for report objects, so if you have written a nice chart or table class, why not contribute it? Snippets and Case Studies: If you have produced some nice output, register online on http://www.reportlab.com and submit a snippet of your output (with or without scripts). If ReportLab solved a problem for you at work, write a little 'case study' and submit it. And if your web site uses our tools to make reports, let us link to it. We will be happy to display your work (and credit it with your name and company) on our site! Working on the core code: we have a long list of things to refine or to implement. If you are missing some features or just want to help out, let us know! The first step for anyone wanting to learn more or get involved is to join the mailing list. To Subscribe visit http://two.pairlist.net/mailman/listinfo/reportlab-users. From there you can also browse through the group's archives and contributions. The mailing list is the place to report bugs and get support. The code now lives on BitBucket (http://bitbucket.org/rptlab/reportlab/) in a Mercurial repository, along with an issue tracker and wiki. Everyone should feel free to contribute, but if you are working actively on some improvements or want to draw attention to an issue, please use the mailing list to let us know.

1.8 Site Configuration


There are a number of options which most likely need to be configured globally for a site. The python script module reportlab/rl_config.py may be edited to change the values of several important sitewide properties. verbose: set to integer values to control diagnostic output. shapeChecking: set this to zero to turn off a lot of error checking in the graphics modules defaultEncoding: set this to WinAnsiEncoding or MacRomanEncoding. defaultPageSize: set this to one of the values defined in reportlab/lib/pagesizes.py; as delivered it is set to pagesizes.A4; other values are pagesizes.letter etc. defaultImageCaching: set to zero to inhibit the creation of .a85 files on your hard-drive. The default is to create these preprocessed PDF compatible image files for faster loading T1SearchPath: this is a python list of strings representing directories that may be queried for information on Type 1 fonts TTFSearchPath: this is a python list of strings representing directories that may be queried for information on TrueType fonts CMapSearchPath: this is a python list of strings representing directories that may be queried for information on font code maps. showBoundary: set to non-zero to get boundary lines drawn. ZLIB_WARNINGS: set to non-zero to get warnings if the Python compression extension is not found.

Page 8

User Guide

Chapter 1 Introduction

pageComression: set to non-zero to try and get compressed PDF. allowtableBoundsErrors: set to 0 to force an error on very large Platypus table elements emptyTableAction: Controls behaviour for empty tables, can be 'error' (default), 'indicate' or 'ignore'.

1.9 Learning More About Python


If you are a total beginner to Python, you should check out one or more from the growing number of resources on Python programming. The following are freely available on the web: Python Documentation. A list of documentation on the Python.org web site. http://www.python.org/doc/ Python Tutorial. The official Python Tutorial , originally written by Guido van Rossum himself. http://docs.python.org/tutorial/ Learning to Program. A tutorial on programming by Alan Gauld. Has a heavy emphasis on Python, but also uses other languages. http://www.freenetpages.co.uk/hp/alan.gauld/ Instant Python. A 6-page minimal crash course by Magnus Lie Hetland. http://www.hetland.org/python/instant-python.php Dive Into Python. A free Python tutorial for experienced programmers. http://www.diveintopython.net/

1.10 Goals for the 2.x and 3.x release series


The main rationale for 2.0 was an incompatible change at the character level: to properly support Unicode input. Since then, we have tried to maintain backward compatibility up to this version 2.7 One main area where we have tried to make progress from release to release is with documentation and installability. We now offer full support for distutils, setuptools, pip and so on. Immediately after this release, we will be shifting focus to work on compatibility with both Python 2.7 and 3.3+, and starting to make larger changes to the ReportLab Toolkit to bring it up to date - using more modern Python libraries, supporting newer PDF features and more. The next ReportLab release is likely to be numbered 3.0. Inevitability this modernisation will need some changes to applications, although we do not plan to needlessly change APIs.

1.11 What's New in ReportLab 2.7


This is a minor release to collect a small number of bug fixes since the last release at end of September 2012. Detailed release notes are available at http://www.reportlab.com/software/documentation/relnotes/27/

Page 9

User Guide

Chapter 2 Graphics and Text with pdfgen

Chapter 2 Graphics and Text with pdfgen


2.1 Basic Concepts
The pdfgen package is the lowest level interface for generating PDF documents. A pdfgen program is essentially a sequence of instructions for "painting" a document onto a sequence of pages. The interface object which provides the painting operations is the pdfgen canvas. The canvas should be thought of as a sheet of white paper with points on the sheet identified using Cartesian (X,Y) coordinates which by default have the (0,0) origin point at the lower left corner of the page. Furthermore the first coordinate x goes to the right and the second coordinate y goes up, by default. A simple example program that uses a canvas follows.
from reportlab.pdfgen import canvas def hello(c): c.drawString(100,100,"Hello World") c = canvas.Canvas("hello.pdf") hello(c) c.showPage() c.save()

The above code creates a canvas object which will generate a PDF file named hello.pdf in the current working directory. It then calls the hello function passing the canvas as an argument. Finally the showPage method saves the current page of the canvas and the save method stores the file and closes the canvas. The showPage method causes the canvas to stop drawing on the current page and any further operations will draw on a subsequent page (if there are any further operations -- if not no new page is created). The save method must be called after the construction of the document is complete -- it generates the PDF document, which is the whole purpose of the canvas object.

2.2 More about the Canvas


Before describing the drawing operations, we will digress to cover some of the things which can be done to configure a canvas. There are many different settings available. If you are new to Python or can't wait to produce some output, you can skip ahead, but come back later and read this! First of all, we will look at the constructor arguments for the canvas:
def __init__(self,filename, pagesize=(595.27,841.89), bottomup = 1, pageCompression=0, encoding=rl_config.defaultEncoding, verbosity=0 encrypt=None):

The filename argument controls the name of the final PDF file. You may also pass in any open file object (such as sys.stdout, the python process standard output) and the PDF document will be written to that. Since PDF is a binary format, you should take care when writing other stuff before or after it; you can't deliver PDF documents inline in the middle of an HTML page! The pagesize argument is a tuple of two numbers in points (1/72 of an inch). The canvas defaults to A4 (an international standard page size which differs from the American standard page size of letter), but it is better to explicitly specify it. Most common page sizes are found in the library module reportlab.lib.pagesizes, so you can use expressions like
from reportlab.lib.pagesizes import letter, A4 myCanvas = Canvas('myfile.pdf', pagesize=letter) width, height = letter #keep for later

NOTE

Page 10

User Guide

Chapter 2 Graphics and Text with pdfgen

If you have problems printing your document make sure you are using the right page size (usually either A4 or letter). Some printers do not work well with pages that are too large or too small. Very often, you will want to calculate things based on the page size. In the example above we extracted the width and height. Later in the program we may use the width variable to define a right margin as width - inch rather than using a constant. By using variables the margin will still make sense even if the page size changes. The bottomup argument switches coordinate systems. Some graphics systems (like PDF and PostScript) place (0,0) at the bottom left of the page others (like many graphical user interfaces [GUI's]) place the origen at the top left. The bottomup argument is deprecated and may be dropped in future Need to see if it really works for all tasks, and if not then get rid of it The pageCompression option determines whether the stream of PDF operations for each page is compressed. By default page streams are not compressed, because the compression slows the file generation process. If output size is important set pageCompression=1, but remember that, compressed documents will be smaller, but slower to generate. Note that images are always compressed, and this option will only save space if you have a very large amount of text and vector graphics on each page. The encoding argument is largely obsolete in version 2.0 and can probably be omitted by 99% of users. Its default value is fine unless you very specifically need to use one of the 25 or so characters which are present in MacRoman and not in Winansi. A useful reference to these is here: http://www.alanwood.net/demos/charsetdiffs.html. The parameter determines which font encoding is used for the standard Type 1 fonts; this should correspond to the encoding on your system. Note that this is the encoding used internally by the font; text you pass to the ReportLab toolkit for rendering should always either be a Python unicode string object or a UTF-8 encoded byte string (see the next chapter)! The font encoding has two values at present: 'WinAnsiEncoding' or 'MacRomanEncoding'. The variable rl_config.defaultEncoding above points to the former, which is standard on Windows, Mac OS X and many Unices (including Linux). If you are Mac user and don't have OS X, you may want to make a global change: modify the line at the top of reportlab/pdfbase/pdfdoc.py to switch it over. Otherwise, you can probably just ignore this argument completely and never pass it. For all TTF and the commonly-used CID fonts, the encoding you pass in here is ignored, since the reportlab library itself knows the right encodings in those cases. The demo script reportlab/demos/stdfonts.py will print out two test documents showing all code points in all fonts, so you can look up characters. Special characters can be inserted into string commands with the usual Python escape sequences; for example \101 = 'A'. The verbosity argument determines how much log information is printed. By default, it is zero to assist applications which want to capture PDF from standard output. With a value of 1, you will get a confirmation message each time a document is generated. Higher numbers may give more output in future. The encrypt argument determines if and how the document is encrypted. By default, the document is not encrypted. If encrypt is a string object, it is used as the user password for the pdf. If encrypt is an instance of reportlab.lib.pdfencrypt.StandardEncryption, this object is used to encrypt the pdf. This allows more finegrained control over the encryption settings. Encryption is covered in more detail in Chapter 4. to do - all the info functions and other non-drawing stuff Cover all constructor arguments, and setAuthor etc.

2.3 Drawing Operations


Suppose the hello function referenced above is implemented as follows (we will not explain each of the operations in detail yet).
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

Page 11

User Guide

Chapter 2 Graphics and Text with pdfgen

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")

Examining this code notice that there are essentially two types of operations performed using a canvas. The first type draws something on the page such as a text string or a rectangle or a line. The second type changes the state of the canvas such as changing the current fill or stroke color or changing the current font type and size. If we imagine the program as a painter working on the canvas the "draw" operations apply paint to the canvas using the current set of tools (colors, line styles, fonts, etcetera) and the "state change" operations change one of the current tools (changing the fill color from whatever it was to blue, or changing the current font to Times-Roman in 15 points, for example). The document generated by the "hello world" program listed above would contain the following graphics.

Figure 2-1: "Hello World" in pdfgen About the demos in this document
This document contains demonstrations of the code discussed like the one shown in the rectangle above. These demos are drawn on a "tiny page" embedded within the real pages of the guide. The tiny pages are 5.5 inches wide and 3 inches tall. The demo displays show the actual output of the demo code. For convenience the size of the output has been reduced slightly.

2.4 The tools: the "draw" operations


This section briefly lists the tools available to the program for painting information onto a page using the canvas interface. These will be discussed in detail in later sections. They are listed here for easy reference and for summary purposes.

Hello World

Page 12

User Guide

Chapter 2 Graphics and Text with pdfgen

Line methods
canvas.line(x1,y1,x2,y2) canvas.lines(linelist)

The line methods draw straight line segments on the canvas.

Shape methods
canvas.grid(xlist, ylist) canvas.bezier(x1, y1, x2, y2, x3, y3, x4, y4) canvas.arc(x1,y1,x2,y2) canvas.rect(x, y, width, height, stroke=1, fill=0) canvas.ellipse(x1,y1, x2,y2, stroke=1, fill=0) canvas.wedge(x1,y1, x2,y2, startAng, extent, stroke=1, fill=0) canvas.circle(x_cen, y_cen, r, stroke=1, fill=0) canvas.roundRect(x, y, width, height, radius, stroke=1, fill=0)

The shape methods draw common complex shapes on the canvas.

String drawing methods


canvas.drawString(x, y, text): canvas.drawRightString(x, y, text) canvas.drawCentredString(x, y, text)

The draw string methods draw single lines of text on the canvas.

The text object methods


textobject = canvas.beginText(x, y) canvas.drawText(textobject)

Text objects are used to format text in ways that are not supported directly by the canvas interface. A program creates a text object from the canvas using beginText and then formats text by invoking textobject methods. Finally the textobject is drawn onto the canvas using drawText.

The path object methods


path = canvas.beginPath() canvas.drawPath(path, stroke=1, fill=0) canvas.clipPath(path, stroke=1, fill=0)

Path objects are similar to text objects: they provide dedicated control for performing complex graphical drawing not directly provided by the canvas interface. A program creates a path object using beginPath populates the path with graphics using the methods of the path object and then draws the path on the canvas Page 13

User Guide

Chapter 2 Graphics and Text with pdfgen

using drawPath. It is also possible to use a path as a "clipping region" using the clipPath method -- for example a circular path can be used to clip away the outer parts of a rectangular image leaving only a circular part of the image visible on the page.

Image methods
You need the Python Imaging Library (PIL) to use images with the ReportLab package. Examnples of the techniques below can be found by running the script test_pdfgen_general.py in our tests subdirectory and looking at page 7 of the output. There are two similar-sounding ways to draw images. The preferred one is the drawImage method. This implements a caching system so you can define an image once and draw it many times; it will only be stored once in the PDF file. drawImage also exposes one advanced parameter, a transparency mask, and will expose more in future. The older technique, drawInlineImage, stores bitmaps within the page stream and is thus very inefficient if you use the same image more than once in a document; but can result in PDFs which render faster if the images are very small and not repeated. We'll discuss the oldest one first:
canvas.drawInlineImage(self, image, x,y, width=None,height=None)

NOTE NOTE

The drawInlineImage method places an image on the canvas. The image parameter may be either a PIL Image object or an image filename. Many common file formats are accepted including GIF and JPEG. It returns the size of the actual image in pixels as a (width, height) tuple.
canvas.drawImage(self, image, x,y, width=None,height=None,mask=None)

The arguments and return value work as for drawInlineImage. However, we use a caching system; a given image will only be stored the first time it is used, and just referenced on subsequent use. If you supply a filename, it assumes that the same filename means the same image. If you supply a PIL image, it tests if the content has actually changed before re-embedding. The mask parameter lets you create transparent images. It takes 6 numbers and defines the range of RGB values which will be masked out or treated as transparent. For example with [0,2,40,42,136,139], it will mask out any pixels with a Red value from 0 or 1, Green from 40 or 41 and Blue of 136, 137 or 138 (on a scale of 0-255). It's currently your job to know which color is the 'transparent' or background one. PDF allows for many image features and we will expose more of the over time, probably with extra keyword arguments to drawImage.

Ending a page
canvas.showPage()

The showPage method finishes the current page. All additional drawing will be done on another page. Warning! All state changes (font changes, color settings, geometry transforms, etcetera) are FORGOTTEN when you advance to a new page in pdfgen. Any state settings you wish to preserve must be set up again before the program proceeds with drawing!

2.5 The toolbox: the "state change" operations


This section briefly lists the ways to switch the tools used by the program for painting information onto a page using the canvas interface. These too will be discussed in detail in later sections.

Page 14

User Guide

Chapter 2 Graphics and Text with pdfgen

Changing Colors
canvas.setFillColorCMYK(c, m, y, k) canvas.setStrikeColorCMYK(c, m, y, k) canvas.setFillColorRGB(r, g, b) canvas.setStrokeColorRGB(r, g, b) canvas.setFillColor(acolor) canvas.setStrokeColor(acolor) canvas.setFillGray(gray) canvas.setStrokeGray(gray)

PDF supports three different color models: gray level, additive (red/green/blue or RGB), and subtractive with darkness parameter (cyan/magenta/yellow/darkness or CMYK). The ReportLab packages also provide named colors such as lawngreen. There are two basic color parameters in the graphics state: the Fill color for the interior of graphic figures and the Stroke color for the boundary of graphic figures. The above methods support setting the fill or stroke color using any of the four color specifications.

Changing Fonts
canvas.setFont(psfontname, size, leading = None)

The setFont method changes the current text font to a given type and size. The leading parameter specifies the distance down to move when advancing from one text line to the next.

Changing Graphical Line Styles


canvas.setLineWidth(width) canvas.setLineCap(mode) canvas.setLineJoin(mode) canvas.setMiterLimit(limit) canvas.setDash(self, array=[], phase=0)

Lines drawn in PDF can be presented in a number of graphical styles. Lines can have different widths, they can end in differing cap styles, they can meet in different join styles, and they can be continuous or they can be dotted or dashed. The above methods adjust these various parameters.

Changing Geometry
canvas.setPageSize(pair) canvas.transform(a,b,c,d,e,f): canvas.translate(dx, dy) canvas.scale(x, y) canvas.rotate(theta)

Page 15

User Guide

Chapter 2 Graphics and Text with pdfgen

canvas.skew(alpha, beta)

All PDF drawings fit into a specified page size. Elements drawn outside of the specified page size are not visible. Furthermore all drawn elements are passed through an affine transformation which may adjust their location and/or distort their appearence. The setPageSize method adjusts the current page size. The transform, translate, scale, rotate, and skew methods add additional transformations to the current transformation. It is important to remember that these transformations are incremental -- a new transform modifies the current transform (but does not replace it).

State control
canvas.saveState() canvas.restoreState()

Very often it is important to save the current font, graphics transform, line styles and other graphics state in order to restore them later. The saveState method marks the current graphics state for later restoration by a matching restoreState. Note that the save and restore method invokation must match -- a restore call restores the state to the most recently saved state which hasn't been restored yet. You cannot save the state on one page and restore it on the next, however -- no state is preserved between pages.

2.6 Other canvas methods.


Not all methods of the canvas object fit into the "tool" or "toolbox" categories. Below are some of the misfits, included here for completeness.
canvas.setAuthor() canvas.addOutlineEntry(title, key, level=0, closed=None) canvas.setTitle(title) canvas.setSubject(subj) canvas.pageHasData() canvas.showOutline() canvas.bookmarkPage(name) canvas.bookmarkHorizontalAbsolute(name, yhorizontal) canvas.doForm() canvas.beginForm(name, lowerx=0, lowery=0, upperx=None, uppery=None) canvas.endForm() canvas.linkAbsolute(contents, destinationname, Rect=None, addtopage=1, name=None, **kw) canvas.linkRect(contents, destinationname, Rect=None, addtopage=1, relative=1, name=None, **kw) canvas.getPageNumber() canvas.addLiteral() canvas.getAvailableFonts() canvas.stringWidth(self, text, fontName, fontSize, encoding=None) canvas.setPageCompression(onoff=1) canvas.setPageTransition(self, effectname=None, duration=1, direction=0,dimension='H',motion='I')

2.7 Coordinates (default user space)


By default locations on a page are identified by a pair of numbers. For example the pair (4.5*inch, 1*inch) identifies the location found on the page by starting at the lower left corner and moving to the right 4.5 inches and up one inch. For example, the following function draws a number of elements on a canvas.
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)

Page 16

User Guide

Chapter 2 Graphics and Text with pdfgen

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)

In the default user space the "origin" (0,0) point is at the lower left corner. Executing the coords function in the default user space (for the "demo minipage") we obtain the following.

(4, 2.5)

(2.5,1) in inches

(0,0) the Origin


Figure 2-2: The Coordinate System Moving the origin: the translate method
Often it is useful to "move the origin" to a new point off the lower left corner. The canvas.translate(x,y) method moves the origin for the current page to the point currently identified by (x,y). For example the following translate function first moves the origin before drawing the same objects as shown above.
def translate(canvas): from reportlab.lib.units import cm canvas.translate(2.3*cm, 0.3*cm) coords(canvas)

This produces the following.

Page 17

User Guide

Chapter 2 Graphics and Text with pdfgen

(4, 2.5)

(2.5,1) in inches

(0,0) the Origin


Figure 2-3: Moving the origin: the translate method

Note: As illustrated in the example it is perfectly possible to draw objects or parts of objects "off the page". In particular a common confusing bug is a translation operation that translates the entire drawing off the visible area of the page. If a program produces a blank page it is possible that all the drawn objects are off the page.

NOTE

Shrinking and growing: the scale operation


Another important operation is scaling. The scaling operation canvas.scale(dx,dy) stretches or shrinks the x and y dimensions by the dx, dy factors respectively. Often dx and dy are the same -- for example to reduce a drawing by half in all dimensions use dx = dy = 0.5. However for the purposes of illustration we show an example where dx and dy are different.
def scale(canvas): canvas.scale(0.75, 0.5) coords(canvas)

This produces a "short and fat" reduced version of the previously displayed operations.

Page 18

User Guide

Chapter 2 Graphics and Text with pdfgen

(4, 2.5)

(2.5,1) in inches

(0,0) the Origin

Figure 2-4: Scaling the coordinate system

Note: scaling may also move objects or parts of objects off the page, or may cause objects to "shrink to nothing." Scaling and translation can be combined, but the order of the operations are important.
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)

NOTE

This example function first saves the current canvas state and then does a scale followed by a translate. Afterward the function restores the state (effectively removing the effects of the scaling and translation) and then does the same operations in a different order. Observe the effect below.

Page 19

User Guide

Chapter 2 Graphics and Text with pdfgen

Translate then scale

(4, 2.5)

Scale then translate

(4, 2.5)

(2.5,1) in inches

(0,0) the Origin (2.5,1) in inches

(0,0) the Origin

Figure 2-5: Scaling and Translating

Note: scaling shrinks or grows everything including line widths so using the canvas.scale method to render a microscopic drawing in scaled microscopic units may produce a blob (because all line widths will get expanded a huge amount). Also rendering an aircraft wing in meters scaled to centimeters may cause the lines to shrink to the point where they disappear. For engineering or scientific purposes such as these scale and translate the units externally before rendering them using the canvas.

NOTE

Saving and restoring the canvas state: saveState and restoreState


The scaletranslate function used an important feature of the canvas object: the ability to save and restore the current parameters of the canvas. By enclosing a sequence of operations in a matching pair of canvas.saveState() an canvas.restoreState() operations all changes of font, color, line style, scaling, translation, or other aspects of the canvas graphics state can be restored to the state at the point of the saveState(). Remember that the save/restore calls must match: a stray save or restore operation may cause unexpected and undesirable behavior. Also, remember that no canvas state is preserved across page breaks, and the save/restore mechanism does not work across page breaks.

Mirror image
It is interesting although perhaps not terribly useful to note that scale factors can be negative. For example the following function
def mirror(canvas): from reportlab.lib.units import inch canvas.translate(5.5*inch, 0) canvas.scale(-1.0, 1.0) coords(canvas)

creates a mirror image of the elements drawn by the coord function.

Page 20

User Guide

Chapter 2 Graphics and Text with pdfgen

)5.2 ,4(

sehcni ni )1,5.2(

nigirO eht )0,0(


Figure 2-6: Mirror Images
Notice that the text strings are painted backwards.

2.8 Colors
There are generally two types of colors used in PDF depending on the media where the PDF will be used. The most commonly known screen colors model RGB can be used in PDF, however in professional printing another color model CMYK is mainly used which gives more control over how inks are applied to paper. More on these color models below.

RGB Colors
The RGB or additive color representation follows the way a computer screen adds different levels of the red, green, and blue light to make any color in between, where white is formed by turning all three lights on full (1,1,1). There are three ways to specify RGB colors in pdfgen: by name (using the color module, by red/green/blue (additive, RGB) value, or by gray level. The colors function below exercises each of the four methods.
def colorsRGB(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)

Page 21

User Guide

Chapter 2 Graphics and Text with pdfgen

canvas.drawCentredString(x+dx/2, y+texty, "r%s g%s b%s"%rgb) 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

gray: 0.0

gray: 0.25

gray: 0.5

gray: 0.75

gray: 1.0

r1 g0 b0

r0 g1 b0

r0 g0 b1

r0.5 g0.3 b0.1

r0.4 g0.5 b0.3

lavenderblush

lawngreen

lemonchiffon

lightblue

lightcoral

Figure 2-7: RGB Color Models


RGB Color Transparency Objects may be painted over other objects to good effect in pdfgen. Generally There are two modes of handling objects that overlap in space, the default objects in the top layer will hide any part of other objects that falls underneath it. If you need transparency you got two choices: 1. If your document is intended to be printed in a professional way and you are working in CMYK color space then you can use overPrint. In overPrinting the colors physically mix in the printer and thus a new color is obtained. By default a knockout will be applied and only top object appears. Read the CMYK section if this is what you intend to use. 2. If your document is intended for screen output and you are using RGB colors then you can set an alpha value, where alpha is the opacity value of the color. The default alpha value is 1 (fully opaque) and you can use any real number value in the range 0-1. Alpha transparency (alpha) is similar to overprint but works in RGB color space this example below demonstrates the alpha funtionality. Refer to our website http://www.reportlab.com/snippets/ and look for snippets of overPrint and alpha to see the code that generates the graph below.
def alpha(canvas): from reportlab.graphics.shapes import Rect from reportlab.lib.colors import Color, black, blue, red red50transparent = Color( 100, 0, 0, alpha=0.5) c = canvas c.setFillColor(black) c.setFont('Helvetica', 10) c.drawString(25,180, 'solid') c.setFillColor(blue) c.rect(25,25,100,100, fill=True, stroke=False) c.setFillColor(red) c.rect(100,75,100,100, fill=True, stroke=False) c.setFillColor(black) c.drawString(225,180, 'transparent')

Page 22

User Guide

Chapter 2 Graphics and Text with pdfgen

c.setFillColor(blue) c.rect(225,25,100,100, fill=True, stroke=False) c.setFillColor(red50transparent) c.rect(300,75,100,100, fill=True, stroke=False)

solid

transparent

Figure 2-8: Alpha example CMYK Colors


The CMYK or subtractive method follows the way a printer mixes three pigments (cyan, magenta, and yellow) to form colors. Because mixing chemicals is more difficult than combining light there is a fourth parameter for darkness. For example a chemical combination of the CMY pigments generally never makes a perfect black -- instead producing a muddy color -- so, to get black printers don not use the CMY pigments but use a direct black ink. Because CMYK maps more directly to the way printer hardware works it may be the case that colors specified in CMYK will provide better fidelity and better control when printed. There are two ways of representing CMYK Color: each color can be represented either by a real value between 0 and 1, or integer value between 0 and 100. Depending on your preference you can either use CMYKColor (for real values) or PCMYKColor ( for integer values). 0 means 'no ink', so printing on white papers gives you white. 1 (or 100 if you use PCMYKColor) means 'the maximum amount of ink'. e.g. CMYKColor(0,0,0,1) is black, CMYKColor(0,0,0,0) means 'no ink', and CMYKColor(0.5,0,0,0) means 50 percent cyan color.
def colorsCMYK(canvas): from reportlab.lib.colors import CMYKColor, PCMYKColor from reportlab.lib.units import inch # creates a black CMYK ; CMYKColor use real values black = CMYKColor(0,0,0,1) # creates a cyan CMYK ; PCMYKColor use integer values cyan = PCMYKColor(100,0,0,0) 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) 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

Page 23

User Guide

Chapter 2 Graphics and Text with pdfgen

c1 m0 y0 k0

c0 m1 y0 k0

c0 m0 y1 k0

c0 m0 y0 k1

c0 m0 y0 k0

Figure 2-9: CMYK Color Models

2.9 Color space checking


The enforceColorSpace argument of the canvas is used to enforce the consistency of the colour model used in a document. It accepts these values: CMYK, RGB, SEP, SEP_BLACK, SEP_CMYK. 'SEP' refers to named color separations such as Pantone spot colors - these can be mixed with CMYK or RGB according to the parameter used. The default is 'MIXED' which allows you to use colors from any color space. An exception is raised if any colors used are not convertible to the specified model, e.g. rgb and cmyk (more information in test_pdfgen_general). This approach doesn't check external images included in document.

2.10 Color Overprinting


When two CMYK colored objects overlap in printing, then either the object 'on top' will knock out the color of the the one underneath it, or the colors of the two objects will mix in the overlapped area. This behaviour can be set using the property overPrint. The overPrint function will cause ovelapping areas of color to mix. In the example below, the colors of the rectangles on the left should appear mixed where they overlap - If you can't see this effect then you may need to enable the 'overprint preview' option in your PDF viewing software. Some PDF viewers such as evince do not support overPrint; however Adobe Acrobat Reader does support it.

Page 24

User Guide

Chapter 2 Graphics and Text with pdfgen

overprint

knockout

Figure 2-10: overPrint example Other Object Order of Printing Examples


The word "SPUMONI" is painted in white over the colored rectangles, with the apparent effect of "removing" the color inside the body of the word.
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")

SPUMONI
Figure 2-11: Painting over colors
Page 25

You might also like