<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?> 
<!DOCTYPE document SYSTEM "rml_1_0.dtd"> 
<document filename="pagecatcher-userguide.pdf"> 
<!-- Last Modified:             $Date$ -->
<!-- Document Version Number:   $Revision$            -->

<template pageSize="(595, 842)" 
        leftMargin="72" 
        showBoundary="0"
        title="PageCatcher Intro"
        author="Reportlab Inc"
        >

    <pageTemplate id="cover">
    <pageGraphics>
        <setFont name="Times-Bold" size="48"/>
        <drawCentredString x="297" y="516">PageCatcher Intro</drawCentredString>
        <setFont name="Times-Bold" size="12"/>
        <drawCentredString x="297" y="414"></drawCentredString>

        <lines>
        72 132 523 132
        </lines>

        <image file="../rml2pdf/images/replogo.gif" x="155" y="626"/>

        <setFont name="Times-Roman" size="10"/>
        <drawString x="72" y="110">Thornton House</drawString>
        <drawString x="72" y="98">Thornton Road</drawString>
        <drawString x="72" y="86">Wimbledon</drawString>
        <drawString x="72" y="74">London SW19 4NG, UK</drawString>

    </pageGraphics>
    <frame id="first" x1="72" y1="72" width="451" height="698"/>
    </pageTemplate>

    <pageTemplate id="contents">
    <pageGraphics>
    </pageGraphics>
    <frame id="first" x1="72" y1="72" width="451" height="698"/>
    </pageTemplate>

    <pageTemplate id="inside">
    <pageGraphics>
        <lines>
        72 796 523 796
        </lines>
        <setFont name="Times-Roman" size="10"/>
        <drawString x="72" y="808">PageCatcher Intro</drawString>
        <drawRightString x="523" y="808">$Revision$</drawRightString>
        <drawCentredString x="297.5" y="60">Page <pageNumber/></drawCentredString>
    </pageGraphics>
    <frame id="first" x1="72" y1="72" width="451" height="698"/>
    </pageTemplate>

</template>

<stylesheet>
    <initialize>
            <alias id="style.normal" value="style.Normal"/>
    </initialize>

    <paraStyle name="style.h1"
    fontName="Times-Bold"
    fontSize="20"
    leading="36"
    />

    <paraStyle name="style.h2"
    fontName="Times-Bold"
    fontSize="20"
    leading="36"
    />

    <paraStyle name="style.h3"
    fontName="Times-Bold"
    fontSize="12"
    leading="15"
    />

    <paraStyle name="contents"
    fontName="Times-Bold"
    fontSize="12"
    />

    <paraStyle name="contents2"
    fontName="Times-Roman"
    fontSize="12"
    leftIndent="20"
    />

    <paraStyle name="contents2a"
    fontName="Times-Roman"
    fontSize="12"
    leftIndent="20"
    spaceAfter="12"
    />

    <paraStyle name="contents2h"
    fontName="Times-Bold"
    fontSize="12"
    leftIndent="20"
    />
    
    <paraStyle name="contents3"
    fontName="Times-Roman"
    fontSize="12"
    leftIndent="40"
    />

    <paraStyle name="contents3a"
    fontName="Times-Roman"
    fontSize="12"
    leftIndent="40"
    spaceAfter="12"
    />

    <paraStyle name="contents3h"
    fontName="Times-Bold"
    fontSize="12"
    leftIndent="40"
    />

    <paraStyle name="style.Normal"
    fontName="Times-Roman"
    fontSize="10"
    leading="12"
    spaceAfter="12"
    firstLineIndent="0"
    />

    <paraStyle name="programListing"
    parent="style.Normal"
    fontName="Courier-Bold"
    fontSize="8"
	leading="10"
    spaceBefore="2"
    spaceAfter="10"
    textColor="darkblue"
    leftIndent="1.2cm"
    />

    <paraStyle name="programListingConventionLabel"
    parent="programListing"
	spaceAfter="0"
    leftIndent="0"
    />
	
    <paraStyle name="bulletList" 
    parent="style.Normal" 
    bulletFontName="ZapfDingbats"
    bulletFontSize="5"
    bulletIndent="20"
    leftIndent="35"
    spaceAfter="6"
    />

    <paraStyle name="bulletNospace" 
    parent="bulletList" 
    spaceAfter="0"
    />
    
    <paraStyle name="nospace" 
    spaceAfter="0"
    parent="style.Normal" 
    />
    
    <paraStyle name="figureCaption" 
    spaceBefore="0"
    spaceAfter="15"
    alignment="CENTER"
    fontSize="8"
    fontName="Times-Italic"
    />
    
    <paraStyle name="paddingTableStyle"
	fontName="Helvetica-BoldOblique"
	fontSize="10"
	textColor="white"
	alignment="CENTER"
	/>

</stylesheet>


<story>

<outlineAdd level="0">PageCatcher Intro</outlineAdd>
<setNextTemplate name="cover"/>

<setNextTemplate name="contents"/>
<nextFrame/>

<h1>PageCatcher Intro</h1>
<outlineAdd level="1">Contents</outlineAdd>

<h2>Contents</h2>
<para style="contents2a">
<name id="chapterNumber" value="1"/>
<seqReset id="sectionNumber"/>
<getName id="chapterNumber"/>.<seq id="sectionNumber"/>
What is PageCatcher for?</para>

<para style="contents2a">
<getName id="chapterNumber"/>.<seq id="sectionNumber"/>
Running the demos
</para>

<para style="contents2a">
<getName id="chapterNumber"/>.<seq id="sectionNumber"/>
How does it work?
</para>

<para style="contents2a">
<getName id="chapterNumber"/>.<seq id="sectionNumber"/>
Known Deficiencies and Caveats
</para>

<para style="contents2a">
<getName id="chapterNumber"/>.<seq id="sectionNumber"/>
Workarounds
</para>

<para style="contents2a">
<getName id="chapterNumber"/>.<seq id="sectionNumber"/>
Page Extraction
</para>

<para style="contents2a">
<getName id="chapterNumber"/>.<seq id="sectionNumber"/>
Using Caught Pages
</para>

<para style="contents2a">
<getName id="chapterNumber"/>.<seq id="sectionNumber"/>
Demo Modes
</para>

<para style="contents2a">
<getName id="chapterNumber"/>.<seq id="sectionNumber"/>
Feedback
</para>

<setNextTemplate name="inside"/>
<nextFrame/>

<h1>PageCatcher Intro</h1>
<para>Last updated 27 August 2001. PageCatcher has been made largely
obsolete by Report Markup Language, but is still available if you want to use it.</para>

<para>
This document provides a basic introduction to using PageCatcher.
It includes explanations of what PageCatcher does, how it can be used,
what the current limitations are,
how to run the demo applications, how to run PageCatcher as a command
line program, how to use PageCatcher with the RML2PDF application,
and how to use the PageCatcher programming interface within
other programs.
</para>

<h2>What is PageCatcher for?</h2>
<outlineAdd level="1">What is PageCatcher for?</outlineAdd>

<para>PageCatcher is an add-on utility for ReportLab's suite of
enterprise reporting tools, as well as the most versatile
tool for batch manipulation of PDF files.  The suite runs on
all common computing platforms.  
</para>

<para>The free ReportLab core API
lets you create PDF files directly using the Python
scripting language; our commercial RML2PDF Report Markup Language
product lets you specify printed documents in easy-to-understand
XML and converts these to PDF.  PageCatcher allows these
packages to reuse complex designs from existing PDF files
in dynamically created PDF documents.</para>

<para>Many documents require elements such as fixed form layouts, 
headers, footers, corporate logos, or other art work which 
are most cost effectively created by artists or design 
specialists using visual tools. With Adobe Acrobat, they
can use any tools they wish and convert it to PDF.  These
visual elements can then be seamlessly integrated into
PDF reports using PageCatcher.</para>

<para>In addition, many applications require batch or server-side
modification of existing PDF documents - adding simple
annotations, combining documents or printing 2-up or
4-up.  These can all be scripted trivially with PageCatcher.
There are many single-purpose programs to append, rearrange
and extract text from PDFs; PageCatcher's
simple API and a scripting interface 
provides the most versatile solution on the market.</para>


<h2>Running the demos</h2>
<outlineAdd level="1">Running the demos</outlineAdd>

<para>The demos are for Windows only and are packaged 
as a zip file.  This creates a subdirectory
called 'pageCatcher' under the location where
you unzip it; so you can safely unzip into C:</para>

<para>This distribution consists of:</para>
<para style="bulletList" bulletText="l">00README.txt - starting point</para>
<para style="bulletList" bulletText="l">PageCatchIntro.html - this document(in html format)</para>
<para style="bulletList" bulletText="l">pageCatcher.exe - executable program</para>
<para style="bulletList" bulletText="l">sample1.pdf - a U.S. government tax form</para>
<para style="bulletList" bulletText="l">sample2.pdf - first ten pages of Psion's 1997 annual report</para>
<para style="bulletList" bulletText="l">sample3.pdf - a custom page backdrop</para>
<para style="bulletList" bulletText="l">five sample scripts (example*.py) to manipulate the examples</para>
<para style="bulletList" bulletText="l">runall.bat - batch file to run all demos at once</para>

<para>When run as a command line program
PageCatcher has many command line options; the first argument
is a command.  The general command line usage for PageCatcher
is</para>

<pre style="programListing">
pageCatcher.exe COMMAND ARGUMENT1 ARGUMENT2 ...
</pre>

<para>The COMMAND indicates what action pageCatcher should perform.
The most general command is the 'exec' command.
</para>

<para>
The 'exec' command runs a Python script that makes
use of PageCatcher's functionality. In the demo distribution we
provide five scripts to demonstrate the versatility of
the API.  Try these commands from a command [MSDOS] prompt:
</para>

<pre style="programListing">
pageCatcher.exe exec example1_fillform.py
pageCatcher.exe exec example2_reverse.py
pageCatcher.exe exec example3_append.py
pageCatcher.exe exec example4_fourpage.py
pageCatcher.exe exec example5_background.py

</pre>

<para>Each results in a PDF file being written which begins with 
'out'; look at these as well as the samples to get an idea
of the capabilities.  You can also use the batch file
'runall.bat' to run all five demos in one go.</para>

<h2>How does it work?</h2>
<outlineAdd level="1">How does it work?</outlineAdd>

<para>There are two logical steps in using PageCatcher.  First, 
pages must be <i>extracted</i>
into a special data file format using the PageCatcher filter script mode.
Second, the extracted pages may be <i>imported</i> by ReportLab programs.
In many applications, extraction is a one-off design-time step,
and the data files produced can then be included in new documents at very high
speeds.</para>

<para>The commercial product consists of a compiled Python module
(similar to a Java class file) which can be used in 3 ways:</para>
<para style="bulletList" bulletText="l">as a command line application with many useful options</para>
<para style="bulletList" bulletText="l">as a library within Python scripts</para>
<para style="bulletList" bulletText="l">controlled by tags within RML documents</para>

<para>The PageCatcher product
can either function as a module in a larger Python installation
(which should include the ReportLab core libraries), or as a
stand alone executable which contains the ReportLab distribution
and all other required software components.</para>

<para>
In either mode you can write your own
scripts as well as looking at the ones we provided.
Please consult the first few chapters of the <b>Reportlab User Guide</b>,
and to look at the documentation for the <b>Python</b> scripting language
for additional information on using the ReportLab toolkit and the Python
programming language.</para>

<para>
PageCatcher also functions as a add on component to the RML2PDF program
supported by the <i>catchForms</i> RML tag.
Please see the RML2PDF userguide for more information on using RML2PDF.
</para>

<h2>Known Deficiencies and Caveats</h2>
<outlineAdd level="1">Known Deficiencies and Caveats</outlineAdd>

<para>PageCatcher does not support PDF pages with stream content arrays
compressed using the LZW compression method.  (Unfortunately this is used in 
British tax forms). We are working to add this support.</para>

<para>PageCatcher cannot capture pages that contain "Active PDF Form" annotations
(such as checkboxes or fill-in text areas).</para>

<para>You must supply a user password to process encrypted PDF files</para>

<pre style="programListing">
pageCatcher...  --password MYUSERPASSWORD
</pre>

<para>Since the preprocessor step for PageCatcher parses the entire PDF file,
parsing very large files may consume a great amount of computational resources
even if only one page is extracted from the file.</para>


<h2>Workarounds</h2>
<outlineAdd level="1">Workarounds</outlineAdd>

<para>If you have a copy of Adobe's Distiller, you can use it to work around 
the majority of problems.
To do this, use Distiller's printer emulation to "print to PDF" and the 
file created will be 
digestible by PageCatcher. (One <i>known</i> exception: 
where the PDF file is encrypted and printing is not 
permitted).
</para>

<h2>Page Extraction</h2>
<outlineAdd level="1">Page Extraction</outlineAdd>

<para>PageCatcher can extract pages from PDF files into the import data format
either using a command line or using a function call from within a python
program or script.  All extraction options may specify a prefix to use
in the form names and also for other internal purposes.  
<b>It is important that if a generated document uses several PageCatcher data files
that the data files use <i>different</i> prefixes.</b>
</para>

<para>
<b>Line mode page extraction:</b>
In script mode PageCatcher prepares the contents of one or more pages of
a PDF file for use in other PDF files.
</para>

<pre style="programListing">
% PageCatcher makeforms pdffile [-s storagefile] [-p prefix]
     [--password password] [--test pdftestfile] [--all] [pagenumber]*
</pre>

<para>
This command
  captures the pages from pdffile and places them in storagefile for later use.
  If the test option is used then the captured pages are reimported and placed
  in the test file, overlayed with a centimeter grid.
</para>

<para><i>
Note! Pagenumbers start at 0 (zero) (with no necessary relation to the
  pagenumber shown by a PDF viewer such as Acroread).</i> If the
  pagenumbers are omitted only the first page of the document will be
  made into a form.
</para>

<para>
  The "form names" for the forms derived from the pages will be prefix0 for the front page,
  prefix1 for the following one, prefix2 for the one after that, and so forth.
</para>

<para><b>For example</b></para>

<pre style="programListing">
  % pageCatcher makeforms picture.pdf -s pic.data -p pict --test pictest.pdf 0 2
</pre>

<para>
  extracts the first and third page from picture.pdf, archiving them in pic.data
  for later use, giving them the form names pict0 and pict2, respectively.
  The test file pictest.pdf will display the captured forms overlayed with a
  centimeter grid.
</para>
<para>
  If the storagefile is omitted it defaults to "storage.data".
  If the prefix is omitted it defaults to PF (for "page form").
  If the --all option is used then all pages of the document are captured.
</para>
<para>
<b>Function call mode page extraction:</b>
The <i>storeForms</i> function extracts a form from within a
program or script.
The Python programming language signature for <i>storeForms</i> is
</para>

<pre style="programListing">
storeForms(frompdffile, storagefile, pagenumbers=None, 
      prefix="PageForms", all=None, verbose=0, password=""):
</pre>

<para>
The usage of <i>storeForms</i> is analogous to the script usage
described above, except that there is no option for test output.
</para>
<para style="bulletList" bulletText="l"><i>frompdffile</i> must provide the name of an existing PDF file
to use for extracting the forms.</para>
<para style="bulletList" bulletText="l"><i>storagefile</i> must provide a name to use for the storage file in
which to store the formatted form data.</para>
<para style="bulletList" bulletText="l"><i>pagenumbers</i> if present should be a Python list of integers
listing the offsets of the pages to store as forms (with the front page of the document at offset 0 and the next
page at offset 1 and so forth).</para>
<para style="bulletList" bulletText="l"><i>prefix</i> when used should be a string to use as the form prefix.</para>
<para style="bulletList" bulletText="l"><i>all</i> when used and set specifies that all pages of the PDF file
should be captured as forms.</para>
<para style="bulletList" bulletText="l"><i>verbose</i> if present and set will cause the generation process
to print verbose commentary on the extraction process (for debugging).</para>
<para style="bulletList" bulletText="l"><i>password</i> will be used if the PDF file has been encrypted.
It should provide the User password for the file (which is the empty string
if the document is readable without a password).</para>

<para>The return value of <i>storeForms</i> is a list of strings listing the
names of the forms stored in the storage file.</para>

<para><b>For example</b></para>

<pre style="programListing">
  names = storeForms("manual.pdf", "manual.data", prefix="fourpage", all=1, verbose=1)
</pre>

<para>
Stores <i>all</i> pages from <i>manual.pdf</i> in storage file <i>manual.data</i>
using the prefix <i>fourpage</i>, with verbose commentary printed to standard
output.</para>


<h2>Using Caught Pages</h2>
<outlineAdd level="1">Using Caught Pages</outlineAdd>

<para>
Both the ReportLab RML2PDF product and the ReportLab core Python API can use
PageCatcher storage files to place captured graphics in generated PDF files.
In addition, PageCatcher provides several built in demo modes listed below.
</para>
<para>
<b>Catching Forms in RML:</b>
If you have production versions of both RML2PDF and PageCatcher you can use
a special Report Markup Language tag <i>catchForms</i> which imports
all forms from a PageCatcher storage file for use in an RML document.
</para>
<para><b>For example:</b>
The following RML code fragment draws a caught form <i>PF0</i>
(stored in storage file <i>storage.data</i>) onto a
page backdrop.
</para>

<para style="programListing">
&lt;pageDrawing&gt;
&lt;catchForms storageFile="storage.data"/&gt;
&lt;doForm name="PF0"/&gt;
&lt;/pageDrawing&gt;
</para>

<para>The <i>catchForms</i> tag can occur anywhere where a <i>doForm</i>
tag can occur.
</para>
<para>
<b>Catching Forms in Python using the ReportLab core API:</b>
You can also use PageCatcher caught pages in documents created using
the ReportLab core API for creating PDF programs.
The <i>restoreForms</i> function imports forms from a storage file
into a pdfgen Canvas object.
</para>

<pre style="programListing">
def restoreForms(storagefilename, canv, verbose=0):
</pre>

<para style="bulletList" bulletText="l">
<i>storagefilename</i> must be the string name of a PageCatcher
storage file.
</para>
<para style="bulletList" bulletText="l">
<i>canv</i> must be a reportlab.pdfgen.canvas.Canvas object
</para>
<para style="bulletList" bulletText="l">
<i>verbose</i> if used and set instructs the function to
print verbose progress and diagnostic information to standard output
(for debugging).
</para>
<para>
The  result of the function is the list of names of the forms extracted
from the storage file.
</para>
<para>
The following example function extracts all pages from a storage file
and places them on 4 to a page in a new PDF file.
</para>

<pre style="programListing">
def fourPage(storagefile, testfile, scalefactor = 0.5):
    print "placing forms from", storagefile, "into", testfile, "four to a page"
    from reportlab.pdfgen import canvas
    canv = canvas.Canvas(testfile)
    (width, height) = canv._pagesize
    names = restoreForms(storagefile, canv, verbose=1)
    while names:
        for (xoff, yoff) in [ (0,1), (1,1), (0,0), (1,0) ]:
            thisname = names[0]
            print thisname,
            canv.saveState()
            (x,y) = (xoff*width/2.0, yoff*height/2.0)
            canv.translate(x,y)
            canv.scale(scalefactor, scalefactor)
            canv.doForm(thisname)
            canv.restoreState()
            del names[0]
            if not names: break
        canv.showPage()
        print
    canv.save()
    print "wrote", testfile
</pre>

<para>
The <i>fourPage</i>
function first creates a canvas, extracts the forms for the canvas
using <i>restoreForms</i>. Then it iterates over the names of the forms
placing the first at the upper right part of the page, the second at the
upper left, the third at the lower right, and the fourth at the lower left.
Then the function continues this process on the next page with the remaining
forms until they all the forms have been placed.  Finally the function saves
the document.  For a detailed explanation of the methods of the canvas object
please see the ReportLab core API userguide.
</para>

<h2>Demo Modes</h2>
<outlineAdd level="1">Demo Modes</outlineAdd>

<para>
The PageCatcher program also includes a number of 
built in demonstration modes.  These options are provided as an easy
way of showing some of the capabilities of PageCatcher without requiring
any programming or the use of RML2PDF.
</para>
<para>
<b>help:</b>
</para>


<pre style="programListing">
 % pageCatcher help
</pre>
<para>
This mode prints a short explanation of the script options.
</para>
<para>
<b>note:</b>
</para>

<pre style="programListing">
 % pageCatcher note [pdffile]
</pre>
<para>
This mode places a text string over the first page of pdffile,
     storing the result in "annotated.pdf".  The font, size and
     string are read interactively from the console.
</para>
<para>
<b>4page:</b>
</para>

<pre style="programListing">
 % pageCatcher 4page pdffile [--scale scalefactor]
                     [--output pdfoutputfilename] [-s storagefilename]
</pre>
<para>
This mode rewrites the pages of pdffile with 4 pages of the input
     on each page of the output ("save the trees" mode).
</para>
<para>
<b>exec</b>
</para>

<pre style="programListing">
 % pageCatcher exec scriptFileName
</pre>
<para>
This mode executes a python script.  This mode is provided for the case
where PageCatcher is distributed as a stand alone executable for demonstration
and evaluation purposes.  It allows evaluation customers to try scripting usage
without having a Python installation.  <i>Note that not all legal scripts will
work with the stand alone evaluation version since the executable does not contain all
standard library modules.</i>
</para>

<h2>Additional Feature -- Copying and Appending PDF files</h2>
<outlineAdd level="1">Additional Feature -- Copying and Appending PDF files</outlineAdd>


<para>There are a number of additional features in PageCatcher beyond
the fundamental operation of capturing pages from one document and
embedding them in another.  These features are available when using
"exec scriptname" form or when importing the licensed pageCatcher component
into another program.  <i>These features do not require
a PageCatcher license to work in production mode.</i></para>

<pre style="programListing">
copyPages(frompdffile, tocanvas, withoutline=1)
</pre>

<para>
The function copyPages will copy all pages of a PDF file into a ReportLab document
(the document that is being created using the canvas
object).  
The pages will be copied without changes.
For example the following script will append any number
of pdf files together into a new pdf document.
</para>
<pre style="programListing">
try:
    from rlextra.pageCatcher.pageCatcher import copyPages
except ImportError:
    pass # running inside pageCatcher module?

from reportlab.pdfgen import canvas

def doappend(topdffile, frompdffilelist):
    canv = canvas.Canvas(topdffile)
    for frompdffile in frompdffilelist:
        print "copying", frompdffile
        copyPages(frompdffile, canv)
    print "\n\nnow writing", topdffile
    canv.save()

if __name__=="__main__":
    # edit this
    doappend("out8_directcopy.pdf", ["sample1.pdf", "sample2.pdf", "sample3.pdf"])
</pre>

<para>If you do not want to include the outline from the copied document in the result
unset the parameter withoutline=0.</para>

<para>Note that copyPages may currently be used without purchasing a PageCatcher 
license.  This functionality was included to assist some open source users of our product
who were urgently in need of this function. We do not, however, promise to keep this free 
in future versions.
</para>

<h2>Feedback</h2>
<outlineAdd level="1">Feedback</outlineAdd>

<para>
We need and welcome feedback to help make this into a great product!  Email 
info@reportlab.com, or join our group of 200+ existing users by emailing
reportlab-users@reportlab.com.  Enjoy!
</para>
 
</story>

</document>
