commit a1959ba9c0c9f3881c3e593e5aef1046750880f2 Author: Matthias Klose Date: Sun Jul 13 17:50:59 2014 +0200 pdfrw (0.1-3) unstable; urgency=medium * QA upload. * Build using dh_python2 # imported from the archive diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..7439b9c --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +pdfrw (pdfrw.googlecode.com) + +Copyright (c) 2006-2012 Patrick Maupin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..843347f --- /dev/null +++ b/README.txt @@ -0,0 +1,3 @@ +pdfrw reads and writes PDF files. + +More info at http://code.google.com/p/pdfrw diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..3e018b8 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,45 @@ +pdfrw (0.1-3) unstable; urgency=medium + + * QA upload. + * Build using dh_python2 + + -- Matthias Klose Sun, 13 Jul 2014 15:50:59 +0000 + +pdfrw (0.1-2) unstable; urgency=medium + + * Orphaning package. + + -- Chris Lamb Sun, 09 Feb 2014 00:05:27 +0000 + +pdfrw (0.1-1) unstable; urgency=low + + * New upstream release. + + -- Chris Lamb Tue, 16 Oct 2012 07:54:53 +0100 + +pdfrw (0+svn136-4) unstable; urgency=low + + * Correct Homepage field. (Closes: #683165) + * Specify a 'name' kwarg in call to setuptools.setup. + + -- Chris Lamb Tue, 31 Jul 2012 02:41:14 -0700 + +pdfrw (0+svn136-3) unstable; urgency=low + + * python-pdfrw should Replaces/Provides/Conflicts pdfrw. Thanks to intrigeri + . (Closes: #639273) + + -- Chris Lamb Fri, 26 Aug 2011 10:48:38 +0100 + +pdfrw (0+svn136-2) unstable; urgency=low + + * Rename binary package to "python-pdfrw". + * Change Section to "python". + + -- Chris Lamb Tue, 23 Aug 2011 15:17:20 +0100 + +pdfrw (0+svn136-1) unstable; urgency=low + + * Initial release. (Closes: #638862) + + -- Chris Lamb Mon, 22 Aug 2011 16:09:03 +0100 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +7 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..80733e6 --- /dev/null +++ b/debian/control @@ -0,0 +1,32 @@ +Source: pdfrw +Section: python +Priority: optional +Maintainer: Debian QA Group +Build-Depends: debhelper (>= 7.0.50~) +Build-Depends-Indep: python-setuptools +Standards-Version: 3.9.2 +Homepage: http://code.google.com/p/pdfrw/ +Vcs-Git: git://github.com/lamby/pkg-pdfrw.git +Vcs-Browser: https://github.com/lamby/pkg-pdfrw + +Package: python-pdfrw +Architecture: all +Depends: ${misc:Depends}, ${python:Depends}, python-reportlab +Replaces: pdfrw +Provides: pdfrw +Conflicts: pdfrw +Description: PDF file manipulation library + pdfrw can read and write PDF files, and can also be used to read in PDFs which + can then be used inside reportlab. + . + pdfrw tries to be agnostic about the contents of PDF files, and support them + as containers, but to do useful work, something a little higher-level is + required. It supports the following: + . + * PDF pages. pdfrw knows enough to find the pages in PDF files you read in, + and to write a set of pages back out to a new PDF file. + * Form XObjects. pdfrw can take any page or rectangle on a page, and convert + it to a Form XObject, suitable for use inside another PDF file + * reportlab objects. pdfrw can recursively create a set of reportlab objects + from its internal object format. This allows, for example, Form XObjects to + be used inside reportlab. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..81f7249 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,44 @@ +Author: Patrick Maupin +Download: http://code.google.com/p/pdfrw/ + +Files: * +Copyright: © 2006-2009 Patrick Maupin +License: MIT + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +Files: debian/* +Copyright: © 2011 Chris Lamb +License: MIT + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff --git a/debian/examples b/debian/examples new file mode 100644 index 0000000..e39721e --- /dev/null +++ b/debian/examples @@ -0,0 +1 @@ +examples/* diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..4647c9c --- /dev/null +++ b/debian/rules @@ -0,0 +1,4 @@ +#!/usr/bin/make -f + +%: + dh $@ --with python2 diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/examples/4up.py b/examples/4up.py new file mode 100755 index 0000000..491af14 --- /dev/null +++ b/examples/4up.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python + +''' +usage: 4up.py my.pdf firstpage lastpage + +Creates 4up.my.pdf + +''' + +import sys +import os + +import find_pdfrw +from pdfrw import PdfReader, PdfWriter, PdfDict, PdfName, PdfArray +from pdfrw.buildxobj import pagexobj + +def get4(allpages): + # Pull a maximum of 4 pages off the list + pages = [pagexobj(x) for x in allpages[:4]] + del allpages[:4] + + x_max = max(page.BBox[2] for page in pages) + y_max = max(page.BBox[3] for page in pages) + + stream = [] + xobjdict = PdfDict() + for index, page in enumerate(pages): + x = x_max * (index & 1) / 2.0 + y = y_max * (index <= 1) / 2.0 + index = '/P%s' % index + stream.append('q 0.5 0 0 0.5 %s %s cm %s Do Q\n' % (x, y, index)) + xobjdict[index] = page + + return PdfDict( + Type = PdfName.Page, + Contents = PdfDict(stream=''.join(stream)), + MediaBox = PdfArray([0, 0, x_max, y_max]), + Resources = PdfDict(XObject = xobjdict), + ) + +def go(inpfn, outfn): + pages = PdfReader(inpfn).pages + writer = PdfWriter() + while pages: + writer.addpage(get4(pages)) + writer.write(outfn) + +if __name__ == '__main__': + inpfn, = sys.argv[1:] + outfn = '4up.' + os.path.basename(inpfn) + go(inpfn, outfn) diff --git a/examples/README.txt b/examples/README.txt new file mode 100644 index 0000000..242f5be --- /dev/null +++ b/examples/README.txt @@ -0,0 +1,32 @@ +Example programs: + +4up.py -- Prints pages four-up + +alter.py -- Simple example of making a very slight modification to a PDF. + +booklet.py -- Converts a PDF into a booklet. + +metadata.py -- Concatenates multiple PDFs, adds metadata. + +poster.py -- Changes the size of a PDF to create a poster + +print_two.py -- this is used when printing two cut-down copies on a single sheet of paper (double-sided) Requires uncompressed PDF. + +rotate.py -- This will rotate selected ranges of pages within a document. + +subset.py -- This will retrieve a subset of pages from a document. + +watermark.py -- Adds a watermark to a PDF + +rl1/4up.py -- Same as 4up.py, using reportlab for output. Next simplest reportlab example. + +rl1/booklet.py -- Version of print_booklet using reportlab for output. + +rl1/platypus_pdf_template.py -- Example using a PDF page as a watermark background with reportlab. + +rl1/subset.py -- Same as subset.py, using reportlab for output. Simplest reportlab example. + +rl2/copy.py -- example of how you could parse a graphics stream and then use reportlab for output. + Works on a few different PDFs, probably not a suitable starting point for real + production work without a lot of work on the library functions. + diff --git a/examples/alter.py b/examples/alter.py new file mode 100755 index 0000000..1c6d4e1 --- /dev/null +++ b/examples/alter.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +''' +usage: alter.py my.pdf + +Creates alter.my.pdf + +Demonstrates making a slight alteration to a preexisting PDF file. + +''' + +import sys +import os + +import find_pdfrw +from pdfrw import PdfReader, PdfWriter + +inpfn, = sys.argv[1:] +outfn = 'alter.' + os.path.basename(inpfn) + +trailer = PdfReader(inpfn) +trailer.Info.Title = 'My New Title Goes Here' +writer = PdfWriter() +writer.trailer = trailer +writer.write(outfn) diff --git a/examples/booklet.py b/examples/booklet.py new file mode 100755 index 0000000..0b3be74 --- /dev/null +++ b/examples/booklet.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +''' +usage: booklet.py my.pdf + +Creates booklet.my.pdf + +Pages organized in a form suitable for booklet printing. + +''' + +import sys +import os + +import find_pdfrw +from pdfrw import PdfReader, PdfWriter, PdfDict, PdfArray, PdfName, IndirectPdfDict +from pdfrw.buildxobj import pagexobj + +def fixpage(*pages): + pages = [pagexobj(x) for x in pages] + + class PageStuff(tuple): + pass + + x = y = 0 + for i, page in enumerate(pages): + index = '/P%s' % i + shift_right = x and '1 0 0 1 %s 0 cm ' % x or '' + stuff = PageStuff((index, page)) + stuff.stream = 'q %s%s Do Q\n' % (shift_right, index) + x += page.BBox[2] + y = max(y, page.BBox[3]) + pages[i] = stuff + + # Multiple copies of first page used as a placeholder to + # get blank page on back. + for p1, p2 in zip(pages, pages[1:]): + if p1[1] is p2[1]: + pages.remove(p1) + + return IndirectPdfDict( + Type = PdfName.Page, + Contents = PdfDict(stream=''.join(page.stream for page in pages)), + MediaBox = PdfArray([0, 0, x, y]), + Resources = PdfDict( + XObject = PdfDict(pages), + ), + ) + +inpfn, = sys.argv[1:] +outfn = 'booklet.' + os.path.basename(inpfn) +pages = PdfReader(inpfn).pages + +# Use page1 as a marker to print a blank at the end +if len(pages) & 1: + pages.append(pages[0]) + +bigpages = [] +while len(pages) > 2: + bigpages.append(fixpage(pages.pop(), pages.pop(0))) + bigpages.append(fixpage(pages.pop(0), pages.pop())) + +bigpages += pages + +PdfWriter().addpages(bigpages).write(outfn) diff --git a/examples/find_pdfrw.py b/examples/find_pdfrw.py new file mode 100644 index 0000000..f69d412 --- /dev/null +++ b/examples/find_pdfrw.py @@ -0,0 +1,33 @@ +''' + find_xxx.py -- Find the place in the tree where xxx lives. + + Ways to use: + 1) Make a copy, change 'xxx' in package to be your name; or + 2) Under Linux, just ln -s to where this is in the right tree + + Created by Pat Maupin, who doesn't consider it big enough to be worth copyrighting +''' + +import sys +import os + +myname = __name__[5:] # remove 'find_' +myname = os.path.join(myname, '__init__.py') + +def trypath(newpath): + path = None + while path != newpath: + path = newpath + if os.path.exists(os.path.join(path, myname)): + return path + newpath = os.path.dirname(path) + +root = trypath(__file__) or trypath(os.path.realpath(__file__)) + +if root is None: + print + print 'Warning: %s: Could not find path to development package %s' % (__file__, myname) + print ' The import will either fail or will use system-installed libraries' + print +elif root not in sys.path: + sys.path.append(root) diff --git a/examples/metadata.py b/examples/metadata.py new file mode 100755 index 0000000..9c69108 --- /dev/null +++ b/examples/metadata.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python + +''' +usage: metadata.py [ ...] + +Creates output.pdf + +This file demonstrates two features: + +1) Concatenating multiple input PDFs. + +2) adding metadata to the PDF. + +If you do not need to add metadata, look at subset.py, which +has a simpler interface to PdfWriter. + +''' + +import sys +import os + +import find_pdfrw +from pdfrw import PdfReader, PdfWriter, IndirectPdfDict + +inputs = sys.argv[1:] +assert inputs +outfn = 'output.pdf' + +writer = PdfWriter() +for inpfn in inputs: + writer.addpages(PdfReader(inpfn.pages) + +writer.trailer.Info = IndirectPdfDict( + Title = 'your title goes here', + Author = 'your name goes here', + Subject = 'what is it all about?', + Creator = 'some script goes here', +) +writer.write(outfn) diff --git a/examples/poster.py b/examples/poster.py new file mode 100755 index 0000000..ee58282 --- /dev/null +++ b/examples/poster.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +''' +usage: poster.py my.pdf + +Shows how to change the size on a PDF. + +Motivation: + +My daughter needed to create a 48" x 36" poster, but her Mac version of Powerpoint +only wanted to output 8.5" x 11" for some reason. + +''' + +import sys +import os + +import find_pdfrw +from pdfrw import PdfReader, PdfWriter, PdfDict, PdfName, PdfArray, IndirectPdfDict +from pdfrw.buildxobj import pagexobj + +def adjust(page): + page = pagexobj(page) + assert page.BBox == [0, 0, 11 * 72, int(8.5 * 72)], page.BBox + margin = 72 // 2 + old_x, old_y = page.BBox[2] - 2 * margin, page.BBox[3] - 2 * margin + + new_x, new_y = 48 * 72, 36 * 72 + ratio = 1.0 * new_x / old_x + assert ratio == 1.0 * new_y / old_y + + index = '/BasePage' + x = -margin * ratio + y = -margin * ratio + stream = 'q %0.2f 0 0 %0.2f %s %s cm %s Do Q\n' % (ratio, ratio, x, y, index) + xobjdict = PdfDict() + xobjdict[index] = page + + return PdfDict( + Type = PdfName.Page, + Contents = PdfDict(stream=stream), + MediaBox = PdfArray([0, 0, new_x, new_y]), + Resources = PdfDict(XObject = xobjdict), + ) + +def go(inpfn, outfn): + reader = PdfReader(inpfn) + page, = reader.pages + writer = PdfWriter() + writer.addpage(adjust(page)) + writer.trailer.Info = IndirectPdfDict(reader.Info) + writer.write(outfn) + +if __name__ == '__main__': + inpfn, = sys.argv[1:] + outfn = 'poster.' + os.path.basename(inpfn) + go(inpfn, outfn) diff --git a/examples/print_two.py b/examples/print_two.py new file mode 100755 index 0000000..d168f68 --- /dev/null +++ b/examples/print_two.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python + +''' +usage: print_two.py my.pdf + +Creates print_two.my.pdf + +This is only useful when you can cut down sheets of paper to make two +small documents. Works for double-sided only right now. + +''' + +import sys +import os + +import find_pdfrw +from pdfrw import PdfReader, PdfWriter, PdfArray, IndirectPdfDict + +def fixpage(page, count=[0]): + count[0] += 1 + evenpage = not (count[0] & 1) + + # For demo purposes, just go with the MediaBox and toast the others + box = [float(x) for x in page.MediaBox] + assert box[0] == box[1] == 0, "demo won't work on this PDF" + + for key, value in sorted(page.iteritems()): + if 'box' in key.lower(): + del page[key] + + startsize = tuple(box[2:]) + finalsize = box[3], 2 * box[2] + page.MediaBox = PdfArray((0, 0) + finalsize) + page.Rotate = (int(page.Rotate or 0) + 90) % 360 + + contents = page.Contents + if contents is None: + return page + contents = isinstance(contents, dict) and [contents] or contents + + prefix = '0 1 -1 0 %s %s cm\n' % (finalsize[0], 0) + if evenpage: + prefix = '1 0 0 1 %s %s cm\n' % (0, finalsize[1]/2) + prefix + first_prefix = 'q\n-1 0 0 -1 %s %s cm\n' % finalsize + prefix + second_prefix = '\nQ\n' + prefix + first_prefix = IndirectPdfDict(stream=first_prefix) + second_prefix = IndirectPdfDict(stream=second_prefix) + contents = PdfArray(([second_prefix] + contents) * 2) + contents[0] = first_prefix + page.Contents = contents + return page + + +inpfn, = sys.argv[1:] +outfn = 'print_two.' + os.path.basename(inpfn) +pages = PdfReader(inpfn).pages + +PdfWriter().addpages(fixpage(x) for x in pages).write(outfn) diff --git a/examples/rl1/4up.py b/examples/rl1/4up.py new file mode 100755 index 0000000..385103a --- /dev/null +++ b/examples/rl1/4up.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +''' +usage: 4up.py my.pdf + + +Uses Form XObjects and reportlab to create 4up.my.pdf. + +Demonstrates use of pdfrw with reportlab. + +''' + +import sys +import os + +from reportlab.pdfgen.canvas import Canvas + +import find_pdfrw +from pdfrw import PdfReader +from pdfrw.buildxobj import pagexobj +from pdfrw.toreportlab import makerl + + +def addpage(canvas, allpages): + pages = allpages[:4] + del allpages[:4] + + x_max = max(page.BBox[2] for page in pages) + y_max = max(page.BBox[3] for page in pages) + + canvas.setPageSize((x_max, y_max)) + + for index, page in enumerate(pages): + x = x_max * (index & 1) / 2.0 + y = y_max * (index <= 1) / 2.0 + canvas.saveState() + canvas.translate(x, y) + canvas.scale(0.5, 0.5) + canvas.doForm(makerl(canvas, page)) + canvas.restoreState() + canvas.showPage() + + +def go(argv): + inpfn, = argv + outfn = '4up.' + os.path.basename(inpfn) + + pages = PdfReader(inpfn).pages + pages = [pagexobj(x) for x in pages] + canvas = Canvas(outfn) + + while pages: + addpage(canvas, pages) + canvas.save() + +if __name__ == '__main__': + go(sys.argv[1:]) diff --git a/examples/rl1/README.txt b/examples/rl1/README.txt new file mode 100644 index 0000000..11cb541 --- /dev/null +++ b/examples/rl1/README.txt @@ -0,0 +1,9 @@ +This directory contains example scripts which read in PDFs +and convert pages to PDF Form XObjects using pdfrw, and then +write out the PDFs using reportlab. + +The examples, from easiest to hardest, are: + +subset.py -- prints a subset of pages +4up.py -- prints pages 4-up +booklet.py -- creates a booklet out of the pages diff --git a/examples/rl1/booklet.py b/examples/rl1/booklet.py new file mode 100755 index 0000000..23f8a72 --- /dev/null +++ b/examples/rl1/booklet.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python + +''' +usage: booklet.py my.pdf + + +Uses Form XObjects and reportlab to create booklet.my.pdf. + +Demonstrates use of pdfrw with reportlab. + +''' + +import sys +import os + +from reportlab.pdfgen.canvas import Canvas + +import find_pdfrw +from pdfrw import PdfReader +from pdfrw.buildxobj import pagexobj +from pdfrw.toreportlab import makerl + + +def read_and_double(inpfn): + pages = PdfReader(inpfn).pages + pages = [pagexobj(x) for x in pages] + if len(pages) & 1: + pages.append(pages[0]) # Sentinel -- get same size for back as front + + xobjs = [] + while len(pages) > 2: + xobjs.append((pages.pop(), pages.pop(0))) + xobjs.append((pages.pop(0), pages.pop())) + xobjs += [(x,) for x in pages] + return xobjs + + +def make_pdf(outfn, xobjpairs): + canvas = Canvas(outfn) + for xobjlist in xobjpairs: + x = y = 0 + for xobj in xobjlist: + x += xobj.BBox[2] + y = max(y, xobj.BBox[3]) + + canvas.setPageSize((x,y)) + + # Handle blank back page + if len(xobjlist) > 1 and xobjlist[0] == xobjlist[-1]: + xobjlist = xobjlist[:1] + x = xobjlist[0].BBox[2] + else: + x = 0 + y = 0 + + for xobj in xobjlist: + canvas.saveState() + canvas.translate(x, y) + canvas.doForm(makerl(canvas, xobj)) + canvas.restoreState() + x += xobj.BBox[2] + canvas.showPage() + canvas.save() + + +inpfn, = sys.argv[1:] +outfn = 'booklet.' + os.path.basename(inpfn) + +make_pdf(outfn, read_and_double(inpfn)) diff --git a/examples/rl1/find_pdfrw.py b/examples/rl1/find_pdfrw.py new file mode 100644 index 0000000..f69d412 --- /dev/null +++ b/examples/rl1/find_pdfrw.py @@ -0,0 +1,33 @@ +''' + find_xxx.py -- Find the place in the tree where xxx lives. + + Ways to use: + 1) Make a copy, change 'xxx' in package to be your name; or + 2) Under Linux, just ln -s to where this is in the right tree + + Created by Pat Maupin, who doesn't consider it big enough to be worth copyrighting +''' + +import sys +import os + +myname = __name__[5:] # remove 'find_' +myname = os.path.join(myname, '__init__.py') + +def trypath(newpath): + path = None + while path != newpath: + path = newpath + if os.path.exists(os.path.join(path, myname)): + return path + newpath = os.path.dirname(path) + +root = trypath(__file__) or trypath(os.path.realpath(__file__)) + +if root is None: + print + print 'Warning: %s: Could not find path to development package %s' % (__file__, myname) + print ' The import will either fail or will use system-installed libraries' + print +elif root not in sys.path: + sys.path.append(root) diff --git a/examples/rl1/platypus_pdf_template.py b/examples/rl1/platypus_pdf_template.py new file mode 100755 index 0000000..8c85794 --- /dev/null +++ b/examples/rl1/platypus_pdf_template.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +usage: platypus_pdf_template.py output.pdf pdf_file_to_use_as_template.pdf + +Example of using pdfrw to use a pdf (page one) as the background for all +other pages together with platypus. + +There is a table of contents in this example for completeness sake. + +Contributed by user asannes + +""" +import sys + +from reportlab.platypus import PageTemplate, BaseDocTemplate, Frame +from reportlab.platypus import NextPageTemplate, Paragraph, PageBreak +from reportlab.platypus.tableofcontents import TableOfContents +from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle +from reportlab.rl_config import defaultPageSize +from reportlab.lib.units import inch +from reportlab.graphics import renderPDF + +import find_pdfrw +from pdfrw import PdfReader +from pdfrw.buildxobj import pagexobj +from pdfrw.toreportlab import makerl + +PAGE_WIDTH = defaultPageSize[0] +PAGE_HEIGHT = defaultPageSize[1] + +class MyTemplate(PageTemplate): + """The kernel of this example, where we use pdfrw to fill in the + background of a page before writing to it. This could be used to fill + in a water mark or similar.""" + + def __init__(self, pdf_template_filename, name=None): + frames = [Frame( + 0.85 * inch, + 0.5 * inch, + PAGE_WIDTH - 1.15 * inch, + PAGE_HEIGHT - (1.5 * inch) + )] + PageTemplate.__init__(self, name, frames) + # use first page as template + page = PdfReader(pdf_template_filename).pages[0] + self.page_template = pagexobj(page) + # Scale it to fill the complete page + self.page_xscale = PAGE_WIDTH/self.page_template.BBox[2] + self.page_yscale = PAGE_HEIGHT/self.page_template.BBox[3] + + def beforeDrawPage(self, canvas, doc): + """Draws the background before anything else""" + canvas.saveState() + rl_obj = makerl(canvas, self.page_template) + canvas.scale(self.page_xscale, self.page_yscale) + canvas.doForm(rl_obj) + canvas.restoreState() + +class MyDocTemplate(BaseDocTemplate): + """Used to apply heading to table of contents.""" + + def afterFlowable(self, flowable): + """Adds Heading1 to table of contents""" + if flowable.__class__.__name__ == 'Paragraph': + style = flowable.style.name + text = flowable.getPlainText() + key = '%s' % self.seq.nextf('toc') + if style == 'Heading1': + self.canv.bookmarkPage(key) + self.notify('TOCEntry', [1, text, self.page, key]) + +def create_toc(): + """Creates the table of contents""" + table_of_contents = TableOfContents() + table_of_contents.dotsMinLevel = 0 + header1 = ParagraphStyle(name = 'Heading1', fontSize = 16, leading = 16) + header2 = ParagraphStyle(name = 'Heading2', fontSize = 14, leading = 14) + table_of_contents.levelStyles = [header1, header2] + return [table_of_contents, PageBreak()] + +def create_pdf(filename, pdf_template_filename): + """Create the pdf, with all the contents""" + pdf_report = open(filename, "w") + document = MyDocTemplate(pdf_report) + templates = [ MyTemplate(pdf_template_filename, name='background') ] + document.addPageTemplates(templates) + + styles = getSampleStyleSheet() + elements = [NextPageTemplate('background')] + elements.extend(create_toc()) + + # Dummy content (hello world x 200) + for i in range(200): + elements.append(Paragraph("Hello World" + str(i), styles['Heading1'])) + + document.multiBuild(elements) + pdf_report.close() + + +if __name__ == '__main__': + try: + output, template = sys.argv[1:] + create_pdf(output, template) + except ValueError: + print "Usage: %s