109 lines
3.6 KiB
Python
Executable File
109 lines
3.6 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
usage: platypus_pdf_template.py source.pdf
|
|
|
|
Creates platypus.source.pdf
|
|
|
|
Example of using pdfrw to use page 1 of a source PDF as the background
|
|
for other pages programmatically generated with Platypus.
|
|
|
|
Contributed by user asannes
|
|
|
|
"""
|
|
import sys
|
|
import os
|
|
|
|
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
|
|
|
|
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, "wb")
|
|
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__':
|
|
template, = sys.argv[1:]
|
|
output = 'platypus_pdf_template.' + os.path.basename(template)
|
|
create_pdf(output, template)
|