[reportlab-users] Draw images with canvas and use SimpleDocTemplate

2,342 views
Skip to first unread message

slothy Rulez a lot

unread,
Mar 21, 2011, 3:56:50 PM3/21/11
to reportl...@lists2.reportlab.com
Hi! [ ]

I'm newbee using reportlab, I'm writing pdfs with reportlab inside a django view, they are very simple, the header, the contents and the footer.

I'm using SimpleDocTemplate wich fits very well, to draw tables in the contents, the footer and the header are drwan using:

build([data], onFirstPage=drawPageFrame, onLaterPages=drawPageFrame).
My question is, How can I draw a image like using Canvas.drawImage(...)? I need a "floating" image... positioned over the text where I want, and with SimpleDocTemplate I don't have a Canvas object to do this.

Thaks.

Searching I have found this:

The platypus layout stuff uses flowables. Packers normally set the attribute canv onto each flowable when it is being wrapped, split or drawn ie around the wrap, split and draw methods. Inside those methods you have access to the canvas using the canv attribute of self.

¿¿How can this be used??

Ummmm, more stuff to test:

flowables.Macro
flowables.CallerMacro

This is my test ¿wrong?

# -*- coding: utf-8 -*-
from reportlab.lib.pagesizes import A4, landscape, portrait
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import Table, Flowable, SimpleDocTemplate, Paragraph, Spacer, Image
from reportlab.lib import randomtext
from reportlab import platypus

import os,random

styles = getSampleStyleSheet()
path = os.path.realpath(os.path.dirname(__file__))

def drawPageFrame(canvas, doc):
    canvas.saveState()
    canvas.drawImage(path+"/ujiPDF.jpg",50,50,57,57)
    canvas.restoreState()

doc = SimpleDocTemplate("salida.pdf",pagesize=A4)

elementos = []

com = 'canvas.drawImage("'+path+'/ujiPDF.jpg",100,100,57,57)'
print com
elementos.append(platypus.flowables.Macro('canvas.saveState()'))
print platypus.flowables.Macro(com)
elementos.append(platypus.flowables.Macro(com))
elementos.append(platypus.flowables.Macro('canvas.restoreState()'))

para = Paragraph(randomtext.randomText(randomtext.PYTHON,20), styles["Normal"])
elementos.append(para)

doc.build(elementos,onFirstPage=drawPageFrame, onLaterPages=drawPageFrame)
This is the Macro aproach...clean exit but without the second image....


Thanks.

--
Alex.
Slothy, the Angry Wombat
http://angrywombat.comuv.com/portfolio/

Tim Roberts

unread,
Mar 21, 2011, 4:06:00 PM3/21/11
to reportlab-users
slothy Rulez a lot wrote:
>
> I'm newbee using reportlab, I'm writing pdfs with reportlab inside a
> django view, they are very simple, the header, the contents and the
> footer.
>
> I'm using SimpleDocTemplate wich fits very well, to draw tables in the
> contents, the footer and the header are drwan using:
>
> build([data], onFirstPage=drawPageFrame, onLaterPages=drawPageFrame).
> My question is, How can I draw a image like using
> Canvas.drawImage(...)? I need a "floating" image... positioned over
> the text where I want, and with SimpleDocTemplate I don't have a
> Canvas object to do this.

What do you mean by "floating", exactly? Are you trying to draw a
watermark image on the page, behind the text? Does the image need to
flow with the text, attached to some particular word, like an <image>
tag? Does the text need to wrap around the image?

There may be a way to do what you need, but we'd need more information.

--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

_______________________________________________
reportlab-users mailing list
reportl...@lists2.reportlab.com
http://two.pairlist.net/mailman/listinfo/reportlab-users

slothy Rulez a lot

unread,
Mar 21, 2011, 4:08:01 PM3/21/11
to reportlab-users
Sorry, 

In front of the text, positioned like the canvas.drawImage method.

2011/3/21 Tim Roberts <ti...@probo.com>

Tim Roberts

unread,
Mar 21, 2011, 4:22:04 PM3/21/11
to reportlab-users
slothy Rulez a lot wrote:
>
> In front of the text, positioned like the canvas.drawImage method.

But associated with and/or positioned based on the position of some
specific piece of text? Like, for example, if you wanted to draw a
circle around some specific word? That kind of thing requires you to
create a custom flowable. The standard paragraph flowable looks for an
<image> tag, which allows you to embed an image at a specific point in
the text, but if you need to draw something over a specific word, you'll
have to add that yourself.

It's each to draw something at a specific point on the page (you do that
with the first/next page callbacks, where you get a canvas), but if it
depends on the final positioning of a particular word, that's tricky.

slothy Rulez a lot

unread,
Mar 21, 2011, 4:39:50 PM3/21/11
to reportlab-users
Ummm, it's much simpler than that, the image axys positioned over everything, something like drawing with the canvas drawImage method.
¿Is there any flowable? a water mark could be valid too.

By the way, what the Macro method does?

2011/3/21 Tim Roberts <ti...@probo.com>
slothy Rulez a lot wrote:
>
> In front of the text, positioned like the canvas.drawImage method.

But associated with and/or positioned based on the position of some
specific piece of text?  Like, for example, if you wanted to draw a
circle around some specific word?  That kind of thing requires you to
create a custom flowable.  The standard paragraph flowable looks for an
<image> tag, which allows you to embed an image at a specific point in
the text, but if you need to draw something over a specific word, you'll
have to add that yourself.

to dIt's each raw something at a specific point on the page (you do that
with the first/next page callbacks, where you get a canvas), but if it
depends on the final positioning of a particular word, that's tricky.

--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

_______________________________________________
reportlab-users mailing list
reportl...@lists2.reportlab.com
http://two.pairlist.net/mailman/listinfo/reportlab-users

Tim Roberts

unread,
Mar 21, 2011, 5:05:50 PM3/21/11
to reportlab-users
slothy Rulez a lot wrote:
> Ummm, it's much simpler than that, the image axys positioned over
> everything, something like drawing with the canvas drawImage method.
> ¿Is there any flowable? a water mark could be valid too.

When you call "build" on your SimpleDocTemplate, you can specify
onFirstPage and onLaterPages functions. Those are called at the
beginning of each page, and they are passed a canvas for the whole
page. They are called before drawing begins. If you need a callback
after drawing ends, you'll have to create your own page templates with
an "afterDrawPage" method. That means using BaseDocTemplate instead of
SimpleDocTemplate.

Robin Becker

unread,
Mar 22, 2011, 5:50:06 AM3/22/11
to reportlab-users
On 21/03/2011 21:05, Tim Roberts wrote:
> slothy Rulez a lot wrote:
>> Ummm, it's much simpler than that, the image axys positioned over
>> everything, something like drawing with the canvas drawImage method.
>> ¿Is there any flowable? a water mark could be valid too.
>
> When you call "build" on your SimpleDocTemplate, you can specify
> onFirstPage and onLaterPages functions. Those are called at the
> beginning of each page, and they are passed a canvas for the whole
> page. They are called before drawing begins. If you need a callback
> after drawing ends, you'll have to create your own page templates with
> an "afterDrawPage" method. That means using BaseDocTemplate instead of
> SimpleDocTemplate.
>
I think there's a choice. The existing page templates call
onPageEnd(canv,doctemplate) and immediately afterwards the doctemplate calls
afterPage on itself.


So if you want you can inherit from SimpleDocTemplate and mess with either of
those two mechanisms.

For the first you can override handle_documentBegin eg

class MyDocTemplate(SimpleDocTemplate):
def handle_documentBegin(self):
do stuff to self.pageTemplates to add onPage end etc etc
SimpleDocTemplate.handle_documentBegin(self)

alternatively and probably easier use the afterPage method

class MyDocTemplate(SimpleDocTemplate):
def afterPage(self):
do stuff to self.canv to draw your watermark
SimpleDocTemplate.afterPage(self)

then just use your derived class instead of SimpleDocTemplate
--
Robin Becker

Reply all
Reply to author
Forward
0 new messages