123 lines
4.1 KiB
Python
123 lines
4.1 KiB
Python
#!/usr/bin/env python
|
|
# encoding: utf-8
|
|
"""matplotlib_example.py
|
|
An simple example of how to insert matplotlib generated figures
|
|
into a ReportLab platypus document.
|
|
"""
|
|
|
|
import matplotlib
|
|
matplotlib.use('PDF')
|
|
import matplotlib.pyplot as plt
|
|
import cStringIO
|
|
|
|
from pdfrw import PdfReader
|
|
from pdfrw.buildxobj import pagexobj
|
|
from pdfrw.toreportlab import makerl
|
|
|
|
from reportlab.platypus import Flowable
|
|
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT
|
|
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
|
|
from reportlab.lib.styles import getSampleStyleSheet
|
|
from reportlab.rl_config import defaultPageSize
|
|
from reportlab.lib.units import inch
|
|
|
|
PAGE_HEIGHT=defaultPageSize[1]; PAGE_WIDTH=defaultPageSize[0]
|
|
styles = getSampleStyleSheet()
|
|
|
|
class PdfImage(Flowable):
|
|
"""PdfImage wraps the first page from a PDF file as a Flowable
|
|
which can be included into a ReportLab Platypus document.
|
|
Based on the vectorpdf extension in rst2pdf (http://code.google.com/p/rst2pdf/)"""
|
|
|
|
def __init__(self, filename_or_object, width=None, height=None, kind='direct'):
|
|
from reportlab.lib.units import inch
|
|
# If using StringIO buffer, set pointer to begining
|
|
if hasattr(filename_or_object, 'read'):
|
|
filename_or_object.seek(0)
|
|
page = PdfReader(filename_or_object, decompress=False).pages[0]
|
|
self.xobj = pagexobj(page)
|
|
self.imageWidth = width
|
|
self.imageHeight = height
|
|
x1, y1, x2, y2 = self.xobj.BBox
|
|
|
|
self._w, self._h = x2 - x1, y2 - y1
|
|
if not self.imageWidth:
|
|
self.imageWidth = self._w
|
|
if not self.imageHeight:
|
|
self.imageHeight = self._h
|
|
self.__ratio = float(self.imageWidth)/self.imageHeight
|
|
if kind in ['direct','absolute'] or width==None or height==None:
|
|
self.drawWidth = width or self.imageWidth
|
|
self.drawHeight = height or self.imageHeight
|
|
elif kind in ['bound','proportional']:
|
|
factor = min(float(width)/self._w,float(height)/self._h)
|
|
self.drawWidth = self._w*factor
|
|
self.drawHeight = self._h*factor
|
|
|
|
def wrap(self, aW, aH):
|
|
return self.drawWidth, self.drawHeight
|
|
|
|
def drawOn(self, canv, x, y, _sW=0):
|
|
if _sW > 0 and hasattr(self, 'hAlign'):
|
|
a = self.hAlign
|
|
if a in ('CENTER', 'CENTRE', TA_CENTER):
|
|
x += 0.5*_sW
|
|
elif a in ('RIGHT', TA_RIGHT):
|
|
x += _sW
|
|
elif a not in ('LEFT', TA_LEFT):
|
|
raise ValueError("Bad hAlign value " + str(a))
|
|
|
|
xobj = self.xobj
|
|
xobj_name = makerl(canv._doc, xobj)
|
|
|
|
xscale = self.drawWidth/self._w
|
|
yscale = self.drawHeight/self._h
|
|
|
|
x -= xobj.BBox[0] * xscale
|
|
y -= xobj.BBox[1] * yscale
|
|
|
|
canv.saveState()
|
|
canv.translate(x, y)
|
|
canv.scale(xscale, yscale)
|
|
canv.doForm(xobj_name)
|
|
canv.restoreState()
|
|
|
|
Title = "Hello world"
|
|
pageinfo = "platypus example"
|
|
def myFirstPage(canvas, doc):
|
|
canvas.saveState()
|
|
canvas.setFont('Times-Bold',16)
|
|
canvas.drawCentredString(PAGE_WIDTH/2.0, PAGE_HEIGHT-108, Title)
|
|
canvas.setFont('Times-Roman',9)
|
|
canvas.drawString(inch, 0.75 * inch, "First Page / %s" % pageinfo)
|
|
canvas.restoreState()
|
|
|
|
|
|
def myLaterPages(canvas, doc):
|
|
canvas.saveState()
|
|
canvas.setFont('Times-Roman',9)
|
|
canvas.drawString(inch, 0.75 * inch, "Page %d %s" % (doc.page, pageinfo))
|
|
canvas.restoreState()
|
|
|
|
def go():
|
|
fig = plt.figure(figsize=(4, 3))
|
|
plt.plot([1,2,3,4])
|
|
plt.ylabel('some numbers')
|
|
imgdata = cStringIO.StringIO()
|
|
fig.savefig(imgdata,format='PDF')
|
|
doc = SimpleDocTemplate("document.pdf")
|
|
Story = [Spacer(1,2*inch)]
|
|
style = styles["Normal"]
|
|
for i in range(5):
|
|
bogustext = ("This is Paragraph number %s. " % i) *20
|
|
p = Paragraph(bogustext, style)
|
|
Story.append(p)
|
|
Story.append(Spacer(1,0.2*inch))
|
|
pi = PdfImage(imgdata)
|
|
Story.append(pi)
|
|
Story.append(Spacer(1,0.2*inch))
|
|
doc.build(Story, onFirstPage=myFirstPage, onLaterPages=myLaterPages)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
go() |