diff options
| author | pinky <> | 2007-01-07 21:26:16 +0000 |
|---|---|---|
| committer | pinky <> | 2007-01-07 21:26:16 +0000 |
| commit | db39be37af8e1f7947c186a2b4688f5963ed7cc7 (patch) | |
| tree | 00228b8f6f6f2d14e30181376b2406d557b6e6de /bin/reportlab/docs/userguide | |
| parent | eacf3d2a7007d9abe4fb00245d6fe833241fe283 (diff) | |
Reportlab 2.0
bzr revid: pinky-42646ca164f938abd312f6b2f8dccf73970f0c59
Diffstat (limited to 'bin/reportlab/docs/userguide')
| -rw-r--r-- | bin/reportlab/docs/userguide/app_demos.py | 113 | ||||
| -rw-r--r-- | bin/reportlab/docs/userguide/ch1_intro.py | 693 | ||||
| -rw-r--r-- | bin/reportlab/docs/userguide/ch2_graphics.py | 1180 | ||||
| -rw-r--r-- | bin/reportlab/docs/userguide/ch2a_fonts.py | 513 | ||||
| -rw-r--r-- | bin/reportlab/docs/userguide/ch3_pdffeatures.py | 271 | ||||
| -rw-r--r-- | bin/reportlab/docs/userguide/ch4_platypus_concepts.py | 509 | ||||
| -rw-r--r-- | bin/reportlab/docs/userguide/ch5_paragraphs.py | 319 | ||||
| -rw-r--r-- | bin/reportlab/docs/userguide/ch6_tables.py | 419 | ||||
| -rw-r--r-- | bin/reportlab/docs/userguide/ch7_custom.py | 81 | ||||
| -rw-r--r-- | bin/reportlab/docs/userguide/ch9_future.py | 35 | ||||
| -rw-r--r-- | bin/reportlab/docs/userguide/genuserguide.py | 85 | ||||
| -rw-r--r-- | bin/reportlab/docs/userguide/testfile.txt | 2 |
12 files changed, 4220 insertions, 0 deletions
diff --git a/bin/reportlab/docs/userguide/app_demos.py b/bin/reportlab/docs/userguide/app_demos.py new file mode 100644 index 00000000000..6c1c156477c --- /dev/null +++ b/bin/reportlab/docs/userguide/app_demos.py @@ -0,0 +1,113 @@ +#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/docs/userguide/app_demos.py +from reportlab.tools.docco.rl_doc_utils import * + +Appendix1("ReportLab Demos") +disc("""In the subdirectories of $reportlab/demos$ there are a number of working examples showing +almost all aspects of reportlab in use.""") + +heading2("""Odyssey""") +disc(""" +The three scripts odyssey.py, dodyssey.py and fodyssey.py all take the file odyssey.txt +and produce PDF documents. The included odyssey.txt is short; a longer and more testing version +can be found at ftp://ftp.reportlab.com/odyssey.full.zip. +""") +eg(""" +Windows +cd reportlab\\demos\\odyssey +python odyssey.py +start odyssey.pdf + +Linux +cd reportlab/demos/odyssey +python odyssey.py +acrord odyssey.pdf +""") +disc("""Simple formatting is shown by the odyssey.py script. It runs quite fast, +but all it does is gather the text and force it onto the canvas pages. It does no paragraph +manipulation at all so you get to see the XML < & > tags. +""") +disc("""The scripts fodyssey.py and dodyssey.py handle paragraph formatting so you get +to see colour changes etc. Both scripts +use the document template class and the dodyssey.py script shows the ability to do dual column +layout and uses multiple page templates. +""") + +heading2("""Standard Fonts and Colors""") +disc("""In $reportlab/demos/stdfonts$ the script stdfonts.py can be used to illustrate +ReportLab's standard fonts. Run the script using""") +eg(""" +cd reportlab\\demos\\stdfonts +python stdfonts.py +""") +disc(""" +to produce two PDF documents, StandardFonts_MacRoman.pdf & +StandardFonts_WinAnsi.pdf which show the two most common built in +font encodings. +""") +disc("""The colortest.py script in $reportlab/demos/colors$ demonstrates the different ways in which +reportlab can set up and use colors.""") +disc("""Try running the script and viewing the output document, colortest.pdf. This shows +different color spaces and a large selection of the colors which are named +in the $reportlab.lib.colors$ module. +""") +heading2("""Py2pdf""") +disc("""Dinu Gherman (<gherman@europemail.com>) contributed this useful script +which uses reportlab to produce nicely colorized PDF documents from Python +scripts including bookmarks for classes, methods and functions. +To get a nice version of the main script try""") +eg(""" +cd reportlab/demos/py2pdf +python py2pdf.py py2pdf.py +acrord py2pdf.pdf +""") +disc("""i.e. we used py2pdf to produce a nice version of py2pdf.py in +the document with the same rootname and a .pdf extension. +""") +disc(""" +The py2pdf.py script has many options which are beyond the scope of this +simple introduction; consult the comments at the start of the script. +""") +heading2("Gadflypaper") +disc(""" +The Python script, gfe.py, in $reportlab/demos/gadflypaper$ uses an inline style of +document preparation. The script almost entirely produced by Aaron Watters produces a document +describing Aaron's $gadfly$ in memory database for Python. To generate the document use +""") +eg(""" +cd reportlab\\gadflypaper +python gfe.py +start gfe.pdf +""") +disc(""" +everything in the PDF document was produced by the script which is why this is an inline style +of document production. So, to produce a header followed by some text the script uses functions +$header$ and $p$ which take some text and append to a global story list. +""") +eg(''' +header("Conclusion") + +p("""The revamped query engine design in Gadfly 2 supports +.......... +and integration.""") +''') +heading2("""Pythonpoint""") +disc("""Andy Robinson has refined the pythonpoint.py script (in $reportlab\\demos\\pythonpoint$) +until it is a really useful script. It takes an input file containing an XML markup +and uses an xmllib style parser to map the tags into PDF slides. When run in its own directory +pythonpoint.py takes as a default input the file pythonpoint.xml and produces pythonpoint.pdf +which is documentation for Pythonpoint! You can also see it in action with an older paper +""") +eg(""" +cd reportlab\\demos\\pythonpoint +python pythonpoint.py monterey.xml +start monterey.pdf +""") +disc(""" +Not only is pythonpoint self documenting, but it also demonstrates reportlab and PDF. It uses +many features of reportlab (document templates, tables etc). +Exotic features of PDF such as fadeins and bookmarks are also shown to good effect. The use of +an XML document can be contrasted with the <i>inline</i> style of the gadflypaper demo; the +content is completely separate from the formatting +""")
\ No newline at end of file diff --git a/bin/reportlab/docs/userguide/ch1_intro.py b/bin/reportlab/docs/userguide/ch1_intro.py new file mode 100644 index 00000000000..1aa99314d99 --- /dev/null +++ b/bin/reportlab/docs/userguide/ch1_intro.py @@ -0,0 +1,693 @@ +#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/docs/userguide/ch1_intro.py +from reportlab.tools.docco.rl_doc_utils import * +import reportlab + +title("ReportLab PDF Library") +title("User Guide") +centred('ReportLab Version ' + reportlab.Version) + +nextTemplate("Normal") + +######################################################################## +# +# Chapter 1 +# +######################################################################## + + +heading1("Introduction") + + +heading2("About this document") +disc("""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. +""") + +disc(""" +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. +""") + +disc("""In this chapter, we will cover the groundwork:""") +bullet("What is ReportLab all about, and why should I use it?") +bullet("What is Python?") +bullet("How do I get everything set up and running?") + +todo(""" +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 <a href="http://www.reportlab.org/">www.reportlab.org</a>. +""") + +heading2("What is the ReportLab PDF Library?") +disc("""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.""") + +disc("""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.""") + +disc("""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. +""") + + +disc("""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. """) + + +disc("""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.""") + +disc("""The ReportLab library is expected to be useful +in at least the following contexts:""") +bullet("Dynamic PDF generation on the web") +bullet("High-volume corporate reporting and database publishing") +bullet("""An embeddable print engine for other applications, including +a 'report language' so that users can customize their own reports. <i> +This is particularly relevant to cross-platform apps which cannot +rely on a consistent printing or previewing API on each operating +system</i>.""") +bullet("""A 'build system' for complex documents with charts, tables +and text such as management accounts, statistical reports and +scientific papers """) +bullet("""Going from XML to PDF in one step!""") + + + + +heading2("What is Python?") +disc(""" +Python is an <i>interpreted, interactive, object-oriented</i> programming language. It is often compared to Tcl, Perl, +Scheme or Java. +""") + +disc(""" +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. +""") + + +disc(""" +Python is as old as Java and has been growing steadily in popularity for 13 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. +""") + +disc(""" +Python is copyrighted but <b>freely usable and distributable, even for commercial use</b>. +""") + +heading2("Acknowledgements") +disc("""Many people have contributed to ReportLab. We would like to thank +in particular (in approximately chronological order) Chris Lee, Magnus Lie Hetland, +Robert Kern, Jeff Bauer (who contributed normalDate.py); Jerome Alet (numerous patches +and the rlzope demo), Andre Reitz, Max M, Albertas Agejevas, T Blatter, Ron Peleg, +Gary Poster, Steve Halasz, Andrew Mercer, Paul McNett, Chad Miller, Tim Roberts, +Jorge Godoy and Benn B.""") + +disc("""Special thanks go to Just van Rossum for his valuable assistance with +font technicalities and the LettErrorRobot-Chrome type 1 font.""") + +disc("""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 Bigelow & Holmes Inc ($design@bigelowandholmes.com$) +for Luxi Serif Regular and Ray Larabie ($http://www.larabiefonts.com$) for the Rina TrueType font.""") + +heading2("Installation and Setup") + +disc(""" +Below we provide an abbreviated setup procedure for Python experts and a more +verbose procedure for people who are new to Python. +""") + +heading3("Installation for experts") +disc("""First of all, we'll give you the high-speed version for experienced +Python developers:""") +list("""Install Python 2.3 or later (2.4 recommended). ReportLab 2.x uses + Python 2.3 features and will use 2.4 going forwards. We also maintain + a 1.x branch which works back to Python 2.1. + """) +list("""If you want to produce compressed PDF files (recommended), +check that zlib is installed.""") +list("""If you want to work with bitmap images, install and +test the Python Imaging Library""") +list("""Unpack the reportlab package (reportlab.zip +or reportlab.tgz) into a directory on your path. (You can also use ^python setup.py install^ if you wish)""") +list("""Unpack the rl_addons package and build the C extensions with distutils; or grab the +corresponding .pyd files from our download page. """) + + +list("""$cd$ to ^reportlab/test^ and execute $runAll.py$. +This will create many PDF files. """) +list("""You may also want to download and run the ^rl_check.py^ on our site, which +health-checks an installation and reports on any missing options. """) +disc(" ") +disc("""If you have any problems, check the 'Detailed Instructions' section below.""") + +heading3("A note on available versions") +disc("""The $reportlab$ library can be found at $ftp.reportlab.com$ in +the top-level directory or at http://www.reportlab.com/ftp/. +Each successive version is stored in both zip +and tgz format, but the contents are identical apart from line endings. +Versions are numbered: $ReportLab_1_00.zip$, $ReportLab_1_01.zip$ and so on. The +latest stable version is also available as just $reportlab.zip$ (or +$reportlab.tgz$), which is actually a symbolic link to the latest +numbered version. Finally, daily snapshots off the trunk are available as +$current.zip$ (or $current.tgz$). +""") + + +heading3("Instructions for novices: Windows") + + + +disc("""This section assumes you +don't know much about Python. We cover all of the steps for three +common platforms, including how to verify that each one is complete. +While this may seem like a long list, everything takes 5 minutes if +you have the binaries at hand.""") + + +restartList() + +list("""Get and install Python from $http://www.python.org/.$ +Reportlab 2.x works with Python 2.3 upwards but we strongly recommend to use +the latest stable version of Python (2.4.3 at the time of writing). +Follow the links to 'Download' and get the latest +official version. This will install itself into $C:\Python24$ +After installing, you should be able to run the +'Python (command line)' option from the Start Menu.""") + +list("""If on Windows, we strongly recommend installing the Python Windows +Extensions, which let you use access all the Windows data sources, and provide +a very nice IDE. This can be found at ^http://sourceforge.net/projects/pywin32/^. +Once this is installed, you can start +Pythonwin from the Start Menu and get a GUI application.""") + +list("""The next step is optional and only necessary if you want to +include images in your reports; it can also be carried out later. However +we always recommend a full installation if time permits.""") + +list("""Install the Python Imaging Library ($PIL$) from $http://www.pythonware.com/products/pil/$. +""") + + +list("""Now you are ready to install reportlab itself. Unzip the archive straight into +your Python directory; it creates a subdirectory named +$reportlab$. You should now be able to go to a Python +command line interpreter and type $import reportlab$ without getting +an error message.""") + +list("""Download the zip file of precompiled DLLs for your Python version from +the bottom of the ^http://www.reportlab.org/downloads.html^ downloads page, and unzip +them into ^C:\Python24\lib\site-packages^ (or its equivalent for other Python versions""") + +list("""Open up a $MS-DOS$ command prompt and CD to +"$..\\reportlab\\test$". Enter "$runAll.py$". You should see lots of dots +and no error messages. This will also create many PDF files and generate +the manuals in ^reportlab/docs^ (including this one). """) + +list(""" +Finally, we recommend you download and run the script ^rl_check.py^ from +^^http://www.reportlab.org/ftp/^. This will health-check all the above +steps and warn you if anything is missing or mismatched.""") + +heading3("Instructions for Python novices: Unix") + +restartList() +list("""On a large number of Unix and Linux distributions, Python is already installed, +or is avaialable as a standard package you can install with the relevant package manager.""") + +list("""If you want to compile from +source download the latest +sources from http://www.python.org (currently the latest source is +in http://www.python.org/ftp/python/2.4.3/Python-2.4.3.tgz). If you wish to use +binaries +get the latest RPM or DEB or whatever package and install (or get your +super user (system administrator) to do the work).""") + +list("""If you are building Python yourself, unpack the sources into a +temporary directory using a tar command e.g. $tar xzvf Python-2.4.3.tgz$; +this will create a subdirectory called Python-2.4.3 (or whatever). cd +into this directory. Then read the file $README$! It contains the +latest information on how to install Python.""") + +list("""If your system has the gzip libz library installed +check that the zlib extension will be installed by default by editing +the file Modules/Setup.in and ensuring that (near line 405) the line +containing zlib zlibmodule.c is uncommented i.e. has no hash '#' character at the +beginning. You also need to decide if you will be installing in the default location +(/usr/local/) or in some other place. +The zlib module is needed if you want compressed PDF and for some images.""") + +list("""Invoke the command $./configure --prefix=/usr/local$ this should configure +the source directory for building. Then you can build the binaries with +a $make$ command. If your $make$ command is not up to it try building +with $make MAKE=make$. If all goes well install with $make install$.""") + +list("""If all has gone well and python is in the execution search path +you should now be able to type $python$ and see a <b>Python</b> prompt.""") + +list(""" +Once you can do that it's time to try and install ReportLab. +First get the latest reportlab.tgz. +If ReportLab is to be available to all then the reportlab archive should be unpacked in +the lib/site-python directory (typically /usr/local/lib/site-python) if necessary by +a superuser. +Otherwise unpack in a directory of your choice and arrange for that directory to be on your +$PYTHONPATH$ variable. +""") +eg(""" +#put something like this in your +#shell rcfile +PYTHONPATH=$HOME/mypythonpackages +export PYTHONPATH +""",after=0.1) + +list("""You should now be able to run python and execute the python statement +""",doBullet=0) +eg("""import reportlab""",after=0.1) +list("""If you want to use images you should certainly consider +getting & installing the Python Imaging Library - follow the +directions from +$http://www.python.org/sigs/image-sig/index.html$ or get it directly from +$http://www.pythonware.com/products/pil/$.""") + + +heading3("Instructions for Python novices: Mac") +disc(""" +This is much, much easier with Mac OS X since Python (usually 2.3) is installed on your +system as standard. Just follow the instructions for installing the ReportLab archive +above. +""") + + +heading3("Instructions for Jython (Java implementation of Python) users") + +disc(""" +A port to Java was done in 2004. This involved some changes to the framework +and creating Java equivalents of the C extensions. At the end of this work +the entire output of the test suite produced byte-for-byte identical output. +However, we have not been testng against Jython since, because (a) as far as +we know no one used it, and (b) Jython has not kept up with Python features +which we need to use. We suggest you use ReportLab v1.19 or v1.20 which +were Python-2.1 compatible. We'd welcome test reports and/or a volunteer to +refresh things now that Jython is progressing.""") + +disc(""" +The Jython version was tested under Sun's J2SDK 1.3.1. It is known that under +J2SDK 1.4.0_01 $test_pdfbase_ttfonts.py$ fails horribly with an outOfMemory +exception, probably caused by a JVM bug. +""") + + + + +restartList() + +list(""" +Before installing Jython, make sure you have a supported version of +Java Virtual Machine installed. For the list of supported JVM's see +$http://www.jython.org/platform.html$ +""") + +list(""" +To install Jython, download the setup package from $www.jython.org$ and +follow installation instructions. +""") + +list(""" +To set ReportLab toolkit under Jython PATH, edit $JYTHON_HOME/registry$ file +and include line that tells Jython where to look for packages. To include +ReportLab toolkit under Jython PATH, directory that contains Reportlab +should be included: $python.path=REPORTLAB_HOME_PARENT_DIR$ +For example, if your Reportlab toolkit is installed under $C:\code\\reportlab$ +the path line should be: $python.path=C:\\\\code$ (note two backslashes!) +""") + +heading3("Instructions for IronPython (Python for .NET) users") + +disc(""" +We haven't tackled this yet officially, but IronPython can apparently +run much of our code. We do need to go through the same exercises we did for Jython +- finding the .NET equivalents of _rl_accel, pyRXP, _renderPM and PIL - +to get 100% managed code. Hopefully this will happen soon and we'd be +delighted to work with anyone on this. +""") + + +heading2("Getting Involved") +disc("""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:""") + +bullet("""General feedback on the core API. Does it work for you? +Are there any rough edges? Does anything feel clunky and awkward?""") + +bullet("""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?""") + +bullet("""Demonstrations and Case Studies: If you have produced some nice +output, send it to us (with or without scripts). If ReportLab solved a +problem for you at work, write a little 'case study' and send it in. +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!""") + +bullet("""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!""") + +disc("""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. """) + + +heading2("Site Configuration") +disc("""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.""") +bullet("""verbose: set to integer values to control diagnostic output.""") +bullet("""shapeChecking: set this to zero to turn off a lot of error checking in the graphics modules""") +bullet("""defaultEncoding: set this to WinAnsiEncoding or MacRomanEncoding.""") +bullet("""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.""") +bullet("""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""") +bullet("""T1SearchPath: this is a python list of strings representing directories that +may be queried for information on Type 1 fonts""") +bullet("""TTFSearchPath: this is a python list of strings representing directories that +may be queried for information on TrueType fonts""") +bullet("""CMapSearchPath: this is a python list of strings representing directories that +may be queried for information on font code maps.""") +bullet("""showBoundary: set to non-zero to get boundary lines drawn.""") +bullet("""ZLIB_WARNINGS: set to non-zero to get warnings if the Python compression extension is not found.""") +bullet("""pageComression: set to non-zero to try and get compressed PDF.""") +bullet("""allowtableBoundsErrors: set to 0 to force an error on very large Platypus table elements""") +bullet("""emptyTableAction: Controls behaviour for empty tables, can be 'error' (default), 'indicate' or 'ignore'.""") + + + +heading2("Learning More About Python") + +disc(""" +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: +""") + + +bullet("""<b>Introductory Material on Python. </b> +A list of tutorials on the Python.org web site. +$http://www.python.org/doc/Intros.html$ +""") + + +bullet("""<b>Python Tutorial. </b> +The official Python Tutorial by Guido van Rossum (edited by Fred L. Drake, Jr.) +$http://www.python.org/doc/tut/$ +""") + + +bullet("""<b>Learning to Program. </b> +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/$ +""") + + +bullet("""<b>How to think like a computer scientist</b> (Python version)</b>. +$http://www.ibiblio.org/obp/thinkCSpy/$ +""") + + +bullet("""<b>Instant Python</b>. +A 6-page minimal crash course by Magnus Lie Hetland. +$http://www.hetland.org/python/instant-python.php$ +""") + + +bullet("""<b>Dive Into Python</b>. +A free Python tutorial for experienced programmers. +$http://diveintopython.org/$ +""") + + +from reportlab.lib.codecharts import SingleByteEncodingChart +from reportlab.tools.docco.stylesheet import getStyleSheet +styles = getStyleSheet() +indent0_style = styles['Indent0'] +indent1_style = styles['Indent1'] + +heading2("What's New in ReportLab 2.0") +disc(""" +Many new features have been added, foremost amongst which is the support +for unicode. This page documents what has changed since version 1.20.""") + +disc(""" +Adding full unicode support meant that we had to break backwards-compatibility, +so old code written for ReportLab 1 will sometimes need changes before it will +run correctly with ReportLab 2. Now that we have made the clean break to +introduce this important new feature, we intend to keep the API +backwards-compatible throughout the 2.* series. +""") +heading3("Goals for the 2.x series") +disc(""" +The main rationale for 2.0 was an incompatible change at the character level: +to properly support Unicode input. Now that it's out we will maintain compatibility +with 2.0. There are no pressing feature wishlists and new features will be driven, +as always, by contributions and the demands of projects.""") + +disc(""" +Our 1.x code base is still Python 2.1 compatible. The new version lets us move forwards +with a baseline of Python 2.4 (2.3 will work too, for the moment, but we don't promise +that going forwards) so we can use newer language features freely in our development.""") + +disc(""" +One area where we do want to make progress from release to release is with documentation +and installability. We'll be looking into better support for distutils, setuptools, +eggs and so on; and into better examples and tools to help people learn what's in the +(substantial) code base.""") + +disc(""" +Bigger ideas and more substantial rewrites are deferred to Version 3.0, with no particular +target dates. +""") + +heading3("Contributions") +disc("""Thanks to everybody who has contributed to the open-source toolkit in the run-up +to the 2.0 release, whether by reporting bugs, sending patches, or contributing to the +reportlab-users mailing list. Thanks especially to the following people, who contributed +code that has gone into 2.0: Andre Reitz, Max M, Albertas Agejevas, T Blatter, Ron Peleg, +Gary Poster, Steve Halasz, Andrew Mercer, Paul McNett, Chad Miller. +""") +todo("""If we missed you, please let us know!""") + +heading3("Unicode support") +disc(""" +This is the Big One, and the reason some apps may break. You must now pass in text either +in UTF-8 or as unicode string objects. The library will handle everything to do with output +encoding. There is more information on this below. +Since this is the biggest change, we'll start by reviewing how it worked in the past.""") + +disc(""" +In ReportLab 1.x, any string input you passed to our APIs was supposed to be in the same +encoding as the font you selected for output. If using the default fonts in Acrobat Reader +(Helvetica/Times/Courier), you would have implicitly used WinAnsi encoding, which is almost +exactly the same as Latin-1. However, if using TrueType fonts, you would have been using UTF-8.""") + +disc("""For Asian fonts, you had a wide choice of encodings but had to specify which one +(e.g Shift-JIS or EUC for Japanese). This state of affairs meant that you had +to make sure that every piece of text input was in the same encoding as the font used +to display it.""") + + + +disc("""Input text encoding is UTF-8 or Python Unicode strings""") +disc(""" +Any text you pass to a canvas API (drawString etc.), Paragraph or other flowable +constructor, into a table cell, or as an attribute of a graphic (e.g. chart.title.text), +is supposed to be unicode. If you use a traditional Python string, it is assumed to be UTF-8. +If you pass a Unicode object, we know it's unicode.""", style=indent1_style) + +disc("""Font encodings""") +disc(""" +Fonts still work in different ways, and the built-in ones will still use WinAnsi or MacRoman +internally while TrueType will use UTF-8. However, the library hides this from you; it converts +as it writes out the PDF file. As before, it's still your job to make sure the font you use has +the characters you need, or you may get either a traceback or a visible error character.""",style=indent1_style) + +disc("""Asian CID fonts""") +disc(""" +You no longer need to specify the encoding for the built-in Asian fonts, just the face name. +ReportLab knows about the standard fonts in Adobe's Asian Language Packs +""", style=indent1_style) + +disc("""Asian Truetype fonts""") +disc(""" +The standard Truetype fonts differ slightly for Asian languages (e.g msmincho.ttc). +These can now be read and used, albeit somewhat inefficiently. +""", style=indent1_style) + +disc("""Asian word wrapping""") +disc(""" +Previously we could display strings in Asian languages, but could not properly +wrap paragraphs as there are no gaps between the words. We now have a basic word wrapping +algorithm. +""", style=indent1_style) + +disc("""unichar tag""") +disc(""" +A convenience tag, <unichar/> has also been added. You can now do <unichar code="0xfc"/> +or <unichar name='LATIN SMALL LETTER U WITH DIAERESIS'/> and +get a lowercase u umlaut. Names should be those in the Unicode Character Database. +""", style=indent1_style) + +disc("""Accents, greeks and symbols""") +disc(""" +The correct way to refer to all non-ASCII characters is to use their unicode representation. +This can be literal Unicode or UTF-8. Special symbols and Greek letters (collectively, "greeks") +inserted in paragraphs using the greek tag (e.g. <greek>lambda</greek>) or using the entity +references (e.g. λ) are now processed in a different way than in version 1.""", style=indent1_style) +disc(""" +Previously, these were always rendered using the Zapf Dingbats font. Now they are always output +in the font you specified, unless that font does not support that character. If the font does +not support the character, and the font you specified was an Adobe Type 1 font, Zapf Dingbats +is used as a fallback. However, at present there is no fallback in the case of TTF fonts. +Note that this means that documents that contain greeks and specify a TTF font may need +changing to explicitly specify the font to use for the greek character, or you will see a black +square in place of that character when you view your PDF output in Acrobat Reader. +""", style=indent1_style) + +# Other New Features Section ####################### +heading3("Other New Features") +disc("""PDF""") +disc("""Improved low-level annotation support for PDF "free text annotations" +""", style=indent0_style) +disc("""FreeTextAnnotation allows showing and hiding of an arbitrary PDF "form" +(reusable chunk of PDF content) depending on whether the document is printed or +viewed on-screen, or depending on whether the mouse is hovered over the content, etc. +""", style=indent1_style) + +disc("""TTC font collection files are now readable" +""", style=indent0_style) +disc("""ReportLab now supports using TTF fonts packaged in .TTC files""", style=indent1_style) + +disc("""East Asian font support (CID and TTF)""", style=indent0_style) +disc("""You no longer need to specify the encoding for the built-in Asian fonts, +just the face name. ReportLab knows about the standard fonts in Adobe's Asian Language Packs. +""", style=indent1_style) + +disc("""Native support for JPEG CMYK images""", style=indent0_style) +disc("""ReportLab now takes advantage of PDF's native JPEG CMYK image support, +so that JPEG CMYK images are no longer (lossily) converted to RGB format before including +them in PDF.""", style=indent1_style) + + +disc("""Platypus""") +disc("""Link support in paragraphs""", style=indent0_style) +disc(""" +Platypus paragraphs can now contain link elements, which support both internal links +to the same PDF document, links to other local PDF documents, and URL links to pages on +the web. Some examples:""", style=indent1_style) +disc("""Web links:""", style=indent1_style) +disc("""<link href="http://www.reportlab.com/">ReportLab<link>""", style=styles['Link']) + +disc("""Internal link to current PDF document:""", style=indent1_style) +disc("""<link href="summary">ReportLab<link>""", style=styles['Link']) + +disc("""External link to a PDF document on the local filesystem:""", style=indent1_style) +disc("""<link href="pdf:C:/john/report.pdf">ReportLab<link>""", style=styles['Link']) + +disc("""Improved wrapping support""", style=indent0_style) +disc("""Support for wrapping arbitrary sequence of flowables around an image, using +reportlab.platypus.flowables.ImageAndFlowables (similar to ParagraphAndImage).""" +,style=indent1_style) + +disc("""KeepInFrame""", style=indent0_style) +disc("""Sometimes the length of a piece of text you'd like to include in a fixed piece +of page "real estate" is not guaranteed to be constrained to a fixed maximum length. +In these cases, KeepInFrame allows you to specify an appropriate action to take when +the text is too long for the space allocated for it. In particular, it can shrink the text +to fit, mask (truncate) overflowing text, allow the text to overflow into the rest of the document, +or raise an error.""",style=indent1_style) + + +disc("""Improved convenience features for inserting unicode symbols and other characters +""", style=indent0_style) +disc("""<unichar/> lets you conveniently insert unicode characters using the standard long name +or code point. Characters inserted with the <greek> tags (e.g. <greek>lambda</greek>) or corresponding +entity references (e.g. λ) support arbitrary fonts (rather than only Zapf Dingbats).""",style=indent1_style) + +disc("""Improvements to Legending""", style=indent0_style) +disc("""Instead of manual placement, there is now a attachment point (N, S, E, W, etc.), so that +the legend is always automatically positioned correctly relative to the chart. Swatches (the small +sample squares of colour / pattern fill sometimes displayed in the legend) can now be automatically +created from the graph data. Legends can now have automatically-computed totals (useful for +financial applications).""",style=indent1_style) + +disc("""More and better ways to place piechart labels""", style=indent0_style) +disc("""New smart algorithms for automatic pie chart label positioning have been added. +You can now produce nice-looking labels without manual positioning even for awkward cases in +big runs of charts.""",style=indent1_style) + +disc("""Adjustable piechart slice ordering""", style=indent0_style) +disc("""For example. pie charts with lots of small slices can be configured to alternate thin and +thick slices to help the lagel placememt algorithm work better.""",style=indent1_style) +disc("""Improved spiderplots""", style=indent0_style) + + +# Noteworthy bug fixes Section ####################### +heading3("Noteworthy bug fixes") +disc("""Fixes to TTF splitting (patch from Albertas Agejevas)""") +disc("""This affected some documents using font subsetting""", style=indent0_style) + +disc("""Tables with spans improved splitting""") +disc("""Splitting of tables across pages did not work correctly when the table had +row/column spans""", style=indent0_style) + +disc("""Fix runtime error affecting keepWithNext""") diff --git a/bin/reportlab/docs/userguide/ch2_graphics.py b/bin/reportlab/docs/userguide/ch2_graphics.py new file mode 100644 index 00000000000..083b756db5b --- /dev/null +++ b/bin/reportlab/docs/userguide/ch2_graphics.py @@ -0,0 +1,1180 @@ +#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/docs/userguide/ch2_graphics.py +from reportlab.tools.docco.rl_doc_utils import * +from reportlab.lib.codecharts import SingleByteEncodingChart + +heading1("Graphics and Text with $pdfgen$") + +heading2("Basic Concepts") +disc(""" +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$. +""") + +disc(""" +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.""") + +disc(""" +A simple example +program that uses a canvas follows. +""") + +eg(""" + 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() +""") + +disc(""" +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.""") + +disc(""" +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. +""") + +heading2("More about the Canvas") +disc(""" +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!""") + +disc("""First of all, we will look at the constructor +arguments for the canvas:""") +eg(""" def __init__(self,filename, + pagesize=(595.27,841.89), + bottomup = 1, + pageCompression=0, + encoding=rl_config.defaultEncoding, + verbosity=0): + """) + +disc("""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!""") + +disc("""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""") + +eg("""from reportlab.lib.pagesizes import letter, A4 +myCanvas = Canvas('myfile.pdf', pagesize=letter) +width, height = letter #keep for later +""") + +pencilnote() + +disc("""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.""") + +disc("""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.""") + +disc("""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""") + +todo("""Need to see if it really works for all tasks, and if not + then get rid of it""") + +disc("""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 <i>always</i> compressed, and this option +will only save space if you have a very large amount of text and vector graphics +on each page.""") + +disc("""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: +<font color="blue"><u><a href="http://www.alanwood.net/demos/charsetdiffs.html">http://www.alanwood.net/demos/charsetdiffs.html</a></u></font>. + +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 <i>internally by the font</i>; 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 +<i>reportlab/pdfbase/pdfdoc.py</i> 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.""") + +disc("""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'.""") + +disc("""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.""") + +todo("to do - all the info functions and other non-drawing stuff") + + + + + +todo("""Cover all constructor arguments, and setAuthor etc.""") + +heading2("Drawing Operations") +disc(""" +Suppose the $hello$ function referenced above is implemented as +follows (we will not explain each of the operations in detail +yet). +""") + +eg(examples.testhello) + +disc(""" +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. +""") + +disc(""" +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). +""") + +disc(""" +The document generated by the "hello world" program listed above would contain +the following graphics. +""") + +illust(examples.hello, '"Hello World" in pdfgen') + +heading3("About the demos in this document") + +disc(""" +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 %s inches wide +and %s inches tall. The demo displays show the actual output of the demo code. +For convenience the size of the output has been reduced slightly. +""" % (examplefunctionxinches, examplefunctionyinches)) + +heading2('The tools: the "draw" operations') + +disc(""" +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. +""") + +heading3("Line methods") + +eg("""canvas.line(x1,y1,x2,y2)""") +eg("""canvas.lines(linelist)""") + +disc(""" +The line methods draw straight line segments on the canvas. +""") + +heading3("Shape methods") + +eg("""canvas.grid(xlist, ylist) """) +eg("""canvas.bezier(x1, y1, x2, y2, x3, y3, x4, y4)""") +eg("""canvas.arc(x1,y1,x2,y2) """) +eg("""canvas.rect(x, y, width, height, stroke=1, fill=0) """) +eg("""canvas.ellipse(x1,y1, x2,y2, stroke=1, fill=0)""") +eg("""canvas.wedge(x1,y1, x2,y2, startAng, extent, stroke=1, fill=0) """) +eg("""canvas.circle(x_cen, y_cen, r, stroke=1, fill=0)""") +eg("""canvas.roundRect(x, y, width, height, radius, stroke=1, fill=0) """) + +disc(""" +The shape methods draw common complex shapes on the canvas. +""") + +heading3("String drawing methods") + +eg("""canvas.drawString(x, y, text):""") +eg("""canvas.drawRightString(x, y, text) """) +eg("""canvas.drawCentredString(x, y, text)""") + +disc(""" +The draw string methods draw single lines of text on the canvas. +""") + +heading3("The text object methods") +eg("""textobject = canvas.beginText(x, y) """) +eg("""canvas.drawText(textobject) """) + +disc(""" +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$. +""") + +heading3("The path object methods") + +eg("""path = canvas.beginPath() """) +eg("""canvas.drawPath(path, stroke=1, fill=0) """) +eg("""canvas.clipPath(path, stroke=1, fill=0) """) + +disc(""" +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 using $drawPath$.""") + +disc("""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. +""") + +heading3("Image methods") +pencilnote() +disc(""" +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 $test$ subdirectory and looking at page 7 of the output. +""") + +disc(""" +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: +""") + +eg("""canvas.drawInlineImage(self, image, x,y, width=None,height=None) """) + +disc(""" +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. +""") + +eg("""canvas.drawImage(self, image, x,y, width=None,height=None,mask=None) """) +disc(""" +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.""") + +disc(""" +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.""") + +disc("""PDF allows for many image features and we will expose more of the over +time, probably with extra keyword arguments to $drawImage$.""") + +heading3("Ending a page") + +eg("""canvas.showPage()""") + +disc("""The $showPage$ method finishes the current page. All additional drawing will +be done on another page.""") + +pencilnote() + +disc("""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!""") + +heading2('The toolbox: the "state change" operations') + +disc(""" +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. +""") + +heading3("Changing Colors") +eg("""canvas.setFillColorCMYK(c, m, y, k) """) +eg("""canvas.setStrikeColorCMYK(c, m, y, k) """) +eg("""canvas.setFillColorRGB(r, g, b) """) +eg("""canvas.setStrokeColorRGB(r, g, b) """) +eg("""canvas.setFillColor(acolor) """) +eg("""canvas.setStrokeColor(acolor) """) +eg("""canvas.setFillGray(gray) """) +eg("""canvas.setStrokeGray(gray) """) + +disc(""" +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. +""") + +heading3("Changing Fonts") +eg("""canvas.setFont(psfontname, size, leading = None) """) + +disc(""" +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. +""") + +heading3("Changing Graphical Line Styles") + +eg("""canvas.setLineWidth(width) """) +eg("""canvas.setLineCap(mode) """) +eg("""canvas.setLineJoin(mode) """) +eg("""canvas.setMiterLimit(limit) """) +eg("""canvas.setDash(self, array=[], phase=0) """) + +disc(""" +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.""") + +heading3("Changing Geometry") + +eg("""canvas.setPageSize(pair) """) +eg("""canvas.transform(a,b,c,d,e,f): """) +eg("""canvas.translate(dx, dy) """) +eg("""canvas.scale(x, y) """) +eg("""canvas.rotate(theta) """) +eg("""canvas.skew(alpha, beta) """) + +disc(""" +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 <i>incremental</i> -- a new +transform modifies the current transform (but does not replace it). +""") + +heading3("State control") + +eg("""canvas.saveState() """) +eg("""canvas.restoreState() """) + +disc(""" +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.""") + +heading2("Other $canvas$ methods.") + +disc(""" +Not all methods of the $canvas$ object fit into the "tool" or "toolbox" +categories. Below are some of the misfits, included here for completeness. +""") + +eg(""" + 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.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') +""") + + +heading2('Coordinates (default user space)') + +disc(""" +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. +""") + +disc("""For example, the following function draws +a number of elements on a $canvas$.""") + +eg(examples.testcoords) + +disc("""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.""") + +illust(examples.coords, 'The Coordinate System') + +heading3("Moving the origin: the $translate$ method") + +disc("""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)^.""") + +disc("""For example the following translate function first moves +the origin before drawing the same objects as shown above.""") + +eg(examples.testtranslate) + +disc("""This produces the following.""") + +illust(examples.translate, "Moving the origin: the $translate$ method") + + +#illust(NOP) # execute some code + +pencilnote() + + +disc(""" +<i>Note:</i> 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. +""") + +heading3("Shrinking and growing: the scale operation") + +disc("""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. +""") + +eg(examples.testscale) + +disc("""This produces a "short and fat" reduced version of the previously displayed operations.""") + +illust(examples.scale, "Scaling the coordinate system") + + +#illust(NOP) # execute some code + +pencilnote() + + +disc("""<i>Note:</i> scaling may also move objects or parts of objects off the page, +or may cause objects to "shrink to nothing." """) + +disc("""Scaling and translation can be combined, but the order of the +operations are important.""") + +eg(examples.testscaletranslate) + +disc("""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 <i>same</i> operations in a different order. +Observe the effect below.""") + +illust(examples.scaletranslate, "Scaling and Translating") + + +#illust(NOP) # execute some code + +pencilnote() + + +disc("""<em>Note:</em> 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.""") + +heading3("Saving and restoring the $canvas$ state: $saveState$ and $restoreState$") + +disc(""" +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 <i>no</i> $canvas$ state is +preserved across page breaks, and the save/restore mechanism does not work +across page breaks. +""") + +heading3("Mirror image") + +disc(""" +It is interesting although perhaps not terribly useful to note that +scale factors can be negative. For example the following function +""") + +eg(examples.testmirror) + +disc(""" +creates a mirror image of the elements drawn by the $coord$ function. +""") + +illust(examples.mirror, "Mirror Images") + +disc(""" +Notice that the text strings are painted backwards. +""") + +heading2("Colors") + +disc(""" +There are four ways to specify colors in $pdfgen$: by name (using the $color$ +module, by red/green/blue (additive, $RGB$) value, +by cyan/magenta/yellow/darkness (subtractive, $CMYK$), or by gray level. +The $colors$ function below exercises each of the four methods. +""") + +eg(examples.testcolors) + +disc(""" +The $RGB$ or additive color specification follows the way a computer +screen adds different levels of the red, green, or blue light to make +any color, where white is formed by turning all three lights on full +$(1,1,1)$.""") + +disc("""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't 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. +""") + +illust(examples.colors, "Color Models") + +heading2('Painting back to front') + +disc(""" +Objects may be painted over other objects to good effect in $pdfgen$. As +in painting with oils the object painted last will show up on top. For +example, the $spumoni$ function below paints up a base of colors and then +paints a white text over the base. +""") + +eg(examples.testspumoni) + +disc(""" +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. +""") + +illust(examples.spumoni, "Painting over colors") + +disc(""" +The last letters of the word are not visible because the default $canvas$ +background is white and painting white letters over a white background +leaves no visible effect. +""") + +disc(""" +This method of building up complex paintings in layers can be done +in very many layers in $pdfgen$ -- there are fewer physical limitations +than there are when dealing with physical paints. +""") + +eg(examples.testspumoni2) + +disc(""" +The $spumoni2$ function layers an ice cream cone over the +$spumoni$ drawing. Note that different parts of the cone +and scoops layer over eachother as well. +""") +illust(examples.spumoni2, "building up a drawing in layers") + + +heading2('Standard fonts and text objects') + +disc(""" +Text may be drawn in many different colors, fonts, and sizes in $pdfgen$. +The $textsize$ function demonstrates how to change the color and font and +size of text and how to place text on the page. +""") + +eg(examples.testtextsize) + +disc(""" +The $textsize$ function generates the following page. +""") + +illust(examples.textsize, "text in different fonts and sizes") + +disc(""" +A number of different fonts are always available in $pdfgen$. +""") + +eg(examples.testfonts) + +disc(""" +The $fonts$ function lists the fonts that are always available. +These don't need to be stored in a PDF document, since they +are guaranteed to be present in Acrobat Reader. +""") + +illust(examples.fonts, "the 14 standard fonts") + +disc(""" +For information on how to use arbitrary fonts, see the next chapter. +""") + + +heading2("Text object methods") + +disc(""" +For the dedicated presentation of text in a PDF document, use a text object. +The text object interface provides detailed control of text layout parameters +not available directly at the $canvas$ level. In addition, it results in smaller +PDF that will render faster than many separate calls to the $drawString$ methods. +""") + +eg("""textobject.setTextOrigin(x,y)""") +eg("""textobject.setTextTransform(a,b,c,d,e,f)""") +eg("""textobject.moveCursor(dx, dy) # from start of current LINE""") +eg("""(x,y) = textobject.getCursor()""") +eg("""x = textobject.getX(); y = textobject.getY()""") +eg("""textobject.setFont(psfontname, size, leading = None)""") +eg("""textobject.textOut(text)""") +eg("""textobject.textLine(text='')""") +eg("""textobject.textLines(stuff, trim=1)""") + +disc(""" +The text object methods shown above relate to basic text geometry. +""") + +disc(""" +A text object maintains a text cursor which moves about the page when +text is drawn. For example the $setTextOrigin$ places the cursor +in a known position and the $textLine$ and $textLines$ methods move +the text cursor down past the lines that have been missing. +""") + +eg(examples.testcursormoves1) + +disc(""" +The $cursormoves$ function relies on the automatic +movement of the text cursor for placing text after the origin +has been set. +""") + +illust(examples.cursormoves1, "How the text cursor moves") + +disc(""" +It is also possible to control the movement of the cursor +more explicitly by using the $moveCursor$ method (which moves +the cursor as an offset from the start of the current <i>line</i> +NOT the current cursor, and which also has positive ^y^ offsets +move <i>down</i> (in contrast to the normal geometry where +positive ^y^ usually moves up. +""") + +eg(examples.testcursormoves2) + +disc(""" +Here the $textOut$ does not move the down a line in contrast +to the $textLine$ function which does move down. +""") + +illust(examples.cursormoves2, "How the text cursor moves again") + +heading3("Character Spacing") + +eg("""textobject.setCharSpace(charSpace)""") + +disc("""The $setCharSpace$ method adjusts one of the parameters of text -- the inter-character +spacing.""") + +eg(examples.testcharspace) + +disc("""The +$charspace$ function exercises various spacing settings. +It produces the following page.""") + +illust(examples.charspace, "Adjusting inter-character spacing") + +heading3("Word Spacing") + +eg("""textobject.setWordSpace(wordSpace)""") + +disc("The $setWordSpace$ method adjusts the space between words.") + +eg(examples.testwordspace) + +disc("""The $wordspace$ function shows what various word space settings +look like below.""") + +illust(examples.wordspace, "Adjusting word spacing") + +heading3("Horizontal Scaling") + +eg("""textobject.setHorizScale(horizScale)""") + +disc("""Lines of text can be stretched or shrunken horizontally by the +$setHorizScale$ method.""") + +eg(examples.testhorizontalscale) + +disc("""The horizontal scaling parameter ^horizScale^ +is given in percentages (with 100 as the default), so the 80 setting +shown below looks skinny. +""") +illust(examples.horizontalscale, "adjusting horizontal text scaling") + +heading3("Interline spacing (Leading)") + +eg("""textobject.setLeading(leading)""") + +disc("""The vertical offset between the point at which one +line starts and where the next starts is called the leading +offset. The $setLeading$ method adjusts the leading offset. +""") + +eg(examples.testleading) + +disc("""As shown below if the leading offset is set too small +characters of one line my write over the bottom parts of characters +in the previous line.""") + +illust(examples.leading, "adjusting the leading") + +heading3("Other text object methods") + +eg("""textobject.setTextRenderMode(mode)""") + +disc("""The $setTextRenderMode$ method allows text to be used +as a forground for clipping background drawings, for example.""") + +eg("""textobject.setRise(rise)""") + +disc(""" +The $setRise$ method <super>raises</super> or <sub>lowers</sub> text on the line +(for creating superscripts or subscripts, for example). +""") + +eg("""textobject.setFillColor(aColor); +textobject.setStrokeColor(self, aColor) +# and similar""") + +disc(""" +These color change operations change the <font color=darkviolet>color</font> of the text and are otherwise +similar to the color methods for the $canvas$ object.""") + +heading2('Paths and Lines') + +disc("""Just as textobjects are designed for the dedicated presentation +of text, path objects are designed for the dedicated construction of +graphical figures. When path objects are drawn onto a $canvas$ they +are drawn as one figure (like a rectangle) and the mode of drawing +for the entire figure can be adjusted: the lines of the figure can +be drawn (stroked) or not; the interior of the figure can be filled or +not; and so forth.""") + +disc(""" +For example the $star$ function uses a path object +to draw a star +""") + +eg(examples.teststar) + +disc(""" +The $star$ function has been designed to be useful in illustrating +various line style parameters supported by $pdfgen$. +""") + +illust(examples.star, "line style parameters") + +heading3("Line join settings") + +disc(""" +The $setLineJoin$ method can adjust whether line segments meet in a point +a square or a rounded vertex. +""") + +eg(examples.testjoins) + +disc(""" +The line join setting is only really of interest for thick lines because +it cannot be seen clearly for thin lines. +""") + +illust(examples.joins, "different line join styles") + +heading3("Line cap settings") + +disc("""The line cap setting, adjusted using the $setLineCap$ method, +determines whether a terminating line +ends in a square exactly at the vertex, a square over the vertex +or a half circle over the vertex. +""") + +eg(examples.testcaps) + +disc("""The line cap setting, like the line join setting, is only clearly +visible when the lines are thick.""") + +illust(examples.caps, "line cap settings") + +heading3("Dashes and broken lines") + +disc(""" +The $setDash$ method allows lines to be broken into dots or dashes. +""") + +eg(examples.testdashes) + +disc(""" +The patterns for the dashes or dots can be in a simple on/off repeating pattern +or they can be specified in a complex repeating pattern. +""") + +illust(examples.dashes, "some dash patterns") + +heading3("Creating complex figures with path objects") + +disc(""" +Combinations of lines, curves, arcs and other figures +can be combined into a single figure using path objects. +For example the function shown below constructs two path +objects using lines and curves. +This function will be used later on as part of a +pencil icon construction. +""") + +eg(examples.testpenciltip) + +disc(""" +Note that the interior of the pencil tip is filled +as one object even though it is constructed from +several lines and curves. The pencil lead is then +drawn over it using a new path object. +""") + +illust(examples.penciltip, "a pencil tip") + +heading2('Rectangles, circles, ellipses') + +disc(""" +The $pdfgen$ module supports a number of generally useful shapes +such as rectangles, rounded rectangles, ellipses, and circles. +Each of these figures can be used in path objects or can be drawn +directly on a $canvas$. For example the $pencil$ function below +draws a pencil icon using rectangles and rounded rectangles with +various fill colors and a few other annotations. +""") + +eg(examples.testpencil) + +pencilnote() + +disc(""" +Note that this function is used to create the "margin pencil" to the left. +Also note that the order in which the elements are drawn are important +because, for example, the white rectangles "erase" parts of a black rectangle +and the "tip" paints over part of the yellow rectangle. +""") + +illust(examples.pencil, "a whole pencil") + +heading2('Bezier curves') + +disc(""" +Programs that wish to construct figures with curving borders +generally use Bezier curves to form the borders. +""") + +eg(examples.testbezier) + +disc(""" +A Bezier curve is specified by four control points +$(x1,y1)$, $(x2,y2)$, $(x3,y3)$, $(x4,y4)$. +The curve starts at $(x1,y1)$ and ends at $(x4,y4)$ +and the line segment from $(x1,y1)$ to $(x2,y2)$ +and the line segment from $(x3,y3)$ to $(x4,y4)$ +both form tangents to the curve. Furthermore the +curve is entirely contained in the convex figure with vertices +at the control points. +""") + +illust(examples.bezier, "basic bezier curves") + +disc(""" +The drawing above (the output of $testbezier$) shows +a bezier curves, the tangent lines defined by the control points +and the convex figure with vertices at the control points. +""") + +heading3("Smoothly joining bezier curve sequences") + +disc(""" +It is often useful to join several bezier curves to form a +single smooth curve. To construct a larger smooth curve from +several bezier curves make sure that the tangent lines to adjacent +bezier curves that join at a control point lie on the same line. +""") + +eg(examples.testbezier2) + +disc(""" +The figure created by $testbezier2$ describes a smooth +complex curve because adjacent tangent lines "line up" as +illustrated below. +""") + +illust(examples.bezier2, "bezier curves") + +heading2("Path object methods") + +disc(""" +Path objects build complex graphical figures by setting +the "pen" or "brush" at a start point on the canvas and drawing +lines or curves to additional points on the canvas. Most operations +apply paint on the canvas starting at the end point of the last +operation and leave the brush at a new end point. +""") + +eg("""pathobject.moveTo(x,y)""") + +disc(""" +The $moveTo$ method lifts the brush (ending any current sequence +of lines or curves if there is one) and replaces the brush at the +new ^(x,y)^ location on the canvas to start a new path sequence. +""") + +eg("""pathobject.lineTo(x,y)""") + +disc(""" +The $lineTo$ method paints straight line segment from the current brush +location to the new ^(x,y)^ location. +""") + +eg("""pathobject.curveTo(x1, y1, x2, y2, x3, y3) """) + +disc(""" +The $curveTo$ method starts painting a Bezier curve beginning at +the current brush location, using ^(x1,y1)^, ^(x2,y2)^, and ^(x3,y3)^ +as the other three control points, leaving the brush on ^(x3,y3)^. +""") + +eg("""pathobject.arc(x1,y1, x2,y2, startAng=0, extent=90) """) + +eg("""pathobject.arcTo(x1,y1, x2,y2, startAng=0, extent=90) """) + +disc(""" +The $arc$ and $arcTo$ methods paint partial ellipses. The $arc$ method first "lifts the brush" +and starts a new shape sequence. The $arcTo$ method joins the start of +the partial ellipse to the current +shape sequence by line segment before drawing the partial ellipse. The points +^(x1,y1)^ and ^(x2,y2)^ define opposite corner points of a rectangle enclosing +the ellipse. The $startAng$ is an angle (in degrees) specifying where to begin +the partial ellipse where the 0 angle is the midpoint of the right border of the enclosing +rectangle (when ^(x1,y1)^ is the lower left corner and ^(x2,y2)^ is the upper +right corner). The $extent$ is the angle in degrees to traverse on the ellipse. +""") + +eg(examples.testarcs) + +disc("""The $arcs$ function above exercises the two partial ellipse methods. +It produces the following drawing.""") + +illust(examples.arcs, "arcs in path objects") + +eg("""pathobject.rect(x, y, width, height) """) + +disc("""The $rect$ method draws a rectangle with lower left corner +at ^(x,y)^ of the specified ^width^ and ^height^.""") + +eg("""pathobject.ellipse(x, y, width, height)""") + +disc("""The $ellipse$ method +draws an ellipse enclosed in the rectange with lower left corner +at ^(x,y)^ of the specified ^width^ and ^height^. +""") + +eg("""pathobject.circle(x_cen, y_cen, r) """) + +disc("""The $circle$ method +draws a circle centered at ^(x_cen, y_cen)^ with radius ^r^. +""") + +eg(examples.testvariousshapes) + +disc(""" +The $variousshapes$ function above shows a rectangle, circle and ellipse +placed in a frame of reference grid. +""") + +illust(examples.variousshapes, "rectangles, circles, ellipses in path objects") + +eg("""pathobject.close() """) + +disc(""" +The $close$ method closes the current graphical figure +by painting a line segment from the last point of the figure +to the starting point of the figure (the the most +recent point where the brush was placed on the paper by $moveTo$ +or $arc$ or other placement operations). +""") + +eg(examples.testclosingfigures) + +disc(""" +The $closingfigures$ function illustrates the +effect of closing or not closing figures including a line +segment and a partial ellipse. +""") + +illust(examples.closingfigures, "closing and not closing pathobject figures") + +disc(""" +Closing or not closing graphical figures effects only the stroked outline +of a figure, not the filling of the figure as illustrated above. +""") + + +disc(""" +For a more extensive example of drawing using a path object +examine the $hand$ function. +""") + +eg(examples.testhand) + +disc(""" +In debug mode (the default) the $hand$ function shows the tangent line segments +to the bezier curves used to compose the figure. Note that where the segments +line up the curves join smoothly, but where they do not line up the curves show +a "sharp edge". +""") + +illust(examples.hand, "an outline of a hand using bezier curves") + +disc(""" +Used in non-debug mode the $hand$ function only shows the +Bezier curves. With the $fill$ parameter set the figure is +filled using the current fill color. +""") + +eg(examples.testhand2) + +disc(""" +Note that the "stroking" of the border draws over the interior fill where +they overlap. +""") + +illust(examples.hand2, "the finished hand, filled") + + + +heading2("Further Reading: The ReportLab Graphics Library") + +disc(""" +So far the graphics we have seen was created on a fairly low level. +It should be noted, though, that there is another way of creating +much more sophisticated graphics using the emerging dedicated +high-level <i>ReportLab Graphics Library</i>. +""") + +disc(""" +It can be used to produce high-quality, platform-independant, +reusable graphics for different output formats (vector and bitmap) +like PDF, EPS and soon others like SVG. +""") + +disc(""" +A thorough description of its philsophy and features is beyond the +scope of this general user guide and the reader is recommended to +continue with the <i>"ReportLab Graphics Guide"</i>. +There she will find information about the existing components and +how to create customized ones. +""") + +disc(""" +Also, the graphics guide contains a presentation of an emerging +charting package and its components (labels, axes, legends and +different types of charts like bar, line and pie charts) that +builds directly on the graphics library. +""") + + +##### FILL THEM IN diff --git a/bin/reportlab/docs/userguide/ch2a_fonts.py b/bin/reportlab/docs/userguide/ch2a_fonts.py new file mode 100644 index 00000000000..460305d42a1 --- /dev/null +++ b/bin/reportlab/docs/userguide/ch2a_fonts.py @@ -0,0 +1,513 @@ +#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/docs/userguide/ch2a_fonts.py +from reportlab.tools.docco.rl_doc_utils import * +from reportlab.lib.codecharts import SingleByteEncodingChart +from reportlab.platypus import Image +import reportlab + +heading1("Fonts and encodings") + +disc(""" +This chapter covers fonts, encodings and Asian language capabilities. +If you are purely concerned with generating PDFs for Western +European languages, you can just read the "Unicode is the default" section +below and skip the rest on a first reading. +We expect this section to grow considerably over time. We +hope that Open Source will enable us to give better support for +more of the world's languages than other tools, and we welcome +feedback and help in this area. +""") + +heading2("Unicode and UTF8 are the default input encodings") + +disc(""" +Starting with reportlab Version 2.0 (May 2006), all text input you +provide to our APIs should be in UTF8 or as Python Unicode objects. +This applies to arguments to canvas.drawString and related APIs, +table cell content, drawing object parameters, and paragraph source +text. +""") + + +disc(""" +We considered making the input encoding configurable or even locale-dependent, +but decided that "explicit is better than implicit".""") + +disc(""" +This simplifies many things we used to do previously regarding greek +letters, symbols and so on. To display any character, find out its +unicode code point, and make sure the font you are using is able +to display it.""") + +disc(""" +If you are adapting a ReportLab 1.x application, or reading data from +another source which contains single-byte data (e.g. latin-1 or WinAnsi), +you need to do a conversion into Unicode. The Python codecs package now +includes converters for all the common encodings, including Asian ones. +""") + + + +disc(u""" +If your data is not encoded as UTF8, you will get a UnicodeDecodeError as +soon as you feed in a non-ASCII character. For example, this snippet below is +attempting to read in and print a series of names, including one with a French +accent: ^Marc-Andr\u00e9 Lemburg^. The standard error is quite helpful and tells you +what character it doesn't like: +""") + +eg(u""" +>>> from reportlab.pdfgen.canvas import Canvas +>>> c = Canvas('temp.pdf') +>>> y = 700 +>>> for line in file('latin_python_gurus.txt','r'): +... c.drawString(100, y, line.strip()) +... +Traceback (most recent call last): +... +UnicodeDecodeError: 'utf8' codec can't decode bytes in position 9-11: invalid data +-->\u00e9 L<--emburg +>>> +""") + + +disc(""" +The simplest fix is just to convert your data to unicode, saying which encoding +it comes from, like this:""") + +eg(""" +>>> for line in file('latin_input.txt','r'): +... uniLine = unicode(line, 'latin-1') +... c.drawString(100, y, uniLine.strip()) +>>> +>>> c.save() +""") + + +heading2("Changing the built-in fonts output encoding") + +disc(""" +There are still a number of places in the code, including the rl_config +defaultEncoding parameter, and arguments passed to various Font constructors. +These generally relate to the OUTPUT encoding used when we write data in the font +file. This affects which characters are actually available in the font if +you are using Type 1 fonts, since only 256 glyphs can be available at +one time. Unless you have a very specific need for +MacRoman or MacExpert encoding characters, we advise you to ignore +this. By default the standard fonts (Helvetica, Courier, Times Roman) +will offer the glyphs available in Latin-1. If you try to print a non-Latin-1 +character using the built-in Helvetica, you'll see a rectangle or blob. + +""") + + +heading2("Using non-standard Type 1 fonts") + +disc(""" +As discussed in the previous chapter, every copy of Acrobat Reader +comes with 14 standard fonts built in. Therefore, the ReportLab +PDF Library only needs to refer to these by name. If you want +to use other fonts, they must be available to your code and +will be embedded in the PDF document.""") + +disc(""" +You can use the mechanism described below to include arbitrary +fonts in your documents. Just van Rossum has kindly donated a Type 1 +font named <i>LettErrorRobot-Chrome</i> which we may +use for testing and/or documenting purposes (and which you may +use as well). It comes bundled with the ReportLab distribution in the +directory $reportlab/fonts$. +""") + +disc(""" +Right now font-embedding relies on font description files in the Adobe +AFM ('Adobe Font Metrics') and PFB ('Printer Font Binary') format. The +former is an ASCII file and contains information about the characters +('glyphs') in the font such as height, width, bounding box info and +other 'metrics', while the latter is a binary file that describes the +shapes of the font. The $reportlab/fonts$ directory contains the files +$'LeERC___.AFM'$ and $'LeERC___.PFB'$ that are used as an example +font. +""") + +disc(""" +In the following example locate the folder containing the test font and +register it for future use with the $pdfmetrics$ module, +after which we can use it like any other standard font. +""") + + +eg(""" +import os +import reportlab +folder = os.path.dirname(reportlab.__file__) + os.sep + 'fonts' +afmFile = os.path.join(folder, 'LeERC___.AFM') +pfbFile = os.path.join(folder, 'LeERC___.PFB') + +from reportlab.pdfbase import pdfmetrics +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') +""") + + +disc(""" +Note that the argument "WinAnsiEncoding" has nothing to do with the input; +it's to say which set of characters within the font file will be active +and available. +""") + +illust(examples.customfont1, "Using a very non-standard font") + +disc(""" +The font's facename comes from the AFM file's $FontName$ field. +In the example above we knew the name in advance, but quite +often the names of font description files are pretty cryptic +and then you might want to retrieve the name from an AFM file +automatically. +When lacking a more sophisticated method you can use some +code as simple as this: +""") + +eg(""" +class FontNameNotFoundError(Exception): + pass + + +def findFontName(path): + "Extract a font name from an AFM file." + + f = open(path) + + found = 0 + while not found: + line = f.readline()[:-1] + if not found and line[:16] == 'StartCharMetrics': + raise FontNameNotFoundError, path + if line[:8] == 'FontName': + fontName = line[9:] + found = 1 + + return fontName +""") + +disc(""" +In the <i>LettErrorRobot-Chrome</i> example we explicitely specified +the place of the font description files to be loaded. +In general, you'll prefer to store your fonts in some canonic +locations and make the embedding mechanism aware of them. +Using the same configuration mechanism we've already seen at the +beginning of this section we can indicate a default search path +for Type-1 fonts. +""") + +disc(""" +Unfortunately, there is no reliable standard yet for such +locations (not even on the same platform) and, hence, you might +have to edit the file $reportlab/rl_config.py$ to modify the +value of the $T1SearchPath$ identifier to contain additional +directories. Our own recommendation is to use the ^reportlab/fonts^ +folder in development; and to have any needed fonts as packaged parts of +your application in any kind of controlled server deployment. This insulates +you from fonts being installed and uninstalled by other software or system +administrator. +""") + +heading3("Warnings about missing glyphs") +disc("""If you specify an encoding, it is generally assumed that +the font designer has provided all the needed glyphs. However, +this is not always true. In the case of our example font, +the letters of the alphabet are present, but many symbols and +accents are missing. The default behaviour is for the font to +print a 'notdef' character - typically a blob, dot or space - +when passed a character it cannot draw. However, you can ask +the library to warn you instead; the code below (executed +before loading a font) will cause warnings to be generated +for any glyphs not in the font when you register it.""") + +eg(""" +import reportlab.rl_config +reportlab.rl_config.warnOnMissingFontGlyphs = 0 +""") + + + +heading2("Standard Single-Byte Font Encodings") +disc(""" +This section shows you the glyphs available in the common encodings. +""") + + +disc("""The code chart below shows the characters in the $WinAnsiEncoding$. +This is the standard encoding on Windows and many Unix systems in America +and Western Europe. It is also knows as Code Page 1252, and is practically +identical to ISO-Latin-1 (it contains one or two extra characters). This +is the default encoding used by the Reportlab PDF Library. It was generated from +a standard routine in $reportlab/lib$, $codecharts.py$, +which can be used to display the contents of fonts. The index numbers +along the edges are in hex.""") + +cht1 = SingleByteEncodingChart(encodingName='WinAnsiEncoding',charsPerRow=32, boxSize=12) +illust(lambda canv: cht1.drawOn(canv, 0, 0), "WinAnsi Encoding", cht1.width, cht1.height) + +disc("""The code chart below shows the characters in the $MacRomanEncoding$. +as it sounds, this is the standard encoding on Macintosh computers in +America and Western Europe. As usual with non-unicode encodings, the first +128 code points (top 4 rows in this case) are the ASCII standard and agree +with the WinAnsi code chart above; but the bottom 4 rows differ.""") +cht2 = SingleByteEncodingChart(encodingName='MacRomanEncoding',charsPerRow=32, boxSize=12) +illust(lambda canv: cht2.drawOn(canv, 0, 0), "MacRoman Encoding", cht2.width, cht2.height) + +disc("""These two encodings are available for the standard fonts (Helvetica, +Times-Roman and Courier and their variants) and will be available for most +commercial fonts including those from Adobe. However, some fonts contain non- +text glyphs and the concept does not really apply. For example, ZapfDingbats +and Symbol can each be treated as having their own encoding.""") + +cht3 = SingleByteEncodingChart(faceName='ZapfDingbats',encodingName='ZapfDingbatsEncoding',charsPerRow=32, boxSize=12) +illust(lambda canv: cht3.drawOn(canv, 0, 0), "ZapfDingbats and its one and only encoding", cht3.width, cht3.height) + +cht4 = SingleByteEncodingChart(faceName='Symbol',encodingName='SymbolEncoding',charsPerRow=32, boxSize=12) +illust(lambda canv: cht4.drawOn(canv, 0, 0), "Symbol and its one and only encoding", cht4.width, cht4.height) + + +CPage(5) +heading2("TrueType Font Support") +disc(""" +Marius Gedminas ($mgedmin@delfi.lt$) with the help of Viktorija Zaksiene ($vika@pov.lt$) +have contributed support for embedded TrueType fonts. TrueType fonts work in Unicode/UTF8 +and are not limited to 256 characters.""") + + +CPage(3) +disc("""We use <b>$reportlab.pdfbase.ttfonts.TTFont$</b> to create a true type +font object and register using <b>$reportlab.pdfbase.pdfmetrics.registerFont$</b>. +In pdfgen drawing directly to the canvas we can do""") +eg(""" +# 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')) +canvas.setFont(Rina, 32) +canvas.drawString(10, 150, "Some text encoded in UTF-8") +canvas.drawString(10, 100, "In the Rina TT Font!") +""") +illust(examples.ttffont1, "Using a the Rina TrueType Font") +disc("""In the above example the true type font object is created using""") +eg(""" + TTFont(name,filename) +""") +disc("""so that the ReportLab internal name is given by the first argument and the second argument +is a string(or file like object) denoting the font's TTF file. In Marius' original patch the filename +was supposed to be exactly correct, but we have modified things so that if the filename is relative +then a search for the corresponding file is done in the current directory and then in directories +specified by $reportlab.rl_config.TTFSearchpath$!""") + +from reportlab.lib.styles import ParagraphStyle + +from reportlab.lib.fonts import addMapping +addMapping('Rina', 0, 0, 'Rina') +addMapping('Rina', 0, 1, 'Rina') +addMapping('Rina', 1, 0, 'Rina') +addMapping('Rina', 1, 1, 'Rina') + +disc("""Before using the TT Fonts in Platypus we should add a mapping from the family name to the +individual font names that describe the behaviour under the $<b>$ and $<i>$ attributes.""") + +eg(""" +from reportlab.lib.fonts import addMapping +addMapping('Rina', 0, 0, 'Rina') #normal +addMapping('Rina', 0, 1, 'Rina') #italic +addMapping('Rina', 1, 0, 'Rina') #bold +addMapping('Rina', 1, 1, 'Rina') #italic and bold +""") + +disc("""We only have a Rina regular font, no bold or italic, so we must map all to the +same internal fontname. ^<b>^ and ^<i>^ tags may now be used safely, but +have no effect. +After registering and mapping +the Rina font as above we can use paragraph text like""") +parabox2("""<font name="Times-Roman" size="14">This is in Times-Roman</font> +<font name="Rina" color="magenta" size="14">and this is in magenta <b>Rina!</b></font>""","Using TTF fonts in paragraphs") + + + + +heading2("Asian Font Support") +disc("""The Reportlab PDF Library aims to expose full support for Asian fonts. +PDF is the first really portable solution for Asian text handling. There are +two main approaches for this: Adobe's Asian Language Packs, or TrueType fonts. +""") + +heading3("Asian Language Packs") +disc(""" +This approach offers the best performance since nothing needs embedding in the PDF file; +as with the standard fonts, everything is on the reader.""") + +disc(""" +Adobe makes available add-ons for each main language. In Adobe Reader 6.0 and 7.0, you +will be prompted to download and install these as soon as you try to open a document +using them. In earlier versions, you would see an error message on opening an Asian document +and had to know what to do. +""") + +disc(""" +Japanese, Traditional Chinese (Taiwan/Hong Kong), Simplified Chinese (mainland China) +and Korean are all supported and our software knows about the following fonts: +""") +bullet(""" +$chs$ = Chinese Simplified (mainland): '$STSong-Light$' +""") +bullet(""" +$cht$ = Chinese Traditional (Taiwan): '$MSung-Light$', '$MHei-Medium$' +""") +bullet(""" +$kor$ = Korean: '$HYSMyeongJoStd-Medium$','$HYGothic-Medium$' +""") +bullet(""" +$jpn$ = Japanese: '$HeiseiMin-W3$', '$HeiseiKakuGo-W5$' +""") + + +disc("""Since many users will not have the font packs installed, we have included +a rather grainy ^bitmap^ of some Japanese characters. We will discuss below what is needed to +generate them.""") +# include a bitmap of some Asian text +I=os.path.join(os.path.dirname(reportlab.__file__),'docs','images','jpnchars.jpg') +try: + getStory().append(Image(I)) +except: + disc("""An image should have appeared here.""") + +disc("""Prior to Version 2.0, you had to specify one of many native encodings +when registering a CID Font. In version 2.0 you should a new UnicodeCIDFont +class.""") + +eg(""" +from reportlab.pdfbase import pdfmetrics +from reportlab.pdfbase.cidfonts import UnicodeCIDFont +pdfmetrics.registerFont(UnicodeCIDFont('HeiseiMin-W3')) +canvas.setFont('HeiseiMin-W3', 16) + +# the two unicode characters below are "Tokyo" +msg = u'\u6771\u4EAC : Unicode font, unicode input' +canvas.drawString(100, 675, msg) +""") +#had to double-escape the slashes above to get escapes into the PDF + +disc("""The old coding style with explicit encodings should still work, but is now +only relevant if you need to construct vertical text. We aim to add more readable options +for horizontal and vertical text to the UnicodeCIDFont constructor in future. +The following four test scripts generate samples in the corresponding languages:""") +eg("""reportlab/test/test_multibyte_jpn.py +reportlab/test/test_multibyte_kor.py +reportlab/test/test_multibyte_chs.py +reportlab/test/test_multibyte_cht.py""") + +## put back in when we have vertical text... +##disc("""The illustration below shows part of the first page +##of the Japanese output sample. It shows both horizontal and vertical +##writing, and illustrates the ability to mix variable-width Latin +##characters in Asian sentences. The choice of horizontal and vertical +##writing is determined by the encoding, which ends in 'H' or 'V'. +##Whether an encoding uses fixed-width or variable-width versions +##of Latin characters also depends on the encoding used; see the definitions +##below.""") +## +##Illustration(image("../images/jpn.gif", width=531*0.50, +##height=435*0.50), 'Output from test_multibyte_jpn.py') +## +##caption(""" +##Output from test_multibyte_jpn.py +##""") + + + + +disc("""In previous versions of the ReportLab PDF Library, we had to make +use of Adobe's CMap files (located near Acrobat Reader if the Asian Language +packs were installed). Now that we only have one encoding to deal with, the +character width data is embedded in the package, and CMap files are not needed +for generation. The CMap search path in ^rl_config.py^ is now deprecated +and has no effect if you restrict yourself to UnicodeCIDFont. +""") + + +heading3("TrueType fonts with Asian characters") +disc(""" +This is the easy way to do it. No special handling at all is needed to +work with Asian TrueType fonts. Windows users who have installed, for example, +Japanese as an option in Control Panel, will have a font "msmincho.ttf" which +can be used. However, be aware that it takes time to parse the fonts, and that +quite large subsets may need to be embedded in your PDFs. We can also now parse +files ending in .ttc, which are a slight variation of .ttf. + +""") + + +heading3("To Do") +disc("""We expect to be developing this area of the package for some time.accept2dyear +Here is an outline of the main priorities. We welcome help!""") + +bullet(""" +Ensure that we have accurate character metrics for all encodings in horizontal and +vertical writing.""") + +bullet(""" +Add options to ^UnicodeCIDFont^ to allow vertical and proportional variants where the font permits it.""") + + +bullet(""" +Improve the word wrapping code in paragraphs and allow vertical writing.""") + + + +CPage(5) +heading2("RenderPM tests") + +disc("""This may also be the best place to mention the test function of $reportlab/graphics/renderPM.py$, +which can be considered the cannonical place for tests which exercise renderPM (the "PixMap Renderer", +as opposed to renderPDF, renderPS or renderSVG).""") + +disc("""If you run this from the command line, you should see lots of output like the following.""") + +eg("""C:\\code\\reportlab\\graphics>renderPM.py +wrote pmout\\renderPM0.gif +wrote pmout\\renderPM0.tif +wrote pmout\\renderPM0.png +wrote pmout\\renderPM0.jpg +wrote pmout\\renderPM0.pct +... +wrote pmout\\renderPM12.gif +wrote pmout\\renderPM12.tif +wrote pmout\\renderPM12.png +wrote pmout\\renderPM12.jpg +wrote pmout\\renderPM12.pct +wrote pmout\\index.html""") + +disc("""This runs a number of tests progressing from a "Hello World" test, through various tests of +Lines; text strings in a number of sizes, fonts, colours and alignments; the basic shapes; translated +and rotated groups; scaled coordinates; rotated strings; nested groups; anchoring and non-standard fonts.""") + +disc("""It creates a subdirectory called $pmout$, writes the image files into it, and writes an +$index.html$ page which makes it easy to refer to all the results.""") + +disc("""The font-related tests which you may wish to look at are test #11 ('Text strings in a non-standard font') +and test #12 ('Test Various Fonts').""") + + + + +##### FILL THEM IN diff --git a/bin/reportlab/docs/userguide/ch3_pdffeatures.py b/bin/reportlab/docs/userguide/ch3_pdffeatures.py new file mode 100644 index 00000000000..36fe8b8be07 --- /dev/null +++ b/bin/reportlab/docs/userguide/ch3_pdffeatures.py @@ -0,0 +1,271 @@ +#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/docs/userguide/ch3_pdffeatures.py +from reportlab.tools.docco.rl_doc_utils import * + + +heading1("Exposing PDF Special Capabilities") +disc("""PDF provides a number of features to make electronic + document viewing more efficient and comfortable, and + our library exposes a number of these.""") + +heading2("Forms") +disc("""The Form feature lets you create a block of graphics and text + once near the start of a PDF file, and then simply refer to it on + subsequent pages. If you are dealing with a run of 5000 repetitive + business forms - for example, one-page invoices or payslips - you + only need to store the backdrop once and simply draw the changing + text on each page. Used correctly, forms can dramatically cut + file size and production time, and apparently even speed things + up on the printer. + """) +disc("""Forms do not need to refer to a whole page; anything which + might be repeated often should be placed in a form.""") +disc("""The example below shows the basic sequence used. A real + program would probably define the forms up front and refer to + them from another location.""") + + +eg(examples.testforms) + +heading2("Links and Destinations") +disc("""PDF supports internal hyperlinks. There is a very wide + range of link types, destination types and events which + can be triggered by a click. At the moment we just + support the basic ability to jump from one part of a document + to another, and to control the zoom level of the window after + the jump. The bookmarkPage method defines a destination that + is the endpoint of a jump.""") +#todo("code example here...") + +eg(""" + canvas.bookmarkPage(name, + fitType="Fit", + left=None, + top=None, + bottom=None, + right=None, + zoom=None + ) +""") +disc(""" +By default the $bookmarkPage$ method defines the page itself as the +destination. After jumping to an endpoint defined by bookmarkPage, +the PDF browser will display the whole page, scaling it to fit the +screen:""") + +eg("""canvas.bookmarkPage(name)""") + +disc("""The $bookmarkPage$ method can be instructed to display the +page in a number of different ways by providing a $fitType$ +parameter.""") + +eg("") + +t = Table([ + ['fitType','Parameters Required','Meaning'], + ['Fit',None,'Entire page fits in window (the default)'], + ['FitH','top','Top coord at top of window, width scaled to fit'], + ['FitV','left','Left coord at left of window, height scaled to fit'], + ['FitR','left bottom right top','Scale window to fit the specified rectangle'], + ['XYZ','left top zoom','Fine grained control. If you omit a parameter\nthe PDF browser interprets it as "leave as is"'] + ]) +t.setStyle(TableStyle([ + ('FONT',(0,0),(-1,1),'Times-Bold',10,12), + ('VALIGN',(0,0),(-1,-1),'MIDDLE'), + ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black), + ('BOX', (0,0), (-1,-1), 0.25, colors.black), + ])) + +getStory().append(t) +caption("""Table <seq template="%(Chapter)s-%(Table+)s"/> - Required attributes for different fit types""") + +disc(""" +Note : $fitType$ settings are case-sensitive so $fitType="FIT"$ is invalid$ +""") + + +disc(""" +Sometimes you want the destination of a jump to be some part of a page. +The $FitR$ fitType allows you to identify a particular rectangle, scaling +the area to fit the entire page. +""") + +disc(""" +To set the display to a particular x and y coordinate of the page and to +control the zoom directly use fitType="XYZ". +""") + +eg(""" +canvas.bookmarkPage('my_bookmark',fitType="XYZ",left=0,top=200) +""") + + + +disc(""" +This destination is at the leftmost of the page with the top of the screen +at position 200. Because $zoom$ was not set the zoom remains at whatever the +user had it set to. +""") + +eg(""" +canvas.bookmarkPage('my_bookmark',fitType="XYZ",left=0,top=200,zoom=2) +""") + +disc("""This time zoom is set to expand the page 2X its normal size.""") + +disc(""" +Note : Both $XYZ$ and $FitR$ fitTypes require that their positional parameters +($top, bottom, left, right$) be specified in terms of the default user space. +They ignore any geometric transform in effect in the canvas graphic state. +""") + + + +pencilnote() + +disc(""" +<i>Note:</i> Two previous bookmark methods are supported but deprecated now +that bookmarkPage is so general. These are $bookmarkHorizontalAbsolute$ +and $bookmarkHorizontal$. +""") + +heading3("Defining internal links") +eg(""" + canvas.linkAbsolute(contents, destinationname, Rect=None, addtopage=1, name=None, **kw) + """) + +disc(""" + The $linkAbsolute$ method defines a starting point for a jump. When the user + is browsing the generated document using a dynamic viewer (such as Acrobat Reader) + when the mouse is clicked when the pointer is within the rectangle specified + by $Rect$ the viewer will jump to the endpoint associated with $destinationname$. + As in the case with $bookmarkHorizontalAbsolute$ the rectangle $Rect$ must be + specified in terms of the default user space. The $contents$ parameter specifies + a chunk of text which displays in the viewer if the user left-clicks on the region. +""") + +disc(""" +The rectangle $Rect$ must be specified in terms of a tuple ^(x1,y1,x2,y2)^ identifying +the lower left and upper right points of the rectangle in default user space. +""") + +disc(""" +For example the code +""") + +eg(""" + canvas.bookmarkPage("Meaning_of_life") +""") + +disc(""" +defines a location as the whole of the current page with the identifier +$Meaning_of_life$. To create a rectangular link to it while drawing a possibly +different page, we would use this code: +""") + +eg(""" + canvas.linkAbsolute("Find the Meaning of Life", "Meaning_of_life", + (inch, inch, 6*inch, 2*inch)) +""") + +disc(""" +By default during interactive viewing a rectangle appears around the +link. Use the keyword argument $Border='[0 0 0]'$ to +suppress the visible rectangle around the during viewing link. +For example +""") + +eg(""" + canvas.linkAbsolute("Meaning of Life", "Meaning_of_life", + (inch, inch, 6*inch, 2*inch), Border='[0 0 0]') +""") + + +heading2("Outline Trees") +disc("""Acrobat Reader has a navigation page which can hold a + document outline; it should normally be visible when you + open this guide. We provide some simple methods to add + outline entries. Typically, a program to make a document + (such as this user guide) will call the method + $canvas.addOutlineEntry(^self, title, key, level=0, + closed=None^)$ as it reaches each heading in the document. + """) + +disc("""^title^ is the caption which will be displayed in + the left pane. The ^key^ must be a string which is + unique within the document and which names a bookmark, + as with the hyperlinks. The ^level^ is zero - the + uppermost level - unless otherwise specified, and + it is an error to go down more than one level at a time + (for example to follow a level 0 heading by a level 2 + heading). Finally, the ^closed^ argument specifies + whether the node in the outline pane is closed + or opened by default.""") + +disc("""The snippet below is taken from the document template + that formats this user guide. A central processor looks + at each paragraph in turn, and makes a new outline entry + when a new chapter occurs, taking the chapter heading text + as the caption text. The key is obtained from the + chapter number (not shown here), so Chapter 2 has the + key 'ch2'. The bookmark to which the + outline entry points aims at the whole page, but it could + as easily have been an individual paragraph. + """) + +eg(""" +#abridged code from our document template +if paragraph.style == 'Heading1': + self.chapter = paragraph.getPlainText() + key = 'ch%d' % self.chapterNo + self.canv.bookmarkPage(key) + self.canv.addOutlineEntry(paragraph.getPlainText(), + key, 0, 0) + """) + +heading2("Page Transition Effects") + + +eg(""" + canvas.setPageTransition(self, effectname=None, duration=1, + direction=0,dimension='H',motion='I') + """) + +disc(""" +The $setPageTransition$ method specifies how one page will be replaced with +the next. By setting the page transition effect to "dissolve" for example +the current page will appear to melt away when it is replaced by the next +page during interactive viewing. These effects are useful in spicing up +slide presentations, among other places. +Please see the reference manual for more detail on how to use this method. +""") + +heading2("Internal File Annotations") + +eg(""" + canvas.setAuthor(name) + canvas.setTitle(title) + canvas.setSubject(subj) + """) + +disc(""" +These methods have no automatically seen visible effect on the document. +They add internal annotations to the document. These annotations can be +viewed using the "Document Info" menu item of the browser and they also can +be used as a simple standard way of providing basic information about the +document to archiving software which need not parse the entire +file. To find the annotations view the $*.pdf$ output file using a standard +text editor (such as $notepad$ on MS/Windows or $vi$ or $emacs$ on unix) and look +for the string $/Author$ in the file contents. +""") + +eg(examples.testannotations) + +disc(""" +If you want the subject, title, and author to automatically display +in the document when viewed and printed you must paint them onto the +document like any other text. +""") + +illust(examples.annotations, "Setting document internal annotations") diff --git a/bin/reportlab/docs/userguide/ch4_platypus_concepts.py b/bin/reportlab/docs/userguide/ch4_platypus_concepts.py new file mode 100644 index 00000000000..b3b6d17a748 --- /dev/null +++ b/bin/reportlab/docs/userguide/ch4_platypus_concepts.py @@ -0,0 +1,509 @@ +#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/docs/userguide/ch4_platypus_concepts.py +from reportlab.tools.docco.rl_doc_utils import * + +#####################################################################################################3 + + +heading1("PLATYPUS - Page Layout and Typography Using Scripts") + +heading2("Design Goals") + +disc(""" +Platypus stands for "Page Layout and Typography Using Scripts". It is a high +level page layout library which lets you programmatically create complex +documents with a minimum of effort. +""") + + + +disc(""" +The design of Platypus seeks to separate "high level" layout decisions +from the document content as much as possible. Thus, for example, paragraphs +are constructed using paragraph styles and pages are constructed +using page templates with the intention that hundreds of +documents with thousands of pages can be reformatted to different +style specifications with the modifications of a few lines in a single +shared file which contains the paragraph styles and page layout specifications. +""") + + +disc(""" +The overall design of Platypus can be thought of has having +several layers, top down, these are""") + +disc("<b>$DocTemplates$</b> the outermost container for the document;") + +disc("<b>$PageTemplates$</b> specifications for layouts of pages of various kinds;") + +disc("<b>$Frames$</b> specifications of regions in pages that can contain flowing text or graphics.") + +disc("""<b>$Flowables$</b> text or graphic elements that should be "flowed + into the document (i.e. things like images, paragraphs and tables, but not things + like page footers or fixed page graphics).""") + +disc("""<b>$pdfgen.Canvas$</b> the lowest level which ultimately receives the painting of the + document from the other layers.""") + +illust(examples.doctemplateillustration, "Illustration of DocTemplate structure") + +disc(""" + The illustration above graphically illustrates the concepts of $DocTemplates$, + $PageTemplates$ and $Flowables$. It is deceptive, however, because each + of the $PageTemplates$ actually may specify the format for any number of pages + (not just one as might be inferred from the diagram). +""") + +disc(""" +$DocTemplates$ contain one or more $PageTemplates$ each of which contain one or more +$Frames$. $Flowables$ are things which can be <i>flowed</i> into a $Frame$ e.g. +a $Paragraph$ or a $Table$. +""") + +disc(""" +To use platypus you create a document from a $DocTemplate$ class and pass +a list of $Flowable$s to its $build$ method. The document +$build$ method knows how to process the list of flowables +into something reasonable. +""") + +disc(""" +Internally the $DocTemplate$ class implements page layout and formatting +using various events. Each of the events has a corresponding handler method +called $handle_XXX$ where $XXX$ is the event name. A typical event is +$frameBegin$ which occurs when the machinery begins to use a frame for the +first time. +""") + +disc(""" +A Platypus story consists of a sequence of basic elements called $Flowables$ +and these elements drive the data driven Platypus formatting engine. +To modify the behavior of the engine +a special kind of flowable, $ActionFlowables$, tell the layout engine to, +for example, skip to the next +column or change to another $PageTemplate$. +""") + + +heading2("""Getting started""") + +disc("""Consider the following code sequence which provides +a very simple "hello world" example for Platypus.""") + +eg(examples.platypussetup) + +disc("""First we import some constructors, some paragraph styles +and other conveniences from other modules.""") + +eg(examples.platypusfirstpage) + +disc("""We define the fixed features of the first page of the document +with the function above.""") + +eg(examples.platypusnextpage) + +disc("""Since we want pages after the first to look different from the +first we define an alternate layout for the fixed features +of the other pages. Note that the two functions above use +the $pdfgen$ level canvas operations to paint the annotations for +the pages. +""") + +eg(examples.platypusgo) + +disc(""" +Finally, we create a story and build the document. +Note that we are using a "canned" document template here which +comes pre-built with page templates. We are also using a pre-built +paragraph style. We are only using two types of flowables here +-- $Spacers$ and $Paragraphs$. The first $Spacer$ ensures that the +Paragraphs skip past the title string. +""") + +disc(""" +To see the output of this example program run the module +$docs/userguide/examples.py$ (from the ReportLab $docs$ distribution) +as a "top level script". The script interpretation $python examples.py$ will +generate the Platypus output $phello.pdf$. +""") + + +heading2("$Flowables$") +disc(""" +$Flowables$ are things which can be drawn and which have $wrap$, $draw$ and perhaps $split$ methods. +$Flowable$ is an abstract base class for things to be drawn and an instance knows its size +and draws in its own coordinate system (this requires the base API to provide an absolute coordinate +system when the $Flowable.draw$ method is called). To get an instance use $f=Flowable()$. +""") +disc(""" +It should be noted that the $Flowable$ class is an <i>abstract</i> class and is normally +only used as a base class. +""") +k=startKeep() +disc(""" +To illustrate the general way in which $Flowables$ are used we show how a derived class $Paragraph$ +is used and drawn on a canvas. $Paragraphs$ are so important they will get a whole chapter +to themselves. +""") +eg(""" + from reportlab.lib.styles import getSampleStyleSheet + from reportlab.platypus import Paragraph + from reportlab.pdfgen.canvas import Canvas + styleSheet = getSampleStyleSheet() + style = styleSheet['BodyText'] + P=Paragraph('This is a very silly example',style) + canv = Canvas('doc.pdf') + aW = 460 # available width and height + aH = 800 + w,h = P.wrap(aW, aH) # find required space + if w<=aW and h<=aH: + P.drawOn(canv,0,aH) + aH = aH - h # reduce the available height + canv.save() + else: + raise ValueError, "Not enough room" +""") +endKeep(k) +heading3("$Flowable$ User Methods") +eg(""" + Flowable.draw() +""") +disc("""This will be called to ask the flowable to actually render itself. +The $Flowable$ class does not implement $draw$. +The calling code should ensure that the flowable has an attribute $canv$ +which is the $pdfgen.Canvas$ which should be drawn to an that the $Canvas$ +is in an appropriate state (as regards translations rotations, etc). Normally +this method will only be called internally by the $drawOn$ method. Derived classes +must implement this method. +""") +eg(""" + Flowable.drawOn(canvas,x,y) +""") +disc(""" +This is the method which controlling programs use to render the flowable to a particular +canvas. It handles the translation to the canvas coordinate (<i>x</i>,<i>y</i>) and ensuring that +the flowable has a $canv$ attribute so that the +$draw$ method (which is not implemented in the base class) can render in an +absolute coordinate frame. +""") +eg(""" + Flowable.wrap(availWidth, availHeight) +""") +disc("""This will be called by the enclosing frame before objects +are asked their size, drawn or whatever. It returns the +size actually used.""") +eg(""" + Flowable.split(self, availWidth, availheight): +""") +disc("""This will be called by more sophisticated frames when + wrap fails. Stupid flowables should return [] meaning that they are unable to split. +Clever flowables should split themselves and return a list of flowables. It is up to +the client code to ensure that repeated attempts to split are avoided. +If the space is sufficient the split method should return [self]. +Otherwise +the flowable should rearrange itself and return a list $[f0,...]$ of flowables +which will be considered in order. The implemented split method should avoid +changing $self$ as this will allow sophisticated layout mechanisms to do multiple +passes over a list of flowables. +""") + +heading2("Guidelines for flowable positioning") + +disc("""Two methods, which by default return zero, provide guidance on vertical +spacing of flowables: +""") + +eg(""" + Flowable.getSpaceAfter(self): + Flowable.getSpaceBefore(self): +""") +disc("""These methods return how much space should follow or precede +the flowable. The space doesn't belong to the flowable itself i.e. the flowable's +$draw$ method shouldn't consider it when rendering. Controlling programs +will use the values returned in determining how much space is required by +a particular flowable in context. +""") + +disc("""All flowables have an $hAlign$ property: $('LEFT', 'RIGHT', 'CENTER' or 'CENTRE')$. +For paragraphs, which fill the full width of the frame, this has no effect. For tables, +images or other objects which are less than the width of the frame, this determines their +horizontal placement. + +""") + + +disc("""The chapters which follow will cover the most important +specific types of flowables: Paragraphs and Tables.""") + + +heading2("Frames") +disc(""" +$Frames$ are active containers which are themselves contained in $PageTemplates$. +$Frames$ have a location and size and maintain a concept of remaining drawable +space. The command +""") + +eg(""" + Frame(x1, y1, width,height, leftPadding=6, bottomPadding=6, + rightPadding=6, topPadding=6, id=None, showBoundary=0) +""") +disc("""creates a $Frame$ instance with lower left hand corner at coordinate $(x1,y1)$ +(relative to the canvas at use time) and with dimensions $width$ x $height$. The $Padding$ +arguments are positive quantities used to reduce the space available for drawing. +The $id$ argument is an identifier for use at runtime e.g. 'LeftColumn' or 'RightColumn' etc. +If the $showBoundary$ argument is non-zero then the boundary of the frame will get drawn +at run time (this is useful sometimes). +""") +heading3("$Frame$ User Methods") +eg(""" + Frame.addFromList(drawlist, canvas) +""") +disc("""consumes $Flowables$ from the front of $drawlist$ until the + frame is full. If it cannot fit one object, raises + an exception.""") + +eg(""" + Frame.split(flowable,canv) +""") +disc('''Asks the flowable to split using up the available space and return +the list of flowables. +''') + +eg(""" + Frame.drawBoundary(canvas) +""") +disc("draws the frame boundary as a rectangle (primarily for debugging).") +heading3("Using $Frames$") +disc(""" +$Frames$ can be used directly with canvases and flowables to create documents. +The $Frame.addFromList$ method handles the $wrap$ & $drawOn$ calls for you. +You don't need all of the Platypus machinery to get something useful into +PDF. +""") +eg(""" +from reportlab.pdfgen.canvas import Canvas +from reportlab.lib.styles import getSampleStyleSheet +from reportlab.lib.units import inch +from reportlab.platypus import Paragraph, Frame +styles = getSampleStyleSheet() +styleN = styles['Normal'] +styleH = styles['Heading1'] +story = [] + +#add some flowables +story.append(Paragraph("This is a Heading",styleH)) +story.append(Paragraph("This is a paragraph in <i>Normal</i> style.", + styleN)) +c = Canvas('mydoc.pdf') +f = Frame(inch, inch, 6*inch, 9*inch, showBoundary=1) +f.addFromList(story,c) +c.save() +""") + +heading2("Documents and Templates") + +disc(""" +The $BaseDocTemplate$ class implements the basic machinery for document +formatting. An instance of the class contains a list of one or more +$PageTemplates$ that can be used to describe the layout of information +on a single page. The $build$ method can be used to process +a list of $Flowables$ to produce a <b>PDF</b> document. +""") + +CPage(3.0) +heading3("The $BaseDocTemplate$ class") + +eg(""" + BaseDocTemplate(self, filename, + pagesize=defaultPageSize, + pageTemplates=[], + showBoundary=0, + leftMargin=inch, + rightMargin=inch, + topMargin=inch, + bottomMargin=inch, + allowSplitting=1, + title=None, + author=None, + _pageBreakQuick=1) +""") + +disc(""" +creates a document template suitable for creating a basic document. It comes with quite a lot +of internal machinery, but no default page templates. The required $filename$ can be a string, +the name of a file to receive the created <b>PDF</b> document; alternatively it +can be an object which has a $write$ method such as a $StringIO$ or $file$ or $socket$. +""") + +disc(""" +The allowed arguments should be self explanatory, but $showBoundary$ controls whether or +not $Frame$ boundaries are drawn which can be useful for debugging purposes. The +$allowSplitting$ argument determines whether the builtin methods should try to <i>split</i> +individual $Flowables$ across $Frames$. The $_pageBreakQuick$ argument determines whether +an attempt to do a page break should try to end all the frames on the page or not, before ending +the page. +""") + +heading4("User $BaseDocTemplate$ Methods") + +disc("""These are of direct interest to client programmers +in that they are normally expected to be used. +""") +eg(""" + BaseDocTemplate.addPageTemplates(self,pageTemplates) +""") +disc(""" +This method is used to add one or a list of $PageTemplates$ to an existing documents. +""") +eg(""" + BaseDocTemplate.build(self, flowables, filename=None, canvasmaker=canvas.Canvas) +""") +disc(""" +This is the main method which is of interest to the application +programmer. Assuming that the document instance is correctly set up the +$build$ method takes the <i>story</i> in the shape of the list of flowables +(the $flowables$ argument) and loops through the list forcing the flowables +one at a time through the formatting machinery. Effectively this causes +the $BaseDocTemplate$ instance to issue calls to the instance $handle_XXX$ methods +to process the various events. +""") +heading4("User Virtual $BaseDocTemplate$ Methods") +disc(""" +These have no semantics at all in the base class. They are intended as pure virtual hooks +into the layout machinery. Creators of immediately derived classes can override these +without worrying about affecting the properties of the layout engine. +""") +eg(""" + BaseDocTemplate.afterInit(self) +""") +disc(""" +This is called after initialisation of the base class; a derived class could overide +the method to add default $PageTemplates$. +""") + +eg(""" + BaseDocTemplate.afterPage(self) +""") +disc("""This is called after page processing, and + immediately after the afterDrawPage method + of the current page template. A derived class could +use this to do things which are dependent on information in the page +such as the first and last word on the page of a dictionary. +""") + +eg(""" + BaseDocTemplate.beforeDocument(self) +""") + +disc("""This is called before any processing is +done on the document, but after the processing machinery +is ready. It can therefore be used to do things to the instance\'s +$pdfgen.canvas$ and the like. +""") + +eg(""" + BaseDocTemplate.beforePage(self) +""") + +disc("""This is called at the beginning of page + processing, and immediately before the + beforeDrawPage method of the current page + template. It could be used to reset page specific + information holders.""") + +eg(""" + BaseDocTemplate.filterFlowables(self,flowables) +""") + +disc("""This is called to filter flowables at the start of the main handle_flowable method. + Upon return if flowables[0] has been set to None it is discarded and the main + method returns immediately. + """) + +eg(""" + BaseDocTemplate.afterFlowable(self, flowable) +""") + +disc("""Called after a flowable has been rendered. An interested class could use this +hook to gather information about what information is present on a particular page or frame.""") + +heading4("$BaseDocTemplate$ Event handler Methods") +disc(""" +These methods constitute the greater part of the layout engine. Programmers shouldn't +have to call or override these methods directly unless they are trying to modify the layout engine. +Of course, the experienced programmer who wants to intervene at a particular event, $XXX$, +which does not correspond to one of the virtual methods can always override and +call the base method from the drived class version. We make this easy by providing +a base class synonym for each of the handler methods with the same name prefixed by an underscore '_'. +""") + +eg(""" + def handle_pageBegin(self): + doStuff() + BaseDocTemplate.handle_pageBegin(self) + doMoreStuff() + + #using the synonym + def handle_pageEnd(self): + doStuff() + self._handle_pageEnd() + doMoreStuff() +""") +disc(""" +Here we list the methods only as an indication of the events that are being +handled. +Interested programmers can take a look at the source. +""") +eg(""" + handle_currentFrame(self,fx) + handle_documentBegin(self) + handle_flowable(self,flowables) + handle_frameBegin(self,*args) + handle_frameEnd(self) + handle_nextFrame(self,fx) + handle_nextPageTemplate(self,pt) + handle_pageBegin(self) + handle_pageBreak(self) + handle_pageEnd(self) +""") + +disc(""" +Using document templates can be very easy; $SimpleDoctemplate$ is a class derived from +$BaseDocTemplate$ which provides its own $PageTemplate$ and $Frame$ setup. +""") + +eg(""" +from reportlab.lib.styles import getSampleStyleSheet +from reportlab.lib.pagesizes import letter +from reportlab.platypus import Paragraph, SimpleDocTemplate +styles = getSampleStyleSheet() +styleN = styles['Normal'] +styleH = styles['Heading1'] +story = [] + +#add some flowables +story.append(Paragraph("This is a Heading",styleH)) +story.append(Paragraph("This is a paragraph in <i>Normal</i> style.", + styleN)) +doc = SimpleDocTemplate('mydoc.pdf',pagesize = letter) +doc.build(story) +""") +heading3("$PageTemplates$") +disc(""" +The $PageTemplate$ class is a container class with fairly minimal semantics. Each instance +contains a list of $Frames$ and has methods which should be called at the start and end +of each page. +""") +eg("PageTemplate(id=None,frames=[],onPage=_doNothing,onPageEnd=_doNothing)") +disc(""" +is used to initialize an instance, the $frames$ argument should be a list of $Frames$ +whilst the optional $onPage$ and $onPageEnd$ arguments are callables which should have signature +$def XXX(canvas,document)$ where $canvas$ and $document$ +are the canvas and document being drawn. These routines are intended to be used to paint non-flowing (i.e. standard) +parts of pages. These attribute functions are exactly parallel to the pure virtual methods +$PageTemplate.beforPage$ and $PageTemplate.afterPage$ which have signature +$beforPage(self,canvas,document)$. The methods allow class derivation to be used to define +standard behaviour, whilst the attributes allow instance changes. The $id$ argument is used at +run time to perform $PageTemplate$ switching so $id='FirstPage'$ or $id='TwoColumns'$ are typical. +""") diff --git a/bin/reportlab/docs/userguide/ch5_paragraphs.py b/bin/reportlab/docs/userguide/ch5_paragraphs.py new file mode 100644 index 00000000000..3191f1f1d55 --- /dev/null +++ b/bin/reportlab/docs/userguide/ch5_paragraphs.py @@ -0,0 +1,319 @@ +#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/docs/userguide/ch5_paragraphs.py +from reportlab.tools.docco.rl_doc_utils import * + +#begin chapter oon paragraphs +heading1("Paragraphs") +disc(""" +The $reportlab.platypus.Paragraph$ class is one of the most useful of the Platypus $Flowables$; +it can format fairly arbitrary text and provides for inline font style and colour changes using +an XML style markup. The overall shape of the formatted text can be justified, right or left ragged +or centered. The XML markup can even be used to insert greek characters or to do subscripts. +""") +disc("""The following text creates an instance of the $Paragraph$ class:""") +eg("""Paragraph(text, style, bulletText=None)""") +disc("""The $text$ argument contains the text of the +paragraph; excess white space is removed from the text at the ends and internally after +linefeeds. This allows easy use of indented triple quoted text in <b>Python</b> scripts. +The $bulletText$ argument provides the text of a default bullet for the paragraph. +The font and other properties for the paragraph text and bullet are set using the style argument. +""") +disc(""" +The $style$ argument should be an instance of class $ParagraphStyle$ obtained typically +using""") +eg(""" +from reportlab.lib.styles import ParagraphStyle +""") +disc(""" +this container class provides for the setting of multiple default paragraph attributes +in a structured way. The styles are arranged in a dictionary style object called a $stylesheet$ +which allows for the styles to be accessed as $stylesheet['BodyText']$. A sample style +sheet is provided. +""") +eg(""" +from reportlab.lib.styles import getSampleStyleSheet +stylesheet=getSampleStyleSheet() +normalStyle = stylesheet['Normal'] +""") +disc(""" +The options which can be set for a $Paragraph$ can be seen from the $ParagraphStyle$ defaults. +""") +heading4("$class ParagraphStyle$") +eg(""" +class ParagraphStyle(PropertySet): + defaults = { + 'fontName':'Times-Roman', + 'fontSize':10, + 'leading':12, + 'leftIndent':0, + 'rightIndent':0, + 'firstLineIndent':0, + 'alignment':TA_LEFT, + 'spaceBefore':0, + 'spaceAfter':0, + 'bulletFontName':'Times-Roman', + 'bulletFontSize':10, + 'bulletIndent':0, + 'textColor': black + } +""") + +heading2("Using Paragraph Styles") + +#this will be used in the ParaBox demos. +sample = """You are hereby charged that on the 28th day of May, 1970, you did +willfully, unlawfully, and with malice of forethought, publish an +alleged English-Hungarian phrase book with intent to cause a breach +of the peace. How do you plead?""" + + +disc("""The $Paragraph$ and $ParagraphStyle$ classes together +handle most common formatting needs. The following examples +draw paragraphs in various styles, and add a bounding box +so that you can see exactly what space is taken up.""") + +s1 = ParagraphStyle('Normal') +parabox(sample, s1, 'The default $ParagraphStyle$') + +disc("""The two attributes $spaceBefore$ and $spaceAfter$ do what they +say, except at the top or bottom of a frame. At the top of a frame, +$spaceBefore$ is ignored, and at the bottom, $spaceAfter$ is ignored. +This means that you could specify that a 'Heading2' style had two +inches of space before when it occurs in mid-page, but will not +get acres of whitespace at the top of a page. These two attributes +should be thought of as 'requests' to the Frame and are not part +of the space occupied by the Paragraph itself.""") + +disc("""The $fontSize$ and $fontName$ tags are obvious, but it is +important to set the $leading$. This is the spacing between +adjacent lines of text; a good rule of thumb is to make this +20% larger than the point size. To get double-spaced text, +use a high $leading$.""") + +disc("""The figure below shows space before and after and an +increased leading:""") + +parabox(sample, + ParagraphStyle('Spaced', + spaceBefore=6, + spaceAfter=6, + leading=16), + 'Space before and after and increased leading' + ) + +disc("""The $leftIndent$ and $rightIndent$ attributes do exactly +what you would expect; $firstLineIndent$ is added to the $leftIndent$ of the +first line. If you want a straight left edge, remember +to set $firstLineIndent$ equal to 0.""") + +parabox(sample, + ParagraphStyle('indented', + firstLineIndent=+24, + leftIndent=24, + rightIndent=24), + 'one third inch indents at left and right, two thirds on first line' + ) + +disc("""Setting $firstLineIndent$ equal to a negative number, $leftIndent$ +much higher, and using a +different font (we'll show you how later!) can give you a +definition list:.""") + +parabox('<b><i>Judge Pickles: </i></b>' + sample, + ParagraphStyle('dl', + leftIndent=36), + 'Definition Lists' + ) + +disc("""There are four possible values of $alignment$, defined as +constants in the module <i>reportlab.lib.enums</i>. These are +TA_LEFT, TA_CENTER or TA_CENTRE, TA_RIGHT and +TA_JUSTIFY, with values of 0, 1, 2 and 4 respectively. These +do exactly what you would expect.""") + + +heading2("Paragraph XML Markup Tags") +disc("""XML markup can be used to modify or specify the +overall paragraph style, and also to specify intra- +paragraph markup.""") + +heading3("The outermost < para > tag") + + +disc(""" +The paragraph text may optionally be surrounded by +<para attributes....> +</para> +tags. The attributes if any of the opening <para> tag affect the style that is used +with the $Paragraph$ $text$ and/or $bulletText$. +""") +disc(" ") + +from reportlab.platypus.paraparser import _addAttributeNames, _paraAttrMap, _bulletAttrMap + +def getAttrs(A): + _addAttributeNames(A) + S={} + for k, v in A.items(): + a = v[0] + if not S.has_key(a): + S[a] = k + else: + S[a] = "%s, %s" %(S[a],k) + + K = S.keys() + K.sort() + D=[('Attribute','Synonyms')] + for k in K: + D.append((k,S[k])) + cols=2*[None] + rows=len(D)*[None] + return D,cols,rows + +t=apply(Table,getAttrs(_paraAttrMap)) +t.setStyle(TableStyle([ + ('FONT',(0,0),(-1,1),'Times-Bold',10,12), + ('FONT',(0,1),(-1,-1),'Courier',8,8), + ('VALIGN',(0,0),(-1,-1),'MIDDLE'), + ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black), + ('BOX', (0,0), (-1,-1), 0.25, colors.black), + ])) +getStory().append(t) +caption("""Table <seq template="%(Chapter)s-%(Table+)s"/> - Synonyms for style attributes""") + +disc("""Some useful synonyms have been provided for our Python attribute +names, including lowercase versions, and the equivalent properties +from the HTML standard where they exist. These additions make +it much easier to build XML-printing applications, since +much intra-paragraph markup may not need translating. The +table below shows the allowed attributes and synonyms in the +outermost paragraph tag.""") + + +heading2("Intra-paragraph markup") +disc("""'<![CDATA[Within each paragraph, we use a basic set of XML tags +to provide markup. The most basic of these are bold (<b>...</b>) +and italic (<i>...</i>). It is also legal to use an underline +tag (<u>...</u> but it has no effect; PostScript fonts don't +support underlining, and neither do we, yet.]]>""") + +parabox2("""<b>You are hereby charged</b> that on the 28th day of May, 1970, you did +willfully, unlawfully, and <i>with malice of forethought</i>, publish an +alleged English-Hungarian phrase book with intent to cause a breach +of the peace. <u>How do you plead</u>?""", "Simple bold and italic tags") + +heading3("The $<font>$ tag") +disc("""The $<font>$ tag can be used to change the font name, +size and text color for any substring within the paragraph. +Legal attributes are $size$, $face$, $name$ (which is the same as $face$), +$color$, and $fg$ (which is the same as $color$). The $name$ is +the font family name, without any 'bold' or 'italic' suffixes. +Colors may be +HTML color names or a hex string encoded in a variety of ways; +see ^reportlab.lib.colors^ for the formats allowed.""") + +parabox2("""<font face="times" color="red"> +You are hereby charged</font> that on the 28th day of May, 1970, you did +willfully, unlawfully, and <font size=14>with malice of forethought</font>, +publish an +alleged English-Hungarian phrase book with intent to cause a breach +of the peace. How do you plead?""", "The $font$ tag") + +heading3("Superscripts and Subscripts") +disc("""Superscripts and subscripts are supported with the +<![CDATA[<super> and <sub> tags, which work exactly +as you might expect. In addition, most greek letters +can be accessed by using the <greek></greek> +tag, or with mathML entity names.]]>""") + +##parabox2("""<greek>epsilon</greek><super><greek>iota</greek> +##<greek>pi</greek></super> = -1""", "Greek letters and subscripts") + +parabox2("""Equation (α): <greek>e</greek> <super><greek>ip</greek></super> = -1""", + "Greek letters and superscripts") + +heading3("Numbering Paragraphs and Lists") +disc("""The $<seq>$ tag provides comprehensive support +for numbering lists, chapter headings and so on. It acts as +an interface to the $Sequencer$ class in ^reportlab.lib.sequencer^. +These are used to number headings and figures throughout this +document. +You may create as many separate 'counters' as you wish, accessed +with the $id$ attribute; these will be incremented by one each +time they are accessed. The $seqreset$ tag resets a counter. +If you want it to resume from a number other than 1, use +the syntax <seqreset id="mycounter" base="42">. +Let's have a go:""") + +parabox2("""<seq id="spam"/>, <seq id="spam"/>, <seq id="spam"/>. +Reset<seqreset id="spam"/>. <seq id="spam"/>, <seq id="spam"/>, +<seq id="spam"/>.""", "Basic sequences") + +disc("""You can save specifying an ID by designating a counter ID +as the <i>default</i> using the <seqdefault id="Counter"> +tag; it will then be used whenever a counter ID +is not specified. This saves some typing, especially when +doing multi-level lists; you just change counter ID when +stepping in or out a level.""") + +parabox2("""<seqdefault id="spam"/>Continued... <seq/>, +<seq/>, <seq/>, <seq/>, <seq/>, <seq/>, <seq/>.""", +"The default sequence") + +disc("""Finally, one can access multi-level sequences using +a variation of Python string formatting and the $template$ +attribute in a <seq> tags. This is used to do the +captions in all of the figures, as well as the level two +headings. The substring $%(counter)s$ extracts the current +value of a counter without incrementing it; appending a +plus sign as in $%(counter)s$ increments the counter. +The figure captions use a pattern like the one below:""") + +parabox2("""Figure <seq template="%(Chapter)s-%(FigureNo+)s"/> - Multi-level templates""", +"Multi-level templates") + +disc("""We cheated a little - the real document used 'Figure', +but the text above uses 'FigureNo' - otherwise we would have +messed up our numbering!""") + +heading2("Bullets and Paragraph Numbering") +disc("""In addition to the three indent properties, some other +parameters are needed to correctly handle bulleted and numbered +lists. We discuss this here because you have now seen how +to handle numbering. A paragraph may have an optional +^bulletText^ argument passed to its constructor; alternatively, +bullet text may be placed in a $<![CDATA[<bullet>..</bullet>]]>$ +tag at its head. The text will be drawn on the first line of +the paragraph, with its x origin determined by the $bulletIndent$ +attribute of the style, and in the font given in the +$bulletFontName$ attribute. For genuine bullets, a good +idea is to select the Times-Roman font in the style, and +use a character such as $\\xe2\\x80\\xa2)$:""") + +t=apply(Table,getAttrs(_bulletAttrMap)) +t.setStyle([ + ('FONT',(0,0),(-1,1),'Times-Bold',10,12), + ('FONT',(0,1),(-1,-1),'Courier',8,8), + ('VALIGN',(0,0),(-1,-1),'MIDDLE'), + ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black), + ('BOX', (0,0), (-1,-1), 0.25, colors.black), + ]) +getStory().append(t) + +caption("""Table <seq template="%(Chapter)s-%(Table+)s"/> - <bullet> attributes & synonyms""") +disc("""The <bullet> tag is only allowed once in a given paragraph and its use +overrides the implied bullet style and ^bulletText^ specified in the ^Paragraph^ +creation. +""") +parabox("""<bullet>\xe2\x80\xa2</bullet>this is a bullet point. Spam +spam spam spam spam spam spam spam spam spam spam spam +spam spam spam spam spam spam spam spam spam spam """, + styleSheet['Bullet'], + 'Basic use of bullet points') + +disc("""Exactly the same technique is used for numbers, +except that a sequence tag is used. It is also possible +to put a multi-character string in the bullet; with a deep +indent and bold bullet font, you can make a compact +definition list.""") diff --git a/bin/reportlab/docs/userguide/ch6_tables.py b/bin/reportlab/docs/userguide/ch6_tables.py new file mode 100644 index 00000000000..011423367ba --- /dev/null +++ b/bin/reportlab/docs/userguide/ch6_tables.py @@ -0,0 +1,419 @@ +#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/docs/userguide/ch6_tables.py +from reportlab.tools.docco.rl_doc_utils import * +from reportlab.platypus import Image +import reportlab + +heading1("Tables and TableStyles") +disc(""" +The $Table$ and $LongTable$ classes derive from the $Flowable$ class and are intended +as a simple textual gridding mechanisms. The $longTable$ class uses a greedy algorithm +when calculating column widths and is intended for long tables where speed counts. +$Table$ cells can hold anything which can be converted to +a <b>Python</b> $string$ or $Flowables$ (or lists of $Flowables$). +""") + +disc(""" +Our present tables are a trade-off between efficient drawing and specification +and functionality. We assume the reader has some familiarity with HTML tables. +In brief, they have the following characteristics: +""") + +bullet("""They can contain anything convertible to a string; flowable +objects such as other tables; or entire sub-stories""") + +bullet("""They can work out the row heights to fit the data if you don't supply +the row height. (They can also work out the widths, but generally it is better +for a designer to set the width manually, and it draws faster).""") + +bullet("""They can split across pages if needed (see the canSplit attribute). +You can specify that a number of rows at the top and bottom should be +repeated after the split (e.g. show the headers again on page 2,3,4...)""") + +bullet("""For very wide tables, they can also split 'by column'. You can choose +whether tou want to split down-and-across or across-and-down""") + +bullet("""They have a simple and powerful notation for specifying shading and +gridlines which works well with financial or database tables, where you +don't know the number of rows up front. You can easily say 'make the last row +bold and put a line above it'""") + +bullet("""The style and data are separated, so you can declare a handful of table +styles and use them for a family of reports. Styes can also 'inherit', as with +paragraphs.""") + +disc("""There is however one main limitation compared to an HTML table. +They define a simple rectangular grid. There is no simple row or column +spanning; if you need to span cells, you must nest tables inside table cells instead or use a more +complex scheme in which the lead cell of a span contains the actual contents.""") + +disc(""" +$Tables$ are created by passing the constructor an optional sequence of column widths, +an optional sequence of row heights, and the data in row order. +Drawing of the table can be controlled by using a $TableStyle$ instance. This allows control of the +color and weight of the lines (if any), and the font, alignment and padding of the text. +A primitive automatic row height and or column width calculation mechanism is provided for. +""") + +heading2('$Table$ User Methods') +disc("""These are the main methods which are of interest to the client programmer.""") + +heading4("""$Table(data, colWidths=None, rowHeights=None, style=None, splitByRow=1, +repeatRows=0, repeatCols=0)$""") + +disc("""The $data$ argument is a sequence of sequences of cell values each of which +should be convertible to a string value using the $str$ function or should be a Flowable instance (such as a $Paragraph$) or a list (or tuple) of such instances. +If a cell value is a $Flowable$ or list of $Flowables$ these must either have a determined width +or the containing column must have a fixed width. +The first row of cell values +is in $data[0]$ i.e. the values are in row order. The $i$, $j$<sup>th.</sup> cell value is in +$data[i][j]$. Newline characters $'\\n'$ in cell values are treated as line split characters and +are used at <i>draw</i> time to format the cell into lines. +""") +disc("""The other arguments are fairly obvious, the $colWidths$ argument is a sequence +of numbers or possibly $None$, representing the widths of the columns. The number of elements +in $colWidths$ determines the number of columns in the table. +A value of $None$ means that the corresponding column width should be calculated automatically.""") + +disc("""The $rowHeights$ argument is a sequence +of numbers or possibly $None$, representing the heights of the rows. The number of elements +in $rowHeights$ determines the number of rows in the table. +A value of $None$ means that the corresponding row height should be calculated automatically.""") + +disc("""The $style$ argument can be an initial style for the table.""") +disc("""The $splitByRow$ argument is only needed for tables both too tall and too wide +to fit in the current context. In this case you must decide whether to 'tile' +down and across, or across and then down. This parameter is a Boolean indicating that the +$Table$ should split itself +by row before attempting to split itself by column when too little space is available in +the current drawing area and the caller wants the $Table$ to split.""") + +disc("""The $repeatRows$ and $repeatCols$ arguments specify the number of leading rows and columns +that should be repeated when the $Table$ is asked to split itself.""") +heading4('$Table.setStyle(tblStyle)$') +disc(""" +This method applies a particular instance of class $TableStyle$ (discussed below) +to the $Table$ instance. This is the only way to get $tables$ to appear +in a nicely formatted way. +""") +disc(""" +Successive uses of the $setStyle$ method apply the styles in an additive fashion. +That is, later applications override earlier ones where they overlap. +""") + +heading2('$TableStyle$') +disc(""" +This class is created by passing it a sequence of <i>commands</i>, each command +is a tuple identified by its first element which is a string; the remaining +elements of the command tuple represent the start and stop cell coordinates +of the command and possibly thickness and colors, etc. +""") +heading2("$TableStyle$ User Methods") +heading3("$TableStyle(commandSequence)$") +disc("""The creation method initializes the $TableStyle$ with the argument +command sequence as an example:""") +eg(""" + LIST_STYLE = TableStyle( + [('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), + ('ALIGN', (1,1), (-1,-1), 'RIGHT')] + ) +""") +heading3("$TableStyle.add(commandSequence)$") +disc("""This method allows you to add commands to an existing +$TableStyle$, i.e. you can build up $TableStyles$ in multiple statements. +""") +eg(""" + LIST_STYLE.add('BACKGROUND', (0,0), (-1,0), colors.Color(0,0.7,0.7)) +""") +heading3("$TableStyle.getCommands()$") +disc("""This method returns the sequence of commands of the instance.""") +eg(""" + cmds = LIST_STYLE.getCommands() +""") +heading2("$TableStyle$ Commands") +disc("""The commands passed to $TableStyles$ come in three main groups +which affect the table background, draw lines, or set cell styles. +""") +disc("""The first element of each command is its identifier, +the second and third arguments determine the cell coordinates of +the box of cells which are affected with negative coordinates +counting backwards from the limit values as in <b>Python</b> +indexing. The coordinates are given as +(column, row) which follows the spreadsheet 'A1' model, but not +the more natural (for mathematicians) 'RC' ordering. +The top left cell is (0, 0) the bottom right is (-1, -1). Depending on +the command various extra (???) occur at indices beginning at 3 on. +""") +heading3("""$TableStyle$ Cell Formatting Commands""") +disc("""The cell formatting commands all begin with an identifier, followed by +the start and stop cell definitions and the perhaps other arguments. +the cell formatting commands are:""") +eg(""" +FONT - takes fontname, optional fontsize and optional leading. +FONTNAME (or FACE) - takes fontname. +FONTSIZE (or SIZE) - takes fontsize in points; leading may get out of sync. +LEADING - takes leading in points. +TEXTCOLOR - takes a color name or (R,G,B) tuple. +ALIGNMENT (or ALIGN) - takes one of LEFT, RIGHT and CENTRE (or CENTER) or DECIMAL. +LEFTPADDING - takes an integer, defaults to 6. +RIGHTPADDING - takes an integer, defaults to 6. +BOTTOMPADDING - takes an integer, defaults to 3. +TOPPADDING - takes an integer, defaults to 3. +BACKGROUND - takes a color. +ROWBACKGROUNDS - takes a list of colors to be used cyclically. +COLBACKGROUNDS - takes a list of colors to be used cyclically. +VALIGN - takes one of TOP, MIDDLE or the default BOTTOM +""") +disc("""This sets the background cell color in the relevant cells. +The following example shows the $BACKGROUND$, and $TEXTCOLOR$ commands in action:""") +EmbeddedCode(""" +data= [['00', '01', '02', '03', '04'], + ['10', '11', '12', '13', '14'], + ['20', '21', '22', '23', '24'], + ['30', '31', '32', '33', '34']] +t=Table(data) +t.setStyle(TableStyle([('BACKGROUND',(1,1),(-2,-2),colors.green), + ('TEXTCOLOR',(0,0),(1,-1),colors.red)])) +""") +disc("""To see the effects of the alignment styles we need some widths +and a grid, but it should be easy to see where the styles come from.""") +EmbeddedCode(""" +data= [['00', '01', '02', '03', '04'], + ['10', '11', '12', '13', '14'], + ['20', '21', '22', '23', '24'], + ['30', '31', '32', '33', '34']] +t=Table(data,5*[0.4*inch], 4*[0.4*inch]) +t.setStyle(TableStyle([('ALIGN',(1,1),(-2,-2),'RIGHT'), + ('TEXTCOLOR',(1,1),(-2,-2),colors.red), + ('VALIGN',(0,0),(0,-1),'TOP'), + ('TEXTCOLOR',(0,0),(0,-1),colors.blue), + ('ALIGN',(0,-1),(-1,-1),'CENTER'), + ('VALIGN',(0,-1),(-1,-1),'MIDDLE'), + ('TEXTCOLOR',(0,-1),(-1,-1),colors.green), + ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black), + ('BOX', (0,0), (-1,-1), 0.25, colors.black), + ])) +""") +heading3("""$TableStyle$ Line Commands""") +disc(""" + Line commands begin with the identifier, the start and stop cell coordinates + and always follow this with the thickness (in points) and color of the desired lines. Colors can be names, + or they can be specified as a (R, G, B) tuple, where R, G and B are floats and (0, 0, 0) is black. The line + command names are: GRID, BOX, OUTLINE, INNERGRID, LINEBELOW, LINEABOVE, LINEBEFORE + and LINEAFTER. BOX and OUTLINE are equivalent, and GRID is the equivalent of applying both BOX and + INNERGRID. +""") +CPage(4.0) +disc("""We can see some line commands in action with the following example. +""") +EmbeddedCode(""" +data= [['00', '01', '02', '03', '04'], + ['10', '11', '12', '13', '14'], + ['20', '21', '22', '23', '24'], + ['30', '31', '32', '33', '34']] +t=Table(data,style=[('GRID',(1,1),(-2,-2),1,colors.green), + ('BOX',(0,0),(1,-1),2,colors.red), + ('LINEABOVE',(1,2),(-2,2),1,colors.blue), + ('LINEBEFORE',(2,1),(2,-2),1,colors.pink), + ]) +""") +disc("""Line commands cause problems for tables when they split; the following example +shows a table being split in various positions""") +EmbeddedCode(""" +data= [['00', '01', '02', '03', '04'], + ['10', '11', '12', '13', '14'], + ['20', '21', '22', '23', '24'], + ['30', '31', '32', '33', '34']] +t=Table(data,style=[ + ('GRID',(0,0),(-1,-1),0.5,colors.grey), + ('GRID',(1,1),(-2,-2),1,colors.green), + ('BOX',(0,0),(1,-1),2,colors.red), + ('BOX',(0,0),(-1,-1),2,colors.black), + ('LINEABOVE',(1,2),(-2,2),1,colors.blue), + ('LINEBEFORE',(2,1),(2,-2),1,colors.pink), + ('BACKGROUND', (0, 0), (0, 1), colors.pink), + ('BACKGROUND', (1, 1), (1, 2), colors.lavender), + ('BACKGROUND', (2, 2), (2, 3), colors.orange), + ]) +""") +t=getStory()[-1] +getStory().append(Spacer(0,6)) +for s in t.split(4*inch,30): + getStory().append(s) + getStory().append(Spacer(0,6)) +getStory().append(Spacer(0,6)) +for s in t.split(4*inch,36): + getStory().append(s) + getStory().append(Spacer(0,6)) + +disc("""When unsplit and split at the first or second row.""") + +CPage(4.0) +heading3("""Complex Cell Values""") +disc(""" +As mentioned above we can have complicated cell values including $Paragraphs$, $Images$ and other $Flowables$ +or lists of the same. To see this in operation consider the following code and the table it produces. +Note that the $Image$ has a white background which will obscure any background you choose for the cell. +To get better results you should use a transparent background. +""") +import os, reportlab.platypus +I = '../images/replogo.gif' +EmbeddedCode(""" +I = Image('%s') +I.drawHeight = 1.25*inch*I.drawHeight / I.drawWidth +I.drawWidth = 1.25*inch +P0 = Paragraph(''' + <b>A pa<font color=red>r</font>a<i>graph</i></b> + <super><font color=yellow>1</font></super>''', + styleSheet["BodyText"]) +P = Paragraph(''' + <para align=center spaceb=3>The <b>ReportLab Left + <font color=red>Logo</font></b> + Image</para>''', + styleSheet["BodyText"]) +data= [['A', 'B', 'C', P0, 'D'], + ['00', '01', '02', [I,P], '04'], + ['10', '11', '12', [P,I], '14'], + ['20', '21', '22', '23', '24'], + ['30', '31', '32', '33', '34']] + +t=Table(data,style=[('GRID',(1,1),(-2,-2),1,colors.green), + ('BOX',(0,0),(1,-1),2,colors.red), + ('LINEABOVE',(1,2),(-2,2),1,colors.blue), + ('LINEBEFORE',(2,1),(2,-2),1,colors.pink), + ('BACKGROUND', (0, 0), (0, 1), colors.pink), + ('BACKGROUND', (1, 1), (1, 2), colors.lavender), + ('BACKGROUND', (2, 2), (2, 3), colors.orange), + ('BOX',(0,0),(-1,-1),2,colors.black), + ('GRID',(0,0),(-1,-1),0.5,colors.black), + ('VALIGN',(3,0),(3,0),'BOTTOM'), + ('BACKGROUND',(3,0),(3,0),colors.limegreen), + ('BACKGROUND',(3,1),(3,1),colors.khaki), + ('ALIGN',(3,1),(3,1),'CENTER'), + ('BACKGROUND',(3,2),(3,2),colors.beige), + ('ALIGN',(3,2),(3,2),'LEFT'), + ]) + +t._argW[3]=1.5*inch +"""%I) +heading3("""$TableStyle$ Span Commands""") +disc("""Our $Table$ classes support the concept of spanning, but it isn't specified in the same way +as html. The style specification +""") +eg(""" +SPAN, (sc,sr), (ec,er) +""") +disc("""indicates that the cells in columns $sc$ - $ec$ and rows $sr$ - $er$ should be combined into a super cell +with contents determined by the cell $(sc, sr)$. The other cells should be present, but should contain empty strings +or you may get unexpected results. +""") +EmbeddedCode(""" +data= [['Top\\nLeft', '', '02', '03', '04'], + ['', '', '12', '13', '14'], + ['20', '21', '22', 'Bottom\\nRight', ''], + ['30', '31', '32', '', '']] +t=Table(data,style=[ + ('GRID',(0,0),(-1,-1),0.5,colors.grey), + ('BACKGROUND',(0,0),(1,1),colors.palegreen), + ('SPAN',(0,0),(1,1)), + ('BACKGROUND',(-2,-2),(-1,-1), colors.pink), + ('SPAN',(-2,-2),(-1,-1)), + ]) +""") + +disc("""notice that we don't need to be conservative with our $GRID$ command. The spanned cells are not drawn through. +""") +heading3("""Special $TableStyle$ Indeces""") +disc("""In any style command the first row index may be set to one of the special strings +$'splitlast'$ or $'splitfirst'$ to indicate that the style should be used only for the last row of +a split table, or the first row of a continuation. This allows splitting tables with nicer effects around the split.""") + +heading1("""Other Useful $Flowables$""") +heading2("""$Preformatted(text, style, bulletText = None, dedent=0)$""") +disc(""" +Creates a preformatted paragraph which does no wrapping, line splitting or other manipulations. +No $XML$ style tags are taken account of in the text. +If dedent is non zero $dedent$ common leading +spaces will be removed from the front of each line. +""") +heading2("""$XPreformatted(text, style, bulletText = None, dedent=0, frags=None)$""") +disc(""" +This is a non rearranging form of the $Paragraph$ class; $XML$ tags are allowed in +$text$ and have the same meanings as for the $Paragraph$ class. +As for $Preformatted$, if dedent is non zero $dedent$ common leading +spaces will be removed from the front of each line. +""") +EmbeddedCode(""" +from reportlab.lib.styles import getSampleStyleSheet +stylesheet=getSampleStyleSheet() +normalStyle = stylesheet['Normal'] +text=''' + + This is a non rearranging form of the <b>Paragraph</b> class; + <b><font color=red>XML</font></b> tags are allowed in <i>text</i> and have the same + + meanings as for the <b>Paragraph</b> class. + As for <b>Preformatted</b>, if dedent is non zero <font color=red size=+1>dedent</font> + common leading spaces will be removed from the + front of each line. + You can have &amp; style entities as well for & < > and ". + +''' +t=XPreformatted(text,normalStyle,dedent=3) +""") +heading2("""$Image(filename, width=None, height=None)$""") +disc("""Create a flowable which will contain the image defined by the data in file $filename$. +The default <b>PDF</b> image type <i>jpeg</i> is supported and if the <b>PIL</b> extension to <b>Python</b> +is installed the other image types can also be handled. If $width$ and or $height$ are specified +then they determine the dimension of the displayed image in <i>points</i>. If either dimension is +not specified (or specified as $None$) then the corresponding pixel dimension of the image is assumed +to be in <i>points</i> and used. +""") +I=os.path.join(os.path.dirname(reportlab.__file__),'docs','images','lj8100.jpg') +eg(""" +Image("lj8100.jpg") +""",after=0.1) +disc("""will display as""") +try: + getStory().append(Image(I)) +except: + disc("""An image should have appeared here.""") +disc("""whereas""") +eg(""" +im = Image("lj8100.jpg", width=2*inch, height=2*inch) +im.hAlign = 'CENTER' +""", after=0.1) +disc('produces') +try: + im = Image(I, width=2*inch, height=2*inch) + im.hAlign = 'CENTER' + getStory().append(Image(I, width=2*inch, height=2*inch)) +except: + disc("""An image should have appeared here.""") +heading2("""$Spacer(width, height)$""") +disc("""This does exactly as would be expected; it adds a certain amount of space into the story. +At present this only works for vertical space. +""") +CPage(1) +heading2("""$PageBreak()$""") +disc("""This $Flowable$ represents a page break. It works by effectively consuming all vertical +space given to it. This is sufficient for a single $Frame$ document, but would only be a +frame break for multiple frames so the $BaseDocTemplate$ mechanism +detects $pageBreaks$ internally and handles them specially. +""") +CPage(1) +heading2("""$CondPageBreak(height)$""") +disc("""This $Flowable$ attempts to force a $Frame$ break if insufficient vertical space remains +in the current $Frame$. It is thus probably wrongly named and should probably be renamed as +$CondFrameBreak$. +""") +CPage(1) +heading2("""$KeepTogether(flowables)$""") +disc(""" +This compound $Flowable$ takes a list of $Flowables$ and attempts to keep them in the same $Frame$. +If the total height of the $Flowables$ in the list $flowables$ exceeds the current frame's available +space then all the space is used and a frame break is forced. +""") diff --git a/bin/reportlab/docs/userguide/ch7_custom.py b/bin/reportlab/docs/userguide/ch7_custom.py new file mode 100644 index 00000000000..176d042cd85 --- /dev/null +++ b/bin/reportlab/docs/userguide/ch7_custom.py @@ -0,0 +1,81 @@ +#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/docs/userguide/ch7_custom.py +from reportlab.tools.docco.rl_doc_utils import * + +heading1("Writing your own $Flowable$ Objects") +disc(""" +Flowables are intended to be an open standard for creating +reusable report content, and you can easily create your +own objects. We hope that over time we will build up +a library of contributions, giving reportlab users a +rich selection of charts, graphics and other "report +widgets" they can use in their own reports. This section +shows you how to create your own flowables.""") + +todo("""we should put the Figure class in the +standard library, as it is a very useful base.""") + + + + +heading2("A very simple $Flowable$") + +disc(""" +Recall the $hand$ function from the $pdfgen$ section of this user guide which +generated a drawing of a hand as a closed figure composed from Bezier curves. +""") +illust(examples.hand, "a hand") +disc(""" +To embed this or any other drawing in a Platypus flowable we must define a +subclass of $Flowable$ +with at least a $wrap$ method and a $draw$ method. +""") +eg(examples.testhandannotation) +disc(""" +The $wrap$ method must provide the size of the drawing -- it is used by +the Platypus mainloop to decide whether this element fits in the space remaining +on the current frame. The $draw$ method performs the drawing of the object after +the Platypus mainloop has translated the $(0,0)$ origin to an appropriate location +in an appropriate frame. +""") +disc(""" +Below are some example uses of the $HandAnnotation$ flowable. +""") + +from reportlab.lib.colors import blue, pink, yellow, cyan, brown +from reportlab.lib.units import inch + +handnote() + +disc("""The default.""") + +handnote(size=inch) + +disc("""Just one inch high.""") + +handnote(xoffset=3*inch, size=inch, strokecolor=blue, fillcolor=cyan) + +disc("""One inch high and shifted to the left with blue and cyan.""") + + +heading2("Modifying a Built in $Flowable$") +disc("""To modify an existing flowable, you should create a derived class +and override the methods you need to change to get the desired behaviour""") +disc("""As an example to create a rotated image you need to override the wrap +and draw methods of the existing Image class""") +import os +from reportlab.platypus import * +I = '../images/replogo.gif' + +EmbeddedCode(""" +class RotatedImage(Image): + def wrap(self,availWidth,availHeight): + h, w = Image.wrap(self,availHeight,availWidth) + return w, h + def draw(self): + self.canv.rotate(90) + Image.draw(self) +I = RotatedImage('%s') +I.hAlign = 'CENTER' +""" % I,'I')
\ No newline at end of file diff --git a/bin/reportlab/docs/userguide/ch9_future.py b/bin/reportlab/docs/userguide/ch9_future.py new file mode 100644 index 00000000000..6ac5b94e502 --- /dev/null +++ b/bin/reportlab/docs/userguide/ch9_future.py @@ -0,0 +1,35 @@ +#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/docs/userguide/ch9_future.py +from reportlab.tools.docco.rl_doc_utils import * + +heading1("Future Directions") + +disc("""We have a very long list of things we plan to do +and what we do first will most likely be inspired by customer +or user interest. +""") + +disc(""" +We plan to provide a large number of pre-designed Platypus example +document types -- brochure, newsletter, business letter, thesis, memo, +etcetera, to give our users a better boost towards the solutions they +desire. +""") + +disc(""" +We plan to fully support adding fonts and internationalization, which are +not well supported in the current release.""") + +disc(""" +We plan to fully support some of the more obscure features of PDF +such as general hyperlinks, which are not yet well supported. +""") + +disc(""" +We are also open for suggestions. Please let us know what you think +is missing. You can also offer patches or contributions. Please +look to $http://www.reportlab.com$ for the latest mailing list and +contact information.""") + +# this comment is a trivial test of SF checkin rights - delete it some time! AR 2001-04-17
\ No newline at end of file diff --git a/bin/reportlab/docs/userguide/genuserguide.py b/bin/reportlab/docs/userguide/genuserguide.py new file mode 100644 index 00000000000..3166a6a6036 --- /dev/null +++ b/bin/reportlab/docs/userguide/genuserguide.py @@ -0,0 +1,85 @@ +#!/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/docs/userguide/genuserguide.py +__version__=''' $Id: genuserguide.py 2900 2006-05-22 21:49:00Z andy $ ''' +__doc__ = """ +This module contains the script for building the user guide. +""" +def run(pagesize=None, verbose=0, outDir=None): + import os + from reportlab.tools.docco.rl_doc_utils import setStory, getStory, RLDocTemplate, defaultPageSize + from reportlab.tools.docco import rl_doc_utils + from reportlab.lib.utils import open_and_read, _RL_DIR + if not outDir: outDir = os.path.join(_RL_DIR,'docs') + destfn = os.path.join(outDir,'userguide.pdf') + doc = RLDocTemplate(destfn,pagesize = pagesize or defaultPageSize) + + #this builds the story + setStory() + G = {} + exec 'from reportlab.tools.docco.rl_doc_utils import *' in G, G + for f in ( + 'ch1_intro', + 'ch2_graphics', + 'ch2a_fonts', + 'ch3_pdffeatures', + 'ch4_platypus_concepts', + 'ch5_paragraphs', + 'ch6_tables', + 'ch7_custom', + 'ch9_future', + 'app_demos', + ): + exec open_and_read(f+'.py',mode='t') in G, G + del G + + story = getStory() + if verbose: print 'Built story contains %d flowables...' % len(story) + doc.build(story) + if verbose: print 'Saved "%s"' % destfn + +def makeSuite(): + "standard test harness support - run self as separate process" + from reportlab.test.utils import ScriptThatMakesFileTest + return ScriptThatMakesFileTest('../docs/userguide', 'genuserguide.py', 'userguide.pdf') + +def main(): + import sys + outDir = filter(lambda x: x[:9]=='--outdir=',sys.argv) + if outDir: + outDir = outDir[0] + sys.argv.remove(outDir) + outDir = outDir[9:] + else: + outDir = None + verbose = '-s' not in sys.argv + if not verbose: sys.argv.remove('-s') + timing = '-timing' in sys.argv + if timing: sys.argv.remove('-timing') + prof = '-prof' in sys.argv + if prof: sys.argv.remove('-prof') + + if len(sys.argv) > 1: + try: + pagesize = (w,h) = eval(sys.argv[1]) + except: + print 'Expected page size in argument 1', sys.argv[1] + raise + if verbose: + print 'set page size to',sys.argv[1] + else: + pagesize = None + if timing: + from time import time + t0 = time() + run(pagesize, verbose,outDir) + if verbose: + print 'Generation of userguide took %.2f seconds' % (time()-t0) + elif prof: + import profile + profile.run('run(pagesize,verbose,outDir)','genuserguide.stats') + else: + run(pagesize, verbose,outDir) +if __name__=="__main__": + main() diff --git a/bin/reportlab/docs/userguide/testfile.txt b/bin/reportlab/docs/userguide/testfile.txt new file mode 100644 index 00000000000..020f3d7cbaf --- /dev/null +++ b/bin/reportlab/docs/userguide/testfile.txt @@ -0,0 +1,2 @@ +Test of ability to create new files in sourceforge CVS, which +seems not to be working. Can be removed any time.
\ No newline at end of file |
